From 163eb3c56b115e649c72fceff89c8370b6e7306f Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Fri, 28 Sep 2018 17:12:46 -0700 Subject: systemc: Centralize how object parents are chosen. 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 Maintainer: Gabe Black --- src/systemc/core/event.cc | 9 +--- src/systemc/core/module.cc | 100 +++++++++++++++++++++++++++--------------- src/systemc/core/module.hh | 29 ++++++++++-- src/systemc/core/object.cc | 37 +++++++++++----- src/systemc/core/object.hh | 4 ++ src/systemc/core/sc_export.cc | 2 +- src/systemc/core/sc_module.cc | 2 +- src/systemc/core/sc_port.cc | 2 +- 8 files changed, 123 insertions(+), 62 deletions(-) diff --git a/src/systemc/core/event.cc b/src/systemc/core/event.cc index 097961e99..36830b308 100644 --- a/src/systemc/core/event.cc +++ b/src/systemc/core/event.cc @@ -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); diff --git a/src/systemc/core/module.cc b/src/systemc/core/module.cc index afc3bf241..f342b7f05 100644 --- a/src/systemc/core/module.cc +++ b/src/systemc/core/module.cc @@ -45,8 +45,6 @@ namespace std::list _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 &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 allModules; } // namespace sc_gem5 diff --git a/src/systemc/core/module.hh b/src/systemc/core/module.hh index aa723368a..695f30565 100644 --- a/src/systemc/core/module.hh +++ b/src/systemc/core/module.hh @@ -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 allModules; diff --git a/src/systemc/core/object.cc b/src/systemc/core/object.cc index ee6a08893..91e3cb36a 100644 --- a/src/systemc/core/object.cc +++ b/src/systemc/core/object.cc @@ -30,6 +30,7 @@ #include "systemc/core/object.hh" #include +#include #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 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 diff --git a/src/systemc/core/object.hh b/src/systemc/core/object.hh index adccde5b3..cff8d84e2 100644 --- a/src/systemc/core/object.hh +++ b/src/systemc/core/object.hh @@ -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__ diff --git a/src/systemc/core/sc_export.cc b/src/systemc/core/sc_export.cc index 0524ca8dc..9123a2553 100644 --- a/src/systemc/core/sc_export.cc +++ b/src/systemc/core/sc_export.cc @@ -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()); diff --git a/src/systemc/core/sc_module.cc b/src/systemc/core/sc_module.cc index d4ffda4e2..46050934e 100644 --- a/src/systemc/core/sc_module.cc +++ b/src/systemc/core/sc_module.cc @@ -787,7 +787,7 @@ at_negedge(const sc_signal_in_if &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); } diff --git a/src/systemc/core/sc_port.cc b/src/systemc/core/sc_port.cc index ddfe39ff5..3a31e411d 100644 --- a/src/systemc/core/sc_port.cc +++ b/src/systemc/core/sc_port.cc @@ -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()); -- cgit v1.2.3