systemc: Ensure sc_stop during callbacks actually stops.
authorGabe Black <gabeblack@google.com>
Tue, 4 Sep 2018 22:09:48 +0000 (15:09 -0700)
committerGabe Black <gabeblack@google.com>
Wed, 3 Oct 2018 00:53:04 +0000 (00:53 +0000)
Make sure calling sc_stop during the appropriate callbacks will
actually skip future action by skipping later callbacks, by flushing
the scheduler before running init (so it doesn't really do anything
but record that it's in running mode now), and schedule the stop event.

Change-Id: I5edfbceda457df88d15bfcac4d97e8578205ec5b
Reviewed-on: https://gem5-review.googlesource.com/c/12468
Reviewed-by: Gabe Black <gabeblack@google.com>
Maintainer: Gabe Black <gabeblack@google.com>

src/systemc/core/kernel.cc

index fd51b4c525d16afc2efd7bc3c2814abc6348985d..cc65fcc20e899c9b967accba2a7632e6aeb2eef7 100644 (file)
@@ -86,15 +86,12 @@ Kernel::init()
     callbackModule(nullptr);
     for (auto c: sc_gem5::allChannels)
         c->sc_chan()->before_end_of_elaboration();
-
-    if (stopAfterCallbacks)
-        stopWork();
 }
 
 void
 Kernel::regStats()
 {
-    if (scMainDone)
+    if (scMainDone || stopAfterCallbacks)
         return;
 
     for (auto m: sc_gem5::allModules)
@@ -113,9 +110,6 @@ Kernel::regStats()
     callbackModule(nullptr);
     for (auto c: sc_gem5::allChannels)
         c->sc_chan()->end_of_elaboration();
-
-    if (stopAfterCallbacks)
-        stopWork();
 }
 
 void
@@ -124,6 +118,11 @@ Kernel::startup()
     if (scMainDone)
         return;
 
+    schedule(t0Event, curTick());
+
+    if (stopAfterCallbacks)
+        return;
+
     status(::sc_core::SC_START_OF_SIMULATION);
     for (auto m: sc_gem5::allModules) {
         m->sc_mod()->start_of_simulation();
@@ -142,7 +141,6 @@ Kernel::startup()
 
     kernel->status(::sc_core::SC_RUNNING);
 
-    schedule(t0Event, curTick());
     // Run update once before the event queue starts.
     ::sc_gem5::scheduler.update();
 }
@@ -178,9 +176,14 @@ Kernel::stopWork()
 void
 Kernel::t0Handler()
 {
-    ::sc_gem5::scheduler.initPhase();
-
-    status(::sc_core::SC_RUNNING);
+    if (stopAfterCallbacks) {
+        scheduler.clear();
+        ::sc_gem5::scheduler.initPhase();
+        scheduler.scheduleStop(false);
+    } else {
+        ::sc_gem5::scheduler.initPhase();
+        status(::sc_core::SC_RUNNING);
+    }
 }
 
 Kernel *kernel;