diff --git a/src/V3LinkDot.cpp b/src/V3LinkDot.cpp index c9fd39163..3b0d582cc 100644 --- a/src/V3LinkDot.cpp +++ b/src/V3LinkDot.cpp @@ -80,13 +80,23 @@ public: if (VL_UNLIKELY(level < 0)) level = v3Global.opt.debugSrcLevel(__FILE__); return level; } + void dump() { + if (debug()>=6) m_syms.dumpFilePrefixed("linkdot"); + } + void preErrorDump() { + static bool diddump = false; + if (!diddump && v3Global.opt.dumpTree()) { + diddump = true; + m_syms.dumpFilePrefixed("linkdot-preerr"); + } + } // CONSTRUCTORS - LinkDotState(AstNetlist* rootp, bool forPrearray, bool forScopeCreation) + LinkDotState(AstNetlist* rootp, VLinkDotStep step) : m_syms(rootp) { UINFO(4,__FUNCTION__<<": "<v3fatalSrc("Null symbol table inserting node"); VSymEnt* symp = new VSymEnt(&m_syms, nodep); UINFO(9," INSERTblk se"<<(void*)symp<<" above=se"<<(void*)abovep<<" node="<user1p()!=NULL; } - static VSymEnt* getNodeSym(AstNodeModule* nodep) { + static VSymEnt* getNodeSym(AstNode* nodep) { VSymEnt* symp = nodep->user1p()->castSymEnt(); - if (!symp) nodep->v3fatalSrc("Module never assigned a symbol entry?"); + if (!symp) nodep->v3fatalSrc("Module/etc never assigned a symbol entry?"); return symp; } VSymEnt* getScopeSym(AstScope* nodep) { @@ -184,16 +194,6 @@ public: } return iter->second; } - void dump() { - if (debug()>=6) m_syms.dumpFilePrefixed("linkdot"); - } - void preErrorDump() { - static bool diddump = false; - if (!diddump && v3Global.opt.dumpTree()) { - diddump = true; - m_syms.dumpFilePrefixed("linkdot-preerr"); - } - } VSymEnt* findDotted(VSymEnt* lookupSymp, const string& dotname, string& baddot, VSymEnt*& okSymp) { // Given a dotted hierarchy name, return where in scope it is @@ -221,7 +221,7 @@ public: altIdent = ident.substr(0,pos); } } - UINFO(8," id "<findDotted(aboveSymp, scope, baddot, okSymp); - if (!aboveSymp) nodep->v3fatalSrc("Can't find cell insertion point at '"<prettyName()); + if (!aboveSymp) { + m_statep->preErrorDump(); + nodep->v3fatalSrc("Can't find cell insertion point at '"<prettyName()); + } } { m_scope = m_scope+"."+nodep->name(); @@ -377,7 +380,10 @@ private: string baddot; VSymEnt* okSymp; aboveSymp = m_statep->findDotted(aboveSymp, dotted, baddot, okSymp); - if (!aboveSymp) nodep->v3fatalSrc("Can't find cellinline insertion point at '"<prettyName()); + if (!aboveSymp) { + m_statep->preErrorDump(); + nodep->v3fatalSrc("Can't find cellinline insertion point at '"<prettyName()); + } m_statep->insertInline(aboveSymp, m_modSymp, nodep, ident); } else { // No __DOT__, just directly underneath m_statep->insertInline(aboveSymp, m_modSymp, nodep, nodep->name()); @@ -386,14 +392,14 @@ private: virtual void visit(AstBegin* nodep, AstNUser*) { UINFO(5," "<insertBegin(m_curSymp, m_modSymp, nodep); nodep->stmtsp()->iterateAndNext(*this); } - m_curSymp = oldSymp; + m_curSymp = oldCurSymp; m_beginp = oldbegin; // nodep->flatsp()->iterateAndNext(*this); @@ -648,13 +654,15 @@ public: //###################################################################### // Link class functions -void V3LinkDot::linkDotGuts(AstNetlist* rootp, bool prearray, bool scoped) { +int V3LinkDot::debug() { return LinkDotState::debug(); } + +void V3LinkDot::linkDotGuts(AstNetlist* rootp, VLinkDotStep step) { UINFO(2,__FUNCTION__<<": "<=5 || v3Global.opt.dumpTree()>=9) v3Global.rootp()->dumpTreeFile(v3Global.debugFilename("prelinkdot.tree")); - LinkDotState state (rootp, prearray, scoped); + LinkDotState state (rootp, step); LinkDotFindVisitor visitor(rootp,&state); if (LinkDotState::debug()>=5 || v3Global.opt.dumpTree()>=9) v3Global.rootp()->dumpTreeFile(v3Global.debugFilename("prelinkdot-find.tree")); - if (scoped) { + if (step == LDS_SCOPED) { // Well after the initial link when we're ready to operate on the flat design, // process AstScope's. This needs to be separate pass after whole hierarchy graph created. LinkDotScopeVisitor visitors(rootp,&state); diff --git a/src/V3LinkDot.h b/src/V3LinkDot.h index 8023a1a93..0416b75e4 100644 --- a/src/V3LinkDot.h +++ b/src/V3LinkDot.h @@ -27,13 +27,21 @@ //============================================================================ +enum VLinkDotStep { LDS_PRIMARY, LDS_PARAMED, LDS_ARRAYED, LDS_SCOPED }; + class V3LinkDot { private: - static void linkDotGuts(AstNetlist* nodep, bool preparam, bool scoped); + static int debug(); + static void linkDotGuts(AstNetlist* nodep, VLinkDotStep step); public: - static void linkDotPrearrayed(AstNetlist* nodep) { linkDotGuts(nodep,true,false); } - static void linkDotArrayed(AstNetlist* nodep) { linkDotGuts(nodep,false,false); } - static void linkDotScope(AstNetlist* nodep) { linkDotGuts(nodep,false,true); } + static void linkDotPrimary(AstNetlist* nodep) { + UINFO(2,__FUNCTION__<<": "<didWidth()) return; + if (!nodep->varp()) nodep->v3fatalSrc("Unlinked varref"); if (!nodep->varp()->didWidth()) { // Var hasn't been widthed, so make it so. nodep->varp()->iterate(*this); diff --git a/src/Verilator.cpp b/src/Verilator.cpp index c7b3ac981..831be7238 100644 --- a/src/Verilator.cpp +++ b/src/Verilator.cpp @@ -161,8 +161,9 @@ void process () { V3Link::link(v3Global.rootp()); if (dumpMore) V3Global::dumpGlobalTree("linkmain.tree"); // Cross-link dotted hierarchical references - V3LinkDot::linkDotPrearrayed(v3Global.rootp()); + V3LinkDot::linkDotPrimary(v3Global.rootp()); if (dumpMore) V3Global::dumpGlobalTree("linkdot.tree"); + v3Global.checkTree(); // Force a check, as link is most likely place for problems // Correct state we couldn't know at parse time, repair SEL's V3LinkResolve::linkResolve(v3Global.rootp()); if (dumpMore) V3Global::dumpGlobalTree("linkresolve.tree"); @@ -179,8 +180,9 @@ void process () { // Remove parameters by cloning modules to de-parameterized versions // This requires some width calculations and constant propagation V3Param::param(v3Global.rootp()); - V3LinkDot::linkDotPrearrayed(v3Global.rootp()); // Cleanup as made new modules - V3Global::dumpGlobalTree("param.tree"); + if (dumpMore) V3Global::dumpGlobalTree("param.tree"); + V3LinkDot::linkDotParamed(v3Global.rootp()); // Cleanup as made new modules + V3Global::dumpGlobalTree("paramlink.tree"); V3Error::abortIfErrors(); // Remove any modules that were parameterized and are no longer referenced.