Internals: Merge from struct branch, rework LinkDot symbol table. No functional change intended.
This commit is contained in:
parent
365034d7dd
commit
3ec687a0cf
|
|
@ -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); }
|
||||
|
|
|
|||
|
|
@ -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<V3SymTable*> 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: "<<nodep<<endl);
|
||||
AstCell* upperCellp = m_cellp;
|
||||
V3SymTable* upperVarsp = m_curVarsp;
|
||||
VSymEnt* upperVarsp = m_curVarsp;
|
||||
{
|
||||
m_modp = nodep;
|
||||
if (!m_curVarsp) nodep->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 "<<m_curVarsp<<endl);
|
||||
}
|
||||
// This state must be save/restored in the cell visitor function
|
||||
|
|
@ -280,7 +280,7 @@ private:
|
|||
nodep->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:
|
|||
<<nodeTextType(foundp)<<": "<<nodep->prettyName());
|
||||
} else if (findvarp != nodep) {
|
||||
UINFO(4,"DupVar: "<<nodep<<" ;; "<<foundp<<endl);
|
||||
if (findvarp && findvarp->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: "<<nodep<<" ;; "<<foundp<<endl);
|
||||
if (findvarp && findvarp->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: "<<nodep->prettyName()<<endl
|
||||
<<findvarp->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," "<<nodep<<endl);
|
||||
|
|
@ -452,7 +453,8 @@ private:
|
|||
if (!nodep->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: "<<nodep->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: "<<nodep->prettyName()); }
|
||||
else if (taskp->dpiExport()) {
|
||||
nodep->v3error("Function was already DPI Exported, duplicate not allowed: "<<nodep->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: "<<nodep->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: "<<nodep<<endl);
|
||||
//if (debug()) { nodep->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: "<<nodep->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 #(."<<nodep->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 "<<nodep->path()<<" never declared");
|
||||
|
|
@ -677,9 +679,9 @@ private:
|
|||
|
||||
virtual void visit(AstPackageImport* nodep, AstNUser*) {
|
||||
UINFO(2," Link: "<<nodep<<endl);
|
||||
V3SymTable* srcp = symsFind(nodep->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: "<<nodep->packagep()->prettyName()<<"::"<<nodep->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<V3SymTable*>::iterator it = m_delSymps.begin(); it != m_delSymps.end(); ++it) {
|
||||
delete (*it);
|
||||
}
|
||||
}
|
||||
virtual ~LinkVisitor() {}
|
||||
};
|
||||
|
||||
//######################################################################
|
||||
|
|
|
|||
|
|
@ -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: "<<nodep<<endl);
|
||||
// Use findIdFallback instead of findIdFlat; it doesn't matter for now
|
||||
// but we might support modules-under-modules someday.
|
||||
AstNodeModule* modp = m_mods.findIdFallback(nodep->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: "<<nodep->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: "<<nodep->prettyName()<<endl
|
||||
|
|
@ -308,7 +308,7 @@ private:
|
|||
nodep->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;
|
||||
|
|
|
|||
|
|
@ -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<string,LinkDotBaseVertex*> 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<<V3Error::msgPrefix()<<" Known scopes under '"<<cellName()<<"': "
|
||||
<<scopes<<endl;
|
||||
}
|
||||
if (debug()) {
|
||||
for (NameVtxMap::iterator it = m_nameToVtxMap.begin(); it!=m_nameToVtxMap.end(); ++it) {
|
||||
UINFO(1,"\t\t KnownScope: "<<it->second->name()<<endl);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class LinkDotCellVertex : public LinkDotBaseVertex {
|
||||
// A real point in the hierarchy, corresponding to an instantiated module
|
||||
AstNodeModule* m_modp; // Module
|
||||
AstCell* m_nodep; // Cell creating this vertex **NULL AT TOP**
|
||||
V3SymTable m_syms; // Symbol table of variable/task names for global lookup
|
||||
public:
|
||||
LinkDotCellVertex(V3Graph* graphp, AstCell* nodep)
|
||||
: LinkDotBaseVertex(graphp, ""), m_modp(nodep->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<string,LinkDotCellVertex*> NameScopeMap;
|
||||
typedef std::multimap<string,VSymEnt*> 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__<<": "<<endl);
|
||||
m_forPrearray = forPrearray;
|
||||
m_forScopeCreation = forScopeCreation;
|
||||
|
|
@ -214,84 +94,111 @@ public:
|
|||
bool forScopeCreation() const { return m_forScopeCreation; }
|
||||
|
||||
// METHODS
|
||||
LinkDotCellVertex* insertTopCell(AstNodeModule* nodep, const string& scopename) {
|
||||
private:
|
||||
VSymEnt* findSubcell(VSymEnt* symp, const string& name, const string& altname) {
|
||||
VSymEnt* findp = symp->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 "<<scopename<<" "<<nodep<<endl);
|
||||
LinkDotCellVertex* vxp = new LinkDotCellVertex(&m_graph, nodep);
|
||||
nodep->user1p(vxp);
|
||||
if (forScopeCreation()) m_nameScopeMap.insert(make_pair(scopename, vxp));
|
||||
return vxp;
|
||||
UINFO(9," INSERTtop "<<scopename<<" "<<nodep<<endl);
|
||||
VSymEnt* symp = new VSymEnt(&m_syms, nodep);
|
||||
symp->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 "<<scopename<<" "<<nodep<<endl);
|
||||
LinkDotCellVertex* vxp = new LinkDotCellVertex(&m_graph, nodep);
|
||||
if (nodep->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 "<<scopename<<" above="<<(void*)abovep<<" cells="<<(void*)cellSymp<<" node="<<nodep<<endl);
|
||||
VSymEnt* symp = new VSymEnt(&m_syms, nodep);
|
||||
symp->parentp(abovep);
|
||||
symp->fallbackp(cellSymp);
|
||||
if (nodep->modp()) nodep->modp()->user1p(symp);
|
||||
abovep->reinsert(nodep->origName(), 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);
|
||||
// Duplicates are possible, as until resolve generates might have 2 same cells under an if
|
||||
cellSymp->reinsert(nodep->name(), symp);
|
||||
}
|
||||
if (forScopeCreation()) m_nameScopeMap.insert(make_pair(scopename, vxp));
|
||||
return vxp;
|
||||
if (forScopeCreation()) m_nameScopeMap.insert(make_pair(scopename, symp));
|
||||
return symp;
|
||||
}
|
||||
LinkDotInlineVertex* insertInline(LinkDotBaseVertex* abovep, LinkDotCellVertex* cellVxp,
|
||||
AstCellInline* nodep, const string& basename) {
|
||||
UINFO(9," INSERTcinl "<<nodep<<endl);
|
||||
LinkDotInlineVertex* vxp = new LinkDotInlineVertex(&m_graph, nodep, cellVxp, basename);
|
||||
abovep->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 "<<basename<<" above="<<(void*)abovep<<" cells="<<(void*)cellSymp<<" node="<<nodep<<endl);
|
||||
VSymEnt* symp = new VSymEnt(&m_syms, nodep);
|
||||
symp->parentp(abovep);
|
||||
symp->fallbackp(cellSymp);
|
||||
symp->symPrefix(nodep->name()+"__DOT__");
|
||||
abovep->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 "<<nodep<<endl);
|
||||
LinkDotBeginVertex* vxp = new LinkDotBeginVertex(&m_graph, nodep, cellVxp);
|
||||
abovep->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="<<nodep<<endl);
|
||||
VSymEnt* symp = new VSymEnt(&m_syms, nodep);
|
||||
symp->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 "<<name<<" "<<nodep<<endl);
|
||||
abovep->syms().insert(name, nodep);
|
||||
void insertSym(VSymEnt* abovep, const string& name, AstNode* nodep) {
|
||||
UINFO(9," INSERTsym name='"<<name<<"' above="<<(void*)abovep<<" node="<<nodep<<endl);
|
||||
// We don't remember the ent associated with each node, because we need a unique scope entry for each instantiation
|
||||
VSymEnt* symp = new VSymEnt(&m_syms, nodep);
|
||||
abovep->insert(name, symp);
|
||||
}
|
||||
bool existsModScope(AstNodeModule* nodep) {
|
||||
return nodep->user1p()!=NULL;
|
||||
}
|
||||
LinkDotCellVertex* findModScope(AstNodeModule* nodep) {
|
||||
LinkDotCellVertex* vxp = (LinkDotCellVertex*)(nodep->user1p());
|
||||
if (!vxp) nodep->v3fatalSrc("Module never assigned a vertex");
|
||||
return vxp;
|
||||
VSymEnt* findModScope(AstNodeModule* nodep) {
|
||||
VSymEnt* symp = nodep->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<LinkDotBaseVertex*>(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 "<<dotname<<endl);
|
||||
bool firstId = true;
|
||||
string leftname = dotname;
|
||||
okVxp = cellVxp; // So can list bad scopes
|
||||
okSymp = cellSymp; // So can list bad scopes
|
||||
while (leftname != "") { // foreach dotted part of xref name
|
||||
string::size_type pos;
|
||||
string ident;
|
||||
|
|
@ -303,7 +210,7 @@ public:
|
|||
leftname = "";
|
||||
}
|
||||
baddot = ident; // So user can see where they botched it
|
||||
okVxp = cellVxp;
|
||||
okSymp = cellSymp;
|
||||
string altIdent = "";
|
||||
if (m_forPrearray) {
|
||||
// Cell foo__[array] before we've expanded arrays is just foo.
|
||||
|
|
@ -311,60 +218,61 @@ public:
|
|||
altIdent = ident.substr(0,pos);
|
||||
}
|
||||
}
|
||||
UINFO(8," id "<<ident<<" left "<<leftname<<" at "<<cellVxp<<endl);
|
||||
UINFO(8," id "<<ident<<" left "<<leftname<<" at "<<cellSymp<<endl);
|
||||
// Spec says; Look at exiting module (cellnames then modname),
|
||||
// then look up (inst name or modname)
|
||||
if (firstId) {
|
||||
// Check this module - subcellnames
|
||||
if (LinkDotBaseVertex* findVxp = cellVxp->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 "<<cellVxp<<endl);
|
||||
if (cellVxp->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 "<<cellSymp<<endl);
|
||||
if ((cellp && cellp->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 "<<dotname
|
||||
<<((cellVxp->symPrefix()=="") ? "" : " as ")
|
||||
<<((cellVxp->symPrefix()=="") ? "" : cellVxp->symPrefix()+dotname)
|
||||
<<" at "<<cellVxp
|
||||
<<((cellSymp->symPrefix()=="") ? "" : " as ")
|
||||
<<((cellSymp->symPrefix()=="") ? "" : cellSymp->symPrefix()+dotname)
|
||||
<<" at "<<cellSymp
|
||||
<<endl);
|
||||
AstNode* nodep = cellVxp->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: "<<topmodp<<endl);
|
||||
m_scope = "TOP";
|
||||
m_cellVxp = m_statep->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," "<<nodep<<endl);
|
||||
if (!m_cellVxp) {
|
||||
if (!m_cellSymp) {
|
||||
// Will be optimized away later
|
||||
UINFO(5, "Module not under any CELL or top - dead module\n");
|
||||
} else {
|
||||
|
|
@ -431,35 +339,35 @@ private:
|
|||
// Recurse in, preserving state
|
||||
string oldscope = m_scope;
|
||||
AstBegin* oldbeginp = m_beginp;
|
||||
LinkDotCellVertex* oldVxp = m_cellVxp;
|
||||
LinkDotBaseVertex* oldInlineVxp = m_inlineVxp;
|
||||
VSymEnt* oldSymp = m_cellSymp;
|
||||
VSymEnt* oldInlineSymp = m_inlineSymp;
|
||||
// Where do we add it?
|
||||
LinkDotBaseVertex* aboveVxp = m_inlineVxp;
|
||||
VSymEnt* aboveSymp = m_inlineSymp;
|
||||
string origname = AstNode::dedotName(nodep->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 '"<<baddot<<"' in: "<<nodep->prettyName());
|
||||
VSymEnt* okSymp;
|
||||
aboveSymp = m_statep->findDotted(aboveSymp, scope, baddot, okSymp);
|
||||
if (!aboveSymp) nodep->v3fatalSrc("Can't find cell insertion point at '"<<baddot<<"' in: "<<nodep->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 "<<m_scope<<" is "<<nodep<<endl);
|
||||
LinkDotBaseVertex* aboveVxp = m_inlineVxp;
|
||||
VSymEnt* aboveSymp = m_inlineSymp;
|
||||
// If baz__DOT__foo__DOT__bar, we need to find baz__DOT__foo and add bar to it.
|
||||
string dottedname = nodep->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 '"<<baddot<<"' in: "<<nodep->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 '"<<baddot<<"' in: "<<nodep->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," "<<nodep<<endl);
|
||||
AstBegin* oldbegin = m_beginp;
|
||||
LinkDotBaseVertex* oldVxp = m_inlineVxp;
|
||||
VSymEnt* oldSymp = m_inlineSymp;
|
||||
{
|
||||
m_beginp = nodep;
|
||||
// We don't pickup variables (as not supported yet), but do need to find cells
|
||||
m_inlineVxp = m_statep->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: "<<nodep<<endl);
|
||||
}
|
||||
|
|
@ -521,7 +429,8 @@ public:
|
|||
// CONSTUCTORS
|
||||
LinkDotFindVisitor(AstNetlist* rootp, LinkDotState* statep) {
|
||||
UINFO(4,__FUNCTION__<<": "<<endl);
|
||||
m_cellVxp = NULL;
|
||||
m_cellSymp = NULL;
|
||||
m_inlineSymp = NULL;
|
||||
m_statep = statep;
|
||||
m_beginp = NULL;
|
||||
//
|
||||
|
|
@ -536,7 +445,7 @@ class LinkDotScopeVisitor : public AstNVisitor {
|
|||
private:
|
||||
// STATE
|
||||
LinkDotState* m_statep; // State to pass between visitors, including symbol table
|
||||
LinkDotCellVertex* m_cellVxp; // Vertex for current module
|
||||
VSymEnt* m_cellSymp; // Symbol entry for current module
|
||||
|
||||
int debug() { return LinkDotState::debug(); }
|
||||
|
||||
|
|
@ -546,17 +455,17 @@ private:
|
|||
if (!m_statep->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__<<": "<<endl);
|
||||
m_cellVxp = NULL;
|
||||
m_cellSymp = NULL;
|
||||
m_statep = statep;
|
||||
//
|
||||
rootp->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," "<<nodep<<endl);
|
||||
if (!m_statep->existsModScope(nodep)) {
|
||||
UINFO(5,"Dead module for "<<nodep<<endl);
|
||||
m_cellVxp = NULL;
|
||||
m_cellSymp = NULL;
|
||||
} else {
|
||||
m_cellVxp = m_statep->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," "<<nodep<<endl);
|
||||
m_cellVxp = m_statep->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," "<<nodep<<endl);
|
||||
if (!m_cellVxp) {
|
||||
if (!m_cellSymp) {
|
||||
UINFO(9,"Dead module for "<<nodep<<endl);
|
||||
nodep->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 '"<<baddot<<"' in: "<<nodep->inlinedDots());
|
||||
dotSymp = m_statep->findDotted(dotSymp, inl, baddot, okSymp);
|
||||
if (!dotSymp) {
|
||||
m_statep->preErrorDump();
|
||||
nodep->v3fatalSrc("Couldn't resolve inlined scope '"<<baddot<<"' in: "<<nodep->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 "<<nodep<<endl); // Also prints varp
|
||||
if (!nodep->varp()) {
|
||||
m_statep->preErrorDump();
|
||||
nodep->v3error("Can't find definition of '"<<baddot<<"' in dotted signal: "<<nodep->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 '"<<baddot<<"' in dotted signal: "<<nodep->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 "<<vscp<<endl); // Also prints taskp
|
||||
|
|
@ -682,7 +596,7 @@ private:
|
|||
UINFO(8," "<<nodep<<endl);
|
||||
if (nodep->packagep()) {
|
||||
// References into packages don't care about cell hierarchy.
|
||||
} else if (!m_cellVxp) {
|
||||
} else if (!m_cellSymp) {
|
||||
UINFO(9,"Dead module for "<<nodep<<endl);
|
||||
nodep->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 "<<inl<<endl);
|
||||
dotVxp = m_statep->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 '"<<baddot<<"' in: "<<nodep->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 "<<nodep<<endl); // Also prints taskp
|
||||
if (!nodep->taskp()) {
|
||||
m_statep->preErrorDump();
|
||||
nodep->v3error("Can't find definition of '"<<baddot<<"' in dotted task/function: "<<nodep->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__<<": "<<endl);
|
||||
m_statep = statep;
|
||||
m_cellVxp = NULL;
|
||||
m_cellSymp = NULL;
|
||||
//
|
||||
rootp->accept(*this);
|
||||
}
|
||||
|
|
@ -735,13 +651,15 @@ public:
|
|||
|
||||
void V3LinkDot::linkDotGuts(AstNetlist* rootp, bool prearray, bool scoped) {
|
||||
UINFO(2,__FUNCTION__<<": "<<endl);
|
||||
if (LinkDotState::debug()>=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);
|
||||
|
|
|
|||
|
|
@ -88,34 +88,32 @@ struct V3ParseBisonYYSType {
|
|||
|
||||
class V3ParseSym {
|
||||
// TYPES
|
||||
typedef vector<V3SymTable*> SymStack;
|
||||
typedef vector<VSymEnt*> 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 "<<symCurrentp()->ownerp()->prettyTypeName()
|
||||
nodep->v3fatalSrc("Symbols suggest ending "<<symCurrentp()->nodep()->prettyTypeName()
|
||||
<<" but parser thinks ending "<<nodep->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"<<symp->ownerp()<<endl);
|
||||
VSymEnt* symp = *it;
|
||||
UINFO(1,"\t"<<symp->nodep()<<endl);
|
||||
}
|
||||
UINFO(1,"ParseSym Current: "<<symCurrentp()->ownerp()<<endl);
|
||||
UINFO(1,"ParseSym Current: "<<symCurrentp()->nodep()<<endl);
|
||||
}
|
||||
void dump(ostream& os, const string& indent="") {
|
||||
os<<"ParseSym Dump:\n";
|
||||
m_sympStack[0]->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() {}
|
||||
};
|
||||
|
||||
//######################################################################
|
||||
|
|
|
|||
154
src/V3SymTable.h
154
src/V3SymTable.h
|
|
@ -28,65 +28,88 @@
|
|||
#include <unistd.h>
|
||||
#include <map>
|
||||
#include <iomanip>
|
||||
#include <memory>
|
||||
|
||||
#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<string,AstNode*> IdNameMap;
|
||||
typedef std::map<string,VSymEnt*> 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<<indent<<left<<setw(30)<<searchName<<setw(0)<<right;
|
||||
os<<" "<<setw(16)<<(void*)(this)<<setw(0);
|
||||
os<<" n="<<nodep();
|
||||
os<<endl;
|
||||
for (IdNameMap::const_iterator it=m_idNameMap.begin(); it!=m_idNameMap.end(); ++it) {
|
||||
if (numLevels >= 1) {
|
||||
it->second->dumpIterate(os, indent+"+ ", numLevels-1, it->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 "<<this<<" '"<<name<<"' "<<nodep<<endl);
|
||||
VSymEnt(VSymGraph* graphp, AstNode* nodep); // Below
|
||||
~VSymEnt() {}
|
||||
void fallbackp(VSymEnt* entp) { m_fallbackp = entp; }
|
||||
void parentp(VSymEnt* entp) { m_parentp = entp; }
|
||||
VSymEnt* parentp() const { return m_parentp; }
|
||||
AstNode* nodep() const { if (!this) return NULL; else return m_nodep; } // null check so can call .findId(...)->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 "<<this<<" '"<<name<<"' "<<(void*)entp<<" "<<entp->nodep()<<endl);
|
||||
if (m_idNameMap.find(name) != m_idNameMap.end()) {
|
||||
if (!V3Error::errorCount()) { // Else may have just reported warning
|
||||
nodep->v3fatalSrc("Inserting two symbols with same name: "<<name<<endl);
|
||||
if (debug()>=9 || V3Error::debugDefault()) dump(cout,"- err-dump: ", 1);
|
||||
entp->nodep()->v3fatalSrc("Inserting two symbols with same name: "<<name<<endl);
|
||||
}
|
||||
} else {
|
||||
m_idNameMap.insert(make_pair(name, nodep));
|
||||
m_idNameMap.insert(make_pair(name, entp));
|
||||
}
|
||||
}
|
||||
void reinsert(const string& name, AstNode* nodep) {
|
||||
void reinsert(const string& name, VSymEnt* entp) {
|
||||
IdNameMap::iterator it = m_idNameMap.find(name);
|
||||
if (it != m_idNameMap.end()) {
|
||||
//UINFO(9, " SymReinsert "<<this<<" '"<<name<<"' "<<nodep<<endl);
|
||||
it->second = nodep; // Replace
|
||||
UINFO(9, " SymReinsert "<<this<<" '"<<name<<"' "<<(void*)entp<<" "<<entp->nodep()<<endl);
|
||||
it->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 "<<this<<" '"<<name<<"' "<<endl);
|
||||
// First, scan this begin/end block or module for the name
|
||||
IdNameMap::const_iterator iter = m_idNameMap.find(name);
|
||||
UINFO(9, " SymFind "<<this<<" '"<<name<<"' -> "<<(iter == m_idNameMap.end() ? "NONE" : cvtToStr((void*)(iter->second->nodep())))<<endl);
|
||||
if (iter != m_idNameMap.end()) return (iter->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<<indent<<it->first;
|
||||
for (size_t i=it->first.length(); i<30; ++i) os<<" ";
|
||||
if (user4p_is_table) {
|
||||
V3SymTable* belowp = (it->second)->user4p()->castSymTable();
|
||||
os<<setw(10)<<(void*)(belowp)<<setw(0)<<" "<<it->second<<endl;
|
||||
if (belowp) belowp->dump(os, indent+"+ ", user4p_is_table);
|
||||
} else {
|
||||
os<<it->second<<endl;
|
||||
void cellErrorScopes(AstNode* lookp) {
|
||||
string scopes;
|
||||
for (IdNameMap::iterator it = m_idNameMap.begin(); it!=m_idNameMap.end(); ++it) {
|
||||
AstNode* nodep = it->second->nodep();
|
||||
if (nodep->castCell()
|
||||
|| (nodep->castModule() && nodep->castModule()->isTop())) {
|
||||
if (scopes != "") scopes += ", ";
|
||||
scopes += AstNode::prettyName(it->first);
|
||||
}
|
||||
}
|
||||
cerr<<V3Error::msgPrefix()<<" Known scopes under '"<<lookp->prettyName()<<"': "
|
||||
<<scopes<<endl;
|
||||
if (debug()) dump(cerr,"\t\t KnownScope: ", 1);
|
||||
}
|
||||
void dump(ostream& os, const string& indent="", int numLevels=1) const {
|
||||
dumpIterate(os,indent,numLevels,"TOP");
|
||||
}
|
||||
};
|
||||
|
||||
//######################################################################
|
||||
// Symbol tables
|
||||
|
||||
class VSymGraph {
|
||||
// Collection of symbol tables
|
||||
// TYPES
|
||||
typedef vector<VSymEnt*> 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<ofstream> logp (V3File::new_ofstream(filename));
|
||||
if (logp->fail()) v3fatalSrc("Can't write "<<filename);
|
||||
dump(*logp, "");
|
||||
}
|
||||
}
|
||||
public:
|
||||
// CREATORS
|
||||
VSymGraph(AstNetlist* nodep) {
|
||||
m_symRootp = new VSymEnt(this, nodep);
|
||||
}
|
||||
~VSymGraph() {
|
||||
for (SymStack::iterator it = m_symsp.begin(); it != m_symsp.end(); ++it) {
|
||||
delete (*it);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
//######################################################################
|
||||
|
||||
inline VSymEnt::VSymEnt(VSymGraph* m_graphp, AstNode* nodep)
|
||||
: m_nodep(nodep) {
|
||||
// No argument to set fallbackp, as generally it's wrong to set it in the new call,
|
||||
// Instead it needs to be set on a "findOrNew()" return, as it may have been new'ed
|
||||
// by an earlier search insertion.
|
||||
m_fallbackp = NULL;
|
||||
m_parentp = NULL;
|
||||
m_graphp->pushNewEnt(this);
|
||||
}
|
||||
|
||||
#endif // guard
|
||||
|
|
|
|||
|
|
@ -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());
|
||||
|
|
|
|||
|
|
@ -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 "<<look_underp<<endl; }
|
||||
scp = look_underp->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 "<<SYMP->symCurrentp()<<" for '"<<*(yylval.strp)<<"'"<<endl);
|
||||
//if (debug()>=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) {
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
Loading…
Reference in New Issue