summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGabe Black <gabeblack@google.com>2018-08-22 17:52:19 -0700
committerGabe Black <gabeblack@google.com>2018-09-25 23:56:18 +0000
commita0f2391fc143cbe505c2cedffb477713bbc85cbe (patch)
treebcd4ae171b6e7012338685363a55ac9dc469456b
parent382066d462d11728a0c9598d1698765da7a05293 (diff)
downloadgem5-a0f2391fc143cbe505c2cedffb477713bbc85cbe.tar.xz
systemc: If sc_main returns, don't do any more systemc stuff.
When sc_main returns, clear out any pending work in the scheduler and also block the systemc kernel from doing actions which correspond with the start of simulation. It's most likely that work like oustanding timeouts might survive past the end of sc_main, especially if it never officially called sc_stop. It's also possible for sc_main to return and never actually call sc_start. In that case, the kernel should not call callbacks of the various objects (which may no longer even exist), or go through the initialization phase. If sc_main is never called at all, then the kernel's actions aren't gated. Change-Id: I49bf094be3283a92d846d2f3da224950bd893a5c Reviewed-on: https://gem5-review.googlesource.com/12249 Reviewed-by: Gabe Black <gabeblack@google.com> Maintainer: Gabe Black <gabeblack@google.com>
-rw-r--r--src/systemc/core/kernel.cc13
-rw-r--r--src/systemc/core/kernel.hh3
-rw-r--r--src/systemc/core/sc_main.cc4
3 files changed, 20 insertions, 0 deletions
diff --git a/src/systemc/core/kernel.cc b/src/systemc/core/kernel.cc
index 2594bcc64..545901a84 100644
--- a/src/systemc/core/kernel.cc
+++ b/src/systemc/core/kernel.cc
@@ -40,6 +40,7 @@ namespace sc_gem5
namespace
{
+bool scMainDone = false;
bool stopAfterCallbacks = false;
bool startComplete = false;
bool endComplete = false;
@@ -51,6 +52,9 @@ sc_core::sc_status _status = sc_core::SC_ELABORATION;
bool Kernel::startOfSimulationComplete() { return startComplete; }
bool Kernel::endOfSimulationComplete() { return endComplete; }
+bool Kernel::scMainFinished() { return scMainDone; }
+void Kernel::scMainFinished(bool finished) { scMainDone = finished; }
+
sc_core::sc_status Kernel::status() { return _status; }
void Kernel::status(sc_core::sc_status s) { _status = s; }
@@ -64,6 +68,9 @@ Kernel::Kernel(Params *params) :
void
Kernel::init()
{
+ if (scMainDone)
+ return;
+
status(::sc_core::SC_BEFORE_END_OF_ELABORATION);
for (auto m: sc_gem5::allModules) {
callbackModule(m);
@@ -84,6 +91,9 @@ Kernel::init()
void
Kernel::regStats()
{
+ if (scMainDone)
+ return;
+
for (auto m: sc_gem5::allModules)
for (auto p: m->ports)
p->_gem5Finalize();
@@ -106,6 +116,9 @@ Kernel::regStats()
void
Kernel::startup()
{
+ if (scMainDone)
+ return;
+
status(::sc_core::SC_START_OF_SIMULATION);
for (auto m: sc_gem5::allModules) {
m->sc_mod()->start_of_simulation();
diff --git a/src/systemc/core/kernel.hh b/src/systemc/core/kernel.hh
index b9a37d00a..e0808fe47 100644
--- a/src/systemc/core/kernel.hh
+++ b/src/systemc/core/kernel.hh
@@ -64,6 +64,9 @@ class Kernel : public SimObject
static bool startOfSimulationComplete();
static bool endOfSimulationComplete();
+ static bool scMainFinished();
+ static void scMainFinished(bool);
+
private:
static void stopWork();
diff --git a/src/systemc/core/sc_main.cc b/src/systemc/core/sc_main.cc
index 7e107af86..bacde2e0f 100644
--- a/src/systemc/core/sc_main.cc
+++ b/src/systemc/core/sc_main.cc
@@ -62,6 +62,10 @@ class ScMainFiber : public Fiber
{
if (::sc_main) {
::sc_main(_argc, _argv);
+ // Make sure no systemc events/notifications are scheduled
+ // after sc_main returns.
+ ::sc_gem5::Kernel::scMainFinished(true);
+ ::sc_gem5::scheduler.clear();
} else {
// If python tries to call sc_main but no sc_main was defined...
fatal("sc_main called but not defined.\n");