diff --git a/src/V3Link.cpp b/src/V3Link.cpp index 346c57829..313738c94 100644 --- a/src/V3Link.cpp +++ b/src/V3Link.cpp @@ -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 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: "<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); } diff --git a/src/V3LinkParse.cpp b/src/V3LinkParse.cpp index d53f3d8ea..9389e8d91 100644 --- a/src/V3LinkParse.cpp +++ b/src/V3LinkParse.cpp @@ -64,6 +64,9 @@ private: AstVar* m_varp; // Variable we're under ImplTypedefMap m_implTypedef; // Created typedefs for each 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() {}