forked from github/verilator
Fix functions inside generate for block.
This commit is contained in:
parent
0de7cece5b
commit
c8e4b1fc84
@ -45,9 +45,31 @@
|
||||
|
||||
//######################################################################
|
||||
|
||||
class BeginState {
|
||||
private:
|
||||
// NODE STATE
|
||||
//Entire netlist:
|
||||
// AstNodeFTask::user1 -> bool, 1=processed
|
||||
AstUser1InUse m_inuser1;
|
||||
bool m_anyFuncInBegin;
|
||||
public:
|
||||
BeginState() {
|
||||
m_anyFuncInBegin = false;
|
||||
}
|
||||
~BeginState() {}
|
||||
void userMarkChanged(AstNodeFTask* nodep) {
|
||||
nodep->user1(true);
|
||||
m_anyFuncInBegin = true;
|
||||
}
|
||||
bool anyFuncInBegin() const { return m_anyFuncInBegin; }
|
||||
};
|
||||
|
||||
//######################################################################
|
||||
|
||||
class BeginVisitor : public AstNVisitor {
|
||||
private:
|
||||
// STATE
|
||||
BeginState* m_statep; // Current global state
|
||||
AstNodeModule* m_modp; // Current module
|
||||
AstNodeFTask* m_ftaskp; // Current function/task
|
||||
string m_namedScope; // Name of begin blocks above us
|
||||
@ -71,8 +93,15 @@ private:
|
||||
}
|
||||
virtual void visit(AstNodeFTask* nodep, AstNUser*) {
|
||||
UINFO(8," "<<nodep<<endl);
|
||||
// Rename it
|
||||
if (m_unnamedScope != "") {
|
||||
nodep->name(m_unnamedScope+"__DOT__"+nodep->name());
|
||||
UINFO(8," rename to "<<nodep->name()<<endl);
|
||||
m_statep->userMarkChanged(nodep);
|
||||
}
|
||||
// BEGIN wrapping a function rename that function, but don't affect the inside function's variables
|
||||
// We then restart with empty naming; so that any begin's inside the function will rename inside the function
|
||||
// Process children
|
||||
string oldScope = m_namedScope;
|
||||
string oldUnnamed = m_unnamedScope;
|
||||
{
|
||||
@ -197,7 +226,8 @@ private:
|
||||
}
|
||||
public:
|
||||
// CONSTUCTORS
|
||||
BeginVisitor(AstNetlist* nodep) {
|
||||
BeginVisitor(AstNetlist* nodep, BeginState* statep) {
|
||||
m_statep = statep;
|
||||
m_modp = NULL;
|
||||
m_ftaskp = NULL;
|
||||
m_repeatNum = 0;
|
||||
@ -207,10 +237,43 @@ public:
|
||||
virtual ~BeginVisitor() {}
|
||||
};
|
||||
|
||||
//######################################################################
|
||||
|
||||
class BeginRelinkVisitor : public AstNVisitor {
|
||||
// Replace tasks with new pointer
|
||||
private:
|
||||
// NODE STATE
|
||||
// Input:
|
||||
// AstNodeFTask::user1p // Node replaced, rename it
|
||||
|
||||
// VISITORS
|
||||
virtual void visit(AstNodeFTaskRef* nodep, AstNUser*) {
|
||||
if (nodep->taskp()->user1()) { // It was converted
|
||||
UINFO(9, " relinkFTask "<<nodep<<endl);
|
||||
nodep->name(nodep->taskp()->name());
|
||||
}
|
||||
nodep->iterateChildren(*this);
|
||||
}
|
||||
//--------------------
|
||||
virtual void visit(AstNode* nodep, AstNUser*) {
|
||||
nodep->iterateChildren(*this);
|
||||
}
|
||||
public:
|
||||
// CONSTUCTORS
|
||||
BeginRelinkVisitor(AstNetlist* nodep, BeginState*) {
|
||||
nodep->accept(*this);
|
||||
}
|
||||
virtual ~BeginRelinkVisitor() {}
|
||||
};
|
||||
|
||||
//######################################################################
|
||||
// Task class functions
|
||||
|
||||
void V3Begin::debeginAll(AstNetlist* nodep) {
|
||||
UINFO(2,__FUNCTION__<<": "<<endl);
|
||||
BeginVisitor bvisitor (nodep);
|
||||
BeginState state;
|
||||
{ BeginVisitor bvisitor (nodep,&state); }
|
||||
if (state.anyFuncInBegin()) {
|
||||
BeginRelinkVisitor brvisitor (nodep,&state);
|
||||
}
|
||||
}
|
||||
|
@ -498,7 +498,9 @@ private:
|
||||
}
|
||||
}
|
||||
virtual void visit(AstNodeFTask* nodep, AstNUser*) {
|
||||
m_statep->insertSym(m_cellVxp, nodep->name(), nodep);
|
||||
if (!m_beginp) { // For now, we don't support xrefs into functions inside begin blocks
|
||||
m_statep->insertSym(m_cellVxp, nodep->name(), nodep);
|
||||
}
|
||||
// No recursion, we don't want to pick up variables
|
||||
}
|
||||
virtual void visit(AstCFunc* nodep, AstNUser*) {
|
||||
@ -681,6 +683,9 @@ private:
|
||||
} else if (!m_cellVxp) {
|
||||
UINFO(9,"Dead module for "<<nodep<<endl);
|
||||
nodep->taskp(NULL); // Module that is not in hierarchy. We'll be dead code eliminating it later.
|
||||
} else if (nodep->dotted()=="" && nodep->taskp()) {
|
||||
// V3Link should have setup the links
|
||||
// Might be under a BEGIN we're not processing, so don't relink it
|
||||
} else {
|
||||
string baddot;
|
||||
LinkDotBaseVertex* okVxp;
|
||||
|
@ -1,20 +1,32 @@
|
||||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// Copyright 2012 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
|
||||
module t (/*AUTOARG*/
|
||||
// Inputs
|
||||
clk
|
||||
);
|
||||
input clk;
|
||||
genvar g;
|
||||
logic [1:0] mask = 0;
|
||||
generate
|
||||
for (g=0; g<1; g++)
|
||||
for (g=0; g<2; g++)
|
||||
begin : picker
|
||||
logic block_passed = 0; // Just for visualizing V3LinkDot debug
|
||||
function [3:0] pick;
|
||||
input [3:0] randnum;
|
||||
pick = randnum+g[3:0];
|
||||
endfunction
|
||||
always @(posedge clk) begin
|
||||
if (pick(3)!=3+g[3:0]) $stop;
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
else mask[g] = 1'b1;
|
||||
if (mask == 2'b11) begin // All iterations must be finished
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
end
|
||||
end
|
||||
endgenerate
|
||||
|
Loading…
Reference in New Issue
Block a user