From 3ec687a0cf8b3ad27b6d5628a941ce2934dc68d4 Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Wed, 20 Jun 2012 06:13:28 -0400 Subject: [PATCH] Internals: Merge from struct branch, rework LinkDot symbol table. No functional change intended. --- src/V3Ast.h | 4 +- src/V3Link.cpp | 89 ++++----- src/V3LinkCells.cpp | 15 +- src/V3LinkDot.cpp | 476 ++++++++++++++++++-------------------------- src/V3ParseImp.h | 66 +++--- src/V3SymTable.h | 154 ++++++++++---- src/Verilator.cpp | 2 +- src/verilog.l | 6 +- src/verilog.y | 2 +- 9 files changed, 404 insertions(+), 410 deletions(-) diff --git a/src/V3Ast.h b/src/V3Ast.h index 537ea9820..300993497 100644 --- a/src/V3Ast.h +++ b/src/V3Ast.h @@ -606,13 +606,13 @@ class LinkVP; class OrderBlockNU; class OrderVarNU; class V3GraphVertex; -class V3SymTable; +class VSymEnt; struct AstNUser { AstNUser* p() { return this; } // So can take address of temporary: iterate(...,AstNUser(args).p()) // Casters WidthVP* c() { return ((WidthVP*)this); } LinkVP* castLinkVP() { return ((LinkVP*)this); } - V3SymTable* castSymTable() { return ((V3SymTable*)this); } + VSymEnt* castSymEnt() { return ((VSymEnt*)this); } AstNode* castNode() { return ((AstNode*)this); } OrderBlockNU* castOrderBlock() { return ((OrderBlockNU*)this); } OrderVarNU* castOrderVar() { return ((OrderVarNU*)this); } diff --git a/src/V3Link.cpp b/src/V3Link.cpp index 7a57ad94a..d2c9e1e0c 100644 --- a/src/V3Link.cpp +++ b/src/V3Link.cpp @@ -50,10 +50,10 @@ private: // Entire netlist: // AstVar/Module/Task::user1() // AstPackage* Set if inside a package // AstVar::user2p() // bool True if port set for this variable - // AstVar/Module::user3p() // V3SymTable* Table used to create this variable - // AstNodeModule::user4p() // V3SymTable* Module's Symbol table - // AstNodeFTask::user4p() // V3SymTable* Local Symbol table - // AstBegin::user4p() // V3SymTable* Local Symbol table + // AstVar/Module::user3p() // VSymEnt* Table used to create this variable + // AstNodeModule::user4p() // VSymEnt* Module's Symbol table + // AstNodeFTask::user4p() // VSymEnt* Local Symbol table + // AstBegin::user4p() // VSymEnt* Local Symbol table // AstVar::user5p() // AstPin* True if port attached to a pin AstUser2InUse m_inuser2; AstUser3InUse m_inuser3; @@ -68,18 +68,18 @@ private: // STATE // Below state needs to be preserved between each module call. + VSymGraph m_syms; // Symbol table graph AstPackage* m_packagep; // Current package AstCell* m_cellp; // Current cell AstNodeModule* m_modp; // Current module AstNodeFTask* m_ftaskp; // Current function/task IdState m_idState; // Id linking mode (find or resolve) int m_paramNum; // Parameter number, for position based connection - V3SymTable* m_curVarsp; // Symbol table of variables and tasks under table we're inserting into - V3SymTable* m_cellVarsp; // Symbol table of variables under cell's module + VSymEnt* m_curVarsp; // Symbol table of variables and tasks under table we're inserting into + VSymEnt* m_cellVarsp; // Symbol table of variables under cell's module int m_beginNum; // Begin block number, 0=none seen int m_modBeginNum; // Begin block number in module, 0=none seen bool m_inGenerate; // Inside a generate - vector m_delSymps; // Symbol tables to delete static int debug() { static int level = -1; @@ -88,21 +88,20 @@ private: } // METHODS - V3SymTable* symsFindNew(AstNode* nodep, V3SymTable* upperVarsp) { + VSymEnt* symsFindNew(AstNode* nodep) { // Find or create symbol table for this node - V3SymTable* symsp = nodep->user4p()->castSymTable(); + VSymEnt* symsp = nodep->user4p()->castSymEnt(); if (symsp) { return symsp; } else { - symsp = new V3SymTable(nodep, upperVarsp); - m_delSymps.push_back(symsp); + symsp = new VSymEnt(&m_syms, nodep); nodep->user4p(symsp); return symsp; } } - V3SymTable* symsFind(AstNode* nodep) { + VSymEnt* symsFind(AstNode* nodep) { // Find or create symbol table for this node - if (V3SymTable* symsp = nodep->user4p()->castSymTable()) { + if (VSymEnt* symsp = nodep->user4p()->castSymEnt()) { return symsp; } else { nodep->v3fatalSrc("Symbol table not found looking up symbol"); @@ -112,7 +111,7 @@ private: void symsInsert(const string& name, AstNode* nodep) { // Insert into symbol table, and remember what table the node is in - m_curVarsp->insert(name, nodep); + m_curVarsp->insert(name, symsFindNew(nodep)); nodep->user3p(m_curVarsp); nodep->user1p(m_packagep); } @@ -125,7 +124,7 @@ private: bool linkVarName (AstVarRef* nodep) { // Return true if changed, and caller should end processing if (!nodep->varp()) { - AstNode* foundp = m_curVarsp->findIdFallback(nodep->name()); + AstNode* foundp = m_curVarsp->findIdFallback(nodep->name())->nodep(); if (AstVar* varp = foundp->castVar()) { nodep->varp(varp); nodep->packagep(packageFor(varp)); @@ -162,7 +161,7 @@ private: // // Note we only check for conflicts at the same level; it's ok if one block hides another // We also wouldn't want to not insert it even though it's lower down - AstNode* foundp = m_curVarsp->findIdFlat(name); + AstNode* foundp = m_curVarsp->findIdFlat(name)->nodep(); if (!foundp) { symsInsert(nodep->name(), nodep); foundp = nodep; @@ -200,7 +199,7 @@ private: m_modp->addStmtp(newp); // Link it to signal list IdState old_id = m_idState; - V3SymTable* old_varsp = m_curVarsp; + VSymEnt* old_varsp = m_curVarsp; m_idState = ID_FIND; m_curVarsp = symsFind(m_modp); // Must add the variable under the module; curVarsp might be lower now newp->accept(*this); @@ -212,7 +211,7 @@ private: // VISITs virtual void visit(AstNetlist* nodep, AstNUser* vup) { // Top scope - m_curVarsp = symsFindNew(nodep, NULL); + m_curVarsp = symsFindNew(nodep); // Recurse..., backward as must do packages before using packages m_idState = ID_FIND; nodep->iterateChildrenBackwards(*this); @@ -228,7 +227,7 @@ private: // Module: Create sim table for entire module and iterate UINFO(2,"Link Module: "<v3fatalSrc("NULL"); @@ -238,7 +237,8 @@ private: // Don't insert dunit itself, or symtable->dump will loop-recurse } else { findAndInsertAndCheck(nodep, nodep->name()); - m_curVarsp = symsFindNew(nodep, upperVarsp); + m_curVarsp = symsFindNew(nodep); + m_curVarsp->fallbackp(upperVarsp); UINFO(9, "New module scope "<trace(false); } // Find under either a task or the module's vars - AstNode* foundp = m_curVarsp->findIdFallback(nodep->name()); + AstNode* foundp = m_curVarsp->findIdFallback(nodep->name())->nodep(); AstVar* findvarp = foundp->castVar(); bool ins=false; if (!foundp) { @@ -290,7 +290,7 @@ private: <prettyName()); } else if (findvarp != nodep) { UINFO(4,"DupVar: "<user3p()->castSymTable() == m_curVarsp) { // Only when on same level + if (findvarp && findvarp->user3p()->castSymEnt() == m_curVarsp) { // Only when on same level if ((findvarp->isIO() && nodep->isSignal()) || (findvarp->isSignal() && nodep->isIO())) { findvarp->combineType(nodep); @@ -354,14 +354,14 @@ private: nodep->iterateChildren(*this); if (m_idState==ID_FIND) { // Find under either a task or the module's vars - AstNode* foundp = m_curVarsp->findIdFallback(nodep->name()); + AstNode* foundp = m_curVarsp->findIdFallback(nodep->name())->nodep(); AstEnumItem* findvarp = foundp->castEnumItem(); bool ins=false; if (!foundp) { ins=true; } else if (findvarp != nodep) { UINFO(4,"DupVar: "<user3p()->castSymTable() == m_curVarsp) { // Only when on same level + if (findvarp && findvarp->user3p()->castSymEnt() == m_curVarsp) { // Only when on same level nodep->v3error("Duplicate declaration of enum value: "<prettyName()<warnMore()<<"... Location of original declaration"); } else { @@ -384,10 +384,11 @@ private: // NodeTask: Remember its name for later resolution if (!m_curVarsp) nodep->v3fatalSrc("Function/Task not under module??\n"); // Remember the existing symbol table scope - V3SymTable* upperVarsp = m_curVarsp; + VSymEnt* upperVarsp = m_curVarsp; { // Create symbol table for the task's vars - m_curVarsp = symsFindNew(nodep, upperVarsp); + m_curVarsp = symsFindNew(nodep); + m_curVarsp->fallbackp(upperVarsp); // Convert the func's range to the output variable // This should probably be done in the Parser instead, as then we could @@ -420,7 +421,7 @@ private: virtual void visit(AstBegin* nodep, AstNUser*) { // Link variables underneath blocks // Remember the existing symbol table scope - V3SymTable* upperVarsp = m_curVarsp; + VSymEnt* upperVarsp = m_curVarsp; // Rename "genblk"s to include a number // All blocks are numbered in the standard, IE we start with "genblk1" even if only one. UINFO(8," "<hidden()) m_beginNum = 0; { // Create symbol table for the task's vars - m_curVarsp = symsFindNew(nodep, upperVarsp); + m_curVarsp = symsFindNew(nodep); + m_curVarsp->fallbackp(upperVarsp); nodep->iterateChildren(*this); } m_curVarsp = upperVarsp; @@ -464,9 +466,9 @@ private: if (nodep->dotted() == "") { AstNodeFTask* taskp; if (nodep->packagep()) { - taskp = symsFind(nodep->packagep())->findIdFallback(nodep->name())->castNodeFTask(); + taskp = symsFind(nodep->packagep())->findIdFallback(nodep->name())->nodep()->castNodeFTask(); } else { - taskp = m_curVarsp->findIdFallback(nodep->name())->castNodeFTask(); + taskp = m_curVarsp->findIdFallback(nodep->name())->nodep()->castNodeFTask(); } if (!taskp) { nodep->v3error("Can't find definition of task/function: "<prettyName()); } nodep->taskp(taskp); @@ -481,7 +483,7 @@ private: nodep->iterateChildren(*this); if (m_idState==ID_RESOLVE) { AstNodeFTask* taskp; - taskp = m_curVarsp->findIdFallback(nodep->name())->castNodeFTask(); + taskp = m_curVarsp->findIdFallback(nodep->name())->nodep()->castNodeFTask(); if (!taskp) { nodep->v3error("Can't find definition of exported task/function: "<prettyName()); } else if (taskp->dpiExport()) { nodep->v3error("Function was already DPI Exported, duplicate not allowed: "<prettyName()); @@ -506,9 +508,9 @@ private: if (m_idState==ID_RESOLVE && !nodep->defp()) { AstTypedef* defp; if (nodep->packagep()) { - defp = symsFind(nodep->packagep())->findIdFlat(nodep->name())->castTypedef(); + defp = symsFind(nodep->packagep())->findIdFlat(nodep->name())->nodep()->castTypedef(); } else { - defp = m_curVarsp->findIdFallback(nodep->name())->castTypedef(); + defp = m_curVarsp->findIdFallback(nodep->name())->nodep()->castTypedef(); } if (!defp) { nodep->v3error("Can't find typedef: "<prettyName()); } nodep->refDTypep(defp->subDTypep()); @@ -535,7 +537,7 @@ private: } // Need to pass the module info to this cell, so we can link up the pin names else if (m_idState==ID_RESOLVE) { - m_cellVarsp = nodep->modp()->user4p()->castSymTable(); + m_cellVarsp = nodep->modp()->user4p()->castSymEnt(); UINFO(4,"(Backto) Link Cell: "<dumpTree(cout,"linkcell:"); } //if (debug()) { nodep->modp()->dumpTree(cout,"linkcemd:"); } @@ -557,7 +559,7 @@ private: if (m_idState==ID_PARAM) { // Need to set pin numbers after varnames are created // But before we do the final resolution based on names - AstVar* refp = m_curVarsp->findIdFlat(nodep->name())->castVar(); + AstVar* refp = m_curVarsp->findIdFlat(nodep->name())->nodep()->castVar(); if (!refp) { nodep->v3error("Input/output/inout declaration not found for port: "<prettyName()); } else if (!refp->isIO()) { @@ -597,7 +599,7 @@ private: // ONLY CALLED by visit(AstCell) during ID_RESOLVE and ID_PARAM state if (m_idState==ID_RESOLVE && !nodep->modVarp()) { if (!m_cellVarsp) nodep->v3fatalSrc("Pin not under cell?\n"); - AstVar* refp = m_cellVarsp->findIdFlat(nodep->name())->castVar(); + AstVar* refp = m_cellVarsp->findIdFlat(nodep->name())->nodep()->castVar(); if (!refp) { if (nodep->name() == "__paramNumber1" && m_cellp->modp()->castPrimitive()) { // Primitive parameter is really a delay we can just ignore @@ -656,7 +658,7 @@ private: nodep->iterateChildren(*this); if (m_idState==ID_PARAM) { nodep->v3warn(DEFPARAM,"Suggest replace defparam with Verilog 2001 #(."<name()<<"(...etc...))"); - AstNode* foundp = m_curVarsp->findIdFallback(nodep->path()); + AstNode* foundp = m_curVarsp->findIdFallback(nodep->path())->nodep(); AstCell* cellp = foundp->castCell(); if (!cellp) { nodep->v3error("In defparam, cell "<path()<<" never declared"); @@ -677,9 +679,9 @@ private: virtual void visit(AstPackageImport* nodep, AstNUser*) { UINFO(2," Link: "<packagep()); + VSymEnt* srcp = symsFind(nodep->packagep()); if (nodep->name()!="*") { - AstNode* impp = srcp->findIdFlat(nodep->name()); + VSymEnt* impp = srcp->findIdFlat(nodep->name()); if (!impp) { nodep->v3error("Import object not found: "<packagep()->prettyName()<<"::"<prettyName()); } @@ -696,7 +698,8 @@ private: public: // CONSTUCTORS - LinkVisitor(AstNetlist* rootp) { + LinkVisitor(AstNetlist* rootp) + : m_syms(rootp) { m_curVarsp = NULL; m_cellVarsp = NULL; m_cellp = NULL; @@ -710,11 +713,7 @@ public: // rootp->accept(*this); } - virtual ~LinkVisitor() { - for (vector::iterator it = m_delSymps.begin(); it != m_delSymps.end(); ++it) { - delete (*it); - } - } + virtual ~LinkVisitor() {} }; //###################################################################### diff --git a/src/V3LinkCells.cpp b/src/V3LinkCells.cpp index 57bd4b82b..1cfd1f91c 100644 --- a/src/V3LinkCells.cpp +++ b/src/V3LinkCells.cpp @@ -91,7 +91,7 @@ private: // Entire netlist: // AstNodeModule::user1p() // V3GraphVertex* Vertex describing this module // Allocated across all readFiles in V3Global::readFiles: - // AstNode::user4p() // V3SymTable* Package and typedef symbol names + // AstNode::user4p() // VSymEnt* Package and typedef symbol names AstUser1InUse m_inuser1; // STATE @@ -99,7 +99,7 @@ private: // Below state needs to be preserved between each module call. AstNodeModule* m_modp; // Current module - V3SymTable m_mods; // Symbol table of all module names + VSymGraph m_mods; // Symbol table of all module names LinkCellsGraph m_graph; // Linked graph of all cell interconnects LibraryVertex* m_libVertexp; // Vertex at root of all libraries V3GraphVertex* m_topVertexp; // Vertex of top module @@ -197,7 +197,7 @@ private: UINFO(4,"Link Cell: "<modName())->castNodeModule(); + AstNodeModule* modp = m_mods.rootp()->findIdFallback(nodep->modName())->nodep()->castNodeModule(); if (!modp) { // Read-subfile // If file not found, make AstNotFoundModule, rather than error out. @@ -208,7 +208,7 @@ private: // We've read new modules, grab new pointers to their names readModNames(); // Check again - modp = m_mods.findIdFallback(nodep->modName())->castNodeModule(); + modp = m_mods.rootp()->findIdFallback(nodep->modName())->nodep()->castNodeModule(); if (!modp) { nodep->v3error("Can't resolve module reference: "<modName()); } @@ -299,7 +299,7 @@ private: // Look at all modules, and store pointers to all module names for (AstNodeModule* nextp,* nodep = v3Global.rootp()->modulesp(); nodep; nodep=nextp) { nextp = nodep->nextp()->castNodeModule(); - AstNode* foundp = m_mods.findIdFallback(nodep->name()); + AstNode* foundp = m_mods.rootp()->findIdFallback(nodep->name())->nodep(); if (foundp && foundp != nodep) { if (!(foundp->fileline()->warnIsOff(V3ErrorCode::MODDUP) || nodep->fileline()->warnIsOff(V3ErrorCode::MODDUP))) { nodep->v3warn(MODDUP,"Duplicate declaration of module: "<prettyName()<unlinkFrBack(); pushDeletep(nodep); nodep=NULL; } else if (!foundp) { - m_mods.insert(nodep->name(), nodep); + m_mods.rootp()->insert(nodep->name(), new VSymEnt(&m_mods, nodep)); } } //if (debug()>=9) m_mods.dump(cout, "-syms: "); @@ -316,7 +316,8 @@ private: public: // CONSTUCTORS - LinkCellsVisitor(AstNetlist* rootp, V3InFilter* filterp) { + LinkCellsVisitor(AstNetlist* rootp, V3InFilter* filterp) + : m_mods(rootp) { m_filterp = filterp; m_modp = NULL; m_libVertexp = NULL; diff --git a/src/V3LinkDot.cpp b/src/V3LinkDot.cpp index b8052545f..3d43917e6 100644 --- a/src/V3LinkDot.cpp +++ b/src/V3LinkDot.cpp @@ -27,13 +27,16 @@ // VarXRef/Func's: // Find appropriate named cell and link to var they reference //************************************************************************* -// Top -// a (LinkDotCellVertex->AstCell) -// aa (LinkDotCellVertex->AstCell) -// var (AstVar) -- in syms(), not a vertex -// beg (LinkDotBeginVertex->AstBegin) -- can see "upper" a's symbol table -// a__DOT__aa (LinkDotInlineVertex->AstCellInline) -- points to a.aa's symbol table -// b (LinkDotCellVertex->AstCell) +// TOP +// {name-of-top-modulename} +// a (VSymEnt->AstCell) +// {name-of-cell} +// {name-of-cell-module} +// aa (VSymEnt->AstCell) +// var (AstVar) -- no sub symbol table needed +// beg (VSymEnt->AstBegin) -- can see "upper" a's symbol table +// a__DOT__aa (VSymEnt->AstCellInline) -- points to a.aa's symbol table +// b (VSymEnt->AstCell) //************************************************************************* #include "config_build.h" @@ -51,130 +54,6 @@ #include "V3Graph.h" #include "V3Ast.h" -//###################################################################### - -class LinkDotGraph : public V3Graph { -public: - LinkDotGraph() {} - virtual ~LinkDotGraph() {} - virtual string dotRankDir() { return "LR"; } -}; - -class LinkDotBaseVertex : public V3GraphVertex { - typedef std::map NameVtxMap; - // A point in the hierarchy, either inlined or real - string m_symPrefix; // String to prefix symbols with - NameVtxMap m_nameToVtxMap; // Lookup of name -> to vertexes -public: - LinkDotBaseVertex(V3Graph* graphp, const string& symPrefix) - : V3GraphVertex(graphp), m_symPrefix(symPrefix) {} - virtual ~LinkDotBaseVertex() {} - virtual string modName() const = 0; - virtual string cellName() const = 0; - virtual V3SymTable& syms() = 0; - string symPrefix() const { return m_symPrefix; } - void insertSubcellName(LinkDotGraph* graphp, const string& name, LinkDotBaseVertex* toVertexp) { - m_nameToVtxMap.insert(make_pair(name, toVertexp)); - new V3GraphEdge(graphp, this, toVertexp, 1, false); - } - LinkDotBaseVertex* findSubcell(const string& name, const string& altname) { - // Find a vertex under this one by name. - // We could walk the edge top() list, but that would be O(n) for large lists of cells - { - NameVtxMap::iterator iter = m_nameToVtxMap.find(name); - if (iter != m_nameToVtxMap.end()) return iter->second; - } - if (altname != "") { - NameVtxMap::iterator iter = m_nameToVtxMap.find(altname); - if (iter != m_nameToVtxMap.end()) return iter->second; - } - return NULL; - } - void errorScopes(AstNode* nodep) { - if (!this) { // Silence if we messed it up and aren't debugging - if (debug() || v3Global.opt.debugCheck()) nodep->v3fatalSrc("Void pointer; perhaps used null vxp instead of okVxp?"); - return; - } - { - string scopes; - for (NameVtxMap::iterator it = m_nameToVtxMap.begin(); it!=m_nameToVtxMap.end(); ++it) { - if (scopes != "") scopes += ", "; - scopes += AstNode::prettyName(it->second->cellName()); - } - cerr<second->name()<modp()), m_nodep(nodep) {} - LinkDotCellVertex(V3Graph* graphp, AstNodeModule* nodep) - : LinkDotBaseVertex(graphp, ""), m_modp(nodep), m_nodep(NULL) {} - virtual ~LinkDotCellVertex() {} - AstNodeModule* modp() const { return m_modp; } // May be NULL - AstCell* nodep() const { return m_nodep; } // Is NULL at TOP - virtual V3SymTable& syms() { return m_syms; } - // We need to use origName as parameters may have renamed the modname - virtual string modName() const { return (modp() ? modp()->origName() : "*NULL*"); } - virtual string cellName() const { return (nodep() ? nodep()->origName() : "*NULL*"); } - virtual string name() const { return (string)("C:")+cellName()+" M:"+modName(); } -}; - -class LinkDotInlineVertex : public LinkDotBaseVertex { - // A fake point in the hierarchy, corresponding to an inlined module - // This refrences to another vertex, and eventually resolves to a module with a prefix - string m_basename; // Name with dotteds stripped - AstCellInline* m_cellInlinep; // Inlined cell - LinkDotCellVertex* m_symVxp; // Above cell so we can find real symbol table - // // (Could walk graph to find it, but that's much slower.) -public: - LinkDotInlineVertex(V3Graph* graphp, AstCellInline* nodep, LinkDotCellVertex* symVxp, - const string& basename) - : LinkDotBaseVertex(graphp, nodep->name()+"__DOT__") - , m_basename(basename), m_cellInlinep(nodep), m_symVxp(symVxp) {} - virtual ~LinkDotInlineVertex() {} - AstCellInline* cellInlinep() const { return m_cellInlinep; } - // Search up through tree to find the real symbol table. - virtual V3SymTable& syms() { return m_symVxp->syms(); } - virtual string modName() const { return cellInlinep()->origModName(); } - virtual string cellName() const { return m_basename; } - virtual string name() const { return (string)("INL C:")+cellName()+" M:"+modName()+" P:"+symPrefix(); } - virtual string dotColor() const { return "yellow"; } -}; - -class LinkDotBeginVertex : public LinkDotBaseVertex { - // A fake point in the hierarchy, corresponding to a begin block - // After we remove begins these will go away - // Note we use the symbol table of the parent, as we want to find variables there - // However, cells walk the graph, so cells will appear under the begin itself - AstBegin* m_nodep; // Relevant node - LinkDotCellVertex* m_symVxp; // Above cell so we can find real symbol table - // // (Could walk graph to find it, but that's much slower.) -public: - LinkDotBeginVertex(V3Graph* graphp, AstBegin* nodep, LinkDotCellVertex* symVxp) - : LinkDotBaseVertex(graphp, nodep->name()+"__DOT__") - , m_nodep(nodep), m_symVxp(symVxp) {} - virtual ~LinkDotBeginVertex() {} - // Search up through tree to find the real symbol table. - virtual V3SymTable& syms() { return m_symVxp->syms(); } - virtual string modName() const { return m_nodep->name(); } - virtual string cellName() const { return m_nodep->name(); } - virtual string name() const { return (string)("BEG C:")+cellName(); } - virtual string dotColor() const { return "blue"; } -}; - //###################################################################### // LinkDot state, as a visitor of each AstNode @@ -182,15 +61,15 @@ class LinkDotState { private: // NODE STATE // Cleared on Netlist - // AstNodeModule::user1p() -> LinkDotCellVertex*. Last cell that uses this module + // AstNodeModule::user1p() -> VSymEnt*. Last cell that uses this module // AstVarScope::user2p() -> AstVarScope*. Base alias for this signal AstUser1InUse m_inuser1; AstUser2InUse m_inuser2; // TYPES - typedef std::multimap NameScopeMap; + typedef std::multimap NameScopeMap; // MEMBERS - LinkDotGraph m_graph; // Graph of hierarchy + VSymGraph m_syms; // Symbol table NameScopeMap m_nameScopeMap; // Hash of scope referenced by non-pretty textual name bool m_forPrearray; // Compress cell__[array] refs bool m_forScopeCreation; // Remove VarXRefs for V3Scope @@ -203,7 +82,8 @@ public: } // CONSTRUCTORS - LinkDotState(bool forPrearray, bool forScopeCreation) { + LinkDotState(AstNetlist* rootp, bool forPrearray, bool forScopeCreation) + : m_syms(rootp) { UINFO(4,__FUNCTION__<<": "<findIdFallback(name); + if (findp) return findp; + findp = symp->findIdFallback(altname); + return findp; + } +public: + VSymEnt* insertTopCell(AstNodeModule* nodep, const string& scopename) { // Only called on the module at the very top of the hierarchy - UINFO(9," INSERTcell "<user1p(vxp); - if (forScopeCreation()) m_nameScopeMap.insert(make_pair(scopename, vxp)); - return vxp; + UINFO(9," INSERTtop "<parentp(m_syms.rootp()); // Needed so backward search can find name of top module + nodep->user1p(symp); + m_syms.rootp()->insert(nodep->origName(),symp); + if (forScopeCreation()) m_nameScopeMap.insert(make_pair(scopename, symp)); + return symp; } - LinkDotCellVertex* insertCell(LinkDotBaseVertex* abovep, LinkDotCellVertex* cellVxp, - AstCell* nodep, const string& scopename) { - UINFO(9," INSERTcell "<modp()) nodep->modp()->user1p(vxp); - abovep->insertSubcellName(&m_graph, nodep->origName(), vxp); - if (abovep != cellVxp) { + VSymEnt* insertCell(VSymEnt* abovep, VSymEnt* cellSymp, + AstCell* nodep, const string& scopename) { + UINFO(9," INSERTcel "<insertSubcellName(&m_graph, basename, vxp); - if (abovep != cellVxp) { + VSymEnt* insertInline(VSymEnt* abovep, VSymEnt* cellSymp, + AstCellInline* nodep, const string& basename) { + // A fake point in the hierarchy, corresponding to an inlined module + // This refrences to another Sym, and eventually resolves to a module with a prefix + UINFO(9," INSERTcel "<reinsert(basename, symp); + if (abovep != cellSymp) { // If it's foo_DOT_bar, we need to be able to find it under that too. - cellVxp->insertSubcellName(&m_graph, nodep->name(), vxp); + cellSymp->reinsert(nodep->name(), symp); } - return vxp; + return symp; } - LinkDotBeginVertex* insertBegin(LinkDotBaseVertex* abovep, LinkDotCellVertex* cellVxp, - AstBegin* nodep) { - UINFO(9," INSERTbeg "<insertSubcellName(&m_graph, nodep->name(), vxp); - return vxp; + VSymEnt* insertBegin(VSymEnt* abovep, VSymEnt* cellSymp, + AstBegin* nodep) { + // A fake point in the hierarchy, corresponding to a begin block + // After we remove begins these will go away + // Note we fallback to the symbol table of the parent, as we want to find variables there + // However, cells walk the graph, so cells will appear under the begin itself + UINFO(9," INSERTbeg above="<<(void*)abovep<<" cells="<<(void*)cellSymp<<" node="<parentp(abovep); + symp->symPrefix(nodep->name()+"__DOT__"); + if (nodep->name() != "") { + // Duplicates are possible, as until resolve generates might have 2 same cells under an if + abovep->reinsert(nodep->name(), symp); + } + return symp; } - void insertSym(LinkDotCellVertex* abovep, const string& name, AstNode* nodep) { - UINFO(9," INSERTsym "<syms().insert(name, nodep); + void insertSym(VSymEnt* abovep, const string& name, AstNode* nodep) { + UINFO(9," INSERTsym name='"<user1p()->castSymEnt(); + if (!symp) nodep->v3fatalSrc("Module never assigned a symbol entry?"); + return symp; } - LinkDotCellVertex* findScope(AstScope* nodep) { + VSymEnt* findScopeSym(AstScope* nodep) { NameScopeMap::iterator iter = m_nameScopeMap.find(nodep->name()); if (iter == m_nameScopeMap.end()) { - nodep->v3fatalSrc("Scope never assigned a vertex"); + nodep->v3fatalSrc("Scope never assigned a symbol entry?"); } return iter->second; } void dump() { - if (debug()>=6) m_graph.dumpDotFilePrefixed("linkdot"); + if (debug()>=6) m_syms.dumpFilePrefixed("linkdot"); } -private: - LinkDotBaseVertex* parentOfCell(LinkDotBaseVertex* lowerVxp) { - for (V3GraphEdge* edgep = lowerVxp->inBeginp(); edgep; edgep=edgep->inNextp()) { - LinkDotBaseVertex* fromVxp = dynamic_cast(edgep->fromp()); - return fromVxp; + void preErrorDump() { + static bool diddump = false; + if (!diddump && v3Global.opt.dumpTree()) { + diddump = true; + m_syms.dumpFilePrefixed("linkdot-preerr"); } - return NULL; } -public: - LinkDotBaseVertex* findDotted(LinkDotBaseVertex* cellVxp, const string& dotname, - string& baddot, LinkDotBaseVertex*& okVxp) { + VSymEnt* findDotted(VSymEnt* cellSymp, const string& dotname, + string& baddot, VSymEnt*& okSymp) { // Given a dotted hierarchy name, return where in scope it is - // Note when dotname=="" we just fall through and return cellVxp + // Note when dotname=="" we just fall through and return cellSymp UINFO(8," dottedFind "<findSubcell(ident, altIdent)) { - cellVxp = findVxp; + AstCell* cellp = cellSymp->nodep()->castCell(); // Replicated below + AstCellInline* inlinep = cellSymp->nodep()->castCellInline(); // Replicated below + if (VSymEnt* findSymp = findSubcell(cellSymp, ident, altIdent)) { + cellSymp = findSymp; } // Check this module - cur modname - else if (cellVxp->modName() == ident) {} - // Check this module - cur cellname - else if (cellVxp->cellName() == ident) {} - else if (cellVxp->cellName() == altIdent) {} + else if ((cellp && cellp->modp()->origName() == ident) + || (inlinep && inlinep->origModName() == ident)) {} // Move up and check cellname + modname else { - while (cellVxp) { - cellVxp = parentOfCell(cellVxp); - if (cellVxp) { - UINFO(9,"\t\tUp to "<modName() == ident - || cellVxp->cellName() == ident - || cellVxp->cellName() == altIdent) { + while (cellSymp) { + cellSymp = cellSymp->parentp(); + cellp = cellSymp->nodep()->castCell(); // Replicated above + inlinep = cellSymp->nodep()->castCellInline(); // Replicated above + if (cellSymp) { + UINFO(9,"\t\tUp to "<modp()->origName() == ident) + || (inlinep && inlinep->origModName() == ident)) { break; } - else if (LinkDotBaseVertex* findVxp = cellVxp->findSubcell(ident, altIdent)) { - cellVxp = findVxp; + else if (VSymEnt* findSymp = findSubcell(cellSymp, ident, altIdent)) { + cellSymp = findSymp; break; } - } + } else break; } - if (!cellVxp) return NULL; // Not found + if (!cellSymp) return NULL; // Not found } } else { // Searching for middle submodule, must be a cell name - if (LinkDotBaseVertex* findVxp = cellVxp->findSubcell(ident, altIdent)) { - cellVxp = findVxp; + if (VSymEnt* findSymp = findSubcell(cellSymp, ident, altIdent)) { + cellSymp = findSymp; } else { return NULL; // Not found } } firstId = false; } - return cellVxp; + return cellSymp; } - AstNode* findSym(LinkDotBaseVertex* cellVxp, const string& dotname, string& baddot) { + AstNode* findSym(VSymEnt* cellSymp, const string& dotname, string& baddot) { // Find symbol in given point in hierarchy - // For simplicity cellVxp may be passed NULL result from findDotted - if (!cellVxp) return NULL; + // For simplicity cellSymp may be passed NULL result from findDotted + if (!cellSymp) return NULL; UINFO(8,"\t\tfindSym "<symPrefix()=="") ? "" : " as ") - <<((cellVxp->symPrefix()=="") ? "" : cellVxp->symPrefix()+dotname) - <<" at "<symPrefix()=="") ? "" : " as ") + <<((cellSymp->symPrefix()=="") ? "" : cellSymp->symPrefix()+dotname) + <<" at "<syms().findIdFlat(cellVxp->symPrefix() + dotname); // Might be NULL + AstNode* nodep = cellSymp->findIdFallback(cellSymp->symPrefix() + dotname)->nodep(); // Might be NULL if (!nodep) baddot = dotname; return nodep; } @@ -376,8 +284,8 @@ class LinkDotFindVisitor : public AstNVisitor { private: // STATE LinkDotState* m_statep; // State to pass between visitors, including symbol table - LinkDotCellVertex* m_cellVxp; // Vertex for current module - LinkDotBaseVertex* m_inlineVxp; // Vertex for current module, possibly a fake inlined one + VSymEnt* m_cellSymp; // Symbol Entry for current module + VSymEnt* m_inlineSymp; // Symbol Entry for current module, possibly a fake inlined one string m_scope; // Scope text AstBegin* m_beginp; // Current Begin/end block @@ -399,21 +307,21 @@ private: } else { UINFO(8,"Top Module: "<insertTopCell(topmodp, m_scope); - m_inlineVxp = m_cellVxp; + m_cellSymp = m_statep->insertTopCell(topmodp, m_scope); + m_inlineSymp = m_cellSymp; { topmodp->accept(*this); } m_scope = ""; - m_cellVxp = NULL; - m_inlineVxp = m_cellVxp; + m_cellSymp = NULL; + m_inlineSymp = m_cellSymp; } } virtual void visit(AstNodeModule* nodep, AstNUser*) { // Called on top module from Netlist, other modules from the cell creating them, // and packages UINFO(8," "<name()); string::size_type pos; if ((pos = origname.rfind(".")) != string::npos) { // Flattened, find what CellInline it should live under string scope = origname.substr(0,pos); string baddot; - LinkDotBaseVertex* okVxp; - aboveVxp = m_statep->findDotted(aboveVxp, scope, baddot, okVxp); - if (!aboveVxp) nodep->v3fatalSrc("Can't find cell insertion point at '"<prettyName()); + VSymEnt* okSymp; + aboveSymp = m_statep->findDotted(aboveSymp, scope, baddot, okSymp); + if (!aboveSymp) nodep->v3fatalSrc("Can't find cell insertion point at '"<prettyName()); } { m_scope = m_scope+"."+nodep->name(); - m_cellVxp = m_statep->insertCell(aboveVxp, m_cellVxp, nodep, m_scope); - m_inlineVxp = m_cellVxp; + m_cellSymp = m_statep->insertCell(aboveSymp, m_cellSymp, nodep, m_scope); + m_inlineSymp = m_cellSymp; m_beginp = NULL; if (nodep->modp()) nodep->modp()->accept(*this); } m_scope = oldscope; m_beginp = oldbeginp; - m_cellVxp = oldVxp; - m_inlineVxp = oldInlineVxp; + m_cellSymp = oldSymp; + m_inlineSymp = oldInlineSymp; } virtual void visit(AstCellInline* nodep, AstNUser*) { UINFO(5," CELLINLINE under "<name(); string::size_type pos; @@ -467,32 +375,32 @@ private: string dotted = dottedname.substr(0, pos); string ident = dottedname.substr(pos+strlen("__DOT__")); string baddot; - LinkDotBaseVertex* okVxp; - aboveVxp = m_statep->findDotted(aboveVxp, dotted, baddot, okVxp); - if (!aboveVxp) nodep->v3fatalSrc("Can't find cellinline insertion point at '"<prettyName()); - m_statep->insertInline(aboveVxp, m_cellVxp, nodep, ident); + VSymEnt* okSymp; + aboveSymp = m_statep->findDotted(aboveSymp, dotted, baddot, okSymp); + if (!aboveSymp) nodep->v3fatalSrc("Can't find cellinline insertion point at '"<prettyName()); + m_statep->insertInline(aboveSymp, m_cellSymp, nodep, ident); } else { // No __DOT__, just directly underneath - m_statep->insertInline(aboveVxp, m_cellVxp, nodep, nodep->name()); + m_statep->insertInline(aboveSymp, m_cellSymp, nodep, nodep->name()); } } virtual void visit(AstBegin* nodep, AstNUser*) { UINFO(5," "<insertBegin(m_inlineVxp, m_cellVxp, nodep); + m_inlineSymp = m_statep->insertBegin(m_inlineSymp, m_cellSymp, nodep); nodep->stmtsp()->iterateAndNext(*this); } - m_inlineVxp = oldVxp; + m_inlineSymp = oldSymp; m_beginp = oldbegin; // nodep->flatsp()->iterateAndNext(*this); } virtual void visit(AstNodeFTask* nodep, AstNUser*) { if (!m_beginp) { // For now, we don't support xrefs into functions inside begin blocks - m_statep->insertSym(m_cellVxp, nodep->name(), nodep); + m_statep->insertSym(m_cellSymp, nodep->name(), nodep); } // No recursion, we don't want to pick up variables } @@ -500,7 +408,7 @@ private: if (!m_statep->forScopeCreation() && !m_beginp // For now, we don't support xrefs into begin blocks && !nodep->isFuncLocal()) { - m_statep->insertSym(m_cellVxp, nodep->name(), nodep); + m_statep->insertSym(m_cellSymp, nodep->name(), nodep); } else { UINFO(9," Not allowing dot refs to: "<forScopeCreation()) v3fatalSrc("Scopes should only exist right after V3Scope"); // Using the CELL names, we created all hierarchy. We now need to match this Scope // up with the hierarchy created by the CELL names. - m_cellVxp = m_statep->findScope(nodep); + m_cellSymp = m_statep->findScopeSym(nodep); nodep->iterateChildren(*this); - m_cellVxp = NULL; + m_cellSymp = NULL; } virtual void visit(AstVarScope* nodep, AstNUser*) { if (!nodep->varp()->isFuncLocal()) { - m_statep->insertSym(m_cellVxp, nodep->varp()->name(), nodep); + m_statep->insertSym(m_cellSymp, nodep->varp()->name(), nodep); } } virtual void visit(AstNodeFTask* nodep, AstNUser*) { - m_statep->insertSym(m_cellVxp, nodep->name(), nodep); + m_statep->insertSym(m_cellSymp, nodep->name(), nodep); // No recursion, we don't want to pick up variables } virtual void visit(AstAssignAlias* nodep, AstNUser*) { @@ -585,7 +494,7 @@ public: // CONSTUCTORS LinkDotScopeVisitor(AstNetlist* rootp, LinkDotState* statep) { UINFO(4,__FUNCTION__<<": "<accept(*this); @@ -599,7 +508,7 @@ class LinkDotResolveVisitor : public AstNVisitor { private: // STATE LinkDotState* m_statep; // State, including dotted symbol table - LinkDotCellVertex* m_cellVxp; // Vertex for current module + VSymEnt* m_cellSymp; // SymEnt for current module int debug() { return LinkDotState::debug(); } @@ -610,18 +519,18 @@ private: UINFO(8," "<existsModScope(nodep)) { UINFO(5,"Dead module for "<findModScope(nodep); + m_cellSymp = m_statep->findModScope(nodep); } nodep->iterateChildren(*this); - m_cellVxp = NULL; + m_cellSymp = NULL; } virtual void visit(AstScope* nodep, AstNUser*) { UINFO(8," "<findScope(nodep); + m_cellSymp = m_statep->findScopeSym(nodep); nodep->iterateChildren(*this); - m_cellVxp = NULL; + m_cellSymp = NULL; } virtual void visit(AstCellInline* nodep, AstNUser*) { if (m_statep->forScopeCreation()) { @@ -633,35 +542,40 @@ private: // We always link even if varp() is set, because the module we choose may change // due to creating new modules, flattening, etc. UINFO(8," "<varp(NULL); // Module that is not in hierarchy. We'll be dead code eliminating it later. } else { string baddot; - LinkDotBaseVertex* okVxp; - LinkDotBaseVertex* dotVxp = m_cellVxp; // Start search at current scope + VSymEnt* okSymp; + VSymEnt* dotSymp = m_cellSymp; // Start search at current scope if (nodep->inlinedDots()!="") { // Correct for current scope string inl = AstNode::dedotName(nodep->inlinedDots()); - dotVxp = m_statep->findDotted(dotVxp, inl, baddot, okVxp); - if (!dotVxp) nodep->v3fatalSrc("Couldn't resolve inlined scope '"<inlinedDots()); + dotSymp = m_statep->findDotted(dotSymp, inl, baddot, okSymp); + if (!dotSymp) { + m_statep->preErrorDump(); + nodep->v3fatalSrc("Couldn't resolve inlined scope '"<inlinedDots()); + } } - dotVxp = m_statep->findDotted(dotVxp, nodep->dotted(), baddot, okVxp); // Maybe NULL + dotSymp = m_statep->findDotted(dotSymp, nodep->dotted(), baddot, okSymp); // Maybe NULL if (!m_statep->forScopeCreation()) { - AstVar* varp = (m_statep->findSym(dotVxp, nodep->name(), baddot) + AstVar* varp = (m_statep->findSym(dotSymp, nodep->name(), baddot) ->castVar()); // maybe NULL nodep->varp(varp); UINFO(7," Resolved "<varp()) { + m_statep->preErrorDump(); nodep->v3error("Can't find definition of '"<dotted()+"."+nodep->prettyName()); - okVxp->errorScopes(nodep); + okSymp->cellErrorScopes(nodep); } } else { string baddot; - AstVarScope* vscp = (m_statep->findSym(dotVxp, nodep->name(), baddot) + AstVarScope* vscp = (m_statep->findSym(dotSymp, nodep->name(), baddot) ->castVarScope()); // maybe NULL if (!vscp) { + m_statep->preErrorDump(); nodep->v3error("Can't find varpin scope of '"<dotted()+"."+nodep->prettyName()); - okVxp->errorScopes(nodep); + okSymp->cellErrorScopes(nodep); } else { while (vscp->user2p()) { // If V3Inline aliased it, pick up the new signal UINFO(7," Resolved pre-alias "<packagep()) { // References into packages don't care about cell hierarchy. - } else if (!m_cellVxp) { + } else if (!m_cellSymp) { UINFO(9,"Dead module for "<taskp(NULL); // Module that is not in hierarchy. We'll be dead code eliminating it later. } else if (nodep->dotted()=="" && nodep->taskp()) { @@ -690,26 +604,28 @@ private: // Might be under a BEGIN we're not processing, so don't relink it } else { string baddot; - LinkDotBaseVertex* okVxp; - LinkDotBaseVertex* dotVxp = m_cellVxp; // Start search at current scope + VSymEnt* okSymp; + VSymEnt* dotSymp = m_cellSymp; // Start search at current scope if (nodep->inlinedDots()!="") { // Correct for current scope string inl = AstNode::dedotName(nodep->inlinedDots()); UINFO(8,"\t\tInlined "<findDotted(dotVxp, inl, baddot, okVxp); - if (!dotVxp) { - okVxp->errorScopes(nodep); + dotSymp = m_statep->findDotted(dotSymp, inl, baddot, okSymp); + if (!dotSymp) { + m_statep->preErrorDump(); + okSymp->cellErrorScopes(nodep); nodep->v3fatalSrc("Couldn't resolve inlined scope '"<inlinedDots()); } } - dotVxp = m_statep->findDotted(dotVxp, nodep->dotted(), baddot, okVxp); // Maybe NULL + dotSymp = m_statep->findDotted(dotSymp, nodep->dotted(), baddot, okSymp); // Maybe NULL - AstNodeFTask* taskp = (m_statep->findSym(dotVxp, nodep->name(), baddot) - ->castNodeFTask()); // maybe NULL + AstNodeFTask* taskp = (m_statep->findSym(dotSymp, nodep->name(), baddot) + ->castNode()->castNodeFTask()); // maybe NULL nodep->taskp(taskp); UINFO(7," Resolved "<taskp()) { + m_statep->preErrorDump(); nodep->v3error("Can't find definition of '"<dotted()+"."+nodep->prettyName()); - okVxp->errorScopes(nodep); + okSymp->cellErrorScopes(nodep); } } nodep->iterateChildren(*this); @@ -723,7 +639,7 @@ public: LinkDotResolveVisitor(AstNetlist* rootp, LinkDotState* statep) { UINFO(4,__FUNCTION__<<": "<accept(*this); } @@ -735,13 +651,15 @@ public: void V3LinkDot::linkDotGuts(AstNetlist* rootp, bool prearray, bool scoped) { UINFO(2,__FUNCTION__<<": "<=5) v3Global.rootp()->dumpTreeFile(v3Global.debugFilename("prelinkdot.tree")); - LinkDotState state (prearray,scoped); + if (LinkDotState::debug()>=5 || v3Global.opt.dumpTree()>=9) v3Global.rootp()->dumpTreeFile(v3Global.debugFilename("prelinkdot.tree")); + LinkDotState state (rootp, prearray, scoped); LinkDotFindVisitor visitor(rootp,&state); + if (LinkDotState::debug()>=5 || v3Global.opt.dumpTree()>=9) v3Global.rootp()->dumpTreeFile(v3Global.debugFilename("prelinkdot-find.tree")); if (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); + if (LinkDotState::debug()>=5 || v3Global.opt.dumpTree()>=9) v3Global.rootp()->dumpTreeFile(v3Global.debugFilename("prelinkdot-scoped.tree")); } state.dump(); LinkDotResolveVisitor visitorb(rootp,&state); diff --git a/src/V3ParseImp.h b/src/V3ParseImp.h index 630b2b42b..0c9c6a982 100644 --- a/src/V3ParseImp.h +++ b/src/V3ParseImp.h @@ -88,34 +88,32 @@ struct V3ParseBisonYYSType { class V3ParseSym { // TYPES - typedef vector SymStack; + typedef vector SymStack; private: // MEMBERS static int s_anonNum; // Number of next anonymous object (parser use only) - V3SymTable* m_symTableNextId; // Symbol table for next lexer lookup (parser use only) - V3SymTable* m_symCurrentp; // Active symbol table for additions/lookups - V3SymTable* m_symRootp; // Root symbol table + VSymGraph m_syms; // Graph of symbol tree + VSymEnt* m_symTableNextId; // Symbol table for next lexer lookup (parser use only) + VSymEnt* m_symCurrentp; // Active symbol table for additions/lookups SymStack m_sympStack; // Stack of upper nodes with pending symbol tables - SymStack m_symsp; // All symbol tables, to cleanup private: // METHODS - static V3SymTable* getTable(AstNode* nodep) { + static VSymEnt* getTable(AstNode* nodep) { if (!nodep->user4p()) nodep->v3fatalSrc("Current symtable not found"); - return nodep->user4p()->castSymTable(); + return nodep->user4p()->castSymEnt(); } public: - V3SymTable* nextId() const { return m_symTableNextId; } - V3SymTable* symCurrentp() const { return m_symCurrentp; } - V3SymTable* symRootp() const { return m_symRootp; } + VSymEnt* nextId() const { return m_symTableNextId; } + VSymEnt* symCurrentp() const { return m_symCurrentp; } + VSymEnt* symRootp() const { return m_syms.rootp(); } - V3SymTable* findNewTable(AstNode* nodep, V3SymTable* parentp) { + VSymEnt* findNewTable(AstNode* nodep) { if (!nodep->user4p()) { - V3SymTable* symsp = new V3SymTable(nodep, parentp); + VSymEnt* symsp = new VSymEnt(&m_syms, nodep); nodep->user4p(symsp); - m_symsp.push_back(symsp); } return getTable(nodep); } @@ -129,31 +127,32 @@ public: m_symTableNextId = NULL; } } - void reinsert(AstNode* nodep, V3SymTable* parentp=NULL) { + void reinsert(AstNode* nodep, VSymEnt* parentp=NULL) { reinsert(nodep, parentp, nodep->name()); } - void reinsert(AstNode* nodep, V3SymTable* parentp, string name) { + void reinsert(AstNode* nodep, VSymEnt* parentp, string name) { if (!parentp) parentp = symCurrentp(); if (name == "") { // New name with space in name so can't collide with users name = string(" anon") + nodep->type().ascii() + cvtToStr(++s_anonNum); } - parentp->reinsert(name,nodep); + parentp->reinsert(name, findNewTable(nodep)); } void pushNew(AstNode* nodep) { pushNewUnder(nodep, NULL); } - void pushNewUnder(AstNode* nodep, V3SymTable* parentp) { + void pushNewUnder(AstNode* nodep, VSymEnt* parentp) { if (!parentp) parentp = symCurrentp(); - V3SymTable* symp = findNewTable(nodep, parentp); // Will set user4p, which is how we connect table to node + VSymEnt* symp = findNewTable(nodep); // Will set user4p, which is how we connect table to node + symp->fallbackp(parentp); reinsert(nodep, parentp); pushScope(symp); } - void pushScope(V3SymTable* symp) { + void pushScope(VSymEnt* symp) { m_sympStack.push_back(symp); m_symCurrentp = symp; } void popScope(AstNode* nodep) { - if (symCurrentp()->ownerp() != nodep) { + if (symCurrentp()->nodep() != nodep) { if (debug()) { showUpward(); dump(cout,"-mism: "); } - nodep->v3fatalSrc("Symbols suggest ending "<ownerp()->prettyTypeName() + nodep->v3fatalSrc("Symbols suggest ending "<nodep()->prettyTypeName() <<" but parser thinks ending "<prettyTypeName()); return; } @@ -164,22 +163,21 @@ public: void showUpward () { UINFO(1,"ParseSym Stack:\n"); for (SymStack::reverse_iterator it=m_sympStack.rbegin(); it!=m_sympStack.rend(); ++it) { - V3SymTable* symp = *it; - UINFO(1,"\t"<ownerp()<nodep()<ownerp()<nodep()<dump(os, indent, true); + m_syms.dump(os,indent); } AstNode* findEntUpward (const string& name) { // Lookup the given string as an identifier, return type of the id, scanning upward - return symCurrentp()->findIdFallback(name); + return symCurrentp()->findIdFallback(name)->nodep(); } void import(AstNode* packagep, const string& id_or_star) { // Import from package::id_or_star to this - V3SymTable* symp = getTable(packagep); + VSymEnt* symp = getTable(packagep); if (!symp) { // Internal problem, because we earlier found pkg to label it an ID__aPACKAGE packagep->v3fatalSrc("Import package not found"); return; @@ -190,18 +188,14 @@ public: } public: // CREATORS - V3ParseSym(AstNetlist* rootp) { + V3ParseSym(AstNetlist* rootp) + : m_syms(rootp) { s_anonNum = 0; // Number of next anonymous object - pushScope(findNewTable(rootp, NULL)); + pushScope(findNewTable(rootp)); m_symTableNextId = NULL; m_symCurrentp = symCurrentp(); - m_symRootp = symCurrentp(); - } - ~V3ParseSym() { - for (SymStack::iterator it = m_symsp.begin(); it != m_symsp.end(); ++it) { - delete (*it); - } } + ~V3ParseSym() {} }; //###################################################################### diff --git a/src/V3SymTable.h b/src/V3SymTable.h index 3b292d17a..81fb8d3a6 100644 --- a/src/V3SymTable.h +++ b/src/V3SymTable.h @@ -28,65 +28,88 @@ #include #include #include +#include #include "V3Global.h" #include "V3Ast.h" +#include "V3File.h" + +class VSymGraph; //###################################################################### // Symbol table -class V3SymTable { +class VSymEnt { // Symbol table that can have a "superior" table for resolving upper references - private: +private: // MEMBERS - typedef std::map IdNameMap; + typedef std::map IdNameMap; IdNameMap m_idNameMap; // Hash of variables by name - AstNode* m_ownerp; // Node that table belongs to - V3SymTable* m_fallbackp; // Table "above" this one in name scope - public: + AstNode* m_nodep; // Node that entry belongs to + VSymEnt* m_fallbackp; // Table "above" this one in name scope, for fallback resolution + VSymEnt* m_parentp; // Table that created this table, dot notation needed to resolve into it + string m_symPrefix; // String to prefix symbols with (for V3LinkDot, unused here) + static int debug() { return 0; } // NOT runtime, too hot of a function +private: + void dumpIterate(ostream& os, const string& indent, int numLevels, const string& searchName) const { + os<first); + } + } + } + +public: // METHODS - V3SymTable(AstNode* ownerp, V3SymTable* upperTablep) { - m_ownerp = ownerp; m_fallbackp = upperTablep; } - V3SymTable() { - m_ownerp = NULL; m_fallbackp = NULL; } - ~V3SymTable() {} - AstNode* ownerp() const { return m_ownerp; } - void insert(const string& name, AstNode* nodep) { - //UINFO(9, " SymInsert "<nodep() + string symPrefix() const { return m_symPrefix; } + void symPrefix(const string& name) { m_symPrefix = name; } + void insert(const string& name, VSymEnt* entp) { + UINFO(9, " SymInsert "<nodep()<v3fatalSrc("Inserting two symbols with same name: "<=9 || V3Error::debugDefault()) dump(cout,"- err-dump: ", 1); + entp->nodep()->v3fatalSrc("Inserting two symbols with same name: "<second = nodep; // Replace + UINFO(9, " SymReinsert "<nodep()<second = entp; // Replace } else { - insert(name,nodep); + insert(name,entp); } } - AstNode* findIdFlat(const string& name) const { + VSymEnt* findIdFlat(const string& name) const { // Find identifier without looking upward through symbol hierarchy - //UINFO(9, " SymFind "< "<<(iter == m_idNameMap.end() ? "NONE" : cvtToStr((void*)(iter->second->nodep())))<second); return NULL; } - AstNode* findIdFallback(const string& name) const { + VSymEnt* findIdFallback(const string& name) const { // Find identifier looking upward through symbol hierarchy // First, scan this begin/end block or module for the name - if (AstNode* nodep = findIdFlat(name)) return nodep; + if (VSymEnt* entp = findIdFlat(name)) return entp; // Then scan the upper begin/end block or module for the name if (m_fallbackp) return m_fallbackp->findIdFallback(name); return NULL; } - bool import(const V3SymTable* srcp, const string& id_or_star) { + bool import(const VSymEnt* srcp, const string& id_or_star) { // Import tokens from source symbol table into this symbol table // Returns true if successful bool any = false; @@ -104,20 +127,79 @@ class V3SymTable { } return any; } - void dump(ostream& os, const string& indent="", bool user4p_is_table=false) const { - if (user4p_is_table) { AstUser4InUse::check(); } - for (IdNameMap::const_iterator it=m_idNameMap.begin(); it!=m_idNameMap.end(); ++it) { - os<first; - for (size_t i=it->first.length(); i<30; ++i) os<<" "; - if (user4p_is_table) { - V3SymTable* belowp = (it->second)->user4p()->castSymTable(); - os<second<dump(os, indent+"+ ", user4p_is_table); - } else { - os<second<second->nodep(); + if (nodep->castCell() + || (nodep->castModule() && nodep->castModule()->isTop())) { + if (scopes != "") scopes += ", "; + scopes += AstNode::prettyName(it->first); } } + cerr<prettyName()<<"': " + < SymStack; + +private: + // MEMBERS + VSymEnt* m_symRootp; // Root symbol table + SymStack m_symsp; // All symbol tables, to cleanup + +protected: + friend class VSymEnt; + void pushNewEnt(VSymEnt* entp) { m_symsp.push_back(entp); } + +public: + VSymEnt* rootp() const { return m_symRootp; } + // Debug + void dump(ostream& os, const string& indent="") { + os<<"SymEnt Dump:\n"; + m_symRootp->dump(os, indent, 9999); + } + void dumpFilePrefixed(const string& nameComment) { + if (v3Global.opt.dumpTree()) { + string filename = v3Global.debugFilename(nameComment)+".txt"; + const auto_ptr logp (V3File::new_ofstream(filename)); + if (logp->fail()) v3fatalSrc("Can't write "<pushNewEnt(this); +} + #endif // guard diff --git a/src/Verilator.cpp b/src/Verilator.cpp index 337e4c3a9..c7b3ac981 100644 --- a/src/Verilator.cpp +++ b/src/Verilator.cpp @@ -108,7 +108,7 @@ void V3Global::clear() { void V3Global::readFiles() { // NODE STATE - // AstNode::user4p() // V3SymTable* Package and typedef symbol names + // AstNode::user4p() // VSymEnt* Package and typedef symbol names AstUser4InUse inuser4; V3InFilter filter (v3Global.opt.pipeFilter()); diff --git a/src/verilog.l b/src/verilog.l index 74d146c8a..8b1513da6 100644 --- a/src/verilog.l +++ b/src/verilog.l @@ -1118,15 +1118,15 @@ int V3ParseImp::lexToken() { // Note above sometimes converts yGLOBAL to a yaID__LEX if (token == yaID__LEX) { AstNode* scp; - if (V3SymTable* look_underp = SYMP->nextId()) { + if (VSymEnt* look_underp = SYMP->nextId()) { if (debugFlex()) { cout<<" lexToken: next id lookup forced under "<findIdFallback(*(yylval.strp)); + scp = look_underp->findIdFallback(*(yylval.strp))->nodep(); // "consume" it. Must set again if want another token under temp scope SYMP->nextId(NULL); } else { UINFO(7," lexToken: find upward "<symCurrentp()<<" for '"<<*(yylval.strp)<<"'"<=9) SYMP->symCurrentp()->dump(cout," -findtree: ",true); - scp = SYMP->symCurrentp()->findIdFallback(*(yylval.strp)); + scp = SYMP->symCurrentp()->findIdFallback(*(yylval.strp))->nodep(); } yylval.scp = scp; if (scp) { diff --git a/src/verilog.y b/src/verilog.y index 1571c53b1..570c9b15c 100644 --- a/src/verilog.y +++ b/src/verilog.y @@ -108,7 +108,7 @@ public: } AstPackage* unitPackage(FileLine* fl) { // Find one made earlier? - AstPackage* pkgp = SYMP->symRootp()->findIdFlat(AstPackage::dollarUnitName())->castPackage(); + AstPackage* pkgp = SYMP->symRootp()->findIdFlat(AstPackage::dollarUnitName())->nodep()->castPackage(); if (!pkgp) { pkgp = new AstPackage(fl, AstPackage::dollarUnitName()); pkgp->inLibrary(true); // packages are always libraries; don't want to make them a "top"