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]
|
**** 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 dpi exports with > 32 bit but < 64 bit args, bug423. [Chandan Egbert]
|
||||||
|
|
||||||
**** Fix array of instantiations with sub-range output, bug414. [Jeremy Bennett]
|
**** 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) {
|
void AstBegin::dump(ostream& str) {
|
||||||
this->AstNode::dump(str);
|
this->AstNode::dump(str);
|
||||||
if (unnamed()) str<<" [UNNAMED]";
|
if (unnamed()) str<<" [UNNAMED]";
|
||||||
|
if (hidden()) str<<" [HIDDEN]";
|
||||||
}
|
}
|
||||||
void AstCoverDecl::dump(ostream& str) {
|
void AstCoverDecl::dump(ostream& str) {
|
||||||
this->AstNode::dump(str);
|
this->AstNode::dump(str);
|
||||||
|
|
|
||||||
|
|
@ -1094,6 +1094,7 @@ struct AstBegin : public AstNode {
|
||||||
private:
|
private:
|
||||||
string m_name; // Name of block
|
string m_name; // Name of block
|
||||||
bool m_unnamed; // Originally unnamed
|
bool m_unnamed; // Originally unnamed
|
||||||
|
bool m_hidden; // Inserted by verilator, not user
|
||||||
public:
|
public:
|
||||||
// Node that simply puts name into the output stream
|
// Node that simply puts name into the output stream
|
||||||
AstBegin(FileLine* fileline, const string& name, AstNode* stmtsp)
|
AstBegin(FileLine* fileline, const string& name, AstNode* stmtsp)
|
||||||
|
|
@ -1101,6 +1102,7 @@ public:
|
||||||
, m_name(name) {
|
, m_name(name) {
|
||||||
addNOp1p(stmtsp);
|
addNOp1p(stmtsp);
|
||||||
m_unnamed = (name=="");
|
m_unnamed = (name=="");
|
||||||
|
m_hidden = false;
|
||||||
}
|
}
|
||||||
ASTNODE_NODE_FUNCS(Begin, BEGIN)
|
ASTNODE_NODE_FUNCS(Begin, BEGIN)
|
||||||
virtual void dump(ostream& str);
|
virtual void dump(ostream& str);
|
||||||
|
|
@ -1108,8 +1110,12 @@ public:
|
||||||
virtual void name(const string& name) { m_name = name; }
|
virtual void name(const string& name) { m_name = name; }
|
||||||
// op1 = Statements
|
// op1 = Statements
|
||||||
AstNode* stmtsp() const { return op1p()->castNode(); } // op1 = List of 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; }
|
bool unnamed() const { return m_unnamed; }
|
||||||
|
void hidden(bool flag) { m_hidden = flag; }
|
||||||
|
bool hidden() const { return m_hidden; }
|
||||||
};
|
};
|
||||||
|
|
||||||
struct AstGenerate : public AstNode {
|
struct AstGenerate : public AstNode {
|
||||||
|
|
|
||||||
|
|
@ -102,18 +102,31 @@ private:
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remap var names and replace lower Begins
|
// 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_namedScope = oldScope;
|
||||||
m_unnamedScope = oldUnnamed;
|
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*) {
|
virtual void visit(AstVar* nodep, AstNUser*) {
|
||||||
if (m_unnamedScope != "") {
|
if (m_unnamedScope != "") {
|
||||||
|
|
|
||||||
|
|
@ -82,7 +82,11 @@ class EmitVBaseVisitor : public EmitCBaseVisitor {
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void visit(AstBegin* nodep, AstNUser*) {
|
virtual void visit(AstBegin* nodep, AstNUser*) {
|
||||||
putbs("begin\n");
|
if (nodep->unnamed()) {
|
||||||
|
putbs("begin\n");
|
||||||
|
} else {
|
||||||
|
putbs("begin : "+nodep->name()+"\n");
|
||||||
|
}
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
puts("end\n");
|
puts("end\n");
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -479,7 +479,7 @@ private:
|
||||||
}
|
}
|
||||||
// Recurse
|
// Recurse
|
||||||
int oldNum = m_beginNum;
|
int oldNum = m_beginNum;
|
||||||
m_beginNum = 0;
|
if (!nodep->hidden()) m_beginNum = 0;
|
||||||
{
|
{
|
||||||
// Create symbol table for the task's vars
|
// Create symbol table for the task's vars
|
||||||
m_curVarsp = symsFindNew(nodep, upperVarsp);
|
m_curVarsp = symsFindNew(nodep, upperVarsp);
|
||||||
|
|
|
||||||
|
|
@ -479,13 +479,14 @@ private:
|
||||||
LinkDotBaseVertex* oldVxp = m_inlineVxp;
|
LinkDotBaseVertex* oldVxp = m_inlineVxp;
|
||||||
{
|
{
|
||||||
m_beginp = nodep;
|
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);
|
m_inlineVxp = m_statep->insertBegin(m_inlineVxp, m_cellVxp, nodep);
|
||||||
// We don't pickup variables, but do need to find cells
|
nodep->stmtsp()->iterateAndNext(*this);
|
||||||
nodep->iterateChildren(*this);
|
|
||||||
}
|
}
|
||||||
m_inlineVxp = oldVxp;
|
m_inlineVxp = oldVxp;
|
||||||
m_beginp = oldbegin;
|
m_beginp = oldbegin;
|
||||||
|
//
|
||||||
|
nodep->flatsp()->iterateAndNext(*this);
|
||||||
}
|
}
|
||||||
virtual void visit(AstVar* nodep, AstNUser*) {
|
virtual void visit(AstVar* nodep, AstNUser*) {
|
||||||
if (!m_statep->forScopeCreation()
|
if (!m_statep->forScopeCreation()
|
||||||
|
|
|
||||||
|
|
@ -385,8 +385,9 @@ private:
|
||||||
// anything lower will be renamed "uppernewname.lowerbegin"
|
// anything lower will be renamed "uppernewname.lowerbegin"
|
||||||
bool lastBegin = m_inBegin;
|
bool lastBegin = m_inBegin;
|
||||||
m_inBegin = true;
|
m_inBegin = true;
|
||||||
nodep->iterateChildren(*this);
|
nodep->stmtsp()->iterateAndNext(*this);
|
||||||
m_inBegin = lastBegin;
|
m_inBegin = lastBegin;
|
||||||
|
nodep->flatsp()->iterateAndNext(*this);
|
||||||
|
|
||||||
if (m_varModeReplace && !m_inBegin // no upper begin, excluding this one
|
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); }
|
| 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
|
id/*new-genvar_identifier*/ sigAttrListE
|
||||||
{ VARRESET_NONLIST(GENVAR); VARDTYPE(new AstBasicDType($<fl>1,AstBasicDTypeKwd::INTEGER));
|
{ VARRESET_NONLIST(GENVAR); VARDTYPE(new AstBasicDType($<fl>1,AstBasicDTypeKwd::INTEGER));
|
||||||
$$ = VARDONEA($<fl>1, *$1, NULL, $2); }
|
$$ = 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
|
loop_generate_construct<nodep>: // ==IEEE: loop_generate_construct
|
||||||
yFOR '(' genvar_initialization ';' expr ';' genvar_iteration ')' generate_block_or_null
|
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
|
genvar_initialization<nodep>: // ==IEEE: genvar_initalization
|
||||||
varRefBase '=' expr { $$ = new AstAssign($2,$1,$3); }
|
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
|
genvar_iteration<nodep>: // ==IEEE: genvar_iteration
|
||||||
|
|
@ -1814,7 +1824,7 @@ stmtBlock<nodep>: // IEEE: statement + seq_block + par_block
|
||||||
seq_block<nodep>: // ==IEEE: seq_block
|
seq_block<nodep>: // ==IEEE: seq_block
|
||||||
// // IEEE doesn't allow declarations in unnamed blocks, but several simulators do.
|
// // IEEE doesn't allow declarations in unnamed blocks, but several simulators do.
|
||||||
// // So need begin's even if unnamed to scope variables down
|
// // 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); }
|
| seq_blockFront /**/ yEND endLabelE { $$=$1; SYMP->popScope($1); }
|
||||||
;
|
;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -302,7 +302,7 @@ sub new {
|
||||||
all_run_flags => [],
|
all_run_flags => [],
|
||||||
# ATSIM
|
# ATSIM
|
||||||
atsim => 0,
|
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"],
|
"+sv_dir+$self->{obj_dir}/.athdl_compile"],
|
||||||
atsim_flags2 => [], # Overridden in some sim files
|
atsim_flags2 => [], # Overridden in some sim files
|
||||||
atsimrun_flags => [],
|
atsimrun_flags => [],
|
||||||
|
|
|
||||||
|
|
@ -87,15 +87,21 @@ module paramed (/*AUTOARG*/
|
||||||
// No else
|
// No else
|
||||||
endgenerate
|
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;
|
genvar i;
|
||||||
generate
|
|
||||||
// Empty loop body
|
|
||||||
for (i=0; i<3; i=i+1) begin end
|
|
||||||
endgenerate
|
|
||||||
|
|
||||||
generate
|
|
||||||
endgenerate
|
|
||||||
|
|
||||||
generate
|
generate
|
||||||
if (MODE==0) begin
|
if (MODE==0) begin
|
||||||
// Flip bitorder, direct assign method
|
// Flip bitorder, direct assign method
|
||||||
|
|
|
||||||
|
|
@ -84,11 +84,23 @@ module Genit (clk, value, result);
|
||||||
input value;
|
input value;
|
||||||
output result;
|
output result;
|
||||||
|
|
||||||
|
`ifndef ATSIM // else unsupported
|
||||||
|
`ifndef NC // else unsupported
|
||||||
|
`define WITH_FOR_GENVAR
|
||||||
|
`endif
|
||||||
|
`endif
|
||||||
|
|
||||||
`define WITH_GENERATE
|
`define WITH_GENERATE
|
||||||
`ifdef WITH_GENERATE
|
`ifdef WITH_GENERATE
|
||||||
|
`ifndef WITH_FOR_GENVAR
|
||||||
genvar i;
|
genvar i;
|
||||||
|
`endif
|
||||||
generate
|
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
|
begin : foo
|
||||||
Test tt (clk, value, result);
|
Test tt (clk, value, result);
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -113,7 +113,7 @@ module Genit (
|
||||||
// IF
|
// IF
|
||||||
generate
|
generate
|
||||||
for (i = 0; i < 2; i = i + 1)
|
for (i = 0; i < 2; i = i + 1)
|
||||||
One cellfor20 (); // genblk5[0..1].cellfor20
|
One cellfor20 (); // genblk4[0..1].cellfor20
|
||||||
endgenerate
|
endgenerate
|
||||||
`ifdef verilator
|
`ifdef verilator
|
||||||
always @ (posedge clk) if (genblk4[0].cellfor20.one !== 1'b1) $stop;
|
always @ (posedge clk) if (genblk4[0].cellfor20.one !== 1'b1) $stop;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue