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 <gabeblack@google.com> Maintainer: Gabe Black <gabeblack@google.com>
This commit is contained in:
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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__
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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());
|
||||
|
||||
Reference in New Issue
Block a user