Fix initial values for local variables, bug210

This commit is contained in:
Wilson Snyder 2010-01-21 20:08:45 -05:00
parent 295faf726b
commit 4360fe492e
3 changed files with 66 additions and 12 deletions

View File

@ -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<V3SymTable*> 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: "<<nodep->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);
}

View File

@ -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<nodep>: // ==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<varp>: // ==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<nodep>: // Verilator extensions
tf_port_listE<nodep>: // 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<nodep>: // IEEE: part of tf_port_list

View File

@ -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