diff --git a/Changes b/Changes index faa8203bd..16eafe9d5 100644 --- a/Changes +++ b/Changes @@ -8,6 +8,8 @@ indicates the contributor was also the author of the fix; Thanks! **** Suppress VARHIDDEN on dpi import arguments. [Ruben Diez] +**** Support "generate for (genvar i=0; ...". [David Kravitz] + **** Fix dpi exports with > 32 bit but < 64 bit args, bug423. [Chandan Egbert] **** Fix array of instantiations with sub-range output, bug414. [Jeremy Bennett] diff --git a/src/V3AstNodes.cpp b/src/V3AstNodes.cpp index 6f7ddd87a..c3cf84bfd 100644 --- a/src/V3AstNodes.cpp +++ b/src/V3AstNodes.cpp @@ -660,6 +660,7 @@ void AstNodeFTask::dump(ostream& str) { void AstBegin::dump(ostream& str) { this->AstNode::dump(str); if (unnamed()) str<<" [UNNAMED]"; + if (hidden()) str<<" [HIDDEN]"; } void AstCoverDecl::dump(ostream& str) { this->AstNode::dump(str); diff --git a/src/V3AstNodes.h b/src/V3AstNodes.h index c50ee09b8..0a7fc7933 100644 --- a/src/V3AstNodes.h +++ b/src/V3AstNodes.h @@ -1094,6 +1094,7 @@ struct AstBegin : public AstNode { private: string m_name; // Name of block bool m_unnamed; // Originally unnamed + bool m_hidden; // Inserted by verilator, not user public: // Node that simply puts name into the output stream AstBegin(FileLine* fileline, const string& name, AstNode* stmtsp) @@ -1101,6 +1102,7 @@ public: , m_name(name) { addNOp1p(stmtsp); m_unnamed = (name==""); + m_hidden = false; } ASTNODE_NODE_FUNCS(Begin, BEGIN) virtual void dump(ostream& str); @@ -1108,8 +1110,12 @@ public: virtual void name(const string& name) { m_name = name; } // op1 = Statements AstNode* stmtsp() const { return op1p()->castNode(); } // op1 = List of statements - void addStmtp(AstNode* nodep) { addNOp1p(nodep); } + void addStmtsp(AstNode* nodep) { addNOp1p(nodep); } + AstNode* flatsp() const { return op2p()->castNode(); } // op2 = Statements that don't appear under new scope + void addFlatsp(AstNode* nodep) { addNOp2p(nodep); } bool unnamed() const { return m_unnamed; } + void hidden(bool flag) { m_hidden = flag; } + bool hidden() const { return m_hidden; } }; struct AstGenerate : public AstNode { diff --git a/src/V3Begin.cpp b/src/V3Begin.cpp index eecea0e6b..afebe6234 100644 --- a/src/V3Begin.cpp +++ b/src/V3Begin.cpp @@ -102,18 +102,31 @@ private: } // Remap var names and replace lower Begins - nodep->iterateChildren(*this); + nodep->stmtsp()->iterateAndNext(*this); - if (AstNode* stmtsp = nodep->stmtsp()) { - stmtsp->unlinkFrBackWithNext(); - nodep->replaceWith(stmtsp); - } else { - nodep->unlinkFrBack(); - } - pushDeletep(nodep); nodep=NULL; } m_namedScope = oldScope; m_unnamedScope = oldUnnamed; + + // Don't change var names of generate FOR() variables, but do recurse into a child FOR + nodep->flatsp()->iterateAndNext(*this); + + // Cleanup + AstNode* addsp = NULL; + if (AstNode* stmtsp = nodep->stmtsp()) { + stmtsp->unlinkFrBackWithNext(); + addsp = addsp->addNextNull(stmtsp); + } + if (AstNode* stmtsp = nodep->flatsp()) { + stmtsp->unlinkFrBackWithNext(); + addsp = addsp->addNextNull(stmtsp); + } + if (addsp) { + nodep->replaceWith(addsp); + } else { + nodep->unlinkFrBack(); + } + pushDeletep(nodep); nodep=NULL; } virtual void visit(AstVar* nodep, AstNUser*) { if (m_unnamedScope != "") { diff --git a/src/V3EmitV.cpp b/src/V3EmitV.cpp index 2b1be6293..5d1e8f12a 100644 --- a/src/V3EmitV.cpp +++ b/src/V3EmitV.cpp @@ -82,7 +82,11 @@ class EmitVBaseVisitor : public EmitCBaseVisitor { } virtual void visit(AstBegin* nodep, AstNUser*) { - putbs("begin\n"); + if (nodep->unnamed()) { + putbs("begin\n"); + } else { + putbs("begin : "+nodep->name()+"\n"); + } nodep->iterateChildren(*this); puts("end\n"); } diff --git a/src/V3Link.cpp b/src/V3Link.cpp index 2d85c5671..acfab34ca 100644 --- a/src/V3Link.cpp +++ b/src/V3Link.cpp @@ -479,7 +479,7 @@ private: } // Recurse int oldNum = m_beginNum; - m_beginNum = 0; + if (!nodep->hidden()) m_beginNum = 0; { // Create symbol table for the task's vars m_curVarsp = symsFindNew(nodep, upperVarsp); diff --git a/src/V3LinkDot.cpp b/src/V3LinkDot.cpp index f119b97b4..18c601169 100644 --- a/src/V3LinkDot.cpp +++ b/src/V3LinkDot.cpp @@ -479,13 +479,14 @@ private: LinkDotBaseVertex* oldVxp = m_inlineVxp; { m_beginp = nodep; - // Ignore begin names + // 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); - // We don't pickup variables, but do need to find cells - nodep->iterateChildren(*this); + nodep->stmtsp()->iterateAndNext(*this); } m_inlineVxp = oldVxp; m_beginp = oldbegin; + // + nodep->flatsp()->iterateAndNext(*this); } virtual void visit(AstVar* nodep, AstNUser*) { if (!m_statep->forScopeCreation() diff --git a/src/V3Unroll.cpp b/src/V3Unroll.cpp index f10753ee8..6ea339635 100644 --- a/src/V3Unroll.cpp +++ b/src/V3Unroll.cpp @@ -385,8 +385,9 @@ private: // anything lower will be renamed "uppernewname.lowerbegin" bool lastBegin = m_inBegin; m_inBegin = true; - nodep->iterateChildren(*this); + nodep->stmtsp()->iterateAndNext(*this); m_inBegin = lastBegin; + nodep->flatsp()->iterateAndNext(*this); if (m_varModeReplace && !m_inBegin // no upper begin, excluding this one ) { diff --git a/src/verilog.y b/src/verilog.y index 58c28f93e..cff172ac7 100644 --- a/src/verilog.y +++ b/src/verilog.y @@ -942,7 +942,7 @@ list_of_genvar_identifiers: // IEEE: list_of_genvar_identifiers (for decl | list_of_genvar_identifiers ',' genvar_identifierDecl { $$ = $1->addNext($3); } ; -genvar_identifierDecl: // IEEE: genvar_identifier (for declaration) +genvar_identifierDecl: // IEEE: genvar_identifier (for declaration) id/*new-genvar_identifier*/ sigAttrListE { VARRESET_NONLIST(GENVAR); VARDTYPE(new AstBasicDType($1,AstBasicDTypeKwd::INTEGER)); $$ = VARDONEA($1, *$1, NULL, $2); } @@ -1474,12 +1474,22 @@ conditional_generate_construct: // ==IEEE: conditional_generate_construct loop_generate_construct: // ==IEEE: loop_generate_construct yFOR '(' genvar_initialization ';' expr ';' genvar_iteration ')' generate_block_or_null - { $$ = new AstGenFor($1,$3,$5,$7,$9); } + { AstBegin* blkp = new AstBegin($1,"",NULL); blkp->hidden(true); + AstNode* initp = $3; AstNode* varp = $3; + if (varp->castVar()) { // Genvar + initp = varp->nextp(); + initp->unlinkFrBackWithNext(); // Detach 2nd from varp, make 1st init + blkp->addStmtsp(varp); + } + // Statements are under 'flatsp' so that cells under this + // for loop won't get an extra layer of hierarchy tacked on + blkp->addFlatsp(new AstGenFor($1,initp,$5,$7,$9)); + $$ = blkp; } ; genvar_initialization: // ==IEEE: genvar_initalization varRefBase '=' expr { $$ = new AstAssign($2,$1,$3); } - //UNSUP yGENVAR genvar_identifierDecl '=' constExpr { UNSUP } + | yGENVAR genvar_identifierDecl '=' constExpr { $$ = $2; $2->addNext(new AstAssign($3,new AstVarRef($3,$2,true), $4)); } ; genvar_iteration: // ==IEEE: genvar_iteration @@ -1814,7 +1824,7 @@ stmtBlock: // IEEE: statement + seq_block + par_block seq_block: // ==IEEE: seq_block // // IEEE doesn't allow declarations in unnamed blocks, but several simulators do. // // So need begin's even if unnamed to scope variables down - seq_blockFront blockDeclStmtList yEND endLabelE { $$=$1; $1->addStmtp($2); SYMP->popScope($1); } + seq_blockFront blockDeclStmtList yEND endLabelE { $$=$1; $1->addStmtsp($2); SYMP->popScope($1); } | seq_blockFront /**/ yEND endLabelE { $$=$1; SYMP->popScope($1); } ; diff --git a/test_regress/driver.pl b/test_regress/driver.pl index 94245cf07..d6e7edc01 100755 --- a/test_regress/driver.pl +++ b/test_regress/driver.pl @@ -302,7 +302,7 @@ sub new { all_run_flags => [], # ATSIM atsim => 0, - atsim_flags => [split(/\s+/,"-c +sv +define+atsim"), + atsim_flags => [split(/\s+/,"-c +sv +define+ATSIM"), "+sv_dir+$self->{obj_dir}/.athdl_compile"], atsim_flags2 => [], # Overridden in some sim files atsimrun_flags => [], diff --git a/test_regress/t/t_gen_for.v b/test_regress/t/t_gen_for.v index ad6d44527..d0349503b 100644 --- a/test_regress/t/t_gen_for.v +++ b/test_regress/t/t_gen_for.v @@ -87,15 +87,21 @@ module paramed (/*AUTOARG*/ // No else endgenerate +`ifndef NC // for(genvar) unsupported + `ifndef ATSIM // for(genvar) unsupported + generate + // Empty loop body, local genvar + for (genvar j=0; j<3; j=j+1) begin end + // Ditto to make sure j has new scope + for (genvar j=0; j<5; j=j+1) begin end + endgenerate + `endif +`endif + + generate + endgenerate + genvar i; - generate - // Empty loop body - for (i=0; i<3; i=i+1) begin end - endgenerate - - generate - endgenerate - generate if (MODE==0) begin // Flip bitorder, direct assign method diff --git a/test_regress/t/t_gen_intdot.v b/test_regress/t/t_gen_intdot.v index ef99ae743..54c18423d 100644 --- a/test_regress/t/t_gen_intdot.v +++ b/test_regress/t/t_gen_intdot.v @@ -84,11 +84,23 @@ module Genit (clk, value, result); input value; output result; +`ifndef ATSIM // else unsupported + `ifndef NC // else unsupported + `define WITH_FOR_GENVAR + `endif +`endif + `define WITH_GENERATE `ifdef WITH_GENERATE + `ifndef WITH_FOR_GENVAR genvar i; + `endif generate - for (i = 0; i < 1; i = i + 1) + for ( + `ifdef WITH_FOR_GENVAR + genvar + `endif + i = 0; i < 1; i = i + 1) begin : foo Test tt (clk, value, result); end diff --git a/test_regress/t/t_gen_intdot2.v b/test_regress/t/t_gen_intdot2.v index 41c0f23fc..f0212e91a 100644 --- a/test_regress/t/t_gen_intdot2.v +++ b/test_regress/t/t_gen_intdot2.v @@ -113,7 +113,7 @@ module Genit ( // IF generate for (i = 0; i < 2; i = i + 1) - One cellfor20 (); // genblk5[0..1].cellfor20 + One cellfor20 (); // genblk4[0..1].cellfor20 endgenerate `ifdef verilator always @ (posedge clk) if (genblk4[0].cellfor20.one !== 1'b1) $stop;