Internals: clang-format files needed for #2249.

This commit is contained in:
Wilson Snyder 2020-04-14 19:55:00 -04:00
parent 08b74e5ab9
commit 1b94e3b0e2
6 changed files with 752 additions and 867 deletions

View File

@ -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

View File

@ -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

View File

@ -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);

View File

@ -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;
}

View File

@ -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");
}