Support "generate for (genvar i=0; ...".

This commit is contained in:
Wilson Snyder 2011-11-29 18:23:18 -05:00
parent e4c96d5be5
commit 362d642c87
13 changed files with 86 additions and 30 deletions

View File

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

View File

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

View File

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

View File

@ -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 != "") {

View File

@ -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");
}

View File

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

View File

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

View File

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

View File

@ -942,7 +942,7 @@ list_of_genvar_identifiers<nodep>: // IEEE: list_of_genvar_identifiers (for decl
| list_of_genvar_identifiers ',' genvar_identifierDecl { $$ = $1->addNext($3); }
;
genvar_identifierDecl<nodep>: // IEEE: genvar_identifier (for declaration)
genvar_identifierDecl<varp>: // IEEE: genvar_identifier (for declaration)
id/*new-genvar_identifier*/ sigAttrListE
{ VARRESET_NONLIST(GENVAR); VARDTYPE(new AstBasicDType($<fl>1,AstBasicDTypeKwd::INTEGER));
$$ = VARDONEA($<fl>1, *$1, NULL, $2); }
@ -1474,12 +1474,22 @@ conditional_generate_construct<nodep>: // ==IEEE: conditional_generate_construct
loop_generate_construct<nodep>: // ==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<nodep>: // ==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<nodep>: // ==IEEE: genvar_iteration
@ -1814,7 +1824,7 @@ stmtBlock<nodep>: // IEEE: statement + seq_block + par_block
seq_block<nodep>: // ==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); }
;

View File

@ -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 => [],

View File

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

View File

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

View File

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