systemc: Raise an error when SC_METHOD, etc. is used after starting.
authorGabe Black <gabeblack@google.com>
Thu, 30 Aug 2018 08:39:21 +0000 (01:39 -0700)
committerGabe Black <gabeblack@google.com>
Wed, 3 Oct 2018 00:21:28 +0000 (00:21 +0000)
Those mechanisms for creating processes are only allowed before the
end of elaboration, or in other words before sc_start is called.
Technically the check in Accellera's implementation won't trigger if
the simulation is stopped, and we immitate that behavior.

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

src/systemc/channel/sc_clock.cc
src/systemc/core/sc_module.cc
src/systemc/ext/core/sc_module.hh

index 6736e57cf2f7b0e02835896b641b4b1d43bf7a51..7cdd1c1d1d25645982bd3f56541dd829e6fc10d3 100644 (file)
@@ -32,6 +32,7 @@
 #include "sim/core.hh"
 #include "sim/eventq.hh"
 #include "systemc/core/kernel.hh"
+#include "systemc/core/process_types.hh"
 #include "systemc/core/sched_event.hh"
 #include "systemc/core/scheduler.hh"
 #include "systemc/ext/channel/sc_clock.hh"
@@ -60,7 +61,8 @@ class ClockTick : public ScEvent
     {
         _name += (to ? ".up_tick" : ".down_tick");
         _procName = _name + ".p";
-        p = newMethodProcess(_procName.c_str(), &funcWrapper);
+        p = new Method(_procName.c_str(), &funcWrapper);
+        scheduler.reg(p);
         scheduler.dontInitialize(p);
     }
 
index bbb9993be636c0e886bf31c2ec7ed47f77e1a509..44e442d005e565eccdaff8c428aae97739862f1a 100644 (file)
@@ -28,6 +28,7 @@
  */
 
 #include <memory>
+#include <string>
 #include <vector>
 
 #include "base/logging.hh"
@@ -36,6 +37,7 @@
 #include "systemc/core/process_types.hh"
 #include "systemc/ext/core/sc_module.hh"
 #include "systemc/ext/core/sc_module_name.hh"
+#include "systemc/ext/utils/sc_report_handler.hh"
 
 namespace sc_gem5
 {
@@ -43,7 +45,14 @@ namespace sc_gem5
 Process *
 newMethodProcess(const char *name, ProcessFuncWrapper *func)
 {
-    Process *p = new Method(name, func);
+    Method *p = new Method(name, func);
+    if (::sc_core::sc_is_running()) {
+        std::string name = p->name();
+        delete p;
+        SC_REPORT_ERROR("(E541) call to SC_METHOD in sc_module while "
+                "simulation running", name.c_str());
+        return nullptr;
+    }
     scheduler.reg(p);
     return p;
 }
@@ -51,7 +60,14 @@ newMethodProcess(const char *name, ProcessFuncWrapper *func)
 Process *
 newThreadProcess(const char *name, ProcessFuncWrapper *func)
 {
-    Process *p = new Thread(name, func);
+    Thread *p = new Thread(name, func);
+    if (::sc_core::sc_is_running()) {
+        std::string name = p->name();
+        delete p;
+        SC_REPORT_ERROR("(E542) call to SC_THREAD in sc_module while "
+                "simulation running", name.c_str());
+        return nullptr;
+    }
     scheduler.reg(p);
     return p;
 }
@@ -59,7 +75,14 @@ newThreadProcess(const char *name, ProcessFuncWrapper *func)
 Process *
 newCThreadProcess(const char *name, ProcessFuncWrapper *func)
 {
-    Process *p = new CThread(name, func);
+    CThread *p = new CThread(name, func);
+    if (::sc_core::sc_is_running()) {
+        std::string name = p->name();
+        delete p;
+        SC_REPORT_ERROR("(E543) call to SC_CTHREAD in sc_module while "
+                "simulation running", name.c_str());
+        return nullptr;
+    }
     scheduler.reg(p);
     p->dontInitialize();
     return p;
index 539d275ece51c4bf861c1294b1b1d8d9f1709779..0e5e679c9094ee20fccb6ba359675d68c70af464 100644 (file)
@@ -289,7 +289,8 @@ bool timed_out();
                 #name, new ::sc_gem5::ProcessMemberFuncWrapper< \
                     SC_CURRENT_USER_MODULE>(this, \
                         &SC_CURRENT_USER_MODULE::name)); \
-        this->sensitive << p; \
+        if (p) \
+            this->sensitive << p; \
     }
 #define SC_THREAD(name) \
     { \
@@ -298,7 +299,8 @@ bool timed_out();
                 #name, new ::sc_gem5::ProcessMemberFuncWrapper< \
                     SC_CURRENT_USER_MODULE>(this, \
                         &SC_CURRENT_USER_MODULE::name)); \
-        this->sensitive << p; \
+        if (p) \
+            this->sensitive << p; \
     }
 #define SC_CTHREAD(name, clk) \
     { \
@@ -307,8 +309,10 @@ bool timed_out();
                 #name, new ::sc_gem5::ProcessMemberFuncWrapper< \
                     SC_CURRENT_USER_MODULE>(this, \
                         &SC_CURRENT_USER_MODULE::name)); \
-        this->sensitive << p; \
-        this->sensitive << clk; \
+        if (p) { \
+            this->sensitive << p; \
+            this->sensitive << clk; \
+        } \
     }
 
 // Nonstandard