forked from github/verilator
Internals: Move initial resolution to V3LinkParse. No functional change intended.
This commit is contained in:
parent
97963fb8c9
commit
09aa9f87d8
@ -78,9 +78,7 @@ private:
|
||||
V3SymTable* 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_inAlways; // Inside an always
|
||||
bool m_inGenerate; // Inside a generate
|
||||
AstNodeModule* m_valueModp; // If set, move AstVar->valuep() initial values to this module
|
||||
vector<V3SymTable*> m_delSymps; // Symbol tables to delete
|
||||
|
||||
static int debug() {
|
||||
@ -233,7 +231,6 @@ private:
|
||||
V3SymTable* upperVarsp = m_curVarsp;
|
||||
{
|
||||
m_modp = nodep;
|
||||
m_valueModp = nodep;
|
||||
if (!m_curVarsp) nodep->v3fatalSrc("NULL");
|
||||
if (nodep->castPackage()) m_packagep = nodep->castPackage();
|
||||
if (m_packagep && m_packagep->isDollarUnit()) { // $unit goes on "top"
|
||||
@ -253,7 +250,6 @@ private:
|
||||
nodep->iterateChildren(*this);
|
||||
// Prep for next
|
||||
m_modp = NULL;
|
||||
m_valueModp = NULL;
|
||||
m_packagep = NULL;
|
||||
}
|
||||
m_curVarsp = upperVarsp;
|
||||
@ -336,26 +332,6 @@ private:
|
||||
if (nodep->isIO() && !m_ftaskp && !nodep->user2()) {
|
||||
nodep->v3error("Input/output/inout does not appear in port list: "<<nodep->prettyName());
|
||||
}
|
||||
// temporaries under an always aren't expected to be blocking
|
||||
if (m_inAlways) nodep->fileline()->modifyWarnOff(V3ErrorCode::BLKSEQ, true);
|
||||
if (nodep->valuep()) {
|
||||
// A variable with a = value can be three things:
|
||||
FileLine* fl = nodep->valuep()->fileline();
|
||||
// 1. Parameters and function inputs: It's a default to use if not overridden
|
||||
if (nodep->isParam() || nodep->isInOnly()) {
|
||||
// 2. Under modules, it's an initial value to be loaded at time 0 via an AstInitial
|
||||
} else if (m_valueModp) {
|
||||
nodep->addNextHere
|
||||
(new AstInitial (fl, new AstAssign (fl,
|
||||
new AstVarRef(fl, nodep, true),
|
||||
nodep->valuep()->unlinkFrBack())));
|
||||
// 3. Under blocks, it's an initial value to be under an assign
|
||||
} else {
|
||||
nodep->addNextHere
|
||||
(new AstAssign (fl, new AstVarRef(fl, nodep, true),
|
||||
nodep->valuep()->unlinkFrBack()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
virtual void visit(AstVarRef* nodep, AstNUser*) {
|
||||
@ -409,10 +385,7 @@ private:
|
||||
if (!m_curVarsp) nodep->v3fatalSrc("Function/Task not under module??\n");
|
||||
// Remember the existing symbol table scope
|
||||
V3SymTable* upperVarsp = m_curVarsp;
|
||||
AstNodeModule* upperValueModp = m_valueModp;
|
||||
{
|
||||
m_valueModp = NULL;
|
||||
|
||||
// Create symbol table for the task's vars
|
||||
m_curVarsp = symsFindNew(nodep, upperVarsp);
|
||||
|
||||
@ -440,7 +413,6 @@ private:
|
||||
m_ftaskp = NULL;
|
||||
}
|
||||
m_curVarsp = upperVarsp;
|
||||
m_valueModp = upperValueModp;
|
||||
if (m_idState==ID_FIND) {
|
||||
findAndInsertAndCheck(nodep, nodep->name());
|
||||
}
|
||||
@ -717,28 +689,6 @@ private:
|
||||
nodep->unlinkFrBack()->deleteTree(); nodep=NULL;
|
||||
}
|
||||
|
||||
void visitIterateNoValueMod(AstNode* nodep) {
|
||||
// Iterate a node which shouldn't have any local variables moved to an Initial
|
||||
AstNodeModule* upperValueModp = m_valueModp;
|
||||
m_valueModp = NULL;
|
||||
nodep->iterateChildren(*this);
|
||||
m_valueModp = upperValueModp;
|
||||
}
|
||||
virtual void visit(AstInitial* nodep, AstNUser*) {
|
||||
visitIterateNoValueMod(nodep);
|
||||
}
|
||||
virtual void visit(AstFinal* nodep, AstNUser*) {
|
||||
visitIterateNoValueMod(nodep);
|
||||
}
|
||||
virtual void visit(AstAlways* nodep, AstNUser*) {
|
||||
m_inAlways = true;
|
||||
visitIterateNoValueMod(nodep);
|
||||
m_inAlways = false;
|
||||
}
|
||||
virtual void visit(AstPslCover* nodep, AstNUser*) {
|
||||
visitIterateNoValueMod(nodep);
|
||||
}
|
||||
|
||||
virtual void visit(AstNode* nodep, AstNUser*) {
|
||||
// Default: Just iterate
|
||||
nodep->iterateChildren(*this);
|
||||
@ -756,9 +706,7 @@ public:
|
||||
m_paramNum = 0;
|
||||
m_beginNum = 0;
|
||||
m_modBeginNum = 0;
|
||||
m_inAlways = false;
|
||||
m_inGenerate = false;
|
||||
m_valueModp = NULL;
|
||||
//
|
||||
rootp->accept(*this);
|
||||
}
|
||||
|
@ -64,6 +64,9 @@ private:
|
||||
AstVar* m_varp; // Variable we're under
|
||||
ImplTypedefMap m_implTypedef; // Created typedefs for each <container,name>
|
||||
FileLineSet m_filelines; // Filelines that have been seen
|
||||
bool m_inAlways; // Inside an always
|
||||
bool m_inGenerate; // Inside a generate
|
||||
AstNodeModule* m_valueModp; // If set, move AstVar->valuep() initial values to this module
|
||||
|
||||
// METHODS
|
||||
static int debug() {
|
||||
@ -111,7 +114,10 @@ private:
|
||||
nodep->dotted(m_dotText);
|
||||
nodep->namep()->unlinkFrBack()->deleteTree(); m_baseTextp=NULL;
|
||||
}
|
||||
AstNodeModule* upperValueModp = m_valueModp;
|
||||
m_valueModp = NULL;
|
||||
nodep->iterateChildren(*this);
|
||||
m_valueModp = upperValueModp;
|
||||
}
|
||||
}
|
||||
virtual void visit(AstParseRef* nodep, AstNUser*) {
|
||||
@ -279,6 +285,26 @@ private:
|
||||
m_varp = nodep;
|
||||
nodep->iterateChildren(*this);
|
||||
m_varp = NULL;
|
||||
// temporaries under an always aren't expected to be blocking
|
||||
if (m_inAlways) nodep->fileline()->modifyWarnOff(V3ErrorCode::BLKSEQ, true);
|
||||
if (nodep->valuep()) {
|
||||
// A variable with an = value can be three things:
|
||||
FileLine* fl = nodep->valuep()->fileline();
|
||||
// 1. Parameters and function inputs: It's a default to use if not overridden
|
||||
if (nodep->isParam() || nodep->isInOnly()) {
|
||||
} // 2. Under modules, it's an initial value to be loaded at time 0 via an AstInitial
|
||||
else if (m_valueModp) {
|
||||
nodep->addNextHere
|
||||
(new AstInitial
|
||||
(fl, new AstAssign (fl, new AstVarRef(fl, nodep->name(), true),
|
||||
nodep->valuep()->unlinkFrBack())));
|
||||
} // 3. Under blocks, it's an initial value to be under an assign
|
||||
else {
|
||||
nodep->addNextHere
|
||||
(new AstAssign (fl, new AstVarRef(fl, nodep->name(), true),
|
||||
nodep->valuep()->unlinkFrBack()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
virtual void visit(AstAttrOf* nodep, AstNUser*) {
|
||||
@ -389,6 +415,40 @@ private:
|
||||
nodep->unlinkFrBack()->deleteTree();
|
||||
}
|
||||
|
||||
virtual void visit(AstNodeModule* nodep, AstNUser*) {
|
||||
// Module: Create sim table for entire module and iterate
|
||||
cleanFileline(nodep);
|
||||
checkExpected(nodep); // So we detect node types we forgot to list here
|
||||
//
|
||||
m_valueModp = nodep;
|
||||
nodep->iterateChildren(*this);
|
||||
m_valueModp = NULL;
|
||||
}
|
||||
void visitIterateNoValueMod(AstNode* nodep) {
|
||||
// Iterate a node which shouldn't have any local variables moved to an Initial
|
||||
cleanFileline(nodep);
|
||||
checkExpected(nodep); // So we detect node types we forgot to list here
|
||||
//
|
||||
AstNodeModule* upperValueModp = m_valueModp;
|
||||
m_valueModp = NULL;
|
||||
nodep->iterateChildren(*this);
|
||||
m_valueModp = upperValueModp;
|
||||
}
|
||||
virtual void visit(AstInitial* nodep, AstNUser*) {
|
||||
visitIterateNoValueMod(nodep);
|
||||
}
|
||||
virtual void visit(AstFinal* nodep, AstNUser*) {
|
||||
visitIterateNoValueMod(nodep);
|
||||
}
|
||||
virtual void visit(AstAlways* nodep, AstNUser*) {
|
||||
m_inAlways = true;
|
||||
visitIterateNoValueMod(nodep);
|
||||
m_inAlways = false;
|
||||
}
|
||||
virtual void visit(AstPslCover* nodep, AstNUser*) {
|
||||
visitIterateNoValueMod(nodep);
|
||||
}
|
||||
|
||||
virtual void visit(AstNode* nodep, AstNUser*) {
|
||||
// Default: Just iterate
|
||||
cleanFileline(nodep);
|
||||
@ -403,6 +463,9 @@ public:
|
||||
m_exp = AstParseRefExp::PX_NONE;
|
||||
m_baseTextp = NULL;
|
||||
m_varp = NULL;
|
||||
m_inAlways = false;
|
||||
m_inGenerate = false;
|
||||
m_valueModp = NULL;
|
||||
rootp->accept(*this);
|
||||
}
|
||||
virtual ~LinkParseVisitor() {}
|
||||
|
Loading…
Reference in New Issue
Block a user