From 4360fe492e0a4cd2d212a9b66e3edd337a0f00e3 Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Thu, 21 Jan 2010 20:08:45 -0500 Subject: [PATCH] Fix initial values for local variables, bug210 --- src/V3Link.cpp | 46 ++++++++++++++++++++++++++++++++++++ src/verilog.y | 18 +++++--------- test_regress/t/t_var_local.v | 14 +++++++++++ 3 files changed, 66 insertions(+), 12 deletions(-) diff --git a/src/V3Link.cpp b/src/V3Link.cpp index 75a0a57bb..216c3188f 100644 --- a/src/V3Link.cpp +++ b/src/V3Link.cpp @@ -77,6 +77,7 @@ private: 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 + AstNodeModule* m_valueModp; // If set, move AstVar->valuep() initial values to this module vector m_delSymps; // Symbol tables to delete static int debug() { @@ -223,6 +224,7 @@ 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" @@ -242,6 +244,7 @@ private: nodep->iterateChildren(*this); // Prep for next m_modp = NULL; + m_valueModp = NULL; m_packagep = NULL; } m_curVarsp = upperVarsp; @@ -314,6 +317,24 @@ private: if (nodep->isIO() && !m_ftaskp && !nodep->user2()) { nodep->v3error("Input/output/inout does not appear in port list: "<prettyName()); } + 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*) { @@ -367,7 +388,10 @@ 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); @@ -395,6 +419,7 @@ private: m_ftaskp = NULL; } m_curVarsp = upperVarsp; + m_valueModp = upperValueModp; if (m_idState==ID_FIND) { findAndInsertAndCheck(nodep, nodep->name()); } @@ -660,6 +685,26 @@ 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*) { + visitIterateNoValueMod(nodep); + } + virtual void visit(AstPslCover* nodep, AstNUser*) { + visitIterateNoValueMod(nodep); + } + virtual void visit(AstNode* nodep, AstNUser*) { // Default: Just iterate nodep->iterateChildren(*this); @@ -678,6 +723,7 @@ public: m_beginNum = 0; m_modBeginNum = 0; m_inGenerate = false; + m_valueModp = NULL; // rootp->accept(*this); } diff --git a/src/verilog.y b/src/verilog.y index 88c0f670a..c28bf9a11 100644 --- a/src/verilog.y +++ b/src/verilog.y @@ -96,11 +96,6 @@ public: nodep->addNext(new AstStop(fileline)); return nodep; } - AstNode* newVarInit(FileLine* fileline, AstNode* varp, AstNode* initp) { - return new AstInitial(fileline, new AstAssign(fileline, - new AstVarRef(fileline, varp->name(),true), - initp)); - } void setDType(AstNodeDType* dtypep) { if (m_varDTypep) { m_varDTypep->deleteTree(); m_varDTypep=NULL; } // It was cloned, so this is safe. m_varDTypep = dtypep; @@ -817,13 +812,13 @@ port: // ==IEEE: port { $$=$2; /*VARDTYPE-same*/ $$->addNextNull(VARDONEP($$,$3,$4)); } // | portDirNetE data_type portSig variable_dimensionListE sigAttrListE '=' constExpr - { $$=$3; VARDTYPE($2); $$->addNextNull(VARDONEP($$,$4,$5)); $$->addNextNull(GRAMMARP->newVarInit($6,$$,$7)); } + { $$=$3; VARDTYPE($2); AstVar* vp=VARDONEP($$,$4,$5); $$->addNextNull(vp); vp->valuep($7); } | portDirNetE yVAR data_type portSig variable_dimensionListE sigAttrListE '=' constExpr - { $$=$3; VARDTYPE($3); $$->addNextNull(VARDONEP($$,$5,$6)); $$->addNextNull(GRAMMARP->newVarInit($7,$$,$8)); } + { $$=$3; VARDTYPE($3); AstVar* vp=VARDONEP($$,$5,$6); $$->addNextNull(vp); vp->valuep($8); } | portDirNetE yVAR implicit_typeE portSig variable_dimensionListE sigAttrListE '=' constExpr - { $$=$3; VARDTYPE($3); $$->addNextNull(VARDONEP($$,$5,$6)); $$->addNextNull(GRAMMARP->newVarInit($7,$$,$8)); } + { $$=$3; VARDTYPE($3); AstVar* vp=VARDONEP($$,$5,$6); $$->addNextNull(vp); vp->valuep($8); } | portDirNetE /*implicit*/ portSig variable_dimensionListE sigAttrListE '=' constExpr - { $$=$3; /*VARDTYPE-same*/ $$->addNextNull(VARDONEP($$,$3,$4)); $$->addNextNull(GRAMMARP->newVarInit($5,$$,$6)); } + { $$=$3; /*VARDTYPE-same*/ AstVar* vp=VARDONEP($$,$3,$4); $$->addNextNull(vp); vp->valuep($6); } ; portDirNetE: // IEEE: part of port, optional net type and/or direction @@ -1115,8 +1110,7 @@ variable_decl_assignment: // ==IEEE: variable_decl_assignment id variable_dimensionListE sigAttrListE { $$ = VARDONEA(*$1,$2,$3); } | id variable_dimensionListE sigAttrListE '=' variable_declExpr - { $$ = VARDONEA(*$1,$2,$3); - $$->addNext(new AstInitial($4,new AstAssign($4, new AstVarRef($4, *$1, true), $5))); } + { $$ = VARDONEA(*$1,$2,$3); $$->valuep($5); } | idSVKwd { $$ = NULL; } // // // IEEE: "dynamic_array_variable_identifier '[' ']' [ '=' dynamic_array_new ]" @@ -2195,7 +2189,7 @@ tf_item_declarationVerilator: // Verilator extensions tf_port_listE: // IEEE: tf_port_list + empty // // Empty covered by tf_port_item {VARRESET_LIST(UNKNOWN); VARIO(INPUT); } - tf_port_listList { $$ = $2; VARRESET_NONLIST(UNKNOWN); } + tf_port_listList { $$ = $2; VARRESET_NONLIST(UNKNOWN); } ; tf_port_listList: // IEEE: part of tf_port_list diff --git a/test_regress/t/t_var_local.v b/test_regress/t/t_var_local.v index be98098b4..543bf1a8d 100644 --- a/test_regress/t/t_var_local.v +++ b/test_regress/t/t_var_local.v @@ -6,20 +6,32 @@ module t; integer top; + integer top_assign=1; + + task automatic tsk; + integer task_assign = 1; + if (task_assign != 1) $stop; + task_assign = 2; + if (task_assign != 2) $stop; + endtask initial begin begin : a integer lower; + integer lower_assign=1; lower = 1; top = 1; if (lower != 1) $stop; + if (lower_assign != 1) $stop; begin : aa integer lev2; lev2 = 1; lower = 2; + lower_assign = 2; top = 2; end if (lower != 2) $stop; + if (lower_assign != 2) $stop; end begin : b integer lower; @@ -30,6 +42,8 @@ module t; end end end + tsk; + tsk; // Second time to insure we reinit the initial value $write("*-* All Finished *-*\n"); $finish; end