Fix inlining static initializer in V3Gate (#7503)

V3Gate could incorrectly inline a non-constant static initializer of
a variable into the use site if there are no other drivers. Disabling.

Fixes #5381
This commit is contained in:
Geza Lore 2026-04-27 16:58:38 +01:00 committed by GitHub
parent c8893b64de
commit cee174c4b6
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 15 additions and 4 deletions

View File

@ -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::hasStatic() const { return m_sentreep->hasStatic(); }
AstAlways::AstAlways(AstAssignW* assignp)
: ASTGEN_SUPER_Always(assignp->fileline(), assignp)

View File

@ -432,6 +432,7 @@ public:
// METHODS
inline bool hasClocked() const;
inline bool hasCombo() const;
inline bool hasStatic() const;
};
class AstAlias final : public AstNode {
// Alias construct - Used for source level net alias, and also for variable aliases internally

View File

@ -47,6 +47,7 @@ class GateEitherVertex VL_NOT_FINAL : public V3GraphVertex {
bool m_reducible = true; // True if this node should be able to be eliminated
bool m_dedupable = true; // True if this node should be able to be deduped
bool m_consumed = false; // Output goes to something meaningful
bool m_staticInit = false; // True if this node is a static initializer
public:
explicit GateEitherVertex(V3Graph* graphp)
: V3GraphVertex{graphp} {}
@ -56,10 +57,12 @@ public:
bool reducible() const { return m_reducible; }
bool dedupable() const { return m_dedupable; }
bool consumed() const { return m_consumed; }
bool staticInit() const { return m_staticInit; }
void setConsumed(const char* /*consumedReason*/) {
// if (!m_consumed) UINFO(0, "\t\tSetConsumed " << consumedReason << " " << this);
m_consumed = true;
}
void setStaticInit() { m_staticInit = true; }
void clearReducible(const char* /*nonReducibleReason*/) {
// UINFO(0, " NR: " << nonReducibleReason << " " << name());
m_reducible = false;
@ -196,6 +199,7 @@ class GateBuildVisitor final : public VNVisitorConst {
const AstScope* m_scopep = nullptr; // Current scope being processed
AstActive* m_activep = nullptr; // Current active
bool m_inClockedActive = false; // Underneath clocked active
bool m_inStaticActive = false; // Underneath static active
bool m_inSenItem = false; // Underneath AstSenItem; any varrefs are clocks
// METHODS
@ -219,6 +223,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) {
m_logicVertexp->setStaticInit();
}
if (consumeReason) m_logicVertexp->setConsumed(consumeReason);
checkNode(nodep);
@ -242,8 +248,10 @@ class GateBuildVisitor final : public VNVisitorConst {
UASSERT_OBJ(!m_activep, nodep, "Should not nest");
VL_RESTORER(m_activep);
VL_RESTORER(m_inClockedActive);
VL_RESTORER(m_inStaticActive);
m_activep = nodep;
m_inClockedActive = nodep->hasClocked();
m_inStaticActive = nodep->hasStatic();
// AstVarScope::user2 -> bool: Signal used in SenItem in *this* active block
const VNUser2InUse user2InUse;
@ -700,6 +708,9 @@ class GateInline final {
if (!VN_IS(substp, NodeVarRef)) continue;
}
// Only inline static initializer if constant known at compile time
if (lVtxp->staticInit() && !VN_IS(substp, Const)) continue;
// Process it
++m_statInlined;

View File

@ -13,6 +13,6 @@ test.scenarios('simulator')
test.compile(verilator_flags2=["--timing"])
test.execute(fails=test.vlt_all) # Issue #5381
test.execute()
test.passes()

View File

@ -15,7 +15,7 @@ module t (
input clk
);
str_t bar_in;
str_t bar_in = '0; // Set bar_in to 0 initially
str_t bar_out;
Sub sub (
@ -28,8 +28,6 @@ module t (
integer i;
str_t initOut;
bar_in = '0; // Set bar_in to 0 initially
// Wait for the first falling edge of the clock
@(negedge clk);