Support "generate for (genvar i=0; ...".
This commit is contained in:
parent
e4c96d5be5
commit
362d642c87
2
Changes
2
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]
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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 != "") {
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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
|
||||
) {
|
||||
|
|
|
|||
|
|
@ -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); }
|
||||
;
|
||||
|
||||
|
|
|
|||
|
|
@ -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 => [],
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
Loading…
Reference in New Issue