Fix functions inside generate for block.

This commit is contained in:
Wilson Snyder 2012-02-21 22:23:06 -05:00
parent 0de7cece5b
commit c8e4b1fc84
3 changed files with 86 additions and 6 deletions

View File

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

View File

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

View File

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