systemc: If sc_main returns, don't do any more systemc stuff.
authorGabe Black <gabeblack@google.com>
Thu, 23 Aug 2018 00:52:19 +0000 (17:52 -0700)
committerGabe Black <gabeblack@google.com>
Tue, 25 Sep 2018 23:56:18 +0000 (23:56 +0000)
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>

src/systemc/core/kernel.cc
src/systemc/core/kernel.hh
src/systemc/core/sc_main.cc

index 2594bcc64191ab55d5e3425a80432f705fcd5e17..545901a84a6e4bf96668197943afbc3dd7252f5b 100644 (file)
@@ -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();
index b9a37d00a31fca8a372b99b856e4c98bf3223b5b..e0808fe4786f6302cbaa8593fbe859992bdd602e 100644 (file)
@@ -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();
 
index 7e107af86e5d18abeb97e821bcdef7d3aa40c3f2..bacde2e0f77cec1affd5356172f0949e3fab7e0b 100644 (file)
@@ -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");