diff --git a/Changes b/Changes index ae31b100d..9e5dc0ff3 100644 --- a/Changes +++ b/Changes @@ -176,6 +176,7 @@ Verilator 5.051 devel * Fix folding of short circuiting operators guarding member access (#8238). [Geza Lore, Testorrent USA, Inc.] * Fix MULTIDRIVENPROC on static loop induction variables (#8242). [Geza Lore, Testorrent USA, Inc.] * Fix multiply undefined behavior on signed int overflow (#8247) (#8248). [Paul Rigge] +* Fix initial statements with gate optimizaion (#8250). [Prithayan Barua] Verilator 5.050 2026-07-01 diff --git a/src/V3AstInlines.h b/src/V3AstInlines.h index 0dd1f5953..ef91c2408 100644 --- a/src/V3AstInlines.h +++ b/src/V3AstInlines.h @@ -146,6 +146,7 @@ bool AstBasicDType::ascending() const { bool AstActive::hasClocked() const { return m_sentreep->hasClocked(); } bool AstActive::hasCombo() const { return m_sentreep->hasCombo(); } +bool AstActive::hasInitial() const { return m_sentreep->hasInitial(); } bool AstActive::hasStatic() const { return m_sentreep->hasStatic(); } AstAlways::AstAlways(AstAssignW* assignp) diff --git a/src/V3AstNodeOther.h b/src/V3AstNodeOther.h index 9d672ab35..1f3f46c43 100644 --- a/src/V3AstNodeOther.h +++ b/src/V3AstNodeOther.h @@ -460,6 +460,7 @@ public: // METHODS inline bool hasClocked() const; inline bool hasCombo() const; + inline bool hasInitial() const; inline bool hasStatic() const; }; class AstAlias final : public AstNode { diff --git a/src/V3Gate.cpp b/src/V3Gate.cpp index 5aa74f81e..beec484e0 100644 --- a/src/V3Gate.cpp +++ b/src/V3Gate.cpp @@ -201,6 +201,7 @@ class GateBuildVisitor final : public VNVisitorConst { bool m_inClockedActive = false; // Underneath clocked active bool m_inEdgeActive = false; // Underneath edge active bool m_inStaticActive = false; // Underneath static active + bool m_inInitialActive = false; // Underneath initial active bool m_inSenItem = false; // Underneath AstSenItem; any varrefs are clocks // METHODS @@ -224,7 +225,8 @@ class GateBuildVisitor final : public VNVisitorConst { m_logicVertexp->clearReducibleAndDedupable(nonReducibleReason); } else if (m_inClockedActive) { m_logicVertexp->clearReducible("Clocked logic"); // but dedupable - } else if (m_inStaticActive) { + } else if (m_inStaticActive || m_inInitialActive) { + // Runs only once, so its output must not be treated as live combinational logic m_logicVertexp->setStaticInit(); } if (consumeReason) m_logicVertexp->setConsumed(consumeReason); @@ -251,10 +253,12 @@ class GateBuildVisitor final : public VNVisitorConst { VL_RESTORER(m_inClockedActive); VL_RESTORER(m_inEdgeActive); VL_RESTORER(m_inStaticActive); + VL_RESTORER(m_inInitialActive); m_activep = nodep; m_inClockedActive = nodep->hasClocked(); m_inEdgeActive = nodep->sentreep() && nodep->sentreep()->hasEdge(); m_inStaticActive = nodep->hasStatic(); + m_inInitialActive = nodep->hasInitial(); // AstVarScope::user2 -> bool: Signal used in SenItem in *this* active block const VNUser2InUse user2InUse;