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**
|
* 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]
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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 =
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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); }
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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));
|
||||||
|
|
|
||||||
|
|
@ -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");
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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()
|
||||||
m_needThis = true;
|
&& 0) { // We no longer thisp-> as still get ambiguation problems
|
||||||
return "thisp->"; // this-> but with restricted aliasing
|
m_needThis = true;
|
||||||
}
|
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";
|
||||||
|
|
|
||||||
105
src/V3EmitC.cpp
105
src/V3EmitC.cpp
|
|
@ -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
|
||||||
|
|
@ -1492,7 +1494,7 @@ void EmitCImp::emitInt(AstModule* modp) {
|
||||||
ofp()->putsPrivate(false); // public:
|
ofp()->putsPrivate(false); // public:
|
||||||
puts("static void\ttraceInit (SpTraceVcd* vcdp, void* userthis, uint32_t code);\n");
|
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\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");
|
puts("} VL_ATTR_ALIGNED(8);\n");
|
||||||
|
|
@ -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;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -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();
|
||||||
|
|
|
||||||
|
|
@ -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) {
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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) {
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue