mirror of
https://github.com/verilator/verilator.git
synced 2025-01-01 04:07:34 +00:00
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:
parent
c78254503c
commit
3909ba1cef
3
Changes
3
Changes
@ -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]
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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 =
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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); }
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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));
|
||||
|
@ -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");
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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";
|
||||
|
105
src/V3EmitC.cpp
105
src/V3EmitC.cpp
@ -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;
|
||||
}
|
||||
};
|
||||
|
@ -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();
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user