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**
** 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 `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
rarely, yet take a long time to compile with optimization on. OPT
specifies overall optimization and affects all compiles, including those
OPT_FAST and OPT_SLOW affect. For best results, use OPT="-O2". Nearly the
same results can be had with much better compile times with OPT_FAST="-O1".
Unfortunately, using the optimizer with SystemC files can result in
compiles taking several minutes. (The SystemC libraries have many little
inlined functions that drive the compiler nuts.)
OPT_FAST and OPT_SLOW affect. For best results, use OPT="-O2
-fstrict-aliasing". Nearly the same results can be had with much better
compile times with OPT_FAST="-O1 -fstrict-aliasing". Unfortunately, using
the optimizer with SystemC files can result in compiles taking several
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
optimization bugs around pointer aliasing detection, which can result in 2x

View File

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

View File

@ -121,7 +121,6 @@ public:
struct Verilated {
// Extern Vars
// Below two are used as bool, but having as uint32_t avoids conversion time
static uint32_t s_coverageRequest; ///< Collect coverage info now
private:
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

View File

@ -52,7 +52,7 @@ CPPFLAGS += $(OPT)
# SystemC takes minutes to optimize, thus it is off by default.
#OPT_SLOW =
# 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 =

View File

@ -42,6 +42,7 @@
#include "V3Global.h"
#include "V3Active.h"
#include "V3Ast.h"
#include "V3EmitCBase.h"
//***** See below for main transformation engine
@ -231,6 +232,8 @@ private:
}
if (!m_scopeFinalp) {
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->formCallTree(true);
m_scopeFinalp->slow(true);

View File

@ -422,7 +422,7 @@ public:
virtual string name() const { return m_name; } // * = Scope name
void name(const string& name) { m_name = name; }
string nameDotless() const;
string nameVlSym() const { return (((string)"VlSym->") + nameDotless()); }
string nameVlSym() const { return (((string)"vlSymsp->") + nameDotless()); }
AstModule* modp() const { return m_modp; }
void addVarp(AstNode* nodep) { addOp1p(nodep); }
AstNode* varsp() const { return op1p()->castNode(); } // op1 = AstVarScope's
@ -586,7 +586,6 @@ struct AstModule : public AstNode {
private:
string m_name; // Name of the module
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_modTrace:1; // Tracing this module
bool m_inLibrary:1; // From a library, no error if not used, never top level
@ -596,7 +595,7 @@ private:
public:
AstModule(FileLine* fl, const string& name)
: 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_level(0), m_varNum(0), m_clkReqVarp(NULL) { }
virtual ~AstModule() {}
@ -623,8 +622,6 @@ public:
int varNumGetInc() { return ++m_varNum; }
AstVar* clkReqVarp() const { return m_clkReqVarp; }
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; }
bool modPublic() const { return m_modPublic; }
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_funcPublic:1; // From user public task/function
bool m_isStatic:1; // Function is declared static (no this)
bool m_symProlog:1; // Setup symbol table for later instructions
public:
AstCFunc(FileLine* fl, const string& name, AstScope* scopep, const string& rtnType="")
: AstNode(fl) {
@ -2788,6 +2786,7 @@ public:
m_slow = false;
m_funcPublic = false;
m_isStatic = false;
m_symProlog = false;
}
virtual ~AstCFunc() {}
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 string name() const { return m_name; }
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; }
AstScope* scopep() const { return m_scopep; }
@ -2819,6 +2820,8 @@ public:
AstCFuncType funcType() const { return m_funcType; }
bool isStatic() const { return m_isStatic; }
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
AstNode* argsp() const { return op1p()->castNode(); }
@ -2840,6 +2843,7 @@ struct AstCCall : public AstNodeStmt {
private:
AstCFunc* m_funcp;
string m_hiername;
string m_argTypes;
public:
AstCCall(FileLine* fl, AstCFunc* funcp, AstNode* argsp=NULL)
: AstNodeStmt(fl) {
@ -2863,7 +2867,8 @@ public:
virtual int instrCount() const { return instrCountCall(); }
virtual V3Hash sameHash() const { return V3Hash(funcp()); }
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
virtual bool isGateOptimizable() const { return false; }
virtual bool isPredictOptimizable() const { return false; }
@ -2872,6 +2877,8 @@ public:
AstCFunc* funcp() const { return m_funcp; }
string hiername() const { return m_hiername; }
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(); }
void addArgsp(AstNode* nodep) { addOp1p(nodep); }

View File

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

View File

@ -39,8 +39,9 @@
#include <set>
#include "V3Global.h"
#include "V3Changed.h"
#include "V3Ast.h"
#include "V3Changed.h"
#include "V3EmitCBase.h"
//######################################################################
// Changed state, as a visitor of each AstNode
@ -106,6 +107,8 @@ private:
m_scopetopp = scopep;
// Create change detection function
m_chgFuncp = new AstCFunc(nodep->fileline(), "_change_request", scopep, "bool");
m_chgFuncp->argTypes(EmitCBaseVisitor::symClassVar());
m_chgFuncp->symProlog(true);
m_scopetopp->addActivep(m_chgFuncp);
// 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));

View File

@ -41,6 +41,7 @@
#include "V3Global.h"
#include "V3Clock.h"
#include "V3Ast.h"
#include "V3EmitCBase.h"
//######################################################################
// Clock state, as a visitor of each AstNode
@ -186,30 +187,42 @@ private:
AstNode::userClearTree();
// Make top functions
{
m_evalFuncp = new AstCFunc(nodep->fileline(), "_eval", m_scopep);
m_evalFuncp->dontCombine(true);
m_scopep->addActivep(m_evalFuncp);
AstCFunc* funcp = new AstCFunc(nodep->fileline(), "_eval", m_scopep);
funcp->argTypes(EmitCBaseVisitor::symClassVar());
funcp->dontCombine(true);
funcp->symProlog(true);
m_scopep->addActivep(funcp);
m_evalFuncp = funcp;
}
{
m_initFuncp = new AstCFunc(nodep->fileline(), "_eval_initial", m_scopep);
m_initFuncp->dontCombine(true);
m_initFuncp->slow(true);
m_scopep->addActivep(m_initFuncp);
AstCFunc* funcp = new AstCFunc(nodep->fileline(), "_eval_initial", m_scopep);
funcp->argTypes(EmitCBaseVisitor::symClassVar());
funcp->dontCombine(true);
funcp->slow(true);
funcp->symProlog(true);
m_scopep->addActivep(funcp);
m_initFuncp = funcp;
}
{
m_finalFuncp = new AstCFunc(nodep->fileline(), "final", m_scopep);
m_finalFuncp->skipDecl(true);
m_finalFuncp->dontCombine(true);
m_finalFuncp->slow(true);
m_finalFuncp->addStmtsp(new AstCStmt(nodep->fileline(),
" "+v3Global.opt.prefix()+"__Syms::init(this);\n"));
m_scopep->addActivep(m_finalFuncp);
AstCFunc* funcp = new AstCFunc(nodep->fileline(), "final", m_scopep);
funcp->skipDecl(true);
funcp->dontCombine(true);
funcp->slow(true);
funcp->addInitsp(
new AstCStmt(nodep->fileline(),
" "+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);
m_settleFuncp->dontCombine(true);
m_settleFuncp->slow(true);
m_scopep->addActivep(m_settleFuncp);
AstCFunc* funcp = new AstCFunc(nodep->fileline(), "_eval_settle", m_scopep);
funcp->argTypes(EmitCBaseVisitor::symClassVar());
funcp->dontCombine(true);
funcp->slow(true);
funcp->symProlog(true);
m_scopep->addActivep(funcp);
m_settleFuncp = funcp;
}
// Process the activates
nodep->iterateChildren(*this);
@ -273,12 +286,16 @@ private:
if (!m_scopep) nodep->v3fatalSrc("Initial Active not under scope\n");
AstCFunc* funcp = new AstCFunc(nodep->fileline(), "_initial__"+m_scopep->nameDotless(),
m_scopep);
funcp->argTypes(EmitCBaseVisitor::symClassVar());
funcp->symProlog(true);
funcp->slow(true);
stmtsp->unlinkFrBackWithNext();
funcp->addStmtsp(stmtsp);
nodep->replaceWith(funcp);
// 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 {
nodep->unlinkFrBack();
}
@ -290,7 +307,9 @@ private:
if (nodep->formCallTree()) {
if (nodep->name() == "_final") {
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 {
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 (newfuncp) {
AstCCall* newp = new AstCCall(callp, newfuncp);
newp->argTypes(callp->argTypes());
callp->replaceWith(newp);
addCall(newp); // Fix the table
} else { // Just deleting empty function

View File

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

View File

@ -182,9 +182,12 @@ public:
puts(nodep->hiername());
puts(nodep->funcp()->name());
puts("(");
puts(nodep->argTypes());
bool comma = (nodep->argTypes() != "");
for (AstNode* subnodep=nodep->argsp(); subnodep; subnodep = subnodep->nextp()) {
if (comma) puts(", ");
subnodep->accept(*this);
if (subnodep->nextp()) puts(", ");
comma = true;
}
if (nodep->backp()->castNodeMath() || nodep->backp()->castCReturn()) {
// We should have a separate CCall for math and statement usage, but...
@ -214,7 +217,7 @@ public:
puts(");\n");
}
virtual void visit(AstCoverInc* nodep, AstNUser*) {
puts("if (Verilated::s_coverageRequest)");
puts("if (VL_LIKELY(vlSymsp->__Vm_coverageRequest))");
puts(" ++__Vcoverage[");
puts(cvtToStr(m_coverIds.remap(nodep->declp()))); puts("];\n");
}
@ -596,6 +599,8 @@ class EmitCImp : EmitCStmts {
+"<<name()"
+"<<endl; );\n");
if (nodep->symProlog()) puts(EmitCBaseVisitor::symTopAssign()+"\n");
if (nodep->initsp()) puts("// Variables\n");
ofp()->putAlign(V3OutFile::AL_AUTO, 4);
for (AstNode* subnodep=nodep->argsp(); subnodep; subnodep = subnodep->nextp()) {
@ -1023,8 +1028,6 @@ void EmitCImp::emitVarResets(AstModule* modp) {
puts("// Reset internal values\n");
if (modp->isTop()) {
if (v3Global.opt.inhibitSim()) puts("__Vm_inhibitSim = false;\n");
puts("__Vm_activity = false;\n");
puts("__Vm_didInit = false;\n");
puts("\n");
}
@ -1201,7 +1204,8 @@ void EmitCImp::emitTextSection(AstType type) {
void EmitCImp::emitCellCtors(AstModule* modp) {
if (modp->isTop()) {
// 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()) {
if (AstCell* cellp=nodep->castCell()) {
@ -1229,48 +1233,48 @@ void EmitCImp::emitSensitives() {
void EmitCImp::emitWrapEval(AstModule* modp) {
puts("\nvoid "+modClassName(modp)+"::eval() {\n");
puts("// Setup global symbol table\n");
puts(symClassName()); puts("::init(this);\n");
puts(EmitCBaseVisitor::symClassVar()+" = this->__VlSymsp; // Setup global symbol table\n");
puts(EmitCBaseVisitor::symTopAssign()+"\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()) {
puts("if (__Vm_inhibitSim) return;\n");
puts("if (VL_UNLIKELY(__Vm_inhibitSim)) return;\n");
}
puts("// Evaluate till stable\n");
puts("VL_DEBUG_IF(cout<<\"\\n----TOP Evaluate "+modClassName(modp)+"::eval\"<<endl; );\n");
#ifndef NEW_ORDERING
puts("int __VclockLoop = 0;\n");
puts("IData __Vchange;\n");
puts("for (__Vchange=1; __Vchange; ) {\n");
puts("IData __Vchange=1;\n");
puts("while (VL_LIKELY(__Vchange)) {\n");
puts( "VL_DEBUG_IF(cout<<\" Clock loop\"<<endl;);\n");
#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
if (v3Global.opt.coverage()) puts( "Verilated::s_coverageRequest = true;\n");
puts( "__Vm_activity = true;\n");
puts( "_eval();\n");
if (v3Global.opt.coverage()) puts( "Verilated::s_coverageRequest = false;\n");
if (v3Global.opt.coverage()) puts( "vlSymsp->__Vm_coverageRequest = true;\n");
puts( "vlSymsp->__Vm_activity = true;\n");
puts( "_eval(vlSymsp);\n");
if (v3Global.opt.coverage()) puts( "vlSymsp->__Vm_coverageRequest = false;\n");
#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("}\n");
#endif
puts("}\n");
//
puts("\nvoid "+modClassName(modp)+"::eval_initial_loop() {\n");
puts("__Vm_didInit = true;\n");
puts("_eval_initial();\n");
puts("\nvoid "+modClassName(modp)+"::_eval_initial_loop("+EmitCBaseVisitor::symClassVar()+") {\n");
puts("vlSymsp->__Vm_didInit = true;\n");
puts("_eval_initial(vlSymsp);\n");
#ifndef NEW_ORDERING
puts( "__Vm_activity = true;\n");
puts( "vlSymsp->__Vm_activity = true;\n");
puts( "int __VclockLoop = 0;\n");
puts( "IData __Vchange;\n");
puts( "for (__Vchange=1; __Vchange; ) {\n");
puts( "IData __Vchange=1;\n");
puts( "while (VL_LIKELY(__Vchange)) {\n");
#endif
puts( "_eval_settle();\n");
puts( "_eval();\n");
puts( "_eval_settle(vlSymsp);\n");
puts( "_eval(vlSymsp);\n");
#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( "}\n");
#endif
@ -1414,10 +1418,6 @@ void EmitCImp::emitInt(AstModule* modp) {
ofp()->putAlign(V3OutFile::AL_AUTO, sizeof(bool));
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);
emitCoverageDecl(modp); // may flip public/private
@ -1449,6 +1449,11 @@ void EmitCImp::emitInt(AstModule* modp) {
puts("\n// METHODS\n");
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:
if (optSystemC() && modp->isTop()) {
puts("SC_CTOR("+modClassName(modp)+");\n");
@ -1466,9 +1471,6 @@ void EmitCImp::emitInt(AstModule* modp) {
puts("void\t__Vconfigure("+symClassName()+"* symsp);\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);
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");
}
ofp()->putsPrivate(true); // private:
puts("void\teval_initial_loop();\n");
puts("void\t_eval_initial_loop("+EmitCBaseVisitor::symClassVar()+");\n");
#ifndef NEW_ORDERING
puts("IData\tchange_request();\n");
#endif
@ -1492,7 +1494,7 @@ void EmitCImp::emitInt(AstModule* modp) {
ofp()->putsPrivate(false); // public:
puts("static void\ttraceInit (SpTraceVcd* vcdp, void* userthis, uint32_t code);\n");
puts("static void\ttraceFull (SpTraceVcd* vcdp, void* userthis, uint32_t code);\n");
puts("static void\ttraceChg (SpTraceVcd* vcdp, void* userthis, uint32_t code);\n");
puts("static void\ttraceChg (SpTraceVcd* vcdp, void* userthis, uint32_t code);\n");
}
puts("} VL_ATTR_ALIGNED(8);\n");
@ -1515,19 +1517,7 @@ void EmitCImp::emitImp(AstModule* modp) {
(modClassName(modp)+".h\"").c_str());
// Us
if (modp->globalSyms() || modp->isTop() || 1 /*for thisp*/) {
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");
}
}
}
puts("#include \""+ symClassName() +".h\"\n");
if (optSystemPerl() && (m_splitFilenum || !m_fast)) {
puts("\n");
@ -1577,9 +1567,6 @@ void EmitCImp::emitImp(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 \""+ symClassName() +".h\"\n");
puts("#define VlSym "+ symClassName() +"::s_thisp\n");
puts("\n");
}
@ -1682,16 +1668,16 @@ class EmitCTrace : EmitCStmts {
puts("void "+topClassName()+"::traceInit(SpTraceVcd* vcdp, void* userthis, uint32_t code) {\n");
puts("// Callback from vcd->open()\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("t->traceInitThis (vcdp, code);\n");
puts("t->traceInitThis (vlSymsp, vcdp, code);\n");
puts("}\n");
puts("void "+topClassName()+"::traceFull(SpTraceVcd* vcdp, void* userthis, uint32_t code) {\n");
puts("// Callback from vcd->dump()\n");
puts(topClassName()+"* t=("+topClassName()+"*)userthis;\n");
puts(symClassName()+"::init(t); // Setup global symbol table\n");
puts("t->traceFullThis (vcdp, code);\n");
puts(EmitCBaseVisitor::symClassVar()+" = t->__VlSymsp; // Setup global symbol table\n");
puts("t->traceFullThis (vlSymsp, vcdp, code);\n");
puts("}\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("// Callback from vcd->dump()\n");
puts(topClassName()+"* t=("+topClassName()+"*)userthis;\n");
puts("if (t->getClearActivity()) {\n");
puts(symClassName()+"::init(t); // Setup global symbol table\n");
puts("t->traceChgThis (vcdp, code);\n");
puts(EmitCBaseVisitor::symClassVar()+" = t->__VlSymsp; // Setup global symbol table\n");
puts("if (vlSymsp->getClearActivity()) {\n");
puts("t->traceChgThis (vlSymsp, vcdp, code);\n");
puts("}\n");
puts("}\n");
@ -1879,7 +1865,6 @@ public:
v3Global.rootp()->accept(*this);
puts("#undef VlSym\n");
m_ofp = NULL;
}
};

View File

@ -108,6 +108,8 @@ public:
bool optSystemC() { return v3Global.opt.systemC(); }
bool optSystemPerl() { return v3Global.opt.systemPerl(); }
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
if (modp->isTop()) {
return v3Global.opt.prefix();

View File

@ -119,14 +119,23 @@ void EmitCSyms::emitInt() {
puts("\n// SYMS CLASS\n");
puts((string)"class "+symClassName()+" {\n");
puts("public:\n");
ofp()->putsPrivate(false); // public:
puts("// STATIC STATE\n");
puts("static "+symClassName()+"* s_thisp;\n");
//puts("\n// STATIC 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.
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");
for (vector<ScopeModPair>::iterator it = m_scopes.begin(); it != m_scopes.end(); ++it) {
AstScope* scopep = it->first; AstModule* modp = it->second;
@ -143,15 +152,10 @@ void EmitCSyms::emitInt() {
puts("\n// CREATORS\n");
puts(symClassName()+"("+topClassName()+"* topp, const char* namep);\n");
puts((string)"~"+symClassName()+"() {};\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 bool getClearActivity() { bool r=__Vm_activity; __Vm_activity=false; return r;}\n");
puts("\n");
puts("};\n");
puts("#endif /*guard*/\n");
@ -172,13 +176,15 @@ void EmitCSyms::emitImp() {
puts("#include \""+modClassName(nodep)+".h\"\n");
}
puts("\n// GLOBALS\n");
puts(symClassName()+"* "+symClassName()+"::s_thisp;\n");
//puts("\n// GLOBALS\n");
puts("\n// FUNCTIONS\n");
puts(symClassName()+"::"+symClassName()+"("+topClassName()+"* topp, const char* namep)\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_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");
char comma=',';
for (vector<ScopeModPair>::iterator it = m_scopes.begin(); it != m_scopes.end(); ++it) {

View File

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

View File

@ -38,6 +38,7 @@
#include "V3Task.h"
#include "V3Inst.h"
#include "V3Ast.h"
#include "V3EmitCBase.h"
//######################################################################
@ -290,8 +291,10 @@ private:
funcp->funcPublic(true);
// We need to get a pointer to all of our variables (may have eval'ed something else earlier)
funcp->addInitsp(new AstCStmt(nodep->fileline(),
string(" ")+v3Global.opt.prefix()+"__Syms::init(__VlSymsp);\n"));
funcp->addInitsp(
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
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);
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->symProlog(true);
m_scopetopp->addActivep(funcp);
m_initFuncp = funcp;
UINFO(5," Newfunc "<<funcp<<endl);
@ -85,15 +86,17 @@ private:
{
AstCFunc* funcp = new AstCFunc(nodep->fileline(), "traceFullThis", m_scopetopp);
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->symProlog(true);
m_scopetopp->addActivep(funcp);
m_fullFuncp = funcp;
}
{
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->symProlog(true);
m_scopetopp->addActivep(funcp);
m_chgFuncp = funcp;
}