Fix scope map for multiple construction (#2710)

This commit is contained in:
Todd Strader 2020-12-17 12:21:40 -05:00 committed by GitHub
parent c18cbca813
commit a88965a124
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 59 additions and 29 deletions

View File

@ -2787,6 +2787,10 @@ void VerilatedHierarchy::add(VerilatedScope* fromp, VerilatedScope* top) {
VerilatedImp::hierarchyAdd(fromp, top);
}
void VerilatedHierarchy::remove(VerilatedScope* fromp, VerilatedScope* top) {
VerilatedImp::hierarchyRemove(fromp, top);
}
//===========================================================================
// VerilatedOneThreaded:: Methods

View File

@ -363,6 +363,7 @@ public: // But internals only - called from VerilatedModule's
class VerilatedHierarchy final {
public:
static void add(VerilatedScope* fromp, VerilatedScope* top);
static void remove(VerilatedScope* fromp, VerilatedScope* top);
};
//===========================================================================

View File

@ -413,6 +413,16 @@ public: // But only for verilated*.cpp
const VerilatedLockGuard lock(s_s.v.m_hierMapMutex);
s_s.v.m_hierMap[fromp].push_back(top);
}
static void hierarchyRemove(const VerilatedScope* fromp,
const VerilatedScope* top) VL_MT_SAFE {
// Slow ok - called at destruction for VPI accessible elements
const VerilatedLockGuard lock(s_s.v.m_hierMapMutex);
VerilatedHierarchyMap& map = s_s.v.m_hierMap;
if (map.find(fromp) == map.end()) return;
VerilatedScopeVector& scopes = map[fromp];
const auto it = find(scopes.begin(), scopes.end(), top);
if (it != scopes.end()) scopes.erase(it);
}
static const VerilatedHierarchyMap* hierarchyMap() VL_MT_SAFE_POSTINIT {
// Thread save only assuming this is called only after model construction completed
return &s_s.v.m_hierMap;

View File

@ -116,6 +116,7 @@ class EmitCSyms final : EmitCBaseVisitor {
void checkSplit(bool usesVfinal);
void closeSplit();
void emitSymImpPreamble();
void emitScopeHier(bool destroy);
void emitSymImp();
void emitDpiHdr();
void emitDpiImp();
@ -467,7 +468,7 @@ void EmitCSyms::emitSymHdr() {
puts("\n// CREATORS\n");
puts(symClassName() + "(" + topClassName() + "* topp, const char* namep);\n");
puts(string("~") + symClassName() + "() = default;\n");
puts(string("~") + symClassName() + "();\n");
for (const auto& i : m_usesVfinal) {
puts("void " + symClassName() + "_" + cvtToStr(i.first) + "(");
@ -555,6 +556,40 @@ void EmitCSyms::emitSymImpPreamble() {
}
}
void EmitCSyms::emitScopeHier(bool destroy) {
if (v3Global.opt.vpi()) {
string verb = destroy ? "Tear down" : "Set up";
string method = destroy ? "remove" : "add";
puts("\n// " + verb + " scope hierarchy\n");
for (ScopeNames::const_iterator it = m_scopeNames.begin(); it != m_scopeNames.end();
++it) {
string name = it->second.m_prettyName;
if (it->first == "TOP") continue;
if ((name.find('.') == string::npos) && (it->second.m_type == "SCOPE_MODULE")) {
puts("__Vhier." + method + "(0, &" + protect("__Vscope_" + it->second.m_symName)
+ ");\n");
}
}
for (ScopeNameHierarchy::const_iterator it = m_vpiScopeHierarchy.begin();
it != m_vpiScopeHierarchy.end(); ++it) {
for (ScopeNameList::const_iterator lit = it->second.begin(); lit != it->second.end();
++lit) {
string fromname = scopeSymString(it->first);
string toname = scopeSymString(*lit);
const auto from = vlstd::as_const(m_scopeNames).find(fromname);
const auto to = vlstd::as_const(m_scopeNames).find(toname);
UASSERT(from != m_scopeNames.end(), fromname + " not in m_scopeNames");
UASSERT(to != m_scopeNames.end(), toname + " not in m_scopeNames");
puts("__Vhier." + method + "(");
puts("&" + protect("__Vscope_" + from->second.m_symName) + ", ");
puts("&" + protect("__Vscope_" + to->second.m_symName) + ");\n");
}
}
puts("\n");
}
}
void EmitCSyms::emitSymImp() {
UINFO(6, __FUNCTION__ << ": " << endl);
string filename = v3Global.opt.makeDir() + "/" + symClassName() + ".cpp";
@ -604,6 +639,10 @@ void EmitCSyms::emitSymImp() {
puts("\n");
puts("\n// FUNCTIONS\n");
puts(symClassName() + "::~" + symClassName() + "()\n");
puts("{\n");
emitScopeHier(true);
puts("}\n\n");
puts(symClassName() + "::" + symClassName() + "(" + topClassName()
+ "* topp, const char* namep)\n");
puts(" // Setup locals\n");
@ -685,34 +724,7 @@ void EmitCSyms::emitSymImp() {
}
}
if (v3Global.opt.vpi()) {
puts("\n// Setup scope hierarchy\n");
for (ScopeNames::const_iterator it = m_scopeNames.begin(); it != m_scopeNames.end();
++it) {
string name = it->second.m_prettyName;
if (it->first == "TOP") continue;
if ((name.find('.') == string::npos) && (it->second.m_type == "SCOPE_MODULE")) {
puts("__Vhier.add(0, &" + protect("__Vscope_" + it->second.m_symName) + ");\n");
}
}
for (ScopeNameHierarchy::const_iterator it = m_vpiScopeHierarchy.begin();
it != m_vpiScopeHierarchy.end(); ++it) {
for (ScopeNameList::const_iterator lit = it->second.begin(); lit != it->second.end();
++lit) {
string fromname = scopeSymString(it->first);
string toname = scopeSymString(*lit);
const auto from = vlstd::as_const(m_scopeNames).find(fromname);
const auto to = vlstd::as_const(m_scopeNames).find(toname);
UASSERT(from != m_scopeNames.end(), fromname + " not in m_scopeNames");
UASSERT(to != m_scopeNames.end(), toname + " not in m_scopeNames");
puts("__Vhier.add(");
puts("&" + protect("__Vscope_" + from->second.m_symName) + ", ");
puts("&" + protect("__Vscope_" + to->second.m_symName) + ");\n");
}
}
puts("\n");
}
emitScopeHier(false);
// Everything past here is in the __Vfinal loop, so start a new split file if needed
closeSplit();

View File

@ -165,6 +165,9 @@ int main(int argc, char** argv, char** env) {
Verilated::fatalOnVpiError(0);
VM_PREFIX* topp = new VM_PREFIX(""); // Note null name - we're flattening it out
// Test second construction
delete topp;
topp = new VM_PREFIX("");
#ifdef VERILATOR
#ifdef TEST_VERBOSE