diff --git a/src/V3Begin.cpp b/src/V3Begin.cpp index 752d94886..daeed9ff8 100644 --- a/src/V3Begin.cpp +++ b/src/V3Begin.cpp @@ -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," "<name(m_unnamedScope+"__DOT__"+nodep->name()); + UINFO(8," rename to "<name()<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 "<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__<<": "<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 "<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; diff --git a/test_regress/t/t_func_gen.v b/test_regress/t/t_func_gen.v index bd55f1f61..d5ef80e5e 100644 --- a/test_regress/t/t_func_gen.v +++ b/test_regress/t/t_func_gen.v @@ -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