diff --git a/src/V3Active.cpp b/src/V3Active.cpp index 68ef3dbf1..2ad8a1a8f 100644 --- a/src/V3Active.cpp +++ b/src/V3Active.cpp @@ -68,7 +68,7 @@ public: : V3GraphVertex{graphp} , m_name{name} , m_type{type} {} - string name() const override { return m_name + " " + typestr(); } + string name() const override VL_MT_STABLE { return m_name + " " + typestr(); } string dotColor() const override { return user() ? "green" : "black"; } virtual int type() const { return m_type; } }; diff --git a/src/V3Ast.cpp b/src/V3Ast.cpp index 86e89fac3..c60db662f 100644 --- a/src/V3Ast.cpp +++ b/src/V3Ast.cpp @@ -125,7 +125,9 @@ string AstNode::encodeNumber(int64_t num) { } } -string AstNode::nameProtect() const { return VIdProtect::protectIf(name(), protect()); } +string AstNode::nameProtect() const VL_MT_STABLE { + return VIdProtect::protectIf(name(), protect()); +} string AstNode::origNameProtect() const { return VIdProtect::protectIf(origName(), protect()); } string AstNode::shortName() const { diff --git a/src/V3Ast.h b/src/V3Ast.h index 0d4ae58a7..cee54c5b8 100644 --- a/src/V3Ast.h +++ b/src/V3Ast.h @@ -1670,7 +1670,7 @@ public: static constexpr int INSTR_COUNT_PLI = 20; // PLI routines // ACCESSORS - virtual string name() const VL_MT_SAFE { return ""; } + virtual string name() const VL_MT_STABLE { return ""; } virtual string origName() const { return ""; } virtual void name(const string& name) { this->v3fatalSrc("name() called on object without name() method"); @@ -1678,7 +1678,7 @@ public: virtual void tag(const string& text) {} virtual string tag() const { return ""; } virtual string verilogKwd() const { return ""; } - string nameProtect() const; // Name with --protect-id applied + string nameProtect() const VL_MT_STABLE; // Name with --protect-id applied string origNameProtect() const; // origName with --protect-id applied string shortName() const; // Name with __PVT__ removed for concatenating scopes static string dedotName(const string& namein); // Name with dots removed @@ -1691,7 +1691,7 @@ public: encodeName(const string& namein); // Encode user name into internal C representation static string encodeNumber(int64_t num); // Encode number into internal C representation static string vcdName(const string& namein); // Name for printing out to vcd files - string prettyName() const VL_MT_SAFE { return prettyName(name()); } + string prettyName() const VL_MT_STABLE { return prettyName(name()); } string prettyNameQ() const { return prettyNameQ(name()); } string prettyTypeName() const; // "VARREF" for error messages (NOT dtype's pretty name) virtual string prettyOperatorName() const { return "operator " + prettyTypeName(); } diff --git a/src/V3AstNodeDType.h b/src/V3AstNodeDType.h index 26f1a740e..97eaacc5b 100644 --- a/src/V3AstNodeDType.h +++ b/src/V3AstNodeDType.h @@ -242,7 +242,7 @@ public: bool similarDType(const AstNodeDType* samep) const override { return this == samep; // We don't compare members, require exact equivalence } - string name() const override { return m_name; } + string name() const override VL_MT_STABLE { return m_name; } void name(const string& flag) override { m_name = flag; } bool packed() const VL_MT_SAFE { return m_packed; } void packed(bool flag) { m_packed = flag; } @@ -281,7 +281,7 @@ public: this->valuep(valuep); } ASTGEN_MEMBERS_AstEnumItem; - string name() const override { return m_name; } + string name() const override VL_MT_STABLE { return m_name; } bool maybePointedTo() const override { return true; } bool hasDType() const override { return true; } void name(const string& flag) override { m_name = flag; } @@ -409,7 +409,7 @@ public: bool similarDType(const AstNodeDType* samep) const override { return type() == samep->type() && same(samep); } - string name() const override { return m.m_keyword.ascii(); } + string name() const override VL_MT_STABLE { return m.m_keyword.ascii(); } string prettyDTypeName() const override; const char* broken() const override { BROKEN_RTN(dtypep() != this); @@ -531,7 +531,7 @@ public: } void dump(std::ostream& str = std::cout) const override; void dumpSmall(std::ostream& str) const override; - string name() const override; + string name() const override VL_MT_STABLE; AstBasicDType* basicp() const override VL_MT_STABLE { return nullptr; } AstNodeDType* skipRefp() const override VL_MT_STABLE { return (AstNodeDType*)this; } AstNodeDType* skipRefToConstp() const override { return (AstNodeDType*)this; } @@ -543,7 +543,7 @@ public: AstNodeDType* subDTypep() const override VL_MT_SAFE { return nullptr; } AstNodeModule* classOrPackagep() const { return m_classOrPackagep; } void classOrPackagep(AstNodeModule* nodep) { m_classOrPackagep = nodep; } - AstClass* classp() const { return m_classp; } + AstClass* classp() const VL_MT_STABLE { return m_classp; } void classp(AstClass* nodep) { m_classp = nodep; } bool isCompound() const override { return true; } }; @@ -641,7 +641,7 @@ public: AstNodeDType* skipRefToEnump() const override { return (AstNodeDType*)this; } int widthAlignBytes() const override { return dtypep()->widthAlignBytes(); } int widthTotalBytes() const override { return dtypep()->widthTotalBytes(); } - string name() const override { return m_name; } + string name() const override VL_MT_STABLE { return m_name; } void name(const string& flag) override { m_name = flag; } bool isCompound() const override { return false; } }; @@ -767,7 +767,7 @@ public: void refDTypep(AstNodeDType* nodep) { m_refDTypep = nodep; } AstNodeDType* virtRefDTypep() const override { return m_refDTypep; } void virtRefDTypep(AstNodeDType* nodep) override { refDTypep(nodep); } - string name() const override { return m_name; } + string name() const override VL_MT_STABLE { return m_name; } void name(const string& flag) override { m_name = flag; } void dump(std::ostream& str = std::cout) const override; void dumpSmall(std::ostream& str) const override; @@ -879,7 +879,7 @@ public: } ASTGEN_MEMBERS_AstMemberDType; void dumpSmall(std::ostream& str) const override; - string name() const override { return m_name; } // * = Var name + string name() const override VL_MT_STABLE { return m_name; } // * = Var name bool hasDType() const override { return true; } bool maybePointedTo() const override { return true; } const char* broken() const override { @@ -955,7 +955,7 @@ public: int widthAlignBytes() const override { return dtypep()->widthAlignBytes(); } int widthTotalBytes() const override { return dtypep()->widthTotalBytes(); } // METHODS - string name() const override { return m_name; } + string name() const override VL_MT_STABLE { return m_name; } bool maybePointedTo() const override { return true; } bool hasDType() const override { return true; } void name(const string& flag) override { m_name = flag; } @@ -1093,7 +1093,7 @@ public: } void dump(std::ostream& str = std::cout) const override; void dumpSmall(std::ostream& str) const override; - string name() const override { return m_name; } + string name() const override VL_MT_STABLE { return m_name; } string prettyDTypeName() const override { return subDTypep() ? prettyName(subDTypep()->name()) : prettyName(); } diff --git a/src/V3AstNodeExpr.h b/src/V3AstNodeExpr.h index 5e12b2bd1..575bac814 100644 --- a/src/V3AstNodeExpr.h +++ b/src/V3AstNodeExpr.h @@ -236,7 +236,7 @@ public: const char* broken() const override; void cloneRelink() override; void dump(std::ostream& str = std::cout) const override; - string name() const override { return m_name; } // * = Var name + string name() const override VL_MT_STABLE { return m_name; } // * = Var name bool isGateOptimizable() const override; string dotted() const { return m_dotted; } // * = Scope name or "" string inlinedDots() const { return m_inlinedDots; } @@ -474,7 +474,7 @@ public: const char* broken() const override; int instrCount() const override { return widthInstrs(); } void cloneRelink() override; - string name() const override { return m_name; } // * = Var name + string name() const override VL_MT_STABLE { return m_name; } // * = Var name void name(const string& name) override { m_name = name; } VAccess access() const { return m_access; } void access(const VAccess& flag) { m_access = flag; } // Avoid using this; Set in constructor @@ -532,7 +532,7 @@ public: } ASTGEN_MEMBERS_AstArg; bool hasDType() const override { return false; } - string name() const override { return m_name; } // * = Pin name, ""=go by number + string name() const override VL_MT_STABLE { return m_name; } // * = Pin name, ""=go by number void name(const string& name) override { m_name = name; } bool emptyConnectNoNext() const { return !exprp() && name() == "" && !nextp(); } @@ -610,7 +610,7 @@ public: this->addPinsp(pinsp); } ASTGEN_MEMBERS_AstCMethodHard; - string name() const override { return m_name; } // * = Var name + string name() const override VL_MT_STABLE { return m_name; } // * = Var name void name(const string& name) override { m_name = name; } bool same(const AstNode* samep) const override { const AstCMethodHard* asamep = static_cast(samep); @@ -689,7 +689,7 @@ public: } ASTGEN_MEMBERS_AstCellArrayRef; // ACCESSORS - string name() const override { return m_name; } // * = Array name + string name() const override VL_MT_STABLE { return m_name; } // * = Array name string emitVerilog() override { V3ERROR_NA_RETURN(""); } string emitC() override { V3ERROR_NA_RETURN(""); } @@ -710,7 +710,7 @@ public: } ASTGEN_MEMBERS_AstCellRef; // ACCESSORS - string name() const override { return m_name; } // * = Array name + string name() const override VL_MT_STABLE { return m_name; } // * = Array name string emitVerilog() override { V3ERROR_NA_RETURN(""); } string emitC() override { V3ERROR_NA_RETURN(""); } @@ -746,7 +746,7 @@ public: == static_cast(samep)->m_classOrPackageNodep); } void dump(std::ostream& str = std::cout) const override; - string name() const override { return m_name; } // * = Var name + string name() const override VL_MT_STABLE { return m_name; } // * = Var name AstNode* classOrPackageNodep() const { return m_classOrPackageNodep; } void classOrPackageNodep(AstNode* nodep) { m_classOrPackageNodep = nodep; } AstNodeModule* classOrPackagep() const; @@ -990,7 +990,7 @@ public: initWithNumber(); } ASTGEN_MEMBERS_AstConst; - string name() const override { return num().ascii(); } // * = Value + string name() const override VL_MT_STABLE { return num().ascii(); } // * = Value const V3Number& num() const VL_MT_SAFE { return m_num; } // * = Value V3Number& num() { return m_num; } // * = Value uint32_t toUInt() const { return num().toUInt(); } @@ -1058,7 +1058,7 @@ public: } ASTGEN_MEMBERS_AstEnumItemRef; void dump(std::ostream& str) const override; - string name() const override { return itemp()->name(); } + string name() const override VL_MT_STABLE { return itemp()->name(); } int instrCount() const override { return 0; } const char* broken() const override; void cloneRelink() override { @@ -1068,7 +1068,7 @@ public: const AstEnumItemRef* const sp = static_cast(samep); return itemp() == sp->itemp(); } - AstEnumItem* itemp() const { return m_itemp; } + AstEnumItem* itemp() const VL_MT_STABLE { return m_itemp; } string emitVerilog() override { V3ERROR_NA_RETURN(""); } string emitC() override { V3ERROR_NA_RETURN(""); } bool cleanOut() const override { return true; } @@ -1209,7 +1209,7 @@ public: this->filep(filep); } ASTGEN_MEMBERS_AstFScanF; - string name() const override { return m_text; } + string name() const override VL_MT_STABLE { return m_text; } string verilogKwd() const override { return "$fscanf"; } string emitVerilog() override { V3ERROR_NA_RETURN(""); } string emitC() override { V3ERROR_NA_RETURN(""); } @@ -1406,7 +1406,7 @@ public: string emitC() override { V3ERROR_NA_RETURN(""); } bool cleanOut() const override { return true; } int instrCount() const override { return widthInstrs(); } - string name() const override { return m_name; } // * = Var name + string name() const override VL_MT_STABLE { return m_name; } // * = Var name void name(const string& name) override { m_name = name; } bool index() const { return m_index; } }; @@ -1432,7 +1432,7 @@ public: void cloneRelink() override; const char* broken() const override; void dump(std::ostream& str) const override; - string name() const override { return m_name; } + string name() const override VL_MT_STABLE { return m_name; } void name(const string& name) override { m_name = name; } string emitVerilog() override { V3ERROR_NA_RETURN(""); } string emitC() override { V3ERROR_NA_RETURN(""); } @@ -1497,7 +1497,7 @@ public: } ASTGEN_MEMBERS_AstParseRef; void dump(std::ostream& str) const override; - string name() const override { return m_name; } // * = Var name + string name() const override VL_MT_STABLE { return m_name; } // * = Var name bool same(const AstNode* samep) const override { const AstParseRef* const asamep = static_cast(samep); return (expect() == asamep->expect() && m_name == asamep->m_name); @@ -1671,7 +1671,7 @@ public: addExprsp(exprsp); } ASTGEN_MEMBERS_AstSFormatF; - string name() const override { return m_text; } + string name() const override VL_MT_STABLE { return m_text; } int instrCount() const override { return INSTR_COUNT_PLI; } bool same(const AstNode* samep) const override { return text() == static_cast(samep)->text(); @@ -1706,7 +1706,7 @@ public: this->fromp(fromp); } ASTGEN_MEMBERS_AstSScanF; - string name() const override { return m_text; } + string name() const override VL_MT_STABLE { return m_text; } string verilogKwd() const override { return "$sscanf"; } string emitVerilog() override { V3ERROR_NA_RETURN(""); } string emitC() override { V3ERROR_NA_RETURN(""); } @@ -1891,7 +1891,7 @@ public: dtypep(nullptr); // V3Width will resolve } ASTGEN_MEMBERS_AstStructSel; - string name() const override { return m_name; } + string name() const override VL_MT_STABLE { return m_name; } void name(const string& name) override { m_name = name; } string emitVerilog() override { V3ERROR_NA_RETURN(""); } string emitC() override { V3ERROR_NA_RETURN(""); } @@ -2200,7 +2200,7 @@ public: void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { out.opCompareNN(lhs, rhs, m_ignoreCase); } - string name() const override { return m_ignoreCase ? "icompare" : "compare"; } + string name() const override VL_MT_STABLE { return m_ignoreCase ? "icompare" : "compare"; } string emitVerilog() override { return m_ignoreCase ? "%k(%l.icompare(%r))" : "%k(%l.compare(%r))"; } @@ -2424,7 +2424,7 @@ public: void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { out.opGetcN(lhs, rhs); } - string name() const override { return "getc"; } + string name() const override VL_MT_STABLE { return "getc"; } string emitVerilog() override { return "%k(%l.getc(%r))"; } string emitC() override { return "VL_GETC_N(%li,%ri)"; } string emitSimpleOperator() override { return ""; } @@ -4304,7 +4304,7 @@ public: const V3Number& ths) override { out.opPutcN(lhs, rhs, ths); } - string name() const override { return "putc"; } + string name() const override VL_MT_STABLE { return "putc"; } string emitVerilog() override { return "%k(%l.putc(%r,%t))"; } string emitC() override { return "VL_PUTC_N(%li,%ri,%ti)"; } string emitSimpleOperator() override { return ""; } @@ -4411,7 +4411,7 @@ public: const V3Number& ths) override { out.opSubstrN(lhs, rhs, ths); } - string name() const override { return "substr"; } + string name() const override VL_MT_STABLE { return "substr"; } string emitVerilog() override { return "%k(%l.substr(%r,%t))"; } string emitC() override { return "VL_SUBSTR_N(%li,%ri,%ti)"; } string emitSimpleOperator() override { return ""; } @@ -4488,7 +4488,7 @@ public: } ASTGEN_MEMBERS_AstAtoN; void numberOperate(V3Number& out, const V3Number& lhs) override { out.opAtoN(lhs, m_fmt); } - string name() const override { + string name() const override VL_MT_STABLE { switch (m_fmt) { case ATOI: return "atoi"; case ATOHEX: return "atohex"; diff --git a/src/V3AstNodeOther.h b/src/V3AstNodeOther.h index 72db0c8d0..ed0bf5098 100644 --- a/src/V3AstNodeOther.h +++ b/src/V3AstNodeOther.h @@ -48,7 +48,7 @@ protected: public: ASTGEN_MEMBERS_AstNodeBlock; void dump(std::ostream& str) const override; - string name() const override { return m_name; } // * = Block name + string name() const override VL_MT_STABLE { return m_name; } // * = Block name void name(const string& name) override { m_name = name; } bool unnamed() const { return m_unnamed; } bool isFirstInMyListOfStatements(AstNode* nodep) const override { return nodep == stmtsp(); } @@ -118,7 +118,7 @@ protected: public: ASTGEN_MEMBERS_AstNodeFTask; void dump(std::ostream& str = std::cout) const override; - string name() const override { return m_name; } // * = Var name + string name() const override VL_MT_STABLE { return m_name; } // * = Var name bool maybePointedTo() const override { return true; } bool isGateOptimizable() const override { return !((m_dpiExport || m_dpiImport) && !m_pure); } // {AstFunc only} op1 = Range output variable @@ -186,7 +186,7 @@ public: , m_name{name} {} ASTGEN_MEMBERS_AstNodeFile; void dump(std::ostream& str) const override; - string name() const override { return m_name; } + string name() const override VL_MT_STABLE { return m_name; } bool same(const AstNode* /*samep*/) const override { return true; } }; class AstNodeModule VL_NOT_FINAL : public AstNode { @@ -234,7 +234,7 @@ public: ASTGEN_MEMBERS_AstNodeModule; void dump(std::ostream& str) const override; bool maybePointedTo() const override { return true; } - string name() const override { return m_name; } + string name() const override VL_MT_STABLE { return m_name; } virtual bool timescaleMatters() const = 0; // ACCESSORS void name(const string& name) override { m_name = name; } @@ -373,7 +373,7 @@ public: this->addPasssp(passsp); } ASTGEN_MEMBERS_AstNodeCoverOrAssert; - string name() const override { return m_name; } // * = Var name + string name() const override VL_MT_STABLE { return m_name; } // * = Var name bool same(const AstNode* samep) const override { return samep->name() == name(); } void name(const string& name) override { m_name = name; } void dump(std::ostream& str = std::cout) const override; @@ -512,7 +512,7 @@ public: } ASTGEN_MEMBERS_AstActive; void dump(std::ostream& str = std::cout) const override; - string name() const override { return m_name; } + string name() const override VL_MT_STABLE { return m_name; } const char* broken() const override; void cloneRelink() override; // Statements are broken into pieces, as some must come before others. @@ -537,7 +537,7 @@ public: } ASTGEN_MEMBERS_AstBind; // ACCESSORS - string name() const override { return m_name; } // * = Bind Target name + string name() const override VL_MT_STABLE { return m_name; } // * = Bind Target name void name(const string& name) override { m_name = name; } }; class AstCFunc final : public AstNode { @@ -607,7 +607,7 @@ public: m_dpiTraceInit = false; } ASTGEN_MEMBERS_AstCFunc; - string name() const override { return m_name; } + string name() const override VL_MT_STABLE { return m_name; } const char* broken() const override; void cloneRelink() override; bool maybePointedTo() const override { return true; } @@ -702,7 +702,7 @@ public: , m_useType{useType} {} ASTGEN_MEMBERS_AstCUse; void dump(std::ostream& str = std::cout) const override; - string name() const override { return m_name; } + string name() const override VL_MT_STABLE { return m_name; } VUseType useType() const { return m_useType; } }; class AstCaseItem final : public AstNode { @@ -755,7 +755,7 @@ public: const char* broken() const override; bool maybePointedTo() const override { return true; } // ACCESSORS - string name() const override { return m_name; } // * = Cell name + string name() const override VL_MT_STABLE { return m_name; } // * = Cell name void name(const string& name) override { m_name = name; } string origName() const override { return m_origName; } // * = Original name void origName(const string& name) { m_origName = name; } @@ -794,7 +794,7 @@ public: void dump(std::ostream& str) const override; const char* broken() const override; // ACCESSORS - string name() const override { return m_name; } // * = Cell name + string name() const override VL_MT_STABLE { return m_name; } // * = Cell name string origModName() const { return m_origModName; } // * = modp()->origName() before inlining void name(const string& name) override { m_name = name; } void scopep(AstScope* scp) { m_scopep = scp; } @@ -845,7 +845,7 @@ public: } ASTGEN_MEMBERS_AstClocking; void dump(std::ostream& str) const override; - std::string name() const override { return m_name; } + std::string name() const override VL_MT_STABLE { return m_name; } bool isDefault() const { return m_isDefault; } bool isGlobal() const { return m_isGlobal; } }; @@ -916,7 +916,7 @@ public: , m_path{path} { this->rhsp(rhsp); } - string name() const override { return m_name; } // * = Scope name + string name() const override VL_MT_STABLE { return m_name; } // * = Scope name ASTGEN_MEMBERS_AstDefParam; bool same(const AstNode*) const override { return true; } string path() const { return m_path; } @@ -934,7 +934,7 @@ public: , m_name{vname} , m_cname{cname} {} ASTGEN_MEMBERS_AstDpiExport; - string name() const override { return m_name; } + string name() const override VL_MT_STABLE { return m_name; } void name(const string& name) override { m_name = name; } string cname() const { return m_cname; } void cname(const string& cname) { m_cname = cname; } @@ -995,7 +995,7 @@ public: BROKEN_RTN(!m_depGraphp); return nullptr; } - string name() const override { return m_name; } + string name() const override VL_MT_STABLE { return m_name; } V3Graph* depGraphp() { return m_depGraphp; } const V3Graph* depGraphp() const { return m_depGraphp; } }; @@ -1033,7 +1033,7 @@ public: AstIntfRef(FileLine* fl, const string& name) : ASTGEN_SUPER_IntfRef(fl) , m_name{name} {} - string name() const override { return m_name; } + string name() const override VL_MT_STABLE { return m_name; } ASTGEN_MEMBERS_AstIntfRef; }; class AstMTaskBody final : public AstNode { @@ -1070,7 +1070,7 @@ public: , m_name{name} { this->addVarsp(varsp); } - string name() const override { return m_name; } + string name() const override VL_MT_STABLE { return m_name; } bool maybePointedTo() const override { return true; } ASTGEN_MEMBERS_AstModport; }; @@ -1092,7 +1092,7 @@ public: const char* broken() const override; void cloneRelink() override; void dump(std::ostream& str) const override; - string name() const override { return m_name; } + string name() const override VL_MT_STABLE { return m_name; } bool isImport() const { return !m_export; } bool isExport() const { return m_export; } AstNodeFTask* ftaskp() const { return m_ftaskp; } // [After Link] Pointer to variable @@ -1115,7 +1115,7 @@ public: const char* broken() const override; void cloneRelink() override; void dump(std::ostream& str) const override; - string name() const override { return m_name; } + string name() const override VL_MT_STABLE { return m_name; } void direction(const VDirection& flag) { m_direction = flag; } VDirection direction() const { return m_direction; } AstVar* varp() const { return m_varp; } // [After Link] Pointer to variable @@ -1149,7 +1149,7 @@ public: ASTGEN_MEMBERS_AstNetlist; const char* broken() const override; void cloneRelink() override { V3ERROR_NA; } - string name() const override { return "$root"; } + string name() const override VL_MT_STABLE { return "$root"; } void dump(std::ostream& str) const override; AstNodeModule* topModulep() const { // Top module in hierarchy return modulesp(); // First one in the list, for now @@ -1198,7 +1198,7 @@ public: const char* broken() const override; void cloneRelink() override; void dump(std::ostream& str) const override; - string name() const override { return m_name; } + string name() const override VL_MT_STABLE { return m_name; } AstPackage* packagep() const { return m_packagep; } void packagep(AstPackage* nodep) { m_packagep = nodep; } }; @@ -1224,7 +1224,7 @@ public: const char* broken() const override; void cloneRelink() override; void dump(std::ostream& str) const override; - string name() const override { return m_name; } + string name() const override VL_MT_STABLE { return m_name; } AstPackage* packagep() const { return m_packagep; } void packagep(AstPackage* nodep) { m_packagep = nodep; } }; @@ -1250,7 +1250,7 @@ public: ASTGEN_MEMBERS_AstPin; void dump(std::ostream& str) const override; const char* broken() const override; - string name() const override { return m_name; } // * = Pin name, ""=go by number + string name() const override VL_MT_STABLE { return m_name; } // * = Pin name, ""=go by number void name(const string& name) override { m_name = name; } string prettyOperatorName() const override; bool dotStar() const { return name() == ".*"; } // Fake name for .* connections until linked @@ -1278,7 +1278,7 @@ public: , m_pinNum{pinnum} , m_name{name} {} ASTGEN_MEMBERS_AstPort; - string name() const override { return m_name; } // * = Port name + string name() const override VL_MT_STABLE { return m_name; } // * = Port name int pinNum() const { return m_pinNum; } // * = Pin number, for order based instantiation }; class AstPragma final : public AstNode { @@ -1356,7 +1356,7 @@ public: void cloneRelink() override; const char* broken() const override; bool maybePointedTo() const override { return true; } - string name() const override { return m_name; } // * = Scope name + string name() const override VL_MT_STABLE { return m_name; } // * = Scope name void name(const string& name) override { m_name = name; } void dump(std::ostream& str) const override; string nameDotless() const; @@ -1548,7 +1548,7 @@ public: return dtypep() ? dtypep() : childDTypep(); } // METHODS - string name() const override { return m_name; } + string name() const override VL_MT_STABLE { return m_name; } bool maybePointedTo() const override { return true; } bool hasDType() const override { return true; } void name(const string& flag) override { m_name = flag; } @@ -1568,7 +1568,7 @@ public: , m_name{name} {} ASTGEN_MEMBERS_AstTypedefFwd; // METHODS - string name() const override { return m_name; } + string name() const override VL_MT_STABLE { return m_name; } bool maybePointedTo() const override { return true; } }; class AstUdpTable final : public AstNode { @@ -1588,7 +1588,7 @@ public: : ASTGEN_SUPER_UdpTableLine(fl) , m_text{text} {} ASTGEN_MEMBERS_AstUdpTableLine; - string name() const override { return m_text; } + string name() const override VL_MT_STABLE { return m_text; } string text() const { return m_text; } }; class AstVar final : public AstNode { @@ -1758,7 +1758,7 @@ public: } ASTGEN_MEMBERS_AstVar; void dump(std::ostream& str) const override; - string name() const override VL_MT_SAFE { return m_name; } // * = Var name + string name() const override VL_MT_STABLE VL_MT_SAFE { return m_name; } // * = Var name bool hasDType() const override { return true; } bool maybePointedTo() const override { return true; } string origName() const override { return m_origName; } // * = Original name @@ -1998,7 +1998,7 @@ public: return nullptr; } bool maybePointedTo() const override { return true; } - string name() const override { return scopep()->name() + "->" + varp()->name(); } + string name() const override VL_MT_STABLE { return scopep()->name() + "->" + varp()->name(); } void dump(std::ostream& str) const override; bool hasDType() const override { return true; } AstVar* varp() const { return m_varp; } // [After Link] Pointer to variable @@ -2452,7 +2452,7 @@ public: , m_name{name} , m_showAt{showAt} {} ASTGEN_MEMBERS_AstComment; - string name() const override { return m_name; } // * = Text + string name() const override VL_MT_STABLE { return m_name; } // * = Text bool same(const AstNode* samep) const override { return true; } // Ignore name in comments virtual bool showAt() const { return m_showAt; } }; @@ -2593,7 +2593,7 @@ public: : ASTGEN_SUPER_Disable(fl) , m_name{name} {} ASTGEN_MEMBERS_AstDisable; - string name() const override { return m_name; } // * = Block name + string name() const override VL_MT_STABLE { return m_name; } // * = Block name void name(const string& flag) override { m_name = flag; } bool isBrancher() const override { return true; // SPECIAL: We don't process code after breaks @@ -2884,7 +2884,7 @@ public: : ASTGEN_SUPER_PrintTimeScale(fl) {} ASTGEN_MEMBERS_AstPrintTimeScale; void name(const string& name) override { m_name = name; } - string name() const override { return m_name; } // * = Var name + string name() const override VL_MT_STABLE { return m_name; } // * = Var name void dump(std::ostream& str) const override; string verilogKwd() const override { return "$printtimescale"; } bool isGateOptimizable() const override { return false; } @@ -3103,7 +3103,7 @@ public: void dump(std::ostream& str) const override; int instrCount() const override { return 100; } // Large... ASTGEN_MEMBERS_AstTraceDecl; - string name() const override { return m_showname; } + string name() const override VL_MT_STABLE { return m_showname; } bool maybePointedTo() const override { return true; } bool hasDType() const override { return true; } bool same(const AstNode* samep) const override { return false; } diff --git a/src/V3Config.cpp b/src/V3Config.cpp index b6ede32c0..c6fb382c3 100644 --- a/src/V3Config.cpp +++ b/src/V3Config.cpp @@ -40,25 +40,31 @@ template class V3ConfigWildcardResolver final { using Map = std::map; - Map m_mapWildcard; // Wildcard strings to entities - Map m_mapResolved; // Resolved strings to converged entities + mutable VerilatedMutex m_mutex; // protects members + Map m_mapWildcard VL_GUARDED_BY(m_mutex); // Wildcard strings to entities + Map m_mapResolved VL_GUARDED_BY(m_mutex); // Resolved strings to converged entities public: V3ConfigWildcardResolver() = default; ~V3ConfigWildcardResolver() = default; /// Update into maps from other - void update(const V3ConfigWildcardResolver& other) { + void update(const V3ConfigWildcardResolver& other) VL_MT_SAFE_EXCLUDES(m_mutex) + VL_EXCLUDES(other.m_mutex) { + VerilatedLockGuard lock{m_mutex}; + VerilatedLockGuard otherLock{other.m_mutex}; for (const auto& itr : other.m_mapResolved) m_mapResolved[itr.first].update(itr.second); for (const auto& itr : other.m_mapWildcard) m_mapWildcard[itr.first].update(itr.second); } // Access and create a (wildcard) entity - T& at(const string& name) { + T& at(const string& name) VL_MT_SAFE_EXCLUDES(m_mutex) { + VerilatedLockGuard lock{m_mutex}; // Don't store into wildcards if the name is not a wildcard string return m_mapWildcard[name]; } // Access an entity and resolve wildcards that match it - T* resolve(const string& name) { + T* resolve(const string& name) VL_MT_SAFE_EXCLUDES(m_mutex) { + VerilatedLockGuard lock{m_mutex}; // Lookup if it was resolved before, typically not auto it = m_mapResolved.find(name); if (VL_UNLIKELY(it != m_mapResolved.end())) return &it->second; @@ -78,7 +84,10 @@ public: return newp; } // Flush on update - void flush() { m_mapResolved.clear(); } + void flush() VL_MT_SAFE_EXCLUDES(m_mutex) { + VerilatedLockGuard lock{m_mutex}; + m_mapResolved.clear(); + } }; // Only public_flat_rw has the sensitity tree diff --git a/src/V3EmitCBase.h b/src/V3EmitCBase.h index ebb7ed3f4..a183b4e78 100644 --- a/src/V3EmitCBase.h +++ b/src/V3EmitCBase.h @@ -63,7 +63,9 @@ public: void putsQuoted(const string& str) { ofp()->putsQuoted(str); } void ensureNewLine() { ofp()->ensureNewLine(); } bool optSystemC() { return v3Global.opt.systemC(); } - static string protect(const string& name) { return VIdProtect::protectIf(name, true); } + static string protect(const string& name) VL_MT_SAFE { + return VIdProtect::protectIf(name, true); + } static string protectIf(const string& name, bool doIt) { return VIdProtect::protectIf(name, doIt); } @@ -84,7 +86,7 @@ public: return symClassName() + "* const __restrict vlSymsp VL_ATTR_UNUSED = vlSelf->vlSymsp;\n"; } static string funcNameProtect(const AstCFunc* nodep, const AstNodeModule* modp = nullptr); - static string prefixNameProtect(const AstNode* nodep) { // C++ name with prefix + static string prefixNameProtect(const AstNode* nodep) VL_MT_SAFE { // C++ name with prefix return v3Global.opt.modPrefix() + "_" + protect(nodep->name()); } static string topClassName() VL_MT_SAFE { // Return name of top wrapper module diff --git a/src/V3File.cpp b/src/V3File.cpp index 6ae1507e0..5fd603d6e 100644 --- a/src/V3File.cpp +++ b/src/V3File.cpp @@ -108,7 +108,8 @@ class V3FileDependImp final { }; // MEMBERS - std::set m_filenameSet; // Files generated (elim duplicates) + VerilatedMutex m_mutex; // Protects members + std::set m_filenameSet VL_GUARDED_BY(m_mutex); // Files generated (elim duplicates) std::set m_filenameList; // Files sourced/generated static string stripQuotes(const string& in) { @@ -121,7 +122,8 @@ class V3FileDependImp final { public: // ACCESSOR METHODS - void addSrcDepend(const string& filename) { + void addSrcDepend(const string& filename) VL_MT_SAFE_EXCLUDES(m_mutex) { + const VerilatedLockGuard lock{m_mutex}; const auto itFoundPair = m_filenameSet.insert(filename); if (itFoundPair.second) { DependFile df{filename, false}; @@ -129,7 +131,8 @@ public: m_filenameList.insert(df); } } - void addTgtDepend(const string& filename) { + void addTgtDepend(const string& filename) VL_MT_SAFE_EXCLUDES(m_mutex) { + const VerilatedLockGuard lock{m_mutex}; const auto itFoundPair = m_filenameSet.insert(filename); if (itFoundPair.second) m_filenameList.insert(DependFile{filename, true}); } @@ -297,8 +300,8 @@ bool V3FileDependImp::checkTimes(const string& filename, const string& cmdlineIn //###################################################################### // V3File -void V3File::addSrcDepend(const string& filename) { dependImp.addSrcDepend(filename); } -void V3File::addTgtDepend(const string& filename) { dependImp.addTgtDepend(filename); } +void V3File::addSrcDepend(const string& filename) VL_MT_SAFE { dependImp.addSrcDepend(filename); } +void V3File::addTgtDepend(const string& filename) VL_MT_SAFE { dependImp.addTgtDepend(filename); } void V3File::writeDepend(const string& filename) { dependImp.writeDepend(filename); } std::vector V3File::getAllDeps() { return dependImp.getAllDeps(); } void V3File::writeTimes(const string& filename, const string& cmdlineIn) { @@ -954,12 +957,13 @@ void V3OutCFile::putsGuard() { class VIdProtectImp final { // MEMBERS + VerilatedMutex m_mutex; // Protects members std::map m_nameMap; // Map of old name into new name - std::unordered_set m_newIdSet; // Which new names exist + std::unordered_set m_newIdSet VL_GUARDED_BY(m_mutex); // Which new names exist protected: // CONSTRUCTORS friend class VIdProtect; - static VIdProtectImp& singleton() { + static VIdProtectImp& singleton() VL_MT_SAFE { static VIdProtectImp s; return s; } @@ -973,8 +977,9 @@ public: } ~VIdProtectImp() = default; // METHODS - string passthru(const string& old) { + string passthru(const string& old) VL_MT_SAFE_EXCLUDES(m_mutex) { if (!v3Global.opt.protectIds()) return old; + const VerilatedLockGuard lock{m_mutex}; const auto it = m_nameMap.find(old); if (it != m_nameMap.end()) { // No way to go back and correct the older crypt name @@ -986,8 +991,9 @@ public: } return old; } - string protectIf(const string& old, bool doIt) { + string protectIf(const string& old, bool doIt) VL_MT_SAFE_EXCLUDES(m_mutex) { if (!v3Global.opt.protectIds() || old.empty() || !doIt) return old; + const VerilatedLockGuard lock{m_mutex}; const auto it = m_nameMap.find(old); if (it != m_nameMap.end()) { return it->second; @@ -1017,7 +1023,7 @@ public: return out; } } - string protectWordsIf(const string& old, bool doIt) { + string protectWordsIf(const string& old, bool doIt) VL_MT_SAFE { // Split at " " (for traces), "." (for scopes), "->", "(", "&", ")" (for self pointers) if (!(doIt && v3Global.opt.protectIds())) return old; string out; @@ -1056,7 +1062,7 @@ public: private: void trySep(const string& old, string::size_type start, const string& trySep, - string::size_type& posr, string& separatorr) { + string::size_type& posr, string& separatorr) VL_PURE { const string::size_type trypos = old.find(trySep, start); if (trypos != string::npos) { if (posr == string::npos || (posr > trypos)) { @@ -1067,10 +1073,10 @@ private: } }; -string VIdProtect::protectIf(const string& old, bool doIt) { +string VIdProtect::protectIf(const string& old, bool doIt) VL_MT_SAFE { return VIdProtectImp::singleton().protectIf(old, doIt); } -string VIdProtect::protectWordsIf(const string& old, bool doIt) { +string VIdProtect::protectWordsIf(const string& old, bool doIt) VL_MT_SAFE { return VIdProtectImp::singleton().protectWordsIf(old, doIt); } void VIdProtect::writeMapFile(const string& filename) { diff --git a/src/V3File.h b/src/V3File.h index 2c1d34850..3f1cbebc2 100644 --- a/src/V3File.h +++ b/src/V3File.h @@ -61,8 +61,8 @@ public: } // Dependencies - static void addSrcDepend(const string& filename); - static void addTgtDepend(const string& filename); + static void addSrcDepend(const string& filename) VL_MT_SAFE; + static void addTgtDepend(const string& filename) VL_MT_SAFE; static void writeDepend(const string& filename); static std::vector getAllDeps(); static void writeTimes(const string& filename, const string& cmdlineIn); @@ -318,10 +318,10 @@ class VIdProtect final { public: // METHODS // Rename to a new encoded string (unless earlier passthru'ed) - static string protect(const string& old) { return protectIf(old, true); } - static string protectIf(const string& old, bool doIt = 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; // Rename words to a new encoded string - static string protectWordsIf(const string& old, bool doIt = true); + static string protectWordsIf(const string& old, bool doIt = true) VL_MT_SAFE; // Write map of renames to output file static void writeMapFile(const string& filename); }; diff --git a/src/V3FileLine.cpp b/src/V3FileLine.cpp index 8f7362b38..839bd4573 100644 --- a/src/V3FileLine.cpp +++ b/src/V3FileLine.cpp @@ -87,7 +87,9 @@ void FileLineSingleton::fileNameNumMapDumpXml(std::ostream& os) { os << "\n"; } -FileLineSingleton::msgEnSetIdx_t FileLineSingleton::addMsgEnBitSet(const MsgEnBitSet& bitSet) { +FileLineSingleton::msgEnSetIdx_t FileLineSingleton::addMsgEnBitSet(const MsgEnBitSet& bitSet) + VL_MT_SAFE_EXCLUDES(m_mutex) { + VerilatedLockGuard lock{m_mutex}; const auto pair = m_internedMsgEnIdxs.emplace(bitSet, 0); msgEnSetIdx_t& idx = pair.first->second; if (pair.second) { @@ -100,7 +102,7 @@ FileLineSingleton::msgEnSetIdx_t FileLineSingleton::addMsgEnBitSet(const MsgEnBi return idx; } -FileLineSingleton::msgEnSetIdx_t FileLineSingleton::defaultMsgEnIndex() { +FileLineSingleton::msgEnSetIdx_t FileLineSingleton::defaultMsgEnIndex() VL_MT_SAFE { MsgEnBitSet msgEnBitSet; for (int i = V3ErrorCode::EC_MIN; i < V3ErrorCode::_ENUM_MAX; ++i) { msgEnBitSet.set(i, !V3ErrorCode{i}.defaultsOff()); diff --git a/src/V3FileLine.h b/src/V3FileLine.h index 96a52526c..6f66277c1 100644 --- a/src/V3FileLine.h +++ b/src/V3FileLine.h @@ -20,6 +20,8 @@ #include "config_build.h" #include "verilatedos.h" +#include "verilated_threads.h" + #include "V3Error.h" #include "V3LangCode.h" @@ -50,12 +52,13 @@ class FileLineSingleton final { using MsgEnBitSet = std::bitset; // MEMBERS + VerilatedMutex m_mutex; // protects members std::map m_namemap; // filenameno for each filename std::deque m_names; // filename text for each filenameno std::deque m_languages; // language for each filenameno // Map from flag set to the index in m_internedMsgEns for interning - std::unordered_map m_internedMsgEnIdxs; + std::unordered_map m_internedMsgEnIdxs VL_GUARDED_BY(m_mutex); // Interned message enablement flag sets std::vector m_internedMsgEns; @@ -78,9 +81,9 @@ class FileLineSingleton final { static string filenameLetters(fileNameIdx_t fileno) VL_PURE; // Add given bitset to the interned bitsets, return interned index - msgEnSetIdx_t addMsgEnBitSet(const MsgEnBitSet& bitSet); + msgEnSetIdx_t addMsgEnBitSet(const MsgEnBitSet& bitSet) VL_MT_SAFE_EXCLUDES(m_mutex); // Add index of default bitset - msgEnSetIdx_t defaultMsgEnIndex(); + msgEnSetIdx_t defaultMsgEnIndex() VL_MT_SAFE; // Set bitIdx to value in bitset at interned index setIdx, return interned index of result msgEnSetIdx_t msgEnSetBit(msgEnSetIdx_t setIdx, size_t bitIdx, bool value); // Return index to intersection set diff --git a/src/V3Gate.cpp b/src/V3Gate.cpp index 3b450856f..4c4ef2e7d 100644 --- a/src/V3Gate.cpp +++ b/src/V3Gate.cpp @@ -134,7 +134,9 @@ public: ~GateVarVertex() override = default; // ACCESSORS AstVarScope* varScp() const { return m_varScp; } - string name() const override { return (cvtToHex(m_varScp) + " " + varScp()->name()); } + string name() const override VL_MT_STABLE { + return (cvtToHex(m_varScp) + " " + varScp()->name()); + } string dotColor() const override { return "blue"; } bool isTop() const { return m_isTop; } void setIsTop() { m_isTop = true; } @@ -174,7 +176,9 @@ public: , m_slow{slow} {} ~GateLogicVertex() override = default; // ACCESSORS - string name() const override { return (cvtToHex(m_nodep) + "@" + scopep()->prettyName()); } + string name() const override VL_MT_STABLE { + return (cvtToHex(m_nodep) + "@" + scopep()->prettyName()); + } string dotColor() const override { return "purple"; } FileLine* fileline() const override { return nodep()->fileline(); } AstNode* nodep() const { return m_nodep; } diff --git a/src/V3Global.h b/src/V3Global.h index 0537f534c..db6dc04ba 100644 --- a/src/V3Global.h +++ b/src/V3Global.h @@ -98,7 +98,7 @@ class V3Global final { VWidthMinUsage m_widthMinUsage = VWidthMinUsage::LINT_WIDTH; // What AstNode::widthMin() is used for - int m_debugFileNumber = 0; // Number to append to debug files created + std::atomic_int m_debugFileNumber{0}; // Number to append to debug files created bool m_assertDTypesResolved = false; // Tree should have dtypep()'s bool m_assertScoped = false; // Tree is scoped bool m_constRemoveXs = false; // Const needs to strip any Xs @@ -143,7 +143,7 @@ public: void widthMinUsage(const VWidthMinUsage& flag) { m_widthMinUsage = flag; } bool constRemoveXs() const { return m_constRemoveXs; } void constRemoveXs(bool flag) { m_constRemoveXs = flag; } - string debugFilename(const string& nameComment, int newNumber = 0) VL_MT_SAFE; + string debugFilename(const string& nameComment, int newNumber = 0); static string digitsFilename(int number); bool needTraceDumper() const { return m_needTraceDumper; } void needTraceDumper(bool flag) { m_needTraceDumper = flag; } diff --git a/src/V3GraphTest.cpp b/src/V3GraphTest.cpp index cb48888a6..8a9637cdf 100644 --- a/src/V3GraphTest.cpp +++ b/src/V3GraphTest.cpp @@ -60,7 +60,7 @@ public: , m_name{name} {} ~V3GraphTestVertex() override = default; // ACCESSORS - string name() const override { return m_name; } + string name() const override VL_MT_STABLE { return m_name; } }; class V3GraphTestVarVertex final : public V3GraphTestVertex { diff --git a/src/V3LinkCells.cpp b/src/V3LinkCells.cpp index 20f5e545c..f30bb9601 100644 --- a/src/V3LinkCells.cpp +++ b/src/V3LinkCells.cpp @@ -59,8 +59,8 @@ public: : V3GraphVertex{graphp} , m_modp{modp} {} ~LinkCellsVertex() override = default; - AstNodeModule* modp() const { return m_modp; } - string name() const override { return modp()->name(); } + AstNodeModule* modp() const VL_MT_STABLE { return m_modp; } + string name() const override VL_MT_STABLE { return modp()->name(); } FileLine* fileline() const override { return modp()->fileline(); } // Recursive modules get space for maximum recursion uint32_t rankAdder() const override { @@ -73,7 +73,7 @@ public: explicit LibraryVertex(V3Graph* graphp) : V3GraphVertex{graphp} {} ~LibraryVertex() override = default; - string name() const override { return "*LIBRARY*"; } + string name() const override VL_MT_STABLE { return "*LIBRARY*"; } }; void LinkCellsGraph::loopsMessageCb(V3GraphVertex* vertexp) { diff --git a/src/V3Number.cpp b/src/V3Number.cpp index a74d7a64d..7defef9a5 100644 --- a/src/V3Number.cpp +++ b/src/V3Number.cpp @@ -498,7 +498,7 @@ V3Number& V3Number::setMask(int nbits) { //====================================================================== // ACCESSORS - as strings -string V3Number::ascii(bool prefixed, bool cleanVerilog) const { +string V3Number::ascii(bool prefixed, bool cleanVerilog) const VL_MT_SAFE { std::ostringstream out; if (is1Step()) { @@ -1050,7 +1050,7 @@ bool V3Number::isEqAllOnes(int optwidth) const { } return true; } -bool V3Number::isFourState() const { +bool V3Number::isFourState() const VL_MT_SAFE { if (isDouble() || isString()) return false; for (int i = 0; i < words(); ++i) { if (m_data.num()[i].m_valueX) return true; diff --git a/src/V3Number.h b/src/V3Number.h index 2afc9354f..b94a212fb 100644 --- a/src/V3Number.h +++ b/src/V3Number.h @@ -583,7 +583,7 @@ public: V3Number& setMask(int nbits); // IE if nbits=1, then 0b1, if 2->0b11, if 3->0b111 etc // ACCESSORS - string ascii(bool prefixed = true, bool cleanVerilog = false) const; + string ascii(bool prefixed = true, bool cleanVerilog = false) const VL_MT_SAFE; string displayed(AstNode* nodep, const string& vformat) const VL_MT_SAFE; static bool displayedFmtLegal(char format, bool isScan); // Is this a valid format letter? int width() const VL_MT_SAFE { return m_data.width(); } @@ -615,7 +615,7 @@ public: bool isNegative() const { return !isString() && bitIs1(width() - 1); } bool is1Step() const VL_MT_SAFE { return m_data.m_is1Step; } bool isNull() const VL_MT_SAFE { return m_data.m_isNull; } - bool isFourState() const; + bool isFourState() const VL_MT_SAFE; bool hasZ() const { if (isString()) return false; for (int i = 0; i < words(); i++) { diff --git a/src/V3Options.cpp b/src/V3Options.cpp index 96996d58c..ea3fcf25f 100644 --- a/src/V3Options.cpp +++ b/src/V3Options.cpp @@ -880,7 +880,9 @@ string V3Options::version() VL_PURE { return ver; } -string V3Options::protectKeyDefaulted() { +string V3Options::protectKeyDefaulted() VL_MT_SAFE { + static VerilatedMutex mutex; + const VerilatedLockGuard lock{mutex}; if (m_protectKey.empty()) { // Create a key with a human-readable symbol-like name. // This conversion drops ~2 bits of entropy out of 256, shouldn't matter. diff --git a/src/V3Options.h b/src/V3Options.h index 26a41f712..7e6b639b3 100644 --- a/src/V3Options.h +++ b/src/V3Options.h @@ -573,7 +573,7 @@ public: string prefix() const VL_MT_SAFE { return m_prefix; } // Not just called protectKey() to avoid bugs of not using protectKeyDefaulted() bool protectKeyProvided() const { return !m_protectKey.empty(); } - string protectKeyDefaulted(); // Set default key if not set by user + string protectKeyDefaulted() VL_MT_SAFE; // Set default key if not set by user string topModule() const { return m_topModule; } string unusedRegexp() const { return m_unusedRegexp; } string waiverOutput() const { return m_waiverOutput; } diff --git a/src/V3OrderGraph.h b/src/V3OrderGraph.h index 5cc0ea85b..c1e3f2a91 100644 --- a/src/V3OrderGraph.h +++ b/src/V3OrderGraph.h @@ -159,7 +159,7 @@ public: AstSenTree* hybridp() const { return m_hybridp; } // LCOV_EXCL_START // Debug code - string name() const override { + string name() const override VL_MT_STABLE { return (cvtToHex(m_nodep) + "\\n " + cvtToStr(nodep()->typeName())); } string dotShape() const override { return VN_IS(m_nodep, Active) ? "doubleoctagon" : "rect"; } @@ -182,7 +182,7 @@ public: // LCOV_EXCL_START // Debug code string dotShape() const override final { return "ellipse"; } virtual string nameSuffix() const = 0; - string name() const override final { + string name() const override final VL_MT_STABLE { return cvtToHex(m_vscp) + " " + nameSuffix() + "\\n " + m_vscp->name(); } // LCOV_EXCL_STOP diff --git a/src/V3OrderMoveGraph.h b/src/V3OrderMoveGraph.h index c0187a68f..622ffd5d9 100644 --- a/src/V3OrderMoveGraph.h +++ b/src/V3OrderMoveGraph.h @@ -64,7 +64,7 @@ public: } } - string name() const override { + string name() const override VL_MT_STABLE { string nm; if (VL_UNCOVERABLE(!logicp())) { // Avoid crash when debugging nm = "nul"; // LCOV_EXCL_LINE diff --git a/src/V3Os.cpp b/src/V3Os.cpp index 7a4722839..377e3594f 100644 --- a/src/V3Os.cpp +++ b/src/V3Os.cpp @@ -28,6 +28,8 @@ #include "config_build.h" #include "verilatedos.h" +#include "verilated_threads.h" + // Limited V3 headers here - this is a base class for Vlc etc #include "V3Os.h" #include "V3String.h" @@ -286,7 +288,7 @@ uint64_t V3Os::rand64(std::array& stater) { return result; } -string V3Os::trueRandom(size_t size) { +string V3Os::trueRandom(size_t size) VL_MT_SAFE { string result(size, '\xFF'); char* const data = const_cast(result.data()); // Note: std::string.data() returns a non-const Char* from C++17 onwards. diff --git a/src/V3Os.h b/src/V3Os.h index 4300417fd..4f4d44bb9 100644 --- a/src/V3Os.h +++ b/src/V3Os.h @@ -59,7 +59,7 @@ public: // METHODS (random) static uint64_t rand64(std::array& stater); - static string trueRandom(size_t size); + static string trueRandom(size_t size) VL_MT_SAFE; // METHODS (time & performance) static void u_sleep(int64_t usec); ///< Sleep for a given number of microseconds. diff --git a/src/V3Partition.cpp b/src/V3Partition.cpp index 82b41ca32..45976fe76 100644 --- a/src/V3Partition.cpp +++ b/src/V3Partition.cpp @@ -321,7 +321,7 @@ public: void checkRelativesCp(GraphWay way) const; - string name() const override { + string name() const override VL_MT_STABLE { // Display forward and reverse critical path costs. This gives a quick // read on whether graph partitioning looks reasonable or bad. std::ostringstream out; diff --git a/src/V3PartitionGraph.h b/src/V3PartitionGraph.h index fc16c81c6..b83679a06 100644 --- a/src/V3PartitionGraph.h +++ b/src/V3PartitionGraph.h @@ -85,7 +85,7 @@ public: // If this MTask maps to a C function, this should be the name return std::string{"__Vmtask"} + "__" + cvtToStr(m_id); } - string name() const override { return std::string{"mt"} + cvtToStr(id()); } + string name() const override VL_MT_STABLE { return std::string{"mt"} + cvtToStr(id()); } string hashName() const { return m_hashName; } void hashName(const string& name) { m_hashName = name; } void dump(std::ostream& str) const { diff --git a/src/V3SchedAcyclic.cpp b/src/V3SchedAcyclic.cpp index bed28d66d..ac9bec353 100644 --- a/src/V3SchedAcyclic.cpp +++ b/src/V3SchedAcyclic.cpp @@ -76,7 +76,7 @@ public: AstScope* scopep() const { return m_scopep; } // LCOV_EXCL_START // Debug code - string name() const override { return m_logicp->fileline()->ascii(); }; + string name() const override VL_MT_STABLE { return m_logicp->fileline()->ascii(); }; string dotShape() const override { return "rectangle2"; } // LCOV_EXCL_STOP }; @@ -93,7 +93,7 @@ public: V3GraphVertex* clone(V3Graph* graphp) const override { return new VarVertex{graphp, vscp()}; } // LCOV_EXCL_START // Debug code - string name() const override { return m_vscp->name(); } + string name() const override VL_MT_STABLE { return m_vscp->name(); } string dotShape() const override { return "ellipse"; } string dotColor() const override { return "blue"; } // LCOV_EXCL_STOP diff --git a/src/V3SchedPartition.cpp b/src/V3SchedPartition.cpp index 0234dab01..849ff16e7 100644 --- a/src/V3SchedPartition.cpp +++ b/src/V3SchedPartition.cpp @@ -89,7 +89,7 @@ public: AstNode* logicp() const { return m_logicp; } // LCOV_EXCL_START // Debug code - string name() const override { + string name() const override VL_MT_STABLE { return m_logicp->typeName() + ("\n" + m_logicp->fileline()->ascii()); }; string dotShape() const override { return "rectangle"; } @@ -105,7 +105,7 @@ public: , m_vscp{vscp} {} // LCOV_EXCL_START // Debug code - string name() const override { return m_vscp->name(); } + string name() const override VL_MT_STABLE { return m_vscp->name(); } string dotShape() const override { return m_vscp->scopep()->isTop() && m_vscp->varp()->isNonOutput() ? "invhouse" : "ellipse"; } diff --git a/src/V3SchedReplicate.cpp b/src/V3SchedReplicate.cpp index 0564bb60d..7db10cabf 100644 --- a/src/V3SchedReplicate.cpp +++ b/src/V3SchedReplicate.cpp @@ -109,7 +109,7 @@ public: RegionFlags assignedRegion() const { return m_assignedRegion; } // For graph dumping - string name() const override { return m_logicp->fileline()->ascii(); }; + string name() const override VL_MT_STABLE { return m_logicp->fileline()->ascii(); }; string dotShape() const override { return "rectangle"; } }; @@ -134,7 +134,7 @@ public: AstScope* scopep() const { return m_vscp->scopep(); } // For graph dumping - string name() const override { return m_vscp->name(); } + string name() const override VL_MT_STABLE { return m_vscp->name(); } string dotShape() const override { return varp()->isPrimaryInish() ? "invhouse" : "ellipse"; } }; diff --git a/src/V3Split.cpp b/src/V3Split.cpp index db8a8da73..0c135d3e9 100644 --- a/src/V3Split.cpp +++ b/src/V3Split.cpp @@ -109,7 +109,9 @@ protected: // ACCESSORS // Do not make accessor for nodep(), It may change due to // reordering a lower block, but we don't repair it - string name() const override { return cvtToHex(m_nodep) + ' ' + m_nodep->prettyTypeName(); } + string name() const override VL_MT_STABLE { + return cvtToHex(m_nodep) + ' ' + m_nodep->prettyTypeName(); + } FileLine* fileline() const override { return nodep()->fileline(); } public: @@ -121,7 +123,7 @@ public: explicit SplitPliVertex(V3Graph* graphp, AstNode* nodep) : SplitNodeVertex{graphp, nodep} {} ~SplitPliVertex() override = default; - string name() const override { return "*PLI*"; } + string name() const override VL_MT_STABLE { return "*PLI*"; } string dotColor() const override { return "green"; } }; @@ -146,7 +148,7 @@ public: SplitVarPostVertex(V3Graph* graphp, AstNode* nodep) : SplitNodeVertex{graphp, nodep} {} ~SplitVarPostVertex() override = default; - string name() const override { return string("POST ") + SplitNodeVertex::name(); } + string name() const override VL_MT_STABLE { return string("POST ") + SplitNodeVertex::name(); } string dotColor() const override { return "CadetBlue"; } }; diff --git a/src/V3Task.cpp b/src/V3Task.cpp index 500d8e6dc..64567e122 100644 --- a/src/V3Task.cpp +++ b/src/V3Task.cpp @@ -67,8 +67,8 @@ public: : TaskBaseVertex{graphp} , m_nodep{nodep} {} ~TaskFTaskVertex() override = default; - AstNodeFTask* nodep() const { return m_nodep; } - string name() const override { return nodep()->name(); } + AstNodeFTask* nodep() const VL_MT_STABLE { return m_nodep; } + string name() const override VL_MT_STABLE { return nodep()->name(); } string dotColor() const override { return pure() ? "black" : "red"; } AstCFunc* cFuncp() const { return m_cFuncp; } void cFuncp(AstCFunc* nodep) { m_cFuncp = nodep; } @@ -80,7 +80,7 @@ public: explicit TaskCodeVertex(V3Graph* graphp) : TaskBaseVertex{graphp} {} ~TaskCodeVertex() override = default; - string name() const override { return "*CODE*"; } + string name() const override VL_MT_STABLE { return "*CODE*"; } string dotColor() const override { return "green"; } }; diff --git a/src/V3Timing.cpp b/src/V3Timing.cpp index 0a096661e..afbba68f5 100644 --- a/src/V3Timing.cpp +++ b/src/V3Timing.cpp @@ -67,7 +67,7 @@ private: class DependencyVertex final : public V3GraphVertex { AstNode* const m_nodep; // AST node represented by this graph vertex // ACCESSORS - string name() const override { + string name() const override VL_MT_STABLE { return cvtToHex(nodep()) + ' ' + nodep()->prettyTypeName(); } FileLine* fileline() const override { return nodep()->fileline(); } diff --git a/src/V3Tristate.cpp b/src/V3Tristate.cpp index 26f2e0343..0028d2bc8 100644 --- a/src/V3Tristate.cpp +++ b/src/V3Tristate.cpp @@ -154,7 +154,7 @@ public: // ACCESSORS AstNode* nodep() const { return m_nodep; } const AstVar* varp() const { return VN_CAST(nodep(), Var); } - string name() const override { + string name() const override VL_MT_STABLE { return ((isTristate() ? "tri\\n" : feedsTri() ? "feed\\n" : "-\\n") diff --git a/src/V3Waiver.cpp b/src/V3Waiver.cpp index 606aa0b46..1650fdefa 100644 --- a/src/V3Waiver.cpp +++ b/src/V3Waiver.cpp @@ -23,8 +23,9 @@ #include #include -void V3Waiver::addEntry(V3ErrorCode errorCode, const std::string& filename, - const std::string& str) { +void V3Waiver::addEntry(V3ErrorCode errorCode, const std::string& filename, const std::string& str) + VL_MT_SAFE_EXCLUDES(s_mutex) { + const VerilatedLockGuard lock{s_mutex}; std::stringstream entry; const size_t pos = str.find('\n'); entry << "lint_off -rule " << errorCode.ascii() << " -file \"*" << filename << "\" -match \"" @@ -34,7 +35,7 @@ void V3Waiver::addEntry(V3ErrorCode errorCode, const std::string& filename, s_waiverList.push_back(entry.str()); } -void V3Waiver::write(const std::string& filename) { +void V3Waiver::write(const std::string& filename) VL_MT_SAFE_EXCLUDES(s_mutex) { const std::unique_ptr ofp{V3File::new_ofstream(filename)}; if (ofp->fail()) v3fatal("Can't write " << filename); @@ -48,9 +49,12 @@ void V3Waiver::write(const std::string& filename) { *ofp << "// 2. Keep the waiver permanently if you are sure this is okay\n"; *ofp << "// 3. Keep the waiver temporarily to suppress the output\n\n"; + const VerilatedLockGuard lock{s_mutex}; + if (s_waiverList.empty()) *ofp << "// No waivers needed - great!\n"; for (const auto& i : s_waiverList) *ofp << "// " << i << "\n\n"; } +VerilatedMutex V3Waiver::s_mutex; V3Waiver::WaiverList V3Waiver::s_waiverList; diff --git a/src/V3Waiver.h b/src/V3Waiver.h index 10f711d1c..c8ca73137 100644 --- a/src/V3Waiver.h +++ b/src/V3Waiver.h @@ -17,6 +17,8 @@ #ifndef VERILATOR_V3WAIVER_H_ #define VERILATOR_V3WAIVER_H_ +#include "verilated_threads.h" + #include "V3Error.h" #include @@ -25,11 +27,13 @@ class V3Waiver final { // TYPES using WaiverList = std::vector; - static WaiverList s_waiverList; + static VerilatedMutex s_mutex; // Protect members + static WaiverList s_waiverList VL_GUARDED_BY(s_mutex); public: - static void addEntry(V3ErrorCode errorCode, const string& filename, const std::string& str); - static void write(const std::string& filename); + static void addEntry(V3ErrorCode errorCode, const string& filename, const std::string& str) + VL_MT_SAFE_EXCLUDES(s_mutex); + static void write(const std::string& filename) VL_MT_SAFE_EXCLUDES(s_mutex); }; #endif // Guard