Reorder structures to always go through symp

git-svn-id: file://localhost/svn/verilator/trunk/verilator@770 77ca24e4-aefa-0310-84f0-b9a241c72d87
This commit is contained in:
Wilson Snyder 2006-08-30 21:07:55 +00:00
parent c78254503c
commit 3909ba1cef
18 changed files with 168 additions and 123 deletions

View File

@ -5,6 +5,9 @@ indicates the contributor was also the author of the fix; Thanks!
* Verilator 3.60** * Verilator 3.60**
** Many changes to the pointers used for internal structures.
When used with gcc's -fstrict-aliasing, large models are ~***% faster.
*** Added --inhibit-sim flag for environments using old __Vm_inhibitSim. *** Added --inhibit-sim flag for environments using old __Vm_inhibitSim.
*** Added `systemc_dtor for destructor extentions. [Allan Cochrane] *** Added `systemc_dtor for destructor extentions. [Allan Cochrane]

View File

@ -645,11 +645,14 @@ fast path, mostly code that is executed every cycle. OPT_SLOW specifies
optimizations for slow-path files (plus tracing), which execute only optimizations for slow-path files (plus tracing), which execute only
rarely, yet take a long time to compile with optimization on. OPT rarely, yet take a long time to compile with optimization on. OPT
specifies overall optimization and affects all compiles, including those specifies overall optimization and affects all compiles, including those
OPT_FAST and OPT_SLOW affect. For best results, use OPT="-O2". Nearly the OPT_FAST and OPT_SLOW affect. For best results, use OPT="-O2
same results can be had with much better compile times with OPT_FAST="-O1". -fstrict-aliasing". Nearly the same results can be had with much better
Unfortunately, using the optimizer with SystemC files can result in compile times with OPT_FAST="-O1 -fstrict-aliasing". Unfortunately, using
compiles taking several minutes. (The SystemC libraries have many little the optimizer with SystemC files can result in compiles taking several
inlined functions that drive the compiler nuts.) minutes. (The SystemC libraries have many little inlined functions that
drive the compiler nuts.) Also read the manual as to the effects of
-fstrict-aliasing; you may want to compile only the verilated code with
this flag.
For best results, use GCC 3.3 or newer. GCC 3.2 and earlier have For best results, use GCC 3.3 or newer. GCC 3.2 and earlier have
optimization bugs around pointer aliasing detection, which can result in 2x optimization bugs around pointer aliasing detection, which can result in 2x

View File

@ -30,7 +30,6 @@
//=========================================================================== //===========================================================================
// Global variables // Global variables
uint32_t Verilated::s_coverageRequest = false;
int Verilated::s_randReset = false; int Verilated::s_randReset = false;
int Verilated::s_debug = 1; int Verilated::s_debug = 1;
bool Verilated::s_calcUnusedSigs = false; bool Verilated::s_calcUnusedSigs = false;

View File

@ -121,7 +121,6 @@ public:
struct Verilated { struct Verilated {
// Extern Vars // Extern Vars
// Below two are used as bool, but having as uint32_t avoids conversion time // Below two are used as bool, but having as uint32_t avoids conversion time
static uint32_t s_coverageRequest; ///< Collect coverage info now
private: private:
static int s_randReset; ///< Random reset: 0=all 0s, 1=all 1s, 2=random static int s_randReset; ///< Random reset: 0=all 0s, 1=all 1s, 2=random
static int s_debug; ///< See accessors... only when VL_DEBUG set static int s_debug; ///< See accessors... only when VL_DEBUG set

View File

@ -52,7 +52,7 @@ CPPFLAGS += $(OPT)
# SystemC takes minutes to optimize, thus it is off by default. # SystemC takes minutes to optimize, thus it is off by default.
#OPT_SLOW = #OPT_SLOW =
# Fast path optimizations. Most time is spent in these classes. # Fast path optimizations. Most time is spent in these classes.
#OPT_FAST = -O2 -funroll-loops #OPT_FAST = -O2 -fstrict-aliasing
#OPT_FAST = -O #OPT_FAST = -O
#OPT_FAST = #OPT_FAST =

View File

@ -42,6 +42,7 @@
#include "V3Global.h" #include "V3Global.h"
#include "V3Active.h" #include "V3Active.h"
#include "V3Ast.h" #include "V3Ast.h"
#include "V3EmitCBase.h"
//***** See below for main transformation engine //***** See below for main transformation engine
@ -231,6 +232,8 @@ private:
} }
if (!m_scopeFinalp) { if (!m_scopeFinalp) {
m_scopeFinalp = new AstCFunc(nodep->fileline(), "_final", m_namer.scopep()); m_scopeFinalp = new AstCFunc(nodep->fileline(), "_final", m_namer.scopep());
m_scopeFinalp->argTypes(EmitCBaseVisitor::symClassVar());
m_scopeFinalp->addInitsp(new AstCStmt(nodep->fileline()," "+EmitCBaseVisitor::symTopAssign()+"\n"));
m_scopeFinalp->dontCombine(true); m_scopeFinalp->dontCombine(true);
m_scopeFinalp->formCallTree(true); m_scopeFinalp->formCallTree(true);
m_scopeFinalp->slow(true); m_scopeFinalp->slow(true);

View File

@ -422,7 +422,7 @@ public:
virtual string name() const { return m_name; } // * = Scope name virtual string name() const { return m_name; } // * = Scope name
void name(const string& name) { m_name = name; } void name(const string& name) { m_name = name; }
string nameDotless() const; string nameDotless() const;
string nameVlSym() const { return (((string)"VlSym->") + nameDotless()); } string nameVlSym() const { return (((string)"vlSymsp->") + nameDotless()); }
AstModule* modp() const { return m_modp; } AstModule* modp() const { return m_modp; }
void addVarp(AstNode* nodep) { addOp1p(nodep); } void addVarp(AstNode* nodep) { addOp1p(nodep); }
AstNode* varsp() const { return op1p()->castNode(); } // op1 = AstVarScope's AstNode* varsp() const { return op1p()->castNode(); } // op1 = AstVarScope's
@ -586,7 +586,6 @@ struct AstModule : public AstNode {
private: private:
string m_name; // Name of the module string m_name; // Name of the module
string m_origName; // Name of the module, ignoring name() changes, for dot lookup string m_origName; // Name of the module, ignoring name() changes, for dot lookup
bool m_globalSyms:1; // References global symbol table
bool m_modPublic:1; // Module has public references bool m_modPublic:1; // Module has public references
bool m_modTrace:1; // Tracing this module bool m_modTrace:1; // Tracing this module
bool m_inLibrary:1; // From a library, no error if not used, never top level bool m_inLibrary:1; // From a library, no error if not used, never top level
@ -596,7 +595,7 @@ private:
public: public:
AstModule(FileLine* fl, const string& name) AstModule(FileLine* fl, const string& name)
: AstNode (fl) : AstNode (fl)
,m_name(name), m_origName(name), m_globalSyms(false), m_modPublic(false) ,m_name(name), m_origName(name), m_modPublic(false)
,m_modTrace(false), m_inLibrary(false) ,m_modTrace(false), m_inLibrary(false)
,m_level(0), m_varNum(0), m_clkReqVarp(NULL) { } ,m_level(0), m_varNum(0), m_clkReqVarp(NULL) { }
virtual ~AstModule() {} virtual ~AstModule() {}
@ -623,8 +622,6 @@ public:
int varNumGetInc() { return ++m_varNum; } int varNumGetInc() { return ++m_varNum; }
AstVar* clkReqVarp() const { return m_clkReqVarp; } AstVar* clkReqVarp() const { return m_clkReqVarp; }
void clkReqVarp(AstVar* varp) { m_clkReqVarp = varp; } void clkReqVarp(AstVar* varp) { m_clkReqVarp = varp; }
void globalSyms(bool flag) { m_globalSyms = flag; }
bool globalSyms() const { return m_globalSyms; }
void modPublic(bool flag) { m_modPublic = flag; } void modPublic(bool flag) { m_modPublic = flag; }
bool modPublic() const { return m_modPublic; } bool modPublic() const { return m_modPublic; }
void modTrace(bool flag) { m_modTrace = flag; } void modTrace(bool flag) { m_modTrace = flag; }
@ -2774,6 +2771,7 @@ private:
bool m_slow:1; // Slow routine, called once or just at init time bool m_slow:1; // Slow routine, called once or just at init time
bool m_funcPublic:1; // From user public task/function bool m_funcPublic:1; // From user public task/function
bool m_isStatic:1; // Function is declared static (no this) bool m_isStatic:1; // Function is declared static (no this)
bool m_symProlog:1; // Setup symbol table for later instructions
public: public:
AstCFunc(FileLine* fl, const string& name, AstScope* scopep, const string& rtnType="") AstCFunc(FileLine* fl, const string& name, AstScope* scopep, const string& rtnType="")
: AstNode(fl) { : AstNode(fl) {
@ -2788,6 +2786,7 @@ public:
m_slow = false; m_slow = false;
m_funcPublic = false; m_funcPublic = false;
m_isStatic = false; m_isStatic = false;
m_symProlog = false;
} }
virtual ~AstCFunc() {} virtual ~AstCFunc() {}
virtual AstType type() const { return AstType::CFUNC;} virtual AstType type() const { return AstType::CFUNC;}
@ -2795,7 +2794,9 @@ public:
virtual void accept(AstNVisitor& v, AstNUser* vup=NULL) { v.visit(this,vup); } virtual void accept(AstNVisitor& v, AstNUser* vup=NULL) { v.visit(this,vup); }
virtual string name() const { return m_name; } virtual string name() const { return m_name; }
virtual V3Hash sameHash() const { return V3Hash(); } virtual V3Hash sameHash() const { return V3Hash(); }
virtual bool same(AstNode* samep) const { return true; } virtual bool same(AstNode* samep) const { return ((funcType()==samep->castCFunc()->funcType())
&& (rtnTypeVoid()==samep->castCFunc()->rtnTypeVoid())
&& (argTypes()==samep->castCFunc()->argTypes())); }
// //
void name(const string& flag) { m_name = flag; } void name(const string& flag) { m_name = flag; }
AstScope* scopep() const { return m_scopep; } AstScope* scopep() const { return m_scopep; }
@ -2819,6 +2820,8 @@ public:
AstCFuncType funcType() const { return m_funcType; } AstCFuncType funcType() const { return m_funcType; }
bool isStatic() const { return m_isStatic; } bool isStatic() const { return m_isStatic; }
void isStatic(bool flag) { m_isStatic = flag; } void isStatic(bool flag) { m_isStatic = flag; }
bool symProlog() const { return m_symProlog; }
void symProlog(bool flag) { m_symProlog = flag; }
// //
// If adding node accessors, see below // If adding node accessors, see below
AstNode* argsp() const { return op1p()->castNode(); } AstNode* argsp() const { return op1p()->castNode(); }
@ -2840,6 +2843,7 @@ struct AstCCall : public AstNodeStmt {
private: private:
AstCFunc* m_funcp; AstCFunc* m_funcp;
string m_hiername; string m_hiername;
string m_argTypes;
public: public:
AstCCall(FileLine* fl, AstCFunc* funcp, AstNode* argsp=NULL) AstCCall(FileLine* fl, AstCFunc* funcp, AstNode* argsp=NULL)
: AstNodeStmt(fl) { : AstNodeStmt(fl) {
@ -2863,7 +2867,8 @@ public:
virtual int instrCount() const { return instrCountCall(); } virtual int instrCount() const { return instrCountCall(); }
virtual V3Hash sameHash() const { return V3Hash(funcp()); } virtual V3Hash sameHash() const { return V3Hash(funcp()); }
virtual bool same(AstNode* samep) const { virtual bool same(AstNode* samep) const {
return funcp()==samep->castCCall()->funcp(); } return (funcp()==samep->castCCall()->funcp()
&& argTypes()==samep->castCCall()->argTypes()); }
AstNode* exprsp() const { return op1p()->castNode(); } // op1= expressions to print AstNode* exprsp() const { return op1p()->castNode(); } // op1= expressions to print
virtual bool isGateOptimizable() const { return false; } virtual bool isGateOptimizable() const { return false; }
virtual bool isPredictOptimizable() const { return false; } virtual bool isPredictOptimizable() const { return false; }
@ -2872,6 +2877,8 @@ public:
AstCFunc* funcp() const { return m_funcp; } AstCFunc* funcp() const { return m_funcp; }
string hiername() const { return m_hiername; } string hiername() const { return m_hiername; }
void hiername(const string& hn) { m_hiername = hn; } void hiername(const string& hn) { m_hiername = hn; }
void argTypes(const string& str) { m_argTypes = str; }
string argTypes() const { return m_argTypes; }
// //
AstNode* argsp() const { return op1p()->castNode(); } AstNode* argsp() const { return op1p()->castNode(); }
void addArgsp(AstNode* nodep) { addOp1p(nodep); } void addArgsp(AstNode* nodep) { addOp1p(nodep); }

View File

@ -393,6 +393,6 @@ void V3Case::caseAll(AstNetlist* nodep) {
CaseVisitor visitor (nodep); CaseVisitor visitor (nodep);
} }
void V3Case::caseLint(AstNodeCase* nodep) { void V3Case::caseLint(AstNodeCase* nodep) {
UINFO(2,__FUNCTION__<<": "<<endl); UINFO(4,__FUNCTION__<<": "<<endl);
CaseLintVisitor visitor (nodep); CaseLintVisitor visitor (nodep);
} }

View File

@ -39,8 +39,9 @@
#include <set> #include <set>
#include "V3Global.h" #include "V3Global.h"
#include "V3Changed.h"
#include "V3Ast.h" #include "V3Ast.h"
#include "V3Changed.h"
#include "V3EmitCBase.h"
//###################################################################### //######################################################################
// Changed state, as a visitor of each AstNode // Changed state, as a visitor of each AstNode
@ -106,6 +107,8 @@ private:
m_scopetopp = scopep; m_scopetopp = scopep;
// Create change detection function // Create change detection function
m_chgFuncp = new AstCFunc(nodep->fileline(), "_change_request", scopep, "bool"); m_chgFuncp = new AstCFunc(nodep->fileline(), "_change_request", scopep, "bool");
m_chgFuncp->argTypes(EmitCBaseVisitor::symClassVar());
m_chgFuncp->symProlog(true);
m_scopetopp->addActivep(m_chgFuncp); m_scopetopp->addActivep(m_chgFuncp);
// We need at least one change detect so we know to emit the correct code // We need at least one change detect so we know to emit the correct code
m_chgFuncp->addStmtsp(new AstChangeDet(nodep->fileline(), NULL, NULL, false)); m_chgFuncp->addStmtsp(new AstChangeDet(nodep->fileline(), NULL, NULL, false));

View File

@ -41,6 +41,7 @@
#include "V3Global.h" #include "V3Global.h"
#include "V3Clock.h" #include "V3Clock.h"
#include "V3Ast.h" #include "V3Ast.h"
#include "V3EmitCBase.h"
//###################################################################### //######################################################################
// Clock state, as a visitor of each AstNode // Clock state, as a visitor of each AstNode
@ -186,30 +187,42 @@ private:
AstNode::userClearTree(); AstNode::userClearTree();
// Make top functions // Make top functions
{ {
m_evalFuncp = new AstCFunc(nodep->fileline(), "_eval", m_scopep); AstCFunc* funcp = new AstCFunc(nodep->fileline(), "_eval", m_scopep);
m_evalFuncp->dontCombine(true); funcp->argTypes(EmitCBaseVisitor::symClassVar());
m_scopep->addActivep(m_evalFuncp); funcp->dontCombine(true);
funcp->symProlog(true);
m_scopep->addActivep(funcp);
m_evalFuncp = funcp;
} }
{ {
m_initFuncp = new AstCFunc(nodep->fileline(), "_eval_initial", m_scopep); AstCFunc* funcp = new AstCFunc(nodep->fileline(), "_eval_initial", m_scopep);
m_initFuncp->dontCombine(true); funcp->argTypes(EmitCBaseVisitor::symClassVar());
m_initFuncp->slow(true); funcp->dontCombine(true);
m_scopep->addActivep(m_initFuncp); funcp->slow(true);
funcp->symProlog(true);
m_scopep->addActivep(funcp);
m_initFuncp = funcp;
} }
{ {
m_finalFuncp = new AstCFunc(nodep->fileline(), "final", m_scopep); AstCFunc* funcp = new AstCFunc(nodep->fileline(), "final", m_scopep);
m_finalFuncp->skipDecl(true); funcp->skipDecl(true);
m_finalFuncp->dontCombine(true); funcp->dontCombine(true);
m_finalFuncp->slow(true); funcp->slow(true);
m_finalFuncp->addStmtsp(new AstCStmt(nodep->fileline(), funcp->addInitsp(
" "+v3Global.opt.prefix()+"__Syms::init(this);\n")); new AstCStmt(nodep->fileline(),
m_scopep->addActivep(m_finalFuncp); " "+EmitCBaseVisitor::symClassVar()+" = this->__VlSymsp;\n"));
funcp->addInitsp(new AstCStmt(nodep->fileline()," "+EmitCBaseVisitor::symTopAssign()+"\n"));
m_scopep->addActivep(funcp);
m_finalFuncp = funcp;
} }
{ {
m_settleFuncp = new AstCFunc(nodep->fileline(), "_eval_settle", m_scopep); AstCFunc* funcp = new AstCFunc(nodep->fileline(), "_eval_settle", m_scopep);
m_settleFuncp->dontCombine(true); funcp->argTypes(EmitCBaseVisitor::symClassVar());
m_settleFuncp->slow(true); funcp->dontCombine(true);
m_scopep->addActivep(m_settleFuncp); funcp->slow(true);
funcp->symProlog(true);
m_scopep->addActivep(funcp);
m_settleFuncp = funcp;
} }
// Process the activates // Process the activates
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
@ -273,12 +286,16 @@ private:
if (!m_scopep) nodep->v3fatalSrc("Initial Active not under scope\n"); if (!m_scopep) nodep->v3fatalSrc("Initial Active not under scope\n");
AstCFunc* funcp = new AstCFunc(nodep->fileline(), "_initial__"+m_scopep->nameDotless(), AstCFunc* funcp = new AstCFunc(nodep->fileline(), "_initial__"+m_scopep->nameDotless(),
m_scopep); m_scopep);
funcp->argTypes(EmitCBaseVisitor::symClassVar());
funcp->symProlog(true);
funcp->slow(true); funcp->slow(true);
stmtsp->unlinkFrBackWithNext(); stmtsp->unlinkFrBackWithNext();
funcp->addStmtsp(stmtsp); funcp->addStmtsp(stmtsp);
nodep->replaceWith(funcp); nodep->replaceWith(funcp);
// Add top level call to it // Add top level call to it
m_initFuncp->addStmtsp(new AstCCall(nodep->fileline(), funcp)); AstCCall* callp = new AstCCall(nodep->fileline(), funcp);
callp->argTypes("vlSymsp");
m_initFuncp->addStmtsp(callp);
} else { } else {
nodep->unlinkFrBack(); nodep->unlinkFrBack();
} }
@ -290,7 +307,9 @@ private:
if (nodep->formCallTree()) { if (nodep->formCallTree()) {
if (nodep->name() == "_final") { if (nodep->name() == "_final") {
UINFO(4, " formCallTree "<<nodep<<endl); UINFO(4, " formCallTree "<<nodep<<endl);
m_finalFuncp->addStmtsp(new AstCCall(nodep->fileline(), nodep)); AstCCall* callp = new AstCCall(nodep->fileline(), nodep);
callp->argTypes("vlSymsp");
m_finalFuncp->addStmtsp(callp);
} else { } else {
nodep->v3fatalSrc("Unknown CFunc name. Make code more generic, with a map of func names"); nodep->v3fatalSrc("Unknown CFunc name. Make code more generic, with a map of func names");
} }

View File

@ -94,6 +94,7 @@ public:
if (callp->funcp() != oldfuncp) callp->v3fatalSrc("Call list broken, points to call w/different func"); if (callp->funcp() != oldfuncp) callp->v3fatalSrc("Call list broken, points to call w/different func");
if (newfuncp) { if (newfuncp) {
AstCCall* newp = new AstCCall(callp, newfuncp); AstCCall* newp = new AstCCall(callp, newfuncp);
newp->argTypes(callp->argTypes());
callp->replaceWith(newp); callp->replaceWith(newp);
addCall(newp); // Fix the table addCall(newp); // Fix the table
} else { // Just deleting empty function } else { // Just deleting empty function

View File

@ -36,6 +36,7 @@
#include "V3Global.h" #include "V3Global.h"
#include "V3Descope.h" #include "V3Descope.h"
#include "V3Ast.h" #include "V3Ast.h"
#include "V3EmitCBase.h"
//###################################################################### //######################################################################
@ -61,13 +62,13 @@ private:
hierThisr = true; hierThisr = true;
if (varp && varp->isFuncLocal()) { if (varp && varp->isFuncLocal()) {
return ""; // Relative to function, not in this return ""; // Relative to function, not in this
} else if (scopep == m_scopep) { } else if (scopep == m_scopep && m_modp->isTop()) {
if (m_modp->isTop()) { //return ""; // Reference to scope we're in, no need to HIER-> it
return ""; // Reference to scope we're in, no need to HIER-> it return "vlTOPp->";
} else { } else if (scopep == m_scopep && !m_modp->isTop()
&& 0) { // We no longer thisp-> as still get ambiguation problems
m_needThis = true; m_needThis = true;
return "thisp->"; // this-> but with restricted aliasing return "thisp->"; // this-> but with restricted aliasing
}
} else if (scopep->aboveScopep() && scopep->aboveScopep()==m_scopep } else if (scopep->aboveScopep() && scopep->aboveScopep()==m_scopep
&& 0 // DISABLED: GCC considers the pointers ambiguous, so goes ld/store crazy && 0 // DISABLED: GCC considers the pointers ambiguous, so goes ld/store crazy
) { ) {
@ -81,13 +82,12 @@ private:
return name+"->"; return name+"->";
} else { } else {
// Reference to something else, use global variable // Reference to something else, use global variable
m_modp->globalSyms(true);
UINFO(8," Descope "<<scopep<<endl); UINFO(8," Descope "<<scopep<<endl);
UINFO(8," to "<<scopep->name()<<endl); UINFO(8," to "<<scopep->name()<<endl);
UINFO(8," under "<<m_scopep->name()<<endl); UINFO(8," under "<<m_scopep->name()<<endl);
hierThisr = false; hierThisr = false;
if (!scopep->aboveScopep()) { // Top if (!scopep->aboveScopep()) { // Top
return "VlSym->TOPp->"; return "vlTOPp->"; // == "vlSymsp->TOPp->", but GCC would suspect aliases
} else { } else {
return scopep->nameVlSym()+"."; return scopep->nameVlSym()+".";
} }
@ -111,6 +111,10 @@ private:
if (newfuncp->stmtsp()) newfuncp->stmtsp()->unlinkFrBackWithNext()->deleteTree(); if (newfuncp->stmtsp()) newfuncp->stmtsp()->unlinkFrBackWithNext()->deleteTree();
if (newfuncp->finalsp()) newfuncp->finalsp()->unlinkFrBackWithNext()->deleteTree(); if (newfuncp->finalsp()) newfuncp->finalsp()->unlinkFrBackWithNext()->deleteTree();
newfuncp->name(name); newfuncp->name(name);
newfuncp->addInitsp(
new AstCStmt(newfuncp->fileline(),
" "+EmitCBaseVisitor::symClassVar()+" = this->__VlSymsp;\n"));
newfuncp->addInitsp(new AstCStmt(newfuncp->fileline()," "+EmitCBaseVisitor::symTopAssign()+"\n"));
topFuncp->addNextHere(newfuncp); topFuncp->addNextHere(newfuncp);
// In the body, call each function if it matches the given scope // In the body, call each function if it matches the given scope
for (FuncMmap::iterator eachIt = it; eachIt!=m_modFuncs.end() && eachIt->first==name; ++eachIt) { for (FuncMmap::iterator eachIt = it; eachIt!=m_modFuncs.end() && eachIt->first==name; ++eachIt) {
@ -209,6 +213,7 @@ private:
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
nodep->user(true); nodep->user(true);
if (m_needThis) { if (m_needThis) {
nodep->v3fatalSrc("old code");
// Really we should have more node types for backend optimization of this stuff // Really we should have more node types for backend optimization of this stuff
string text = " "+v3Global.opt.modPrefix() + "_" + m_modp->name() string text = " "+v3Global.opt.modPrefix() + "_" + m_modp->name()
+"* thisp = &("+m_scopep->nameVlSym()+");\n"; +"* thisp = &("+m_scopep->nameVlSym()+");\n";

View File

@ -182,9 +182,12 @@ public:
puts(nodep->hiername()); puts(nodep->hiername());
puts(nodep->funcp()->name()); puts(nodep->funcp()->name());
puts("("); puts("(");
puts(nodep->argTypes());
bool comma = (nodep->argTypes() != "");
for (AstNode* subnodep=nodep->argsp(); subnodep; subnodep = subnodep->nextp()) { for (AstNode* subnodep=nodep->argsp(); subnodep; subnodep = subnodep->nextp()) {
if (comma) puts(", ");
subnodep->accept(*this); subnodep->accept(*this);
if (subnodep->nextp()) puts(", "); comma = true;
} }
if (nodep->backp()->castNodeMath() || nodep->backp()->castCReturn()) { if (nodep->backp()->castNodeMath() || nodep->backp()->castCReturn()) {
// We should have a separate CCall for math and statement usage, but... // We should have a separate CCall for math and statement usage, but...
@ -214,7 +217,7 @@ public:
puts(");\n"); puts(");\n");
} }
virtual void visit(AstCoverInc* nodep, AstNUser*) { virtual void visit(AstCoverInc* nodep, AstNUser*) {
puts("if (Verilated::s_coverageRequest)"); puts("if (VL_LIKELY(vlSymsp->__Vm_coverageRequest))");
puts(" ++__Vcoverage["); puts(" ++__Vcoverage[");
puts(cvtToStr(m_coverIds.remap(nodep->declp()))); puts("];\n"); puts(cvtToStr(m_coverIds.remap(nodep->declp()))); puts("];\n");
} }
@ -596,6 +599,8 @@ class EmitCImp : EmitCStmts {
+"<<name()" +"<<name()"
+"<<endl; );\n"); +"<<endl; );\n");
if (nodep->symProlog()) puts(EmitCBaseVisitor::symTopAssign()+"\n");
if (nodep->initsp()) puts("// Variables\n"); if (nodep->initsp()) puts("// Variables\n");
ofp()->putAlign(V3OutFile::AL_AUTO, 4); ofp()->putAlign(V3OutFile::AL_AUTO, 4);
for (AstNode* subnodep=nodep->argsp(); subnodep; subnodep = subnodep->nextp()) { for (AstNode* subnodep=nodep->argsp(); subnodep; subnodep = subnodep->nextp()) {
@ -1023,8 +1028,6 @@ void EmitCImp::emitVarResets(AstModule* modp) {
puts("// Reset internal values\n"); puts("// Reset internal values\n");
if (modp->isTop()) { if (modp->isTop()) {
if (v3Global.opt.inhibitSim()) puts("__Vm_inhibitSim = false;\n"); if (v3Global.opt.inhibitSim()) puts("__Vm_inhibitSim = false;\n");
puts("__Vm_activity = false;\n");
puts("__Vm_didInit = false;\n");
puts("\n"); puts("\n");
} }
@ -1201,7 +1204,8 @@ void EmitCImp::emitTextSection(AstType type) {
void EmitCImp::emitCellCtors(AstModule* modp) { void EmitCImp::emitCellCtors(AstModule* modp) {
if (modp->isTop()) { if (modp->isTop()) {
// Must be before other constructors, as __vlCoverInsert calls it // Must be before other constructors, as __vlCoverInsert calls it
puts("__VlSymsp = new "+symClassName()+"(this, name());\n"); puts(EmitCBaseVisitor::symClassVar()+" = __VlSymsp = new "+symClassName()+"(this, name());\n");
puts(EmitCBaseVisitor::symTopAssign()+"\n");
} }
for (AstNode* nodep=modp->stmtsp(); nodep; nodep = nodep->nextp()) { for (AstNode* nodep=modp->stmtsp(); nodep; nodep = nodep->nextp()) {
if (AstCell* cellp=nodep->castCell()) { if (AstCell* cellp=nodep->castCell()) {
@ -1229,48 +1233,48 @@ void EmitCImp::emitSensitives() {
void EmitCImp::emitWrapEval(AstModule* modp) { void EmitCImp::emitWrapEval(AstModule* modp) {
puts("\nvoid "+modClassName(modp)+"::eval() {\n"); puts("\nvoid "+modClassName(modp)+"::eval() {\n");
puts("// Setup global symbol table\n"); puts(EmitCBaseVisitor::symClassVar()+" = this->__VlSymsp; // Setup global symbol table\n");
puts(symClassName()); puts("::init(this);\n"); puts(EmitCBaseVisitor::symTopAssign()+"\n");
puts("// Initialize\n"); puts("// Initialize\n");
puts("if (!__Vm_didInit) eval_initial_loop();\n"); puts("if (VL_UNLIKELY(!vlSymsp->__Vm_didInit)) _eval_initial_loop(vlSymsp);\n");
if (v3Global.opt.inhibitSim()) { if (v3Global.opt.inhibitSim()) {
puts("if (__Vm_inhibitSim) return;\n"); puts("if (VL_UNLIKELY(__Vm_inhibitSim)) return;\n");
} }
puts("// Evaluate till stable\n"); puts("// Evaluate till stable\n");
puts("VL_DEBUG_IF(cout<<\"\\n----TOP Evaluate "+modClassName(modp)+"::eval\"<<endl; );\n"); puts("VL_DEBUG_IF(cout<<\"\\n----TOP Evaluate "+modClassName(modp)+"::eval\"<<endl; );\n");
#ifndef NEW_ORDERING #ifndef NEW_ORDERING
puts("int __VclockLoop = 0;\n"); puts("int __VclockLoop = 0;\n");
puts("IData __Vchange;\n"); puts("IData __Vchange=1;\n");
puts("for (__Vchange=1; __Vchange; ) {\n"); puts("while (VL_LIKELY(__Vchange)) {\n");
puts( "VL_DEBUG_IF(cout<<\" Clock loop\"<<endl;);\n"); puts( "VL_DEBUG_IF(cout<<\" Clock loop\"<<endl;);\n");
#endif #endif
// FIX coverage! w/combo logic interspersed, this is complicated. // Not exactly correct for coverage. w/combo logic interspersed, this is complicated. Punt.
// Perhaps have temp & each _combo_ turn it on or off // Perhaps have temp & each _combo_ turn it on or off
if (v3Global.opt.coverage()) puts( "Verilated::s_coverageRequest = true;\n"); if (v3Global.opt.coverage()) puts( "vlSymsp->__Vm_coverageRequest = true;\n");
puts( "__Vm_activity = true;\n"); puts( "vlSymsp->__Vm_activity = true;\n");
puts( "_eval();\n"); puts( "_eval(vlSymsp);\n");
if (v3Global.opt.coverage()) puts( "Verilated::s_coverageRequest = false;\n"); if (v3Global.opt.coverage()) puts( "vlSymsp->__Vm_coverageRequest = false;\n");
#ifndef NEW_ORDERING #ifndef NEW_ORDERING
puts( "__Vchange = _change_request();\n"); puts( "__Vchange = _change_request(vlSymsp);\n");
puts( "if (++__VclockLoop > 100) vl_fatal(__FILE__,__LINE__,__FILE__,\"Verilated model didn't converge\");\n"); puts( "if (++__VclockLoop > 100) vl_fatal(__FILE__,__LINE__,__FILE__,\"Verilated model didn't converge\");\n");
puts("}\n"); puts("}\n");
#endif #endif
puts("}\n"); puts("}\n");
// //
puts("\nvoid "+modClassName(modp)+"::eval_initial_loop() {\n"); puts("\nvoid "+modClassName(modp)+"::_eval_initial_loop("+EmitCBaseVisitor::symClassVar()+") {\n");
puts("__Vm_didInit = true;\n"); puts("vlSymsp->__Vm_didInit = true;\n");
puts("_eval_initial();\n"); puts("_eval_initial(vlSymsp);\n");
#ifndef NEW_ORDERING #ifndef NEW_ORDERING
puts( "__Vm_activity = true;\n"); puts( "vlSymsp->__Vm_activity = true;\n");
puts( "int __VclockLoop = 0;\n"); puts( "int __VclockLoop = 0;\n");
puts( "IData __Vchange;\n"); puts( "IData __Vchange=1;\n");
puts( "for (__Vchange=1; __Vchange; ) {\n"); puts( "while (VL_LIKELY(__Vchange)) {\n");
#endif #endif
puts( "_eval_settle();\n"); puts( "_eval_settle(vlSymsp);\n");
puts( "_eval();\n"); puts( "_eval(vlSymsp);\n");
#ifndef NEW_ORDERING #ifndef NEW_ORDERING
puts( "__Vchange = _change_request();\n"); puts( "__Vchange = _change_request(vlSymsp);\n");
puts( "if (++__VclockLoop > 100) vl_fatal(__FILE__,__LINE__,__FILE__,\"Verilated model didn't DC converge\");\n"); puts( "if (++__VclockLoop > 100) vl_fatal(__FILE__,__LINE__,__FILE__,\"Verilated model didn't DC converge\");\n");
puts( "}\n"); puts( "}\n");
#endif #endif
@ -1414,10 +1418,6 @@ void EmitCImp::emitInt(AstModule* modp) {
ofp()->putAlign(V3OutFile::AL_AUTO, sizeof(bool)); ofp()->putAlign(V3OutFile::AL_AUTO, sizeof(bool));
puts("bool\t__Vm_inhibitSim;\t///< Set true to disable evaluation of module\n"); puts("bool\t__Vm_inhibitSim;\t///< Set true to disable evaluation of module\n");
} }
ofp()->putAlign(V3OutFile::AL_AUTO, sizeof(bool));
puts("bool\t__Vm_activity;\t\t///< Used by trace routines to determine change occurred\n");
ofp()->putAlign(V3OutFile::AL_AUTO, sizeof(bool));
puts("bool\t__Vm_didInit;\n");
} }
ofp()->putAlign(V3OutFile::AL_AUTO, 8); ofp()->putAlign(V3OutFile::AL_AUTO, 8);
emitCoverageDecl(modp); // may flip public/private emitCoverageDecl(modp); // may flip public/private
@ -1449,6 +1449,11 @@ void EmitCImp::emitInt(AstModule* modp) {
puts("\n// METHODS\n"); puts("\n// METHODS\n");
ofp()->resetPrivate(); ofp()->resetPrivate();
// We don't need a private copy constructor, as VerilatedModule has one for us.
ofp()->putsPrivate(true);
puts(modClassName(modp)+"& operator= (const "+modClassName(modp)+"&);\t///< Copying not allowed\n");
puts(modClassName(modp)+"(const "+modClassName(modp)+"&);\t///< Copying not allowed\n");
ofp()->putsPrivate(false); // public: ofp()->putsPrivate(false); // public:
if (optSystemC() && modp->isTop()) { if (optSystemC() && modp->isTop()) {
puts("SC_CTOR("+modClassName(modp)+");\n"); puts("SC_CTOR("+modClassName(modp)+");\n");
@ -1466,9 +1471,6 @@ void EmitCImp::emitInt(AstModule* modp) {
puts("void\t__Vconfigure("+symClassName()+"* symsp);\n"); puts("void\t__Vconfigure("+symClassName()+"* symsp);\n");
if (optSystemPerl()) puts("/*AUTOMETHODS*/\n"); if (optSystemPerl()) puts("/*AUTOMETHODS*/\n");
if (modp->isTop()) {
puts("inline bool\tgetClearActivity() { bool r=__Vm_activity; __Vm_activity=false; return r;}\n");
}
emitTextSection(AstType::SCINT); emitTextSection(AstType::SCINT);
puts("\n// Sensitivity blocks\n"); puts("\n// Sensitivity blocks\n");
@ -1480,7 +1482,7 @@ void EmitCImp::emitInt(AstModule* modp) {
puts("void\tinhibitSim(bool flag) { __Vm_inhibitSim=flag; }\t///< Set true to disable evaluation of module\n"); puts("void\tinhibitSim(bool flag) { __Vm_inhibitSim=flag; }\t///< Set true to disable evaluation of module\n");
} }
ofp()->putsPrivate(true); // private: ofp()->putsPrivate(true); // private:
puts("void\teval_initial_loop();\n"); puts("void\t_eval_initial_loop("+EmitCBaseVisitor::symClassVar()+");\n");
#ifndef NEW_ORDERING #ifndef NEW_ORDERING
puts("IData\tchange_request();\n"); puts("IData\tchange_request();\n");
#endif #endif
@ -1515,19 +1517,7 @@ void EmitCImp::emitImp(AstModule* modp) {
(modClassName(modp)+".h\"").c_str()); (modClassName(modp)+".h\"").c_str());
// Us // Us
if (modp->globalSyms() || modp->isTop() || 1 /*for thisp*/) {
puts("#include \""+ symClassName() +".h\"\n"); puts("#include \""+ symClassName() +".h\"\n");
puts("#define VlSym "+ symClassName() +"::s_thisp\n");
} else {
// Instantiated modules
for (AstNode* nodep=modp->stmtsp(); nodep; nodep = nodep->nextp()) {
if (AstCell* cellp=nodep->castCell()) {
ofp()->printf("#include \"%-20s",
(modClassName(cellp->modp())+".h\"").c_str());
puts(" // For "+cellp->name()+"\n");
}
}
}
if (optSystemPerl() && (m_splitFilenum || !m_fast)) { if (optSystemPerl() && (m_splitFilenum || !m_fast)) {
puts("\n"); puts("\n");
@ -1577,9 +1567,6 @@ void EmitCImp::emitImp(AstModule* modp) {
} }
void EmitCImp::emitImpBottom(AstModule* modp) { void EmitCImp::emitImpBottom(AstModule* modp) {
if (modp->globalSyms()) {
puts("#undef VlSym\n");
}
} }
//###################################################################### //######################################################################
@ -1660,7 +1647,6 @@ class EmitCTrace : EmitCStmts {
} }
puts("#include \"SpTraceVcdC.h\"\n"); puts("#include \"SpTraceVcdC.h\"\n");
puts("#include \""+ symClassName() +".h\"\n"); puts("#include \""+ symClassName() +".h\"\n");
puts("#define VlSym "+ symClassName() +"::s_thisp\n");
puts("\n"); puts("\n");
} }
@ -1682,16 +1668,16 @@ class EmitCTrace : EmitCStmts {
puts("void "+topClassName()+"::traceInit(SpTraceVcd* vcdp, void* userthis, uint32_t code) {\n"); puts("void "+topClassName()+"::traceInit(SpTraceVcd* vcdp, void* userthis, uint32_t code) {\n");
puts("// Callback from vcd->open()\n"); puts("// Callback from vcd->open()\n");
puts(topClassName()+"* t=("+topClassName()+"*)userthis;\n"); puts(topClassName()+"* t=("+topClassName()+"*)userthis;\n");
puts(symClassName()+"::init(t); // Setup global symbol table\n"); puts(EmitCBaseVisitor::symClassVar()+" = t->__VlSymsp; // Setup global symbol table\n");
puts("if (!Verilated::calcUnusedSigs()) vl_fatal(__FILE__,__LINE__,__FILE__,\"Turning on wave traces requires Verilated::traceEverOn(true) call before time 0.\");\n"); puts("if (!Verilated::calcUnusedSigs()) vl_fatal(__FILE__,__LINE__,__FILE__,\"Turning on wave traces requires Verilated::traceEverOn(true) call before time 0.\");\n");
puts("t->traceInitThis (vcdp, code);\n"); puts("t->traceInitThis (vlSymsp, vcdp, code);\n");
puts("}\n"); puts("}\n");
puts("void "+topClassName()+"::traceFull(SpTraceVcd* vcdp, void* userthis, uint32_t code) {\n"); puts("void "+topClassName()+"::traceFull(SpTraceVcd* vcdp, void* userthis, uint32_t code) {\n");
puts("// Callback from vcd->dump()\n"); puts("// Callback from vcd->dump()\n");
puts(topClassName()+"* t=("+topClassName()+"*)userthis;\n"); puts(topClassName()+"* t=("+topClassName()+"*)userthis;\n");
puts(symClassName()+"::init(t); // Setup global symbol table\n"); puts(EmitCBaseVisitor::symClassVar()+" = t->__VlSymsp; // Setup global symbol table\n");
puts("t->traceFullThis (vcdp, code);\n"); puts("t->traceFullThis (vlSymsp, vcdp, code);\n");
puts("}\n"); puts("}\n");
puts("\n//======================\n\n"); puts("\n//======================\n\n");
@ -1703,9 +1689,9 @@ class EmitCTrace : EmitCStmts {
puts("void "+topClassName()+"::traceChg(SpTraceVcd* vcdp, void* userthis, uint32_t code) {\n"); puts("void "+topClassName()+"::traceChg(SpTraceVcd* vcdp, void* userthis, uint32_t code) {\n");
puts("// Callback from vcd->dump()\n"); puts("// Callback from vcd->dump()\n");
puts(topClassName()+"* t=("+topClassName()+"*)userthis;\n"); puts(topClassName()+"* t=("+topClassName()+"*)userthis;\n");
puts("if (t->getClearActivity()) {\n"); puts(EmitCBaseVisitor::symClassVar()+" = t->__VlSymsp; // Setup global symbol table\n");
puts(symClassName()+"::init(t); // Setup global symbol table\n"); puts("if (vlSymsp->getClearActivity()) {\n");
puts("t->traceChgThis (vcdp, code);\n"); puts("t->traceChgThis (vlSymsp, vcdp, code);\n");
puts("}\n"); puts("}\n");
puts("}\n"); puts("}\n");
@ -1879,7 +1865,6 @@ public:
v3Global.rootp()->accept(*this); v3Global.rootp()->accept(*this);
puts("#undef VlSym\n");
m_ofp = NULL; m_ofp = NULL;
} }
}; };

View File

@ -108,6 +108,8 @@ public:
bool optSystemC() { return v3Global.opt.systemC(); } bool optSystemC() { return v3Global.opt.systemC(); }
bool optSystemPerl() { return v3Global.opt.systemPerl(); } bool optSystemPerl() { return v3Global.opt.systemPerl(); }
static string symClassName() { return v3Global.opt.prefix()+"__Syms"; } static string symClassName() { return v3Global.opt.prefix()+"__Syms"; }
static string symClassVar() { return symClassName()+"* __restrict vlSymsp"; }
static string symTopAssign() { return v3Global.opt.prefix()+"* __restrict vlTOPp = vlSymsp->TOPp;"; }
static string modClassName(AstModule* modp) { // Return name of current module being processed static string modClassName(AstModule* modp) { // Return name of current module being processed
if (modp->isTop()) { if (modp->isTop()) {
return v3Global.opt.prefix(); return v3Global.opt.prefix();

View File

@ -119,14 +119,23 @@ void EmitCSyms::emitInt() {
puts("\n// SYMS CLASS\n"); puts("\n// SYMS CLASS\n");
puts((string)"class "+symClassName()+" {\n"); puts((string)"class "+symClassName()+" {\n");
puts("public:\n"); ofp()->putsPrivate(false); // public:
puts("// STATIC STATE\n"); //puts("\n// STATIC STATE\n");
puts("static "+symClassName()+"* s_thisp;\n");
puts("\n// LOCAL STATE\n"); puts("\n// LOCAL STATE\n");
ofp()->putAlign(V3OutFile::AL_AUTO, sizeof(uint64_t));
puts("const char* __Vm_namep;\n"); // Must be before subcells, as constructor order needed before _vlCoverInsert. puts("const char* __Vm_namep;\n"); // Must be before subcells, as constructor order needed before _vlCoverInsert.
ofp()->putAlign(V3OutFile::AL_AUTO, sizeof(bool));
puts("bool\t__Vm_activity;\t\t///< Used by trace routines to determine change occurred\n");
ofp()->putAlign(V3OutFile::AL_AUTO, sizeof(bool));
puts("bool\t__Vm_didInit;\n");
if (v3Global.opt.coverage()) {
ofp()->putAlign(V3OutFile::AL_AUTO, sizeof(bool));
puts("bool __Vm_coverageRequest;\n");
}
ofp()->putAlign(V3OutFile::AL_AUTO, sizeof(uint64_t));
puts("\n// SUBCELL STATE\n"); puts("\n// SUBCELL STATE\n");
for (vector<ScopeModPair>::iterator it = m_scopes.begin(); it != m_scopes.end(); ++it) { for (vector<ScopeModPair>::iterator it = m_scopes.begin(); it != m_scopes.end(); ++it) {
AstScope* scopep = it->first; AstModule* modp = it->second; AstScope* scopep = it->first; AstModule* modp = it->second;
@ -143,15 +152,10 @@ void EmitCSyms::emitInt() {
puts("\n// CREATORS\n"); puts("\n// CREATORS\n");
puts(symClassName()+"("+topClassName()+"* topp, const char* namep);\n"); puts(symClassName()+"("+topClassName()+"* topp, const char* namep);\n");
puts((string)"~"+symClassName()+"() {};\n"); puts((string)"~"+symClassName()+"() {};\n");
puts("\n// METHODS\n"); puts("\n// METHODS\n");
puts("/// Called at top of each eval to setup global pointer to top-of-symbol table\n");
puts((string)"inline static void init ("+symClassName()+"* symsp) {\n");
puts("s_thisp = symsp;\n");
puts("}\n");
puts((string)"inline static void init ("+topClassName()+"* topp) {\n");
puts("s_thisp = topp->__VlSymsp;\n");
puts("}\n");
puts("inline const char* name() { return __Vm_namep; }\n"); puts("inline const char* name() { return __Vm_namep; }\n");
puts("inline bool getClearActivity() { bool r=__Vm_activity; __Vm_activity=false; return r;}\n");
puts("\n"); puts("\n");
puts("};\n"); puts("};\n");
puts("#endif /*guard*/\n"); puts("#endif /*guard*/\n");
@ -172,13 +176,15 @@ void EmitCSyms::emitImp() {
puts("#include \""+modClassName(nodep)+".h\"\n"); puts("#include \""+modClassName(nodep)+".h\"\n");
} }
puts("\n// GLOBALS\n"); //puts("\n// GLOBALS\n");
puts(symClassName()+"* "+symClassName()+"::s_thisp;\n");
puts("\n// FUNCTIONS\n"); puts("\n// FUNCTIONS\n");
puts(symClassName()+"::"+symClassName()+"("+topClassName()+"* topp, const char* namep)\n"); puts(symClassName()+"::"+symClassName()+"("+topClassName()+"* topp, const char* namep)\n");
puts("\t// Setup locals\n"); puts("\t// Setup locals\n");
puts("\t: __Vm_namep(namep)\n"); // No leak, as we get destroyed when the top is destroyed puts("\t: __Vm_namep(namep)\n"); // No leak, as we get destroyed when the top is destroyed
puts("\t, __Vm_activity(false)\n");
puts("\t, __Vm_didInit(false)\n");
if (v3Global.opt.coverage()) puts("\t, __Vm_coverageRequest(false)\n");
puts("\t// Setup submodule names\n"); puts("\t// Setup submodule names\n");
char comma=','; char comma=',';
for (vector<ScopeModPair>::iterator it = m_scopes.begin(); it != m_scopes.end(); ++it) { for (vector<ScopeModPair>::iterator it = m_scopes.begin(); it != m_scopes.end(); ++it) {

View File

@ -106,6 +106,7 @@
#include "V3List.h" #include "V3List.h"
#include "V3SenTree.h" #include "V3SenTree.h"
#include "V3Stats.h" #include "V3Stats.h"
#include "V3EmitCBase.h"
#include "V3Order.h" #include "V3Order.h"
#include "V3OrderGraph.h" #include "V3OrderGraph.h"
@ -1380,6 +1381,8 @@ void OrderVisitor::processMoveOne(OrderMoveVertex* vertexp, OrderMoveDomScope* d
if (!m_pomNewFuncp && domainp != m_deleteDomainp) { if (!m_pomNewFuncp && domainp != m_deleteDomainp) {
string name = cfuncName(modp, domainp, scopep, nodep); string name = cfuncName(modp, domainp, scopep, nodep);
m_pomNewFuncp = new AstCFunc(nodep->fileline(), name, scopep); m_pomNewFuncp = new AstCFunc(nodep->fileline(), name, scopep);
m_pomNewFuncp->argTypes(EmitCBaseVisitor::symClassVar());
m_pomNewFuncp->symProlog(true);
if (domainp->hasInitial() || domainp->hasSettle()) m_pomNewFuncp->slow(true); if (domainp->hasInitial() || domainp->hasSettle()) m_pomNewFuncp->slow(true);
scopep->addActivep(m_pomNewFuncp); scopep->addActivep(m_pomNewFuncp);
// Where will we be adding the call? // Where will we be adding the call?
@ -1387,6 +1390,7 @@ void OrderVisitor::processMoveOne(OrderMoveVertex* vertexp, OrderMoveDomScope* d
processMoveLoopStmt(callunderp); processMoveLoopStmt(callunderp);
// Add a top call to it // Add a top call to it
AstCCall* callp = new AstCCall(nodep->fileline(), m_pomNewFuncp); AstCCall* callp = new AstCCall(nodep->fileline(), m_pomNewFuncp);
callp->argTypes("vlSymsp");
callunderp->addStmtsp(callp); callunderp->addStmtsp(callp);
UINFO(6," New "<<m_pomNewFuncp<<endl); UINFO(6," New "<<m_pomNewFuncp<<endl);
} }

View File

@ -38,6 +38,7 @@
#include "V3Task.h" #include "V3Task.h"
#include "V3Inst.h" #include "V3Inst.h"
#include "V3Ast.h" #include "V3Ast.h"
#include "V3EmitCBase.h"
//###################################################################### //######################################################################
@ -290,8 +291,10 @@ private:
funcp->funcPublic(true); funcp->funcPublic(true);
// We need to get a pointer to all of our variables (may have eval'ed something else earlier) // We need to get a pointer to all of our variables (may have eval'ed something else earlier)
funcp->addInitsp(new AstCStmt(nodep->fileline(), funcp->addInitsp(
string(" ")+v3Global.opt.prefix()+"__Syms::init(__VlSymsp);\n")); new AstCStmt(nodep->fileline(),
" "+EmitCBaseVisitor::symClassVar()+" = this->__VlSymsp;\n"));
funcp->addInitsp(new AstCStmt(nodep->fileline()," "+EmitCBaseVisitor::symTopAssign()+"\n"));
// Create list of arguments and move to function // Create list of arguments and move to function
for (AstNode* nextp, *stmtp = nodep->stmtsp(); stmtp; stmtp=nextp) { for (AstNode* nextp, *stmtp = nodep->stmtsp(); stmtp; stmtp=nextp) {

View File

@ -76,8 +76,9 @@ private:
{ {
AstCFunc* funcp = new AstCFunc(nodep->fileline(), "traceInitThis", m_scopetopp); AstCFunc* funcp = new AstCFunc(nodep->fileline(), "traceInitThis", m_scopetopp);
funcp->slow(true); funcp->slow(true);
funcp->argTypes("SpTraceVcd* vcdp, uint32_t code"); funcp->argTypes(EmitCBaseVisitor::symClassVar()+", SpTraceVcd* vcdp, uint32_t code");
funcp->funcType(AstCFuncType::TRACE_INIT); funcp->funcType(AstCFuncType::TRACE_INIT);
funcp->symProlog(true);
m_scopetopp->addActivep(funcp); m_scopetopp->addActivep(funcp);
m_initFuncp = funcp; m_initFuncp = funcp;
UINFO(5," Newfunc "<<funcp<<endl); UINFO(5," Newfunc "<<funcp<<endl);
@ -85,15 +86,17 @@ private:
{ {
AstCFunc* funcp = new AstCFunc(nodep->fileline(), "traceFullThis", m_scopetopp); AstCFunc* funcp = new AstCFunc(nodep->fileline(), "traceFullThis", m_scopetopp);
funcp->slow(true); funcp->slow(true);
funcp->argTypes("SpTraceVcd* vcdp, uint32_t code"); funcp->argTypes(EmitCBaseVisitor::symClassVar()+", SpTraceVcd* vcdp, uint32_t code");
funcp->funcType(AstCFuncType::TRACE_FULL); funcp->funcType(AstCFuncType::TRACE_FULL);
funcp->symProlog(true);
m_scopetopp->addActivep(funcp); m_scopetopp->addActivep(funcp);
m_fullFuncp = funcp; m_fullFuncp = funcp;
} }
{ {
AstCFunc* funcp = new AstCFunc(nodep->fileline(), "traceChgThis", m_scopetopp); AstCFunc* funcp = new AstCFunc(nodep->fileline(), "traceChgThis", m_scopetopp);
funcp->argTypes("SpTraceVcd* vcdp, uint32_t code"); funcp->argTypes(EmitCBaseVisitor::symClassVar()+", SpTraceVcd* vcdp, uint32_t code");
funcp->funcType(AstCFuncType::TRACE_CHANGE); funcp->funcType(AstCFuncType::TRACE_CHANGE);
funcp->symProlog(true);
m_scopetopp->addActivep(funcp); m_scopetopp->addActivep(funcp);
m_chgFuncp = funcp; m_chgFuncp = funcp;
} }