diff --git a/src/Makefile_obj.in b/src/Makefile_obj.in index eb9b83e247..c626c454ae 100644 --- a/src/Makefile_obj.in +++ b/src/Makefile_obj.in @@ -199,10 +199,14 @@ RAW_OBJS_PCH_ASTMT = \ V3File.o \ V3Global.o \ V3Hasher.o \ + V3LinkLValue.o \ V3Number.o \ V3Options.o \ + V3Randomize.o \ V3Stats.o \ V3StatsReport.o \ + V3Task.o \ + V3Width.o \ RAW_OBJS_PCH_ASTNOMT = \ V3Active.o \ @@ -255,7 +259,6 @@ RAW_OBJS_PCH_ASTNOMT = \ V3LinkDot.o \ V3LinkInc.o \ V3LinkJump.o \ - V3LinkLValue.o \ V3LinkLevel.o \ V3LinkParse.o \ V3LinkResolve.o \ @@ -267,7 +270,6 @@ RAW_OBJS_PCH_ASTNOMT = \ V3Partition.o \ V3Premit.o \ V3ProtectLib.o \ - V3Randomize.o \ V3Reloop.o \ V3Sched.o \ V3SchedAcyclic.o \ @@ -283,7 +285,6 @@ RAW_OBJS_PCH_ASTNOMT = \ V3Subst.o \ V3TSP.o \ V3Table.o \ - V3Task.o \ V3Timing.o \ V3Trace.o \ V3TraceDecl.o \ @@ -292,7 +293,6 @@ RAW_OBJS_PCH_ASTNOMT = \ V3Unknown.o \ V3Unroll.o \ V3VariableOrder.o \ - V3Width.o \ V3WidthCommit.o \ V3WidthSel.o \ @@ -337,6 +337,13 @@ ifneq ($(filter -Wthread-safety,$(CPPFLAGS) $(CXXFLAGS)),) THREAD_SAFETY_NEGATIVE_OBJS := \ V3Ast.o \ V3AstNodes.o \ + V3Const__gen.o \ + V3Expand.o \ + V3Graph.o \ + V3LinkLValue.o \ + V3Randomize.o \ + V3Task.o \ + V3Width.o \ $(THREAD_SAFETY_NEGATIVE_OBJS): override CXXFLAGS_PRIV = -Wthread-safety-negative endif diff --git a/src/V3Const.cpp b/src/V3Const.cpp index 088e2df932..f113b7304f 100644 --- a/src/V3Const.cpp +++ b/src/V3Const.cpp @@ -20,8 +20,6 @@ // If operands are constant, replace this node with constant. //************************************************************************* -#define VL_MT_DISABLED_CODE_UNIT 1 - #include "config_build.h" #include "verilatedos.h" @@ -29,6 +27,7 @@ #include "V3Ast.h" #include "V3Global.h" +#include "V3Mutex.h" #include "V3Simulate.h" #include "V3Stats.h" #include "V3String.h" @@ -52,17 +51,17 @@ VL_DEFINE_DEBUG_FUNCTIONS; //###################################################################### // Utilities -static bool isConst(const AstNode* nodep, uint64_t v) { +static bool isConst(const AstNode* nodep, uint64_t v) VL_MT_SAFE { const AstConst* const constp = VN_CAST(nodep, Const); return constp && constp->toUQuad() == v; } template -static typename std::enable_if::value, bool>::type isPow2(T val) { +static typename std::enable_if::value, bool>::type isPow2(T val) VL_MT_SAFE { return (val & (val - 1)) == 0; } -static int countTrailingZeroes(uint64_t val) { +static int countTrailingZeroes(uint64_t val) VL_MT_SAFE { UASSERT(val, "countTrailingZeroes argument must be non-zero"); #if defined(__GNUC__) && !defined(VL_NO_BUILTINS) return __builtin_ctzll(val); @@ -77,10 +76,15 @@ static int countTrailingZeroes(uint64_t val) { #endif } +// Guards use of AstNode::user4. Must be locked when VNUser4InUse object exists. +static V3Mutex s_user4InUseLock; + // This visitor can be used in the post-expanded Ast from V3Expand, where the Ast satisfies: // - Constants are 64 bit at most (because words are accessed via AstWordSel) // - Variables are scoped. class ConstBitOpTreeVisitor final : public VNVisitorConst { + V3LockGuard m_oneInstanceLockGuard{s_user4InUseLock}; + // NODE STATE // AstVarRef::user4u -> Base index of m_varInfos that points VarInfo // AstVarScope::user4u -> Same as AstVarRef::user4 @@ -650,6 +654,7 @@ class ConstBitOpTreeVisitor final : public VNVisitorConst { // CONSTRUCTORS ConstBitOpTreeVisitor(AstNodeExpr* nodep, unsigned externalOps) + VL_REQUIRES_UNLOCKED(s_user4InUseLock) : m_ops{externalOps} , m_rootp{nodep} { // Fill nullptr at [0] because AstVarScope::user4 is 0 by default @@ -681,7 +686,8 @@ class ConstBitOpTreeVisitor final : public VNVisitorConst { // Reduction ops are transformed in the same way. // &{v[0], v[1]} => 2'b11 == (2'b11 & v) static AstNodeExpr* simplify(AstNodeExpr* nodep, int resultWidth, unsigned externalOps, - VDouble0& reduction, VNDeleter& deleterr) { + VDouble0& reduction, VNDeleter& deleterr) + VL_REQUIRES_UNLOCKED(s_user4InUseLock) { UASSERT_OBJ(1 <= resultWidth && resultWidth <= 64, nodep, "resultWidth out of range"); // Walk tree, gathering all terms referenced in expression @@ -1168,7 +1174,7 @@ class ConstVisitor final : public VNVisitor { return false; } - bool matchBitOpTree(AstNodeExpr* nodep) { + bool matchBitOpTree(AstNodeExpr* nodep) VL_REQUIRES_UNLOCKED(s_user4InUseLock) { if (nodep->widthMin() != 1) return false; if (!v3Global.opt.fConstBitOpTree()) return false; @@ -2040,7 +2046,7 @@ class ConstVisitor final : public VNVisitor { && varNotReferenced(nodep->op4p(), varp, level + 1)); } - bool replaceNodeAssign(AstNodeAssign* nodep) { + bool replaceNodeAssign(AstNodeAssign* nodep) VL_REQUIRES_UNLOCKED(s_user4InUseLock) { if (VN_IS(nodep->lhsp(), VarRef) && VN_IS(nodep->rhsp(), VarRef) && VN_AS(nodep->lhsp(), VarRef)->sameNoLvalue(VN_AS(nodep->rhsp(), VarRef)) && !VN_IS(nodep, AssignDly)) { @@ -2057,6 +2063,7 @@ class ConstVisitor final : public VNVisitor { if (m_warn && !VN_IS(nodep, AssignDly)) { // Is same var on LHS and RHS? // Note only do this (need user4) when m_warn, which is // done as unique visitor + const V3LockGuard user4Lock{s_user4InUseLock}; const VNUser4InUse m_inuser4; nodep->lhsp()->foreach([](const AstVarRef* nodep) { if (nodep->varp()) nodep->varp()->user4(1); @@ -2988,7 +2995,7 @@ class ConstVisitor final : public VNVisitor { //----- // Zero elimination - void visit(AstNodeAssign* nodep) override { + void visit(AstNodeAssign* nodep) override VL_REQUIRES_UNLOCKED(s_user4InUseLock) { iterateChildren(nodep); if (nodep->timingControlp()) m_hasJumpDelay = true; if (m_doNConst && replaceNodeAssign(nodep)) return; @@ -2999,7 +3006,7 @@ class ConstVisitor final : public VNVisitor { void visit(AstAssignVarScope* nodep) override { // Don't perform any optimizations, the node won't be linked yet } - void visit(AstAssignW* nodep) override { + void visit(AstAssignW* nodep) override VL_REQUIRES_UNLOCKED(s_user4InUseLock) { iterateChildren(nodep); if (m_doNConst && replaceNodeAssign(nodep)) return; AstNodeVarRef* const varrefp = VN_CAST( @@ -3646,7 +3653,7 @@ class ConstVisitor final : public VNVisitor { TREEOPV("AstRedOr {$lhsp.castExtend}", "AstRedOr {$lhsp->castExtend()->lhsp()}"); TREEOPV("AstRedXor{$lhsp.castExtend}", "AstRedXor{$lhsp->castExtend()->lhsp()}"); TREEOP ("AstRedXor{$lhsp.castXor, VN_IS(VN_AS($lhsp,,Xor)->lhsp(),,Const)}", "AstXor{AstRedXor{$lhsp->castXor()->lhsp()}, AstRedXor{$lhsp->castXor()->rhsp()}}"); // ^(const ^ a) => (^const)^(^a) - TREEOPC("AstAnd {$lhsp.castConst, $rhsp.castRedXor, matchBitOpTree(nodep)}", "DONE"); + TREEOPC("AstAnd {$lhsp.castConst, $rhsp.castRedXor, matchBitOpTree(nodep)}", "DONE", "VL_REQUIRES_UNLOCKED(s_user4InUseLock)"); TREEOPV("AstOneHot{$lhsp.width1}", "replaceWLhs(nodep)"); TREEOPV("AstOneHot0{$lhsp.width1}", "replaceNum(nodep,1)"); // Binary AND/OR is faster than logical and/or (usually) @@ -3671,9 +3678,9 @@ class ConstVisitor final : public VNVisitor { TREEOP ("AstAnd {operandShiftSame(nodep)}", "replaceShiftSame(nodep)"); TREEOP ("AstOr {operandShiftSame(nodep)}", "replaceShiftSame(nodep)"); TREEOP ("AstXor {operandShiftSame(nodep)}", "replaceShiftSame(nodep)"); - TREEOPC("AstAnd {matchBitOpTree(nodep)}", "DONE"); - TREEOPC("AstOr {matchBitOpTree(nodep)}", "DONE"); - TREEOPC("AstXor {matchBitOpTree(nodep)}", "DONE"); + TREEOPC("AstAnd {matchBitOpTree(nodep)}", "DONE", "VL_REQUIRES_UNLOCKED(s_user4InUseLock)"); + TREEOPC("AstOr {matchBitOpTree(nodep)}", "DONE", "VL_REQUIRES_UNLOCKED(s_user4InUseLock)"); + TREEOPC("AstXor {matchBitOpTree(nodep)}", "DONE", "VL_REQUIRES_UNLOCKED(s_user4InUseLock)"); // Note can't simplify a extend{extends}, extends{extend}, as the sign // bits end up in the wrong places TREEOPV("AstExtend {$lhsp.castExtend}", "replaceExtend(nodep, VN_AS(nodep->lhsp(), Extend)->lhsp())"); @@ -3854,7 +3861,7 @@ AstNode* V3Const::constifyParamsNoWarnEdit(AstNode* nodep) { //! something a generate block can depend on, we can wait until later to do the //! width check. //! @return Pointer to the edited node. -AstNode* V3Const::constifyGenerateParamsEdit(AstNode* nodep) { +AstNode* V3Const::constifyGenerateParamsEdit(AstNode* nodep) VL_MT_DISABLED { // if (debug() > 0) nodep->dumpTree("- forceConPRE:: "); // Resize even if the node already has a width, because buried in the tree // we may have a node we just created with signing, etc, that isn't sized @@ -3876,7 +3883,7 @@ AstNode* V3Const::constifyGenerateParamsEdit(AstNode* nodep) { return nodep; } -void V3Const::constifyAllLint(AstNetlist* nodep) { +void V3Const::constifyAllLint(AstNetlist* nodep) VL_MT_DISABLED { // Only call from Verilator.cpp, as it uses user#'s UINFO(2, __FUNCTION__ << ": " << endl); { @@ -3886,7 +3893,7 @@ void V3Const::constifyAllLint(AstNetlist* nodep) { v3Global.dumpCheckGlobalTree("const", 0, dumpTreeLevel() >= 3); } -void V3Const::constifyCpp(AstNetlist* nodep) { +void V3Const::constifyCpp(AstNetlist* nodep) VL_MT_DISABLED { UINFO(2, __FUNCTION__ << ": " << endl); { ConstVisitor visitor{ConstVisitor::PROC_CPP, /* globalPass: */ true}; @@ -3895,19 +3902,19 @@ void V3Const::constifyCpp(AstNetlist* nodep) { v3Global.dumpCheckGlobalTree("const_cpp", 0, dumpTreeLevel() >= 3); } -AstNode* V3Const::constifyEdit(AstNode* nodep) { +AstNode* V3Const::constifyEdit(AstNode* nodep) VL_MT_DISABLED { ConstVisitor visitor{ConstVisitor::PROC_V_NOWARN, /* globalPass: */ false}; nodep = visitor.mainAcceptEdit(nodep); return nodep; } -AstNode* V3Const::constifyEditCpp(AstNode* nodep) { +AstNode* V3Const::constifyEditCpp(AstNode* nodep) VL_MT_ENABLED { ConstVisitor visitor{ConstVisitor::PROC_CPP, /* globalPass: */ false}; nodep = visitor.mainAcceptEdit(nodep); return nodep; } -void V3Const::constifyAllLive(AstNetlist* nodep) { +void V3Const::constifyAllLive(AstNetlist* nodep) VL_MT_DISABLED { // Only call from Verilator.cpp, as it uses user#'s // This only pushes constants up, doesn't make any other edits // IE doesn't prune dead statements, as we need to do some usability checks after this @@ -3919,7 +3926,7 @@ void V3Const::constifyAllLive(AstNetlist* nodep) { v3Global.dumpCheckGlobalTree("const", 0, dumpTreeLevel() >= 3); } -void V3Const::constifyAll(AstNetlist* nodep) { +void V3Const::constifyAll(AstNetlist* nodep) VL_MT_DISABLED { // Only call from Verilator.cpp, as it uses user#'s UINFO(2, __FUNCTION__ << ": " << endl); { @@ -3929,7 +3936,7 @@ void V3Const::constifyAll(AstNetlist* nodep) { v3Global.dumpCheckGlobalTree("const", 0, dumpTreeLevel() >= 3); } -AstNode* V3Const::constifyExpensiveEdit(AstNode* nodep) { +AstNode* V3Const::constifyExpensiveEdit(AstNode* nodep) VL_MT_DISABLED { ConstVisitor visitor{ConstVisitor::PROC_V_EXPENSIVE, /* globalPass: */ false}; nodep = visitor.mainAcceptEdit(nodep); return nodep; diff --git a/src/V3Const.h b/src/V3Const.h index e992faca83..6d128bc0ee 100644 --- a/src/V3Const.h +++ b/src/V3Const.h @@ -27,12 +27,12 @@ class V3Const final { public: - static AstNode* constifyParamsEdit(AstNode* nodep) VL_MT_DISABLED; - static AstNodeExpr* constifyParamsEdit(AstNodeExpr* exprp) VL_MT_DISABLED { + static AstNode* constifyParamsEdit(AstNode* nodep); + static AstNodeExpr* constifyParamsEdit(AstNodeExpr* exprp) { return VN_AS(constifyParamsEdit(static_cast(exprp)), NodeExpr); } - static AstNode* constifyParamsNoWarnEdit(AstNode* nodep) VL_MT_DISABLED; - static AstNodeExpr* constifyParamsNoWarnEdit(AstNodeExpr* exprp) VL_MT_DISABLED { + static AstNode* constifyParamsNoWarnEdit(AstNode* nodep); + static AstNodeExpr* constifyParamsNoWarnEdit(AstNodeExpr* exprp) { return VN_AS(constifyParamsNoWarnEdit(static_cast(exprp)), NodeExpr); } static AstNode* constifyGenerateParamsEdit(AstNode* nodep) VL_MT_DISABLED; @@ -46,14 +46,14 @@ class V3Const final { static void constifyCpp(AstNetlist* nodep) VL_MT_DISABLED; // Only the current node and lower // Return new node that may have replaced nodep - static AstNode* constifyEditCpp(AstNode* nodep) VL_MT_DISABLED; - static AstNodeExpr* constifyEditCpp(AstNodeExpr* exprp) VL_MT_DISABLED { + static AstNode* constifyEditCpp(AstNode* nodep); + static AstNodeExpr* constifyEditCpp(AstNodeExpr* exprp) { return VN_AS(constifyEditCpp(static_cast(exprp)), NodeExpr); } // Only the current node and lower // Return new node that may have replaced nodep - static AstNode* constifyEdit(AstNode* nodep) VL_MT_DISABLED; - static AstNodeExpr* constifyEdit(AstNodeExpr* exprp) VL_MT_DISABLED { + static AstNode* constifyEdit(AstNode* nodep); + static AstNodeExpr* constifyEdit(AstNodeExpr* exprp) { return VN_AS(constifyEdit(static_cast(exprp)), NodeExpr); } // Only the current node and lower, with special SenTree optimization diff --git a/src/V3Expand.cpp b/src/V3Expand.cpp index d4f048f403..7a91c2a262 100644 --- a/src/V3Expand.cpp +++ b/src/V3Expand.cpp @@ -25,7 +25,7 @@ // //************************************************************************* -#include "V3PchAstNoMT.h" // VL_MT_DISABLED_CODE_UNIT +#include "V3PchAstMT.h" #include "V3Expand.h" diff --git a/src/V3Expand.h b/src/V3Expand.h index e3f8fc6306..d119b9391e 100644 --- a/src/V3Expand.h +++ b/src/V3Expand.h @@ -28,7 +28,7 @@ class AstNetlist; class V3Expand final { public: - static void expandAll(AstNetlist* nodep) VL_MT_DISABLED; + static void expandAll(AstNetlist* nodep); }; #endif // Guard diff --git a/src/V3Global.h b/src/V3Global.h index e48c1276c8..1cd4041757 100644 --- a/src/V3Global.h +++ b/src/V3Global.h @@ -222,7 +222,8 @@ class V3Global final { void shutdown(); // Release allocated resources // ACCESSORS (general) - AstNetlist* rootp() const VL_MT_DISABLED { return m_rootp; } + //AstNetlist* rootp() const VL_MT_DISABLED { return m_rootp; } + AstNetlist* rootp() const { return m_rootp; } VNetlist* netlistp() const VL_MT_SAFE { return m_netlist.get(); } VWidthMinUsage widthMinUsage() const { return m_widthMinUsage; } bool assertDTypesResolved() const { return m_assertDTypesResolved; } diff --git a/src/V3Graph.cpp b/src/V3Graph.cpp index f77f1d056f..dd9c9a40f1 100644 --- a/src/V3Graph.cpp +++ b/src/V3Graph.cpp @@ -14,8 +14,6 @@ // //************************************************************************* -#define VL_MT_DISABLED_CODE_UNIT 1 - #include "config_build.h" #include "verilatedos.h" diff --git a/src/V3Graph.h b/src/V3Graph.h index c2973cae7d..bca3f6a9fa 100644 --- a/src/V3Graph.h +++ b/src/V3Graph.h @@ -96,12 +96,12 @@ class V3Graph VL_NOT_FINAL { // ACCESSORS public: - V3Graph() VL_MT_DISABLED; - virtual ~V3Graph() VL_MT_DISABLED; + V3Graph(); + virtual ~V3Graph(); virtual string dotRankDir() const { return "TB"; } // rankdir for dot plotting // METHODS - void clear() VL_MT_DISABLED; // Empty it of all vertices/edges, as if making a new object + void clear(); // Empty it of all vertices/edges, as if making a new object bool empty() const { return m_vertices.empty(); } V3GraphVertex* verticesBeginp() const { return m_vertices.begin(); } @@ -152,7 +152,7 @@ class V3Graph VL_NOT_FINAL { /// Remove any redundant edges, weights become SUM of any other weight /// Side-effect: changes user() - void removeRedundantEdgesSum(V3EdgeFuncP edgeFuncp) VL_MT_DISABLED; + void removeRedundantEdgesSum(V3EdgeFuncP edgeFuncp); /// Remove any transitive edges. E.g. if have edges A->B, B->C, and A->C /// then A->C is a "transitive" edge; it's implied by the first two @@ -175,9 +175,8 @@ class V3Graph VL_NOT_FINAL { /// Debugging void dump(std::ostream& os = std::cout) const VL_MT_DISABLED; - void dumpDotFile(const string& filename, bool colorAsSubgraph) const VL_MT_DISABLED; - void dumpDotFilePrefixed(const string& nameComment, - bool colorAsSubgraph = false) const VL_MT_DISABLED; + void dumpDotFile(const string& filename, bool colorAsSubgraph) const; + void dumpDotFilePrefixed(const string& nameComment, bool colorAsSubgraph = false) const; void dumpDotFilePrefixedAlways(const string& nameComment, bool colorAsSubgraph = false) const VL_MT_DISABLED; static void selfTest() VL_MT_DISABLED; @@ -208,17 +207,17 @@ class V3GraphVertex VL_NOT_FINAL { uint32_t m_user; // Marker for some algorithms }; // METHODS - void verticesPushBack(V3Graph* graphp) VL_MT_DISABLED; + void verticesPushBack(V3Graph* graphp); // ACCESSORS void fanout(double fanout) { m_fanout = fanout; } void inUnlink() { m_ins.reset(); } // Low level; normally unlinkDelete is what you want void outUnlink() { m_outs.reset(); } // Low level; normally unlinkDelete is what you want protected: // CONSTRUCTORS - V3GraphVertex(V3Graph* graphp, const V3GraphVertex& old) VL_MT_DISABLED; + V3GraphVertex(V3Graph* graphp, const V3GraphVertex& old); public: - explicit V3GraphVertex(V3Graph* graphp) VL_MT_DISABLED; + explicit V3GraphVertex(V3Graph* graphp); //! Clone copy constructor. Doesn't copy edges or user/userp. virtual V3GraphVertex* clone(V3Graph* graphp) const VL_MT_DISABLED { return new V3GraphVertex{graphp, *this}; @@ -338,21 +337,21 @@ class V3GraphEdge VL_NOT_FINAL { }; // METHODS void init(V3Graph* graphp, V3GraphVertex* fromp, V3GraphVertex* top, int weight, - bool cutable = false) VL_MT_DISABLED; + bool cutable = false); void cut() { m_weight = 0; } // 0 weight is same as disconnected - void outPushBack() VL_MT_DISABLED; - void inPushBack() VL_MT_DISABLED; + void outPushBack(); + void inPushBack(); // CONSTRUCTORS protected: V3GraphEdge(V3Graph* graphp, V3GraphVertex* fromp, V3GraphVertex* top, - const V3GraphEdge& old) VL_MT_DISABLED { + const V3GraphEdge& old) { init(graphp, fromp, top, old.m_weight, old.m_cutable); } public: //! Add DAG from one node to the specified node V3GraphEdge(V3Graph* graphp, V3GraphVertex* fromp, V3GraphVertex* top, int weight, - bool cutable = false) VL_MT_DISABLED { + bool cutable = false) { init(graphp, fromp, top, weight, cutable); } //! Clone copy constructor. Doesn't copy existing vertices or user/userp. diff --git a/src/V3LinkLValue.cpp b/src/V3LinkLValue.cpp index b0ce942d9f..f768843c5c 100644 --- a/src/V3LinkLValue.cpp +++ b/src/V3LinkLValue.cpp @@ -18,7 +18,7 @@ // Set lvalue() attributes on appropriate VARREFs. //************************************************************************* -#include "V3PchAstNoMT.h" // VL_MT_DISABLED_CODE_UNIT +#include "V3PchAstMT.h" #include "V3LinkLValue.h" diff --git a/src/V3LinkLValue.h b/src/V3LinkLValue.h index 26cbaa4e3f..16656936d0 100644 --- a/src/V3LinkLValue.h +++ b/src/V3LinkLValue.h @@ -20,8 +20,6 @@ #include "config_build.h" #include "verilatedos.h" -#include "V3ThreadSafety.h" - class AstNetlist; class AstNode; @@ -29,8 +27,8 @@ class AstNode; class V3LinkLValue final { public: - static void linkLValue(AstNetlist* nodep) VL_MT_DISABLED; - static void linkLValueSet(AstNode* nodep) VL_MT_DISABLED; + static void linkLValue(AstNetlist* nodep); + static void linkLValueSet(AstNode* nodep); }; #endif // Guard diff --git a/src/V3Randomize.cpp b/src/V3Randomize.cpp index 340cbf8a7b..6e01777379 100644 --- a/src/V3Randomize.cpp +++ b/src/V3Randomize.cpp @@ -24,7 +24,7 @@ // //************************************************************************* -#include "V3PchAstNoMT.h" // VL_MT_DISABLED_CODE_UNIT +#include "V3PchAstMT.h" #include "V3Randomize.h" diff --git a/src/V3Randomize.h b/src/V3Randomize.h index 5de300667b..2dff583138 100644 --- a/src/V3Randomize.h +++ b/src/V3Randomize.h @@ -28,10 +28,10 @@ class AstNetlist; class V3Randomize final { public: - static void randomizeNetlist(AstNetlist* nodep) VL_MT_DISABLED; + static void randomizeNetlist(AstNetlist* nodep); - static AstFunc* newRandomizeFunc(AstClass* nodep) VL_MT_DISABLED; - static AstFunc* newSRandomFunc(AstClass* nodep) VL_MT_DISABLED; + static AstFunc* newRandomizeFunc(AstClass* nodep); + static AstFunc* newSRandomFunc(AstClass* nodep); }; #endif // Guard diff --git a/src/V3Task.cpp b/src/V3Task.cpp index 58dd51eaf4..8d28046d03 100644 --- a/src/V3Task.cpp +++ b/src/V3Task.cpp @@ -23,7 +23,7 @@ // //************************************************************************* -#include "V3PchAstNoMT.h" // VL_MT_DISABLED_CODE_UNIT +#include "V3PchAstMT.h" #include "V3Task.h" diff --git a/src/V3Task.h b/src/V3Task.h index feea7e17ea..7ba223c9d5 100644 --- a/src/V3Task.h +++ b/src/V3Task.h @@ -55,16 +55,15 @@ class V3Task final { static void taskAll(AstNetlist* nodep) VL_MT_DISABLED; /// Return vector of [port, pin-connects-to] (SLOW) static V3TaskConnects taskConnects(AstNodeFTaskRef* nodep, AstNode* taskStmtsp, - V3TaskConnectState* statep = nullptr) VL_MT_DISABLED; + V3TaskConnectState* statep = nullptr); static void taskConnectWrap(AstNodeFTaskRef* nodep, const V3TaskConnects& tconnects, V3TaskConnectState* statep, - const std::set& argWrap) VL_MT_DISABLED; + const std::set& argWrap); static AstNodeFTask* taskConnectWrapNew(AstNodeFTask* taskp, const string& newname, const V3TaskConnects& tconnects, - const std::set& argWrap) VL_MT_DISABLED; + const std::set& argWrap); static string assignInternalToDpi(AstVar* portp, bool isPtr, const string& frSuffix, - const string& toSuffix, - const string& frPrefix = "") VL_MT_DISABLED; + const string& toSuffix, const string& frPrefix = ""); static string assignDpiToInternal(const string& lhsName, AstVar* rhsp) VL_MT_DISABLED; static const char* dpiTemporaryVarSuffix() VL_MT_SAFE { return s_dpiTemporaryVarSuffix; } }; diff --git a/src/V3ThreadSafety.h b/src/V3ThreadSafety.h index 1753069303..e478453ea8 100644 --- a/src/V3ThreadSafety.h +++ b/src/V3ThreadSafety.h @@ -73,4 +73,8 @@ using V3MtDisabledLockGuard = V3LockGuardImp; VL_CLANG_ATTR(annotate("MT_DISABLED")) \ VL_REQUIRES(V3MtDisabledLock::instance()) +#define VL_MT_ENABLED \ + VL_CLANG_ATTR(annotate("MT_ENABLED")) \ + VL_REQUIRES_UNLOCKED(V3MtDisabledLock::instance()) + #endif // guard diff --git a/src/V3Width.cpp b/src/V3Width.cpp index 9597ecf1d5..3bcc9c3812 100644 --- a/src/V3Width.cpp +++ b/src/V3Width.cpp @@ -63,7 +63,7 @@ // iterateSubtreeReturnEdits. //************************************************************************* -#include "V3PchAstNoMT.h" // VL_MT_DISABLED_CODE_UNIT +#include "V3PchAstMT.h" #include "V3Width.h" diff --git a/src/V3Width.h b/src/V3Width.h index 0ac3a6b25e..e5cb9b3953 100644 --- a/src/V3Width.h +++ b/src/V3Width.h @@ -31,13 +31,13 @@ class AstNodeDType; class V3Width final { public: static void width(AstNetlist* nodep) VL_MT_DISABLED; - static AstNode* widthParamsEdit(AstNode* nodep) VL_MT_DISABLED; + static AstNode* widthParamsEdit(AstNode* nodep); static AstNode* widthGenerateParamsEdit(AstNode* nodep) VL_MT_DISABLED; // For use only in WidthVisitor // Replace AstSelBit, etc with AstSel/AstArraySel // Returns replacement node if nodep was deleted, or null if none. - static AstNode* widthSelNoIterEdit(AstNode* nodep) VL_MT_DISABLED; + static AstNode* widthSelNoIterEdit(AstNode* nodep); }; #endif // Guard diff --git a/src/Verilator.cpp b/src/Verilator.cpp index 3c3b1a3fef..d04c636ce0 100644 --- a/src/Verilator.cpp +++ b/src/Verilator.cpp @@ -197,9 +197,13 @@ static void process() { // Coverage insertion // Before we do dead code elimination and inlining, or we'll lose it. if (v3Global.opt.coverage()) V3Coverage::coverage(v3Global.rootp()); + } - // Add randomize() class methods if they are used by the design - if (v3Global.useRandomizeMethods()) V3Randomize::randomizeNetlist(v3Global.rootp()); + // Add randomize() class methods if they are used by the design + if (v3Global.useRandomizeMethods()) V3Randomize::randomizeNetlist(v3Global.rootp()); + + { + const V3MtDisabledLockGuard mtDisabler{v3MtDisabledLock()}; // Push constants, but only true constants preserving liveness // so V3Undriven sees variables to be eliminated, ie "if (0 && foo) ..." @@ -485,11 +489,15 @@ static void process() { // Move wide constants to BLOCK temps / ConstPool. V3Premit::premitAll(v3Global.rootp()); } + } - // Expand macros and wide operators into C++ primitives - if (!v3Global.opt.lintOnly() && !v3Global.opt.xmlOnly() && v3Global.opt.fExpand()) { - V3Expand::expandAll(v3Global.rootp()); - } + // Expand macros and wide operators into C++ primitives + if (!v3Global.opt.lintOnly() && !v3Global.opt.xmlOnly() && v3Global.opt.fExpand()) { + V3Expand::expandAll(v3Global.rootp()); + } + + { + const V3MtDisabledLockGuard mtDisabler{v3MtDisabledLock()}; // Propagate constants across WORDSEL arrayed temporaries if (!v3Global.opt.xmlOnly() && v3Global.opt.fSubst()) {