# 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):
*/
#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());
::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()
{
// 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;
}
#include "params/SystemC_Kernel.hh"
#include "sim/sim_object.hh"
+#include "systemc/ext/core/sc_main.hh"
-namespace SystemC
+namespace sc_gem5
{
/*
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__
_new_module = this;
}
+Module::~Module() { allModules.erase(this); }
+
void
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
return _new_module;
}
+std::set<Module *> allModules;
+
} // namespace sc_gem5
#define __SYSTEMC_CORE_MODULE_HH__
#include <cassert>
+#include <set>
#include "systemc/core/object.hh"
#include "systemc/ext/core/sc_module.hh"
public:
Module(const char *name);
+ ~Module();
+
void finish(Object *this_obj);
const char *name() const { return _name; }
Module *currentModule();
Module *newModule();
+extern std::set<Module *> allModules;
+
} // namespace sc_gem5
#endif //__SYSTEMC_CORE_MODULE_HH__
#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"
EmbeddedPyBind embed_("systemc", &systemc_pybind);
sc_stop_mode _stop_mode = SC_STOP_FINISH_DELTA;
-sc_status _status = SC_ELABORATION;
} // anonymous namespace
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
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();
}
}
bool
sc_is_running()
{
- return _status & (SC_RUNNING | SC_PAUSED);
+ return sc_get_status() & (SC_RUNNING | SC_PAUSED);
}
bool
sc_status
sc_get_status()
{
- return _status;
+ return ::sc_gem5::kernel ? ::sc_gem5::kernel->status() : SC_ELABORATION;
}
} // namespace sc_core
#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"
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);
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 *
#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
{
Scheduler::pause()
{
_paused = true;
+ kernel->status(::sc_core::SC_PAUSED);
scMain->run();
}
Scheduler::stop()
{
_stopped = true;
+ kernel->stop();
scMain->run();
}
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();
namespace sc_gem5
{
+class Kernel;
class Module;
class Process;
struct ProcessFuncWrapper;
class sc_module : public sc_object
{
public:
+ friend class ::sc_gem5::Kernel;
+
virtual ~sc_module();
virtual const char *kind() const { return "sc_module"; }