scc 2025.09
SystemC components library
report.cpp
1/*******************************************************************************
2 * Copyright 2017, 2018 MINRES Technologies GmbH
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 *******************************************************************************/
16#include "report.h"
17#include "configurer.h"
18#include <array>
19#include <cci_configuration>
20#include <fstream>
21#include <mutex>
22#include <nonstd/optional.hpp>
23#include <spdlog/async.h>
24#include <spdlog/sinks/basic_file_sink.h>
25#include <spdlog/sinks/stdout_color_sinks.h>
26#include <spdlog/spdlog.h>
27#include <tuple>
28#include <unordered_map>
29#include <util/logging.h>
30#ifdef WITH_STACKTRACE
31#include <boost/stacktrace.hpp>
32#endif
33#include <cstdlib>
34#ifdef __GNUC__
35#define GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__)
36#if GCC_VERSION < 40900
37#define USE_C_REGEX
38#endif
39#define likely(x) __builtin_expect(x, 1)
40#define unlikely(x) __builtin_expect(x, 0)
41#else
42#define likely(x) x
43#define unlikely(x) x
44#endif
45
46#ifdef USE_C_REGEX
47#include <regex.h>
48#else
49#include <regex>
50#endif
51#ifdef ERROR
52#undef ERROR
53#endif
54using namespace std;
55using namespace sc_core;
56using namespace scc;
57
58namespace {
59struct char_equal_to : public std::equal_to<char const*> {
60 bool operator()(char const* __x, char const* __y) const { return strcmp(__x, __y) == 0; }
61};
62
63struct char_hash {
64 // BKDR hash algorithm
65 uint64_t operator()(char const* str) const {
66 constexpr unsigned int seed = 131; // 31 131 1313 13131131313 etc//
67 uint64_t hash = 0;
68 while(*str) {
69 hash = (hash * seed) + (*str);
70 str++;
71 }
72 return hash;
73 }
74};
75static class {
76 std::unordered_map<char const*, sc_core::sc_verbosity, char_hash, char_equal_to> table;
77 std::vector<std::string> cache;
78 std::mutex mtx;
79
80public:
81 std::tuple<bool, sc_core::sc_verbosity> get(char const* key) {
82 std::lock_guard<std::mutex> lock(mtx);
83 auto it = table.find(key);
84 if(it != table.end())
85 return {true, it->second};
86 else
87 return {false, sc_core::SC_DEBUG};
88 }
89 void insert(char const* key, sc_core::sc_verbosity verb) {
90 std::lock_guard<std::mutex> lock(mtx);
91 cache.push_back(key);
92 table.insert({cache.back().c_str(), verb});
93 }
94 void clear() {
95 std::lock_guard<std::mutex> lock(mtx);
96 table.clear();
97 cache.clear();
98 }
99} lut;
100#ifdef MTI_SYSTEMC
101static const cci::cci_originator originator;
102#else
103static const cci::cci_originator originator("reporting");
104#endif
105
106bool& inst_based_logging() {
107 thread_local bool active = getenv("SCC_DISABLE_INSTANCE_BASED_LOGGING") == nullptr;
108 return active;
109}
110
111static struct ExtLogConfig : public scc::LogConfig {
112 shared_ptr<spdlog::logger> file_logger;
113 shared_ptr<spdlog::logger> console_logger;
114#ifdef USE_C_REGEX
115 regex_t start_state{};
116#else
117 regex reg_ex;
118#endif
119 sc_time cycle_base{0, SC_NS};
120 auto operator=(const scc::LogConfig& o) -> ExtLogConfig& {
121 scc::LogConfig::operator=(o);
122 return *this;
123 }
124 auto match(const char* type) -> bool {
125#ifdef USE_C_REGEX
126 return regexec(&start_state, type, 0, nullptr, 0) == 0;
127#else
128 return regex_search(type, reg_ex);
129#endif
130 }
131 bool initialized{false};
132 std::mutex mtx;
133 nonstd::optional<cci::cci_broker_handle> broker;
134} log_cfg;
135
136auto get_tuple(const sc_time& t) -> tuple<sc_time::value_type, sc_time_unit> {
137 auto val = t.value();
138 auto tr = (uint64_t)(sc_time::from_value(1).to_seconds() * 1E15);
139 auto scale = 0U;
140 while((tr % 10) == 0) {
141 tr /= 10;
142 scale++;
143 }
144 sc_assert(tr == 1);
145
146 auto tu = scale / 3;
147 while(tu < SC_SEC && (val % 10) == 0) {
148 val /= 10;
149 scale++;
150 tu += (0 == (scale % 3));
151 }
152 for(scale %= 3; scale != 0; scale--)
153 val *= 10;
154 return make_tuple(val, static_cast<sc_time_unit>(tu));
155}
156
157auto time2string(const sc_time& t) -> string {
158 const array<const char*, 6> time_units{"fs", "ps", "ns", "us", "ms", "s "};
159 const array<uint64_t, 6> multiplier{
160 1ULL, 1000ULL, 1000ULL * 1000, 1000ULL * 1000 * 1000, 1000ULL * 1000 * 1000 * 1000, 1000ULL * 1000 * 1000 * 1000 * 1000};
161 ostringstream oss;
162 if(!t.value()) {
163 oss << "0 s ";
164 } else {
165 const auto tt = get_tuple(t);
166 const auto val = get<0>(tt);
167 const auto scale = get<1>(tt);
168 const auto fs_val = val * multiplier[scale];
169 for(int j = multiplier.size() - 1; j >= scale; --j) {
170 if(fs_val >= multiplier[j]) {
171 const auto i = val / multiplier[j - scale];
172 const auto f = val % multiplier[j - scale];
173 oss << i << '.' << setw(3 * (j - scale)) << setfill('0') << right << f << ' ' << time_units[j];
174 break;
175 }
176 }
177 }
178 return oss.str();
179}
180auto compose_message(const sc_report& rep, const scc::LogConfig& cfg) -> const string {
181 if(rep.get_severity() > SC_INFO || cfg.log_filter_regex.length() == 0 || rep.get_verbosity() == sc_core::SC_MEDIUM ||
182 log_cfg.match(rep.get_msg_type())) {
183 stringstream os;
184 if(unlikely(cfg.print_sys_time))
185 os << "<" << logging::now_time() << ">";
186 if(likely(cfg.print_sim_time)) {
187 if(unlikely(log_cfg.cycle_base.value())) {
188 if(unlikely(cfg.print_delta))
189 os << "[" << std::setw(7) << std::setfill(' ') << sc_time_stamp().value() / log_cfg.cycle_base.value() << "(" << setw(5)
190 << sc_delta_count() << ")]";
191 else
192 os << "[" << std::setw(7) << std::setfill(' ') << sc_time_stamp().value() / log_cfg.cycle_base.value() << "]";
193 } else {
194 auto t = time2string(sc_time_stamp());
195 if(unlikely(cfg.print_delta))
196 os << "[" << std::setw(20) << std::setfill(' ') << t << "(" << setw(5) << sc_delta_count() << ")]";
197 else
198 os << "[" << std::setw(20) << std::setfill(' ') << t << "]";
199 }
200 }
201 if(unlikely(rep.get_id() >= 0))
202 os << " ("
203 << "IWEF"[rep.get_severity()] << rep.get_id() << ") " << rep.get_msg_type() << ": ";
204 else if(cfg.msg_type_field_width) {
205 if(cfg.msg_type_field_width == std::numeric_limits<unsigned>::max())
206 os << " " << rep.get_msg_type() << ": ";
207 else
208 os << " " << util::padded(rep.get_msg_type(), cfg.msg_type_field_width) << ": ";
209 }
210 if(*rep.get_msg())
211 os << rep.get_msg();
212 if(rep.get_severity() > SC_INFO) {
213 if(rep.get_line_number())
214 os << "\n [FILE:" << rep.get_file_name() << ":" << rep.get_line_number() << "]";
215 sc_simcontext* simc = sc_get_curr_simcontext();
216 if(simc && sc_is_running()) {
217 const char* proc_name = rep.get_process_name();
218 if(proc_name)
219 os << "\n [PROCESS:" << proc_name << "]";
220 }
221 }
222 return os.str();
223 } else
224 return "";
225}
226
227inline void log2logger(spdlog::logger& logger, const sc_report& rep, const scc::LogConfig& cfg) {
228 auto msg = compose_message(rep, cfg);
229 if(!msg.size())
230 return;
231 switch(rep.get_severity()) {
232 case SC_INFO:
233 switch(rep.get_verbosity()) {
234 case SC_DEBUG:
235 case SC_FULL:
236 logger.trace(msg);
237 break;
238 case SC_HIGH:
239 logger.debug(msg);
240 break;
241 default:
242 logger.info(msg);
243 break;
244 }
245 break;
246 case SC_WARNING:
247 logger.warn(msg);
248 break;
249 case SC_ERROR:
250 logger.error(msg);
251#ifdef WITH_STACKTRACE
252 if(getenv("SCC_PRINT_STACK_ON_ERROR"))
253 logger.error(boost::stacktrace::to_string(boost::stacktrace::stacktrace()));
254#endif
255 break;
256 case SC_FATAL:
257 logger.critical(msg);
258#ifdef WITH_STACKTRACE
259 if(getenv("SCC_PRINT_STACK_ON_ERROR"))
260 logger.error(boost::stacktrace::to_string(boost::stacktrace::stacktrace()));
261#endif
262 break;
263 default:
264 break;
265 }
266}
267
268inline void flush_loggers() {
269 log_cfg.console_logger->flush();
270 if(log_cfg.file_logger)
271 log_cfg.file_logger->flush();
272}
273
274void report_handler(const sc_report& rep, const sc_actions& actions) {
275 thread_local bool sc_stop_called = false;
276 if(actions & SC_DO_NOTHING)
277 return;
278 if(rep.get_severity() == sc_core::SC_INFO || !log_cfg.report_only_first_error || sc_report_handler::get_count(SC_ERROR) < 2) {
279 if((actions & SC_DISPLAY) && (!log_cfg.file_logger || rep.get_verbosity() < SC_HIGH))
280 try {
281 log2logger(*log_cfg.console_logger, rep, log_cfg);
282 } catch(spdlog::spdlog_ex e) {
283 }
284 if((actions & SC_LOG) && log_cfg.file_logger) {
285 scc::LogConfig lcfg(log_cfg);
286 lcfg.print_sim_time = true;
287 if(!lcfg.msg_type_field_width)
288 lcfg.msg_type_field_width = 24;
289 log2logger(*log_cfg.file_logger, rep, lcfg);
290 }
291 }
292 if(actions & SC_STOP) {
293 try {
294 flush_loggers();
295 } catch(spdlog::spdlog_ex e) {
296 }
297 if(sc_is_running() && !sc_stop_called) {
298 sc_stop();
299 sc_stop_called = true;
300 }
301 }
302 if(actions & SC_ABORT) {
303 try {
304 flush_loggers();
305 } catch(spdlog::spdlog_ex e) {
306 }
307 spdlog::shutdown();
308 abort();
309 }
310 if(actions & SC_THROW) {
311 try {
312 flush_loggers();
313 } catch(spdlog::spdlog_ex e) {
314 }
315 throw rep;
316 }
317 if(sc_time_stamp().value() && !sc_is_running()) {
318 try {
319 flush_loggers();
320 } catch(spdlog::spdlog_ex e) {
321 }
322 }
323}
324} // namespace
325namespace scc {
326std::mutex verbosity_mtx;
327}
329: os(os)
330, level(level) {
331 old_buf = os.rdbuf(this); // save and redirect
332}
333
335 os.rdbuf(old_buf); // restore
336}
337
339 os.rdbuf(old_buf); // restore
340 old_buf = nullptr;
341}
342
343auto scc::stream_redirection::xsputn(const char_type* s, streamsize n) -> streamsize {
344 auto sz = stringbuf::xsputn(s, n);
345 if(s[n - 1] == '\n') {
346 sync();
347 }
348 return sz;
349}
350
351static const array<sc_severity, 8> severity = {SC_FATAL, // scc::log::NONE
352 SC_FATAL, // scc::log::FATAL
353 SC_ERROR, // scc::log::ERROR
354 SC_WARNING, // scc::log::WARNING
355 SC_INFO, // scc::log::INFO
356 SC_INFO, // scc::log::DEBUG
357 SC_INFO, // scc::log::TRACE
358 SC_INFO}; // scc::log::DBGTRACE
359static const array<sc_verbosity, 8> verbosity = {SC_NONE, // scc::log::NONE
360 SC_LOW, // scc::log::FATAL
361 SC_LOW, // scc::log::ERROR
362 SC_LOW, // scc::log::WARNING
363 SC_MEDIUM, // scc::log::INFO
364 SC_HIGH, // scc::log::DEBUG
365 SC_FULL, // scc::log::TRACE
366 SC_DEBUG}; // scc::log::DBGTRACE
367
368auto scc::stream_redirection::sync() -> int {
369 if(level <= log_cfg.level) {
370 auto timestr = time2string(sc_time_stamp());
371 istringstream buf(str());
372 string line;
373 while(getline(buf, line)) {
374 ::sc_report_handler::report(severity[static_cast<unsigned>(level)], "SystemC", line.c_str(),
375 verbosity[static_cast<unsigned>(level)], "", 0);
376 }
377 str(string(""));
378 }
379 return 0; // Success
380}
381
382static void configure_logging() {
383 std::lock_guard<mutex> lock(log_cfg.mtx);
384 static bool spdlog_initialized = false;
385 if(!log_cfg.dont_create_broker)
386 scc::init_cci("SCCBroker");
387 log_cfg.broker = cci::cci_get_global_broker(originator);
388 if(log_cfg.install_handler) {
389 if(!log_cfg.instance_based_log_levels || getenv("SCC_DISABLE_INSTANCE_BASED_LOGGING"))
390 inst_based_logging() = false;
391 sc_report_handler::set_verbosity_level(verbosity[static_cast<unsigned>(log_cfg.level)]);
392 sc_report_handler::set_handler(report_handler);
393 if(!spdlog_initialized) {
394 spdlog::init_thread_pool(1024U,
395 log_cfg.log_file_name.size() ? 2U : 1U); // queue with 8k items and 1 backing thread.
396 log_cfg.console_logger = log_cfg.log_async ? spdlog::stdout_color_mt<spdlog::async_factory>("console_logger")
397 : spdlog::stdout_color_mt("console_logger");
398 auto logger_fmt = log_cfg.print_severity ? "[%L] %v" : "%v";
399 if(log_cfg.colored_output) {
400 std::ostringstream os;
401 os << "%^" << logger_fmt << "%$";
402 log_cfg.console_logger->set_pattern(os.str());
403 } else
404 log_cfg.console_logger->set_pattern("[%L] %v");
405 log_cfg.console_logger->flush_on(spdlog::level::err);
406 log_cfg.console_logger->set_level(spdlog::level::level_enum::trace);
407 if(log_cfg.log_file_name.size()) {
408 {
409 ofstream ofs;
410 ofs.open(log_cfg.log_file_name, ios::out | ios::trunc);
411 }
412 log_cfg.file_logger = log_cfg.log_async
413 ? spdlog::basic_logger_mt<spdlog::async_factory>("file_logger", log_cfg.log_file_name)
414 : spdlog::basic_logger_mt("file_logger", log_cfg.log_file_name);
415 if(log_cfg.print_severity)
416 log_cfg.file_logger->set_pattern("[%8l] %v");
417 else
418 log_cfg.file_logger->set_pattern("%v");
419 log_cfg.file_logger->flush_on(spdlog::level::err);
420 log_cfg.file_logger->set_level(spdlog::level::level_enum::trace);
421 }
422 spdlog_initialized = true;
423 } else {
424 log_cfg.console_logger = spdlog::get("console_logger");
425 if(log_cfg.log_file_name.size())
426 log_cfg.file_logger = spdlog::get("file_logger");
427 }
428 if(log_cfg.log_filter_regex.size()) {
429#ifdef USE_C_REGEX
430 regcomp(&log_cfg.start_state, log_cfg.log_filter_regex.c_str(), REG_EXTENDED);
431#else
432 log_cfg.reg_ex = regex(log_cfg.log_filter_regex, regex::extended | regex::icase);
433#endif
434 }
435 logging::LoggerCallbacks::set_output_cb([](logging::log_level lvl, std::string const& msg_type, std::string const& msg) {
436 switch(lvl) {
437 case logging::log_level::FATAL:
438 ::scc ::ScLogger<::sc_core ::SC_FATAL>("", 0, sc_core ::SC_MEDIUM)
439 .type(msg_type.size() ? msg_type : std::string("C++"))
440 .get()
441 << msg;
442 break;
443 case logging::log_level::ERR:
444 ::scc ::ScLogger<::sc_core ::SC_ERROR>("", 0, sc_core ::SC_MEDIUM)
445 .type(msg_type.size() ? msg_type : std::string("C++"))
446 .get()
447 << msg;
448 break;
449 case logging::log_level::WARN:
450 if(::scc ::get_log_verbosity(msg_type) >= sc_core ::SC_LOW)
451 ::scc ::ScLogger<::sc_core ::SC_WARNING>("", 0, sc_core ::SC_MEDIUM)
452 .type(msg_type.size() ? msg_type : std::string("C++"))
453 .get()
454 << msg;
455 break;
456 case logging::log_level::INFO:
457 if(::scc ::get_log_verbosity(msg_type) >= sc_core ::SC_MEDIUM)
458 ::scc ::ScLogger<::sc_core ::SC_INFO>("", 0, sc_core ::SC_MEDIUM)
459 .type(msg_type.size() ? msg_type : std::string("C++"))
460 .get()
461 << msg;
462 break;
463 case logging::log_level::DEBUG:
464 if(::scc ::get_log_verbosity(msg_type) >= sc_core ::SC_HIGH)
465 ::scc ::ScLogger<::sc_core ::SC_INFO>("", 0, sc_core ::SC_HIGH)
466 .type(msg_type.size() ? msg_type : std::string("C++"))
467 .get()
468 << msg;
469 break;
470 case logging::log_level::TRACE:
471 if(::scc ::get_log_verbosity(msg_type) >= sc_core ::SC_FULL)
472 ::scc ::ScLogger<::sc_core ::SC_INFO>("", 0, sc_core ::SC_FULL).type(msg_type).get() << msg;
473 break;
474 case logging::log_level::TRACEALL:
475 if(::scc ::get_log_verbosity(msg_type) >= sc_core ::SC_DEBUG)
476 ::scc ::ScLogger<::sc_core ::SC_INFO>("", 0, sc_core ::SC_DEBUG)
477 .type(msg_type.size() ? msg_type : std::string("C++"))
478 .get()
479 << msg;
480 break;
481 default:
482 break;
483 }
484 });
485 }
486}
487
488void scc::reinit_logging() { reinit_logging(log_cfg.level); }
489
490void scc::reinit_logging(scc::log level) {
491 if(log_cfg.install_handler)
492 sc_report_handler::set_handler(report_handler);
493 log_cfg.level = level;
494 lut.clear();
495 if(!log_cfg.instance_based_log_levels || getenv("SCC_DISABLE_INSTANCE_BASED_LOGGING"))
496 inst_based_logging() = false;
497 log_cfg.initialized = true;
498}
499
500bool scc::is_logging_initialized() { return log_cfg.initialized; }
501
502void scc::init_logging(scc::log level, unsigned type_field_width, bool print_time) {
503 log_cfg.msg_type_field_width = type_field_width;
504 log_cfg.print_sys_time = print_time;
505 log_cfg.level = level;
506 configure_logging();
507 log_cfg.initialized = true;
508}
509
510void scc::init_logging(const scc::LogConfig& log_config) {
511 log_cfg = log_config;
512 configure_logging();
513 log_cfg.initialized = true;
514}
515
517 log_cfg.level = level;
518 sc_report_handler::set_verbosity_level(verbosity[static_cast<unsigned>(level)]);
519 log_cfg.console_logger->set_level(
520 static_cast<spdlog::level::level_enum>(SPDLOG_LEVEL_OFF - min<int>(SPDLOG_LEVEL_OFF, static_cast<int>(log_cfg.level))));
521 log_cfg.initialized = true;
522}
523
524auto scc::get_logging_level() -> scc::log { return log_cfg.level; }
525
526void scc::set_cycle_base(sc_time period) { log_cfg.cycle_base = period; }
527
529 this->level = level;
530 return *this;
531}
532
534 this->msg_type_field_width = width;
535 return *this;
536}
537
539 this->print_sys_time = enable;
540 return *this;
541}
542
544 this->print_sim_time = enable;
545 return *this;
546}
547
549 this->print_delta = enable;
550 return *this;
551}
552
554 this->print_severity = enable;
555 return *this;
556}
557
558auto scc::LogConfig::logFileName(string&& name) -> scc::LogConfig& {
559 this->log_file_name = name;
560 return *this;
561}
562
563auto scc::LogConfig::logFileName(const string& name) -> scc::LogConfig& {
564 this->log_file_name = name;
565 return *this;
566}
567
569 this->colored_output = enable;
570 return *this;
571}
572
573auto scc::LogConfig::logFilterRegex(string&& expr) -> scc::LogConfig& {
574 this->log_filter_regex = expr;
575 return *this;
576}
577
578auto scc::LogConfig::logFilterRegex(const string& expr) -> scc::LogConfig& {
579 this->log_filter_regex = expr;
580 return *this;
581}
582
584 this->log_async = v;
585 return *this;
586}
587
589 this->dont_create_broker = v;
590 return *this;
591}
592
594 this->report_only_first_error = v;
595 return *this;
596}
598 this->instance_based_log_levels = v;
599 return *this;
600}
602 this->install_handler = v;
603 return *this;
604}
605namespace {
606std::mutex mtx;
607sc_core::sc_verbosity __get_log_verbosity(string current_name, char const* str, cci::cci_broker_handle const& broker,
608 sc_core::sc_verbosity verb) {
609 std::lock_guard<std::mutex> lk(mtx);
610 while(true) {
611 string param_name = (current_name.empty()) ? SCC_LOG_LEVEL_PARAM_NAME : current_name + "." SCC_LOG_LEVEL_PARAM_NAME;
612 auto h = broker.get_param_handle(param_name);
613 if(h.is_valid()) {
614 sc_core::sc_verbosity ret = verbosity.at(std::min<unsigned>(h.get_cci_value().get_int(), verbosity.size() - 1));
615 lut.insert(str, ret);
616 return ret;
617 } else {
618 auto val = broker.get_preset_cci_value(param_name);
619 if(val.is_int()) {
620 sc_core::sc_verbosity ret = verbosity.at(std::min<unsigned>(val.get_int(), verbosity.size() - 1));
621 lut.insert(str, ret);
622 return ret;
623 } else {
624 if(current_name.empty()) {
625 lut.insert(str, verb);
626 return verb;
627 }
628 auto pos = current_name.rfind(".");
629 if(pos == std::string::npos) {
630 current_name = "";
631 } else {
632 current_name = current_name.substr(0, pos);
633 }
634 }
635 }
636 return verb;
637 }
638}
639} // namespace
640
641auto scc::get_log_verbosity(char const* str) -> sc_core::sc_verbosity {
642 std::unique_lock<std::mutex> lock(verbosity_mtx);
643 auto global_verb = static_cast<sc_core::sc_verbosity>(::sc_core::sc_report_handler::get_verbosity_level());
644 lock.unlock();
645 if(inst_based_logging()) {
646 auto res = lut.get(str);
647 if(std::get<0>(res))
648 return std::get<1>(res);
649 auto* curr_object = sc_core::sc_get_current_object();
650 if(strchr(str, '.') == nullptr || curr_object) {
651 string current_name = std::string(str);
652 if(log_cfg.broker)
653 return __get_log_verbosity(current_name, str, log_cfg.broker.value(), global_verb);
654 else {
655 return __get_log_verbosity(current_name, str, curr_object ? cci::cci_get_broker() : cci::cci_get_global_broker(originator),
656 global_verb);
657 }
658 }
659 }
660 return global_verb;
661}
~stream_redirection()
destructor restoring the output stream buffer
Definition report.cpp:334
void reset()
reset the stream redirection and restore output buffer of the stream
Definition report.cpp:338
stream_redirection(std::ostream &os, log level)
constructor redirecting the given stream to a SystemC log message of given llog level
log_level
enum defining the log levels
Definition logging.h:53
std::string now_time()
Definition logging.h:328
SCC TLM utilities.
void set_logging_level(log level)
sets the SystemC logging level
Definition report.cpp:516
void init_logging(log level=log::WARNING, unsigned type_field_width=24, bool print_time=false)
initializes the SystemC logging system with a particular logging level
Definition report.cpp:502
bool is_logging_initialized()
get the state of the SCC logging system
Definition report.cpp:500
void set_cycle_base(sc_core::sc_time period)
sets the cycle base for cycle based logging
log get_logging_level()
get the SystemC logging level
Definition report.cpp:524
sc_core::sc_verbosity get_log_verbosity()
get the global verbosity level
Definition report.h:324
log
enum defining the log levels
Definition report.h:86
std::mutex verbosity_mtx
a mutex needed to syncronize verbosity manipulations
Definition report.cpp:326
std::string padded(std::string str, size_t width, bool show_ellipsis=true)
pad a string to a given length by either cutting of the overflow or inserting an ellipsis
Definition ities.h:396
the configuration class for the logging setup
Definition report.h:163
LogConfig & printSeverity(bool=true)
Definition report.cpp:553
LogConfig & printSysTime(bool=true)
Definition report.cpp:538
LogConfig & reportOnlyFirstError(bool=true)
Definition report.cpp:593
LogConfig & coloredOutput(bool=true)
Definition report.cpp:568
LogConfig & logFileName(std::string &&)
LogConfig & dontCreateBroker(bool=true)
Definition report.cpp:588
LogConfig & logLevel(log)
Definition report.cpp:528
LogConfig & msgTypeFieldWidth(unsigned)
Definition report.cpp:533
LogConfig & printSimTime(bool=true)
Definition report.cpp:543
LogConfig & logAsync(bool=true)
Definition report.cpp:583
LogConfig & printDelta(bool=true)
Definition report.cpp:548
LogConfig & instanceBasedLogLevels(bool=true)
Definition report.cpp:597
LogConfig & installHandler(bool=true)
Definition report.cpp:601
LogConfig & logFilterRegex(std::string &&)