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