systemc: Centralize how object parents are chosen.
authorGabe Black <gabeblack@google.com>
Sat, 29 Sep 2018 00:12:46 +0000 (17:12 -0700)
committerGabe Black <gabeblack@google.com>
Tue, 16 Oct 2018 00:40:21 +0000 (00:40 +0000)
There's a lot of repeated code for this. Also, the sc_vector type
needs to be able to artificially inject a parent for the objects it
creates.

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

src/systemc/core/event.cc
src/systemc/core/module.cc
src/systemc/core/module.hh
src/systemc/core/object.cc
src/systemc/core/object.hh
src/systemc/core/sc_export.cc
src/systemc/core/sc_module.cc
src/systemc/core/sc_port.cc

index 097961e99f751ba2bd3cdbc675224468638bc722..36830b3081f1be6c0a55913560c64cf57971043a 100644 (file)
@@ -49,17 +49,10 @@ Event::Event(sc_core::sc_event *_sc_event, const char *_basename_cstr) :
     _sc_event(_sc_event), _basename(_basename_cstr ? _basename_cstr : ""),
     delayedNotify([this]() { this->notify(); }), _triggeredStamp(~0ULL)
 {
-    Module *p = currentModule();
-
     if (_basename == "" && ::sc_core::sc_is_running())
         _basename = ::sc_core::sc_gen_unique_name("event");
 
-    if (p)
-        parent = p->obj()->sc_obj();
-    else if (scheduler.current())
-        parent = scheduler.current();
-    else
-        parent = nullptr;
+    parent = pickParentObj();
 
     std::string original_name = _basename;
     _basename = pickUniqueName(parent, _basename);
index afc3bf24192e2889b0ec16a71920a29d963f60eb..f342b7f05c880166d3c6e6aaa7fab1ffabc030ee 100644 (file)
@@ -45,8 +45,6 @@ namespace
 std::list<Module *> _modules;
 Module *_new_module;
 
-Module *_callbackModule = nullptr;
-
 } // anonymous namespace
 
 Module::Module(const char *name) :
@@ -59,10 +57,15 @@ Module::Module(const char *name) :
 
 Module::~Module()
 {
-    if (_new_module == this) {
-        // Aborted module construction?
+    // Aborted module construction?
+    if (_new_module == this)
         _new_module = nullptr;
-    }
+
+    // Attempt to pop now in case we're at the top of the stack, so that
+    // a stale pointer to us isn't left floating around for somebody to trip
+    // on.
+    pop();
+
     allModules.remove(this);
 }
 
@@ -72,21 +75,29 @@ Module::finish(Object *this_obj)
     assert(!_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.emplace_back(this);
+    pushParentModule(this);
+    try {
+        _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.emplace_back(this);
+    } catch (...) {
+        popParentModule();
+        throw;
+    }
 }
 
 void
 Module::pop()
 {
-    panic_if(!_modules.size(), "Popping from empty module list.\n");
-    panic_if(_modules.back() != this,
-            "Popping module which isn't at the end of the module list.\n");
+    if (_modules.empty() || _modules.back() != this)
+        return;
+
     panic_if(_new_module, "Pop with unfinished module.\n");
+
     _modules.pop_back();
+    popParentModule();
 }
 
 void
@@ -111,11 +122,16 @@ Module::bindPorts(std::vector<const ::sc_core::sc_bind_proxy *> &proxies)
 void
 Module::beforeEndOfElaboration()
 {
-    callbackModule(this);
-    _sc_mod->before_end_of_elaboration();
-    for (auto e: exports)
-        e->before_end_of_elaboration();
-    callbackModule(nullptr);
+    pushParentModule(this);
+    try {
+        _sc_mod->before_end_of_elaboration();
+        for (auto e: exports)
+            e->before_end_of_elaboration();
+    } catch (...) {
+        popParentModule();
+        throw;
+    }
+    popParentModule();
 }
 
 void
@@ -127,31 +143,46 @@ Module::endOfElaboration()
                 "did you forget to add a sc_module_name parameter to "
                 "your module constructor?", msg.c_str());
     }
-    callbackModule(this);
-    _sc_mod->end_of_elaboration();
-    for (auto e: exports)
-        e->end_of_elaboration();
-    callbackModule(nullptr);
+    pushParentModule(this);
+    try {
+        _sc_mod->end_of_elaboration();
+        for (auto e: exports)
+            e->end_of_elaboration();
+    } catch (...) {
+        popParentModule();
+        throw;
+    }
+    popParentModule();
 }
 
 void
 Module::startOfSimulation()
 {
-    callbackModule(this);
-    _sc_mod->start_of_simulation();
-    for (auto e: exports)
-        e->start_of_simulation();
-    callbackModule(nullptr);
+    pushParentModule(this);
+    try {
+        _sc_mod->start_of_simulation();
+        for (auto e: exports)
+            e->start_of_simulation();
+    } catch (...) {
+        popParentModule();
+        throw;
+    }
+    popParentModule();
 }
 
 void
 Module::endOfSimulation()
 {
-    callbackModule(this);
-    _sc_mod->end_of_simulation();
-    for (auto e: exports)
-        e->end_of_simulation();
-    callbackModule(nullptr);
+    pushParentModule(this);
+    try {
+        _sc_mod->end_of_simulation();
+        for (auto e: exports)
+            e->end_of_simulation();
+    } catch(...) {
+        popParentModule();
+        throw;
+    }
+    popParentModule();
 }
 
 Module *
@@ -179,9 +210,6 @@ newModule()
     return _new_module;
 }
 
-void callbackModule(Module *m) { _callbackModule = m; }
-Module *callbackModule() { return _callbackModule; }
-
 std::list<Module *> allModules;
 
 } // namespace sc_gem5
index aa723368a7aece91aec691934fd203957b924028..695f30565d87f1e26ef6604b446ec86764479955 100644 (file)
@@ -80,10 +80,15 @@ class Module
     UniqueNameGen nameGen;
 
   public:
-
     Module(const char *name);
     ~Module();
 
+    static Module *
+    fromScModule(::sc_core::sc_module *mod)
+    {
+        return mod->_gem5_module;
+    }
+
     void finish(Object *this_obj);
 
     const char *name() const { return _name; }
@@ -130,8 +135,26 @@ Module *currentModule();
 Module *newModuleChecked();
 Module *newModule();
 
-void callbackModule(Module *m);
-Module *callbackModule();
+static inline Module *
+pickParentModule()
+{
+    ::sc_core::sc_object *obj = pickParentObj();
+    auto mod = dynamic_cast<::sc_core::sc_module *>(obj);
+    if (!mod)
+        return nullptr;
+    return Module::fromScModule(mod);
+}
+static inline void
+pushParentModule(Module *m)
+{
+    pushParentObj(m->obj()->sc_obj());
+}
+static inline void
+popParentModule()
+{
+    assert(pickParentModule());
+    popParentObj();
+}
 
 extern std::list<Module *> allModules;
 
index ee6a088931b780b5e87975b90cb1357154bf6139..91e3cb36a449a59030f5d3ea8d3f2b3b0ba8da10 100644 (file)
@@ -30,6 +30,7 @@
 #include "systemc/core/object.hh"
 
 #include <algorithm>
+#include <stack>
 
 #include "base/logging.hh"
 #include "systemc/core/event.hh"
@@ -91,9 +92,7 @@ Object::Object(sc_core::sc_object *_sc_obj, const char *obj_name) :
     if (_basename == "")
         _basename = ::sc_core::sc_gen_unique_name("object");
 
-    Module *p = currentModule();
-    if (!p)
-        p = callbackModule();
+    parent = pickParentObj();
 
     Module *n = newModule();
     if (n) {
@@ -101,15 +100,6 @@ Object::Object(sc_core::sc_object *_sc_obj, const char *obj_name) :
         n->finish(this);
     }
 
-    if (p) {
-        // We're "within" a parent module, ie we're being created while its
-        // constructor or end_of_elaboration callback is running.
-        parent = p->obj()->_sc_obj;
-    } else if (scheduler.current()) {
-        // Our parent is the currently running process.
-        parent = scheduler.current();
-    }
-
     std::string original_name = _basename;
     _basename = sc_gem5::pickUniqueName(parent, original_name);
 
@@ -308,4 +298,27 @@ findObject(const char *name, const Objects &objects)
     return it == allObjects.end() ? nullptr : *it;
 }
 
+namespace
+{
+
+std::stack<sc_core::sc_object *> objParentStack;
+
+} // anonymous namespace
+
+sc_core::sc_object *
+pickParentObj()
+{
+    if (!objParentStack.empty())
+        return objParentStack.top();
+
+    Process *p = scheduler.current();
+    if (p)
+        return p;
+
+    return nullptr;
+}
+
+void pushParentObj(sc_core::sc_object *obj) { objParentStack.push(obj); }
+void popParentObj() { objParentStack.pop(); }
+
 } // namespace sc_gem5
index adccde5b3d813b384e2a475b5a9a469e3c5fb167..cff8d84e29f280af432c2ea7346330de420b0ce5 100644 (file)
@@ -113,6 +113,10 @@ extern Objects allObjects;
 sc_core::sc_object *findObject(
         const char *name, const Objects &objects=topLevelObjects);
 
+sc_core::sc_object *pickParentObj();
+void pushParentObj(sc_core::sc_object *obj);
+void popParentObj();
+
 } // namespace sc_gem5
 
 #endif  //__SYSTEMC_CORE_OBJECT_HH__
index 0524ca8dcc1400c04955337e52af909450da79f5..9123a25535cc173738a7e20273753a30a3802bee 100644 (file)
@@ -65,7 +65,7 @@ sc_export_base::sc_export_base(const char *n) : sc_object(n)
                 name(), kind());
     }
 
-    ::sc_gem5::Module *m = ::sc_gem5::currentModule();
+    auto m = sc_gem5::pickParentModule();
     if (!m) {
         reportError("(E122) sc_export specified outside of module",
                 nullptr, name(), kind());
index d4ffda4e2917d85f5b61a0160d0c4fa7699fb0e9..46050934e05de49b6a7797ece74034bc5264bec7 100644 (file)
@@ -787,7 +787,7 @@ at_negedge(const sc_signal_in_if<sc_dt::sc_logic> &s)
 const char *
 sc_gen_unique_name(const char *seed)
 {
-    ::sc_gem5::Module *mod = ::sc_gem5::currentModule();
+    auto mod = sc_gem5::pickParentModule();
     return mod ? mod->uniqueName(seed) :
         ::sc_gem5::nameGen.gen(seed);
 }
index ddfe39ff5f567e3c8a405b99e2e99e86b3dfaccc..3a31e411d2f28fb6ec23ec125e2d4b734e79193a 100644 (file)
@@ -67,7 +67,7 @@ sc_port_base::sc_port_base(const char *n, int max_size, sc_port_policy p) :
                 name(), kind());
     }
 
-    ::sc_gem5::Module *m = ::sc_gem5::currentModule();
+    auto m = sc_gem5::pickParentModule();
     if (!m) {
         reportError("(E100) port specified outside of module",
                 nullptr, name(), kind());