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 <gabeblack@google.com> Maintainer: Gabe Black <gabeblack@google.com>
This commit is contained in:
@@ -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):
|
||||
|
||||
@@ -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;
|
||||
|
||||
SystemC::Kernel *
|
||||
} // namespace sc_gem5
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -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<Kernel, &Kernel::t0Handler> t0Event;
|
||||
};
|
||||
|
||||
} // namespace SystemC
|
||||
extern Kernel *kernel;
|
||||
|
||||
} // namespace sc_gem5
|
||||
|
||||
#endif // __SYSTEMC_KERNEL_H__
|
||||
|
||||
@@ -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<Module *> allModules;
|
||||
|
||||
} // namespace sc_gem5
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
#define __SYSTEMC_CORE_MODULE_HH__
|
||||
|
||||
#include <cassert>
|
||||
#include <set>
|
||||
|
||||
#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<Module *> allModules;
|
||||
|
||||
} // namespace sc_gem5
|
||||
|
||||
#endif //__SYSTEMC_CORE_MODULE_HH__
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
#include <vector>
|
||||
|
||||
#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 *
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -46,6 +46,7 @@ class sc_logic;
|
||||
namespace sc_gem5
|
||||
{
|
||||
|
||||
class Kernel;
|
||||
class Module;
|
||||
class Process;
|
||||
struct ProcessFuncWrapper;
|
||||
@@ -91,6 +92,8 @@ extern const sc_bind_proxy SC_BIND_PROXY_NIL;
|
||||
class sc_module : public sc_object
|
||||
{
|
||||
public:
|
||||
friend class ::sc_gem5::Kernel;
|
||||
|
||||
virtual ~sc_module();
|
||||
|
||||
virtual const char *kind() const { return "sc_module"; }
|
||||
|
||||
Reference in New Issue
Block a user