diff --git a/docs/guide/exe_verilator.rst b/docs/guide/exe_verilator.rst index 7069dd2aa..73ed42486 100644 --- a/docs/guide/exe_verilator.rst +++ b/docs/guide/exe_verilator.rst @@ -749,8 +749,8 @@ Summary: externally between evaluations. The optimization is automatically disabled for top level input signals that are written within the design. Accesses via the VPI cannot be analyzed at compile time, therefore :vlopt:`--vpi` - disables this optimization. It can be turned back on by explicitly passing - :vlopt:`-fico-change-detect`. + disables this optimization for all inputs; it may be turned back on by + explicitly passing :vlopt:`-fico-change-detect`. .. option:: -fno-inline diff --git a/src/V3AstNodeOther.h b/src/V3AstNodeOther.h index 579d62977..f9518bf63 100644 --- a/src/V3AstNodeOther.h +++ b/src/V3AstNodeOther.h @@ -2138,6 +2138,7 @@ class AstVar final : public AstNode { bool m_attrFsmArcInclCond : 1; // declared with fsm_arc_include_cond metacomment bool m_fileDescr : 1; // File descriptor bool m_gotNansiType : 1; // Linker saw Non-ANSI type declaration + bool m_icoMaybeWritten : 1; // Design might write this input signal - for ico change detect bool m_isConst : 1; // Table contains constant data bool m_isContinuously : 1; // Ever assigned continuously (for force/release) bool m_hasStrengthAssignment : 1; // Is on LHS of assignment with strength specifier @@ -2151,7 +2152,6 @@ class AstVar final : public AstNode { bool m_isDpiOpenArray : 1; // DPI import open array bool m_isHideLocal : 1; // Verilog local bool m_isHideProtected : 1; // Verilog protected - bool m_maybeWritten : 1; // Design might write to this signal (not very accurate) 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 @@ -2201,6 +2201,7 @@ class AstVar final : public AstNode { m_attrFsmArcInclCond = false; m_fileDescr = false; m_gotNansiType = false; + m_icoMaybeWritten = false; m_isConst = false; m_isContinuously = false; m_hasStrengthAssignment = false; @@ -2214,7 +2215,6 @@ class AstVar final : public AstNode { m_isDpiOpenArray = false; m_isHideLocal = false; m_isHideProtected = false; - m_maybeWritten = false; m_noCReset = false; m_noReset = false; m_noSubst = false; @@ -2381,14 +2381,14 @@ public: void hasStrengthAssignment(bool flag) { m_hasStrengthAssignment = flag; } bool hasUserInit() const { return m_hasUserInit; } void hasUserInit(bool flag) { m_hasUserInit = flag; } + void icoMaybeWritten(bool flag) { m_icoMaybeWritten = flag; } + bool icoMaybeWritten() const { return m_icoMaybeWritten; } bool isDpiOpenArray() const VL_MT_SAFE { return m_isDpiOpenArray; } void isDpiOpenArray(bool flag) { m_isDpiOpenArray = flag; } bool isHideLocal() const { return m_isHideLocal; } void isHideLocal(bool flag) { m_isHideLocal = flag; } bool isHideProtected() const { return m_isHideProtected; } void isHideProtected(bool flag) { m_isHideProtected = flag; } - void maybeWritten(bool flag) { m_maybeWritten = flag; } - bool maybeWritten() const { return m_maybeWritten; } bool noCReset() const { return m_noCReset; } void noCReset(bool flag) { m_noCReset = flag; } bool noReset() const { return m_noReset; } diff --git a/src/V3AstNodes.cpp b/src/V3AstNodes.cpp index 2c93b3d58..ef3efd271 100644 --- a/src/V3AstNodes.cpp +++ b/src/V3AstNodes.cpp @@ -630,6 +630,7 @@ void AstVar::combineType(const AstVar* otherp) { varType(otherp->varType()); direction(otherp->direction()); } + if (otherp->icoMaybeWritten()) icoMaybeWritten(true); } void AstVar::combineType(VVarType type) { // These flags get combined with the existing settings of the flags. @@ -3215,6 +3216,7 @@ void AstVar::dump(std::ostream& str) const { str << " [FUNC]"; } if (hasUserInit()) str << " [UINIT]"; + if (icoMaybeWritten()) str << " [ICOMAYBEWRITTEN]"; if (isDpiOpenArray()) str << " [DPIOPENA]"; if (ignorePostWrite()) str << " [IGNPWR]"; if (ignoreSchedWrite()) str << " [IGNWR]"; @@ -3243,6 +3245,7 @@ void AstVar::dumpJson(std::ostream& str) const { dumpJsonBoolFuncIf(str, attrFsmResetArc); dumpJsonBoolFuncIf(str, attrFsmArcInclCond); dumpJsonBoolFuncIf(str, attrFileDescr); + dumpJsonBoolFuncIf(str, icoMaybeWritten); dumpJsonBoolFuncIf(str, isDpiOpenArray); dumpJsonBoolFuncIf(str, isFuncReturn); dumpJsonBoolFuncIf(str, isFuncLocal); diff --git a/src/V3LinkLevel.cpp b/src/V3LinkLevel.cpp index e9099102c..066097239 100644 --- a/src/V3LinkLevel.cpp +++ b/src/V3LinkLevel.cpp @@ -291,7 +291,7 @@ void V3LinkLevel::wrapTopCell(AstNetlist* rootp) { varp->sigPublic(true); // User needs to be able to get to it... oldvarp->primaryIO(false); varp->primaryIO(true); - varp->maybeWritten(oldvarp->maybeWritten()); + varp->icoMaybeWritten(oldvarp->icoMaybeWritten()); if (varp->isRef() || varp->isConstRef()) { varp->v3warn(E_UNSUPPORTED, "Unsupported: ref/const ref as primary input/output: " diff --git a/src/V3Sched.cpp b/src/V3Sched.cpp index 784a173e9..217cd3f95 100644 --- a/src/V3Sched.cpp +++ b/src/V3Sched.cpp @@ -548,7 +548,7 @@ AstNode* createInputCombLoop(AstNetlist* netlistp, AstCFunc* const initFuncp, // Only for top level ports, assume outputs don't change externally if (!vscp->varp()->isPrimaryInish()) continue; // Don't do if written by the design - wouldn't update the change detect 'prev' value - if (vscp->varp()->maybeWritten()) continue; + if (vscp->varp()->icoMaybeWritten()) continue; // Don't do if forceable, as we can't see the actual value - this is belt and braces if (vscp->varp()->isForced()) continue; // Can't handle unpacked arrays (they have special types when primary input) diff --git a/src/V3Width.cpp b/src/V3Width.cpp index 91578132f..f5e55d2a7 100644 --- a/src/V3Width.cpp +++ b/src/V3Width.cpp @@ -3073,7 +3073,7 @@ class WidthVisitor final : public VNVisitor { UASSERT_OBJ(nodep->dtypep(), nodep, "LHS var should be dtype completed"); } // UINFOTREE(9, nodep, "", "VRout"); - if (nodep->access().isWriteOrRW()) nodep->varp()->maybeWritten(true); + if (nodep->access().isWriteOrRW()) nodep->varp()->icoMaybeWritten(true); if (nodep->access().isWriteOrRW() && nodep->varp()->direction() == VDirection::CONSTREF) { nodep->v3error("Assigning to const ref variable: " << nodep->prettyNameQ()); } else if (nodep->access().isWriteOrRW() && nodep->varp()->isInput()