Internals: Refactor V3EmitUtil to not be base class. No functional change.

This commit is contained in:
Wilson Snyder 2025-08-25 22:05:40 -04:00
parent ac2859bf24
commit 5f23bf95f6
24 changed files with 259 additions and 236 deletions

View File

@ -954,10 +954,10 @@ AstNodeDType::CTypeRecursed AstNodeDType::cTypeRecurse(bool compound, bool packe
info.m_type = "VlSampleQueue<" + sub.m_type + ">"; info.m_type = "VlSampleQueue<" + sub.m_type + ">";
} else if (const auto* const adtypep = VN_CAST(dtypep, ClassRefDType)) { } else if (const auto* const adtypep = VN_CAST(dtypep, ClassRefDType)) {
UASSERT_OBJ(!packed, this, "Unsupported type for packed struct or union"); UASSERT_OBJ(!packed, this, "Unsupported type for packed struct or union");
info.m_type = "VlClassRef<" + EmitCBase::prefixNameProtect(adtypep) + ">"; info.m_type = "VlClassRef<" + EmitCUtil::prefixNameProtect(adtypep) + ">";
} else if (const auto* const adtypep = VN_CAST(dtypep, IfaceRefDType)) { } else if (const auto* const adtypep = VN_CAST(dtypep, IfaceRefDType)) {
UASSERT_OBJ(!packed, this, "Unsupported type for packed struct or union"); UASSERT_OBJ(!packed, this, "Unsupported type for packed struct or union");
info.m_type = EmitCBase::prefixNameProtect(adtypep->ifaceViaCellp()) + "*"; info.m_type = EmitCUtil::prefixNameProtect(adtypep->ifaceViaCellp()) + "*";
} else if (const auto* const adtypep = VN_CAST(dtypep, UnpackArrayDType)) { } else if (const auto* const adtypep = VN_CAST(dtypep, UnpackArrayDType)) {
UASSERT_OBJ(!packed, this, "Unsupported type for packed struct or union"); UASSERT_OBJ(!packed, this, "Unsupported type for packed struct or union");
if (adtypep->isCompound()) compound = true; if (adtypep->isCompound()) compound = true;
@ -991,7 +991,7 @@ AstNodeDType::CTypeRecursed AstNodeDType::cTypeRecurse(bool compound, bool packe
const AstNodeUOrStructDType* const sdtypep = VN_AS(dtypep, NodeUOrStructDType); const AstNodeUOrStructDType* const sdtypep = VN_AS(dtypep, NodeUOrStructDType);
UASSERT_OBJ(!packed || sdtypep->packed(), this, UASSERT_OBJ(!packed || sdtypep->packed(), this,
"Unsupported type for packed struct or union"); "Unsupported type for packed struct or union");
info.m_type = EmitCBase::prefixNameProtect(sdtypep); info.m_type = EmitCUtil::prefixNameProtect(sdtypep);
} else if (const AstBasicDType* const bdtypep = dtypep->basicp()) { } else if (const AstBasicDType* const bdtypep = dtypep->basicp()) {
// We don't print msb()/lsb() as multidim packed would require recursion, // We don't print msb()/lsb() as multidim packed would require recursion,
// and may confuse users as C++ data is stored always with bit 0 used // and may confuse users as C++ data is stored always with bit 0 used

View File

@ -67,7 +67,7 @@ class V3CCtorsBuilder final {
funcp->slow(!m_type.isClass()); // Only classes construct on fast path funcp->slow(!m_type.isClass()); // Only classes construct on fast path
string preventUnusedStmt; string preventUnusedStmt;
if (m_type.isClass()) { if (m_type.isClass()) {
funcp->argTypes(EmitCBase::symClassVar()); funcp->argTypes(EmitCUtil::symClassVar());
preventUnusedStmt = "(void)vlSymsp; // Prevent unused variable warning\n"; preventUnusedStmt = "(void)vlSymsp; // Prevent unused variable warning\n";
} else if (m_type.isCoverage()) { } else if (m_type.isCoverage()) {
funcp->argTypes("bool first"); funcp->argTypes("bool first");

View File

@ -52,7 +52,7 @@ string V3Common::makeToStringCall(AstNodeDType* nodep, const std::string& lhs) {
static void makeVlToString(AstClass* nodep) { static void makeVlToString(AstClass* nodep) {
AstCFunc* const funcp AstCFunc* const funcp
= new AstCFunc{nodep->fileline(), "VL_TO_STRING", nullptr, "std::string"}; = new AstCFunc{nodep->fileline(), "VL_TO_STRING", nullptr, "std::string"};
funcp->argTypes("const VlClassRef<" + EmitCBase::prefixNameProtect(nodep) + ">& obj"); funcp->argTypes("const VlClassRef<" + EmitCUtil::prefixNameProtect(nodep) + ">& obj");
funcp->isMethod(false); funcp->isMethod(false);
funcp->isConst(false); funcp->isConst(false);
funcp->isStatic(false); funcp->isStatic(false);
@ -66,7 +66,7 @@ static void makeVlToString(AstClass* nodep) {
static void makeVlToString(AstIface* nodep) { static void makeVlToString(AstIface* nodep) {
AstCFunc* const funcp AstCFunc* const funcp
= new AstCFunc{nodep->fileline(), "VL_TO_STRING", nullptr, "std::string"}; = new AstCFunc{nodep->fileline(), "VL_TO_STRING", nullptr, "std::string"};
funcp->argTypes("const " + EmitCBase::prefixNameProtect(nodep) + "* obj"); funcp->argTypes("const " + EmitCUtil::prefixNameProtect(nodep) + "* obj");
funcp->isMethod(false); funcp->isMethod(false);
funcp->isConst(false); funcp->isConst(false);
funcp->isStatic(false); funcp->isStatic(false);
@ -81,7 +81,7 @@ static void makeVlToString(AstNodeUOrStructDType* nodep) {
UASSERT_OBJ(modp, nodep, "Unlinked struct package"); UASSERT_OBJ(modp, nodep, "Unlinked struct package");
AstCFunc* const funcp AstCFunc* const funcp
= new AstCFunc{nodep->fileline(), "VL_TO_STRING", nullptr, "std::string"}; = new AstCFunc{nodep->fileline(), "VL_TO_STRING", nullptr, "std::string"};
funcp->argTypes("const " + EmitCBase::prefixNameProtect(nodep) + "& obj"); funcp->argTypes("const " + EmitCUtil::prefixNameProtect(nodep) + "& obj");
funcp->isMethod(false); funcp->isMethod(false);
funcp->isConst(false); funcp->isConst(false);
funcp->isStatic(false); funcp->isStatic(false);
@ -145,7 +145,7 @@ static void makeToStringMiddle(AstClass* nodep) {
string stmt = "out += "; string stmt = "out += ";
if (!comma.empty()) stmt += "\", \"+ "; if (!comma.empty()) stmt += "\", \"+ ";
// comma = ", "; // Nothing further so not needed // comma = ", "; // Nothing further so not needed
stmt += EmitCBase::prefixNameProtect(nodep->extendsp()->dtypep()); stmt += EmitCUtil::prefixNameProtect(nodep->extendsp()->dtypep());
stmt += "::to_string_middle();\n"; stmt += "::to_string_middle();\n";
nodep->user1(true); // So what we extend dumps this nodep->user1(true); // So what we extend dumps this
funcp->addStmtsp(new AstCStmt{nodep->fileline(), stmt}); funcp->addStmtsp(new AstCStmt{nodep->fileline(), stmt});

View File

@ -57,7 +57,7 @@ class DepthBlockVisitor final : public VNVisitor {
AstCCall* const callp = new AstCCall{nodep->fileline(), funcp}; AstCCall* const callp = new AstCCall{nodep->fileline(), funcp};
callp->dtypeSetVoid(); callp->dtypeSetVoid();
if (VN_IS(m_modp, Class)) { if (VN_IS(m_modp, Class)) {
funcp->argTypes(EmitCBase::symClassVar()); funcp->argTypes(EmitCUtil::symClassVar());
callp->argTypes("vlSymsp"); callp->argTypes("vlSymsp");
} }
UINFO(6, " New " << callp); UINFO(6, " New " << callp);

View File

@ -36,9 +36,9 @@ EmitCParentModule::EmitCParentModule() {
} }
//###################################################################### //######################################################################
// EmitCBase implementation // EmitCUtil implementation
string EmitCBase::prefixNameProtect(const AstNode* nodep) VL_MT_STABLE { string EmitCUtil::prefixNameProtect(const AstNode* nodep) VL_MT_STABLE {
const string prefix = v3Global.opt.modPrefix() + "_" + VIdProtect::protect(nodep->name()); const string prefix = v3Global.opt.modPrefix() + "_" + VIdProtect::protect(nodep->name());
// If all-uppercase prefix conflicts with a previous usage of the // If all-uppercase prefix conflicts with a previous usage of the
// prefix with different capitalization, rename to avoid conflict. // prefix with different capitalization, rename to avoid conflict.
@ -78,13 +78,13 @@ string EmitCBaseVisitorConst::funcNameProtect(const AstCFunc* nodep, const AstNo
modp = modp ? modp : EmitCParentModule::get(nodep); modp = modp ? modp : EmitCParentModule::get(nodep);
string name; string name;
if (nodep->isConstructor()) { if (nodep->isConstructor()) {
name += prefixNameProtect(modp); name += EmitCUtil::prefixNameProtect(modp);
} else if (nodep->isDestructor()) { } else if (nodep->isDestructor()) {
name += "~"; name += "~";
name += prefixNameProtect(modp); name += EmitCUtil::prefixNameProtect(modp);
} else { } else {
if (nodep->isLoose()) { if (nodep->isLoose()) {
name += prefixNameProtect(modp); name += EmitCUtil::prefixNameProtect(modp);
name += "__"; name += "__";
} }
name += nodep->nameProtect(); name += nodep->nameProtect();
@ -112,7 +112,7 @@ string EmitCBaseVisitorConst::cFuncArgs(const AstCFunc* nodep) {
string args; string args;
if (nodep->isLoose() && !nodep->isStatic()) { if (nodep->isLoose() && !nodep->isStatic()) {
if (nodep->isConst().trueKnown()) args += "const "; if (nodep->isConst().trueKnown()) args += "const ";
args += prefixNameProtect(EmitCParentModule::get(nodep)); args += EmitCUtil::prefixNameProtect(EmitCParentModule::get(nodep));
args += "* vlSelf"; args += "* vlSelf";
} }
if (nodep->needProcess()) { if (nodep->needProcess()) {
@ -150,9 +150,9 @@ void EmitCBaseVisitorConst::emitCFuncHeader(const AstCFunc* funcp, const AstNode
} }
if (withScope) { if (withScope) {
if (funcp->dpiExportDispatcher()) { if (funcp->dpiExportDispatcher()) {
putns(funcp, topClassName() + "::"); putns(funcp, EmitCUtil::topClassName() + "::");
} else if (funcp->isProperMethod()) { } else if (funcp->isProperMethod()) {
putns(funcp, prefixNameProtect(modp) + "::"); putns(funcp, EmitCUtil::prefixNameProtect(modp) + "::");
} }
} }
putns(funcp, funcNameProtect(funcp, modp)); putns(funcp, funcNameProtect(funcp, modp));
@ -313,7 +313,7 @@ std::pair<string, FileLine*> EmitCBaseVisitorConst::textSection(const AstNodeMod
string::size_type pos; string::size_type pos;
while ((pos = text.find("`systemc_class_name")) != string::npos) { while ((pos = text.find("`systemc_class_name")) != string::npos) {
text.replace(pos, std::strlen("`systemc_class_name"), text.replace(pos, std::strlen("`systemc_class_name"),
EmitCBase::prefixNameProtect(modp)); EmitCUtil::prefixNameProtect(modp));
} }
} }
return std::make_pair(text, fl); return std::make_pair(text, fl);

View File

@ -45,9 +45,9 @@ public:
}; };
//###################################################################### //######################################################################
// Base Visitor class -- holds output file pointer // EmitC-related utility functions
class EmitCBase VL_NOT_FINAL { class EmitCUtil final {
public: public:
static string voidSelfAssign(const AstNodeModule* modp) { static string voidSelfAssign(const AstNodeModule* modp) {
const string className = prefixNameProtect(modp); const string className = prefixNameProtect(modp);
@ -81,7 +81,10 @@ public:
} }
}; };
class EmitCBaseVisitorConst VL_NOT_FINAL : public VNVisitorConst, public EmitCBase { //######################################################################
// Base Visitor class -- holds output file pointer
class EmitCBaseVisitorConst VL_NOT_FINAL : public VNVisitorConst {
public: public:
// STATE // STATE
V3OutCFile* m_ofp = nullptr; V3OutCFile* m_ofp = nullptr;
@ -130,15 +133,6 @@ public:
void ensureNewLine() { ofp()->ensureNewLine(); } void ensureNewLine() { ofp()->ensureNewLine(); }
bool optSystemC() { return v3Global.opt.systemC(); } bool optSystemC() { return v3Global.opt.systemC(); }
static string protect(const string& name) VL_MT_SAFE { return VIdProtect::protect(name); } static string protect(const string& name) VL_MT_SAFE { return VIdProtect::protect(name); }
static string protectIf(const string& name, bool doIt) {
return VIdProtect::protectIf(name, doIt);
}
static string protectWordsIf(const string& name, bool doIt) {
return VIdProtect::protectWordsIf(name, doIt);
}
static string ifNoProtect(const string& in) VL_MT_SAFE {
return v3Global.opt.protectIds() ? "" : in;
}
static string funcNameProtect(const AstCFunc* nodep, const AstNodeModule* modp = nullptr); static string funcNameProtect(const AstCFunc* nodep, const AstNodeModule* modp = nullptr);
static AstCFile* newCFile(const string& filename, bool slow, bool source); static AstCFile* newCFile(const string& filename, bool slow, bool source);
static AstCFile* createCFile(const string& filename, bool slow, bool source) VL_MT_SAFE; static AstCFile* createCFile(const string& filename, bool slow, bool source) VL_MT_SAFE;
@ -153,11 +147,11 @@ public:
if (const AstCUse* const usep = VN_CAST(itemp, CUse)) { if (const AstCUse* const usep = VN_CAST(itemp, CUse)) {
if (usep->useType().containsAny(useType)) { if (usep->useType().containsAny(useType)) {
if (usep->useType().containsAny(VUseType::INT_INCLUDE)) { if (usep->useType().containsAny(VUseType::INT_INCLUDE)) {
action("#include \"" + prefixNameProtect(usep) + ".h\"\n"); action("#include \"" + EmitCUtil::prefixNameProtect(usep) + ".h\"\n");
continue; // Forward declaration is not necessary continue; // Forward declaration is not necessary
} }
if (usep->useType().containsAny(VUseType::INT_FWD_CLASS)) { if (usep->useType().containsAny(VUseType::INT_FWD_CLASS)) {
action("class " + prefixNameProtect(usep) + ";\n"); action("class " + EmitCUtil::prefixNameProtect(usep) + ";\n");
} }
} }
} }

View File

@ -32,7 +32,6 @@ class EmitCConstInit VL_NOT_FINAL : public EmitCBaseVisitorConst {
bool m_inUnpacked = false; bool m_inUnpacked = false;
// METHODS // METHODS
uint32_t tabModulus(const AstNodeDType* dtypep) { uint32_t tabModulus(const AstNodeDType* dtypep) {
const uint32_t elemBytes = dtypep->widthTotalBytes(); const uint32_t elemBytes = dtypep->widthTotalBytes();
return dtypep->isString() ? 1 // String return dtypep->isString() ? 1 // String
@ -99,6 +98,7 @@ protected:
} // LCOV_EXCL_STOP } // LCOV_EXCL_STOP
void visit(AstConst* nodep) override { void visit(AstConst* nodep) override {
// TODO merge with EmitCFunc::emitConstant
const V3Number& num = nodep->num(); const V3Number& num = nodep->num();
UASSERT_OBJ(!num.isFourState(), nodep, "4-state value in constant pool"); UASSERT_OBJ(!num.isFourState(), nodep, "4-state value in constant pool");
const AstNodeDType* const dtypep = nodep->dtypep(); const AstNodeDType* const dtypep = nodep->dtypep();

View File

@ -42,8 +42,8 @@ class EmitCConstPool final : public EmitCConstInit {
// METHODS // METHODS
OutCFilePair newOutCFile() const { OutCFilePair newOutCFile() const {
const string fileName = v3Global.opt.makeDir() + "/" + topClassName() + "__ConstPool_" const string fileName = v3Global.opt.makeDir() + "/" + EmitCUtil::topClassName()
+ cvtToStr(m_outFileCount) + ".cpp"; + "__ConstPool_" + cvtToStr(m_outFileCount) + ".cpp";
AstCFile* const cfilep = newCFile(fileName, /* slow: */ true, /* source: */ true); AstCFile* const cfilep = newCFile(fileName, /* slow: */ true, /* source: */ true);
V3OutCFile* const ofp = new V3OutCFile{fileName}; V3OutCFile* const ofp = new V3OutCFile{fileName};
ofp->putsHeader(); ofp->putsHeader();
@ -84,7 +84,8 @@ class EmitCConstPool final : public EmitCConstInit {
for (const AstVar* varp : varps) { for (const AstVar* varp : varps) {
maybeSplitCFile(); maybeSplitCFile();
const string nameProtect = topClassName() + "__ConstPool__" + varp->nameProtect(); const string nameProtect
= EmitCUtil::topClassName() + "__ConstPool__" + varp->nameProtect();
puts("\n"); puts("\n");
putns(varp, "extern const "); putns(varp, "extern const ");
putns(varp, varp->dtypep()->cType(nameProtect, false, false)); putns(varp, varp->dtypep()->cType(nameProtect, false, false));

View File

@ -488,6 +488,7 @@ void EmitCFunc::emitCvtWideArray(AstNode* nodep, AstNode* fromp) {
void EmitCFunc::emitConstant(AstConst* nodep, AstVarRef* assigntop, const string& assignString) { void EmitCFunc::emitConstant(AstConst* nodep, AstVarRef* assigntop, const string& assignString) {
// Put out constant set to the specified variable, or given variable in a string // Put out constant set to the specified variable, or given variable in a string
// TODO merge with V3EmitCConstInit::visit(AstConst)
putns(nodep, ""); putns(nodep, "");
if (nodep->num().isNull()) { if (nodep->num().isNull()) {
putns(nodep, "VlNull{}"); putns(nodep, "VlNull{}");

View File

@ -64,7 +64,7 @@ class EmitCLazyDecls final : public VNVisitorConst {
void lazyDeclareConstPoolVar(AstVar* varp) { void lazyDeclareConstPoolVar(AstVar* varp) {
if (!declaredOnce(varp)) return; // Already declared if (!declaredOnce(varp)) return; // Already declared
const string nameProtect const string nameProtect
= m_emitter.topClassName() + "__ConstPool__" + varp->nameProtect(); = EmitCUtil::topClassName() + "__ConstPool__" + varp->nameProtect();
m_emitter.putns(varp, "extern const "); m_emitter.putns(varp, "extern const ");
m_emitter.puts(varp->dtypep()->cType(nameProtect, false, false)); m_emitter.puts(varp->dtypep()->cType(nameProtect, false, false));
m_emitter.puts(";\n"); m_emitter.puts(";\n");
@ -85,7 +85,7 @@ class EmitCLazyDecls final : public VNVisitorConst {
void visit(AstVarRef* nodep) override { void visit(AstVarRef* nodep) override {
AstVar* const varp = nodep->varp(); AstVar* const varp = nodep->varp();
// Only constant pool symbols are lazy declared for now ... // Only constant pool symbols are lazy declared for now ...
if (EmitCBase::isConstPoolMod(EmitCParentModule::get(varp))) { if (EmitCUtil::isConstPoolMod(EmitCParentModule::get(varp))) {
lazyDeclareConstPoolVar(varp); lazyDeclareConstPoolVar(varp);
} }
} }
@ -272,7 +272,7 @@ public:
if (doneClasses.count(vbase)) continue; if (doneClasses.count(vbase)) continue;
puts(doneClasses.empty() ? "" : "\n , "); puts(doneClasses.empty() ? "" : "\n , ");
doneClasses.emplace(vbase); doneClasses.emplace(vbase);
puts(prefixNameProtect(vbase)); puts(EmitCUtil::EmitCUtil::prefixNameProtect(vbase));
if (constructorNeedsProcess(vbase)) { if (constructorNeedsProcess(vbase)) {
puts("(vlProcess, vlSymsp)"); puts("(vlProcess, vlSymsp)");
} else { } else {
@ -287,7 +287,7 @@ public:
if (doneClasses.count(extp->classp())) continue; if (doneClasses.count(extp->classp())) continue;
puts(doneClasses.empty() ? "" : "\n , "); puts(doneClasses.empty() ? "" : "\n , ");
doneClasses.emplace(extp->classp()); doneClasses.emplace(extp->classp());
puts(prefixNameProtect(extp->classp())); puts(EmitCUtil::EmitCUtil::prefixNameProtect(extp->classp()));
if (constructorNeedsProcess(extp->classp())) { if (constructorNeedsProcess(extp->classp())) {
puts("(vlProcess, vlSymsp"); puts("(vlProcess, vlSymsp");
} else { } else {
@ -349,7 +349,7 @@ public:
// "+" in the debug indicates a print from the model // "+" in the debug indicates a print from the model
puts("VL_DEBUG_IF(VL_DBG_MSGF(\"+ "); puts("VL_DEBUG_IF(VL_DBG_MSGF(\"+ ");
for (int i = 0; i < m_modp->level(); ++i) puts(" "); for (int i = 0; i < m_modp->level(); ++i) puts(" ");
puts(prefixNameProtect(m_modp)); puts(EmitCUtil::prefixNameProtect(m_modp));
puts(nodep->isLoose() ? "__" : "::"); puts(nodep->isLoose() ? "__" : "::");
puts(nodep->nameProtect() + "\\n\"); );\n"); puts(nodep->nameProtect() + "\\n\"); );\n");
@ -358,7 +358,7 @@ public:
if (!nodep->isStatic()) { // Standard prologue if (!nodep->isStatic()) { // Standard prologue
m_useSelfForThis = true; m_useSelfForThis = true;
if (!VN_IS(m_modp, Class)) { if (!VN_IS(m_modp, Class)) {
puts(symClassAssign()); // Uses vlSelf puts(EmitCUtil::symClassAssign()); // Uses vlSelf
} else { } else {
puts("(void)vlSelf; // Prevent unused variable warning\n"); puts("(void)vlSelf; // Prevent unused variable warning\n");
} }
@ -606,11 +606,11 @@ public:
putns(nodep, funcp->name()); putns(nodep, funcp->name());
} else if (funcp->isProperMethod() && funcp->isStatic()) { } else if (funcp->isProperMethod() && funcp->isStatic()) {
// Call static method via the containing class // Call static method via the containing class
putns(funcModp, prefixNameProtect(funcModp) + "::"); putns(funcModp, EmitCUtil::prefixNameProtect(funcModp) + "::");
putns(nodep, funcp->nameProtect()); putns(nodep, funcp->nameProtect());
} else if (nodep->superReference()) { } else if (nodep->superReference()) {
// Calling superclass method // Calling superclass method
putns(funcModp, prefixNameProtect(funcModp) + "::"); putns(funcModp, EmitCUtil::prefixNameProtect(funcModp) + "::");
putns(nodep, funcp->nameProtect()); putns(nodep, funcp->nameProtect());
} else if (funcp->isLoose()) { } else if (funcp->isLoose()) {
// Calling loose method // Calling loose method
@ -642,7 +642,7 @@ public:
return; return;
} }
// assignment case; // assignment case;
putns(nodep, "VL_NEW(" + prefixNameProtect(nodep->dtypep()) + ", " putns(nodep, "VL_NEW(" + EmitCUtil::prefixNameProtect(nodep->dtypep()) + ", "
+ optionalProcArg(nodep->dtypep()) + "vlSymsp"); + optionalProcArg(nodep->dtypep()) + "vlSymsp");
putCommaIterateNext(nodep->argsp(), true); putCommaIterateNext(nodep->argsp(), true);
puts(")"); puts(")");
@ -716,11 +716,11 @@ public:
puts(cvtToStr(nodep->offset() + nodep->fileline()->firstColumn())); puts(cvtToStr(nodep->offset() + nodep->fileline()->firstColumn()));
puts(", "); puts(", ");
putsQuoted((!nodep->hier().empty() ? "." : "") putsQuoted((!nodep->hier().empty() ? "." : "")
+ protectWordsIf(nodep->hier(), nodep->protect())); + VIdProtect::protectWordsIf(nodep->hier(), nodep->protect()));
puts(", "); puts(", ");
putsQuoted(protectWordsIf(nodep->page(), nodep->protect())); putsQuoted(VIdProtect::protectWordsIf(nodep->page(), nodep->protect()));
puts(", "); puts(", ");
putsQuoted(protectWordsIf(nodep->comment(), nodep->protect())); putsQuoted(VIdProtect::protectWordsIf(nodep->comment(), nodep->protect()));
puts(", "); puts(", ");
putsQuoted(nodep->linescov()); putsQuoted(nodep->linescov());
puts(");\n"); puts(");\n");
@ -750,11 +750,11 @@ public:
puts(cvtToStr(nodep->fileline()->firstColumn())); puts(cvtToStr(nodep->fileline()->firstColumn()));
puts(", "); puts(", ");
putsQuoted((!nodep->hier().empty() ? "." : "") putsQuoted((!nodep->hier().empty() ? "." : "")
+ protectWordsIf(nodep->hier(), nodep->protect())); + VIdProtect::protectWordsIf(nodep->hier(), nodep->protect()));
puts(", "); puts(", ");
putsQuoted(protectWordsIf(nodep->page(), nodep->protect())); putsQuoted(VIdProtect::protectWordsIf(nodep->page(), nodep->protect()));
puts(", "); puts(", ");
putsQuoted(protectWordsIf(nodep->comment(), nodep->protect())); putsQuoted(VIdProtect::protectWordsIf(nodep->comment(), nodep->protect()));
puts(");\n"); puts(");\n");
} }
void visit(AstCoverInc* nodep) override { void visit(AstCoverInc* nodep) override {
@ -1254,8 +1254,8 @@ public:
VL_RESTORER(m_inUC); VL_RESTORER(m_inUC);
m_inUC = true; m_inUC = true;
putnbs(nodep, ""); putnbs(nodep, "");
putsDecoration(nodep, putsDecoration(nodep, VIdProtect::ifNoProtect("// $c statement at "
ifNoProtect("// $c statement at " + nodep->fileline()->ascii() + "\n")); + nodep->fileline()->ascii() + "\n"));
iterateAndNextConstNull(nodep->exprsp()); iterateAndNextConstNull(nodep->exprsp());
puts("\n"); puts("\n");
} }
@ -1264,8 +1264,8 @@ public:
m_inUC = true; m_inUC = true;
puts("\n"); puts("\n");
putnbs(nodep, ""); putnbs(nodep, "");
putsDecoration(nodep, putsDecoration(nodep, VIdProtect::ifNoProtect("// $c function at "
ifNoProtect("// $c function at " + nodep->fileline()->ascii() + "\n")); + nodep->fileline()->ascii() + "\n"));
iterateAndNextConstNull(nodep->exprsp()); iterateAndNextConstNull(nodep->exprsp());
puts("\n"); puts("\n");
} }
@ -1385,7 +1385,7 @@ public:
puts(")"); puts(")");
} }
void visit(AstNewCopy* nodep) override { void visit(AstNewCopy* nodep) override {
putns(nodep, "VL_NEW(" + prefixNameProtect(nodep->dtypep())); putns(nodep, "VL_NEW(" + EmitCUtil::prefixNameProtect(nodep->dtypep()));
puts(", *"); // i.e. make into a reference puts(", *"); // i.e. make into a reference
iterateAndNextConstNull(nodep->rhsp()); iterateAndNextConstNull(nodep->rhsp());
puts(")"); puts(")");
@ -1467,15 +1467,15 @@ public:
void visit(AstVarRef* nodep) override { void visit(AstVarRef* nodep) override {
const AstVar* const varp = nodep->varp(); const AstVar* const varp = nodep->varp();
const AstNodeModule* const varModp = EmitCParentModule::get(varp); const AstNodeModule* const varModp = EmitCParentModule::get(varp);
if (isConstPoolMod(varModp)) { if (EmitCUtil::isConstPoolMod(varModp)) {
// Reference to constant pool variable // Reference to constant pool variable
putns(nodep, topClassName() + "__ConstPool__"); putns(nodep, EmitCUtil::topClassName() + "__ConstPool__");
} else if (varp->isStatic()) { } else if (varp->isStatic()) {
// Access static variable via the containing class // Access static variable via the containing class
putns(nodep, prefixNameProtect(varModp) + "::"); putns(nodep, EmitCUtil::prefixNameProtect(varModp) + "::");
} else if (VN_IS(varModp, Class) && varModp != m_modp) { } else if (VN_IS(varModp, Class) && varModp != m_modp) {
// Superclass member reference // Superclass member reference
putns(nodep, prefixNameProtect(varModp) + "::"); putns(nodep, EmitCUtil::prefixNameProtect(varModp) + "::");
} else if (varp->isIfaceRef()) { } else if (varp->isIfaceRef()) {
putns(nodep, nodep->selfPointerProtect(m_useSelfForThis)); putns(nodep, nodep->selfPointerProtect(m_useSelfForThis));
return; return;

View File

@ -47,8 +47,8 @@ class EmitCHeader final : public EmitCConstInit {
for (const AstNode* nodep = modp->stmtsp(); nodep; nodep = nodep->nextp()) { for (const AstNode* nodep = modp->stmtsp(); nodep; nodep = nodep->nextp()) {
if (const AstCell* const cellp = VN_CAST(nodep, Cell)) { if (const AstCell* const cellp = VN_CAST(nodep, Cell)) {
decorateFirst(first, "// CELLS\n"); decorateFirst(first, "// CELLS\n");
putns(cellp, putns(cellp, EmitCUtil::prefixNameProtect(cellp->modp()) + "* "
prefixNameProtect(cellp->modp()) + "* " + cellp->nameProtect() + ";\n"); + cellp->nameProtect() + ";\n");
} }
} }
} }
@ -111,7 +111,7 @@ class EmitCHeader final : public EmitCConstInit {
if (const AstVar* const varp = VN_CAST(nodep, Var)) { if (const AstVar* const varp = VN_CAST(nodep, Var)) {
if (varp->isIO() || varp->isSignal() || varp->isClassMember() || varp->isTemp() if (varp->isIO() || varp->isSignal() || varp->isClassMember() || varp->isTemp()
|| varp->isGenVar()) { || varp->isGenVar()) {
const bool anon = isAnonOk(varp); const bool anon = EmitCUtil::isAnonOk(varp);
if (anon != lastAnon) emitCurrentList(); if (anon != lastAnon) emitCurrentList();
lastAnon = anon; lastAnon = anon;
varList.emplace_back(varp); varList.emplace_back(varp);
@ -130,7 +130,7 @@ class EmitCHeader final : public EmitCConstInit {
} }
} else { // not class } else { // not class
putsDecoration(nullptr, "\n// INTERNAL VARIABLES\n"); putsDecoration(nullptr, "\n// INTERNAL VARIABLES\n");
puts(symClassName() + "* const vlSymsp;\n"); puts(EmitCUtil::symClassName() + "* const vlSymsp;\n");
} }
} }
void emitParamDecls(const AstNodeModule* modp) { void emitParamDecls(const AstNodeModule* modp) {
@ -156,9 +156,10 @@ class EmitCHeader final : public EmitCConstInit {
} }
void emitCtorDtorDecls(const AstNodeModule* modp) { void emitCtorDtorDecls(const AstNodeModule* modp) {
if (!VN_IS(modp, Class)) { // Classes use CFuncs with isConstructor/isDestructor if (!VN_IS(modp, Class)) { // Classes use CFuncs with isConstructor/isDestructor
const string& name = prefixNameProtect(modp); const string& name = EmitCUtil::prefixNameProtect(modp);
putsDecoration(nullptr, "\n// CONSTRUCTORS\n"); putsDecoration(nullptr, "\n// CONSTRUCTORS\n");
putns(modp, name + "(" + symClassName() + "* symsp, const char* v__name);\n"); putns(modp,
name + "(" + EmitCUtil::symClassName() + "* symsp, const char* v__name);\n");
putns(modp, "~" + name + "();\n"); putns(modp, "~" + name + "();\n");
putns(modp, "VL_UNCOPYABLE(" + name + ");\n"); putns(modp, "VL_UNCOPYABLE(" + name + ");\n");
} }
@ -290,7 +291,7 @@ class EmitCHeader final : public EmitCConstInit {
} }
void emitUnpackedUOrSBody(AstNodeUOrStructDType* sdtypep) { void emitUnpackedUOrSBody(AstNodeUOrStructDType* sdtypep) {
putns(sdtypep, sdtypep->verilogKwd()); // "struct"/"union" putns(sdtypep, sdtypep->verilogKwd()); // "struct"/"union"
puts(" " + EmitCBase::prefixNameProtect(sdtypep) + " {\n"); puts(" " + EmitCUtil::prefixNameProtect(sdtypep) + " {\n");
for (const AstMemberDType* itemp = sdtypep->membersp(); itemp; for (const AstMemberDType* itemp = sdtypep->membersp(); itemp;
itemp = VN_AS(itemp->nextp(), MemberDType)) { itemp = VN_AS(itemp->nextp(), MemberDType)) {
putns(itemp, itemp->dtypep()->cType(itemp->nameProtect(), false, false)); putns(itemp, itemp->dtypep()->cType(itemp->nameProtect(), false, false));
@ -347,7 +348,7 @@ class EmitCHeader final : public EmitCConstInit {
} }
puts(");\n}\n"); puts(");\n}\n");
} }
putns(sdtypep, "\nbool operator==(const " + EmitCBase::prefixNameProtect(sdtypep) putns(sdtypep, "\nbool operator==(const " + EmitCUtil::prefixNameProtect(sdtypep)
+ "& rhs) const {\n"); + "& rhs) const {\n");
puts("return "); puts("return ");
for (const AstMemberDType* itemp = sdtypep->membersp(); itemp; for (const AstMemberDType* itemp = sdtypep->membersp(); itemp;
@ -357,10 +358,10 @@ class EmitCHeader final : public EmitCConstInit {
} }
puts(";\n"); puts(";\n");
puts("}\n"); puts("}\n");
putns(sdtypep, "bool operator!=(const " + EmitCBase::prefixNameProtect(sdtypep) putns(sdtypep, "bool operator!=(const " + EmitCUtil::prefixNameProtect(sdtypep)
+ "& rhs) const {\n"); + "& rhs) const {\n");
puts("return !(*this == rhs);\n}\n"); puts("return !(*this == rhs);\n}\n");
putns(sdtypep, "\nbool operator<(const " + EmitCBase::prefixNameProtect(sdtypep) putns(sdtypep, "\nbool operator<(const " + EmitCUtil::prefixNameProtect(sdtypep)
+ "& rhs) const {\n"); + "& rhs) const {\n");
puts("return "); puts("return ");
puts("std::tie("); puts("std::tie(");
@ -379,7 +380,7 @@ class EmitCHeader final : public EmitCConstInit {
puts("}\n"); puts("}\n");
puts("};\n"); puts("};\n");
puts("template <>\n"); puts("template <>\n");
putns(sdtypep, "struct VlIsCustomStruct<" + EmitCBase::prefixNameProtect(sdtypep) putns(sdtypep, "struct VlIsCustomStruct<" + EmitCUtil::prefixNameProtect(sdtypep)
+ "> : public std::true_type {};\n"); + "> : public std::true_type {};\n");
} }
@ -457,7 +458,7 @@ class EmitCHeader final : public EmitCConstInit {
} }
void emitPackedUOrSBody(AstNodeUOrStructDType* sdtypep) { void emitPackedUOrSBody(AstNodeUOrStructDType* sdtypep) {
putns(sdtypep, sdtypep->verilogKwd()); // "struct"/"union" putns(sdtypep, sdtypep->verilogKwd()); // "struct"/"union"
puts(" " + EmitCBase::prefixNameProtect(sdtypep) + " {\n"); puts(" " + EmitCUtil::prefixNameProtect(sdtypep) + " {\n");
AstMemberDType* itemp; AstMemberDType* itemp;
AstMemberDType* lastItemp; AstMemberDType* lastItemp;
@ -553,13 +554,14 @@ class EmitCHeader final : public EmitCConstInit {
if (const AstClass* const classp = VN_CAST(modp, Class)) { if (const AstClass* const classp = VN_CAST(modp, Class)) {
for (const AstClassExtends* extp = classp->extendsp(); extp; for (const AstClassExtends* extp = classp->extendsp(); extp;
extp = VN_AS(extp->nextp(), ClassExtends)) { extp = VN_AS(extp->nextp(), ClassExtends)) {
putns(extp, "#include \"" + prefixNameProtect(extp->classp()->classOrPackagep()) putns(extp, "#include \""
+ EmitCUtil::prefixNameProtect(extp->classp()->classOrPackagep())
+ ".h\"\n"); + ".h\"\n");
} }
} }
// Forward declarations required by this AstNodeModule // Forward declarations required by this AstNodeModule
puts("\nclass " + symClassName() + ";\n"); puts("\nclass " + EmitCUtil::symClassName() + ";\n");
// From `systemc_header // From `systemc_header
emitTextSection(modp, VNType::atScHdr); emitTextSection(modp, VNType::atScHdr);
@ -570,7 +572,7 @@ class EmitCHeader final : public EmitCConstInit {
puts("\n"); puts("\n");
putns(modp, "class "); putns(modp, "class ");
if (!VN_IS(modp, Class)) puts("alignas(VL_CACHE_LINE_BYTES) "); if (!VN_IS(modp, Class)) puts("alignas(VL_CACHE_LINE_BYTES) ");
puts(prefixNameProtect(modp)); puts(EmitCUtil::prefixNameProtect(modp));
if (const AstClass* const classp = VN_CAST(modp, Class)) { if (const AstClass* const classp = VN_CAST(modp, Class)) {
puts(" : "); puts(" : ");
if (classp->extendsp()) { if (classp->extendsp()) {
@ -581,7 +583,7 @@ class EmitCHeader final : public EmitCConstInit {
// Use virtual only for interfaces for class inheritance // Use virtual only for interfaces for class inheritance
// (extends) // (extends)
puts(extp->classp()->useVirtualPublic() ? "virtual public " : "public "); puts(extp->classp()->useVirtualPublic() ? "virtual public " : "public ");
putns(extp, prefixNameProtect(extp->classp())); putns(extp, EmitCUtil::prefixNameProtect(extp->classp()));
needComma = true; needComma = true;
} }
} else { } else {
@ -618,10 +620,11 @@ class EmitCHeader final : public EmitCConstInit {
} }
explicit EmitCHeader(const AstNodeModule* modp) { explicit EmitCHeader(const AstNodeModule* modp) {
UINFO(5, " Emitting header for " << prefixNameProtect(modp)); UINFO(5, " Emitting header for " << EmitCUtil::prefixNameProtect(modp));
// Open output file // Open output file
const string filename = v3Global.opt.makeDir() + "/" + prefixNameProtect(modp) + ".h"; const string filename
= v3Global.opt.makeDir() + "/" + EmitCUtil::prefixNameProtect(modp) + ".h";
AstCFile* const cfilep = newCFile(filename, /* slow: */ false, /* source: */ false); AstCFile* const cfilep = newCFile(filename, /* slow: */ false, /* source: */ false);
V3OutCFile* const ofilep V3OutCFile* const ofilep
= v3Global.opt.systemC() ? new V3OutScFile{filename} : new V3OutCFile{filename}; = v3Global.opt.systemC() ? new V3OutScFile{filename} : new V3OutCFile{filename};
@ -630,7 +633,7 @@ class EmitCHeader final : public EmitCConstInit {
ofp()->putsHeader(); ofp()->putsHeader();
puts("// DESCRIPTION: Verilator output: Design internal header\n"); puts("// DESCRIPTION: Verilator output: Design internal header\n");
puts("// See " + topClassName() + ".h for the primary calling header\n"); puts("// See " + EmitCUtil::topClassName() + ".h for the primary calling header\n");
ofp()->putsGuard(); ofp()->putsGuard();

View File

@ -35,23 +35,23 @@ class EmitCGatherDependencies final : VNVisitorConst {
std::set<string> m_dependencies; // Header names to be included in output C++ file std::set<string> m_dependencies; // Header names to be included in output C++ file
// METHODS // METHODS
void addSymsDependency() { m_dependencies.insert(EmitCBase::symClassName()); } void addSymsDependency() { m_dependencies.insert(EmitCUtil::symClassName()); }
void addModDependency(const AstNodeModule* modp) { void addModDependency(const AstNodeModule* modp) {
if (const AstClass* const classp = VN_CAST(modp, Class)) { if (const AstClass* const classp = VN_CAST(modp, Class)) {
m_dependencies.insert(EmitCBase::prefixNameProtect(classp->classOrPackagep())); m_dependencies.insert(EmitCUtil::prefixNameProtect(classp->classOrPackagep()));
} else { } else {
m_dependencies.insert(EmitCBase::prefixNameProtect(modp)); m_dependencies.insert(EmitCUtil::prefixNameProtect(modp));
} }
} }
void addDTypeDependency(const AstNodeDType* nodep) { void addDTypeDependency(const AstNodeDType* nodep) {
if (const AstClassRefDType* const dtypep = VN_CAST(nodep, ClassRefDType)) { if (const AstClassRefDType* const dtypep = VN_CAST(nodep, ClassRefDType)) {
m_dependencies.insert( m_dependencies.insert(
EmitCBase::prefixNameProtect(dtypep->classp()->classOrPackagep())); EmitCUtil::prefixNameProtect(dtypep->classp()->classOrPackagep()));
} else if (const AstNodeUOrStructDType* const dtypep } else if (const AstNodeUOrStructDType* const dtypep
= VN_CAST(nodep, NodeUOrStructDType)) { = VN_CAST(nodep, NodeUOrStructDType)) {
if (!dtypep->packed()) { if (!dtypep->packed()) {
UASSERT_OBJ(dtypep->classOrPackagep(), nodep, "Unlinked struct package"); UASSERT_OBJ(dtypep->classOrPackagep(), nodep, "Unlinked struct package");
m_dependencies.insert(EmitCBase::prefixNameProtect(dtypep->classOrPackagep())); m_dependencies.insert(EmitCUtil::prefixNameProtect(dtypep->classOrPackagep()));
} }
} }
} }
@ -177,7 +177,8 @@ class EmitCImp final : EmitCFunc {
V3OutCFile* const ofilep = new V3OutCFile{filename}; V3OutCFile* const ofilep = new V3OutCFile{filename};
setOutputFile(ofilep, filep); setOutputFile(ofilep, filep);
} else { } else {
string filename = v3Global.opt.makeDir() + "/" + prefixNameProtect(m_fileModp); string filename
= v3Global.opt.makeDir() + "/" + EmitCUtil::prefixNameProtect(m_fileModp);
if (!subFileName.empty()) { if (!subFileName.empty()) {
filename += "__" + subFileName; filename += "__" + subFileName;
filename = m_uniqueNames.get(filename); filename = m_uniqueNames.get(filename);
@ -193,10 +194,10 @@ class EmitCImp final : EmitCFunc {
putsHeader(); putsHeader();
puts("// DESCRIPTION: Verilator output: Design implementation internals\n"); puts("// DESCRIPTION: Verilator output: Design implementation internals\n");
puts("// See " + topClassName() + ".h for the primary calling header\n"); puts("// See " + EmitCUtil::topClassName() + ".h for the primary calling header\n");
puts("\n"); puts("\n");
puts("#include \"" + pchClassName() + ".h\"\n"); puts("#include \"" + EmitCUtil::pchClassName() + ".h\"\n");
for (const string& name : headers) puts("#include \"" + name + ".h\"\n"); for (const string& name : headers) puts("#include \"" + name + ".h\"\n");
emitTextSection(m_modp, VNType::atScImpHdr); emitTextSection(m_modp, VNType::atScImpHdr);
@ -204,7 +205,7 @@ class EmitCImp final : EmitCFunc {
void emitStaticVarDefns(const AstNodeModule* modp) { void emitStaticVarDefns(const AstNodeModule* modp) {
// Emit static variable definitions // Emit static variable definitions
const string modName = prefixNameProtect(modp); const string modName = EmitCUtil::prefixNameProtect(modp);
for (const AstNode* nodep = modp->stmtsp(); nodep; nodep = nodep->nextp()) { for (const AstNode* nodep = modp->stmtsp(); nodep; nodep = nodep->nextp()) {
if (const AstVar* const varp = VN_CAST(nodep, Var)) { if (const AstVar* const varp = VN_CAST(nodep, Var)) {
if (varp->isStatic()) { if (varp->isStatic()) {
@ -215,7 +216,7 @@ class EmitCImp final : EmitCFunc {
} }
} }
void emitParamDefns(const AstNodeModule* modp) { void emitParamDefns(const AstNodeModule* modp) {
const string modName = prefixNameProtect(modp); const string modName = EmitCUtil::prefixNameProtect(modp);
bool first = true; bool first = true;
for (const AstNode* nodep = modp->stmtsp(); nodep; nodep = nodep->nextp()) { for (const AstNode* nodep = modp->stmtsp(); nodep; nodep = nodep->nextp()) {
if (const AstVar* const varp = VN_CAST(nodep, Var)) { if (const AstVar* const varp = VN_CAST(nodep, Var)) {
@ -242,15 +243,15 @@ class EmitCImp final : EmitCFunc {
if (!first) puts("\n"); if (!first) puts("\n");
} }
void emitCtorImp(const AstNodeModule* modp) { void emitCtorImp(const AstNodeModule* modp) {
const string modName = prefixNameProtect(modp); const string modName = EmitCUtil::prefixNameProtect(modp);
puts("\n"); puts("\n");
m_lazyDecls.emit("void " + modName + "__", protect("_ctor_var_reset"), m_lazyDecls.emit("void " + modName + "__", protect("_ctor_var_reset"),
"(" + modName + "* vlSelf);"); "(" + modName + "* vlSelf);");
puts("\n"); puts("\n");
putns(modp, putns(modp, modName + "::" + modName + "(" + EmitCUtil::symClassName()
modName + "::" + modName + "(" + symClassName() + "* symsp, const char* v__name)\n"); + "* symsp, const char* v__name)\n");
puts(" : VerilatedModule{v__name}\n"); puts(" : VerilatedModule{v__name}\n");
ofp()->indentInc(); ofp()->indentInc();
@ -290,7 +291,7 @@ class EmitCImp final : EmitCFunc {
puts("}\n"); puts("}\n");
} }
void emitConfigureImp(const AstNodeModule* modp) { void emitConfigureImp(const AstNodeModule* modp) {
const string modName = prefixNameProtect(modp); const string modName = EmitCUtil::prefixNameProtect(modp);
if (v3Global.opt.coverage()) { if (v3Global.opt.coverage()) {
puts("\n"); puts("\n");
@ -312,7 +313,7 @@ class EmitCImp final : EmitCFunc {
// arguments. // arguments.
if (v3Global.opt.coverage()) { if (v3Global.opt.coverage()) {
puts("\n// Coverage\n"); puts("\n// Coverage\n");
puts("void " + prefixNameProtect(m_modp) + "::__vlCoverInsert("); puts("void " + EmitCUtil::prefixNameProtect(m_modp) + "::__vlCoverInsert(");
puts(v3Global.opt.threads() > 1 ? "std::atomic<uint32_t>" : "uint32_t"); puts(v3Global.opt.threads() > 1 ? "std::atomic<uint32_t>" : "uint32_t");
puts("* countp, bool enable, const char* filenamep, int lineno, int column,\n"); puts("* countp, bool enable, const char* filenamep, int lineno, int column,\n");
puts("const char* hierp, const char* pagep, const char* commentp, const char* " puts("const char* hierp, const char* pagep, const char* commentp, const char* "
@ -344,7 +345,7 @@ class EmitCImp final : EmitCFunc {
} }
if (v3Global.opt.coverageToggle()) { if (v3Global.opt.coverageToggle()) {
puts("\n// Toggle Coverage\n"); puts("\n// Toggle Coverage\n");
puts("void " + prefixNameProtect(m_modp) + "::__vlCoverToggleInsert("); puts("void " + EmitCUtil::prefixNameProtect(m_modp) + "::__vlCoverToggleInsert(");
puts("int begin, int end, bool ranged, "); puts("int begin, int end, bool ranged, ");
puts(v3Global.opt.threads() > 1 ? "std::atomic<uint32_t>" : "uint32_t"); puts(v3Global.opt.threads() > 1 ? "std::atomic<uint32_t>" : "uint32_t");
puts("* countp, bool enable, const char* filenamep, int lineno, int column,\n"); puts("* countp, bool enable, const char* filenamep, int lineno, int column,\n");
@ -390,7 +391,8 @@ class EmitCImp final : EmitCFunc {
} }
void emitDestructorImp(const AstNodeModule* modp) { void emitDestructorImp(const AstNodeModule* modp) {
puts("\n"); puts("\n");
putns(modp, prefixNameProtect(modp) + "::~" + prefixNameProtect(modp) + "() {\n"); putns(modp, EmitCUtil::prefixNameProtect(modp) + "::~" + EmitCUtil::prefixNameProtect(modp)
+ "() {\n");
emitTextSection(modp, VNType::atScDtor); emitTextSection(modp, VNType::atScDtor);
puts("}\n"); puts("}\n");
splitSizeInc(10); splitSizeInc(10);
@ -403,8 +405,8 @@ class EmitCImp final : EmitCFunc {
const string funcname = de ? "__Vdeserialize" : "__Vserialize"; const string funcname = de ? "__Vdeserialize" : "__Vserialize";
const string op = de ? ">>" : "<<"; const string op = de ? ">>" : "<<";
// NOLINTNEXTLINE(performance-inefficient-string-concatenation) // NOLINTNEXTLINE(performance-inefficient-string-concatenation)
putns(modp, "void " + prefixNameProtect(modp) + "::" + protect(funcname) + "(" putns(modp, "void " + EmitCUtil::prefixNameProtect(modp) + "::" + protect(funcname)
+ classname + "& os) {\n"); + "(" + classname + "& os) {\n");
// Place a computed checksum to ensure proper structure save/restore formatting // Place a computed checksum to ensure proper structure save/restore formatting
// OK if this hash includes some things we won't dump, since // OK if this hash includes some things we won't dump, since
// just looking for loading the wrong model // just looking for loading the wrong model
@ -514,8 +516,8 @@ class EmitCImp final : EmitCFunc {
if (hasCommonImp(modp) || hasCommonImp(classp)) { if (hasCommonImp(modp) || hasCommonImp(classp)) {
std::set<string> headers; std::set<string> headers;
headers.insert(prefixNameProtect(m_fileModp)); headers.insert(EmitCUtil::prefixNameProtect(m_fileModp));
headers.insert(symClassName()); headers.insert(EmitCUtil::symClassName());
openNextOutputFile(headers, ""); openNextOutputFile(headers, "");
@ -595,7 +597,7 @@ class EmitCImp final : EmitCFunc {
: m_fileModp{modp} : m_fileModp{modp}
, m_slow{slow} , m_slow{slow}
, m_cfilesr{cfilesr} { , m_cfilesr{cfilesr} {
UINFO(5, " Emitting implementation of " << prefixNameProtect(modp)); UINFO(5, " Emitting implementation of " << EmitCUtil::prefixNameProtect(modp));
m_modp = modp; m_modp = modp;
@ -644,7 +646,7 @@ class EmitCTrace final : EmitCFunc {
m_lazyDecls.reset(); // Need to emit new lazy declarations m_lazyDecls.reset(); // Need to emit new lazy declarations
string filename string filename
= (v3Global.opt.makeDir() + "/" + topClassName() + "_" + protect("_Trace")); = (v3Global.opt.makeDir() + "/" + EmitCUtil::topClassName() + "_" + protect("_Trace"));
filename = m_uniqueNames.get(filename); filename = m_uniqueNames.get(filename);
if (m_slow) filename += "__Slow"; if (m_slow) filename += "__Slow";
filename += ".cpp"; filename += ".cpp";
@ -663,7 +665,7 @@ class EmitCTrace final : EmitCFunc {
// Includes // Includes
puts("#include \"" + v3Global.opt.traceSourceLang() + ".h\"\n"); puts("#include \"" + v3Global.opt.traceSourceLang() + ".h\"\n");
puts("#include \"" + symClassName() + ".h\"\n"); puts("#include \"" + EmitCUtil::symClassName() + ".h\"\n");
puts("\n"); puts("\n");
} }
@ -672,8 +674,8 @@ class EmitCTrace final : EmitCFunc {
void openNextTypesFile() { void openNextTypesFile() {
UASSERT(!m_typesFp, "Declarations output file already open"); UASSERT(!m_typesFp, "Declarations output file already open");
string filename string filename = (v3Global.opt.makeDir() + "/" + EmitCUtil::topClassName() + "_"
= (v3Global.opt.makeDir() + "/" + topClassName() + "_" + protect("_TraceDecls")); + protect("_TraceDecls"));
filename = m_uniqueNames.get(filename); filename = m_uniqueNames.get(filename);
filename += "__Slow.cpp"; filename += "__Slow.cpp";
@ -694,7 +696,7 @@ class EmitCTrace final : EmitCFunc {
typesFp()->puts("#include \"" + v3Global.opt.traceSourceLang() + ".h\"\n"); typesFp()->puts("#include \"" + v3Global.opt.traceSourceLang() + ".h\"\n");
typesFp()->puts("\n"); typesFp()->puts("\n");
typesFp()->puts("\nvoid " + prefixNameProtect(m_modp) + "__" typesFp()->puts("\nvoid " + EmitCUtil::prefixNameProtect(m_modp) + "__"
+ protect("traceDeclTypesSub" + cvtToStr(m_traceTypeSubs++)) + "(" + protect("traceDeclTypesSub" + cvtToStr(m_traceTypeSubs++)) + "("
+ v3Global.opt.traceClassBase() + "* tracep) {\n"); + v3Global.opt.traceClassBase() + "* tracep) {\n");
} }
@ -709,15 +711,16 @@ class EmitCTrace final : EmitCFunc {
// Forward declarations for subs in other files // Forward declarations for subs in other files
for (int i = 0; i < m_traceTypeSubs - 1; ++i) { for (int i = 0; i < m_traceTypeSubs - 1; ++i) {
typesFp()->puts("void " + prefixNameProtect(m_modp) + "__" typesFp()->puts("void " + EmitCUtil::prefixNameProtect(m_modp) + "__"
+ protect("traceDeclTypesSub" + cvtToStr(i)) + "(" + protect("traceDeclTypesSub" + cvtToStr(i)) + "("
+ v3Global.opt.traceClassBase() + "* tracep);\n"); + v3Global.opt.traceClassBase() + "* tracep);\n");
} }
typesFp()->puts("\nvoid " + prefixNameProtect(m_modp) + "__" + protect("trace_decl_types") typesFp()->puts("\nvoid " + EmitCUtil::prefixNameProtect(m_modp) + "__"
+ "(" + v3Global.opt.traceClassBase() + "* tracep) {\n"); + protect("trace_decl_types") + "(" + v3Global.opt.traceClassBase()
+ "* tracep) {\n");
for (int i = 0; i < m_traceTypeSubs; ++i) { for (int i = 0; i < m_traceTypeSubs; ++i) {
typesFp()->puts(prefixNameProtect(m_modp) + "__" typesFp()->puts(EmitCUtil::prefixNameProtect(m_modp) + "__"
+ protect("traceDeclTypesSub" + cvtToStr(i)) + "(tracep);\n"); + protect("traceDeclTypesSub" + cvtToStr(i)) + "(tracep);\n");
} }
} }

View File

@ -41,7 +41,8 @@ public:
private: private:
// MAIN METHOD // MAIN METHOD
void emitInt() { void emitInt() {
const string filename = v3Global.opt.makeDir() + "/" + topClassName() + "__main.cpp"; const string filename
= v3Global.opt.makeDir() + "/" + EmitCUtil::topClassName() + "__main.cpp";
AstCFile* const cfilep = newCFile(filename, false /*slow*/, true /*source*/); AstCFile* const cfilep = newCFile(filename, false /*slow*/, true /*source*/);
V3OutCFile cf{filename}; V3OutCFile cf{filename};
setOutputFile(&cf, cfilep); setOutputFile(&cf, cfilep);
@ -59,7 +60,7 @@ private:
puts("\n"); puts("\n");
puts("#include \"verilated.h\"\n"); puts("#include \"verilated.h\"\n");
puts("#include \"" + topClassName() + ".h\"\n"); puts("#include \"" + EmitCUtil::topClassName() + ".h\"\n");
puts("\n//======================\n\n"); puts("\n//======================\n\n");
@ -72,8 +73,8 @@ private:
puts("\n"); puts("\n");
puts("// Construct the Verilated model, from Vtop.h generated from Verilating\n"); puts("// Construct the Verilated model, from Vtop.h generated from Verilating\n");
puts("const std::unique_ptr<" + topClassName() + "> topp{new " + topClassName() puts("const std::unique_ptr<" + EmitCUtil::topClassName() + "> topp{new "
+ "{contextp.get(), \"" + topName + "\"}};\n"); + EmitCUtil::topClassName() + "{contextp.get(), \"" + topName + "\"}};\n");
puts("\n"); puts("\n");
puts("// Simulate until $finish\n"); puts("// Simulate until $finish\n");

View File

@ -55,7 +55,7 @@ class EmitCModel final : public EmitCFunc {
void emitHeader(AstNodeModule* modp) { void emitHeader(AstNodeModule* modp) {
UASSERT(!ofp(), "Output file should not be open"); UASSERT(!ofp(), "Output file should not be open");
const string filename = v3Global.opt.makeDir() + "/" + topClassName() + ".h"; const string filename = v3Global.opt.makeDir() + "/" + EmitCUtil::topClassName() + ".h";
setOutputFile(v3Global.opt.systemC() ? new V3OutScFile{filename} setOutputFile(v3Global.opt.systemC() ? new V3OutScFile{filename}
: new V3OutCFile{filename}, : new V3OutCFile{filename},
newCFile(filename, /* slow: */ false, /* source: */ false)); newCFile(filename, /* slow: */ false, /* source: */ false));
@ -80,15 +80,16 @@ class EmitCModel final : public EmitCFunc {
// Declare foreign instances up front to make C++ happy // Declare foreign instances up front to make C++ happy
puts("\n"); puts("\n");
puts("class " + symClassName() + ";\n"); puts("class " + EmitCUtil::symClassName() + ";\n");
puts("class " + prefixNameProtect(modp) + ";\n"); // For rootp pointer only puts("class " + EmitCUtil::prefixNameProtect(modp) + ";\n"); // For rootp pointer only
if (v3Global.opt.trace()) puts("class " + v3Global.opt.traceClassLang() + ";\n"); if (v3Global.opt.trace()) puts("class " + v3Global.opt.traceClassLang() + ";\n");
emitModCUse(modp, VUseType::INT_FWD_CLASS); // Note: This is needed for cell forwarding emitModCUse(modp, VUseType::INT_FWD_CLASS); // Note: This is needed for cell forwarding
puts("\n"); puts("\n");
puts("// This class is the main interface to the Verilated model\n"); puts("// This class is the main interface to the Verilated model\n");
putns(modp, "class alignas(VL_CACHE_LINE_BYTES) " + topClassName() + " VL_NOT_FINAL : "); putns(modp, "class alignas(VL_CACHE_LINE_BYTES) " + EmitCUtil::topClassName()
+ " VL_NOT_FINAL : ");
if (optSystemC()) { if (optSystemC()) {
// SC_MODULE, but with multiple-inheritance of VerilatedModel // SC_MODULE, but with multiple-inheritance of VerilatedModel
puts("public ::sc_core::sc_module, "); puts("public ::sc_core::sc_module, ");
@ -98,7 +99,7 @@ class EmitCModel final : public EmitCFunc {
ofp()->putsPrivate(true); // private: ofp()->putsPrivate(true); // private:
puts("// Symbol table holding complete model state (owned by this class)\n"); puts("// Symbol table holding complete model state (owned by this class)\n");
puts(symClassName() + "* const vlSymsp;\n"); puts(EmitCUtil::symClassName() + "* const vlSymsp;\n");
puts("\n"); puts("\n");
ofp()->putsPrivate(false); // public: ofp()->putsPrivate(false); // public:
@ -138,36 +139,36 @@ class EmitCModel final : public EmitCFunc {
"// Otherwise the application code can consider these internals.\n"); "// Otherwise the application code can consider these internals.\n");
for (AstNode* nodep = modp->stmtsp(); nodep; nodep = nodep->nextp()) { for (AstNode* nodep = modp->stmtsp(); nodep; nodep = nodep->nextp()) {
if (const AstCell* const cellp = VN_CAST(nodep, Cell)) { if (const AstCell* const cellp = VN_CAST(nodep, Cell)) {
putns(cellp, prefixNameProtect(cellp->modp()) + "* const " + cellp->nameProtect() putns(cellp, EmitCUtil::prefixNameProtect(cellp->modp()) + "* const "
+ ";\n"); + cellp->nameProtect() + ";\n");
} }
} }
// root instance pointer (for access to internals, including public_flat items). // root instance pointer (for access to internals, including public_flat items).
puts("\n// Root instance pointer to allow access to model internals,\n" puts("\n// Root instance pointer to allow access to model internals,\n"
"// including inlined /* verilator public_flat_* */ items.\n"); "// including inlined /* verilator public_flat_* */ items.\n");
puts(prefixNameProtect(modp) + "* const rootp;\n"); puts(EmitCUtil::prefixNameProtect(modp) + "* const rootp;\n");
puts("\n"); puts("\n");
ofp()->putsPrivate(false); // public: ofp()->putsPrivate(false); // public:
puts("// CONSTRUCTORS\n"); puts("// CONSTRUCTORS\n");
if (optSystemC()) { if (optSystemC()) {
puts("SC_CTOR(" + topClassName() + ");\n"); puts("SC_CTOR(" + EmitCUtil::topClassName() + ");\n");
puts("virtual ~" + topClassName() + "();\n"); puts("virtual ~" + EmitCUtil::topClassName() + "();\n");
} else { } else {
puts("/// Construct the model; called by application code\n"); puts("/// Construct the model; called by application code\n");
puts("/// If contextp is null, then the model will use the default global " puts("/// If contextp is null, then the model will use the default global "
"context\n"); "context\n");
puts("/// If name is \"\", then makes a wrapper with a\n"); puts("/// If name is \"\", then makes a wrapper with a\n");
puts("/// single model invisible with respect to DPI scope names.\n"); puts("/// single model invisible with respect to DPI scope names.\n");
puts("explicit " + topClassName() + "(VerilatedContext* contextp," puts("explicit " + EmitCUtil::topClassName() + "(VerilatedContext* contextp,"
+ " const char* name = \"TOP\");\n"); + " const char* name = \"TOP\");\n");
puts("explicit " + topClassName() + "(const char* name = \"TOP\");\n"); puts("explicit " + EmitCUtil::topClassName() + "(const char* name = \"TOP\");\n");
puts("/// Destroy the model; called (often implicitly) by application code\n"); puts("/// Destroy the model; called (often implicitly) by application code\n");
puts("virtual ~" + topClassName() + "();\n"); puts("virtual ~" + EmitCUtil::topClassName() + "();\n");
} }
ofp()->putsPrivate(true); ofp()->putsPrivate(true);
puts("VL_UNCOPYABLE(" + topClassName() + "); ///< Copying not allowed\n"); puts("VL_UNCOPYABLE(" + EmitCUtil::topClassName() + "); ///< Copying not allowed\n");
puts("\n"); puts("\n");
ofp()->putsPrivate(false); // public: ofp()->putsPrivate(false); // public:
@ -243,9 +244,9 @@ class EmitCModel final : public EmitCFunc {
puts("\n"); puts("\n");
puts("// Serialization functions\n"); puts("// Serialization functions\n");
puts("friend VerilatedSerialize& operator<<(VerilatedSerialize& os, " // puts("friend VerilatedSerialize& operator<<(VerilatedSerialize& os, " //
+ topClassName() + "& rhs);\n"); + EmitCUtil::topClassName() + "& rhs);\n");
puts("friend VerilatedDeserialize& operator>>(VerilatedDeserialize& os, " puts("friend VerilatedDeserialize& operator>>(VerilatedDeserialize& os, "
+ topClassName() + "& rhs);\n"); + EmitCUtil::topClassName() + "& rhs);\n");
} }
puts("\n// Abstract methods from VerilatedModel\n"); puts("\n// Abstract methods from VerilatedModel\n");
@ -277,15 +278,17 @@ class EmitCModel final : public EmitCFunc {
putSectionDelimiter("Constructors"); putSectionDelimiter("Constructors");
puts("\n"); puts("\n");
putns(modp, topClassName() + "::" + topClassName()); putns(modp, EmitCUtil::topClassName() + "::" + EmitCUtil::topClassName());
if (optSystemC()) { if (optSystemC()) {
puts("(sc_core::sc_module_name /* unused */)\n"); puts("(sc_core::sc_module_name /* unused */)\n");
puts(" : VerilatedModel{*Verilated::threadContextp()}\n"); puts(" : VerilatedModel{*Verilated::threadContextp()}\n");
puts(" , vlSymsp{new " + symClassName() + "(contextp(), name(), this)}\n"); puts(" , vlSymsp{new " + EmitCUtil::symClassName()
+ "(contextp(), name(), this)}\n");
} else { } else {
puts(+"(VerilatedContext* _vcontextp__, const char* _vcname__)\n"); puts(+"(VerilatedContext* _vcontextp__, const char* _vcname__)\n");
puts(" : VerilatedModel{*_vcontextp__}\n"); puts(" : VerilatedModel{*_vcontextp__}\n");
puts(" , vlSymsp{new " + symClassName() + "(contextp(), _vcname__, this)}\n"); puts(" , vlSymsp{new " + EmitCUtil::symClassName()
+ "(contextp(), _vcname__, this)}\n");
} }
// Set up IO references // Set up IO references
@ -356,8 +359,10 @@ class EmitCModel final : public EmitCFunc {
if (!optSystemC()) { if (!optSystemC()) {
puts("\n"); puts("\n");
puts(topClassName() + "::" + topClassName() + "(const char* _vcname__)\n"); puts(EmitCUtil::topClassName() + "::" + EmitCUtil::topClassName()
puts(" : " + topClassName() + "(Verilated::threadContextp(), _vcname__)\n{\n}\n"); + "(const char* _vcname__)\n");
puts(" : " + EmitCUtil::topClassName()
+ "(Verilated::threadContextp(), _vcname__)\n{\n}\n");
} }
} }
@ -365,7 +370,7 @@ class EmitCModel final : public EmitCFunc {
putSectionDelimiter("Destructor"); putSectionDelimiter("Destructor");
puts("\n"); puts("\n");
puts(topClassName() + "::~" + topClassName() + "() {\n"); puts(EmitCUtil::topClassName() + "::~" + EmitCUtil::topClassName() + "() {\n");
puts("delete vlSymsp;\n"); puts("delete vlSymsp;\n");
puts("}\n"); puts("}\n");
} }
@ -373,7 +378,7 @@ class EmitCModel final : public EmitCFunc {
void emitStandardMethods1(AstNodeModule* modp) { void emitStandardMethods1(AstNodeModule* modp) {
UASSERT_OBJ(modp->isTop(), modp, "Attempting to emitWrapEval for non-top class"); UASSERT_OBJ(modp->isTop(), modp, "Attempting to emitWrapEval for non-top class");
const string topModNameProtected = prefixNameProtect(modp); const string topModNameProtected = EmitCUtil::prefixNameProtect(modp);
const string selfDecl = "(" + topModNameProtected + "* vlSelf)"; const string selfDecl = "(" + topModNameProtected + "* vlSelf)";
putSectionDelimiter("Evaluation function"); putSectionDelimiter("Evaluation function");
@ -391,7 +396,7 @@ class EmitCModel final : public EmitCFunc {
if (optSystemC() && v3Global.usesTiming()) { if (optSystemC() && v3Global.usesTiming()) {
// ::eval // ::eval
puts("\nvoid " + topClassName() + "::eval() {\n"); puts("\nvoid " + EmitCUtil::topClassName() + "::eval() {\n");
puts("eval_step();\n"); puts("eval_step();\n");
puts("if (eventsPending()) {\n"); puts("if (eventsPending()) {\n");
puts("sc_core::sc_time dt = sc_core::sc_time::from_value(nextTimeSlot() - " puts("sc_core::sc_time dt = sc_core::sc_time::from_value(nextTimeSlot() - "
@ -403,14 +408,14 @@ class EmitCModel final : public EmitCFunc {
puts("}\n"); puts("}\n");
// ::eval_sens // ::eval_sens
puts("\nvoid " + topClassName() + "::eval_sens() {\n"); puts("\nvoid " + EmitCUtil::topClassName() + "::eval_sens() {\n");
puts("trigger_eval.notify();\n"); puts("trigger_eval.notify();\n");
puts("}\n"); puts("}\n");
} }
// ::eval_step // ::eval_step
puts("\nvoid " + topClassName() + "::eval_step() {\n"); puts("\nvoid " + EmitCUtil::topClassName() + "::eval_step() {\n");
puts("VL_DEBUG_IF(VL_DBG_MSGF(\"+++++TOP Evaluate " + topClassName() puts("VL_DEBUG_IF(VL_DBG_MSGF(\"+++++TOP Evaluate " + EmitCUtil::topClassName()
+ "::eval_step\\n\"); );\n"); + "::eval_step\\n\"); );\n");
puts("#ifdef VL_DEBUG\n"); puts("#ifdef VL_DEBUG\n");
@ -445,14 +450,14 @@ class EmitCModel final : public EmitCFunc {
} }
void emitStandardMethods2(AstNodeModule* modp) { void emitStandardMethods2(AstNodeModule* modp) {
const string topModNameProtected = prefixNameProtect(modp); const string topModNameProtected = EmitCUtil::prefixNameProtect(modp);
const string selfDecl = "(" + topModNameProtected + "* vlSelf)"; const string selfDecl = "(" + topModNameProtected + "* vlSelf)";
// ::eval_end_step // ::eval_end_step
if (v3Global.needTraceDumper() && !optSystemC()) { if (v3Global.needTraceDumper() && !optSystemC()) {
puts("\n"); puts("\n");
putns(modp, "void " + topClassName() + "::eval_end_step() {\n"); putns(modp, "void " + EmitCUtil::topClassName() + "::eval_end_step() {\n");
puts("VL_DEBUG_IF(VL_DBG_MSGF(\"+eval_end_step " + topClassName() puts("VL_DEBUG_IF(VL_DBG_MSGF(\"+eval_end_step " + EmitCUtil::topClassName()
+ "::eval_end_step\\n\"); );\n"); + "::eval_end_step\\n\"); );\n");
puts("#ifdef VM_TRACE\n"); puts("#ifdef VM_TRACE\n");
putsDecoration(nullptr, "// Tracing\n"); putsDecoration(nullptr, "// Tracing\n");
@ -464,16 +469,19 @@ class EmitCModel final : public EmitCFunc {
putSectionDelimiter("Events and timing"); putSectionDelimiter("Events and timing");
if (auto* const delaySchedp = v3Global.rootp()->delaySchedulerp()) { if (auto* const delaySchedp = v3Global.rootp()->delaySchedulerp()) {
putns(modp, "bool " + topClassName() + "::eventsPending() { return !vlSymsp->TOP."); putns(modp, "bool " + EmitCUtil::topClassName()
+ "::eventsPending() { return !vlSymsp->TOP.");
puts(delaySchedp->nameProtect()); puts(delaySchedp->nameProtect());
puts(".empty(); }\n\n"); puts(".empty(); }\n\n");
putns(modp, "uint64_t " + topClassName() + "::nextTimeSlot() { return vlSymsp->TOP."); putns(modp, "uint64_t " + EmitCUtil::topClassName()
+ "::nextTimeSlot() { return vlSymsp->TOP.");
puts(delaySchedp->nameProtect()); puts(delaySchedp->nameProtect());
puts(".nextTimeSlot(); }\n"); puts(".nextTimeSlot(); }\n");
} else { } else {
putns(modp, "bool " + topClassName() + "::eventsPending() { return false; }\n\n"); putns(modp,
puts("uint64_t " + topClassName() + "::nextTimeSlot() {\n"); "bool " + EmitCUtil::topClassName() + "::eventsPending() { return false; }\n\n");
puts("uint64_t " + EmitCUtil::topClassName() + "::nextTimeSlot() {\n");
puts("VL_FATAL_MT(__FILE__, __LINE__, \"\", \"No delays in the design\");\n"); puts("VL_FATAL_MT(__FILE__, __LINE__, \"\", \"No delays in the design\");\n");
puts("return 0;\n}\n"); puts("return 0;\n}\n");
} }
@ -483,7 +491,7 @@ class EmitCModel final : public EmitCFunc {
if (!optSystemC()) { if (!optSystemC()) {
// ::name // ::name
puts("\n"); puts("\n");
putns(modp, "const char* " + topClassName() + "::name() const {\n"); putns(modp, "const char* " + EmitCUtil::topClassName() + "::name() const {\n");
puts(/**/ "return vlSymsp->name();\n"); puts(/**/ "return vlSymsp->name();\n");
puts("}\n"); puts("}\n");
} }
@ -494,23 +502,23 @@ class EmitCModel final : public EmitCFunc {
putns(modp, putns(modp,
"void " + topModNameProtected + "__" + protect("_eval_final") + selfDecl + ";\n"); "void " + topModNameProtected + "__" + protect("_eval_final") + selfDecl + ";\n");
// ::final // ::final
puts("\nVL_ATTR_COLD void " + topClassName() + "::final() {\n"); puts("\nVL_ATTR_COLD void " + EmitCUtil::topClassName() + "::final() {\n");
puts(/**/ topModNameProtected + "__" + protect("_eval_final") + "(&(vlSymsp->TOP));\n"); puts(/**/ topModNameProtected + "__" + protect("_eval_final") + "(&(vlSymsp->TOP));\n");
puts("}\n"); puts("}\n");
putSectionDelimiter("Implementations of abstract methods from VerilatedModel\n"); putSectionDelimiter("Implementations of abstract methods from VerilatedModel\n");
putns(modp, "const char* " + topClassName() putns(modp, "const char* " + EmitCUtil::topClassName()
+ "::hierName() const { return vlSymsp->name(); }\n"); + "::hierName() const { return vlSymsp->name(); }\n");
putns(modp, "const char* " + topClassName() + "::modelName() const { return \"" putns(modp, "const char* " + EmitCUtil::topClassName() + "::modelName() const { return \""
+ topClassName() + "\"; }\n"); + EmitCUtil::topClassName() + "\"; }\n");
const int threads = v3Global.opt.hierChild() const int threads = v3Global.opt.hierChild()
? v3Global.opt.threads() ? v3Global.opt.threads()
: std::max(v3Global.opt.threads(), v3Global.opt.hierThreads()); : std::max(v3Global.opt.threads(), v3Global.opt.hierThreads());
putns(modp, "unsigned " + topClassName() + "::threads() const { return " putns(modp, "unsigned " + EmitCUtil::topClassName() + "::threads() const { return "
+ cvtToStr(threads) + "; }\n"); + cvtToStr(threads) + "; }\n");
putns(modp, "void " + topClassName() putns(modp, "void " + EmitCUtil::topClassName()
+ "::prepareClone() const { contextp()->prepareClone(); }\n"); + "::prepareClone() const { contextp()->prepareClone(); }\n");
putns(modp, "void " + topClassName() + "::atClone() const {\n"); putns(modp, "void " + EmitCUtil::topClassName() + "::atClone() const {\n");
if (v3Global.opt.threads() > 1) { if (v3Global.opt.threads() > 1) {
puts("vlSymsp->__Vm_threadPoolp = static_cast<VlThreadPool*>("); puts("vlSymsp->__Vm_threadPoolp = static_cast<VlThreadPool*>(");
} }
@ -519,7 +527,7 @@ class EmitCModel final : public EmitCFunc {
puts(";\n}\n"); puts(";\n}\n");
if (v3Global.opt.trace()) { if (v3Global.opt.trace()) {
putns(modp, "std::unique_ptr<VerilatedTraceConfig> " + topClassName() putns(modp, "std::unique_ptr<VerilatedTraceConfig> " + EmitCUtil::topClassName()
+ "::traceConfig() const {\n"); + "::traceConfig() const {\n");
puts("return std::unique_ptr<VerilatedTraceConfig>{new VerilatedTraceConfig{"); puts("return std::unique_ptr<VerilatedTraceConfig>{new VerilatedTraceConfig{");
puts(v3Global.opt.useTraceParallel() ? "true" : "false"); puts(v3Global.opt.useTraceParallel() ? "true" : "false");
@ -531,7 +539,7 @@ class EmitCModel final : public EmitCFunc {
} }
void emitTraceMethods(AstNodeModule* modp) { void emitTraceMethods(AstNodeModule* modp) {
const string topModNameProtected = prefixNameProtect(modp); const string topModNameProtected = EmitCUtil::prefixNameProtect(modp);
putSectionDelimiter("Trace configuration"); putSectionDelimiter("Trace configuration");
@ -547,8 +555,8 @@ class EmitCModel final : public EmitCFunc {
putns(modp, "VL_ATTR_COLD static void " + protect("trace_init") + "(void* voidSelf, " putns(modp, "VL_ATTR_COLD static void " + protect("trace_init") + "(void* voidSelf, "
+ v3Global.opt.traceClassBase() + "* tracep, uint32_t code) {\n"); + v3Global.opt.traceClassBase() + "* tracep, uint32_t code) {\n");
putsDecoration(modp, "// Callback from tracep->open()\n"); putsDecoration(modp, "// Callback from tracep->open()\n");
puts(voidSelfAssign(modp)); puts(EmitCUtil::voidSelfAssign(modp));
puts(symClassAssign()); puts(EmitCUtil::symClassAssign());
puts("if (!vlSymsp->_vm_contextp__->calcUnusedSigs()) {\n"); puts("if (!vlSymsp->_vm_contextp__->calcUnusedSigs()) {\n");
puts("VL_FATAL_MT(__FILE__, __LINE__, __FILE__,\n"); puts("VL_FATAL_MT(__FILE__, __LINE__, __FILE__,\n");
puts("\"Turning on wave traces requires Verilated::traceEverOn(true) call before time " puts("\"Turning on wave traces requires Verilated::traceEverOn(true) call before time "
@ -570,11 +578,11 @@ class EmitCModel final : public EmitCFunc {
// ::traceRegisterModel // ::traceRegisterModel
puts("\n"); puts("\n");
putns(modp, "VL_ATTR_COLD void " + topClassName() + "::traceBaseModel("); putns(modp, "VL_ATTR_COLD void " + EmitCUtil::topClassName() + "::traceBaseModel(");
puts("VerilatedTraceBaseC* tfp, int levels, int options) {\n"); puts("VerilatedTraceBaseC* tfp, int levels, int options) {\n");
if (optSystemC()) { if (optSystemC()) {
puts(/**/ "if (!sc_core::sc_get_curr_simcontext()->elaboration_done()) {\n"); puts(/**/ "if (!sc_core::sc_get_curr_simcontext()->elaboration_done()) {\n");
puts(/****/ "vl_fatal(__FILE__, __LINE__, name(), \"" + topClassName() puts(/****/ "vl_fatal(__FILE__, __LINE__, name(), \"" + EmitCUtil::topClassName()
+ +"::trace() is called before sc_core::sc_start(). " + +"::trace() is called before sc_core::sc_start(). "
"Run sc_core::sc_start(sc_core::SC_ZERO_TIME) before trace() to complete " "Run sc_core::sc_start(sc_core::SC_ZERO_TIME) before trace() to complete "
"elaboration.\");\n"); "elaboration.\");\n");
@ -584,7 +592,7 @@ class EmitCModel final : public EmitCFunc {
puts(/**/ v3Global.opt.traceClassBase() + "C* const stfp = dynamic_cast<" puts(/**/ v3Global.opt.traceClassBase() + "C* const stfp = dynamic_cast<"
+ v3Global.opt.traceClassBase() + "C*>(tfp);\n"); + v3Global.opt.traceClassBase() + "C*>(tfp);\n");
puts(/**/ "if (VL_UNLIKELY(!stfp)) {\n"); puts(/**/ "if (VL_UNLIKELY(!stfp)) {\n");
puts(/****/ "vl_fatal(__FILE__, __LINE__, __FILE__,\"'" + topClassName() puts(/****/ "vl_fatal(__FILE__, __LINE__, __FILE__,\"'" + EmitCUtil::topClassName()
+ "::trace()' called on non-" + v3Global.opt.traceClassBase() + "C object;\"\n" + "::trace()' called on non-" + v3Global.opt.traceClassBase() + "C object;\"\n"
+ "\" use --trace-fst with VerilatedFst object," + "\" use --trace-fst with VerilatedFst object,"
+ " and --trace-vcd with VerilatedVcd object\");\n"); + " and --trace-vcd with VerilatedVcd object\");\n");
@ -600,15 +608,15 @@ class EmitCModel final : public EmitCFunc {
void emitSerializationFunctions() { void emitSerializationFunctions() {
putSectionDelimiter("Model serialization"); putSectionDelimiter("Model serialization");
puts("\nVerilatedSerialize& operator<<(VerilatedSerialize& os, " + topClassName() puts("\nVerilatedSerialize& operator<<(VerilatedSerialize& os, "
+ "& rhs) {\n"); + EmitCUtil::topClassName() + "& rhs) {\n");
puts(/**/ "Verilated::quiesce();\n"); puts(/**/ "Verilated::quiesce();\n");
puts(/**/ "rhs.vlSymsp->" + protect("__Vserialize") + "(os);\n"); puts(/**/ "rhs.vlSymsp->" + protect("__Vserialize") + "(os);\n");
puts(/**/ "return os;\n"); puts(/**/ "return os;\n");
puts("}\n"); puts("}\n");
puts("\nVerilatedDeserialize& operator>>(VerilatedDeserialize& os, " + topClassName() puts("\nVerilatedDeserialize& operator>>(VerilatedDeserialize& os, "
+ "& rhs) {\n"); + EmitCUtil::topClassName() + "& rhs) {\n");
puts(/**/ "Verilated::quiesce();\n"); puts(/**/ "Verilated::quiesce();\n");
puts(/**/ "rhs.vlSymsp->" + protect("__Vdeserialize") + "(os);\n"); puts(/**/ "rhs.vlSymsp->" + protect("__Vdeserialize") + "(os);\n");
puts(/**/ "return os;\n"); puts(/**/ "return os;\n");
@ -618,7 +626,7 @@ class EmitCModel final : public EmitCFunc {
void emitImplementation(AstNodeModule* modp) { void emitImplementation(AstNodeModule* modp) {
UASSERT(!ofp(), "Output file should not be open"); UASSERT(!ofp(), "Output file should not be open");
const string filename = v3Global.opt.makeDir() + "/" + topClassName() + ".cpp"; const string filename = v3Global.opt.makeDir() + "/" + EmitCUtil::topClassName() + ".cpp";
setOutputFile(v3Global.opt.systemC() ? new V3OutScFile{filename} setOutputFile(v3Global.opt.systemC() ? new V3OutScFile{filename}
: new V3OutCFile{filename}, : new V3OutCFile{filename},
newCFile(filename, /* slow: */ false, /* source: */ true)); newCFile(filename, /* slow: */ false, /* source: */ true));
@ -628,7 +636,7 @@ class EmitCModel final : public EmitCFunc {
"Model implementation (design independent parts)\n"); "Model implementation (design independent parts)\n");
puts("\n"); puts("\n");
puts("#include \"" + pchClassName() + ".h\"\n"); puts("#include \"" + EmitCUtil::pchClassName() + ".h\"\n");
if (v3Global.opt.trace()) { if (v3Global.opt.trace()) {
puts("#include \"" + v3Global.opt.traceSourceLang() + ".h\"\n"); puts("#include \"" + v3Global.opt.traceSourceLang() + ".h\"\n");
} }
@ -659,7 +667,8 @@ class EmitCModel final : public EmitCFunc {
} }
if (!ofp()) { if (!ofp()) {
string filename = v3Global.opt.makeDir() + "/" + topClassName() + "__Dpi_Export"; string filename
= v3Global.opt.makeDir() + "/" + EmitCUtil::topClassName() + "__Dpi_Export";
filename = m_uniqueNames.get(filename); filename = m_uniqueNames.get(filename);
filename += ".cpp"; filename += ".cpp";
setOutputFile(v3Global.opt.systemC() ? new V3OutScFile{filename} setOutputFile(v3Global.opt.systemC() ? new V3OutScFile{filename}
@ -671,8 +680,8 @@ class EmitCModel final : public EmitCFunc {
puts( puts(
"// DESCRIPTION: Verilator output: Implementation of DPI export functions.\n"); "// DESCRIPTION: Verilator output: Implementation of DPI export functions.\n");
puts("//\n"); puts("//\n");
puts("#include \"" + topClassName() + ".h\"\n"); puts("#include \"" + EmitCUtil::topClassName() + ".h\"\n");
puts("#include \"" + symClassName() + ".h\"\n"); puts("#include \"" + EmitCUtil::symClassName() + ".h\"\n");
puts("#include \"verilated_dpi.h\"\n"); puts("#include \"verilated_dpi.h\"\n");
puts("\n"); puts("\n");
} }

View File

@ -23,19 +23,19 @@ VL_DEFINE_DEBUG_FUNCTIONS;
//###################################################################### //######################################################################
// Precompiled header emitter // Precompiled header emitter
class EmitCPch final : EmitCBase { class EmitCPch final {
public: public:
// METHODS // METHODS
void emitPch() { void emitPch() {
// Generate the makefile // Generate the makefile
V3OutCFile of{v3Global.opt.makeDir() + "/" + pchClassName() + ".h"}; V3OutCFile of{v3Global.opt.makeDir() + "/" + EmitCUtil::pchClassName() + ".h"};
of.putsHeader(); of.putsHeader();
of.puts("// DESCRIPTION: Verilator output: Precompiled header\n"); of.puts("// DESCRIPTION: Verilator output: Precompiled header\n");
of.puts("//\n"); of.puts("//\n");
of.puts("// Internal details; most user sources do not need this header,\n"); of.puts("// Internal details; most user sources do not need this header,\n");
of.puts("// unless using verilator public meta comments.\n"); of.puts("// unless using verilator public meta comments.\n");
of.puts("// Suggest use " + topClassName() + ".h instead.\n"); of.puts("// Suggest use " + EmitCUtil::topClassName() + ".h instead.\n");
of.puts("\n"); of.puts("\n");
of.putsGuard(); of.putsGuard();
@ -54,8 +54,8 @@ public:
if (v3Global.dpi()) of.puts("#include \"verilated_dpi.h\"\n"); if (v3Global.dpi()) of.puts("#include \"verilated_dpi.h\"\n");
of.puts("\n"); of.puts("\n");
of.puts("#include \"" + symClassName() + ".h\"\n"); of.puts("#include \"" + EmitCUtil::symClassName() + ".h\"\n");
of.puts("#include \"" + topClassName() + ".h\"\n"); of.puts("#include \"" + EmitCUtil::topClassName() + ".h\"\n");
of.puts("\n// Additional include files added using '--compiler-include'\n"); of.puts("\n// Additional include files added using '--compiler-include'\n");
for (const string& filename : v3Global.opt.compilerIncludes()) { for (const string& filename : v3Global.opt.compilerIncludes()) {

View File

@ -399,7 +399,7 @@ public:
void EmitCSyms::emitSymHdr() { void EmitCSyms::emitSymHdr() {
UINFO(6, __FUNCTION__ << ": "); UINFO(6, __FUNCTION__ << ": ");
const string filename = v3Global.opt.makeDir() + "/" + symClassName() + ".h"; const string filename = v3Global.opt.makeDir() + "/" + EmitCUtil::symClassName() + ".h";
AstCFile* const cfilep = newCFile(filename, true /*slow*/, false /*source*/); AstCFile* const cfilep = newCFile(filename, true /*slow*/, false /*source*/);
V3OutCFile* const ofilep = optSystemC() ? new V3OutScFile{filename} : new V3OutCFile{filename}; V3OutCFile* const ofilep = optSystemC() ? new V3OutScFile{filename} : new V3OutCFile{filename};
setOutputFile(ofilep, cfilep); setOutputFile(ofilep, cfilep);
@ -421,13 +421,13 @@ void EmitCSyms::emitSymHdr() {
if (v3Global.opt.usesProfiler()) puts("#include \"verilated_profiler.h\"\n"); if (v3Global.opt.usesProfiler()) puts("#include \"verilated_profiler.h\"\n");
puts("\n// INCLUDE MODEL CLASS\n"); puts("\n// INCLUDE MODEL CLASS\n");
puts("\n#include \"" + topClassName() + ".h\"\n"); puts("\n#include \"" + EmitCUtil::topClassName() + ".h\"\n");
puts("\n// INCLUDE MODULE CLASSES\n"); puts("\n// INCLUDE MODULE CLASSES\n");
for (AstNodeModule* nodep = v3Global.rootp()->modulesp(); nodep; for (AstNodeModule* nodep = v3Global.rootp()->modulesp(); nodep;
nodep = VN_AS(nodep->nextp(), NodeModule)) { nodep = VN_AS(nodep->nextp(), NodeModule)) {
if (VN_IS(nodep, Class)) continue; // Class included earlier if (VN_IS(nodep, Class)) continue; // Class included earlier
putns(nodep, "#include \"" + prefixNameProtect(nodep) + ".h\"\n"); putns(nodep, "#include \"" + EmitCUtil::prefixNameProtect(nodep) + ".h\"\n");
} }
if (v3Global.dpi()) { if (v3Global.dpi()) {
@ -446,12 +446,12 @@ void EmitCSyms::emitSymHdr() {
} }
puts("\n// SYMS CLASS (contains all model state)\n"); puts("\n// SYMS CLASS (contains all model state)\n");
puts("class alignas(VL_CACHE_LINE_BYTES)" + symClassName() puts("class alignas(VL_CACHE_LINE_BYTES)" + EmitCUtil::symClassName()
+ " final : public VerilatedSyms {\n"); + " final : public VerilatedSyms {\n");
ofp()->putsPrivate(false); // public: ofp()->putsPrivate(false); // public:
puts("// INTERNAL STATE\n"); puts("// INTERNAL STATE\n");
puts(topClassName() + "* const __Vm_modelp;\n"); puts(EmitCUtil::topClassName() + "* const __Vm_modelp;\n");
if (v3Global.needTraceDumper()) { if (v3Global.needTraceDumper()) {
// __Vm_dumperp is local, otherwise we wouldn't know what design's eval() // __Vm_dumperp is local, otherwise we wouldn't know what design's eval()
@ -496,9 +496,9 @@ void EmitCSyms::emitSymHdr() {
const AstScope* const scopep = i.first; const AstScope* const scopep = i.first;
const AstNodeModule* const modp = i.second; const AstNodeModule* const modp = i.second;
if (VN_IS(modp, Class)) continue; if (VN_IS(modp, Class)) continue;
const string name = prefixNameProtect(modp); const string name = EmitCUtil::prefixNameProtect(modp);
ofp()->printf("%-30s ", name.c_str()); ofp()->printf("%-30s ", name.c_str());
putns(scopep, protectIf(scopep->nameDotless(), scopep->protect()) + ";\n"); putns(scopep, VIdProtect::protectIf(scopep->nameDotless(), scopep->protect()) + ";\n");
} }
if (m_coverBins) { if (m_coverBins) {
@ -528,12 +528,12 @@ void EmitCSyms::emitSymHdr() {
} }
puts("\n// CONSTRUCTORS\n"); puts("\n// CONSTRUCTORS\n");
puts(symClassName() + "(VerilatedContext* contextp, const char* namep, " + topClassName() puts(EmitCUtil::symClassName() + "(VerilatedContext* contextp, const char* namep, "
+ "* modelp);\n"); + EmitCUtil::topClassName() + "* modelp);\n");
puts("~"s + symClassName() + "();\n"); puts("~"s + EmitCUtil::symClassName() + "();\n");
for (const auto& i : m_usesVfinal) { for (const auto& i : m_usesVfinal) {
puts("void " + symClassName() + "_" + cvtToStr(i.first) + "("); puts("void " + EmitCUtil::symClassName() + "_" + cvtToStr(i.first) + "(");
if (i.second) puts("int __Vfinal"); if (i.second) puts("int __Vfinal");
puts(");\n"); puts(");\n");
} }
@ -599,8 +599,8 @@ void EmitCSyms::checkSplit(bool usesVfinal) {
v3Global.useParallelBuild(true); v3Global.useParallelBuild(true);
m_numStmts = 0; m_numStmts = 0;
const string filename const string filename = v3Global.opt.makeDir() + "/" + EmitCUtil::symClassName() + "__"
= v3Global.opt.makeDir() + "/" + symClassName() + "__" + cvtToStr(++m_funcNum) + ".cpp"; + cvtToStr(++m_funcNum) + ".cpp";
AstCFile* const cfilep = newCFile(filename, true /*slow*/, true /*source*/); AstCFile* const cfilep = newCFile(filename, true /*slow*/, true /*source*/);
cfilep->support(true); cfilep->support(true);
m_usesVfinal[m_funcNum] = usesVfinal; m_usesVfinal[m_funcNum] = usesVfinal;
@ -609,12 +609,13 @@ void EmitCSyms::checkSplit(bool usesVfinal) {
V3OutCFile* const ofilep = optSystemC() ? new V3OutScFile{filename} : new V3OutCFile{filename}; V3OutCFile* const ofilep = optSystemC() ? new V3OutScFile{filename} : new V3OutCFile{filename};
setOutputFile(ofilep, cfilep); setOutputFile(ofilep, cfilep);
m_ofpBase->puts(symClassName() + "_" + cvtToStr(m_funcNum) + "("); m_ofpBase->puts(EmitCUtil::symClassName() + "_" + cvtToStr(m_funcNum) + "(");
if (usesVfinal) m_ofpBase->puts("__Vfinal"); if (usesVfinal) m_ofpBase->puts("__Vfinal");
m_ofpBase->puts(");\n"); m_ofpBase->puts(");\n");
emitSymImpPreamble(); emitSymImpPreamble();
puts("void " + symClassName() + "::" + symClassName() + "_" + cvtToStr(m_funcNum) + "("); puts("void " + EmitCUtil::symClassName() + "::" + EmitCUtil::symClassName() + "_"
+ cvtToStr(m_funcNum) + "(");
if (usesVfinal) puts("int __Vfinal"); if (usesVfinal) puts("int __Vfinal");
puts(") {\n"); puts(") {\n");
} }
@ -626,12 +627,12 @@ void EmitCSyms::emitSymImpPreamble() {
puts("\n"); puts("\n");
// Includes // Includes
puts("#include \"" + pchClassName() + ".h\"\n"); puts("#include \"" + EmitCUtil::pchClassName() + ".h\"\n");
puts("#include \"" + topClassName() + ".h\"\n"); puts("#include \"" + EmitCUtil::topClassName() + ".h\"\n");
for (AstNodeModule* nodep = v3Global.rootp()->modulesp(); nodep; for (AstNodeModule* nodep = v3Global.rootp()->modulesp(); nodep;
nodep = VN_AS(nodep->nextp(), NodeModule)) { nodep = VN_AS(nodep->nextp(), NodeModule)) {
if (VN_IS(nodep, Class)) continue; // Class included earlier if (VN_IS(nodep, Class)) continue; // Class included earlier
putns(nodep, "#include \"" + prefixNameProtect(nodep) + ".h\"\n"); putns(nodep, "#include \"" + EmitCUtil::prefixNameProtect(nodep) + ".h\"\n");
} }
puts("\n"); puts("\n");
// Declarations for DPI Export implementation functions // Declarations for DPI Export implementation functions
@ -683,7 +684,7 @@ void EmitCSyms::emitScopeHier(bool destroy) {
void EmitCSyms::emitSymImp() { void EmitCSyms::emitSymImp() {
UINFO(6, __FUNCTION__ << ": "); UINFO(6, __FUNCTION__ << ": ");
const string filename = v3Global.opt.makeDir() + "/" + symClassName() + ".cpp"; const string filename = v3Global.opt.makeDir() + "/" + EmitCUtil::symClassName() + ".cpp";
AstCFile* const cfilep = newCFile(filename, true /*slow*/, true /*source*/); AstCFile* const cfilep = newCFile(filename, true /*slow*/, true /*source*/);
cfilep->support(true); cfilep->support(true);
@ -699,7 +700,7 @@ void EmitCSyms::emitSymImp() {
const string funcname = de ? "__Vdeserialize" : "__Vserialize"; const string funcname = de ? "__Vdeserialize" : "__Vserialize";
const string op = de ? ">>" : "<<"; const string op = de ? ">>" : "<<";
// NOLINTNEXTLINE(performance-inefficient-string-concatenation) // NOLINTNEXTLINE(performance-inefficient-string-concatenation)
puts("void " + symClassName() + "::" + protect(funcname) + "(" + classname puts("void " + EmitCUtil::symClassName() + "::" + protect(funcname) + "(" + classname
+ "& os) {\n"); + "& os) {\n");
puts("// Internal state\n"); puts("// Internal state\n");
if (v3Global.opt.trace()) puts("os" + op + "__Vm_activity;\n"); if (v3Global.opt.trace()) puts("os" + op + "__Vm_activity;\n");
@ -707,8 +708,8 @@ void EmitCSyms::emitSymImp() {
puts("// Module instance state\n"); puts("// Module instance state\n");
for (const auto& pair : m_scopes) { for (const auto& pair : m_scopes) {
const AstScope* const scopep = pair.first; const AstScope* const scopep = pair.first;
puts(protectIf(scopep->nameDotless(), scopep->protect()) + "." + protect(funcname) puts(VIdProtect::protectIf(scopep->nameDotless(), scopep->protect()) + "."
+ "(os);\n"); + protect(funcname) + "(os);\n");
} }
puts("}\n"); puts("}\n");
} }
@ -718,7 +719,7 @@ void EmitCSyms::emitSymImp() {
puts("// FUNCTIONS\n"); puts("// FUNCTIONS\n");
// Destructor // Destructor
puts(symClassName() + "::~" + symClassName() + "()\n"); puts(EmitCUtil::symClassName() + "::~" + EmitCUtil::symClassName() + "()\n");
puts("{\n"); puts("{\n");
emitScopeHier(true); emitScopeHier(true);
if (v3Global.needTraceDumper()) { if (v3Global.needTraceDumper()) {
@ -730,21 +731,21 @@ void EmitCSyms::emitSymImp() {
// Do not overwrite data during the last hierarchical stage. // Do not overwrite data during the last hierarchical stage.
const string firstHierCall const string firstHierCall
= (v3Global.opt.hierBlocks().empty() || v3Global.opt.hierChild()) ? "true" : "false"; = (v3Global.opt.hierBlocks().empty() || v3Global.opt.hierChild()) ? "true" : "false";
puts("_vm_pgoProfiler.write(\"" + topClassName() puts("_vm_pgoProfiler.write(\"" + EmitCUtil::topClassName()
+ "\", _vm_contextp__->profVltFilename(), " + firstHierCall + ");\n"); + "\", _vm_contextp__->profVltFilename(), " + firstHierCall + ");\n");
} }
puts("}\n"); puts("}\n");
if (v3Global.needTraceDumper()) { if (v3Global.needTraceDumper()) {
if (!optSystemC()) { if (!optSystemC()) {
puts("\nvoid " + symClassName() + "::_traceDump() {\n"); puts("\nvoid " + EmitCUtil::symClassName() + "::_traceDump() {\n");
// Caller checked for __Vm_dumperp non-nullptr // Caller checked for __Vm_dumperp non-nullptr
puts("const VerilatedLockGuard lock{__Vm_dumperMutex};\n"); puts("const VerilatedLockGuard lock{__Vm_dumperMutex};\n");
puts("__Vm_dumperp->dump(VL_TIME_Q());\n"); puts("__Vm_dumperp->dump(VL_TIME_Q());\n");
puts("}\n"); puts("}\n");
} }
puts("\nvoid " + symClassName() + "::_traceDumpOpen() {\n"); puts("\nvoid " + EmitCUtil::symClassName() + "::_traceDumpOpen() {\n");
puts("const VerilatedLockGuard lock{__Vm_dumperMutex};\n"); puts("const VerilatedLockGuard lock{__Vm_dumperMutex};\n");
puts("if (VL_UNLIKELY(!__Vm_dumperp)) {\n"); puts("if (VL_UNLIKELY(!__Vm_dumperp)) {\n");
puts("__Vm_dumperp = new " + v3Global.opt.traceClassLang() + "();\n"); puts("__Vm_dumperp = new " + v3Global.opt.traceClassLang() + "();\n");
@ -755,7 +756,7 @@ void EmitCSyms::emitSymImp() {
puts("}\n"); puts("}\n");
puts("}\n"); puts("}\n");
puts("\nvoid " + symClassName() + "::_traceDumpClose() {\n"); puts("\nvoid " + EmitCUtil::symClassName() + "::_traceDumpClose() {\n");
puts("const VerilatedLockGuard lock{__Vm_dumperMutex};\n"); puts("const VerilatedLockGuard lock{__Vm_dumperMutex};\n");
puts("__Vm_dumping = false;\n"); puts("__Vm_dumping = false;\n");
puts("VL_DO_CLEAR(delete __Vm_dumperp, __Vm_dumperp = nullptr);\n"); puts("VL_DO_CLEAR(delete __Vm_dumperp, __Vm_dumperp = nullptr);\n");
@ -764,8 +765,9 @@ void EmitCSyms::emitSymImp() {
puts("\n"); puts("\n");
// Constructor // Constructor
puts(symClassName() + "::" + symClassName() puts(EmitCUtil::symClassName() + "::" + EmitCUtil::symClassName()
+ "(VerilatedContext* contextp, const char* namep, " + topClassName() + "* modelp)\n"); + "(VerilatedContext* contextp, const char* namep, " + EmitCUtil::topClassName()
+ "* modelp)\n");
puts(" : VerilatedSyms{contextp}\n"); puts(" : VerilatedSyms{contextp}\n");
puts(" // Setup internal state of the Syms class\n"); puts(" // Setup internal state of the Syms class\n");
puts(" , __Vm_modelp{modelp}\n"); puts(" , __Vm_modelp{modelp}\n");
@ -813,7 +815,7 @@ void EmitCSyms::emitSymImp() {
} else { } else {
// The "." is added by catName // The "." is added by catName
puts(", Verilated::catName(namep, "); puts(", Verilated::catName(namep, ");
putsQuoted(protectWordsIf(scopep->prettyName(), scopep->protect())); putsQuoted(VIdProtect::protectWordsIf(scopep->prettyName(), scopep->protect()));
puts(")"); puts(")");
} }
puts("}\n"); puts("}\n");
@ -862,17 +864,18 @@ void EmitCSyms::emitSymImp() {
const AstNodeModule* const modp = i.second; const AstNodeModule* const modp = i.second;
if (const AstScope* const aboveScopep = scopep->aboveScopep()) { if (const AstScope* const aboveScopep = scopep->aboveScopep()) {
checkSplit(false); checkSplit(false);
const string protName = protectWordsIf(scopep->name(), scopep->protect()); const string protName = VIdProtect::protectWordsIf(scopep->name(), scopep->protect());
if (VN_IS(modp, ClassPackage)) { if (VN_IS(modp, ClassPackage)) {
// ClassPackage modules seem to be a bit out of place, so hard code... // ClassPackage modules seem to be a bit out of place, so hard code...
putns(scopep, "TOP"); putns(scopep, "TOP");
} else { } else {
putns(scopep, protectIf(aboveScopep->nameDotless(), aboveScopep->protect())); putns(scopep,
VIdProtect::protectIf(aboveScopep->nameDotless(), aboveScopep->protect()));
} }
puts("."); puts(".");
puts(protName.substr(protName.rfind('.') + 1)); puts(protName.substr(protName.rfind('.') + 1));
puts(" = &"); puts(" = &");
puts(protectIf(scopep->nameDotless(), scopep->protect()) + ";\n"); puts(VIdProtect::protectIf(scopep->nameDotless(), scopep->protect()) + ";\n");
++m_numStmts; ++m_numStmts;
} }
} }
@ -885,7 +888,7 @@ void EmitCSyms::emitSymImp() {
// first is used by AstCoverDecl's call to __vlCoverInsert // first is used by AstCoverDecl's call to __vlCoverInsert
const bool first = !modp->user1(); const bool first = !modp->user1();
modp->user1(true); modp->user1(true);
putns(scopep, protectIf(scopep->nameDotless(), scopep->protect()) + "." putns(scopep, VIdProtect::protectIf(scopep->nameDotless(), scopep->protect()) + "."
+ protect("__Vconfigure") + "(" + (first ? "true" : "false") + ");\n"); + protect("__Vconfigure") + "(" + (first ? "true" : "false") + ");\n");
++m_numStmts; ++m_numStmts;
} }
@ -896,7 +899,7 @@ void EmitCSyms::emitSymImp() {
checkSplit(false); checkSplit(false);
putns(it->second.m_nodep, putns(it->second.m_nodep,
protect("__Vscope_" + it->second.m_symName) + ".configure(this, name(), "); protect("__Vscope_" + it->second.m_symName) + ".configure(this, name(), ");
putsQuoted(protectWordsIf(it->second.m_prettyName, true)); putsQuoted(VIdProtect::protectWordsIf(it->second.m_prettyName, true));
puts(", "); puts(", ");
putsQuoted(protect(scopeDecodeIdentifier(it->second.m_prettyName))); putsQuoted(protect(scopeDecodeIdentifier(it->second.m_prettyName)));
puts(", "); puts(", ");
@ -926,7 +929,7 @@ void EmitCSyms::emitSymImp() {
protect("__Vscope_" + scopep->scopeSymName()) + ".exportInsert(__Vfinal, "); protect("__Vscope_" + scopep->scopeSymName()) + ".exportInsert(__Vfinal, ");
putsQuoted(funcp->cname()); // Not protected - user asked for import/export putsQuoted(funcp->cname()); // Not protected - user asked for import/export
puts(", (void*)(&"); puts(", (void*)(&");
puts(prefixNameProtect(modp)); puts(EmitCUtil::prefixNameProtect(modp));
puts("__"); puts("__");
puts(funcp->nameProtect()); puts(funcp->nameProtect());
puts("));\n"); puts("));\n");
@ -975,7 +978,7 @@ void EmitCSyms::emitSymImp() {
putsQuoted(protect(it->second.m_varBasePretty)); putsQuoted(protect(it->second.m_varBasePretty));
std::string varName; std::string varName;
varName += protectIf(scopep->nameDotless(), scopep->protect()) + "."; varName += VIdProtect::protectIf(scopep->nameDotless(), scopep->protect()) + ".";
varName += protect(varp->name()); varName += protect(varp->name());
if (varp->isParam()) { if (varp->isParam()) {
@ -1022,7 +1025,7 @@ void EmitCSyms::emitSymImp() {
void EmitCSyms::emitDpiHdr() { void EmitCSyms::emitDpiHdr() {
UINFO(6, __FUNCTION__ << ": "); UINFO(6, __FUNCTION__ << ": ");
const string filename = v3Global.opt.makeDir() + "/" + topClassName() + "__Dpi.h"; const string filename = v3Global.opt.makeDir() + "/" + EmitCUtil::topClassName() + "__Dpi.h";
AstCFile* const cfilep = newCFile(filename, false /*slow*/, false /*source*/); AstCFile* const cfilep = newCFile(filename, false /*slow*/, false /*source*/);
cfilep->support(true); cfilep->support(true);
V3OutCFile hf{filename}; V3OutCFile hf{filename};
@ -1051,14 +1054,16 @@ void EmitCSyms::emitDpiHdr() {
for (AstCFunc* nodep : m_dpis) { for (AstCFunc* nodep : m_dpis) {
if (nodep->dpiExportDispatcher()) { if (nodep->dpiExportDispatcher()) {
if (!firstExp++) puts("\n// DPI EXPORTS\n"); if (!firstExp++) puts("\n// DPI EXPORTS\n");
putsDecoration(nodep, "// DPI export" putsDecoration(
+ ifNoProtect(" at " + nodep->fileline()->ascii()) + "\n"); nodep, "// DPI export"
+ VIdProtect::ifNoProtect(" at " + nodep->fileline()->ascii()) + "\n");
putns(nodep, "extern " + nodep->rtnTypeVoid() + " " + nodep->nameProtect() + "(" putns(nodep, "extern " + nodep->rtnTypeVoid() + " " + nodep->nameProtect() + "("
+ cFuncArgs(nodep) + ");\n"); + cFuncArgs(nodep) + ");\n");
} else if (nodep->dpiImportPrototype()) { } else if (nodep->dpiImportPrototype()) {
if (!firstImp++) puts("\n// DPI IMPORTS\n"); if (!firstImp++) puts("\n// DPI IMPORTS\n");
putsDecoration(nodep, "// DPI import" putsDecoration(
+ ifNoProtect(" at " + nodep->fileline()->ascii()) + "\n"); nodep, "// DPI import"
+ VIdProtect::ifNoProtect(" at " + nodep->fileline()->ascii()) + "\n");
putns(nodep, "extern " + nodep->rtnTypeVoid() + " " + nodep->nameProtect() + "(" putns(nodep, "extern " + nodep->rtnTypeVoid() + " " + nodep->nameProtect() + "("
+ cFuncArgs(nodep) + ");\n"); + cFuncArgs(nodep) + ");\n");
} }
@ -1077,7 +1082,7 @@ void EmitCSyms::emitDpiHdr() {
void EmitCSyms::emitDpiImp() { void EmitCSyms::emitDpiImp() {
UINFO(6, __FUNCTION__ << ": "); UINFO(6, __FUNCTION__ << ": ");
const string filename = v3Global.opt.makeDir() + "/" + topClassName() + "__Dpi.cpp"; const string filename = v3Global.opt.makeDir() + "/" + EmitCUtil::topClassName() + "__Dpi.cpp";
AstCFile* const cfilep = newCFile(filename, false /*slow*/, true /*source*/); AstCFile* const cfilep = newCFile(filename, false /*slow*/, true /*source*/);
cfilep->support(true); cfilep->support(true);
V3OutCFile hf(filename); V3OutCFile hf(filename);
@ -1092,14 +1097,14 @@ void EmitCSyms::emitDpiImp() {
puts("// function names, you will get multiple definition link errors from here.\n"); puts("// function names, you will get multiple definition link errors from here.\n");
puts("// This is an unfortunate result of the DPI specification.\n"); puts("// This is an unfortunate result of the DPI specification.\n");
puts("// To solve this, either\n"); puts("// To solve this, either\n");
puts("// 1. Call " + topClassName() + "::{export_function} instead,\n"); puts("// 1. Call " + EmitCUtil::topClassName() + "::{export_function} instead,\n");
puts("// and do not even bother to compile this file\n"); puts("// and do not even bother to compile this file\n");
puts("// or 2. Compile all __Dpi.cpp files in the same compiler run,\n"); puts("// or 2. Compile all __Dpi.cpp files in the same compiler run,\n");
puts("// and #ifdefs already inserted here will sort everything out.\n"); puts("// and #ifdefs already inserted here will sort everything out.\n");
puts("\n"); puts("\n");
puts("#include \"" + topClassName() + "__Dpi.h\"\n"); puts("#include \"" + EmitCUtil::topClassName() + "__Dpi.h\"\n");
puts("#include \"" + topClassName() + ".h\"\n"); puts("#include \"" + EmitCUtil::topClassName() + ".h\"\n");
puts("\n"); puts("\n");
for (AstCFunc* nodep : m_dpis) { for (AstCFunc* nodep : m_dpis) {
@ -1109,8 +1114,9 @@ void EmitCSyms::emitDpiImp() {
puts("#define VL_DPIDECL_" + nodep->name() + "_\n"); puts("#define VL_DPIDECL_" + nodep->name() + "_\n");
putns(nodep, putns(nodep,
nodep->rtnTypeVoid() + " " + nodep->name() + "(" + cFuncArgs(nodep) + ") {\n"); nodep->rtnTypeVoid() + " " + nodep->name() + "(" + cFuncArgs(nodep) + ") {\n");
puts("// DPI export" + ifNoProtect(" at " + nodep->fileline()->ascii()) + "\n"); puts("// DPI export" + VIdProtect::ifNoProtect(" at " + nodep->fileline()->ascii())
putns(nodep, "return " + topClassName() + "::" + nodep->name() + "("); + "\n");
putns(nodep, "return " + EmitCUtil::topClassName() + "::" + nodep->name() + "(");
string comma; string comma;
for (AstNode* stmtp = nodep->argsp(); stmtp; stmtp = stmtp->nextp()) { for (AstNode* stmtp = nodep->argsp(); stmtp; stmtp = stmtp->nextp()) {
if (const AstVar* const portp = VN_CAST(stmtp, Var)) { if (const AstVar* const portp = VN_CAST(stmtp, Var)) {

View File

@ -73,7 +73,7 @@ class EmitVBaseVisitorConst VL_NOT_FINAL : public VNVisitorConst {
// VISITORS // VISITORS
void visit(AstNetlist* nodep) override { iterateAndNextConstNull(nodep->modulesp()); } void visit(AstNetlist* nodep) override { iterateAndNextConstNull(nodep->modulesp()); }
void visit(AstNodeModule* nodep) override { void visit(AstNodeModule* nodep) override {
putfs(nodep, nodep->verilogKwd() + " " + EmitCBase::prefixNameProtect(nodep) + ";\n"); putfs(nodep, nodep->verilogKwd() + " " + EmitCUtil::prefixNameProtect(nodep) + ";\n");
iterateChildrenConst(nodep); iterateChildrenConst(nodep);
putqs(nodep, "end" + nodep->verilogKwd() + "\n"); putqs(nodep, "end" + nodep->verilogKwd() + "\n");
} }

View File

@ -982,8 +982,8 @@ const std::vector<AstCFunc*> createThreadFunctions(const ThreadSchedule& schedul
funcp->argTypes("void* voidSelf, bool even_cycle"); funcp->argTypes("void* voidSelf, bool even_cycle");
// Setup vlSelf and vlSyms // Setup vlSelf and vlSyms
funcp->addStmtsp(new AstCStmt{fl, EmitCBase::voidSelfAssign(modp)}); funcp->addStmtsp(new AstCStmt{fl, EmitCUtil::voidSelfAssign(modp)});
funcp->addStmtsp(new AstCStmt{fl, EmitCBase::symClassAssign()}); funcp->addStmtsp(new AstCStmt{fl, EmitCUtil::symClassAssign()});
// Invoke each mtask scheduled to this thread from the thread function // Invoke each mtask scheduled to this thread from the thread function
for (const ExecMTask* const mtaskp : thread) { for (const ExecMTask* const mtaskp : thread) {

View File

@ -1118,6 +1118,9 @@ private:
} }
}; };
string VIdProtect::ifNoProtect(const string& in) VL_MT_SAFE {
return v3Global.opt.protectIds() ? "" : in;
}
string VIdProtect::protectIf(const string& old, bool doIt) VL_MT_SAFE { string VIdProtect::protectIf(const string& old, bool doIt) VL_MT_SAFE {
return VIdProtectImp::singleton().protectIf(old, doIt); return VIdProtectImp::singleton().protectIf(old, doIt);
} }

View File

@ -461,6 +461,8 @@ class VIdProtectImp;
class VIdProtect final { class VIdProtect final {
public: public:
// METHODS // METHODS
// Return 'in' only if not protecting (e.g. for emitting a comment)
static string ifNoProtect(const string& in) VL_MT_SAFE;
// Rename to a new encoded string (unless earlier passthru'ed) // Rename to a new encoded string (unless earlier passthru'ed)
static string protect(const string& old) VL_MT_SAFE { return protectIf(old, true); } static string protect(const string& old) VL_MT_SAFE { return protectIf(old, true); }
static string protectIf(const string& old, bool doIt = true) VL_MT_SAFE; static string protectIf(const string& old, bool doIt = true) VL_MT_SAFE;

View File

@ -390,7 +390,7 @@ void transformForks(AstNetlist* const netlistp) {
// If we're in a class, add a vlSymsp arg // If we're in a class, add a vlSymsp arg
if (m_inClass) { if (m_inClass) {
newfuncp->addInitsp(new AstCStmt{nodep->fileline(), "VL_KEEP_THIS;\n"}); newfuncp->addInitsp(new AstCStmt{nodep->fileline(), "VL_KEEP_THIS;\n"});
newfuncp->argTypes(EmitCBase::symClassVar()); newfuncp->argTypes(EmitCUtil::symClassVar());
callp->argTypes("vlSymsp"); callp->argTypes("vlSymsp");
} }
// Put the begin's statements in the function, delete the begin // Put the begin's statements in the function, delete the begin

View File

@ -897,7 +897,7 @@ class TaskVisitor final : public VNVisitor {
// Convert input/inout DPI arguments to Internal types // Convert input/inout DPI arguments to Internal types
string args; string args;
args += ("(" + EmitCBase::symClassName() args += ("(" + EmitCUtil::symClassName()
+ "*)(__Vscopep->symsp())"); // Upcast w/o overhead + "*)(__Vscopep->symsp())"); // Upcast w/o overhead
AstNode* argnodesp = nullptr; AstNode* argnodesp = nullptr;
for (AstNode* stmtp = nodep->stmtsp(); stmtp; stmtp = stmtp->nextp()) { for (AstNode* stmtp = nodep->stmtsp(); stmtp; stmtp = stmtp->nextp()) {
@ -1284,7 +1284,7 @@ class TaskVisitor final : public VNVisitor {
if (!nodep->dpiImport() && !nodep->taskPublic()) { if (!nodep->dpiImport() && !nodep->taskPublic()) {
// Need symbol table // Need symbol table
cfuncp->argTypes(EmitCBase::symClassVar()); cfuncp->argTypes(EmitCUtil::symClassVar());
if (cfuncp->name() == "new") { if (cfuncp->name() == "new") {
const string stmt = VIdProtect::protect("_ctor_var_reset") + "(vlSymsp);\n"; const string stmt = VIdProtect::protect("_ctor_var_reset") + "(vlSymsp);\n";
cfuncp->addInitsp(new AstCStmt{nodep->fileline(), stmt}); cfuncp->addInitsp(new AstCStmt{nodep->fileline(), stmt});

View File

@ -519,8 +519,8 @@ class TraceVisitor final : public VNVisitor {
if (isTopFunc) { if (isTopFunc) {
// Top functions // Top functions
funcp->argTypes("void* voidSelf, " + bufArg); funcp->argTypes("void* voidSelf, " + bufArg);
addInitStr(EmitCBase::voidSelfAssign(m_topModp)); addInitStr(EmitCUtil::voidSelfAssign(m_topModp));
addInitStr(EmitCBase::symClassAssign()); addInitStr(EmitCUtil::symClassAssign());
// Add global activity check to change dump functions // Add global activity check to change dump functions
if (traceType == VTraceType::CHANGE) { // if (traceType == VTraceType::CHANGE) { //
addInitStr("if (VL_UNLIKELY(!vlSymsp->__Vm_activity)) return;\n"); addInitStr("if (VL_UNLIKELY(!vlSymsp->__Vm_activity)) return;\n");
@ -732,8 +732,8 @@ class TraceVisitor final : public VNVisitor {
cleanupFuncp->isStatic(true); cleanupFuncp->isStatic(true);
cleanupFuncp->isLoose(true); cleanupFuncp->isLoose(true);
m_topScopep->addBlocksp(cleanupFuncp); m_topScopep->addBlocksp(cleanupFuncp);
cleanupFuncp->addInitsp(new AstCStmt{fl, EmitCBase::voidSelfAssign(m_topModp)}); cleanupFuncp->addInitsp(new AstCStmt{fl, EmitCUtil::voidSelfAssign(m_topModp)});
cleanupFuncp->addInitsp(new AstCStmt{fl, EmitCBase::symClassAssign()}); cleanupFuncp->addInitsp(new AstCStmt{fl, EmitCUtil::symClassAssign()});
// Register it // Register it
m_regFuncp->addStmtsp(new AstText{fl, "tracep->addCleanupCb(", true}); m_regFuncp->addStmtsp(new AstText{fl, "tracep->addCleanupCb(", true});

View File

@ -231,7 +231,7 @@ class VariableOrder final {
: (sigbytes == 2) ? 3 : (sigbytes == 2) ? 3
: (sigbytes == 1) ? 2 : (sigbytes == 1) ? 2
: 10; : 10;
m_attributes.emplace(varp, VarAttributes{stratum, EmitCBase::isAnonOk(varp)}); m_attributes.emplace(varp, VarAttributes{stratum, EmitCUtil::isAnonOk(varp)});
} }
} }