From a6c0e4623c6bb1077ca43c66663e039efb221bda Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Thu, 19 Jul 2018 15:51:24 -0700 Subject: systemc: Implement the various sc_module stage callbacks. This change also gets rid of the SystemC namespace which was deprecated in favor of sc_gem5. A few utility functions which check whether certain callbacks have finished were also implemented. status tracking moved from a global variable in sc_main.cc to a member of the kernel simobject. Change-Id: I50967fae9c576fbe45b1faff587aaa824857a289 Reviewed-on: https://gem5-review.googlesource.com/12033 Reviewed-by: Gabe Black Maintainer: Gabe Black --- src/systemc/core/SystemC.py | 2 +- src/systemc/core/kernel.cc | 80 ++++++++++++++++++++++++++++++++++++++++--- src/systemc/core/kernel.hh | 24 +++++++++++-- src/systemc/core/module.cc | 8 +++++ src/systemc/core/module.hh | 5 +++ src/systemc/core/sc_main.cc | 19 ++++------ src/systemc/core/sc_module.cc | 9 +++-- src/systemc/core/scheduler.cc | 8 ++++- 8 files changed, 128 insertions(+), 27 deletions(-) (limited to 'src/systemc/core') diff --git a/src/systemc/core/SystemC.py b/src/systemc/core/SystemC.py index 41fecb2c2..dff72e2ce 100644 --- a/src/systemc/core/SystemC.py +++ b/src/systemc/core/SystemC.py @@ -33,7 +33,7 @@ from m5.SimObject import SimObject # It also acts as a collecting point for systemc related control functionality. class SystemC_Kernel(SimObject): type = 'SystemC_Kernel' - cxx_class = 'SystemC::Kernel' + cxx_class = 'sc_gem5::Kernel' cxx_header = 'systemc/core/kernel.hh' def sc_main(self, *args): diff --git a/src/systemc/core/kernel.cc b/src/systemc/core/kernel.cc index 3b75c2fd2..dac2229e2 100644 --- a/src/systemc/core/kernel.cc +++ b/src/systemc/core/kernel.cc @@ -28,17 +28,56 @@ */ #include "systemc/core/kernel.hh" + +#include "base/logging.hh" +#include "systemc/core/module.hh" #include "systemc/core/scheduler.hh" -namespace SystemC +namespace sc_gem5 { Kernel::Kernel(Params *params) : - SimObject(params), t0Event(this, false, EventBase::Default_Pri - 1) {} + SimObject(params), _stopAfterCallbacks(false), + _startComplete(false), _endComplete(false), + _status(sc_core::SC_ELABORATION), + t0Event(this, false, EventBase::Default_Pri - 1) {} + +void +Kernel::init() +{ + kernel->status(::sc_core::SC_BEFORE_END_OF_ELABORATION); + for (auto m: sc_gem5::allModules) + m->sc_mod()->before_end_of_elaboration(); + + if (_stopAfterCallbacks) + stopWork(); +} + +void +Kernel::regStats() +{ + kernel->status(::sc_core::SC_END_OF_ELABORATION); + for (auto m: sc_gem5::allModules) + m->sc_mod()->end_of_elaboration(); + + if (_stopAfterCallbacks) + stopWork(); +} void Kernel::startup() { + kernel->status(::sc_core::SC_START_OF_SIMULATION); + for (auto m: sc_gem5::allModules) + m->sc_mod()->start_of_simulation(); + + _startComplete = true; + + if (_stopAfterCallbacks) + stopWork(); + + kernel->status(::sc_core::SC_RUNNING); + schedule(t0Event, curTick()); // Install ourselves as the scheduler's event manager. ::sc_gem5::scheduler.setEventQueue(eventQueue()); @@ -46,6 +85,30 @@ Kernel::startup() ::sc_gem5::scheduler.update(); } +void +Kernel::stop() +{ + if (status() < ::sc_core::SC_RUNNING) + _stopAfterCallbacks = true; + else + stopWork(); +} + +void +Kernel::stopWork() +{ + kernel->status(::sc_core::SC_END_OF_SIMULATION); + for (auto m: sc_gem5::allModules) + m->sc_mod()->end_of_simulation(); + + _endComplete = true; + + kernel->status(::sc_core::SC_STOPPED); + + if (_stopAfterCallbacks) + fatal("Simulation called sc_stop during elaboration.\n"); +} + void Kernel::t0Handler() { @@ -57,12 +120,19 @@ Kernel::t0Handler() // in the spec. The delta phase will happen at normal priority, and then // the event which runs the processes which is at a lower priority. ::sc_gem5::scheduler.prepareForInit(); + + status(::sc_core::SC_RUNNING); } -} // namespace SystemC +Kernel *kernel; + +} // namespace sc_gem5 -SystemC::Kernel * +sc_gem5::Kernel * SystemC_KernelParams::create() { - return new SystemC::Kernel(this); + panic_if(sc_gem5::kernel, + "Only one systemc kernel object may be defined.\n"); + sc_gem5::kernel = new sc_gem5::Kernel(this); + return sc_gem5::kernel; } diff --git a/src/systemc/core/kernel.hh b/src/systemc/core/kernel.hh index 8cbf4fb3b..15641c510 100644 --- a/src/systemc/core/kernel.hh +++ b/src/systemc/core/kernel.hh @@ -32,8 +32,9 @@ #include "params/SystemC_Kernel.hh" #include "sim/sim_object.hh" +#include "systemc/ext/core/sc_main.hh" -namespace SystemC +namespace sc_gem5 { /* @@ -49,14 +50,33 @@ class Kernel : public SimObject typedef SystemC_KernelParams Params; Kernel(Params *params); + void init() override; + void regStats() override; void startup() override; void t0Handler(); + sc_core::sc_status status() { return _status; } + void status(sc_core::sc_status s) { _status = s; } + + void stop(); + + bool startOfSimulationComplete() { return _startComplete; } + bool endOfSimulationComplete() { return _endComplete; } + private: + bool _stopAfterCallbacks; + void stopWork(); + + bool _startComplete; + bool _endComplete; + sc_core::sc_status _status; + EventWrapper t0Event; }; -} // namespace SystemC +extern Kernel *kernel; + +} // namespace sc_gem5 #endif // __SYSTEMC_KERNEL_H__ diff --git a/src/systemc/core/module.cc b/src/systemc/core/module.cc index 3b7e922e3..e41e93285 100644 --- a/src/systemc/core/module.cc +++ b/src/systemc/core/module.cc @@ -51,6 +51,8 @@ Module::Module(const char *name) : _name(name), _sc_mod(nullptr), _obj(nullptr) _new_module = this; } +Module::~Module() { allModules.erase(this); } + void Module::finish(Object *this_obj) { @@ -58,6 +60,10 @@ Module::finish(Object *this_obj) _obj = this_obj; _modules.push_back(this); _new_module = nullptr; + // This is called from the constructor of this_obj, so it can't use + // dynamic cast. + sc_mod(static_cast<::sc_core::sc_module *>(this_obj->sc_obj())); + allModules.insert(this); } void @@ -84,4 +90,6 @@ newModule() return _new_module; } +std::set allModules; + } // namespace sc_gem5 diff --git a/src/systemc/core/module.hh b/src/systemc/core/module.hh index 3734e633f..696d8c570 100644 --- a/src/systemc/core/module.hh +++ b/src/systemc/core/module.hh @@ -31,6 +31,7 @@ #define __SYSTEMC_CORE_MODULE_HH__ #include +#include #include "systemc/core/object.hh" #include "systemc/ext/core/sc_module.hh" @@ -48,6 +49,8 @@ class Module public: Module(const char *name); + ~Module(); + void finish(Object *this_obj); const char *name() const { return _name; } @@ -79,6 +82,8 @@ class Module Module *currentModule(); Module *newModule(); +extern std::set allModules; + } // namespace sc_gem5 #endif //__SYSTEMC_CORE_MODULE_HH__ diff --git a/src/systemc/core/sc_main.cc b/src/systemc/core/sc_main.cc index 103b3032f..8e92c9403 100644 --- a/src/systemc/core/sc_main.cc +++ b/src/systemc/core/sc_main.cc @@ -36,6 +36,7 @@ #include "sim/core.hh" #include "sim/eventq.hh" #include "sim/init.hh" +#include "systemc/core/kernel.hh" #include "systemc/core/scheduler.hh" #include "systemc/ext/core/sc_main.hh" #include "systemc/ext/utils/sc_report_handler.hh" @@ -121,7 +122,6 @@ systemc_pybind(pybind11::module &m_internal) EmbeddedPyBind embed_("systemc", &systemc_pybind); sc_stop_mode _stop_mode = SC_STOP_FINISH_DELTA; -sc_status _status = SC_ELABORATION; } // anonymous namespace @@ -147,22 +147,15 @@ sc_start() void sc_pause() { - if (_status == SC_RUNNING) + if (::sc_gem5::kernel->status() == SC_RUNNING) ::sc_gem5::scheduler.schedulePause(); } void sc_start(const sc_time &time, sc_starvation_policy p) { - _status = SC_RUNNING; - Tick now = ::sc_gem5::scheduler.getCurTick(); ::sc_gem5::scheduler.start(now + time.value(), p == SC_RUN_TO_TIME); - - if (::sc_gem5::scheduler.paused()) - _status = SC_PAUSED; - else if (::sc_gem5::scheduler.stopped()) - _status = SC_STOPPED; } void @@ -185,14 +178,14 @@ sc_get_stop_mode() void sc_stop() { - if (_status == SC_STOPPED) + if (::sc_gem5::kernel->status() == SC_STOPPED) return; if (sc_is_running()) { bool finish_delta = (_stop_mode == SC_STOP_FINISH_DELTA); ::sc_gem5::scheduler.scheduleStop(finish_delta); } else { - //XXX Should stop if in one of the various elaboration callbacks. + ::sc_gem5::kernel->stop(); } } @@ -215,7 +208,7 @@ sc_delta_count() bool sc_is_running() { - return _status & (SC_RUNNING | SC_PAUSED); + return sc_get_status() & (SC_RUNNING | SC_PAUSED); } bool @@ -246,7 +239,7 @@ sc_time_to_pending_activity() sc_status sc_get_status() { - return _status; + return ::sc_gem5::kernel ? ::sc_gem5::kernel->status() : SC_ELABORATION; } } // namespace sc_core diff --git a/src/systemc/core/sc_module.cc b/src/systemc/core/sc_module.cc index 20cc4d288..499a741ce 100644 --- a/src/systemc/core/sc_module.cc +++ b/src/systemc/core/sc_module.cc @@ -31,6 +31,7 @@ #include #include "base/logging.hh" +#include "systemc/core/kernel.hh" #include "systemc/core/module.hh" #include "systemc/core/process_types.hh" #include "systemc/ext/core/sc_module.hh" @@ -72,7 +73,7 @@ sc_bind_proxy::sc_bind_proxy(const sc_port_base &_port) : const sc_bind_proxy SC_BIND_PROXY_NUL(*(const sc_port_base *)nullptr); -sc_module::~sc_module() {} +sc_module::~sc_module() { delete _gem5_module; } const sc_bind_proxy SC_BIND_PROXY_NIL(*(const sc_port_base *)nullptr); @@ -652,15 +653,13 @@ sc_hierarchical_name_exists(const char *name) bool sc_start_of_simulation_invoked() { - warn("%s not implemented.\n", __PRETTY_FUNCTION__); - return false; + return ::sc_gem5::kernel->startOfSimulationComplete(); } bool sc_end_of_simulation_invoked() { - warn("%s not implemented.\n", __PRETTY_FUNCTION__); - return false; + return ::sc_gem5::kernel->endOfSimulationComplete(); } sc_module * diff --git a/src/systemc/core/scheduler.cc b/src/systemc/core/scheduler.cc index eab6f482c..6bb67d136 100644 --- a/src/systemc/core/scheduler.cc +++ b/src/systemc/core/scheduler.cc @@ -32,6 +32,8 @@ #include "base/fiber.hh" #include "base/logging.hh" #include "sim/eventq.hh" +#include "systemc/core/kernel.hh" +#include "systemc/ext/core/sc_main.hh" namespace sc_gem5 { @@ -174,6 +176,7 @@ void Scheduler::pause() { _paused = true; + kernel->status(::sc_core::SC_PAUSED); scMain->run(); } @@ -181,6 +184,7 @@ void Scheduler::stop() { _stopped = true; + kernel->stop(); scMain->run(); } @@ -197,8 +201,10 @@ Scheduler::start(Tick max_tick, bool run_to_time) maxTick = max_tick; - if (initReady) + if (initReady) { + kernel->status(::sc_core::SC_RUNNING); eq->schedule(&maxTickEvent, maxTick); + } // Return to gem5 to let it run events, etc. Fiber::primaryFiber()->run(); -- cgit v1.2.3