diff --git a/src/V3AstNodeOther.h b/src/V3AstNodeOther.h index 0c2632604..decaddbb7 100644 --- a/src/V3AstNodeOther.h +++ b/src/V3AstNodeOther.h @@ -1951,6 +1951,7 @@ class AstVar final : public AstNode { bool m_noCReset : 1; // Do not do automated CReset creation bool m_noReset : 1; // Do not do automated reset/randomization bool m_noSubst : 1; // Do not substitute out references + bool m_sampled : 1; // Sampled timing region bool m_substConstOnly : 1; // Only substitute if constant bool m_overridenParam : 1; // Overridden parameter by #(...) or defparam bool m_trace : 1; // Trace this variable @@ -1969,6 +1970,7 @@ class AstVar final : public AstNode { bool m_globalConstrained : 1; // Global constraint per IEEE 1800-2023 18.5.8 bool m_isStdRandomizeArg : 1; // Argument variable created for std::randomize (__Varg*) bool m_noSample : 1; // Do not wrap with AstSampled in assertion context + bool m_processQueue : 1; // Process queue variable void init() { m_ansi = false; m_declTyped = false; @@ -2009,6 +2011,7 @@ class AstVar final : public AstNode { m_noCReset = false; m_noReset = false; m_noSubst = false; + m_sampled = false; m_substConstOnly = false; m_overridenParam = false; m_trace = false; @@ -2027,6 +2030,7 @@ class AstVar final : public AstNode { m_globalConstrained = false; m_isStdRandomizeArg = false; m_noSample = false; + m_processQueue = false; } public: @@ -2176,6 +2180,10 @@ public: void noSubst(bool flag) { m_noSubst = flag; } bool noSample() const { return m_noSample; } void noSample(bool flag) { m_noSample = flag; } + bool processQueue() const { return m_processQueue; } + void processQueue(bool flag) { m_processQueue = flag; } + bool sampled() const { return m_sampled; } + void sampled(bool flag) { m_sampled = flag; } bool substConstOnly() const { return m_substConstOnly; } void substConstOnly(bool flag) { m_substConstOnly = flag; } bool overriddenParam() const { return m_overridenParam; } diff --git a/src/V3AstNodes.cpp b/src/V3AstNodes.cpp index 9383f542f..2b715848f 100644 --- a/src/V3AstNodes.cpp +++ b/src/V3AstNodes.cpp @@ -2956,6 +2956,8 @@ void AstVar::dump(std::ostream& str) const { if (rand().isRandomizable()) str << " [" << rand() << "]"; if (noCReset()) str << " [!CRST]"; if (noReset()) str << " [!RST]"; + if (processQueue()) str << " [PROCQ]"; + if (sampled()) str << " [SAMPLED]"; if (attrIsolateAssign()) str << " [aISO]"; if (attrFileDescr()) str << " [aFD]"; if (isFuncReturn()) { @@ -2986,6 +2988,8 @@ void AstVar::dumpJson(std::ostream& str) const { dumpJsonBoolFuncIf(str, isUsedLoopIdx); dumpJsonBoolFuncIf(str, noCReset); dumpJsonBoolFuncIf(str, noReset); + dumpJsonBoolFuncIf(str, processQueue); + dumpJsonBoolFuncIf(str, sampled); dumpJsonBoolFuncIf(str, attrIsolateAssign); dumpJsonBoolFuncIf(str, attrFileDescr); dumpJsonBoolFuncIf(str, isDpiOpenArray); diff --git a/src/V3Clock.cpp b/src/V3Clock.cpp index 6a0b3e3fa..8b3fb243c 100644 --- a/src/V3Clock.cpp +++ b/src/V3Clock.cpp @@ -100,7 +100,7 @@ class ClockVisitor final : public VNVisitor { void visit(AstVarScope* nodep) override { AstVar* const varp = nodep->varp(); if (!varp->valuep()) return; - if (!VString::startsWith(varp->name(), "__Vsampled")) return; + if (!varp->sampled()) return; // Create the containing function on first encounter if (!m_sampleCFuncp) { diff --git a/src/V3Fork.cpp b/src/V3Fork.cpp index 2e40faa24..737b31429 100644 --- a/src/V3Fork.cpp +++ b/src/V3Fork.cpp @@ -611,7 +611,7 @@ class ForkVisitor final : public VNVisitor { const AstCMethodHard* const methodp = VN_CAST(stmtExprp->exprp(), CMethodHard); if (!methodp || methodp->name() != "push_back") return false; const AstVarRef* const queueRefp = VN_CAST(methodp->fromp(), VarRef); - return queueRefp && queueRefp->name().rfind("__VprocessQueue_", 0) == 0; + return queueRefp && queueRefp->varp()->processQueue(); } static void moveForkSentinelAfterDisableQueuePushes(AstBegin* const beginp) { AstNode* const firstStmtp = beginp->stmtsp(); diff --git a/src/V3LinkJump.cpp b/src/V3LinkJump.cpp index a5c0870e6..6f46de45a 100644 --- a/src/V3LinkJump.cpp +++ b/src/V3LinkJump.cpp @@ -236,20 +236,24 @@ class LinkJumpVisitor final : public VNVisitor { m_taskDisableBegins.emplace(taskp, taskBodyp); return taskBodyp; } - AstVar* getOrCreateTaskDisableQueuep(AstTask* const taskp, FileLine* const fl) { - const auto it = m_taskDisableQueues.find(taskp); - if (it != m_taskDisableQueues.end()) return it->second; - + AstVar* getProcessQueuep(AstNode* const nodep, FileLine* const fl) { AstPackage* const topPkgp = v3Global.rootp()->dollarUnitPkgAddp(); AstClass* const processClassp = VN_AS(getMemberp(v3Global.rootp()->stdPackagep(), "process"), Class); AstVar* const processQueuep = new AstVar{ - fl, VVarType::VAR, m_queueNames.get(taskp->name()), VFlagChildDType{}, + fl, VVarType::VAR, m_queueNames.get(nodep->name()), VFlagChildDType{}, new AstQueueDType{fl, VFlagChildDType{}, new AstClassRefDType{fl, processClassp, nullptr}, nullptr}}; processQueuep->lifetime(VLifetime::STATIC_EXPLICIT); + processQueuep->processQueue(true); topPkgp->addStmtsp(processQueuep); + return processQueuep; + } + AstVar* getOrCreateTaskDisableQueuep(AstTask* const taskp, FileLine* const fl) { + const auto it = m_taskDisableQueues.find(taskp); + if (it != m_taskDisableQueues.end()) return it->second; + AstVar* const processQueuep = getProcessQueuep(taskp, fl); AstStmtExpr* const pushCurrentProcessp = getQueuePushProcessSelfp(fl, processQueuep); AstBegin* const taskBodyp = getOrCreateTaskDisableBeginp(taskp, fl); prependStmtsp(taskBodyp, pushCurrentProcessp); @@ -274,16 +278,7 @@ class LinkJumpVisitor final : public VNVisitor { const auto it = m_beginDisableQueues.find(beginp); if (it != m_beginDisableQueues.end()) return it->second; - AstPackage* const topPkgp = v3Global.rootp()->dollarUnitPkgAddp(); - AstClass* const processClassp - = VN_AS(getMemberp(v3Global.rootp()->stdPackagep(), "process"), Class); - AstVar* const processQueuep = new AstVar{ - fl, VVarType::VAR, m_queueNames.get(beginp->name()), VFlagChildDType{}, - new AstQueueDType{fl, VFlagChildDType{}, - new AstClassRefDType{fl, processClassp, nullptr}, nullptr}}; - processQueuep->lifetime(VLifetime::STATIC_EXPLICIT); - topPkgp->addStmtsp(processQueuep); - + AstVar* const processQueuep = getProcessQueuep(beginp, fl); AstStmtExpr* const pushCurrentProcessp = getQueuePushProcessSelfp(fl, processQueuep); AstBegin* const beginBodyp = getOrCreateBeginDisableBeginp(beginp, fl); prependStmtsp(beginBodyp, pushCurrentProcessp); @@ -315,17 +310,9 @@ class LinkJumpVisitor final : public VNVisitor { nodep->v3warn(E_UNSUPPORTED, "Unsupported: disabling fork from task / function"); } } - AstPackage* const topPkgp = v3Global.rootp()->dollarUnitPkgAddp(); - AstClass* const processClassp - = VN_AS(getMemberp(v3Global.rootp()->stdPackagep(), "process"), Class); - // Declare queue of processes (as a global variable for simplicity) - AstVar* const processQueuep = new AstVar{ - fl, VVarType::VAR, m_queueNames.get(targetp->name()), VFlagChildDType{}, - new AstQueueDType{fl, VFlagChildDType{}, - new AstClassRefDType{fl, processClassp, nullptr}, nullptr}}; - processQueuep->lifetime(VLifetime::STATIC_EXPLICIT); - topPkgp->addStmtsp(processQueuep); + AstPackage* const topPkgp = v3Global.rootp()->dollarUnitPkgAddp(); + AstVar* const processQueuep = getProcessQueuep(targetp, fl); AstVarRef* const queueWriteRefp = new AstVarRef{fl, topPkgp, processQueuep, VAccess::WRITE}; AstStmtExpr* pushCurrentProcessp = getQueuePushProcessSelfp(queueWriteRefp); diff --git a/src/V3Sampled.cpp b/src/V3Sampled.cpp index d978df73f..4fb45e772 100644 --- a/src/V3Sampled.cpp +++ b/src/V3Sampled.cpp @@ -53,6 +53,7 @@ class SampledVisitor final : public VNVisitor { AstVarScope* const newvscp = new AstVarScope{flp, m_scopep, newvarp}; newvarp->direction(VDirection::INPUT); // Inform V3Sched that it will be driven later newvarp->primaryIO(true); + newvarp->sampled(true); vscp->user1p(newvscp); m_scopep->addVarsp(newvscp); // At the top of _eval, assign them (use valuep here as temporary storage during V3Sched) diff --git a/src/V3Timing.cpp b/src/V3Timing.cpp index 060ac2348..25b19e788 100644 --- a/src/V3Timing.cpp +++ b/src/V3Timing.cpp @@ -750,7 +750,7 @@ class TimingControlVisitor final : public VNVisitor { const AstCMethodHard* const methodp = VN_CAST(stmtExprp->exprp(), CMethodHard); if (!methodp || methodp->name() != "push_back") return false; const AstVarRef* const queueRefp = VN_CAST(methodp->fromp(), VarRef); - return queueRefp && queueRefp->name().rfind("__VprocessQueue_", 0) == 0; + return queueRefp && queueRefp->varp()->processQueue(); } // Register a callback so killing a process-backed fork branch decrements the join counter void addForkOnKill(AstBegin* const beginp, AstVarScope* const forkVscp) const {