Internals: clang-format files needed for #2249.
This commit is contained in:
parent
08b74e5ab9
commit
1b94e3b0e2
|
|
@ -16,33 +16,9 @@ clang-format -i examples/make_hello_sc/sc_main.cpp
|
||||||
#clang-format -i examples/make_protect_lib/sim_main.cpp
|
#clang-format -i examples/make_protect_lib/sim_main.cpp
|
||||||
clang-format -i examples/make_tracing_c/sim_main.cpp
|
clang-format -i examples/make_tracing_c/sim_main.cpp
|
||||||
clang-format -i examples/make_tracing_sc/sc_main.cpp
|
clang-format -i examples/make_tracing_sc/sc_main.cpp
|
||||||
clang-format -i include/verilated.cpp
|
clang-format -i include/*.cpp
|
||||||
clang-format -i include/verilated.h
|
clang-format -i include/*.h
|
||||||
clang-format -i include/verilated_config.h.in
|
clang-format -i include/verilated_config.h.in
|
||||||
clang-format -i include/verilated_cov.cpp
|
|
||||||
clang-format -i include/verilated_cov.h
|
|
||||||
clang-format -i include/verilated_cov_key.h
|
|
||||||
clang-format -i include/verilated_dpi.cpp
|
|
||||||
clang-format -i include/verilated_dpi.h
|
|
||||||
clang-format -i include/verilated_fst_c.cpp
|
|
||||||
clang-format -i include/verilated_fst_c.h
|
|
||||||
clang-format -i include/verilated_heavy.h
|
|
||||||
clang-format -i include/verilated_imp.h
|
|
||||||
clang-format -i include/verilated_save.cpp
|
|
||||||
clang-format -i include/verilated_save.h
|
|
||||||
clang-format -i include/verilated_sc.h
|
|
||||||
clang-format -i include/verilated_sym_props.h
|
|
||||||
clang-format -i include/verilated_syms.h
|
|
||||||
clang-format -i include/verilated_threads.cpp
|
|
||||||
clang-format -i include/verilated_threads.h
|
|
||||||
clang-format -i include/verilated_unordered_set_map.h
|
|
||||||
clang-format -i include/verilated_vcd_c.cpp
|
|
||||||
clang-format -i include/verilated_vcd_c.h
|
|
||||||
clang-format -i include/verilated_vcd_sc.cpp
|
|
||||||
clang-format -i include/verilated_vcd_sc.h
|
|
||||||
clang-format -i include/verilated_vpi.cpp
|
|
||||||
clang-format -i include/verilated_vpi.h
|
|
||||||
clang-format -i include/verilatedos.h
|
|
||||||
clang-format -i nodist/fuzzer/wrapper.cpp
|
clang-format -i nodist/fuzzer/wrapper.cpp
|
||||||
clang-format -i src/V3Active.cpp
|
clang-format -i src/V3Active.cpp
|
||||||
clang-format -i src/V3Active.h
|
clang-format -i src/V3Active.h
|
||||||
|
|
@ -107,7 +83,7 @@ clang-format -i src/V3EmitC.h
|
||||||
clang-format -i src/V3EmitCInlines.cpp
|
clang-format -i src/V3EmitCInlines.cpp
|
||||||
##clang-format -i src/V3EmitCMake.cpp
|
##clang-format -i src/V3EmitCMake.cpp
|
||||||
clang-format -i src/V3EmitCMake.h
|
clang-format -i src/V3EmitCMake.h
|
||||||
##clang-format -i src/V3EmitCSyms.cpp
|
clang-format -i src/V3EmitCSyms.cpp
|
||||||
##clang-format -i src/V3EmitMk.cpp
|
##clang-format -i src/V3EmitMk.cpp
|
||||||
clang-format -i src/V3EmitMk.h
|
clang-format -i src/V3EmitMk.h
|
||||||
##clang-format -i src/V3EmitV.cpp
|
##clang-format -i src/V3EmitV.cpp
|
||||||
|
|
@ -175,12 +151,12 @@ clang-format -i src/V3Name.h
|
||||||
##clang-format -i src/V3Number.cpp
|
##clang-format -i src/V3Number.cpp
|
||||||
##clang-format -i src/V3Number.h
|
##clang-format -i src/V3Number.h
|
||||||
clang-format -i src/V3Number_test.cpp
|
clang-format -i src/V3Number_test.cpp
|
||||||
##clang-format -i src/V3Options.cpp
|
clang-format -i src/V3Options.cpp
|
||||||
##clang-format -i src/V3Options.h
|
clang-format -i src/V3Options.h
|
||||||
##clang-format -i src/V3Order.cpp
|
##clang-format -i src/V3Order.cpp
|
||||||
clang-format -i src/V3Order.h
|
clang-format -i src/V3Order.h
|
||||||
clang-format -i src/V3OrderGraph.h
|
clang-format -i src/V3OrderGraph.h
|
||||||
##clang-format -i src/V3Os.cpp
|
clang-format -i src/V3Os.cpp
|
||||||
clang-format -i src/V3Os.h
|
clang-format -i src/V3Os.h
|
||||||
##clang-format -i src/V3Param.cpp
|
##clang-format -i src/V3Param.cpp
|
||||||
clang-format -i src/V3Param.h
|
clang-format -i src/V3Param.h
|
||||||
|
|
@ -248,7 +224,7 @@ clang-format -i src/V3Unroll.h
|
||||||
clang-format -i src/V3Width.h
|
clang-format -i src/V3Width.h
|
||||||
clang-format -i src/V3WidthCommit.h
|
clang-format -i src/V3WidthCommit.h
|
||||||
##clang-format -i src/V3WidthSel.cpp
|
##clang-format -i src/V3WidthSel.cpp
|
||||||
##clang-format -i src/Verilator.cpp
|
clang-format -i src/Verilator.cpp
|
||||||
clang-format -i src/VlcBucket.h
|
clang-format -i src/VlcBucket.h
|
||||||
clang-format -i src/VlcMain.cpp
|
clang-format -i src/VlcMain.cpp
|
||||||
clang-format -i src/VlcOptions.h
|
clang-format -i src/VlcOptions.h
|
||||||
|
|
|
||||||
|
|
@ -36,38 +36,55 @@ class EmitCSyms : EmitCBaseVisitor {
|
||||||
// NODE STATE
|
// NODE STATE
|
||||||
// Cleared on Netlist
|
// Cleared on Netlist
|
||||||
// AstNodeModule::user1() -> bool. Set true __Vconfigure called
|
// AstNodeModule::user1() -> bool. Set true __Vconfigure called
|
||||||
AstUser1InUse m_inuser1;
|
AstUser1InUse m_inuser1;
|
||||||
|
|
||||||
// TYPES
|
// TYPES
|
||||||
struct ScopeData { string m_symName; string m_prettyName; string m_type;
|
struct ScopeData {
|
||||||
|
string m_symName;
|
||||||
|
string m_prettyName;
|
||||||
|
string m_type;
|
||||||
ScopeData(const string& symName, const string& prettyName, const string& type)
|
ScopeData(const string& symName, const string& prettyName, const string& type)
|
||||||
: m_symName(symName), m_prettyName(prettyName), m_type(type) {}
|
: m_symName(symName)
|
||||||
|
, m_prettyName(prettyName)
|
||||||
|
, m_type(type) {}
|
||||||
};
|
};
|
||||||
struct ScopeFuncData { AstScopeName* m_scopep; AstCFunc* m_funcp; AstNodeModule* m_modp;
|
struct ScopeFuncData {
|
||||||
|
AstScopeName* m_scopep;
|
||||||
|
AstCFunc* m_funcp;
|
||||||
|
AstNodeModule* m_modp;
|
||||||
ScopeFuncData(AstScopeName* scopep, AstCFunc* funcp, AstNodeModule* modp)
|
ScopeFuncData(AstScopeName* scopep, AstCFunc* funcp, AstNodeModule* modp)
|
||||||
: m_scopep(scopep), m_funcp(funcp), m_modp(modp) {}
|
: m_scopep(scopep)
|
||||||
|
, m_funcp(funcp)
|
||||||
|
, m_modp(modp) {}
|
||||||
};
|
};
|
||||||
struct ScopeVarData { string m_scopeName; string m_varBasePretty; AstVar* m_varp;
|
struct ScopeVarData {
|
||||||
AstNodeModule* m_modp; AstScope* m_scopep;
|
string m_scopeName;
|
||||||
ScopeVarData(const string& scopeName, const string& varBasePretty,
|
string m_varBasePretty;
|
||||||
AstVar* varp, AstNodeModule* modp, AstScope* scopep)
|
AstVar* m_varp;
|
||||||
: m_scopeName(scopeName), m_varBasePretty(varBasePretty)
|
AstNodeModule* m_modp;
|
||||||
, m_varp(varp), m_modp(modp), m_scopep(scopep) {}
|
AstScope* m_scopep;
|
||||||
|
ScopeVarData(const string& scopeName, const string& varBasePretty, AstVar* varp,
|
||||||
|
AstNodeModule* modp, AstScope* scopep)
|
||||||
|
: m_scopeName(scopeName)
|
||||||
|
, m_varBasePretty(varBasePretty)
|
||||||
|
, m_varp(varp)
|
||||||
|
, m_modp(modp)
|
||||||
|
, m_scopep(scopep) {}
|
||||||
};
|
};
|
||||||
typedef std::map<string,ScopeFuncData> ScopeFuncs;
|
typedef std::map<string, ScopeFuncData> ScopeFuncs;
|
||||||
typedef std::map<string,ScopeVarData> ScopeVars;
|
typedef std::map<string, ScopeVarData> ScopeVars;
|
||||||
typedef std::map<string,ScopeData> ScopeNames;
|
typedef std::map<string, ScopeData> ScopeNames;
|
||||||
typedef std::pair<AstScope*,AstNodeModule*> ScopeModPair;
|
typedef std::pair<AstScope*, AstNodeModule*> ScopeModPair;
|
||||||
typedef std::pair<AstNodeModule*,AstVar*> ModVarPair;
|
typedef std::pair<AstNodeModule*, AstVar*> ModVarPair;
|
||||||
typedef std::vector<string> ScopeNameList;
|
typedef std::vector<string> ScopeNameList;
|
||||||
typedef std::map<string, ScopeNameList> ScopeNameHierarchy;
|
typedef std::map<string, ScopeNameList> ScopeNameHierarchy;
|
||||||
struct CmpName {
|
struct CmpName {
|
||||||
inline bool operator() (const ScopeModPair& lhsp, const ScopeModPair& rhsp) const {
|
inline bool operator()(const ScopeModPair& lhsp, const ScopeModPair& rhsp) const {
|
||||||
return lhsp.first->name() < rhsp.first->name();
|
return lhsp.first->name() < rhsp.first->name();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
struct CmpDpi {
|
struct CmpDpi {
|
||||||
inline bool operator() (const AstCFunc* lhsp, const AstCFunc* rhsp) const {
|
inline bool operator()(const AstCFunc* lhsp, const AstCFunc* rhsp) const {
|
||||||
if (lhsp->dpiImport() != rhsp->dpiImport()) {
|
if (lhsp->dpiImport() != rhsp->dpiImport()) {
|
||||||
// cppcheck-suppress comparisonOfFuncReturningBoolError
|
// cppcheck-suppress comparisonOfFuncReturningBoolError
|
||||||
return lhsp->dpiImport() < rhsp->dpiImport();
|
return lhsp->dpiImport() < rhsp->dpiImport();
|
||||||
|
|
@ -77,23 +94,23 @@ class EmitCSyms : EmitCBaseVisitor {
|
||||||
};
|
};
|
||||||
|
|
||||||
// STATE
|
// STATE
|
||||||
AstCFunc* m_funcp; // Current function
|
AstCFunc* m_funcp; // Current function
|
||||||
AstNodeModule* m_modp; // Current module
|
AstNodeModule* m_modp; // Current module
|
||||||
std::vector<ScopeModPair> m_scopes; // Every scope by module
|
std::vector<ScopeModPair> m_scopes; // Every scope by module
|
||||||
std::vector<AstCFunc*> m_dpis; // DPI functions
|
std::vector<AstCFunc*> m_dpis; // DPI functions
|
||||||
std::vector<ModVarPair> m_modVars; // Each public {mod,var}
|
std::vector<ModVarPair> m_modVars; // Each public {mod,var}
|
||||||
ScopeNames m_scopeNames; // Each unique AstScopeName
|
ScopeNames m_scopeNames; // Each unique AstScopeName
|
||||||
ScopeFuncs m_scopeFuncs; // Each {scope,dpi-export-func}
|
ScopeFuncs m_scopeFuncs; // Each {scope,dpi-export-func}
|
||||||
ScopeVars m_scopeVars; // Each {scope,public-var}
|
ScopeVars m_scopeVars; // Each {scope,public-var}
|
||||||
ScopeNames m_vpiScopeCandidates; // All scopes for VPI
|
ScopeNames m_vpiScopeCandidates; // All scopes for VPI
|
||||||
ScopeNameHierarchy m_vpiScopeHierarchy; // The actual hierarchy of scopes
|
ScopeNameHierarchy m_vpiScopeHierarchy; // The actual hierarchy of scopes
|
||||||
V3LanguageWords m_words; // Reserved word detector
|
V3LanguageWords m_words; // Reserved word detector
|
||||||
int m_coverBins; // Coverage bin number
|
int m_coverBins; // Coverage bin number
|
||||||
bool m_dpiHdrOnly; // Only emit the DPI header
|
bool m_dpiHdrOnly; // Only emit the DPI header
|
||||||
int m_numStmts; // Number of statements output
|
int m_numStmts; // Number of statements output
|
||||||
int m_funcNum; // CFunc split function number
|
int m_funcNum; // CFunc split function number
|
||||||
V3OutCFile* m_ofpBase; // Base (not split) C file
|
V3OutCFile* m_ofpBase; // Base (not split) C file
|
||||||
std::map<int,bool> m_usesVfinal; // Split method uses __Vfinal
|
std::map<int, bool> m_usesVfinal; // Split method uses __Vfinal
|
||||||
|
|
||||||
// METHODS
|
// METHODS
|
||||||
void emitSymHdr();
|
void emitSymHdr();
|
||||||
|
|
@ -115,8 +132,10 @@ class EmitCSyms : EmitCBaseVisitor {
|
||||||
// Generally V3Name should find all of these and throw SYMRSVDWORD.
|
// Generally V3Name should find all of these and throw SYMRSVDWORD.
|
||||||
// We'll still check here because the compiler errors
|
// We'll still check here because the compiler errors
|
||||||
// resulting if we miss this warning are SO nasty
|
// resulting if we miss this warning are SO nasty
|
||||||
nodep->v3error("Symbol matching "+rsvd+" reserved word reached emitter,"
|
nodep->v3error("Symbol matching " + rsvd
|
||||||
" should have hit SYMRSVDWORD: "<<nodep->prettyNameQ());
|
+ " reserved word reached emitter,"
|
||||||
|
" should have hit SYMRSVDWORD: "
|
||||||
|
<< nodep->prettyNameQ());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -124,17 +143,11 @@ class EmitCSyms : EmitCBaseVisitor {
|
||||||
string scopeSymString(const string& scpname) {
|
string scopeSymString(const string& scpname) {
|
||||||
string out = scpname;
|
string out = scpname;
|
||||||
string::size_type pos;
|
string::size_type pos;
|
||||||
while ((pos = out.find("__PVT__")) != string::npos) {
|
while ((pos = out.find("__PVT__")) != string::npos) out.replace(pos, 7, "");
|
||||||
out.replace(pos, 7, "");
|
|
||||||
}
|
|
||||||
if (out.substr(0, 10) == "TOP__DOT__") out.replace(0, 10, "");
|
if (out.substr(0, 10) == "TOP__DOT__") out.replace(0, 10, "");
|
||||||
if (out.substr(0, 4) == "TOP.") out.replace(0, 4, "");
|
if (out.substr(0, 4) == "TOP.") out.replace(0, 4, "");
|
||||||
while ((pos = out.find('.')) != string::npos) {
|
while ((pos = out.find('.')) != string::npos) out.replace(pos, 1, "__");
|
||||||
out.replace(pos, 1, "__");
|
while ((pos = out.find("__DOT__")) != string::npos) out.replace(pos, 7, "__");
|
||||||
}
|
|
||||||
while ((pos = out.find("__DOT__")) != string::npos) {
|
|
||||||
out.replace(pos, 7, "__");
|
|
||||||
}
|
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -147,9 +160,9 @@ class EmitCSyms : EmitCBaseVisitor {
|
||||||
while ((pos = out.find("__0")) != string::npos) {
|
while ((pos = out.find("__0")) != string::npos) {
|
||||||
unsigned int x;
|
unsigned int x;
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
ss << std::hex << out.substr(pos+3, 2);
|
ss << std::hex << out.substr(pos + 3, 2);
|
||||||
ss >> x;
|
ss >> x;
|
||||||
out.replace(pos, 5, 1, (char) x);
|
out.replace(pos, 5, 1, (char)x);
|
||||||
}
|
}
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
@ -158,7 +171,7 @@ class EmitCSyms : EmitCBaseVisitor {
|
||||||
while (!scp.empty()) {
|
while (!scp.empty()) {
|
||||||
ScopeNames::const_iterator scpit = m_vpiScopeCandidates.find(scp);
|
ScopeNames::const_iterator scpit = m_vpiScopeCandidates.find(scp);
|
||||||
if ((scpit != m_vpiScopeCandidates.end())
|
if ((scpit != m_vpiScopeCandidates.end())
|
||||||
&& (m_scopeNames.find(scp) == m_scopeNames.end())) {
|
&& (m_scopeNames.find(scp) == m_scopeNames.end())) {
|
||||||
m_scopeNames.insert(make_pair(scpit->second.m_symName, scpit->second));
|
m_scopeNames.insert(make_pair(scpit->second.m_symName, scpit->second));
|
||||||
}
|
}
|
||||||
string::size_type pos = scp.rfind("__DOT__");
|
string::size_type pos = scp.rfind("__DOT__");
|
||||||
|
|
@ -174,11 +187,12 @@ class EmitCSyms : EmitCBaseVisitor {
|
||||||
// We didn't have all m_scopes loaded when we encountered variables, so expand them now
|
// We didn't have all m_scopes loaded when we encountered variables, so expand them now
|
||||||
// It would be less code if each module inserted its own variables.
|
// It would be less code if each module inserted its own variables.
|
||||||
// Someday. For now public isn't common.
|
// Someday. For now public isn't common.
|
||||||
for (std::vector<ScopeModPair>::iterator itsc = m_scopes.begin();
|
for (std::vector<ScopeModPair>::iterator itsc = m_scopes.begin(); itsc != m_scopes.end();
|
||||||
itsc != m_scopes.end(); ++itsc) {
|
++itsc) {
|
||||||
AstScope* scopep = itsc->first; AstNodeModule* smodp = itsc->second;
|
AstScope* scopep = itsc->first;
|
||||||
for (std::vector<ModVarPair>::iterator it = m_modVars.begin();
|
AstNodeModule* smodp = itsc->second;
|
||||||
it != m_modVars.end(); ++it) {
|
for (std::vector<ModVarPair>::iterator it = m_modVars.begin(); it != m_modVars.end();
|
||||||
|
++it) {
|
||||||
AstNodeModule* modp = it->first;
|
AstNodeModule* modp = it->first;
|
||||||
AstVar* varp = it->second;
|
AstVar* varp = it->second;
|
||||||
if (modp == smodp) {
|
if (modp == smodp) {
|
||||||
|
|
@ -186,28 +200,27 @@ class EmitCSyms : EmitCBaseVisitor {
|
||||||
// original-ish full scope and variable name under that scope.
|
// original-ish full scope and variable name under that scope.
|
||||||
// The module instance name is included later, when we
|
// The module instance name is included later, when we
|
||||||
// know the scopes this module is under
|
// know the scopes this module is under
|
||||||
string whole = scopep->name()+"__DOT__"+varp->name();
|
string whole = scopep->name() + "__DOT__" + varp->name();
|
||||||
string scpName;
|
string scpName;
|
||||||
string varBase;
|
string varBase;
|
||||||
if (whole.substr(0, 10) == "__DOT__TOP") whole.replace(0, 10, "");
|
if (whole.substr(0, 10) == "__DOT__TOP") whole.replace(0, 10, "");
|
||||||
string::size_type dpos = whole.rfind("__DOT__");
|
string::size_type dpos = whole.rfind("__DOT__");
|
||||||
if (dpos != string::npos) {
|
if (dpos != string::npos) {
|
||||||
scpName = whole.substr(0, dpos);
|
scpName = whole.substr(0, dpos);
|
||||||
varBase = whole.substr(dpos+strlen("__DOT__"));
|
varBase = whole.substr(dpos + strlen("__DOT__"));
|
||||||
} else {
|
} else {
|
||||||
varBase = whole;
|
varBase = whole;
|
||||||
}
|
}
|
||||||
//UINFO(9,"For "<<scopep->name()<<" - "<<varp->name()<<" Scp "<<scpName<<" Var "<<varBase<<endl);
|
// UINFO(9,"For "<<scopep->name()<<" - "<<varp->name()<<" Scp "<<scpName<<"
|
||||||
|
// Var "<<varBase<<endl);
|
||||||
string varBasePretty = AstNode::prettyName(varBase);
|
string varBasePretty = AstNode::prettyName(varBase);
|
||||||
string scpPretty = AstNode::prettyName(scpName);
|
string scpPretty = AstNode::prettyName(scpName);
|
||||||
string scpSym = scopeSymString(scpName);
|
string scpSym = scopeSymString(scpName);
|
||||||
//UINFO(9," scnameins sp "<<scpName<<" sp "<<scpPretty<<" ss "<<scpSym<<endl);
|
// UINFO(9," scnameins sp "<<scpName<<" sp "<<scpPretty<<" ss "<<scpSym<<endl);
|
||||||
if (v3Global.opt.vpi()) {
|
if (v3Global.opt.vpi()) varHierarchyScopes(scpName);
|
||||||
varHierarchyScopes(scpName);
|
|
||||||
}
|
|
||||||
if (m_scopeNames.find(scpSym) == m_scopeNames.end()) {
|
if (m_scopeNames.find(scpSym) == m_scopeNames.end()) {
|
||||||
m_scopeNames.insert(make_pair(scpSym, ScopeData(scpSym, scpPretty,
|
m_scopeNames.insert(
|
||||||
"SCOPE_OTHER")));
|
make_pair(scpSym, ScopeData(scpSym, scpPretty, "SCOPE_OTHER")));
|
||||||
}
|
}
|
||||||
m_scopeVars.insert(
|
m_scopeVars.insert(
|
||||||
make_pair(scpSym + " " + varp->name(),
|
make_pair(scpSym + " " + varp->name(),
|
||||||
|
|
@ -218,7 +231,8 @@ class EmitCSyms : EmitCBaseVisitor {
|
||||||
}
|
}
|
||||||
|
|
||||||
void buildVpiHierarchy() {
|
void buildVpiHierarchy() {
|
||||||
for (ScopeNames::const_iterator it = m_scopeNames.begin(); it != m_scopeNames.end(); ++it) {
|
for (ScopeNames::const_iterator it = m_scopeNames.begin(); it != m_scopeNames.end();
|
||||||
|
++it) {
|
||||||
if (it->second.m_type != "SCOPE_MODULE") continue;
|
if (it->second.m_type != "SCOPE_MODULE") continue;
|
||||||
|
|
||||||
string name = it->second.m_prettyName;
|
string name = it->second.m_prettyName;
|
||||||
|
|
@ -244,9 +258,7 @@ class EmitCSyms : EmitCBaseVisitor {
|
||||||
iterateChildren(nodep);
|
iterateChildren(nodep);
|
||||||
varsExpand();
|
varsExpand();
|
||||||
|
|
||||||
if (v3Global.opt.vpi()) {
|
if (v3Global.opt.vpi()) buildVpiHierarchy();
|
||||||
buildVpiHierarchy();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sort by names, so line/process order matters less
|
// Sort by names, so line/process order matters less
|
||||||
stable_sort(m_scopes.begin(), m_scopes.end(), CmpName());
|
stable_sort(m_scopes.begin(), m_scopes.end(), CmpName());
|
||||||
|
|
@ -274,12 +286,11 @@ class EmitCSyms : EmitCBaseVisitor {
|
||||||
}
|
}
|
||||||
virtual void visit(AstCellInline* nodep) VL_OVERRIDE {
|
virtual void visit(AstCellInline* nodep) VL_OVERRIDE {
|
||||||
if (v3Global.opt.vpi()) {
|
if (v3Global.opt.vpi()) {
|
||||||
string type = (nodep->origModName() == "__BEGIN__") ? "SCOPE_OTHER"
|
string type = (nodep->origModName() == "__BEGIN__") ? "SCOPE_OTHER" : "SCOPE_MODULE";
|
||||||
: "SCOPE_MODULE";
|
|
||||||
string name = nodep->scopep()->name() + "__DOT__" + nodep->name();
|
string name = nodep->scopep()->name() + "__DOT__" + nodep->name();
|
||||||
string name_dedot = AstNode::dedotName(name);
|
string name_dedot = AstNode::dedotName(name);
|
||||||
m_vpiScopeCandidates.insert(make_pair(name, ScopeData(scopeSymString(name),
|
m_vpiScopeCandidates.insert(
|
||||||
name_dedot, type)));
|
make_pair(name, ScopeData(scopeSymString(name), name_dedot, type)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
virtual void visit(AstScope* nodep) VL_OVERRIDE {
|
virtual void visit(AstScope* nodep) VL_OVERRIDE {
|
||||||
|
|
@ -290,28 +301,28 @@ class EmitCSyms : EmitCBaseVisitor {
|
||||||
|
|
||||||
if (v3Global.opt.vpi() && !nodep->isTop()) {
|
if (v3Global.opt.vpi() && !nodep->isTop()) {
|
||||||
string name_dedot = AstNode::dedotName(nodep->shortName());
|
string name_dedot = AstNode::dedotName(nodep->shortName());
|
||||||
m_vpiScopeCandidates.insert(make_pair(nodep->name(),
|
m_vpiScopeCandidates.insert(
|
||||||
ScopeData(scopeSymString(nodep->name()),
|
make_pair(nodep->name(),
|
||||||
name_dedot, "SCOPE_MODULE")));
|
ScopeData(scopeSymString(nodep->name()), name_dedot, "SCOPE_MODULE")));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
virtual void visit(AstScopeName* nodep) VL_OVERRIDE {
|
virtual void visit(AstScopeName* nodep) VL_OVERRIDE {
|
||||||
string name = nodep->scopeSymName();
|
string name = nodep->scopeSymName();
|
||||||
//UINFO(9,"scnameins sp "<<nodep->name()<<" sp "<<nodep->scopePrettySymName()<<" ss "<<name<<endl);
|
// UINFO(9,"scnameins sp "<<nodep->name()<<" sp "<<nodep->scopePrettySymName()<<" ss
|
||||||
|
// "<<name<<endl);
|
||||||
if (m_scopeNames.find(name) == m_scopeNames.end()) {
|
if (m_scopeNames.find(name) == m_scopeNames.end()) {
|
||||||
m_scopeNames.insert(make_pair(name, ScopeData(name, nodep->scopePrettySymName(),
|
m_scopeNames.insert(
|
||||||
"SCOPE_OTHER")));
|
make_pair(name, ScopeData(name, nodep->scopePrettySymName(), "SCOPE_OTHER")));
|
||||||
}
|
}
|
||||||
if (nodep->dpiExport()) {
|
if (nodep->dpiExport()) {
|
||||||
UASSERT_OBJ(m_funcp, nodep, "ScopeName not under DPI function");
|
UASSERT_OBJ(m_funcp, nodep, "ScopeName not under DPI function");
|
||||||
m_scopeFuncs.insert(make_pair(name + " " + m_funcp->name(),
|
m_scopeFuncs.insert(
|
||||||
ScopeFuncData(nodep, m_funcp, m_modp)));
|
make_pair(name + " " + m_funcp->name(), ScopeFuncData(nodep, m_funcp, m_modp)));
|
||||||
} else {
|
} else {
|
||||||
if (m_scopeNames.find(nodep->scopeDpiName()) == m_scopeNames.end()) {
|
if (m_scopeNames.find(nodep->scopeDpiName()) == m_scopeNames.end()) {
|
||||||
m_scopeNames.insert(make_pair(nodep->scopeDpiName(),
|
m_scopeNames.insert(make_pair(
|
||||||
ScopeData(nodep->scopeDpiName(),
|
nodep->scopeDpiName(),
|
||||||
nodep->scopePrettyDpiName(),
|
ScopeData(nodep->scopeDpiName(), nodep->scopePrettyDpiName(), "SCOPE_OTHER")));
|
||||||
"SCOPE_OTHER")));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -319,7 +330,9 @@ class EmitCSyms : EmitCBaseVisitor {
|
||||||
nameCheck(nodep);
|
nameCheck(nodep);
|
||||||
iterateChildren(nodep);
|
iterateChildren(nodep);
|
||||||
if (nodep->isSigUserRdPublic()
|
if (nodep->isSigUserRdPublic()
|
||||||
&& !nodep->isParam()) { // The VPI functions require a pointer to allow modification, but parameters are constants
|
// The VPI functions require a pointer to allow modification,
|
||||||
|
// but parameters are constants
|
||||||
|
&& !nodep->isParam()) {
|
||||||
m_modVars.push_back(make_pair(m_modp, nodep));
|
m_modVars.push_back(make_pair(m_modp, nodep));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -331,9 +344,7 @@ class EmitCSyms : EmitCBaseVisitor {
|
||||||
}
|
}
|
||||||
virtual void visit(AstCFunc* nodep) VL_OVERRIDE {
|
virtual void visit(AstCFunc* nodep) VL_OVERRIDE {
|
||||||
nameCheck(nodep);
|
nameCheck(nodep);
|
||||||
if (nodep->dpiImport() || nodep->dpiExportWrapper()) {
|
if (nodep->dpiImport() || nodep->dpiExportWrapper()) m_dpis.push_back(nodep);
|
||||||
m_dpis.push_back(nodep);
|
|
||||||
}
|
|
||||||
m_funcp = nodep;
|
m_funcp = nodep;
|
||||||
iterateChildren(nodep);
|
iterateChildren(nodep);
|
||||||
m_funcp = NULL;
|
m_funcp = NULL;
|
||||||
|
|
@ -357,9 +368,9 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
void EmitCSyms::emitSymHdr() {
|
void EmitCSyms::emitSymHdr() {
|
||||||
UINFO(6,__FUNCTION__<<": "<<endl);
|
UINFO(6, __FUNCTION__ << ": " << endl);
|
||||||
string filename = v3Global.opt.makeDir()+"/"+symClassName()+".h";
|
string filename = v3Global.opt.makeDir() + "/" + symClassName() + ".h";
|
||||||
newCFile(filename, true/*slow*/, false/*source*/);
|
newCFile(filename, true /*slow*/, false /*source*/);
|
||||||
|
|
||||||
if (v3Global.opt.systemC()) {
|
if (v3Global.opt.systemC()) {
|
||||||
m_ofp = new V3OutScFile(filename);
|
m_ofp = new V3OutScFile(filename);
|
||||||
|
|
@ -368,7 +379,8 @@ void EmitCSyms::emitSymHdr() {
|
||||||
}
|
}
|
||||||
|
|
||||||
ofp()->putsHeader();
|
ofp()->putsHeader();
|
||||||
puts("// DESCR" "IPTION: Verilator output: Symbol table internal header\n");
|
puts("// DESCR"
|
||||||
|
"IPTION: Verilator output: Symbol table internal header\n");
|
||||||
puts("//\n");
|
puts("//\n");
|
||||||
puts("// Internal details; most calling programs do not need this header,\n");
|
puts("// Internal details; most calling programs do not need this header,\n");
|
||||||
puts("// unless using verilator public meta comments.\n");
|
puts("// unless using verilator public meta comments.\n");
|
||||||
|
|
@ -392,25 +404,27 @@ void EmitCSyms::emitSymHdr() {
|
||||||
|
|
||||||
if (v3Global.dpi()) {
|
if (v3Global.dpi()) {
|
||||||
puts("\n// DPI TYPES for DPI Export callbacks (Internal use)\n");
|
puts("\n// DPI TYPES for DPI Export callbacks (Internal use)\n");
|
||||||
std::map<string,int> types; // Remove duplicates and sort
|
std::map<string, int> types; // Remove duplicates and sort
|
||||||
for (ScopeFuncs::iterator it = m_scopeFuncs.begin(); it != m_scopeFuncs.end(); ++it) {
|
for (ScopeFuncs::iterator it = m_scopeFuncs.begin(); it != m_scopeFuncs.end(); ++it) {
|
||||||
AstCFunc* funcp = it->second.m_funcp;
|
AstCFunc* funcp = it->second.m_funcp;
|
||||||
if (funcp->dpiExport()) {
|
if (funcp->dpiExport()) {
|
||||||
string cbtype = protect(v3Global.opt.prefix()+"__Vcb_"+funcp->cname()+"_t");
|
string cbtype = protect(v3Global.opt.prefix() + "__Vcb_" + funcp->cname() + "_t");
|
||||||
types["typedef void (*"+cbtype+") ("+cFuncArgs(funcp)+");\n"] = 1;
|
types["typedef void (*" + cbtype + ") (" + cFuncArgs(funcp) + ");\n"] = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (std::map<string,int>::iterator it = types.begin(); it != types.end(); ++it) {
|
for (std::map<string, int>::iterator it = types.begin(); it != types.end(); ++it) {
|
||||||
puts(it->first);
|
puts(it->first);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
puts("\n// SYMS CLASS\n");
|
puts("\n// SYMS CLASS\n");
|
||||||
puts(string("class ")+symClassName()+" : public VerilatedSyms {\n");
|
puts(string("class ") + symClassName() + " : public VerilatedSyms {\n");
|
||||||
ofp()->putsPrivate(false); // public:
|
ofp()->putsPrivate(false); // public:
|
||||||
|
|
||||||
puts("\n// LOCAL STATE\n");
|
puts("\n// LOCAL STATE\n");
|
||||||
puts("const char* __Vm_namep;\n"); // Must be before subcells, as constructor order needed before _vlCoverInsert.
|
// Must be before subcells, as constructor order needed before _vlCoverInsert.
|
||||||
|
puts("const char* __Vm_namep;\n");
|
||||||
|
|
||||||
if (v3Global.needTraceDumper()) {
|
if (v3Global.needTraceDumper()) {
|
||||||
// __Vm_dumperp is local, otherwise we wouldn't know what design's eval()
|
// __Vm_dumperp is local, otherwise we wouldn't know what design's eval()
|
||||||
// should call a global dumpperp
|
// should call a global dumpperp
|
||||||
|
|
@ -449,7 +463,7 @@ void EmitCSyms::emitSymHdr() {
|
||||||
if (!m_scopeNames.empty()) { // Scope names
|
if (!m_scopeNames.empty()) { // Scope names
|
||||||
puts("\n// SCOPE NAMES\n");
|
puts("\n// SCOPE NAMES\n");
|
||||||
for (ScopeNames::iterator it = m_scopeNames.begin(); it != m_scopeNames.end(); ++it) {
|
for (ScopeNames::iterator it = m_scopeNames.begin(); it != m_scopeNames.end(); ++it) {
|
||||||
puts("VerilatedScope "+protect("__Vscope_"+it->second.m_symName)+";\n");
|
puts("VerilatedScope " + protect("__Vscope_" + it->second.m_symName) + ";\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -459,16 +473,15 @@ void EmitCSyms::emitSymHdr() {
|
||||||
}
|
}
|
||||||
|
|
||||||
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");
|
||||||
|
|
||||||
for (std::map<int,bool>::iterator it = m_usesVfinal.begin();
|
for (std::map<int, bool>::iterator it = m_usesVfinal.begin(); it != m_usesVfinal.end(); ++it) {
|
||||||
it != m_usesVfinal.end(); ++it) {
|
puts("void " + symClassName() + "_" + cvtToStr(it->first) + "(");
|
||||||
puts("void "+symClassName()+"_"+cvtToStr(it->first)+"(");
|
|
||||||
if (it->second) {
|
if (it->second) {
|
||||||
puts("int __Vfinal");
|
puts("int __Vfinal");
|
||||||
} else {
|
} else {
|
||||||
puts(topClassName()+"* topp");
|
puts(topClassName() + "* topp");
|
||||||
}
|
}
|
||||||
puts(");\n");
|
puts(");\n");
|
||||||
}
|
}
|
||||||
|
|
@ -476,11 +489,12 @@ void EmitCSyms::emitSymHdr() {
|
||||||
puts("\n// METHODS\n");
|
puts("\n// METHODS\n");
|
||||||
puts("inline const char* name() { return __Vm_namep; }\n");
|
puts("inline const char* name() { return __Vm_namep; }\n");
|
||||||
if (v3Global.opt.trace()) {
|
if (v3Global.opt.trace()) {
|
||||||
puts("inline bool getClearActivity() { bool r=__Vm_activity; __Vm_activity=false; return r; }\n");
|
puts("inline bool getClearActivity() { bool r=__Vm_activity; "
|
||||||
|
"__Vm_activity=false; return r; }\n");
|
||||||
}
|
}
|
||||||
if (v3Global.opt.savable() ) {
|
if (v3Global.opt.savable()) {
|
||||||
puts("void "+protect("__Vserialize")+"(VerilatedSerialize& os);\n");
|
puts("void " + protect("__Vserialize") + "(VerilatedSerialize& os);\n");
|
||||||
puts("void "+protect("__Vdeserialize")+"(VerilatedDeserialize& os);\n");
|
puts("void " + protect("__Vdeserialize") + "(VerilatedDeserialize& os);\n");
|
||||||
}
|
}
|
||||||
puts("\n");
|
puts("\n");
|
||||||
puts("} VL_ATTR_ALIGNED(VL_CACHE_LINE_BYTES);\n");
|
puts("} VL_ATTR_ALIGNED(VL_CACHE_LINE_BYTES);\n");
|
||||||
|
|
@ -497,12 +511,15 @@ void EmitCSyms::closeSplit() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmitCSyms::checkSplit(bool usesVfinal) {
|
void EmitCSyms::checkSplit(bool usesVfinal) {
|
||||||
if (m_ofp && (!v3Global.opt.outputSplitCFuncs() ||
|
if (m_ofp
|
||||||
m_numStmts < v3Global.opt.outputSplitCFuncs())) return;
|
&& (!v3Global.opt.outputSplitCFuncs() || m_numStmts < v3Global.opt.outputSplitCFuncs())) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
m_numStmts = 0;
|
m_numStmts = 0;
|
||||||
string filename = v3Global.opt.makeDir()+"/"+symClassName()+"__"+cvtToStr(++m_funcNum)+".cpp";
|
string filename
|
||||||
AstCFile* cfilep = newCFile(filename, true/*slow*/, true/*source*/);
|
= v3Global.opt.makeDir() + "/" + symClassName() + "__" + cvtToStr(++m_funcNum) + ".cpp";
|
||||||
|
AstCFile* cfilep = newCFile(filename, true /*slow*/, true /*source*/);
|
||||||
cfilep->support(true);
|
cfilep->support(true);
|
||||||
m_usesVfinal[m_funcNum] = usesVfinal;
|
m_usesVfinal[m_funcNum] = usesVfinal;
|
||||||
closeSplit();
|
closeSplit();
|
||||||
|
|
@ -513,7 +530,7 @@ void EmitCSyms::checkSplit(bool usesVfinal) {
|
||||||
m_ofp = new V3OutCFile(filename);
|
m_ofp = new V3OutCFile(filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_ofpBase->puts(symClassName()+"_"+cvtToStr(m_funcNum)+"(");
|
m_ofpBase->puts(symClassName() + "_" + cvtToStr(m_funcNum) + "(");
|
||||||
if (usesVfinal) {
|
if (usesVfinal) {
|
||||||
m_ofpBase->puts("__Vfinal");
|
m_ofpBase->puts("__Vfinal");
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -522,22 +539,23 @@ void EmitCSyms::checkSplit(bool usesVfinal) {
|
||||||
m_ofpBase->puts(");\n");
|
m_ofpBase->puts(");\n");
|
||||||
|
|
||||||
emitSymImpPreamble();
|
emitSymImpPreamble();
|
||||||
puts("void "+symClassName()+"::"+symClassName()+"_"+cvtToStr(m_funcNum)+"(");
|
puts("void " + symClassName() + "::" + symClassName() + "_" + cvtToStr(m_funcNum) + "(");
|
||||||
if (usesVfinal) {
|
if (usesVfinal) {
|
||||||
puts("int __Vfinal");
|
puts("int __Vfinal");
|
||||||
} else {
|
} else {
|
||||||
puts(topClassName()+"* topp");
|
puts(topClassName() + "* topp");
|
||||||
}
|
}
|
||||||
puts(") {\n");
|
puts(") {\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmitCSyms::emitSymImpPreamble() {
|
void EmitCSyms::emitSymImpPreamble() {
|
||||||
ofp()->putsHeader();
|
ofp()->putsHeader();
|
||||||
puts("// DESCR" "IPTION: Verilator output: Symbol table implementation internals\n");
|
puts("// DESCR"
|
||||||
|
"IPTION: Verilator output: Symbol table implementation internals\n");
|
||||||
puts("\n");
|
puts("\n");
|
||||||
|
|
||||||
// Includes
|
// Includes
|
||||||
puts("#include \""+symClassName()+".h\"\n");
|
puts("#include \"" + symClassName() + ".h\"\n");
|
||||||
for (AstNodeModule* nodep = v3Global.rootp()->modulesp(); nodep;
|
for (AstNodeModule* nodep = v3Global.rootp()->modulesp(); nodep;
|
||||||
nodep = VN_CAST(nodep->nextp(), NodeModule)) {
|
nodep = VN_CAST(nodep->nextp(), NodeModule)) {
|
||||||
if (VN_IS(nodep, Class)) continue; // Class included earlier
|
if (VN_IS(nodep, Class)) continue; // Class included earlier
|
||||||
|
|
@ -546,9 +564,9 @@ void EmitCSyms::emitSymImpPreamble() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmitCSyms::emitSymImp() {
|
void EmitCSyms::emitSymImp() {
|
||||||
UINFO(6,__FUNCTION__<<": "<<endl);
|
UINFO(6, __FUNCTION__ << ": " << endl);
|
||||||
string filename = v3Global.opt.makeDir()+"/"+symClassName()+".cpp";
|
string filename = v3Global.opt.makeDir() + "/" + symClassName() + ".cpp";
|
||||||
AstCFile* cfilep = newCFile(filename, true/*slow*/, true/*source*/);
|
AstCFile* cfilep = newCFile(filename, true /*slow*/, true /*source*/);
|
||||||
cfilep->support(true);
|
cfilep->support(true);
|
||||||
|
|
||||||
if (v3Global.opt.systemC()) {
|
if (v3Global.opt.systemC()) {
|
||||||
|
|
@ -560,31 +578,31 @@ void EmitCSyms::emitSymImp() {
|
||||||
m_ofpBase = m_ofp;
|
m_ofpBase = m_ofp;
|
||||||
emitSymImpPreamble();
|
emitSymImpPreamble();
|
||||||
|
|
||||||
//puts("\n// GLOBALS\n");
|
// puts("\n// GLOBALS\n");
|
||||||
|
|
||||||
puts("\n");
|
puts("\n");
|
||||||
|
|
||||||
if (v3Global.opt.savable() ) {
|
if (v3Global.opt.savable()) {
|
||||||
puts("\n");
|
puts("\n");
|
||||||
for (int de=0; de<2; ++de) {
|
for (int de = 0; de < 2; ++de) {
|
||||||
string classname = de ? "VerilatedDeserialize" : "VerilatedSerialize";
|
string classname = de ? "VerilatedDeserialize" : "VerilatedSerialize";
|
||||||
string funcname = de ? "__Vdeserialize" : "__Vserialize";
|
string funcname = de ? "__Vdeserialize" : "__Vserialize";
|
||||||
string op = de ? ">>" : "<<";
|
string op = de ? ">>" : "<<";
|
||||||
// NOLINTNEXTLINE(performance-inefficient-string-concatenation)
|
// NOLINTNEXTLINE(performance-inefficient-string-concatenation)
|
||||||
puts("void "+symClassName()+"::"+protect(funcname)+"("+classname+"& os) {\n");
|
puts("void " + symClassName() + "::" + protect(funcname) + "(" + classname
|
||||||
puts( "// LOCAL STATE\n");
|
+ "& os) {\n");
|
||||||
|
puts("// LOCAL STATE\n");
|
||||||
// __Vm_namep presumably already correct
|
// __Vm_namep presumably already correct
|
||||||
if (v3Global.opt.trace()) {
|
if (v3Global.opt.trace()) { puts("os" + op + "__Vm_activity;\n"); }
|
||||||
puts( "os"+op+"__Vm_activity;\n");
|
puts("os" + op + "__Vm_didInit;\n");
|
||||||
}
|
puts("// SUBCELL STATE\n");
|
||||||
puts( "os"+op+"__Vm_didInit;\n");
|
for (std::vector<ScopeModPair>::iterator it = m_scopes.begin(); it != m_scopes.end();
|
||||||
puts( "// SUBCELL STATE\n");
|
++it) {
|
||||||
for (std::vector<ScopeModPair>::iterator it = m_scopes.begin();
|
AstScope* scopep = it->first;
|
||||||
it != m_scopes.end(); ++it) {
|
AstNodeModule* modp = it->second;
|
||||||
AstScope* scopep = it->first; AstNodeModule* modp = it->second;
|
|
||||||
if (!modp->isTop()) {
|
if (!modp->isTop()) {
|
||||||
puts(protectIf(scopep->nameDotless(), scopep->protect())
|
puts(protectIf(scopep->nameDotless(), scopep->protect()) + "."
|
||||||
+"."+protect(funcname)+"(os);\n");
|
+ protect(funcname) + "(os);\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
puts("}\n");
|
puts("}\n");
|
||||||
|
|
@ -594,7 +612,8 @@ void EmitCSyms::emitSymImp() {
|
||||||
puts("\n");
|
puts("\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(" // Setup locals\n");
|
puts(" // Setup locals\n");
|
||||||
puts(" : __Vm_namep(namep)\n"); // No leak, as gets destroyed when the top is destroyed
|
puts(" : __Vm_namep(namep)\n"); // No leak, as gets destroyed when the top is destroyed
|
||||||
if (v3Global.needTraceDumper()) {
|
if (v3Global.needTraceDumper()) {
|
||||||
|
|
@ -631,9 +650,7 @@ void EmitCSyms::emitSymImp() {
|
||||||
checkSplit(false);
|
checkSplit(false);
|
||||||
string arrow = scopep->name();
|
string arrow = scopep->name();
|
||||||
string::size_type pos;
|
string::size_type pos;
|
||||||
while ((pos = arrow.find('.')) != string::npos) {
|
while ((pos = arrow.find('.')) != string::npos) arrow.replace(pos, 1, "->");
|
||||||
arrow.replace(pos, 1, "->");
|
|
||||||
}
|
|
||||||
if (arrow.substr(0, 5) == "TOP->") arrow.replace(0, 5, "TOPp->");
|
if (arrow.substr(0, 5) == "TOP->") arrow.replace(0, 5, "TOPp->");
|
||||||
ofp()->puts(protectWordsIf(arrow, scopep->protect()));
|
ofp()->puts(protectWordsIf(arrow, scopep->protect()));
|
||||||
puts(" = &");
|
puts(" = &");
|
||||||
|
|
@ -643,7 +660,7 @@ void EmitCSyms::emitSymImp() {
|
||||||
}
|
}
|
||||||
|
|
||||||
puts("// Setup each module's pointer back to symbol table (for public functions)\n");
|
puts("// Setup each module's pointer back to symbol table (for public functions)\n");
|
||||||
puts("TOPp->"+protect("__Vconfigure")+"(this, true);\n");
|
puts("TOPp->" + protect("__Vconfigure") + "(this, true);\n");
|
||||||
for (std::vector<ScopeModPair>::iterator it = m_scopes.begin(); it != m_scopes.end(); ++it) {
|
for (std::vector<ScopeModPair>::iterator it = m_scopes.begin(); it != m_scopes.end(); ++it) {
|
||||||
AstScope* scopep = it->first;
|
AstScope* scopep = it->first;
|
||||||
AstNodeModule* modp = it->second;
|
AstNodeModule* modp = it->second;
|
||||||
|
|
@ -652,10 +669,8 @@ void EmitCSyms::emitSymImp() {
|
||||||
// first is used by AstCoverDecl's call to __vlCoverInsert
|
// first is used by AstCoverDecl's call to __vlCoverInsert
|
||||||
bool first = !modp->user1();
|
bool first = !modp->user1();
|
||||||
modp->user1(true);
|
modp->user1(true);
|
||||||
puts(protectIf(scopep->nameDotless(), scopep->protect())
|
puts(protectIf(scopep->nameDotless(), scopep->protect()) + "."
|
||||||
+"."+protect("__Vconfigure")+"(this, "
|
+ protect("__Vconfigure") + "(this, " + (first ? "true" : "false") + ");\n");
|
||||||
+(first?"true":"false")
|
|
||||||
+");\n");
|
|
||||||
++m_numStmts;
|
++m_numStmts;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -664,20 +679,19 @@ void EmitCSyms::emitSymImp() {
|
||||||
puts("// Setup scopes\n");
|
puts("// Setup scopes\n");
|
||||||
for (ScopeNames::iterator it = m_scopeNames.begin(); it != m_scopeNames.end(); ++it) {
|
for (ScopeNames::iterator it = m_scopeNames.begin(); it != m_scopeNames.end(); ++it) {
|
||||||
checkSplit(false);
|
checkSplit(false);
|
||||||
puts(protect("__Vscope_"+it->second.m_symName)
|
puts(protect("__Vscope_" + it->second.m_symName) + ".configure(this, name(), ");
|
||||||
+".configure(this, name(), ");
|
|
||||||
putsQuoted(protectWordsIf(it->second.m_prettyName, true));
|
putsQuoted(protectWordsIf(it->second.m_prettyName, true));
|
||||||
puts(", ");
|
puts(", ");
|
||||||
putsQuoted(protect(scopeDecodeIdentifier(it->second.m_prettyName)));
|
putsQuoted(protect(scopeDecodeIdentifier(it->second.m_prettyName)));
|
||||||
puts(", VerilatedScope::"+it->second.m_type+");\n");
|
puts(", VerilatedScope::" + it->second.m_type + ");\n");
|
||||||
++m_numStmts;
|
++m_numStmts;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (v3Global.opt.vpi()) {
|
if (v3Global.opt.vpi()) {
|
||||||
puts("\n// Setup scope hierarchy\n");
|
puts("\n// Setup scope hierarchy\n");
|
||||||
for (ScopeNames::const_iterator it = m_scopeNames.begin();
|
for (ScopeNames::const_iterator it = m_scopeNames.begin(); it != m_scopeNames.end();
|
||||||
it != m_scopeNames.end(); ++it) {
|
++it) {
|
||||||
string name = it->second.m_prettyName;
|
string name = it->second.m_prettyName;
|
||||||
if (it->first == "TOP") continue;
|
if (it->first == "TOP") continue;
|
||||||
name = name.replace(0, 4, ""); // Remove the "TOP."
|
name = name.replace(0, 4, ""); // Remove the "TOP."
|
||||||
|
|
@ -688,17 +702,17 @@ void EmitCSyms::emitSymImp() {
|
||||||
|
|
||||||
for (ScopeNameHierarchy::const_iterator it = m_vpiScopeHierarchy.begin();
|
for (ScopeNameHierarchy::const_iterator it = m_vpiScopeHierarchy.begin();
|
||||||
it != m_vpiScopeHierarchy.end(); ++it) {
|
it != m_vpiScopeHierarchy.end(); ++it) {
|
||||||
for (ScopeNameList::const_iterator lit = it->second.begin();
|
for (ScopeNameList::const_iterator lit = it->second.begin(); lit != it->second.end();
|
||||||
lit != it->second.end(); ++lit) {
|
++lit) {
|
||||||
string fromname = scopeSymString(it->first);
|
string fromname = scopeSymString(it->first);
|
||||||
string toname = scopeSymString(*lit);
|
string toname = scopeSymString(*lit);
|
||||||
ScopeNames::const_iterator from = m_scopeNames.find(fromname);
|
ScopeNames::const_iterator from = m_scopeNames.find(fromname);
|
||||||
ScopeNames::const_iterator to = m_scopeNames.find(toname);
|
ScopeNames::const_iterator to = m_scopeNames.find(toname);
|
||||||
UASSERT(from != m_scopeNames.end(), fromname+" not in m_scopeNames");
|
UASSERT(from != m_scopeNames.end(), fromname + " not in m_scopeNames");
|
||||||
UASSERT(to != m_scopeNames.end(), toname+" not in m_scopeNames");
|
UASSERT(to != m_scopeNames.end(), toname + " not in m_scopeNames");
|
||||||
puts("__Vhier.add(");
|
puts("__Vhier.add(");
|
||||||
puts("&"+protect("__Vscope_"+from->second.m_symName)+", ");
|
puts("&" + protect("__Vscope_" + from->second.m_symName) + ", ");
|
||||||
puts("&"+protect("__Vscope_"+to->second.m_symName)+");\n");
|
puts("&" + protect("__Vscope_" + to->second.m_symName) + ");\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
puts("\n");
|
puts("\n");
|
||||||
|
|
@ -716,7 +730,7 @@ void EmitCSyms::emitSymImp() {
|
||||||
AstNodeModule* modp = it->second.m_modp;
|
AstNodeModule* modp = it->second.m_modp;
|
||||||
if (funcp->dpiExport()) {
|
if (funcp->dpiExport()) {
|
||||||
checkSplit(true);
|
checkSplit(true);
|
||||||
puts(protect("__Vscope_"+scopep->scopeSymName())+".exportInsert(__Vfinal, ");
|
puts(protect("__Vscope_" + scopep->scopeSymName()) + ".exportInsert(__Vfinal, ");
|
||||||
putsQuoted(funcp->cname()); // Not protected - user asked for import/export
|
putsQuoted(funcp->cname()); // Not protected - user asked for import/export
|
||||||
puts(", (void*)(&");
|
puts(", (void*)(&");
|
||||||
puts(prefixNameProtect(modp));
|
puts(prefixNameProtect(modp));
|
||||||
|
|
@ -740,30 +754,40 @@ void EmitCSyms::emitSymImp() {
|
||||||
if (AstBasicDType* basicp = varp->basicp()) {
|
if (AstBasicDType* basicp = varp->basicp()) {
|
||||||
// Range is always first, it's not in "C" order
|
// Range is always first, it's not in "C" order
|
||||||
if (basicp->isRanged()) {
|
if (basicp->isRanged()) {
|
||||||
bounds += " ,"; bounds += cvtToStr(basicp->msb());
|
bounds += " ,";
|
||||||
bounds += ","; bounds += cvtToStr(basicp->lsb());
|
bounds += cvtToStr(basicp->msb());
|
||||||
|
bounds += ",";
|
||||||
|
bounds += cvtToStr(basicp->lsb());
|
||||||
pdim++;
|
pdim++;
|
||||||
}
|
}
|
||||||
for (AstNodeDType* dtypep = varp->dtypep(); dtypep; ) {
|
for (AstNodeDType* dtypep = varp->dtypep(); dtypep;) {
|
||||||
dtypep = dtypep->skipRefp(); // Skip AstRefDType/AstTypedef, or return same node
|
dtypep
|
||||||
|
= dtypep->skipRefp(); // Skip AstRefDType/AstTypedef, or return same node
|
||||||
if (const AstNodeArrayDType* adtypep = VN_CAST(dtypep, NodeArrayDType)) {
|
if (const AstNodeArrayDType* adtypep = VN_CAST(dtypep, NodeArrayDType)) {
|
||||||
bounds += " ,"; bounds += cvtToStr(adtypep->msb());
|
bounds += " ,";
|
||||||
bounds += ","; bounds += cvtToStr(adtypep->lsb());
|
bounds += cvtToStr(adtypep->msb());
|
||||||
if (VN_IS(dtypep, PackArrayDType)) pdim++; else udim++;
|
bounds += ",";
|
||||||
|
bounds += cvtToStr(adtypep->lsb());
|
||||||
|
if (VN_IS(dtypep, PackArrayDType)) {
|
||||||
|
pdim++;
|
||||||
|
} else {
|
||||||
|
udim++;
|
||||||
|
}
|
||||||
dtypep = adtypep->subDTypep();
|
dtypep = adtypep->subDTypep();
|
||||||
|
} else {
|
||||||
|
break; // AstBasicDType - nothing below, 1
|
||||||
}
|
}
|
||||||
else break; // AstBasicDType - nothing below, 1
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//
|
//
|
||||||
if (pdim>1 || udim>1) {
|
if (pdim > 1 || udim > 1) {
|
||||||
puts("//UNSUP "); // VerilatedImp can't deal with >2d or packed arrays
|
puts("//UNSUP "); // VerilatedImp can't deal with >2d or packed arrays
|
||||||
}
|
}
|
||||||
puts(protect("__Vscope_"+it->second.m_scopeName)+".varInsert(__Vfinal,");
|
puts(protect("__Vscope_" + it->second.m_scopeName) + ".varInsert(__Vfinal,");
|
||||||
putsQuoted(protect(it->second.m_varBasePretty));
|
putsQuoted(protect(it->second.m_varBasePretty));
|
||||||
puts(", &(");
|
puts(", &(");
|
||||||
if (modp->isTop()) {
|
if (modp->isTop()) {
|
||||||
puts(protectIf(scopep->nameDotless()+"p", scopep->protect()));
|
puts(protectIf(scopep->nameDotless() + "p", scopep->protect()));
|
||||||
puts("->");
|
puts("->");
|
||||||
} else {
|
} else {
|
||||||
puts(protectIf(scopep->nameDotless(), scopep->protect()));
|
puts(protectIf(scopep->nameDotless(), scopep->protect()));
|
||||||
|
|
@ -775,7 +799,7 @@ void EmitCSyms::emitSymImp() {
|
||||||
puts(",");
|
puts(",");
|
||||||
puts(varp->vlEnumDir()); // VLVD_IN etc
|
puts(varp->vlEnumDir()); // VLVD_IN etc
|
||||||
puts(",");
|
puts(",");
|
||||||
puts(cvtToStr(pdim+udim));
|
puts(cvtToStr(pdim + udim));
|
||||||
puts(bounds);
|
puts(bounds);
|
||||||
puts(");\n");
|
puts(");\n");
|
||||||
++m_numStmts;
|
++m_numStmts;
|
||||||
|
|
@ -791,15 +815,16 @@ void EmitCSyms::emitSymImp() {
|
||||||
//######################################################################
|
//######################################################################
|
||||||
|
|
||||||
void EmitCSyms::emitDpiHdr() {
|
void EmitCSyms::emitDpiHdr() {
|
||||||
UINFO(6,__FUNCTION__<<": "<<endl);
|
UINFO(6, __FUNCTION__ << ": " << endl);
|
||||||
string filename = v3Global.opt.makeDir()+"/"+topClassName()+"__Dpi.h";
|
string filename = v3Global.opt.makeDir() + "/" + topClassName() + "__Dpi.h";
|
||||||
AstCFile* cfilep = newCFile(filename, false/*slow*/, false/*source*/);
|
AstCFile* cfilep = newCFile(filename, false /*slow*/, false /*source*/);
|
||||||
cfilep->support(true);
|
cfilep->support(true);
|
||||||
V3OutCFile hf (filename);
|
V3OutCFile hf(filename);
|
||||||
m_ofp = &hf;
|
m_ofp = &hf;
|
||||||
|
|
||||||
m_ofp->putsHeader();
|
m_ofp->putsHeader();
|
||||||
puts("// DESCR" "IPTION: Verilator output: Prototypes for DPI import and export functions.\n");
|
puts("// DESCR"
|
||||||
|
"IPTION: Verilator output: Prototypes for DPI import and export functions.\n");
|
||||||
puts("//\n");
|
puts("//\n");
|
||||||
puts("// Verilator includes this file in all generated .cpp files that use DPI functions.\n");
|
puts("// Verilator includes this file in all generated .cpp files that use DPI functions.\n");
|
||||||
puts("// Manually include this file where DPI .c import functions are declared to ensure\n");
|
puts("// Manually include this file where DPI .c import functions are declared to ensure\n");
|
||||||
|
|
@ -818,15 +843,14 @@ void EmitCSyms::emitDpiHdr() {
|
||||||
AstCFunc* nodep = *it;
|
AstCFunc* nodep = *it;
|
||||||
if (nodep->dpiExportWrapper()) {
|
if (nodep->dpiExportWrapper()) {
|
||||||
if (!firstExp++) puts("\n// DPI EXPORTS\n");
|
if (!firstExp++) puts("\n// DPI EXPORTS\n");
|
||||||
puts("// DPI export"+ifNoProtect(" at "+nodep->fileline()->ascii())+"\n");
|
puts("// DPI export" + ifNoProtect(" at " + nodep->fileline()->ascii()) + "\n");
|
||||||
puts("extern "+nodep->rtnTypeVoid()+" "+nodep->nameProtect()
|
puts("extern " + nodep->rtnTypeVoid() + " " + nodep->nameProtect() + "("
|
||||||
+"("+cFuncArgs(nodep)+");\n");
|
+ cFuncArgs(nodep) + ");\n");
|
||||||
}
|
} else if (nodep->dpiImport()) {
|
||||||
else if (nodep->dpiImport()) {
|
|
||||||
if (!firstImp++) puts("\n// DPI IMPORTS\n");
|
if (!firstImp++) puts("\n// DPI IMPORTS\n");
|
||||||
puts("// DPI import"+ifNoProtect(" at "+nodep->fileline()->ascii())+"\n");
|
puts("// DPI import" + ifNoProtect(" at " + nodep->fileline()->ascii()) + "\n");
|
||||||
puts("extern "+nodep->rtnTypeVoid()+" "+nodep->nameProtect()
|
puts("extern " + nodep->rtnTypeVoid() + " " + nodep->nameProtect() + "("
|
||||||
+"("+cFuncArgs(nodep)+");\n");
|
+ cFuncArgs(nodep) + ");\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -839,49 +863,50 @@ void EmitCSyms::emitDpiHdr() {
|
||||||
//######################################################################
|
//######################################################################
|
||||||
|
|
||||||
void EmitCSyms::emitDpiImp() {
|
void EmitCSyms::emitDpiImp() {
|
||||||
UINFO(6,__FUNCTION__<<": "<<endl);
|
UINFO(6, __FUNCTION__ << ": " << endl);
|
||||||
string filename = v3Global.opt.makeDir()+"/"+topClassName()+"__Dpi.cpp";
|
string filename = v3Global.opt.makeDir() + "/" + topClassName() + "__Dpi.cpp";
|
||||||
AstCFile* cfilep = newCFile(filename, false/*slow*/, true/*source*/);
|
AstCFile* cfilep = newCFile(filename, false /*slow*/, true /*source*/);
|
||||||
cfilep->support(true);
|
cfilep->support(true);
|
||||||
V3OutCFile hf (filename);
|
V3OutCFile hf(filename);
|
||||||
m_ofp = &hf;
|
m_ofp = &hf;
|
||||||
|
|
||||||
m_ofp->putsHeader();
|
m_ofp->putsHeader();
|
||||||
puts("// DESCR" "IPTION: Verilator output: Implementation of DPI export functions.\n");
|
puts("// DESCR"
|
||||||
|
"IPTION: Verilator output: Implementation of DPI export functions.\n");
|
||||||
puts("//\n");
|
puts("//\n");
|
||||||
puts("// Verilator compiles this file in when DPI functions are used.\n");
|
puts("// Verilator compiles this file in when DPI functions are used.\n");
|
||||||
puts("// If you have multiple Verilated designs with the same DPI exported\n");
|
puts("// If you have multiple Verilated designs with the same DPI exported\n");
|
||||||
puts("// function names, you will get multiple definition link errors from here.\n");
|
puts("// function names, you will get multiple definition link errors from here.\n");
|
||||||
puts("// This is an unfortunate result of the DPI specification.\n");
|
puts("// This is an unfortunate result of the DPI specification.\n");
|
||||||
puts("// To solve this, either\n");
|
puts("// To solve this, either\n");
|
||||||
puts("// 1. Call "+topClassName()+"::{export_function} instead,\n");
|
puts("// 1. Call " + topClassName() + "::{export_function} instead,\n");
|
||||||
puts("// and do not even bother to compile this file\n");
|
puts("// and do not even bother to compile this file\n");
|
||||||
puts("// or 2. Compile all __Dpi.cpp files in the same compiler run,\n");
|
puts("// or 2. Compile all __Dpi.cpp files in the same compiler run,\n");
|
||||||
puts("// and #ifdefs already inserted here will sort everything out.\n");
|
puts("// and #ifdefs already inserted here will sort everything out.\n");
|
||||||
puts("\n");
|
puts("\n");
|
||||||
|
|
||||||
puts("#include \""+topClassName()+"__Dpi.h\"\n");
|
puts("#include \"" + topClassName() + "__Dpi.h\"\n");
|
||||||
puts("#include \""+topClassName()+".h\"\n");
|
puts("#include \"" + topClassName() + ".h\"\n");
|
||||||
puts("\n");
|
puts("\n");
|
||||||
|
|
||||||
for (std::vector<AstCFunc*>::iterator it = m_dpis.begin(); it != m_dpis.end(); ++it) {
|
for (std::vector<AstCFunc*>::iterator it = m_dpis.begin(); it != m_dpis.end(); ++it) {
|
||||||
AstCFunc* nodep = *it;
|
AstCFunc* nodep = *it;
|
||||||
if (nodep->dpiExportWrapper()) {
|
if (nodep->dpiExportWrapper()) {
|
||||||
puts("#ifndef _VL_DPIDECL_"+nodep->name()+"\n");
|
puts("#ifndef _VL_DPIDECL_" + nodep->name() + "\n");
|
||||||
puts("#define _VL_DPIDECL_"+nodep->name()+"\n");
|
puts("#define _VL_DPIDECL_" + nodep->name() + "\n");
|
||||||
puts(nodep->rtnTypeVoid()+" "+nodep->name()+"("+cFuncArgs(nodep)+") {\n");
|
puts(nodep->rtnTypeVoid() + " " + nodep->name() + "(" + cFuncArgs(nodep) + ") {\n");
|
||||||
puts("// DPI export"+ifNoProtect(" at "+nodep->fileline()->ascii())+"\n");
|
puts("// DPI export" + ifNoProtect(" at " + nodep->fileline()->ascii()) + "\n");
|
||||||
puts("return "+topClassName()+"::"+nodep->name()+"(");
|
puts("return " + topClassName() + "::" + nodep->name() + "(");
|
||||||
string args;
|
string args;
|
||||||
for (AstNode* stmtp = nodep->argsp(); stmtp; stmtp=stmtp->nextp()) {
|
for (AstNode* stmtp = nodep->argsp(); stmtp; stmtp = stmtp->nextp()) {
|
||||||
if (const AstVar* portp = VN_CAST(stmtp, Var)) {
|
if (const AstVar* portp = VN_CAST(stmtp, Var)) {
|
||||||
if (portp->isIO() && !portp->isFuncReturn()) {
|
if (portp->isIO() && !portp->isFuncReturn()) {
|
||||||
if (args != "") args+= ", ";
|
if (args != "") args += ", ";
|
||||||
args += portp->name();
|
args += portp->name();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
puts(args+");\n");
|
puts(args + ");\n");
|
||||||
puts("}\n");
|
puts("}\n");
|
||||||
puts("#endif\n");
|
puts("#endif\n");
|
||||||
puts("\n");
|
puts("\n");
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -37,18 +37,15 @@ class VOptionBool {
|
||||||
// Class to track options that are either not specified (and default
|
// Class to track options that are either not specified (and default
|
||||||
// true/false), versus user setting the option to true or false
|
// true/false), versus user setting the option to true or false
|
||||||
public:
|
public:
|
||||||
enum en {
|
enum en { OPT_DEFAULT_FALSE = 0, OPT_DEFAULT_TRUE, OPT_TRUE, OPT_FALSE, _ENUM_END };
|
||||||
OPT_DEFAULT_FALSE = 0,
|
|
||||||
OPT_DEFAULT_TRUE,
|
|
||||||
OPT_TRUE,
|
|
||||||
OPT_FALSE,
|
|
||||||
_ENUM_END
|
|
||||||
};
|
|
||||||
enum en m_e;
|
enum en m_e;
|
||||||
inline VOptionBool() : m_e(OPT_DEFAULT_FALSE) {}
|
inline VOptionBool()
|
||||||
|
: m_e(OPT_DEFAULT_FALSE) {}
|
||||||
// cppcheck-suppress noExplicitConstructor
|
// cppcheck-suppress noExplicitConstructor
|
||||||
inline VOptionBool(en _e) : m_e(_e) {}
|
inline VOptionBool(en _e)
|
||||||
explicit inline VOptionBool(int _e) : m_e(static_cast<en>(_e)) {}
|
: m_e(_e) {}
|
||||||
|
explicit inline VOptionBool(int _e)
|
||||||
|
: m_e(static_cast<en>(_e)) {}
|
||||||
operator en() const { return m_e; }
|
operator en() const { return m_e; }
|
||||||
bool isDefault() const { return m_e == OPT_DEFAULT_FALSE || m_e == OPT_DEFAULT_TRUE; }
|
bool isDefault() const { return m_e == OPT_DEFAULT_FALSE || m_e == OPT_DEFAULT_TRUE; }
|
||||||
bool isTrue() const { return m_e == OPT_TRUE || m_e == OPT_DEFAULT_TRUE; }
|
bool isTrue() const { return m_e == OPT_TRUE || m_e == OPT_DEFAULT_TRUE; }
|
||||||
|
|
@ -57,9 +54,9 @@ public:
|
||||||
bool isSetFalse() const { return m_e == OPT_FALSE; }
|
bool isSetFalse() const { return m_e == OPT_FALSE; }
|
||||||
void setTrueOrFalse(bool flag) { m_e = flag ? OPT_TRUE : OPT_FALSE; }
|
void setTrueOrFalse(bool flag) { m_e = flag ? OPT_TRUE : OPT_FALSE; }
|
||||||
const char* ascii() const {
|
const char* ascii() const {
|
||||||
static const char* const names[] = {
|
static const char* const names[] = {"DEFAULT_FALSE", "DEFAULT_TRUE", "TRUE", "FALSE"};
|
||||||
"DEFAULT_FALSE", "DEFAULT_TRUE", "TRUE", "FALSE"};
|
return names[m_e];
|
||||||
return names[m_e]; }
|
}
|
||||||
};
|
};
|
||||||
inline bool operator==(const VOptionBool& lhs, const VOptionBool& rhs) {
|
inline bool operator==(const VOptionBool& lhs, const VOptionBool& rhs) {
|
||||||
return lhs.m_e == rhs.m_e;
|
return lhs.m_e == rhs.m_e;
|
||||||
|
|
@ -74,31 +71,21 @@ inline std::ostream& operator<<(std::ostream& os, const VOptionBool& rhs) {
|
||||||
|
|
||||||
class TraceFormat {
|
class TraceFormat {
|
||||||
public:
|
public:
|
||||||
enum en {
|
enum en { VCD = 0, FST, FST_THREAD } m_e;
|
||||||
VCD = 0,
|
|
||||||
FST,
|
|
||||||
FST_THREAD
|
|
||||||
} m_e;
|
|
||||||
// cppcheck-suppress noExplicitConstructor
|
// cppcheck-suppress noExplicitConstructor
|
||||||
inline TraceFormat(en _e = VCD) : m_e(_e) {}
|
inline TraceFormat(en _e = VCD)
|
||||||
explicit inline TraceFormat(int _e) : m_e(static_cast<en>(_e)) {}
|
: m_e(_e) {}
|
||||||
|
explicit inline TraceFormat(int _e)
|
||||||
|
: m_e(static_cast<en>(_e)) {}
|
||||||
operator en() const { return m_e; }
|
operator en() const { return m_e; }
|
||||||
bool fstFlavor() const { return m_e == FST || m_e == FST_THREAD; }
|
bool fstFlavor() const { return m_e == FST || m_e == FST_THREAD; }
|
||||||
bool threaded() const { return m_e == FST_THREAD; }
|
bool threaded() const { return m_e == FST_THREAD; }
|
||||||
string classBase() const {
|
string classBase() const {
|
||||||
static const char* const names[] = {
|
static const char* const names[] = {"VerilatedVcd", "VerilatedFst", "VerilatedFst"};
|
||||||
"VerilatedVcd",
|
|
||||||
"VerilatedFst",
|
|
||||||
"VerilatedFst"
|
|
||||||
};
|
|
||||||
return names[m_e];
|
return names[m_e];
|
||||||
}
|
}
|
||||||
string sourceName() const {
|
string sourceName() const {
|
||||||
static const char* const names[] = {
|
static const char* const names[] = {"verilated_vcd", "verilated_fst", "verilated_fst"};
|
||||||
"verilated_vcd",
|
|
||||||
"verilated_fst",
|
|
||||||
"verilated_fst"
|
|
||||||
};
|
|
||||||
return names[m_e];
|
return names[m_e];
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
@ -115,15 +102,15 @@ typedef std::set<string> V3StringSet;
|
||||||
// V3Options - Command line options
|
// V3Options - Command line options
|
||||||
|
|
||||||
class V3Options {
|
class V3Options {
|
||||||
public:
|
public:
|
||||||
|
private:
|
||||||
private:
|
|
||||||
// TYPES
|
// TYPES
|
||||||
typedef std::map<string,int> DebugSrcMap;
|
typedef std::map<string, int> DebugSrcMap;
|
||||||
|
|
||||||
// MEMBERS (general options)
|
// MEMBERS (general options)
|
||||||
V3OptionsImp* m_impp; // Slow hidden options
|
V3OptionsImp* m_impp; // Slow hidden options
|
||||||
|
|
||||||
|
// clang-format off
|
||||||
V3StringSet m_cppFiles; // argument: C++ files to link against
|
V3StringSet m_cppFiles; // argument: C++ files to link against
|
||||||
V3StringList m_cFlags; // argument: user CFLAGS
|
V3StringList m_cFlags; // argument: user CFLAGS
|
||||||
V3StringList m_ldLibs; // argument: user LDFLAGS
|
V3StringList m_ldLibs; // argument: user LDFLAGS
|
||||||
|
|
@ -137,7 +124,6 @@ class V3Options {
|
||||||
DebugSrcMap m_dumpTrees; // argument: --dump-treei-<srcfile>=<level>
|
DebugSrcMap m_dumpTrees; // argument: --dump-treei-<srcfile>=<level>
|
||||||
std::map<string,string> m_parameters; // Parameters
|
std::map<string,string> m_parameters; // Parameters
|
||||||
|
|
||||||
|
|
||||||
bool m_preprocOnly; // main switch: -E
|
bool m_preprocOnly; // main switch: -E
|
||||||
bool m_makePhony; // main switch: -MP
|
bool m_makePhony; // main switch: -MP
|
||||||
bool m_preprocNoLine;// main switch: -P
|
bool m_preprocNoLine;// main switch: -P
|
||||||
|
|
@ -268,8 +254,9 @@ class V3Options {
|
||||||
bool m_oSubst; // main switch: -Ou: substitute expression temp values
|
bool m_oSubst; // main switch: -Ou: substitute expression temp values
|
||||||
bool m_oSubstConst; // main switch: -Ok: final constant substitution
|
bool m_oSubstConst; // main switch: -Ok: final constant substitution
|
||||||
bool m_oTable; // main switch: -Oa: lookup table creation
|
bool m_oTable; // main switch: -Oa: lookup table creation
|
||||||
|
// clang-format on
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// METHODS
|
// METHODS
|
||||||
void addArg(const string& arg);
|
void addArg(const string& arg);
|
||||||
void addDefine(const string& defline, bool allowPlus);
|
void addDefine(const string& defline, bool allowPlus);
|
||||||
|
|
@ -291,12 +278,13 @@ class V3Options {
|
||||||
|
|
||||||
// CONSTRUCTORS
|
// CONSTRUCTORS
|
||||||
VL_UNCOPYABLE(V3Options);
|
VL_UNCOPYABLE(V3Options);
|
||||||
public:
|
|
||||||
|
public:
|
||||||
V3Options();
|
V3Options();
|
||||||
~V3Options();
|
~V3Options();
|
||||||
void setDebugMode(int level);
|
void setDebugMode(int level);
|
||||||
void setDebugSrcLevel(const string& srcfile, int level);
|
void setDebugSrcLevel(const string& srcfile, int level);
|
||||||
int debugSrcLevel(const string& srcfile_path, int default_level=V3Error::debugDefault());
|
int debugSrcLevel(const string& srcfile_path, int default_level = V3Error::debugDefault());
|
||||||
void setDumpTreeLevel(const string& srcfile, int level);
|
void setDumpTreeLevel(const string& srcfile, int level);
|
||||||
int dumpTreeLevel(const string& srcfile_path);
|
int dumpTreeLevel(const string& srcfile_path);
|
||||||
|
|
||||||
|
|
@ -359,7 +347,7 @@ class V3Options {
|
||||||
bool traceUnderscore() const { return m_traceUnderscore; }
|
bool traceUnderscore() const { return m_traceUnderscore; }
|
||||||
bool orderClockDly() const { return m_orderClockDly; }
|
bool orderClockDly() const { return m_orderClockDly; }
|
||||||
bool outFormatOk() const { return m_outFormatOk; }
|
bool outFormatOk() const { return m_outFormatOk; }
|
||||||
bool keepTempFiles() const { return (V3Error::debugDefault()!=0); }
|
bool keepTempFiles() const { return (V3Error::debugDefault() != 0); }
|
||||||
bool pedantic() const { return m_pedantic; }
|
bool pedantic() const { return m_pedantic; }
|
||||||
bool pinsScUint() const { return m_pinsScUint; }
|
bool pinsScUint() const { return m_pinsScUint; }
|
||||||
bool pinsScBigUint() const { return m_pinsScBigUint; }
|
bool pinsScBigUint() const { return m_pinsScBigUint; }
|
||||||
|
|
@ -407,7 +395,7 @@ class V3Options {
|
||||||
int compLimitMembers() const { return m_compLimitMembers; }
|
int compLimitMembers() const { return m_compLimitMembers; }
|
||||||
int compLimitParens() const { return m_compLimitParens; }
|
int compLimitParens() const { return m_compLimitParens; }
|
||||||
|
|
||||||
string exeName() const { return m_exeName!="" ? m_exeName : prefix(); }
|
string exeName() const { return m_exeName != "" ? m_exeName : prefix(); }
|
||||||
string l2Name() const { return m_l2Name; }
|
string l2Name() const { return m_l2Name; }
|
||||||
string makeDir() const { return m_makeDir; }
|
string makeDir() const { return m_makeDir; }
|
||||||
string modPrefix() const { return m_modPrefix; }
|
string modPrefix() const { return m_modPrefix; }
|
||||||
|
|
@ -417,7 +405,7 @@ class V3Options {
|
||||||
string protectKeyDefaulted(); // Set default key if not set by user
|
string protectKeyDefaulted(); // Set default key if not set by user
|
||||||
string protectLib() const { return m_protectLib; }
|
string protectLib() const { return m_protectLib; }
|
||||||
string protectLibName(bool shared) {
|
string protectLibName(bool shared) {
|
||||||
string libName = "lib"+protectLib();
|
string libName = "lib" + protectLib();
|
||||||
if (shared) {
|
if (shared) {
|
||||||
libName += ".so";
|
libName += ".so";
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -499,10 +487,10 @@ class V3Options {
|
||||||
|
|
||||||
// METHODS (file utilities using these options)
|
// METHODS (file utilities using these options)
|
||||||
string fileExists(const string& filename);
|
string fileExists(const string& filename);
|
||||||
string filePath(FileLine* fl, const string& modname,
|
string filePath(FileLine* fl, const string& modname, const string& lastpath,
|
||||||
const string& lastpath, const string& errmsg);
|
const string& errmsg);
|
||||||
void filePathLookedMsg(FileLine* fl, const string& modname);
|
void filePathLookedMsg(FileLine* fl, const string& modname);
|
||||||
V3LangCode fileLanguage(const string &filename);
|
V3LangCode fileLanguage(const string& filename);
|
||||||
static bool fileStatDir(const string& filename);
|
static bool fileStatDir(const string& filename);
|
||||||
static bool fileStatNormal(const string& filename);
|
static bool fileStatNormal(const string& filename);
|
||||||
static void fileNfsFlush(const string& filename);
|
static void fileNfsFlush(const string& filename);
|
||||||
|
|
|
||||||
106
src/V3Os.cpp
106
src/V3Os.cpp
|
|
@ -14,6 +14,7 @@
|
||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
|
|
||||||
|
// clang-format off
|
||||||
#if defined(_WIN32) || defined(__MINGW32__)
|
#if defined(_WIN32) || defined(__MINGW32__)
|
||||||
# ifndef PSAPI_VERSION
|
# ifndef PSAPI_VERSION
|
||||||
# define PSAPI_VERSION 1 // Needed for compatibility with Windows 7
|
# define PSAPI_VERSION 1 // Needed for compatibility with Windows 7
|
||||||
|
|
@ -22,6 +23,7 @@
|
||||||
#if defined(__MINGW32__)
|
#if defined(__MINGW32__)
|
||||||
# define MINGW_HAS_SECURE_API 1 // Needed to expose a "secure" POSIX-like API
|
# define MINGW_HAS_SECURE_API 1 // Needed to expose a "secure" POSIX-like API
|
||||||
#endif
|
#endif
|
||||||
|
// clang-format on
|
||||||
|
|
||||||
#include "config_build.h"
|
#include "config_build.h"
|
||||||
#include "verilatedos.h"
|
#include "verilatedos.h"
|
||||||
|
|
@ -42,6 +44,7 @@
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
// clang-format off
|
||||||
#if defined(_WIN32) || defined(__MINGW32__)
|
#if defined(_WIN32) || defined(__MINGW32__)
|
||||||
# include <windows.h> // LONG for bcrypt.h on MINGW
|
# include <windows.h> // LONG for bcrypt.h on MINGW
|
||||||
# include <bcrypt.h> // BCryptGenRandom
|
# include <bcrypt.h> // BCryptGenRandom
|
||||||
|
|
@ -53,7 +56,7 @@
|
||||||
# include <sys/time.h>
|
# include <sys/time.h>
|
||||||
# include <unistd.h> // usleep
|
# include <unistd.h> // usleep
|
||||||
#endif
|
#endif
|
||||||
|
// clang-format on
|
||||||
|
|
||||||
//######################################################################
|
//######################################################################
|
||||||
// Environment
|
// Environment
|
||||||
|
|
@ -80,17 +83,17 @@ string V3Os::getenvStr(const string& envvar, const string& defaultValue) {
|
||||||
|
|
||||||
void V3Os::setenvStr(const string& envvar, const string& value, const string& why) {
|
void V3Os::setenvStr(const string& envvar, const string& value, const string& why) {
|
||||||
if (why != "") {
|
if (why != "") {
|
||||||
UINFO(1,"export "<<envvar<<"="<<value<<" # "<<why<<endl);
|
UINFO(1, "export " << envvar << "=" << value << " # " << why << endl);
|
||||||
} else {
|
} else {
|
||||||
UINFO(1,"export "<<envvar<<"="<<value<<endl);
|
UINFO(1, "export " << envvar << "=" << value << endl);
|
||||||
}
|
}
|
||||||
#if defined(_WIN32) || defined(__MINGW32__)
|
#if defined(_WIN32) || defined(__MINGW32__)
|
||||||
_putenv_s(envvar.c_str(), value.c_str());
|
_putenv_s(envvar.c_str(), value.c_str());
|
||||||
#elif defined(_BSD_SOURCE) || (defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 200112L)
|
#elif defined(_BSD_SOURCE) || (defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 200112L)
|
||||||
setenv(envvar.c_str(), value.c_str(), true);
|
setenv(envvar.c_str(), value.c_str(), true);
|
||||||
#else
|
#else
|
||||||
//setenv() replaced by putenv() in Solaris environment. Prototype is different
|
// setenv() replaced by putenv() in Solaris environment. Prototype is different
|
||||||
//putenv() requires NAME=VALUE format
|
// putenv() requires NAME=VALUE format
|
||||||
string vareq = envvar + "=" + value;
|
string vareq = envvar + "=" + value;
|
||||||
putenv(const_cast<char*>(vareq.c_str()));
|
putenv(const_cast<char*>(vareq.c_str()));
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -101,8 +104,11 @@ void V3Os::setenvStr(const string& envvar, const string& value, const string& wh
|
||||||
|
|
||||||
string V3Os::filenameFromDirBase(const string& dir, const string& basename) {
|
string V3Os::filenameFromDirBase(const string& dir, const string& basename) {
|
||||||
// Don't return ./{filename} because if filename was absolute, that makes it relative
|
// Don't return ./{filename} because if filename was absolute, that makes it relative
|
||||||
if (dir == ".") return basename;
|
if (dir == ".") {
|
||||||
else return dir+"/"+basename;
|
return basename;
|
||||||
|
} else {
|
||||||
|
return dir + "/" + basename;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
string V3Os::filenameDir(const string& filename) {
|
string V3Os::filenameDir(const string& filename) {
|
||||||
|
|
@ -117,7 +123,7 @@ string V3Os::filenameDir(const string& filename) {
|
||||||
string V3Os::filenameNonDir(const string& filename) {
|
string V3Os::filenameNonDir(const string& filename) {
|
||||||
string::size_type pos;
|
string::size_type pos;
|
||||||
if ((pos = filename.rfind('/')) != string::npos) {
|
if ((pos = filename.rfind('/')) != string::npos) {
|
||||||
return filename.substr(pos+1);
|
return filename.substr(pos + 1);
|
||||||
} else {
|
} else {
|
||||||
return filename;
|
return filename;
|
||||||
}
|
}
|
||||||
|
|
@ -126,9 +132,7 @@ string V3Os::filenameNonDir(const string& filename) {
|
||||||
string V3Os::filenameNonExt(const string& filename) {
|
string V3Os::filenameNonExt(const string& filename) {
|
||||||
string base = filenameNonDir(filename);
|
string base = filenameNonDir(filename);
|
||||||
string::size_type pos;
|
string::size_type pos;
|
||||||
if ((pos = base.find('.')) != string::npos) {
|
if ((pos = base.find('.')) != string::npos) base.erase(pos);
|
||||||
base.erase(pos);
|
|
||||||
}
|
|
||||||
return base;
|
return base;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -136,32 +140,35 @@ string V3Os::filenameSubstitute(const string& filename) {
|
||||||
string out;
|
string out;
|
||||||
enum { NONE, PAREN, CURLY } brackets = NONE;
|
enum { NONE, PAREN, CURLY } brackets = NONE;
|
||||||
for (string::size_type pos = 0; pos < filename.length(); ++pos) {
|
for (string::size_type pos = 0; pos < filename.length(); ++pos) {
|
||||||
if ((filename[pos] == '$') && (pos+1 < filename.length())) {
|
if ((filename[pos] == '$') && (pos + 1 < filename.length())) {
|
||||||
switch (filename[pos+1]) {
|
switch (filename[pos + 1]) {
|
||||||
case '{': brackets = CURLY; break;
|
case '{': brackets = CURLY; break;
|
||||||
case '(': brackets = PAREN; break;
|
case '(': brackets = PAREN; break;
|
||||||
default: brackets = NONE; break;
|
default: brackets = NONE; break;
|
||||||
}
|
}
|
||||||
if (brackets != NONE) pos = pos+1;
|
if (brackets != NONE) pos = pos + 1;
|
||||||
string::size_type endpos = pos+1;
|
string::size_type endpos = pos + 1;
|
||||||
while (((endpos+1) < filename.length()) &&
|
while (((endpos + 1) < filename.length())
|
||||||
(((brackets==NONE) && (isalnum(filename[endpos+1])
|
&& (((brackets == NONE)
|
||||||
|| filename[endpos+1]=='_'))
|
&& (isalnum(filename[endpos + 1]) || filename[endpos + 1] == '_'))
|
||||||
|| ((brackets==CURLY) && (filename[endpos+1]!='}'))
|
|| ((brackets == CURLY) && (filename[endpos + 1] != '}'))
|
||||||
|| ((brackets==PAREN) && (filename[endpos+1]!=')'))))
|
|| ((brackets == PAREN) && (filename[endpos + 1] != ')'))))
|
||||||
++endpos;
|
++endpos;
|
||||||
// Catch bracket errors
|
// Catch bracket errors
|
||||||
if (((brackets==CURLY) && (filename[endpos+1]!='}')) ||
|
if (((brackets == CURLY) && (filename[endpos + 1] != '}'))
|
||||||
((brackets==PAREN) && (filename[endpos+1]!=')'))) {
|
|| ((brackets == PAREN) && (filename[endpos + 1] != ')'))) {
|
||||||
v3fatal("Unmatched brackets in variable substitution in file: "+filename);
|
v3fatal("Unmatched brackets in variable substitution in file: " + filename);
|
||||||
}
|
}
|
||||||
string envvar = filename.substr(pos+1, endpos-pos);
|
string envvar = filename.substr(pos + 1, endpos - pos);
|
||||||
string envvalue;
|
string envvalue;
|
||||||
if (!envvar.empty()) envvalue = getenvStr(envvar, "");
|
if (!envvar.empty()) envvalue = getenvStr(envvar, "");
|
||||||
if (!envvalue.empty()) {
|
if (!envvalue.empty()) {
|
||||||
out += envvalue;
|
out += envvalue;
|
||||||
if (brackets==NONE) pos = endpos;
|
if (brackets == NONE) {
|
||||||
else pos = endpos+1;
|
pos = endpos;
|
||||||
|
} else {
|
||||||
|
pos = endpos + 1;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
out += filename[pos]; // *pos == '$'
|
out += filename[pos]; // *pos == '$'
|
||||||
}
|
}
|
||||||
|
|
@ -170,7 +177,6 @@ string V3Os::filenameSubstitute(const string& filename) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return out;
|
return out;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
string V3Os::filenameRealPath(const string& filename) {
|
string V3Os::filenameRealPath(const string& filename) {
|
||||||
|
|
@ -183,7 +189,7 @@ string V3Os::filenameRealPath(const string& filename) {
|
||||||
#else
|
#else
|
||||||
realpath(filename.c_str(), retpath)
|
realpath(filename.c_str(), retpath)
|
||||||
#endif
|
#endif
|
||||||
) {
|
) {
|
||||||
return string(retpath);
|
return string(retpath);
|
||||||
} else {
|
} else {
|
||||||
return filename;
|
return filename;
|
||||||
|
|
@ -191,7 +197,7 @@ string V3Os::filenameRealPath(const string& filename) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool V3Os::filenameIsRel(const string& filename) {
|
bool V3Os::filenameIsRel(const string& filename) {
|
||||||
return (filename.length()>0 && filename[0] != '/');
|
return (filename.length() > 0 && filename[0] != '/');
|
||||||
}
|
}
|
||||||
|
|
||||||
//######################################################################
|
//######################################################################
|
||||||
|
|
@ -243,28 +249,27 @@ vluint64_t V3Os::rand64(vluint64_t* statep) {
|
||||||
// Xoroshiro128+ algorithm
|
// Xoroshiro128+ algorithm
|
||||||
vluint64_t result = statep[0] + statep[1];
|
vluint64_t result = statep[0] + statep[1];
|
||||||
statep[1] ^= statep[0];
|
statep[1] ^= statep[0];
|
||||||
statep[0] = (((statep[0] << 55) | (statep[0] >> 9))
|
statep[0] = (((statep[0] << 55) | (statep[0] >> 9)) ^ statep[1] ^ (statep[1] << 14));
|
||||||
^ statep[1] ^ (statep[1] << 14));
|
|
||||||
statep[1] = (statep[1] << 36) | (statep[1] >> 28);
|
statep[1] = (statep[1] << 36) | (statep[1] >> 28);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
string V3Os::trueRandom(size_t size) {
|
string V3Os::trueRandom(size_t size) {
|
||||||
string result(size, '\xFF');
|
string result(size, '\xFF');
|
||||||
char *const data = const_cast<char*>(result.data());
|
char* const data = const_cast<char*>(result.data());
|
||||||
// Note: std::string.data() returns a non-const Char* from C++17 onwards.
|
// Note: std::string.data() returns a non-const Char* from C++17 onwards.
|
||||||
// For pre-C++17, this cast is OK in practice, even though it's UB.
|
// For pre-C++17, this cast is OK in practice, even though it's UB.
|
||||||
#if defined(_WIN32) || defined(__MINGW32__)
|
#if defined(_WIN32) || defined(__MINGW32__)
|
||||||
NTSTATUS hr = BCryptGenRandom(NULL, reinterpret_cast<BYTE*>(data), size, BCRYPT_USE_SYSTEM_PREFERRED_RNG);
|
NTSTATUS hr = BCryptGenRandom(NULL, reinterpret_cast<BYTE*>(data), size,
|
||||||
if (!BCRYPT_SUCCESS(hr)) {
|
BCRYPT_USE_SYSTEM_PREFERRED_RNG);
|
||||||
v3fatal("Could not acquire random data.");
|
if (!BCRYPT_SUCCESS(hr)) { v3fatal("Could not acquire random data."); }
|
||||||
}
|
|
||||||
#else
|
#else
|
||||||
std::ifstream is ("/dev/urandom", std::ios::in | std::ios::binary);
|
std::ifstream is("/dev/urandom", std::ios::in | std::ios::binary);
|
||||||
// This read uses the size of the buffer.
|
// This read uses the size of the buffer.
|
||||||
// Flawfinder: ignore
|
// Flawfinder: ignore
|
||||||
if (!is.read(data, size)) {
|
if (!is.read(data, size)) {
|
||||||
v3fatal("Could not open /dev/urandom, no source of randomness. Try specifying a key instead.");
|
v3fatal("Could not open /dev/urandom, no source of randomness. "
|
||||||
|
"Try specifying a key instead.");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
return result;
|
return result;
|
||||||
|
|
@ -278,15 +283,16 @@ uint64_t V3Os::timeUsecs() {
|
||||||
// Microseconds between 1601-01-01 00:00:00 UTC and 1970-01-01 00:00:00 UTC
|
// Microseconds between 1601-01-01 00:00:00 UTC and 1970-01-01 00:00:00 UTC
|
||||||
static const uint64_t EPOCH_DIFFERENCE_USECS = 11644473600000000ull;
|
static const uint64_t EPOCH_DIFFERENCE_USECS = 11644473600000000ull;
|
||||||
|
|
||||||
FILETIME ft; // contains number of 0.1us intervals since the beginning of 1601 UTC.
|
FILETIME ft; // contains number of 0.1us intervals since the beginning of 1601 UTC.
|
||||||
GetSystemTimeAsFileTime(&ft);
|
GetSystemTimeAsFileTime(&ft);
|
||||||
uint64_t us = ((static_cast<uint64_t>(ft.dwHighDateTime) << 32) + ft.dwLowDateTime + 5ull) / 10ull;
|
uint64_t us
|
||||||
|
= ((static_cast<uint64_t>(ft.dwHighDateTime) << 32) + ft.dwLowDateTime + 5ull) / 10ull;
|
||||||
return us - EPOCH_DIFFERENCE_USECS;
|
return us - EPOCH_DIFFERENCE_USECS;
|
||||||
#else
|
#else
|
||||||
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init)
|
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init)
|
||||||
timeval tv;
|
timeval tv;
|
||||||
if (gettimeofday(&tv, NULL) < 0) return 0;
|
if (gettimeofday(&tv, NULL) < 0) return 0;
|
||||||
return static_cast<uint64_t>(tv.tv_sec)*1000000 + tv.tv_usec;
|
return static_cast<uint64_t>(tv.tv_sec) * 1000000 + tv.tv_usec;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -303,13 +309,13 @@ uint64_t V3Os::memUsageBytes() {
|
||||||
// Highly unportable. Sorry
|
// Highly unportable. Sorry
|
||||||
const char* const statmFilename = "/proc/self/statm";
|
const char* const statmFilename = "/proc/self/statm";
|
||||||
FILE* fp = fopen(statmFilename, "r");
|
FILE* fp = fopen(statmFilename, "r");
|
||||||
if (!fp) {
|
if (!fp) return 0;
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
vluint64_t size, resident, share, text, lib, data, dt; // All in pages
|
vluint64_t size, resident, share, text, lib, data, dt; // All in pages
|
||||||
if (7 != fscanf(fp, "%" VL_PRI64 "u %" VL_PRI64 "u %" VL_PRI64 "u %"
|
if (7
|
||||||
VL_PRI64 "u %" VL_PRI64 "u %" VL_PRI64 "u %" VL_PRI64 "u",
|
!= fscanf(fp,
|
||||||
&size, &resident, &share, &text, &lib, &data, &dt)) {
|
"%" VL_PRI64 "u %" VL_PRI64 "u %" VL_PRI64 "u %" VL_PRI64 "u %" VL_PRI64
|
||||||
|
"u %" VL_PRI64 "u %" VL_PRI64 "u",
|
||||||
|
&size, &resident, &share, &text, &lib, &data, &dt)) {
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -144,9 +144,7 @@ static void process() {
|
||||||
|
|
||||||
// Coverage insertion
|
// Coverage insertion
|
||||||
// Before we do dead code elimination and inlining, or we'll lose it.
|
// Before we do dead code elimination and inlining, or we'll lose it.
|
||||||
if (v3Global.opt.coverage()) {
|
if (v3Global.opt.coverage()) V3Coverage::coverage(v3Global.rootp());
|
||||||
V3Coverage::coverage(v3Global.rootp());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Push constants, but only true constants preserving liveness
|
// Push constants, but only true constants preserving liveness
|
||||||
// so V3Undriven sees variables to be eliminated, ie "if (0 && foo) ..."
|
// so V3Undriven sees variables to be eliminated, ie "if (0 && foo) ..."
|
||||||
|
|
@ -262,9 +260,7 @@ static void process() {
|
||||||
// Push constants across variables and remove redundant assignments
|
// Push constants across variables and remove redundant assignments
|
||||||
V3Const::constifyAll(v3Global.rootp());
|
V3Const::constifyAll(v3Global.rootp());
|
||||||
|
|
||||||
if (v3Global.opt.oLife()) {
|
if (v3Global.opt.oLife()) V3Life::lifeAll(v3Global.rootp());
|
||||||
V3Life::lifeAll(v3Global.rootp());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Make large low-fanin logic blocks into lookup tables
|
// Make large low-fanin logic blocks into lookup tables
|
||||||
// This should probably be done much later, once we have common logic elimination.
|
// This should probably be done much later, once we have common logic elimination.
|
||||||
|
|
@ -282,15 +278,11 @@ static void process() {
|
||||||
V3Active::activeAll(v3Global.rootp());
|
V3Active::activeAll(v3Global.rootp());
|
||||||
|
|
||||||
// Split single ALWAYS blocks into multiple blocks for better ordering chances
|
// Split single ALWAYS blocks into multiple blocks for better ordering chances
|
||||||
if (v3Global.opt.oSplit()) {
|
if (v3Global.opt.oSplit()) V3Split::splitAlwaysAll(v3Global.rootp());
|
||||||
V3Split::splitAlwaysAll(v3Global.rootp());
|
|
||||||
}
|
|
||||||
V3SplitAs::splitAsAll(v3Global.rootp());
|
V3SplitAs::splitAsAll(v3Global.rootp());
|
||||||
|
|
||||||
// Create tracing sample points, before we start eliminating signals
|
// Create tracing sample points, before we start eliminating signals
|
||||||
if (v3Global.opt.trace()) {
|
if (v3Global.opt.trace()) V3TraceDecl::traceDeclAll(v3Global.rootp());
|
||||||
V3TraceDecl::traceDeclAll(v3Global.rootp());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Gate-based logic elimination; eliminate signals and push constant across cell boundaries
|
// Gate-based logic elimination; eliminate signals and push constant across cell boundaries
|
||||||
// Instant propagation makes lots-o-constant reduction possibilities.
|
// Instant propagation makes lots-o-constant reduction possibilities.
|
||||||
|
|
@ -298,13 +290,12 @@ static void process() {
|
||||||
V3Gate::gateAll(v3Global.rootp());
|
V3Gate::gateAll(v3Global.rootp());
|
||||||
// V3Gate calls constant propagation itself.
|
// V3Gate calls constant propagation itself.
|
||||||
} else {
|
} else {
|
||||||
v3info("Command Line disabled gate optimization with -Og/-O0. This may cause ordering problems.");
|
v3info("Command Line disabled gate optimization with -Og/-O0. "
|
||||||
|
"This may cause ordering problems.");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Combine COVERINCs with duplicate terms
|
// Combine COVERINCs with duplicate terms
|
||||||
if (v3Global.opt.coverage()) {
|
if (v3Global.opt.coverage()) V3CoverageJoin::coverageJoin(v3Global.rootp());
|
||||||
V3CoverageJoin::coverageJoin(v3Global.rootp());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remove unused vars
|
// Remove unused vars
|
||||||
V3Const::constifyAll(v3Global.rootp());
|
V3Const::constifyAll(v3Global.rootp());
|
||||||
|
|
@ -318,9 +309,7 @@ static void process() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reorder assignments in pipelined blocks
|
// Reorder assignments in pipelined blocks
|
||||||
if (v3Global.opt.oReorder()) {
|
if (v3Global.opt.oReorder()) V3Split::splitReorderAll(v3Global.rootp());
|
||||||
V3Split::splitReorderAll(v3Global.rootp());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create delayed assignments
|
// Create delayed assignments
|
||||||
// This creates lots of duplicate ACTIVES so ActiveTop needs to be after this step
|
// This creates lots of duplicate ACTIVES so ActiveTop needs to be after this step
|
||||||
|
|
@ -349,9 +338,7 @@ static void process() {
|
||||||
V3Const::constifyAll(v3Global.rootp());
|
V3Const::constifyAll(v3Global.rootp());
|
||||||
V3Life::lifeAll(v3Global.rootp());
|
V3Life::lifeAll(v3Global.rootp());
|
||||||
}
|
}
|
||||||
if (v3Global.opt.oLifePost()) {
|
if (v3Global.opt.oLifePost()) V3LifePost::lifepostAll(v3Global.rootp());
|
||||||
V3LifePost::lifepostAll(v3Global.rootp());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remove unused vars
|
// Remove unused vars
|
||||||
V3Const::constifyAll(v3Global.rootp());
|
V3Const::constifyAll(v3Global.rootp());
|
||||||
|
|
@ -364,9 +351,7 @@ static void process() {
|
||||||
// Note past this point, we presume traced variables won't move between CFuncs
|
// Note past this point, we presume traced variables won't move between CFuncs
|
||||||
// (It's OK if untraced temporaries move around, or vars
|
// (It's OK if untraced temporaries move around, or vars
|
||||||
// "effectively" activate the same way.)
|
// "effectively" activate the same way.)
|
||||||
if (v3Global.opt.trace()) {
|
if (v3Global.opt.trace()) V3Trace::traceAll(v3Global.rootp());
|
||||||
V3Trace::traceAll(v3Global.rootp());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (v3Global.opt.stats()) V3Stats::statsStageAll(v3Global.rootp(), "Scoped");
|
if (v3Global.opt.stats()) V3Stats::statsStageAll(v3Global.rootp(), "Scoped");
|
||||||
|
|
||||||
|
|
@ -383,14 +368,10 @@ static void process() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Move BLOCKTEMPS from class to local variables
|
// Move BLOCKTEMPS from class to local variables
|
||||||
if (v3Global.opt.oLocalize()) {
|
if (v3Global.opt.oLocalize()) V3Localize::localizeAll(v3Global.rootp());
|
||||||
V3Localize::localizeAll(v3Global.rootp());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Icache packing; combine common code in each module's functions into subroutines
|
// Icache packing; combine common code in each module's functions into subroutines
|
||||||
if (v3Global.opt.oCombine()) {
|
if (v3Global.opt.oCombine()) V3Combine::combineAll(v3Global.rootp());
|
||||||
V3Combine::combineAll(v3Global.rootp());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
V3Error::abortIfErrors();
|
V3Error::abortIfErrors();
|
||||||
|
|
@ -414,38 +395,30 @@ static void process() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Expand macros and wide operators into C++ primitives
|
// Expand macros and wide operators into C++ primitives
|
||||||
if (!v3Global.opt.lintOnly()
|
if (!v3Global.opt.lintOnly() && !v3Global.opt.xmlOnly() && v3Global.opt.oExpand()) {
|
||||||
&& !v3Global.opt.xmlOnly()
|
|
||||||
&& v3Global.opt.oExpand()) {
|
|
||||||
V3Expand::expandAll(v3Global.rootp());
|
V3Expand::expandAll(v3Global.rootp());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Propagate constants across WORDSEL arrayed temporaries
|
// Propagate constants across WORDSEL arrayed temporaries
|
||||||
if (!v3Global.opt.xmlOnly()
|
if (!v3Global.opt.xmlOnly() && v3Global.opt.oSubst()) {
|
||||||
&& v3Global.opt.oSubst()) {
|
|
||||||
// Constant folding of expanded stuff
|
// Constant folding of expanded stuff
|
||||||
V3Const::constifyCpp(v3Global.rootp());
|
V3Const::constifyCpp(v3Global.rootp());
|
||||||
V3Subst::substituteAll(v3Global.rootp());
|
V3Subst::substituteAll(v3Global.rootp());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!v3Global.opt.xmlOnly()
|
if (!v3Global.opt.xmlOnly() && v3Global.opt.oSubstConst()) {
|
||||||
&& v3Global.opt.oSubstConst()) {
|
|
||||||
// Constant folding of substitutions
|
// Constant folding of substitutions
|
||||||
V3Const::constifyCpp(v3Global.rootp());
|
V3Const::constifyCpp(v3Global.rootp());
|
||||||
|
|
||||||
V3Dead::deadifyAll(v3Global.rootp());
|
V3Dead::deadifyAll(v3Global.rootp());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!v3Global.opt.lintOnly()
|
if (!v3Global.opt.lintOnly() && !v3Global.opt.xmlOnly() && v3Global.opt.oReloop()) {
|
||||||
&& !v3Global.opt.xmlOnly()
|
|
||||||
&& v3Global.opt.oReloop()) {
|
|
||||||
// Reform loops to reduce code size
|
// Reform loops to reduce code size
|
||||||
// Must be after all Sel/array index based optimizations
|
// Must be after all Sel/array index based optimizations
|
||||||
V3Reloop::reloopAll(v3Global.rootp());
|
V3Reloop::reloopAll(v3Global.rootp());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!v3Global.opt.lintOnly()
|
if (!v3Global.opt.lintOnly() && !v3Global.opt.xmlOnly()) {
|
||||||
&& !v3Global.opt.xmlOnly()) {
|
|
||||||
// Fix very deep expressions
|
// Fix very deep expressions
|
||||||
// Mark evaluation functions as member functions, if needed.
|
// Mark evaluation functions as member functions, if needed.
|
||||||
V3Depth::depthAll(v3Global.rootp());
|
V3Depth::depthAll(v3Global.rootp());
|
||||||
|
|
@ -459,15 +432,12 @@ static void process() {
|
||||||
}
|
}
|
||||||
|
|
||||||
V3Error::abortIfErrors();
|
V3Error::abortIfErrors();
|
||||||
if (!v3Global.opt.lintOnly()
|
if (!v3Global.opt.lintOnly() && !v3Global.opt.xmlOnly()) { //
|
||||||
&& !v3Global.opt.xmlOnly()) {
|
|
||||||
V3CCtors::cctorsAll();
|
V3CCtors::cctorsAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Output the text
|
// Output the text
|
||||||
if (!v3Global.opt.lintOnly()
|
if (!v3Global.opt.lintOnly() && !v3Global.opt.xmlOnly() && !v3Global.opt.dpiHdrOnly()) {
|
||||||
&& !v3Global.opt.xmlOnly()
|
|
||||||
&& !v3Global.opt.dpiHdrOnly()) {
|
|
||||||
// Create AstCUse to determine what class forward declarations/#includes needed in C
|
// Create AstCUse to determine what class forward declarations/#includes needed in C
|
||||||
// Must be before V3EmitC
|
// Must be before V3EmitC
|
||||||
V3CUse::cUseAll(v3Global.rootp());
|
V3CUse::cUseAll(v3Global.rootp());
|
||||||
|
|
@ -479,8 +449,7 @@ static void process() {
|
||||||
} else if (v3Global.opt.dpiHdrOnly()) {
|
} else if (v3Global.opt.dpiHdrOnly()) {
|
||||||
V3EmitC::emitcSyms(true);
|
V3EmitC::emitcSyms(true);
|
||||||
}
|
}
|
||||||
if (!v3Global.opt.xmlOnly()
|
if (!v3Global.opt.xmlOnly() && v3Global.opt.mtasks()) {
|
||||||
&& v3Global.opt.mtasks()) {
|
|
||||||
// Finalize our MTask cost estimates and pack the mtasks into
|
// Finalize our MTask cost estimates and pack the mtasks into
|
||||||
// threads. Must happen pre-EmitC which relies on the packing
|
// threads. Must happen pre-EmitC which relies on the packing
|
||||||
// order. Must happen post-V3LifePost which changes the relative
|
// order. Must happen post-V3LifePost which changes the relative
|
||||||
|
|
@ -493,8 +462,7 @@ static void process() {
|
||||||
}
|
}
|
||||||
if (v3Global.opt.xmlOnly()
|
if (v3Global.opt.xmlOnly()
|
||||||
// Check XML when debugging to make sure no missing node types
|
// Check XML when debugging to make sure no missing node types
|
||||||
|| (v3Global.opt.debugCheck() && !v3Global.opt.lintOnly()
|
|| (v3Global.opt.debugCheck() && !v3Global.opt.lintOnly() && !v3Global.opt.dpiHdrOnly())) {
|
||||||
&& !v3Global.opt.dpiHdrOnly())) {
|
|
||||||
V3EmitXml::emitxml();
|
V3EmitXml::emitxml();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -511,14 +479,12 @@ static void process() {
|
||||||
V3Stats::statsReport();
|
V3Stats::statsReport();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!v3Global.opt.lintOnly()
|
if (!v3Global.opt.lintOnly() && !v3Global.opt.xmlOnly() && !v3Global.opt.dpiHdrOnly()) {
|
||||||
&& !v3Global.opt.xmlOnly()
|
|
||||||
&& !v3Global.opt.dpiHdrOnly()) {
|
|
||||||
// Makefile must be after all other emitters
|
// Makefile must be after all other emitters
|
||||||
if (v3Global.opt.cmake()) {
|
if (v3Global.opt.cmake()) { //
|
||||||
V3EmitCMake::emit();
|
V3EmitCMake::emit();
|
||||||
}
|
}
|
||||||
if (v3Global.opt.gmake()) {
|
if (v3Global.opt.gmake()) { //
|
||||||
V3EmitMk::emitmk();
|
V3EmitMk::emitmk();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -545,9 +511,8 @@ int main(int argc, char** argv, char** env) {
|
||||||
|
|
||||||
// Command option parsing
|
// Command option parsing
|
||||||
v3Global.opt.bin(argv[0]);
|
v3Global.opt.bin(argv[0]);
|
||||||
string argString = V3Options::argString(argc-1, argv+1);
|
string argString = V3Options::argString(argc - 1, argv + 1);
|
||||||
v3Global.opt.parseOpts(new FileLine(FileLine::commandLineFilename()),
|
v3Global.opt.parseOpts(new FileLine(FileLine::commandLineFilename()), argc - 1, argv + 1);
|
||||||
argc-1, argv+1);
|
|
||||||
|
|
||||||
// Validate settings (aka Boost.Program_options)
|
// Validate settings (aka Boost.Program_options)
|
||||||
v3Global.opt.notify();
|
v3Global.opt.notify();
|
||||||
|
|
@ -558,8 +523,9 @@ int main(int argc, char** argv, char** env) {
|
||||||
V3File::addSrcDepend(v3Global.opt.bin());
|
V3File::addSrcDepend(v3Global.opt.bin());
|
||||||
if (v3Global.opt.skipIdentical().isTrue()
|
if (v3Global.opt.skipIdentical().isTrue()
|
||||||
&& V3File::checkTimes(v3Global.opt.makeDir() + "/" + v3Global.opt.prefix()
|
&& V3File::checkTimes(v3Global.opt.makeDir() + "/" + v3Global.opt.prefix()
|
||||||
+ "__verFiles.dat", argString)) {
|
+ "__verFiles.dat",
|
||||||
UINFO(1,"--skip-identical: No change to any source files, exiting\n");
|
argString)) {
|
||||||
|
UINFO(1, "--skip-identical: No change to any source files, exiting\n");
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
// Undocumented debugging - cannot be a switch as then command line
|
// Undocumented debugging - cannot be a switch as then command line
|
||||||
|
|
@ -571,9 +537,9 @@ int main(int argc, char** argv, char** env) {
|
||||||
//--FRONTEND------------------
|
//--FRONTEND------------------
|
||||||
|
|
||||||
// Cleanup
|
// Cleanup
|
||||||
V3Os::unlinkRegexp(v3Global.opt.makeDir(), v3Global.opt.prefix()+"_*.tree");
|
V3Os::unlinkRegexp(v3Global.opt.makeDir(), v3Global.opt.prefix() + "_*.tree");
|
||||||
V3Os::unlinkRegexp(v3Global.opt.makeDir(), v3Global.opt.prefix()+"_*.dot");
|
V3Os::unlinkRegexp(v3Global.opt.makeDir(), v3Global.opt.prefix() + "_*.dot");
|
||||||
V3Os::unlinkRegexp(v3Global.opt.makeDir(), v3Global.opt.prefix()+"_*.txt");
|
V3Os::unlinkRegexp(v3Global.opt.makeDir(), v3Global.opt.prefix() + "_*.txt");
|
||||||
|
|
||||||
// Internal tests (after option parsing as need debug() setting,
|
// Internal tests (after option parsing as need debug() setting,
|
||||||
// and after removing files as may make debug output)
|
// and after removing files as may make debug output)
|
||||||
|
|
@ -591,7 +557,7 @@ int main(int argc, char** argv, char** env) {
|
||||||
v3Global.readFiles();
|
v3Global.readFiles();
|
||||||
|
|
||||||
// Link, etc, if needed
|
// Link, etc, if needed
|
||||||
if (!v3Global.opt.preprocOnly()) {
|
if (!v3Global.opt.preprocOnly()) { //
|
||||||
process();
|
process();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -600,10 +566,11 @@ int main(int argc, char** argv, char** env) {
|
||||||
V3Error::abortIfWarnings();
|
V3Error::abortIfWarnings();
|
||||||
|
|
||||||
if (v3Global.opt.makeDepend().isTrue()) {
|
if (v3Global.opt.makeDepend().isTrue()) {
|
||||||
V3File::writeDepend(v3Global.opt.makeDir()+"/"+v3Global.opt.prefix()+"__ver.d");
|
V3File::writeDepend(v3Global.opt.makeDir() + "/" + v3Global.opt.prefix() + "__ver.d");
|
||||||
}
|
}
|
||||||
if (v3Global.opt.protectIds()) {
|
if (v3Global.opt.protectIds()) {
|
||||||
VIdProtect::writeMapFile(v3Global.opt.makeDir()+"/"+v3Global.opt.prefix()+"__idmap.xml");
|
VIdProtect::writeMapFile(v3Global.opt.makeDir() + "/" + v3Global.opt.prefix()
|
||||||
|
+ "__idmap.xml");
|
||||||
}
|
}
|
||||||
if (v3Global.opt.skipIdentical().isTrue() || v3Global.opt.makeDepend().isTrue()) {
|
if (v3Global.opt.skipIdentical().isTrue() || v3Global.opt.makeDepend().isTrue()) {
|
||||||
V3File::writeTimes(v3Global.opt.makeDir() + "/" + v3Global.opt.prefix() + "__verFiles.dat",
|
V3File::writeTimes(v3Global.opt.makeDir() + "/" + v3Global.opt.prefix() + "__verFiles.dat",
|
||||||
|
|
@ -618,5 +585,5 @@ int main(int argc, char** argv, char** env) {
|
||||||
#endif
|
#endif
|
||||||
FileLine::deleteAllRemaining();
|
FileLine::deleteAllRemaining();
|
||||||
|
|
||||||
UINFO(1,"Done, Exiting...\n");
|
UINFO(1, "Done, Exiting...\n");
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue