From ea6b370fe79e043ed949033f9f3a4306b668aa94 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Wed, 25 Jul 2018 19:30:30 -0700 Subject: systemc: Implement most of the sc_report_handler mechanism. This doesn't include support for the deprecated integer message ids. Change-Id: I309d58df1cdc464428189eb0b7180edf41ca4f67 Reviewed-on: https://gem5-review.googlesource.com/12048 Reviewed-by: Gabe Black Maintainer: Gabe Black --- src/systemc/core/process.cc | 13 ++ src/systemc/core/process.hh | 8 + src/systemc/ext/utils/sc_report.hh | 49 +++- src/systemc/ext/utils/sc_report_handler.hh | 3 +- src/systemc/utils/sc_report.cc | 97 +++----- src/systemc/utils/sc_report_handler.cc | 348 ++++++++++++++++++++++------- 6 files changed, 357 insertions(+), 161 deletions(-) diff --git a/src/systemc/core/process.cc b/src/systemc/core/process.cc index 39ee9e051..6a0e7d5a3 100644 --- a/src/systemc/core/process.cc +++ b/src/systemc/core/process.cc @@ -333,6 +333,19 @@ Process::ready() scheduler.ready(this); } +void +Process::lastReport(::sc_core::sc_report *report) +{ + if (report) { + _lastReport = std::unique_ptr<::sc_core::sc_report>( + new ::sc_core::sc_report(*report)); + } else { + _lastReport = nullptr; + } +} + +::sc_core::sc_report *Process::lastReport() const { return _lastReport.get(); } + Process::Process(const char *name, ProcessFuncWrapper *func, bool _dynamic, bool needs_start) : ::sc_core::sc_object(name), excWrapper(nullptr), func(func), diff --git a/src/systemc/core/process.hh b/src/systemc/core/process.hh index 3b1fb4eb6..8abafbd69 100644 --- a/src/systemc/core/process.hh +++ b/src/systemc/core/process.hh @@ -31,6 +31,7 @@ #define __SYSTEMC_CORE_PROCESS_HH__ #include +#include #include #include "base/fiber.hh" @@ -44,6 +45,7 @@ #include "systemc/ext/core/sc_module.hh" #include "systemc/ext/core/sc_port.hh" #include "systemc/ext/core/sc_process_handle.hh" +#include "systemc/ext/utils/sc_report.hh" namespace sc_gem5 { @@ -270,6 +272,7 @@ class Process : public ::sc_core::sc_object, public ListNode bool needsStart() const { return _needsStart; } bool dynamic() const { return _dynamic; } bool isUnwinding() const { return _isUnwinding; } + void isUnwinding(bool v) { _isUnwinding = v; } bool terminated() const { return _terminated; } void forEachKid(const std::function &work); @@ -318,6 +321,9 @@ class Process : public ::sc_core::sc_object, public ListNode static Process *newest() { return _newest; } + void lastReport(::sc_core::sc_report *report); + ::sc_core::sc_report *lastReport() const; + protected: Process(const char *name, ProcessFuncWrapper *func, bool _dynamic, bool needs_start); @@ -355,6 +361,8 @@ class Process : public ::sc_core::sc_object, public ListNode PendingSensitivities pendingStaticSensitivities; Sensitivity *dynamicSensitivity; + + std::unique_ptr<::sc_core::sc_report> _lastReport; }; inline void diff --git a/src/systemc/ext/utils/sc_report.hh b/src/systemc/ext/utils/sc_report.hh index f0ed14fb2..6f652ce2c 100644 --- a/src/systemc/ext/utils/sc_report.hh +++ b/src/systemc/ext/utils/sc_report.hh @@ -31,12 +31,13 @@ #define __SYSTEMC_EXT_UTIL_SC_REPORT_HH__ #include +#include + +#include "systemc/ext/core/sc_time.hh" namespace sc_core { -class sc_time; - enum sc_severity { SC_INFO = 0, @@ -56,6 +57,8 @@ enum sc_verbosity SC_DEBUG = 500 }; +class sc_report_handler; + class sc_report : public std::exception { public: @@ -63,15 +66,15 @@ class sc_report : public std::exception sc_report &operator = (const sc_report &); virtual ~sc_report() throw(); - sc_severity get_severity() const; - const char *get_msg_type() const; - const char *get_msg() const; - int get_verbosity() const; - const char *get_file_name() const; - int get_line_number() const; + sc_severity get_severity() const { return _severity; } + const char *get_msg_type() const { return _msgType; } + const char *get_msg() const { return _msg; } + int get_verbosity() const { return _verbosity; } + const char *get_file_name() const { return _fileName; } + int get_line_number() const { return _lineNumber; } - const sc_time &get_time() const; - const char *get_process_name() const; + const sc_time &get_time() const { return _time; } + const char *get_process_name() const { return _processName; } virtual const char *what() const throw(); @@ -83,7 +86,31 @@ class sc_report : public std::exception static void suppress_id(int id, bool); // Only for info or warning. static void suppress_infos(bool); static void suppress_warnings(bool); - int get_id() const; + int get_id() const { return _id; } + + private: + friend class sc_report_handler; + + sc_report(sc_severity _severity, + const char *_msgType, + const char *_msg, + int _verbosity, + const char *_fileName, + int _lineNumber, + sc_time _time, + const char *_processName, + int _id); + + sc_severity _severity; + const char *_msgType; + const char *_msg; + int _verbosity; + const char *_fileName; + int _lineNumber; + sc_time _time; + const char *_processName; + int _id; + std::string _what; }; // A non-standard function the Accellera datatypes rely on. diff --git a/src/systemc/ext/utils/sc_report_handler.hh b/src/systemc/ext/utils/sc_report_handler.hh index 33c2499e0..f65b32cca 100644 --- a/src/systemc/ext/utils/sc_report_handler.hh +++ b/src/systemc/ext/utils/sc_report_handler.hh @@ -82,8 +82,7 @@ class sc_report_handler static int stop_after(sc_severity, int limit=-1); static int stop_after(const char *msg_type, int limit=-1); - static int stop_after(const char *msg_type, sc_severity, - sc_actions=SC_UNSPECIFIED); + static int stop_after(const char *msg_type, sc_severity, int limit=-1); static int get_count(sc_severity); static int get_count(const char *msg_type); diff --git a/src/systemc/utils/sc_report.cc b/src/systemc/utils/sc_report.cc index 6edbf2a05..838488021 100644 --- a/src/systemc/utils/sc_report.cc +++ b/src/systemc/utils/sc_report.cc @@ -29,85 +29,47 @@ #include "base/logging.hh" #include "systemc/ext/utils/sc_report.hh" +#include "systemc/ext/utils/sc_report_handler.hh" namespace sc_core { -sc_report::sc_report(const sc_report &) +sc_report::sc_report(sc_severity _severity, const char *_msgType, + const char *_msg, int _verbosity, const char *_fileName, + int _lineNumber, sc_time _time, const char *_processName, int _id) : + _severity(_severity), _msgType(_msgType), _msg(_msg), + _verbosity(_verbosity), _fileName(_fileName), _lineNumber(_lineNumber), + _time(_time), _processName(_processName), _id(_id) { - warn("%s not implemented.\n", __PRETTY_FUNCTION__); + _what = sc_report_compose_message(*this); } +sc_report::sc_report(const sc_report &r) : + sc_report(r._severity, r._msgType, r._msg, r._verbosity, r._fileName, + r._lineNumber, r._time, r._processName, r._id) +{} + sc_report & -sc_report::operator = (const sc_report &) -{ - warn("%s not implemented.\n", __PRETTY_FUNCTION__); +sc_report::operator = (const sc_report &r) +{ + _severity = r._severity; + _msgType = r._msgType; + _msg = r._msg; + _verbosity = r._verbosity; + _fileName = r._fileName; + _lineNumber = r._lineNumber; + _time = r._time; + _processName = r._processName; + _id = r._id; return *this; } sc_report::~sc_report() throw() {} -sc_severity -sc_report::get_severity() const -{ - warn("%s not implemented.\n", __PRETTY_FUNCTION__); - return SC_FATAL; -} - -const char * -sc_report::get_msg_type() const -{ - warn("%s not implemented.\n", __PRETTY_FUNCTION__); - return ""; -} - -const char * -sc_report::get_msg() const -{ - warn("%s not implemented.\n", __PRETTY_FUNCTION__); - return ""; -} - -int -sc_report::get_verbosity() const -{ - warn("%s not implemented.\n", __PRETTY_FUNCTION__); - return SC_NONE; -} - -const char * -sc_report::get_file_name() const -{ - warn("%s not implemented.\n", __PRETTY_FUNCTION__); - return ""; -} - -int -sc_report::get_line_number() const -{ - warn("%s not implemented.\n", __PRETTY_FUNCTION__); - return 0; -} - -const sc_time & -sc_report::get_time() const -{ - warn("%s not implemented.\n", __PRETTY_FUNCTION__); - return *(const sc_time *)nullptr; -} - -const char * -sc_report::get_process_name() const -{ - warn("%s not implemented.\n", __PRETTY_FUNCTION__); - return ""; -} - const char * sc_report::what() const throw() { - warn("%s not implemented.\n", __PRETTY_FUNCTION__); - return ""; + return _what.c_str(); } const char * @@ -154,17 +116,10 @@ sc_report::suppress_warnings(bool) warn("%s not implemented.\n", __PRETTY_FUNCTION__); } -int -sc_report::get_id() const -{ - warn("%s not implemented.\n", __PRETTY_FUNCTION__); - return 0; -} - void sc_abort() { - panic("%s not implemented.\n", __PRETTY_FUNCTION__); + panic("simulation aborted"); } } // namespace sc_core diff --git a/src/systemc/utils/sc_report_handler.cc b/src/systemc/utils/sc_report_handler.cc index 1a0e0d491..6b259342a 100644 --- a/src/systemc/utils/sc_report_handler.cc +++ b/src/systemc/utils/sc_report_handler.cc @@ -27,225 +27,419 @@ * Authors: Gabe Black */ +#include +#include +#include +#include + #include "base/logging.hh" +#include "systemc/core/process.hh" +#include "systemc/core/scheduler.hh" +#include "systemc/ext/core/sc_main.hh" #include "systemc/ext/utils/sc_report_handler.hh" namespace sc_core { +namespace +{ + +std::unique_ptr logFileName; +std::unique_ptr logFile; + +struct ReportCatInfo +{ + explicit ReportCatInfo(sc_actions actions) : + actions(actions), count(0), limit(-1) + {} + ReportCatInfo() : ReportCatInfo(SC_UNSPECIFIED) {} + + bool + checkLimit(sc_actions &actions) + { + if (limit == 0 || count < limit) + return false; + if (limit != -1) + actions |= SC_STOP; + return true; + } + + sc_actions actions; + int count; + int limit; +}; + +const char *severityNames[] = { + [SC_INFO] = "Info", + [SC_WARNING] = "Warning", + [SC_ERROR] = "Error", + [SC_FATAL] = "Fatal" +}; + +ReportCatInfo catForSeverity[SC_MAX_SEVERITY] = +{ + [SC_INFO] = ReportCatInfo(SC_DEFAULT_INFO_ACTIONS), + [SC_WARNING] = ReportCatInfo(SC_DEFAULT_WARNING_ACTIONS), + [SC_ERROR] = ReportCatInfo(SC_DEFAULT_ERROR_ACTIONS), + [SC_FATAL] = ReportCatInfo(SC_DEFAULT_FATAL_ACTIONS) +}; + +std::map catForMsgType; +std::map, ReportCatInfo> + catForSeverityAndMsgType; + +int verbosityLevel = SC_MEDIUM; + +sc_actions suppressedActions = SC_UNSPECIFIED; +sc_actions forcedActions = SC_UNSPECIFIED; +sc_actions catchActions = SC_UNSPECIFIED; + +sc_report_handler_proc reportHandlerProc = &sc_report_handler::default_handler; + +sc_actions maxAction = SC_ABORT; + +std::unique_ptr globalReportCache; + +} // anonymous namespace + void -sc_report_handler::report(sc_severity, const char *msg_type, const char *msg, - const char *file, int line) +sc_report_handler::report(sc_severity severity, const char *msg_type, + const char *msg, const char *file, int line) { - warn("%s not implemented.\n", __PRETTY_FUNCTION__); + report(severity, msg_type, msg, SC_MEDIUM, file, line); } void -sc_report_handler::report(sc_severity, const char *msg_type, const char *msg, - int verbosity, const char *file, int line) -{ - warn("%s not implemented.\n", __PRETTY_FUNCTION__); +sc_report_handler::report(sc_severity severity, const char *msg_type, + const char *msg, int verbosity, const char *file, + int line) +{ + if (severity == SC_INFO && verbosity > verbosityLevel) + return; + + ReportCatInfo &sevInfo = catForSeverity[severity]; + ReportCatInfo &msgInfo = catForMsgType[msg_type]; + ReportCatInfo &sevMsgInfo = catForSeverityAndMsgType[ + std::make_pair(std::string(msg_type), severity)]; + + sevInfo.count++; + msgInfo.count++; + sevMsgInfo.count++; + + sc_actions actions = SC_UNSPECIFIED; + if (sevMsgInfo.actions != SC_UNSPECIFIED) + actions = sevMsgInfo.actions; + else if (msgInfo.actions != SC_UNSPECIFIED) + actions = msgInfo.actions; + else if (sevInfo.actions != SC_UNSPECIFIED) + actions = sevInfo.actions; + + actions &= ~suppressedActions; + actions |= forcedActions; + + if (sevMsgInfo.checkLimit(actions) && msgInfo.checkLimit(actions)) + sevInfo.checkLimit(actions); + + ::sc_gem5::Process *current = ::sc_gem5::scheduler.current(); + sc_report report(severity, msg_type, msg, verbosity, file, line, + sc_time::from_value(::sc_gem5::scheduler.getCurTick()), + current ? current->name() : nullptr, -1); + + if (actions & SC_CACHE_REPORT) { + if (current) { + current->lastReport(&report); + } else { + globalReportCache = + std::unique_ptr(new sc_report(report)); + } + } + + reportHandlerProc(report, actions); } void sc_report_handler::report(sc_severity, int id, const char *msg, const char *file, int line) { + warn("%s:%d %s\n", file, line, msg); warn("%s not implemented.\n", __PRETTY_FUNCTION__); } sc_actions -sc_report_handler::set_actions(sc_severity, sc_actions) +sc_report_handler::set_actions(sc_severity severity, sc_actions actions) { - warn("%s not implemented.\n", __PRETTY_FUNCTION__); - return SC_UNSPECIFIED; + ReportCatInfo &info = catForSeverity[severity]; + sc_actions previous = info.actions; + info.actions = actions; + return previous; } sc_actions -sc_report_handler::set_actions(const char *msg_type, sc_actions) +sc_report_handler::set_actions(const char *msg_type, sc_actions actions) { - warn("%s not implemented.\n", __PRETTY_FUNCTION__); - return SC_UNSPECIFIED; + ReportCatInfo &info = catForMsgType[msg_type]; + sc_actions previous = info.actions; + info.actions = actions; + return previous; } sc_actions -sc_report_handler::set_actions(const char *msg_type, sc_severity, sc_actions) -{ - warn("%s not implemented.\n", __PRETTY_FUNCTION__); - return SC_UNSPECIFIED; +sc_report_handler::set_actions( + const char *msg_type, sc_severity severity, sc_actions actions) +{ + ReportCatInfo &info = catForSeverityAndMsgType[ + std::make_pair(std::string(msg_type), severity)]; + sc_actions previous = info.actions; + info.actions = actions; + return previous; } int -sc_report_handler::stop_after(sc_severity, int limit) +sc_report_handler::stop_after(sc_severity severity, int limit) { - warn("%s not implemented.\n", __PRETTY_FUNCTION__); - return 0; + ReportCatInfo &info = catForSeverity[severity]; + int previous = info.limit; + info.limit = limit; + return previous; } int sc_report_handler::stop_after(const char *msg_type, int limit) { - warn("%s not implemented.\n", __PRETTY_FUNCTION__); - return 0; + ReportCatInfo &info = catForMsgType[msg_type]; + int previous = info.limit; + info.limit = limit; + return previous; } int -sc_report_handler::stop_after(const char *msg_type, sc_severity, sc_actions) -{ - warn("%s not implemented.\n", __PRETTY_FUNCTION__); - return 0; +sc_report_handler::stop_after( + const char *msg_type, sc_severity severity, int limit) +{ + ReportCatInfo &info = catForSeverityAndMsgType[ + std::make_pair(std::string(msg_type), severity)]; + int previous = info.limit; + info.limit = limit; + return previous; } int -sc_report_handler::get_count(sc_severity) +sc_report_handler::get_count(sc_severity severity) { - warn("%s not implemented.\n", __PRETTY_FUNCTION__); - return 0; + return catForSeverity[severity].count; } int sc_report_handler::get_count(const char *msg_type) { - warn("%s not implemented.\n", __PRETTY_FUNCTION__); - return 0; + return catForMsgType[msg_type].count; } int -sc_report_handler::get_count(const char *msg_type, sc_severity) +sc_report_handler::get_count(const char *msg_type, sc_severity severity) { - warn("%s not implemented.\n", __PRETTY_FUNCTION__); - return 0; + return catForSeverityAndMsgType[ + std::make_pair(std::string(msg_type), severity)].count; } int -sc_report_handler::set_verbosity_level(int) +sc_report_handler::set_verbosity_level(int vl) { - warn("%s not implemented.\n", __PRETTY_FUNCTION__); - return 0; + int previous = verbosityLevel; + verbosityLevel = vl; + return previous; } int sc_report_handler::get_verbosity_level() { - warn("%s not implemented.\n", __PRETTY_FUNCTION__); - return 0; + return verbosityLevel; } sc_actions -sc_report_handler::suppress(sc_actions) +sc_report_handler::suppress(sc_actions actions) { - warn("%s not implemented.\n", __PRETTY_FUNCTION__); - return SC_UNSPECIFIED; + sc_actions previous = suppressedActions; + suppressedActions = actions; + return previous; } sc_actions sc_report_handler::suppress() { - warn("%s not implemented.\n", __PRETTY_FUNCTION__); - return SC_UNSPECIFIED; + return suppress(SC_UNSPECIFIED); } sc_actions -sc_report_handler::force(sc_actions) +sc_report_handler::force(sc_actions actions) { - warn("%s not implemented.\n", __PRETTY_FUNCTION__); - return SC_UNSPECIFIED; + sc_actions previous = forcedActions; + forcedActions = actions; + return previous; } sc_actions sc_report_handler::force() { - warn("%s not implemented.\n", __PRETTY_FUNCTION__); - return SC_UNSPECIFIED; + return force(SC_UNSPECIFIED); } sc_actions -sc_report_handler::set_catch_actions(sc_actions) +sc_report_handler::set_catch_actions(sc_actions actions) { - warn("%s not implemented.\n", __PRETTY_FUNCTION__); - return SC_UNSPECIFIED; + sc_actions previous = catchActions; + catchActions = actions; + return previous; } sc_actions sc_report_handler::get_catch_actions() { - warn("%s not implemented.\n", __PRETTY_FUNCTION__); - return SC_UNSPECIFIED; + return catchActions; } void -sc_report_handler::set_handler(sc_report_handler_proc) +sc_report_handler::set_handler(sc_report_handler_proc proc) { - warn("%s not implemented.\n", __PRETTY_FUNCTION__); + reportHandlerProc = proc; } void -sc_report_handler::default_handler(const sc_report &, const sc_actions &) -{ - warn("%s not implemented.\n", __PRETTY_FUNCTION__); +sc_report_handler::default_handler( + const sc_report &report, const sc_actions &actions) +{ + if (actions & SC_DISPLAY) + cprintf("\n%s\n", sc_report_compose_message(report)); + + if ((actions & SC_LOG) && logFile) { + ccprintf(*logFile, "%s: %s\n", report.get_time().to_string(), + sc_report_compose_message(report)); + } + if (actions & SC_STOP) { + sc_stop_here(report.get_msg_type(), report.get_severity()); + sc_stop(); + } + if (actions & SC_INTERRUPT) + sc_interrupt_here(report.get_msg_type(), report.get_severity()); + if (actions & SC_ABORT) + sc_abort(); + if (actions & SC_THROW) { + ::sc_gem5::Process *current = ::sc_gem5::scheduler.current(); + if (current) + current->isUnwinding(false); + throw report; + } } sc_actions sc_report_handler::get_new_action_id() { - warn("%s not implemented.\n", __PRETTY_FUNCTION__); - return SC_UNSPECIFIED; + maxAction = maxAction << 1; + return maxAction; } sc_report * sc_report_handler::get_cached_report() { - warn("%s not implemented.\n", __PRETTY_FUNCTION__); - return nullptr; + ::sc_gem5::Process *current = ::sc_gem5::scheduler.current(); + if (current) + return current->lastReport(); + return globalReportCache.get(); } void sc_report_handler::clear_cached_report() { - warn("%s not implemented.\n", __PRETTY_FUNCTION__); + ::sc_gem5::Process *current = ::sc_gem5::scheduler.current(); + if (current) { + current->lastReport(nullptr); + } else { + globalReportCache = nullptr; + } } bool -sc_report_handler::set_log_file_name(const char *) -{ - warn("%s not implemented.\n", __PRETTY_FUNCTION__); - return false; +sc_report_handler::set_log_file_name(const char *new_name) +{ + if (!new_name) { + logFile = nullptr; + logFileName = nullptr; + return false; + } else { + if (logFileName) + return false; + logFileName = std::unique_ptr(new std::string(new_name)); + logFile = std::unique_ptr(new std::ofstream(new_name)); + return true; + } } const char * sc_report_handler::get_log_file_name() { - warn("%s not implemented.\n", __PRETTY_FUNCTION__); - return nullptr; + if (!logFileName) + return nullptr; + else + return logFileName->c_str(); } void sc_interrupt_here(const char *msg_type, sc_severity) { - warn("%s not implemented.\n", __PRETTY_FUNCTION__); + // Purposefully empty, for setting breakpoints supposedly. } void sc_stop_here(const char *msg_type, sc_severity) { - warn("%s not implemented.\n", __PRETTY_FUNCTION__); + // Purposefully empty, for setting breakpoints supposedly. } const std::string -sc_report_compose_message(const sc_report &) +sc_report_compose_message(const sc_report &report) { - warn("%s not implemented.\n", __PRETTY_FUNCTION__); - return ""; + std::ostringstream str; + + const char *sevName = severityNames[report.get_severity()]; + int id = report.get_id(); + + str << sevName << ": "; + if (id >= 0) { + ccprintf(str, "(%c%d) ", sevName[0], id); + } + str << report.get_msg_type(); + + const char *msg = report.get_msg(); + if (msg[0]) + str << ": " << msg; + + if (report.get_severity() > SC_INFO) { + ccprintf(str, "\nIn file: %s:%d", report.get_file_name(), + report.get_line_number()); + + ::sc_gem5::Process *current = ::sc_gem5::scheduler.current(); + const char *name = report.get_process_name(); + if (current && sc_is_running() && name) { + ccprintf(str, "\nIn process: %s @ %s", name, + report.get_time().to_string()); + } + } + + return str.str(); } bool sc_report_close_default_log() { - warn("%s not implemented.\n", __PRETTY_FUNCTION__); - return false; + if (logFile) { + logFile = nullptr; + logFileName = nullptr; + return false; + } + return true; } } // namespace sc_core -- cgit v1.2.3