From 7607f0e7fa0e3f6cfb742320316d793dfa072a9f Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Tue, 24 Feb 2026 14:04:43 -0500 Subject: [PATCH] Support proper automatic/static initialization, and remove STATICVAR warning (#6405). (#7086) --- Changes | 1 + docs/guide/warnings.rst | 9 +- src/V3AstNodeStmt.h | 32 +++ src/V3Begin.cpp | 95 +++++++- src/V3Const.cpp | 11 + src/V3EmitCFunc.cpp | 46 ++-- src/V3EmitCFunc.h | 28 ++- src/V3EmitV.cpp | 2 + src/V3Fork.cpp | 53 +++- src/V3Gate.cpp | 7 + src/V3LinkLValue.cpp | 8 +- src/V3LinkParse.cpp | 211 ++++++++++++---- src/V3Simulate.h | 8 + src/V3SplitVar.cpp | 45 +++- src/V3Tristate.cpp | 1 + src/V3Undriven.cpp | 67 ++++-- src/V3UndrivenCapture.cpp | 25 +- src/V3Width.cpp | 12 + test_regress/t/t_constraint_json_only.out | 10 +- test_regress/t/t_cover_line.out | 6 +- test_regress/t/t_cover_line_cc.info.out | 2 + test_regress/t/t_cover_line_expr.out | 6 +- test_regress/t/t_debug_emitv.out | 2 + test_regress/t/t_flag_csplit_groups.py | 2 +- test_regress/t/t_func_crc.py | 2 +- test_regress/t/t_hier_block_chained.py | 4 +- test_regress/t/t_json_only_debugcheck.out | 181 +++++++------- test_regress/t/t_json_only_flat_vlvbound.out | 36 +-- ...c_in_loop_unsup.py => t_static_in_loop.py} | 4 +- test_regress/t/t_static_in_loop.v | 6 +- test_regress/t/t_timing_debug2.out | 26 +- test_regress/t/t_var_init_static_automatic.py | 18 ++ test_regress/t/t_var_init_static_automatic.v | 226 ++++++++++++++++++ .../t/t_wrapper_context__top0.dat.out | 2 +- .../t/t_wrapper_context__top1.dat.out | 2 +- 35 files changed, 914 insertions(+), 282 deletions(-) rename test_regress/t/{t_static_in_loop_unsup.py => t_static_in_loop.py} (89%) create mode 100755 test_regress/t/t_var_init_static_automatic.py create mode 100644 test_regress/t/t_var_init_static_automatic.v diff --git a/Changes b/Changes index 954fc5f5b..aa4c4af90 100644 --- a/Changes +++ b/Changes @@ -28,6 +28,7 @@ Verilator 5.045 devel * Support nested interface as port connection (#5066) (#6986). [Leela Pakanati] * Support solve..before constraints (#5647) (#7123). [Yilou Wang] * Support structure initial values (#6130). +* Support proper automatic/static initialization, and remove STATICVAR warning (#6405). * Support vpi_put/vpi_get forcing of signals (#5933) (#6704). [Christian Hecken] * Support detailed failure info for constraint violations (#6617) (#6883). [Yilou Wang] * Support `unique` constraints (on 1D static arrays) (#6810) (#6878). [Srinivasan Venkataramanan] diff --git a/docs/guide/warnings.rst b/docs/guide/warnings.rst index 6e750d97a..2e38afff8 100644 --- a/docs/guide/warnings.rst +++ b/docs/guide/warnings.rst @@ -1982,13 +1982,10 @@ List Of Warnings .. option:: STATICVAR - Warns that a static variable declared in a loop with declaration assignment - was converted to automatic. Often such variables were intended to - instead be declared "automatic". + Historical, never issued since version 5.046. - Ignoring this warning may make Verilator differ from other simulators, - which will treat the variable as static. Verilator may in future versions also - treat the variable as static. + Warned that a static variable was declared in a loop with declaration + assignment, and Verilator converted it to an "automatic". .. option:: STMTDLY diff --git a/src/V3AstNodeStmt.h b/src/V3AstNodeStmt.h index c6caae754..3b9b7da94 100644 --- a/src/V3AstNodeStmt.h +++ b/src/V3AstNodeStmt.h @@ -756,6 +756,38 @@ public: ASTGEN_MEMBERS_AstFireEvent; bool isDelayed() const { return m_delayed; } }; +class AstInitialAutomaticStmt final : public AstNodeStmt { + // Automatic variable initialization in a statement position + // Used during early stages to record an initial initialization of a variable + // Moves later to an appropriate constructor, or AstInitialAutomatic, or + // AstCFunc normal statement + // Children: {statement list usually only with assignments} + // @astgen op1 := stmtsp : List[AstNode] +public: + AstInitialAutomaticStmt(FileLine* fl, AstNode* stmtsp) + : ASTGEN_SUPER_InitialAutomaticStmt(fl) { + addStmtsp(stmtsp); + } + ASTGEN_MEMBERS_AstInitialAutomaticStmt; + int instrCount() const override { return 0; } + bool isPure() override { return true; } +}; +class AstInitialStaticStmt final : public AstNodeStmt { + // Static variable initialization in a statement position + // Used during early stages to record a static initialization of a variable + // Moves later to an appropriate constructor, or AstInitialStatic, or + // AstCFunc normal statement + // Children: {statement list usually only with assignments} + // @astgen op1 := stmtsp : List[AstNode] +public: + AstInitialStaticStmt(FileLine* fl, AstNode* stmtsp) + : ASTGEN_SUPER_InitialStaticStmt(fl) { + addStmtsp(stmtsp); + } + ASTGEN_MEMBERS_AstInitialStaticStmt; + int instrCount() const override { return 0; } + bool isPure() override { return true; } +}; class AstJumpBlock final : public AstNodeStmt { // Block of code that might contain AstJumpGo statements as children, // which when exectued branch to right after the referenced AstJumpBlock. diff --git a/src/V3Begin.cpp b/src/V3Begin.cpp index 5bbe74667..b1b02ca0a 100644 --- a/src/V3Begin.cpp +++ b/src/V3Begin.cpp @@ -68,6 +68,7 @@ class BeginVisitor final : public VNVisitor { // STATE - for current visit position (use VL_RESTORER) AstNodeModule* m_modp = nullptr; // Current module AstNodeFTask* m_ftaskp = nullptr; // Current function/task + AstNodeProcedure* m_procedurep = nullptr; // Current procedure AstNode* m_liftedp = nullptr; // Local nodes we are lifting into m_ftaskp string m_displayScope; // Name of %m in $display/AstScopeName string m_namedScope; // Name of begin blocks above us @@ -120,17 +121,6 @@ class BeginVisitor final : public VNVisitor { } // VISITORS - void visit(AstFork* nodep) override { - dotNames(nodep->name(), nodep->fileline(), "__FORK__"); - iterateAndNextNull(nodep->stmtsp()); - { - // Keep begins in forks to group their statements together - VL_RESTORER(m_keepBegins); - m_keepBegins = true; - iterateAndNextNull(nodep->forksp()); - } - nodep->name(""); - } void visit(AstForeach* nodep) override { VL_DO_DANGLING(V3Begin::convertToWhile(nodep), nodep); } @@ -158,6 +148,11 @@ class BeginVisitor final : public VNVisitor { m_unnamedScope = ""; iterateChildren(nodep); } + void visit(AstNodeProcedure* nodep) override { + VL_RESTORER(m_procedurep); + m_procedurep = nodep; + iterateChildren(nodep); + } void visit(AstNodeFTask* nodep) override { UINFO(8, " " << nodep); // Rename it @@ -212,6 +207,27 @@ class BeginVisitor final : public VNVisitor { } VL_DO_DANGLING(pushDeletep(nodep->unlinkFrBack()), nodep); } + void visit(AstFork* nodep) override { + dotNames(nodep->name(), nodep->fileline(), "__FORK__"); + iterateAndNextNull(nodep->stmtsp()); + { + // Keep begins in forks to group their statements together + VL_RESTORER(m_keepBegins); + m_keepBegins = true; + iterateAndNextNull(nodep->forksp()); + } + AstNode* addsp = nullptr; + if (AstNode* const declsp = nodep->declsp()) { + declsp->unlinkFrBackWithNext(); + addsp = AstNode::addNext(addsp, declsp); + } + if (AstNode* const stmtsp = nodep->stmtsp()) { + stmtsp->unlinkFrBackWithNext(); + addsp = AstNode::addNext(addsp, stmtsp); + } + if (addsp) nodep->addHereThisAsNext(addsp); + nodep->name(""); + } void visit(AstBegin* nodep) override { // Begin blocks were only useful in variable creation, change names and delete UINFO(8, " " << nodep); @@ -246,6 +262,41 @@ class BeginVisitor final : public VNVisitor { } VL_DO_DANGLING(pushDeletep(nodep), nodep); } + void visit(AstNodeBlock* nodep) override { + // Begin/Fork blocks were only useful in variable creation, change names and delete + UINFO(8, " " << nodep); + VL_RESTORER(m_displayScope); + VL_RESTORER(m_namedScope); + VL_RESTORER(m_unnamedScope); + { + VL_RESTORER(m_keepBegins); + m_keepBegins = VN_IS(nodep, Fork); + dotNames(nodep->name(), nodep->fileline(), + VN_IS(nodep, Fork) ? "__FORK__" : "__BEGIN__"); + iterateChildren(nodep); + } + + // Cleanup + if (m_keepBegins) { + nodep->name(""); + return; + } + AstNode* addsp = nullptr; + if (AstNode* const declsp = nodep->declsp()) { + declsp->unlinkFrBackWithNext(); + addsp = AstNode::addNext(addsp, declsp); + } + if (AstNode* const stmtsp = nodep->stmtsp()) { + stmtsp->unlinkFrBackWithNext(); + addsp = AstNode::addNext(addsp, stmtsp); + } + if (addsp) { + nodep->replaceWith(addsp); + } else { + nodep->unlinkFrBack(); + } + VL_DO_DANGLING(pushDeletep(nodep), nodep); + } void visit(AstVar* nodep) override { // If static variable, move it outside a function. if (nodep->lifetime().isStatic() && m_ftaskp) { @@ -263,6 +314,28 @@ class BeginVisitor final : public VNVisitor { liftNode(nodep); } } + void visit(AstInitialAutomaticStmt* nodep) override { + // Automatic sets go at the current location + nodep->replaceWith(nodep->stmtsp()->unlinkFrBackWithNext()); + VL_DO_DANGLING(pushDeletep(nodep), nodep); + } + void visit(AstInitialStaticStmt* nodep) override { + // As we moved static variables, move static initializers too + if (nodep->user1SetOnce()) return; // Don't double-add text's + AstNode* wasUnderp = m_ftaskp; + if (!m_ftaskp) wasUnderp = m_procedurep; + if (wasUnderp) { + if (nodep->stmtsp()) { + AstNode* const newp = new AstInitialStatic{ + nodep->fileline(), nodep->stmtsp()->unlinkFrBackWithNext()}; + wasUnderp->addHereThisAsNext(newp); + iterateChildren(newp); + } + VL_DO_DANGLING(pushDeletep(nodep->unlinkFrBack()), nodep); + } else { + nodep->v3fatalSrc("InitialStaticStmt under unexpected grand-parent"); + } + } void visit(AstTypedef* nodep) override { if (m_unnamedScope != "") { // Rename it diff --git a/src/V3Const.cpp b/src/V3Const.cpp index 6f654e7d9..7ef77be05 100644 --- a/src/V3Const.cpp +++ b/src/V3Const.cpp @@ -3329,6 +3329,17 @@ class ConstVisitor final : public VNVisitor { varrefp->varp()->valuep(initvaluep); } } + void visit(AstCReset* nodep) override { + iterateChildren(nodep); + if (!m_doNConst) return; + const AstBasicDType* const bdtypep = VN_CAST(nodep->dtypep()->skipRefp(), BasicDType); + if (!bdtypep) return; + if (!bdtypep->isZeroInit()) return; + AstConst* const newp = new AstConst{nodep->fileline(), V3Number{nodep, bdtypep}}; + UINFO(9, "CRESET(0) => CONST(0) " << nodep); + nodep->replaceWith(newp); + VL_DO_DANGLING(pushDeletep(nodep), nodep); + } void visit(AstCvtArrayToArray* nodep) override { iterateChildren(nodep); // Handle the case where we have a stream operation inside a cast conversion diff --git a/src/V3EmitCFunc.cpp b/src/V3EmitCFunc.cpp index 6ff146d0a..efcf167c4 100644 --- a/src/V3EmitCFunc.cpp +++ b/src/V3EmitCFunc.cpp @@ -456,21 +456,22 @@ void EmitCFunc::emitCCallArgs(const AstNodeCCall* nodep, const string& selfPoint puts(")"); } -void EmitCFunc::emitDereference(AstNode* nodep, const string& pointer) { +std::string EmitCFunc::dereferenceString(const std::string& pointer) { if (pointer[0] == '(' && pointer[1] == '&') { // remove "address of" followed by immediate dereference // Note: this relies on only the form '(&OBJECT)' being used by Verilator - putns(nodep, pointer.substr(2, pointer.length() - 3)); - puts("."); + return pointer.substr(2, pointer.length() - 3) + '.'; } else { if (pointer == "vlSelf" && m_usevlSelfRef) { - puts("vlSelfRef."); + return "vlSelfRef."; } else { - putns(nodep, pointer); - puts("->"); + return pointer + "->"; } } } +void EmitCFunc::emitDereference(AstNode* nodep, const string& pointer) { + putns(nodep, dereferenceString(pointer)); +} void EmitCFunc::emitCvtPackStr(AstNode* nodep) { if (const AstConst* const constp = VN_CAST(nodep, Const)) { @@ -527,13 +528,16 @@ void EmitCFunc::emitSetVarConstant(const string& assignString, AstConst* constp) puts(";\n"); } -void EmitCFunc::emitVarReset(AstVar* varp, bool constructing) { - // 'constructing' indicates that the object was just constructed, so no need to clear it also +void EmitCFunc::emitVarReset(const string& prefix, AstVar* varp, bool constructing) { + // 'constructing' indicates that the object was just constructed, so if it is a string or + // something that starts off clear already, no need to clear it again AstNodeDType* const dtypep = varp->dtypep()->skipRefp(); const string vlSelf = VSelfPointerText::replaceThis(m_useSelfForThis, "this->"); - const string varNameProtected = (VN_IS(m_modp, Class) || varp->isFuncLocal()) - ? varp->nameProtect() - : vlSelf + varp->nameProtect(); + const string varNameProtected + = ((VN_IS(m_modp, Class) || varp->isFuncLocal()) || !prefix.empty()) + ? varp->nameProtect() + : vlSelf + varp->nameProtect(); + const string newPrefix = prefix + varNameProtected; if (varp->isIO() && m_modp->isTop() && optSystemC()) { // System C top I/O doesn't need loading, as the lower level subinst code does it.} } else if (varp->isParam()) { @@ -546,47 +550,45 @@ void EmitCFunc::emitVarReset(AstVar* varp, bool constructing) { // TODO merge this functionality with V3EmitCConstInit.h visitors if (VN_IS(dtypep, AssocArrayDType)) { if (initarp->defaultp()) { - emitSetVarConstant(varNameProtected + ".atDefault()", - VN_AS(initarp->defaultp(), Const)); + emitSetVarConstant(newPrefix + ".atDefault()", VN_AS(initarp->defaultp(), Const)); } if (!constructing) puts(varNameProtected + ".clear();"); const auto& mapr = initarp->map(); for (const auto& itr : mapr) { AstNode* const valuep = itr.second->valuep(); - emitSetVarConstant(varNameProtected + ".at(" + cvtToStr(itr.first) + ")", + emitSetVarConstant(newPrefix + ".at(" + cvtToStr(itr.first) + ")", VN_AS(valuep, Const)); } } else if (VN_IS(dtypep, WildcardArrayDType)) { if (initarp->defaultp()) { - emitSetVarConstant(varNameProtected + ".atDefault()", - VN_AS(initarp->defaultp(), Const)); + emitSetVarConstant(newPrefix + ".atDefault()", VN_AS(initarp->defaultp(), Const)); } - if (!constructing) puts(varNameProtected + ".clear();"); + if (!constructing) puts(newPrefix + ".clear();"); const auto& mapr = initarp->map(); for (const auto& itr : mapr) { AstNode* const valuep = itr.second->valuep(); - emitSetVarConstant(varNameProtected + ".at(" + cvtToStr(itr.first) + ")", + emitSetVarConstant(newPrefix + ".at(" + cvtToStr(itr.first) + ")", VN_AS(valuep, Const)); } } else if (AstUnpackArrayDType* const adtypep = VN_CAST(dtypep, UnpackArrayDType)) { if (initarp->defaultp()) { puts("for (int __Vi = 0; __Vi < " + cvtToStr(adtypep->elementsConst())); puts("; ++__Vi) {\n"); - emitSetVarConstant(varNameProtected + "[__Vi]", VN_AS(initarp->defaultp(), Const)); + emitSetVarConstant(newPrefix + "[__Vi]", VN_AS(initarp->defaultp(), Const)); puts("}\n"); } const auto& mapr = initarp->map(); for (const auto& itr : mapr) { AstNode* const valuep = itr.second->valuep(); - emitSetVarConstant(varNameProtected + "[" + cvtToStr(itr.first) + "]", + emitSetVarConstant(newPrefix + "[" + cvtToStr(itr.first) + "]", VN_AS(valuep, Const)); } } else { varp->v3fatalSrc("InitArray under non-arrayed var"); } } else { - putns(varp, emitVarResetRecurse(varp, constructing, varNameProtected, dtypep, 0, "", - varp->valuep())); + putns(varp, + emitVarResetRecurse(varp, constructing, newPrefix, dtypep, 0, "", varp->valuep())); } } diff --git a/src/V3EmitCFunc.h b/src/V3EmitCFunc.h index 6c67eda0f..1684cc1ca 100644 --- a/src/V3EmitCFunc.h +++ b/src/V3EmitCFunc.h @@ -209,12 +209,13 @@ public: AstNode* thsp); void emitCCallArgs(const AstNodeCCall* nodep, const string& selfPointer, bool inProcess); void emitDereference(AstNode* nodep, const string& pointer); + std::string dereferenceString(const std::string& pointer); void emitCvtPackStr(AstNode* nodep); void emitCvtWideArray(AstNode* nodep, AstNode* fromp); void emitConstant(AstConst* nodep); void emitConstantString(const AstConst* nodep); void emitSetVarConstant(const string& assignString, AstConst* constp); - void emitVarReset(AstVar* varp, bool constructing); + void emitVarReset(const string& prefix, AstVar* varp, bool constructing); string emitVarResetRecurse(const AstVar* varp, bool constructing, const string& varNameProtected, AstNodeDType* dtypep, int depth, const string& suffix, const AstNode* valuep); @@ -526,8 +527,29 @@ public: void visit(AstNodeAssign* nodep) override { if (AstCReset* const resetp = VN_CAST(nodep->rhsp(), CReset)) { - AstVar* const varp = VN_AS(nodep->lhsp(), NodeVarRef)->varp(); - emitVarReset(varp, resetp->constructing()); + // TODO get rid of emitVarReset and instead let AstNodeAssign understand how to init + // anything + AstNode* fromp = nodep->lhsp(); + // Fork needs to use a member select. Nothing else should be possible before VarRef. + if (AstMemberSel* const sfromp = VN_CAST(fromp, MemberSel)) { + // Fork-DynScope generated pointer to previously automatic variable + AstVar* const memberVarp = sfromp->varp(); + fromp = sfromp->fromp(); + if (AstNullCheck* const sfromp = VN_CAST(fromp, NullCheck)) fromp = sfromp->lhsp(); + AstNodeVarRef* const fromVarRefp = VN_AS(fromp, NodeVarRef); + emitVarReset( + ("VL_NULL_CHECK("s + + (fromVarRefp->selfPointer().isEmpty() + ? "" + : dereferenceString(fromVarRefp->selfPointerProtect(m_useSelfForThis))) + + fromVarRefp->varp()->nameProtect() + ", \"" + + V3OutFormatter::quoteNameControls(protect(nodep->fileline()->filename())) + + "\", " + std::to_string(nodep->fileline()->lineno()) + ")->"), + memberVarp, resetp->constructing()); + } else { + AstVar* const varp = VN_AS(fromp, NodeVarRef)->varp(); + emitVarReset("", varp, resetp->constructing()); + } return; } bool paren = true; diff --git a/src/V3EmitV.cpp b/src/V3EmitV.cpp index 65d9f035f..904da3186 100644 --- a/src/V3EmitV.cpp +++ b/src/V3EmitV.cpp @@ -182,6 +182,8 @@ class EmitVBaseVisitorConst VL_NOT_FINAL : public VNVisitorConst { } void visit(AstInitialAutomatic* nodep) override { iterateChildrenConst(nodep); } void visit(AstInitialStatic* nodep) override { iterateChildrenConst(nodep); } + void visit(AstInitialAutomaticStmt* nodep) override { iterateChildrenConst(nodep); } + void visit(AstInitialStaticStmt* nodep) override { iterateChildrenConst(nodep); } void visit(AstAlways* nodep) override { if (const AstAssignW* const ap = VN_CAST(nodep->stmtsp(), AssignW)) { if (!ap->nextp()) { diff --git a/src/V3Fork.cpp b/src/V3Fork.cpp index 7b8d065d9..e5f636338 100644 --- a/src/V3Fork.cpp +++ b/src/V3Fork.cpp @@ -335,13 +335,31 @@ class DynScopeVisitor final : public VNVisitor { auto r = m_frames.emplace(nodep, framep); if (r.second) m_frameOrder.push_back(nodep); } + void bindInitIterate(AstNode* stmtsp, ForkDynScopeFrame* framep) { + for (AstNode* stmtp = stmtsp; stmtp; stmtp = stmtp->nextp()) { + if (AstAssign* const asgnp = VN_CAST(stmtp, Assign)) { + bindNodeToDynScope(asgnp->lhsp(), framep); + iterate(asgnp->rhsp()); + } else if (AstInitialAutomaticStmt* astmtp + = VN_CAST(stmtp, InitialAutomaticStmt)) { // Moves in V3Begin + // Underlying assign RHS might use function argument, so can't just + // move whole thing into the new class's constructor/statements + bindInitIterate(astmtp->stmtsp(), framep); + } else if (AstInitialStaticStmt* astmtp + = VN_CAST(stmtp, InitialStaticStmt)) { // Moves in V3Begin + bindInitIterate(astmtp->stmtsp(), framep); + } else { + stmtp->v3fatalSrc("Invalid node under block item initialization part of fork"); + } + } + } bool needsDynScope(const AstVarRef* refp) const { const AstVar* const varp = refp->varp(); - const bool localLifetime = varp->isFuncLocal() || varp->lifetime().isAutomatic(); return // Can this variable escape the scope - ((m_forkDepth > varp->user1()) && localLifetime) + ((m_forkDepth > varp->user1()) && varp->isFuncLocal()) + && varp->lifetime().isAutomatic() && ( // Is it mutated (varp->isClassHandleValue() ? refp->user2() : refp->access().isWriteOrRW()) @@ -384,18 +402,14 @@ class DynScopeVisitor final : public VNVisitor { for (AstNode* declp = nodep->declsp(); declp; declp = declp->nextp()) { AstVar* const varp = VN_CAST(declp, Var); UASSERT_OBJ(varp, declp, "Invalid node under block item initialization part of fork"); - if (!framep->instance().initialized()) framep->createInstancePrototype(); - framep->captureVarInsert(varp); - bindNodeToDynScope(varp, framep); - } - for (AstNode* stmtp = nodep->stmtsp(); stmtp; stmtp = stmtp->nextp()) { - if (AstAssign* const asgnp = VN_CAST(stmtp, Assign)) { - bindNodeToDynScope(asgnp->lhsp(), framep); - iterate(asgnp->rhsp()); - } else { - stmtp->v3fatalSrc("Invalid node under block item initialization part of fork"); + UASSERT_OBJ(!varp->lifetime().isNone(), nodep, "Variable's lifetime is unknown"); + if (varp->lifetime().isAutomatic()) { // else V3Begin will move later + if (!framep->instance().initialized()) framep->createInstancePrototype(); + framep->captureVarInsert(varp); + bindNodeToDynScope(varp, framep); } } + bindInitIterate(nodep->stmtsp(), framep); for (AstNode* stmtp = nodep->forksp(); stmtp; stmtp = stmtp->nextp()) { m_afterTimingControl = false; @@ -526,6 +540,7 @@ class ForkVisitor final : public VNVisitor { // STATE - for current AstFork item bool m_inFork = false; // Traversal in an async fork + bool m_inInitStmt = false; // Traversal in InitialStaticStmt/InitialAutomaticStmt std::set m_forkLocalsp; // Variables local to a given fork AstVar* m_capturedVarsp = nullptr; // Local copies of captured variables AstArg* m_capturedArgsp = nullptr; // References to captured variables (as args) @@ -650,7 +665,8 @@ class ForkVisitor final : public VNVisitor { // If this ref is to a variable that will move into the task, then nothing to do if (m_forkLocalsp.count(varp)) return; - if (nodep->access().isWriteOrRW() && (!nodep->isClassHandleValue() || nodep->user2())) { + if (nodep->access().isWriteOrRW() && (!nodep->isClassHandleValue() || nodep->user2()) + && !m_inInitStmt) { nodep->v3warn( E_LIFETIME, "Invalid reference: Process might outlive variable " @@ -671,6 +687,17 @@ class ForkVisitor final : public VNVisitor { } iterateChildren(nodep); } + void visit(AstInitialAutomaticStmt* nodep) override { + VL_RESTORER(m_inInitStmt); + m_inInitStmt = true; + iterateChildren(nodep); + } + void visit(AstInitialStaticStmt* nodep) override { + VL_RESTORER(m_inInitStmt); + m_inInitStmt = true; + iterateChildren(nodep); + } + void visit(AstThisRef* nodep) override {} void visit(AstNode* nodep) override { iterateChildren(nodep); } diff --git a/src/V3Gate.cpp b/src/V3Gate.cpp index ed078eee6..182a451c7 100644 --- a/src/V3Gate.cpp +++ b/src/V3Gate.cpp @@ -456,6 +456,13 @@ class GateOkVisitor final : public VNVisitorConst { clearSimple("Not a buffer (goes to a clock)"); } } + void visit(AstCReset* nodep) override { + if (!m_isSimple) return; + // CReset is pure because we can optimize assignments, but if is + // the only assignment to a variable we still need to initial + // assign to get randomization etc + clearSimple("CReset"); + } //-------------------- void visit(AstNode* nodep) override { if (!m_isSimple) return; // Fastpath diff --git a/src/V3LinkLValue.cpp b/src/V3LinkLValue.cpp index 9258d7fa4..c8a701888 100644 --- a/src/V3LinkLValue.cpp +++ b/src/V3LinkLValue.cpp @@ -39,6 +39,7 @@ class LinkLValueVisitor final : public VNVisitor { bool m_setStrengthSpecified = false; // Set that var has assignment with strength specified. bool m_inFunc = false; // Set if inside AstNodeFTask bool m_inInitialStatic = false; // Set if inside AstInitialStatic + bool m_inInitialStaticStmt = false; // Set if inside AstInitialStaticStmt VAccess m_setRefLvalue; // Set VarRefs to lvalues for pin assignments // VISITORS @@ -113,7 +114,7 @@ class LinkLValueVisitor final : public VNVisitor { iterateAndNextNull(nodep->rhsp()); } - if (m_inInitialStatic && m_inFunc) { + if ((m_inInitialStatic || m_inInitialStaticStmt) && m_inFunc) { const bool rhsHasIO = nodep->rhsp()->exists([](const AstNodeVarRef* const refp) { // Exclude module I/O referenced from a function/task. return refp->varp() && refp->varp()->isIO() @@ -147,6 +148,11 @@ class LinkLValueVisitor final : public VNVisitor { m_inInitialStatic = true; iterateChildren(nodep); } + void visit(AstInitialStaticStmt* nodep) override { + VL_RESTORER(m_inInitialStaticStmt); + m_inInitialStaticStmt = true; + iterateChildren(nodep); + } void visit(AstRelease* nodep) override { VL_RESTORER(m_setRefLvalue); VL_RESTORER(m_setContinuously); diff --git a/src/V3LinkParse.cpp b/src/V3LinkParse.cpp index 1bd5691b4..4e238c75f 100644 --- a/src/V3LinkParse.cpp +++ b/src/V3LinkParse.cpp @@ -57,6 +57,8 @@ class LinkParseVisitor final : public VNVisitor { AstNodeProcedure* m_procedurep = nullptr; // Current procedure AstNodeFTask* m_ftaskp = nullptr; // Current task AstNodeBlock* m_blockp = nullptr; // Current AstNodeBlock + AstNodeStmt* m_blockAddAutomaticStmtp = nullptr; // Initial statements to add to block + AstNodeStmt* m_blockAddStaticStmtp = nullptr; // Initial statements to add to block AstNodeDType* m_dtypep = nullptr; // Current data type AstNodeExpr* m_defaultInSkewp = nullptr; // Current default input skew AstNodeExpr* m_defaultOutSkewp = nullptr; // Current default output skew @@ -66,9 +68,9 @@ class LinkParseVisitor final : public VNVisitor { int m_beginDepth = 0; // How many begin blocks above current node within current AstNodeModule int m_randSequenceNum = 0; // RandSequence uniqify number VLifetime m_lifetime = VLifetime::STATIC_IMPLICIT; // Propagating lifetime - bool m_insideLoop = false; // True if the node is inside a loop bool m_lifetimeAllowed = false; // True to allow lifetime settings bool m_moduleWithGenericIface = false; // If current module contains generic interface + std::set m_portDups; // Non-ANSI port datatype duplicating input/output decls // STATE - Statistic tracking VDouble0 m_statModules; // Number of modules seen @@ -181,6 +183,54 @@ class LinkParseVisitor final : public VNVisitor { << nodep->warnContextSecondary()); } + void collectPorts(AstNode* nodeListp) { + // V3LinkDot hasn't run yet, so have VAR for pre-IEEE 'input' and + // separate var for pre-IEEE 'integer'. + std::unordered_map portNames; + for (AstNode* nodep = nodeListp; nodep; nodep = nodep->nextp()) { + if (AstVar* const varp = VN_CAST(nodep, Var)) { + if (varp->isIO()) portNames.emplace(varp->name(), varp); + } + } + for (AstNode* nodep = nodeListp; nodep; nodep = nodep->nextp()) { + if (AstVar* const varp = VN_CAST(nodep, Var)) { + if (varp->isIO()) continue; + const auto it = portNames.find(varp->name()); + if (it == portNames.end()) continue; + AstVar* const iop = it->second; + UINFO(9, "Non-ANSI port dtype declaration " << varp); + if (!iop->valuep() && varp->valuep()) + iop->valuep(varp->valuep()->unlinkFrBackWithNext()); + m_portDups.emplace(varp); + } + } + } + + AstNode* getVarsAndUnlink(AstNode* stmtsp) { + AstNode* varsp = nullptr; + for (AstNode *nextp, *itemp = stmtsp; itemp; itemp = nextp) { + nextp = itemp->nextp(); + if (VN_IS(itemp, Var)) varsp = AstNode::addNext(varsp, itemp->unlinkFrBack()); + } + return varsp; + } + AstNodeStmt* getBlockAdds() { + AstNodeStmt* addsp = nullptr; + // Add a single AstInitial...Stmt as the statements within may + // depend on each other, e.g. "var a=1; var b=a;" (but must be a constant expression) + if (m_blockAddStaticStmtp) + addsp = AstNode::addNext(addsp, + new AstInitialStaticStmt{m_blockAddStaticStmtp->fileline(), + m_blockAddStaticStmtp}); + if (m_blockAddAutomaticStmtp) + addsp = AstNode::addNext( + addsp, new AstInitialAutomaticStmt{m_blockAddAutomaticStmtp->fileline(), + m_blockAddAutomaticStmtp}); + m_blockAddStaticStmtp = nullptr; + m_blockAddAutomaticStmtp = nullptr; + return addsp; + } + // VISITORS void visit(AstNodeFTask* nodep) override { if (nodep->user1SetOnce()) return; // Process only once. @@ -191,6 +241,10 @@ class LinkParseVisitor final : public VNVisitor { cleanFileline(nodep); VL_RESTORER(m_ftaskp); m_ftaskp = nodep; + VL_RESTORER(m_blockAddAutomaticStmtp); + m_blockAddAutomaticStmtp = nullptr; + VL_RESTORER(m_blockAddStaticStmtp); + m_blockAddStaticStmtp = nullptr; VL_RESTORER(m_lifetime); VL_RESTORER(m_lifetimeAllowed); m_lifetimeAllowed = true; @@ -212,7 +266,26 @@ class LinkParseVisitor final : public VNVisitor { << nodep->warnMore() << "... May have intended 'static " << nodep->verilogKwd() << "'"); } + + VL_RESTORER(m_portDups); + collectPorts(nodep->stmtsp()); + iterateChildren(nodep); + + // If let, the statement must go first + AstNode* stmtsp = nullptr; + if (VN_IS(nodep, Let) && nodep->stmtsp()) stmtsp = nodep->stmtsp()->unlinkFrBack(); + // Move all Vars to front of function + stmtsp = AstNode::addNextNull(stmtsp, getVarsAndUnlink(nodep->stmtsp())); + // Follow vars by m_blockAddp's (if any) + stmtsp = AstNode::addNextNull(stmtsp, getBlockAdds()); + if (stmtsp) { + if (nodep->stmtsp()) { + nodep->stmtsp()->addHereThisAsNext(stmtsp); + } else { + nodep->addStmtsp(stmtsp); + } + } } void visit(AstNodeDType* nodep) override { visitIterateNodeDType(nodep); } void visit(AstConstraint* nodep) override { @@ -267,19 +340,13 @@ class LinkParseVisitor final : public VNVisitor { cleanFileline(nodep); UINFO(9, "VAR " << nodep); if (nodep->valuep()) nodep->hasUserInit(true); - if (m_insideLoop && nodep->lifetime().isNone() && nodep->varType() == VVarType::VAR - && !nodep->direction().isAny()) { - nodep->lifetime(VLifetime::AUTOMATIC_IMPLICIT); - } - if (nodep->lifetime().isStatic() && m_insideLoop && nodep->valuep()) { - nodep->lifetime(VLifetime::AUTOMATIC_IMPLICIT); - nodep->v3warn(STATICVAR, "Static variable with assignment declaration declared in a " - "loop converted to automatic"); - } else if (nodep->valuep() && nodep->lifetime().isNone() && m_lifetime.isStatic() - && !nodep->isIO() - && !nodep->isParam() - // In task, or a procedure but not Initial/Final as executed only once - && ((m_ftaskp && !m_ftaskp->lifetime().isStaticExplicit()) || m_procedurep)) { + // IEEE 1800-2026 6.21: for loop variables are automatic. verilog.y is + // responsible for marking those. + if (nodep->valuep() && nodep->lifetime().isNone() && m_lifetime.isStatic() + && !nodep->isIO() + && !nodep->isParam() + // In task, or a procedure but not Initial/Final as executed only once + && ((m_ftaskp && !m_ftaskp->lifetime().isStaticExplicit()) || m_procedurep)) { if (VN_IS(m_modp, Module) && m_ftaskp) { m_ftaskp->v3warn( IMPLICITSTATIC, @@ -415,43 +482,75 @@ class LinkParseVisitor final : public VNVisitor { // temporaries under an always aren't expected to be blocking if (m_procedurep && VN_IS(m_procedurep, Always)) nodep->fileline()->modifyWarnOff(V3ErrorCode::BLKSEQ, true); - if (nodep->valuep()) { - FileLine* const fl = nodep->valuep()->fileline(); - // A variable with an = value can be 4 things: - if (nodep->isParam() || (m_ftaskp && nodep->isNonOutput())) { + // Compute initial value + if (nodep->valuep() || nodep->needsCReset()) { + FileLine* const fl = nodep->valuep() ? nodep->valuep()->fileline() : nodep->fileline(); + auto createValuep = [&]() -> AstNodeExpr* { + if (nodep->valuep()) { + return VN_AS(nodep->valuep()->unlinkFrBack(), NodeExpr); + } else { + return new AstCReset{fl, nodep, false}; + } + }; + // A variable can be in these positions related to having an initial value (or not): + if (m_portDups.find(nodep) != m_portDups.end()) { + // 0. Non-ANSI type declaration that is really a port, but we haven't resolved yet + // Earlier moved any valuep() under the duplicate to the IO declaration + UINFO(9, "VarInit case0 " << nodep); + } else if (nodep->isParam() || nodep->isGenVar() + || (m_ftaskp && (nodep->isNonOutput() || nodep->isFuncReturn()))) { // 1. Parameters and function inputs: It's a default to use if not overridden + UINFO(9, "VarInit case1 " << nodep); } else if (!m_ftaskp && !VN_IS(m_modp, Class) && nodep->isNonOutput() && !nodep->isInput()) { // 2. Module inout/ref/constref: const default to use - nodep->v3warn(E_UNSUPPORTED, - "Unsupported: Default value on module inout/ref/constref: " - << nodep->prettyNameQ()); - nodep->valuep()->unlinkFrBack()->deleteTree(); - } else if (m_blockp) { + UINFO(9, "VarInit case2 " << nodep); + if (nodep->valuep()) { + nodep->v3warn(E_UNSUPPORTED, + "Unsupported: Default value on module inout/ref/constref: " + << nodep->prettyNameQ()); + nodep->valuep()->unlinkFrBack()->deleteTree(); + } + } else if (m_blockp || m_ftaskp) { // 3. Under blocks, it's an initial value to be under an assign - // TODO: This is wrong if it's a static variable right? + UINFO(9, "VarInit case3 " << nodep); + nodep->noCReset(true); FileLine* const newfl = new FileLine{fl}; newfl->warnOff(V3ErrorCode::E_CONSTWRITTEN, true); - m_blockp->addStmtsp( - new AstAssign{newfl, new AstVarRef{newfl, nodep, VAccess::WRITE}, - VN_AS(nodep->valuep()->unlinkFrBack(), NodeExpr)}); + AstAssign* const assp + = new AstAssign{newfl, new AstParseRef{newfl, nodep->name()}, createValuep()}; + if (nodep->lifetime().isAutomatic()) { + // May later make: new AstInitialAutomaticStmt{newfl, assp}; + m_blockAddAutomaticStmtp = AstNode::addNext(m_blockAddAutomaticStmtp, assp); + } else { + // May later make: new AstInitialStaticStmt{newfl, assp}; + m_blockAddStaticStmtp = AstNode::addNext(m_blockAddStaticStmtp, assp); + } } else if (m_valueModp) { // 4. Under modules/class, it's the time 0 initialziation value // Making an AstAssign (vs AstAssignW) to a wire is an error, suppress it - FileLine* const newfl = new FileLine{fl}; - newfl->warnOff(V3ErrorCode::PROCASSWIRE, true); - newfl->warnOff(V3ErrorCode::E_CONSTWRITTEN, true); - // Create a ParseRef to the wire. We cannot use the var as it may be deleted if - // it's a port (see t_var_set_link.v) - AstAssign* const assp - = new AstAssign{newfl, new AstParseRef{newfl, nodep->name()}, - VN_AS(nodep->valuep()->unlinkFrBack(), NodeExpr)}; - if (nodep->lifetime().isAutomatic()) { - nodep->addNextHere(new AstInitialAutomatic{newfl, assp}); - } else { - nodep->addNextHere(new AstInitialStatic{newfl, assp}); + UINFO(9, "VarInit case4 " << nodep); + if (nodep->valuep()) { + nodep->noCReset(true); + FileLine* const newfl = new FileLine{fl}; + newfl->warnOff(V3ErrorCode::PROCASSWIRE, true); + newfl->warnOff(V3ErrorCode::E_CONSTWRITTEN, true); + // Create a ParseRef to the wire. We cannot use the var as it may be deleted if + // it's a port (see t_var_set_link.v) + AstAssign* const assp = new AstAssign{ + newfl, new AstParseRef{newfl, nodep->name()}, createValuep()}; + AstNode* newInitp; + // Must make a unique InitialAutomatic/Static for each + // variable or otherwise V3Gate will assume ordering + // within, and not properly optimize. + if (nodep->lifetime().isAutomatic()) { + newInitp = new AstInitialAutomatic{newfl, assp}; + } else { + newInitp = new AstInitialStatic{newfl, assp}; + } + nodep->addNextHere(newInitp); } - } else { + } else if (nodep->valuep()) { nodep->v3fatalSrc("Variable with initializer in unexpected position"); } } @@ -592,8 +691,6 @@ class LinkParseVisitor final : public VNVisitor { // 2. ASTSELBIT(first, var0)) // 3. ASTSELLOOPVARS(first, var0..var1)) // 4. DOT(DOT(first, second), ASTSELBIT(third, var0)) - VL_RESTORER(m_insideLoop); - m_insideLoop = true; AstForeachHeader* const headerp = nodep->headerp(); if (!headerp->elementsp()) { nodep->v3error("Foreach missing bracketed loop variable is no-operation" @@ -605,15 +702,11 @@ class LinkParseVisitor final : public VNVisitor { } void visit(AstRepeat* nodep) override { cleanFileline(nodep); - VL_RESTORER(m_insideLoop); - m_insideLoop = true; checkIndent(nodep, nodep->stmtsp()); iterateChildren(nodep); } void visit(AstLoop* nodep) override { cleanFileline(nodep); - VL_RESTORER(m_insideLoop); - m_insideLoop = true; if (VN_IS(nodep->stmtsp(), LoopTest)) { checkIndent(nodep, nodep->stmtsp()->nextp()); } else { @@ -680,6 +773,10 @@ class LinkParseVisitor final : public VNVisitor { nodep->v3warn(E_UNSUPPORTED, "Module cannot be named 'TOP' as conflicts with " "Verilator top-level internals"); } + + VL_RESTORER(m_portDups); + collectPorts(nodep->stmtsp()); + iterateChildren(nodep); if (AstModule* const modp = VN_CAST(nodep, Module)) { modp->hasGenericIface(m_moduleWithGenericIface); @@ -781,14 +878,14 @@ class LinkParseVisitor final : public VNVisitor { iterateChildren(nodep); } void visit(AstNodeBlock* nodep) override { + VL_RESTORER(m_blockAddAutomaticStmtp); + m_blockAddAutomaticStmtp = nullptr; + VL_RESTORER(m_blockAddStaticStmtp); + m_blockAddStaticStmtp = nullptr; { VL_RESTORER(m_blockp); m_blockp = nodep; - // Temporarily unlink the statements so variable initializers can be inserted in order - AstNode* const stmtsp = nodep->stmtsp(); - if (stmtsp) stmtsp->unlinkFrBackWithNext(); iterateAndNextNull(nodep->declsp()); - nodep->addStmtsp(stmtsp); } if (AstBegin* const beginp = VN_CAST(nodep, Begin)) { @@ -797,6 +894,20 @@ class LinkParseVisitor final : public VNVisitor { cleanFileline(nodep); iterateAndNextNull(nodep->stmtsp()); if (AstFork* const forkp = VN_CAST(nodep, Fork)) iterateAndNextNull(forkp->forksp()); + // Add statements created by AstVar vistor; can't do as-go because iteration + // would then get confused, additionally we did already iterate the contents + AstNode* stmtsp = nullptr; + // Move all Vars to front of function + stmtsp = AstNode::addNextNull(stmtsp, getVarsAndUnlink(nodep->stmtsp())); + // Follow vars by m_blockAddp's (if any) + stmtsp = AstNode::addNextNull(stmtsp, getBlockAdds()); + if (stmtsp) { + if (nodep->stmtsp()) { + nodep->stmtsp()->addHereThisAsNext(stmtsp); + } else { + nodep->addStmtsp(stmtsp); + } + } } void visit(AstCase* nodep) override { V3Control::applyCase(nodep); diff --git a/src/V3Simulate.h b/src/V3Simulate.h index 0fd8b97ea..7b16dec7f 100644 --- a/src/V3Simulate.h +++ b/src/V3Simulate.h @@ -574,6 +574,14 @@ private: checkNodeInfo(nodep); iterateChildrenConst(nodep); } + void visit(AstInitialAutomaticStmt* nodep) override { + checkNodeInfo(nodep); + iterateChildrenConst(nodep); + } + void visit(AstInitialStaticStmt* nodep) override { + checkNodeInfo(nodep); + iterateChildrenConst(nodep); + } void visit(AstInitialStatic* nodep) override { if (jumpingOver()) return; if (!m_params) { diff --git a/src/V3SplitVar.cpp b/src/V3SplitVar.cpp index 949988506..62c386293 100644 --- a/src/V3SplitVar.cpp +++ b/src/V3SplitVar.cpp @@ -836,10 +836,17 @@ public: // If this is AstVarRef and referred in the sensitivity list of always@, // return the sensitivity item AstSenItem* backSenItemp() const { - if (const AstVarRef* const refp = VN_CAST(m_nodep, VarRef)) { - return VN_CAST(refp->backp(), SenItem); - } - return nullptr; + const AstVarRef* const refp = VN_CAST(m_nodep, VarRef); + if (!refp) return nullptr; + return VN_CAST(refp->backp(), SenItem); + } + AstNodeAssign* backCResetp() const { + const AstVarRef* const refp = VN_CAST(m_nodep, VarRef); + if (!refp) return nullptr; + AstNodeAssign* const assp = VN_CAST(refp->backp(), NodeAssign); + if (!assp) return nullptr; + if (!VN_IS(assp->rhsp(), CReset)) return nullptr; + return assp; } }; @@ -1027,7 +1034,8 @@ class SplitPackedVarVisitor final : public VNVisitor, public SplitVarImpl { UINFO(4, var.varp()->prettyNameQ() << "[" << msb << ":" << lsb << "] used for " << ref.nodep()->prettyNameQ() << '\n'); // LSB of varp is always 0. "lsb - var.lsb()" means this. see also SplitNewVar - return new AstSel{fl, refp, lsb - var.lsb(), bitwidth}; + AstNodeExpr* const newp = new AstSel{fl, refp, lsb - var.lsb(), bitwidth}; + return newp; } } static void connectPortAndVar(const std::vector& vars, AstVar* portp, @@ -1083,6 +1091,7 @@ class SplitPackedVarVisitor final : public VNVisitor, public SplitVarImpl { dtypep->rangep(new AstRange{ varp->fileline(), VNumRange{newvar.msb(), newvar.lsb(), basicp->ascending()}}); newvar.varp(new AstVar{varp->fileline(), VVarType::VAR, name, dtypep}); + newvar.varp()->lifetime(varp->lifetime()); newvar.varp()->propagateAttrFrom(varp); newvar.varp()->funcLocal(varp->isFuncLocal() || varp->isFuncReturn()); // Enable this line to trace split variable directly: @@ -1092,6 +1101,15 @@ class SplitPackedVarVisitor final : public VNVisitor, public SplitVarImpl { UINFO(4, newvar.varp()->prettyNameQ() << " is added for " << varp->prettyNameQ()); } } + static AstAssign* newAssignCReset(AstNodeAssign* cresetAssp, AstVar* attachVarp) { + AstCReset* const cresetp = VN_AS(cresetAssp->rhsp(), CReset); + AstCReset* const newCResetp = cresetp->cloneTree(false); + newCResetp->dtypeFrom(attachVarp); + AstAssign* const newp = new AstAssign{ + cresetAssp->fileline(), + new AstVarRef{cresetAssp->fileline(), attachVarp, VAccess::WRITE}, newCResetp}; + return newp; + } static void updateReferences(AstVar* varp, PackedVarRef& pref, const std::vector& vars) { for (const bool lvalue : {false, true}) { // Refer the new split variables @@ -1102,9 +1120,14 @@ class SplitPackedVarVisitor final : public VNVisitor, public SplitVarImpl { UASSERT_OBJ(varit != vars.end(), ref.nodep(), "Not found"); UASSERT(!(varit->msb() < ref.lsb() || ref.msb() < varit->lsb()), "wrong search result"); - AstNode* prevp; + AstNode* prevp = nullptr; bool inSentitivityList = false; - if (AstSenItem* const senitemp = ref.backSenItemp()) { + AstNodeAssign* const cresetAssp = ref.backCResetp(); + if (cresetAssp) { + // ASSIGN(VARREF old, CRESET) convert to a creset of each new var + cresetAssp->addNextHere(newAssignCReset(cresetAssp, varit->varp())); + } else if (AstSenItem* const senitemp = ref.backSenItemp()) { + // SENITEM(VARREF old) convert to a list of separate SenItems for each new var AstNode* const oldsenrefp = senitemp->sensp(); oldsenrefp->replaceWith( new AstVarRef{senitemp->fileline(), varit->varp(), VAccess::READ}); @@ -1118,7 +1141,9 @@ class SplitPackedVarVisitor final : public VNVisitor, public SplitVarImpl { residue -= varit->bitwidth()) { ++varit; UASSERT_OBJ(varit != vars.end(), ref.nodep(), "not enough split variables"); - if (AstSenItem* const senitemp = VN_CAST(prevp, SenItem)) { + if (cresetAssp) { + cresetAssp->addNextHere(newAssignCReset(cresetAssp, varit->varp())); + } else if (AstSenItem* const senitemp = VN_CAST(prevp, SenItem)) { prevp = new AstSenItem{ senitemp->fileline(), senitemp->edgeType(), new AstVarRef{senitemp->fileline(), varit->varp(), VAccess::READ}}; @@ -1135,7 +1160,9 @@ class SplitPackedVarVisitor final : public VNVisitor, public SplitVarImpl { // split() if (varp->isIO() && (varp->isFuncLocal() || varp->isFuncReturn())) connectPortAndVar(vars, varp, ref.nodep()); - if (!inSentitivityList) ref.replaceNodeWith(prevp); + if (!inSentitivityList && !cresetAssp) ref.replaceNodeWith(prevp); + if (cresetAssp) + VL_DO_DANGLING(cresetAssp->unlinkFrBack()->deleteTree(), cresetAssp); UASSERT_OBJ(varit->msb() >= ref.msb(), varit->varp(), "Out of range"); } } diff --git a/src/V3Tristate.cpp b/src/V3Tristate.cpp index 39aa49a8d..667184be7 100644 --- a/src/V3Tristate.cpp +++ b/src/V3Tristate.cpp @@ -1296,6 +1296,7 @@ class TristateVisitor final : public TristateBaseVisitor { void visitAssign(AstNodeAssign* nodep) { VL_RESTORER(m_alhs); VL_RESTORER(m_currentStrength); + if (VN_IS(nodep->rhsp(), CReset)) return; if (m_graphing) { if (AstAssignW* assignWp = VN_CAST(nodep, AssignW)) { if (assignWp->timingControlp() || assignWp->getLhsNetDelay()) return; diff --git a/src/V3Undriven.cpp b/src/V3Undriven.cpp index 9074d7140..b108f40bb 100644 --- a/src/V3Undriven.cpp +++ b/src/V3Undriven.cpp @@ -117,17 +117,17 @@ private: } public: - void usedWhole() { - UINFO(9, "set u[*] " << m_varp->name()); + void usedWhole(const AstNode* nodep) { + UINFO(9, "set u[*] " << m_varp->name() << " " << nodep); m_wholeFlags[FLAG_USED] = true; } - void drivenWhole() { - UINFO(9, "set d[*] " << m_varp->name()); + void drivenWhole(const AstNode* nodep) { + UINFO(9, "set d[*] " << m_varp->name() << " " << nodep); m_wholeFlags[FLAG_DRIVEN] = true; } void drivenWhole(const AstNodeVarRef* nodep, const FileLine* fileLinep, bool ftaskDef) { m_ftaskDriven = ftaskDef && !isDrivenWhole(); - drivenWhole(); + drivenWhole(nodep); m_nodep = nodep; m_nodeFileLinep = fileLinep; } @@ -301,7 +301,7 @@ public: } void drivenViaCall(const AstNodeFTaskRef* nodep) { - drivenWhole(); + drivenWhole(nodep); if (!m_callNodep) m_callNodep = nodep; } const AstNodeFTaskRef* callNodep() const { return m_callNodep; } @@ -323,6 +323,7 @@ class UndrivenVisitor final : public VNVisitorConst { std::array, 3> m_entryps = {}; // Nodes to delete when finished bool m_inBBox = false; // In black box; mark as driven+used bool m_inContAssign = false; // In continuous assignment + bool m_inInitialSetup = false; // In InitialAutomatic*/InitialStatic* assignment LHS bool m_inInitialStatic = false; // In InitialStatic bool m_inProcAssign = false; // In procedural assignment bool m_inFTaskRef = false; // In function or task call @@ -380,16 +381,16 @@ class UndrivenVisitor final : public VNVisitorConst { // usr==2 for always-only checks. UndrivenVarEntry* const entryp = getEntryp(nodep, usr); if ((nodep->isNonOutput() && !funcInout) || nodep->isSigPublic() - || nodep->isSigUserRWPublic() + || nodep->hasUserInit() || nodep->isSigUserRWPublic() || (m_taskp && (m_taskp->dpiImport() || m_taskp->dpiExport()))) { - entryp->drivenWhole(); + entryp->drivenWhole(nodep); } if ((nodep->isWritable() && !funcInout) || nodep->isSigPublic() || nodep->isSigUserRWPublic() || nodep->isSigUserRdPublic() || (m_taskp && (m_taskp->dpiImport() || m_taskp->dpiExport()))) { - entryp->usedWhole(); + entryp->usedWhole(nodep); } - if (nodep->valuep()) entryp->drivenWhole(); + if (nodep->valuep()) entryp->drivenWhole(nodep->valuep()); } // Discover variables used in bit definitions, etc iterateChildrenConst(nodep); @@ -504,7 +505,10 @@ class UndrivenVisitor final : public VNVisitorConst { << otherWritep->warnContextSecondary()); } } - entryp->drivenWhole(nodep, nodep->fileline(), ftaskDef); + if (!m_inInitialSetup || nodep->varp()->hasUserInit()) { + // Else don't count default initialization as a driver to a net/variable + entryp->drivenWhole(nodep, nodep->fileline(), ftaskDef); + } if (m_alwaysCombp && entryp->isDrivenAlwaysCombWhole() && m_alwaysCombp != entryp->getAlwCombp() && m_alwaysCombp->fileline() == entryp->getAlwCombFileLinep()) @@ -517,13 +521,14 @@ class UndrivenVisitor final : public VNVisitorConst { if (m_alwaysp && m_inProcAssign && !entryp->procWritep()) entryp->procWritep(nodep); } - if (m_inBBox || nodep->access().isReadOrRW() - || fdrv - // Inouts have only isWrite set, as we don't have more - // information and operating on module boundary, treat as - // both read and writing - || m_inInoutOrRefPin) - entryp->usedWhole(); + if ((!m_inInitialSetup || nodep->varp()->hasUserInit()) + && (m_inBBox || nodep->access().isReadOrRW() + || fdrv + // Inouts have only isWrite set, as we don't have more + // information and operating on module boundary, treat as + // both read and writing + || m_inInoutOrRefPin)) + entryp->usedWhole(nodep); } } @@ -537,9 +542,12 @@ class UndrivenVisitor final : public VNVisitorConst { void visit(AstAssign* nodep) override { VL_RESTORER(m_inProcAssign); m_inProcAssign = true; - // Don't count default initialization as a driver to a net/variable - if (VN_IS(nodep->rhsp(), CReset)) return; - iterateChildrenConst(nodep); + { + VL_RESTORER(m_inInitialSetup); + m_inInitialSetup = false; + iterateConst(nodep->rhsp()); + } + iterateConst(nodep->lhsp()); } void visit(AstAssignDly* nodep) override { VL_RESTORER(m_inProcAssign); @@ -551,9 +559,26 @@ class UndrivenVisitor final : public VNVisitorConst { m_inContAssign = true; iterateChildrenConst(nodep); } + void visit(AstInitialAutomatic* nodep) override { + VL_RESTORER(m_inInitialSetup); + m_inInitialSetup = true; + iterateChildrenConst(nodep); + } + void visit(AstInitialAutomaticStmt* nodep) override { + VL_RESTORER(m_inInitialSetup); + m_inInitialSetup = true; + iterateChildrenConst(nodep); + } void visit(AstInitialStatic* nodep) override { VL_RESTORER(m_inInitialStatic); m_inInitialStatic = true; + VL_RESTORER(m_inInitialSetup); + m_inInitialSetup = true; + iterateChildrenConst(nodep); + } + void visit(AstInitialStaticStmt* nodep) override { + VL_RESTORER(m_inInitialSetup); + m_inInitialSetup = true; iterateChildrenConst(nodep); } void visit(AstAlways* nodep) override { diff --git a/src/V3UndrivenCapture.cpp b/src/V3UndrivenCapture.cpp index ecab78037..4d310cda2 100644 --- a/src/V3UndrivenCapture.cpp +++ b/src/V3UndrivenCapture.cpp @@ -34,6 +34,7 @@ public: class CaptureVisitor final : public VNVisitorConst { V3UndrivenCapture& m_cap; const AstNodeFTask* m_curTaskp = nullptr; // Current task + bool m_inInitialSetup = false; // In InitialAutomatic*/InitialStatic* assignment LHS public: explicit CaptureVisitor(V3UndrivenCapture& cap, AstNetlist* netlistp) @@ -51,8 +52,28 @@ private: iterateAndNextConstNull(nodep->stmtsp()); } + void visit(AstInitialAutomaticStmt* nodep) override { + VL_RESTORER(m_inInitialSetup); + m_inInitialSetup = true; + iterateChildrenConst(nodep); + } + void visit(AstInitialStaticStmt* nodep) override { + VL_RESTORER(m_inInitialSetup); + m_inInitialSetup = true; + iterateChildrenConst(nodep); + } + void visit(AstAssign* nodep) override { + { + VL_RESTORER(m_inInitialSetup); + m_inInitialSetup = false; + iterateConst(nodep->rhsp()); + } + iterateConst(nodep->lhsp()); + } + void visit(AstNodeVarRef* nodep) override { - if (m_curTaskp && nodep->access().isWriteOrRW()) { + if (m_curTaskp && nodep->access().isWriteOrRW() + && (nodep->varp()->hasUserInit() || !m_inInitialSetup)) { UINFO(9, "undriven capture direct write in " << CaptureUtil::taskNameQ(m_curTaskp) << " var=" << nodep->varp()->prettyNameQ() << " at " << nodep->fileline()); @@ -163,7 +184,7 @@ void V3UndrivenCapture::noteDirectWrite(const AstNodeFTask* taskp, AstVar* varp) if (retVarp && varp == retVarp) return; // Filter out duplicates. - if (info.directWritesSet.insert(varp).second) { info.directWrites.push_back(varp); } + if (info.directWritesSet.insert(varp).second) info.directWrites.push_back(varp); } void V3UndrivenCapture::noteCallEdge(const AstNodeFTask* callerp, const AstNodeFTask* calleep) { diff --git a/src/V3Width.cpp b/src/V3Width.cpp index bb799caea..de98e9de6 100644 --- a/src/V3Width.cpp +++ b/src/V3Width.cpp @@ -5503,6 +5503,18 @@ class WidthVisitor final : public VNVisitor { if (AstAssign* const aitemp = VN_CAST(nodep, Assign)) { if (VN_IS(aitemp->rhsp(), Const) || VN_IS(aitemp->rhsp(), CReset)) return true; } + if (AstInitialStaticStmt* const aitemp = VN_CAST(nodep, InitialStaticStmt)) { + for (AstNode* stmtp = aitemp->stmtsp(); stmtp; stmtp = stmtp->nextp()) { + if (!firstNewStatementOkRecurse(stmtp)) return false; + } + return true; + } + if (AstInitialAutomaticStmt* const aitemp = VN_CAST(nodep, InitialAutomaticStmt)) { + for (AstNode* stmtp = aitemp->stmtsp(); stmtp; stmtp = stmtp->nextp()) { + if (!firstNewStatementOkRecurse(stmtp)) return false; + } + return true; + } return false; } diff --git a/test_regress/t/t_constraint_json_only.out b/test_regress/t/t_constraint_json_only.out index 22c066235..96e145376 100644 --- a/test_regress/t/t_constraint_json_only.out +++ b/test_regress/t/t_constraint_json_only.out @@ -36,14 +36,14 @@ {"type":"VAR","name":"b","addr":"(DB)","loc":"d,61:48,61:49","dtypep":"(M)","origName":"b","verilogName":"b","direction":"INPUT","isFuncLocal":true,"lifetime":"VAUTOMI","varType":"PORT","dtypeName":"string","sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, {"type":"ASSIGN","name":"","addr":"(EB)","loc":"d,61:17,61:30","dtypep":"(U)", "rhsp": [ - {"type":"CRESET","name":"","addr":"(FB)","loc":"d,61:17,61:30","dtypep":"(U)"} + {"type":"CONST","name":"1'h0","addr":"(FB)","loc":"d,61:17,61:30","dtypep":"(GB)"} ], "lhsp": [ - {"type":"VARREF","name":"strings_equal","addr":"(GB)","loc":"d,61:17,61:30","dtypep":"(U)","access":"WR","varp":"(BB)","varScopep":"UNLINKED","classOrPackagep":"UNLINKED"} + {"type":"VARREF","name":"strings_equal","addr":"(HB)","loc":"d,61:17,61:30","dtypep":"(U)","access":"WR","varp":"(BB)","varScopep":"UNLINKED","classOrPackagep":"UNLINKED"} ],"timingControlp": []}, - {"type":"ASSIGN","name":"","addr":"(HB)","loc":"d,62:7,62:13","dtypep":"(U)", + {"type":"ASSIGN","name":"","addr":"(IB)","loc":"d,62:7,62:13","dtypep":"(U)", "rhsp": [ - {"type":"EQN","name":"","addr":"(IB)","loc":"d,62:16,62:18","dtypep":"(JB)", + {"type":"EQN","name":"","addr":"(JB)","loc":"d,62:16,62:18","dtypep":"(GB)", "lhsp": [ {"type":"VARREF","name":"a","addr":"(KB)","loc":"d,62:14,62:15","dtypep":"(M)","access":"RD","varp":"(CB)","varScopep":"UNLINKED","classOrPackagep":"(O)"} ], @@ -63,7 +63,7 @@ "miscsp": [ {"type":"TYPETABLE","name":"","addr":"(C)","loc":"a,0:0,0:0","constraintRefp":"UNLINKED","emptyQueuep":"UNLINKED","queueIndexp":"UNLINKED","streamp":"UNLINKED","voidp":"(OB)", "typesp": [ - {"type":"BASICDTYPE","name":"logic","addr":"(JB)","loc":"d,22:14,22:15","dtypep":"(JB)","keyword":"logic","generic":true,"rangep": []}, + {"type":"BASICDTYPE","name":"logic","addr":"(GB)","loc":"d,22:14,22:15","dtypep":"(GB)","keyword":"logic","generic":true,"rangep": []}, {"type":"BASICDTYPE","name":"logic","addr":"(RB)","loc":"d,25:21,25:22","dtypep":"(RB)","keyword":"logic","range":"31:0","generic":true,"rangep": []}, {"type":"BASICDTYPE","name":"string","addr":"(M)","loc":"d,73:7,73:13","dtypep":"(M)","keyword":"string","generic":true,"rangep": []}, {"type":"BASICDTYPE","name":"int","addr":"(Q)","loc":"d,8:9,8:12","dtypep":"(Q)","keyword":"int","range":"31:0","generic":true,"signed":true,"rangep": []}, diff --git a/test_regress/t/t_cover_line.out b/test_regress/t/t_cover_line.out index 9fd2713c9..182202d24 100644 --- a/test_regress/t/t_cover_line.out +++ b/test_regress/t/t_cover_line.out @@ -324,7 +324,8 @@ end 000011 begin +000011 point: comment=block hier=top.t.t1 - Cls c; + 000011 Cls c; ++000011 point: comment=block hier=top.t.t1 000011 c = new(1'b1); +000011 point: comment=block hier=top.t.t1 000011 c.fauto(); @@ -458,7 +459,8 @@ 000010 function arr_t get_arr; +000010 point: comment=block hier=top.t.cond1 - arr_t arr; + 000010 arr_t arr; ++000010 point: comment=block hier=top.t.cond1 000010 return arr; +000010 point: comment=block hier=top.t.cond1 endfunction diff --git a/test_regress/t/t_cover_line_cc.info.out b/test_regress/t/t_cover_line_cc.info.out index edae983eb..6e42f53a9 100644 --- a/test_regress/t/t_cover_line_cc.info.out +++ b/test_regress/t/t_cover_line_cc.info.out @@ -115,6 +115,7 @@ BRDA:225,0,0,1 BRDA:225,0,1,10 DA:226,1 DA:229,11 +DA:230,11 DA:231,11 DA:232,11 DA:233,11 @@ -153,6 +154,7 @@ DA:323,21 DA:324,21 DA:325,21 DA:328,10 +DA:329,10 DA:330,10 DA:333,31 BRDA:333,0,0,0 diff --git a/test_regress/t/t_cover_line_expr.out b/test_regress/t/t_cover_line_expr.out index 15c2aa4a8..752549445 100644 --- a/test_regress/t/t_cover_line_expr.out +++ b/test_regress/t/t_cover_line_expr.out @@ -401,8 +401,10 @@ -000001 point: comment=block hier=top.t %000001 automatic cls null_obj = null; -000001 point: comment=block hier=top.t - automatic int q[5]; - automatic int qv[$]; +%000001 automatic int q[5]; +-000001 point: comment=block hier=top.t +%000001 automatic int qv[$]; +-000001 point: comment=block hier=top.t %000001 q = '{1, 2, 2, 4, 3}; -000001 point: comment=block hier=top.t diff --git a/test_regress/t/t_debug_emitv.out b/test_regress/t/t_debug_emitv.out index e5f33d5f6..aecca1cf7 100644 --- a/test_regress/t/t_debug_emitv.out +++ b/test_regress/t/t_debug_emitv.out @@ -126,6 +126,7 @@ module Vt_debug_emitv_t; initial begin begin : unnamedblk1 int signed other; + other = /*CRESET*/; begin begin : unnamedblk2 int signed i; @@ -690,6 +691,7 @@ module Vt_debug_emitv_sub; task inc; input int signed i; output int signed o; + o = /*CRESET*/; o = ({32'h1{{1'h0, i[31:1]}}} + 32'h1); endtask function f; diff --git a/test_regress/t/t_flag_csplit_groups.py b/test_regress/t/t_flag_csplit_groups.py index c92448c9e..6e15ff128 100755 --- a/test_regress/t/t_flag_csplit_groups.py +++ b/test_regress/t/t_flag_csplit_groups.py @@ -125,7 +125,7 @@ test.file_grep_not(test.obj_dir + "/" + test.vm_prefix + "_classes.mk", "vm_clas test.file_grep_not(test.obj_dir + "/" + test.vm_prefix + "_classes.mk", "vm_classes_2") # Check combine count -test.file_grep(test.stats, r'Node count, CFILE + (\d+)', (276 if test.vltmt else 259)) +test.file_grep(test.stats, r'Node count, CFILE + (\d+)', (275 if test.vltmt else 258)) test.file_grep(test.stats, r'Makefile targets, VM_CLASSES_FAST + (\d+)', 2) test.file_grep(test.stats, r'Makefile targets, VM_CLASSES_SLOW + (\d+)', 2) diff --git a/test_regress/t/t_func_crc.py b/test_regress/t/t_func_crc.py index 142d3bc44..0f6ce0c75 100755 --- a/test_regress/t/t_func_crc.py +++ b/test_regress/t/t_func_crc.py @@ -18,6 +18,6 @@ test.compile( test.execute() if test.vlt: - test.file_grep(test.stats, r'Optimizations, Const bit op reduction\s+(\d+)', 3416) + test.file_grep(test.stats, r'Optimizations, Const bit op reduction\s+(\d+)', 3888) test.passes() diff --git a/test_regress/t/t_hier_block_chained.py b/test_regress/t/t_hier_block_chained.py index 41e89faab..fb17db8e6 100755 --- a/test_regress/t/t_hier_block_chained.py +++ b/test_regress/t/t_hier_block_chained.py @@ -31,9 +31,9 @@ test.compile(v_flags2=[ if test.vltmt: test.file_grep(test.obj_dir + "/V" + test.name + "__hier.dir/V" + test.name + "__stats.txt", - r'Optimizations, Thread schedule count\s+(\d+)', 4) + r'Optimizations, Thread schedule count\s+(\d+)', 3) test.file_grep(test.obj_dir + "/V" + test.name + "__hier.dir/V" + test.name + "__stats.txt", - r'Optimizations, Thread schedule total tasks\s+(\d+)', 6) + r'Optimizations, Thread schedule total tasks\s+(\d+)', 5) test.execute() diff --git a/test_regress/t/t_json_only_debugcheck.out b/test_regress/t/t_json_only_debugcheck.out index f4d5c9b74..b360d118a 100644 --- a/test_regress/t/t_json_only_debugcheck.out +++ b/test_regress/t/t_json_only_debugcheck.out @@ -7,7 +7,7 @@ {"type":"VAR","name":"__Vtrigprevexpr___TOP__clk__0","addr":"(N)","loc":"d,11:8,11:9","dtypep":"(K)","origName":"__Vtrigprevexpr___TOP__clk__0","verilogName":"__Vtrigprevexpr___TOP__clk__0","direction":"NONE","lifetime":"NONE","varType":"MODULETEMP","dtypeName":"logic","sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, {"type":"VAR","name":"__VactPhaseResult","addr":"(O)","loc":"d,11:8,11:9","dtypep":"(P)","origName":"__VactPhaseResult","verilogName":"__VactPhaseResult","direction":"NONE","noReset":true,"lifetime":"NONE","varType":"MODULETEMP","dtypeName":"bit","sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, {"type":"VAR","name":"__VnbaPhaseResult","addr":"(Q)","loc":"d,11:8,11:9","dtypep":"(P)","origName":"__VnbaPhaseResult","verilogName":"__VnbaPhaseResult","direction":"NONE","noReset":true,"lifetime":"NONE","varType":"MODULETEMP","dtypeName":"bit","sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, - {"type":"VAR","name":"t.cyc","addr":"(R)","loc":"d,23:17,23:20","dtypep":"(S)","origName":"cyc","verilogName":"cyc","direction":"NONE","lifetime":"VSTATICI","varType":"VAR","dtypeName":"integer","hasUserInit":true,"sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, + {"type":"VAR","name":"t.cyc","addr":"(R)","loc":"d,23:17,23:20","dtypep":"(S)","origName":"cyc","verilogName":"cyc","direction":"NONE","noCReset":true,"lifetime":"VSTATICI","varType":"VAR","dtypeName":"integer","hasUserInit":true,"sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, {"type":"VAR","name":"__VactIterCount","addr":"(T)","loc":"d,11:8,11:9","dtypep":"(U)","origName":"__VactIterCount","verilogName":"__VactIterCount","direction":"NONE","noReset":true,"lifetime":"NONE","varType":"MODULETEMP","dtypeName":"bit","sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, {"type":"VAR","name":"__VactTriggered","addr":"(V)","loc":"d,11:8,11:9","dtypep":"(W)","origName":"__VactTriggered","verilogName":"__VactTriggered","direction":"NONE","lifetime":"NONE","varType":"MODULETEMP","dtypeName":"","sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, {"type":"VAR","name":"__VnbaTriggered","addr":"(X)","loc":"d,11:8,11:9","dtypep":"(W)","origName":"__VnbaTriggered","verilogName":"__VnbaTriggered","direction":"NONE","lifetime":"NONE","varType":"MODULETEMP","dtypeName":"","sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, @@ -2859,175 +2859,178 @@ "lhsp": [ {"type":"VARREF","name":"clk","addr":"(YPB)","loc":"d,15:10,15:13","dtypep":"(K)","access":"WR","varp":"(J)","varScopep":"UNLINKED","classOrPackagep":"UNLINKED"} ],"timingControlp": []}, - {"type":"ASSIGN","name":"","addr":"(ZPB)","loc":"d,23:17,23:20","dtypep":"(S)", + {"type":"ASSIGN","name":"","addr":"(ZPB)","loc":"d,24:9,24:10","dtypep":"(M)", "rhsp": [ - {"type":"CRESET","name":"","addr":"(AQB)","loc":"d,23:17,23:20","dtypep":"(S)","constructing":true} + {"type":"CRESET","name":"","addr":"(AQB)","loc":"d,24:9,24:10","dtypep":"(M)","constructing":true} ], "lhsp": [ - {"type":"VARREF","name":"t.cyc","addr":"(BQB)","loc":"d,23:17,23:20","dtypep":"(S)","access":"WR","varp":"(R)","varScopep":"UNLINKED","classOrPackagep":"UNLINKED"} + {"type":"VARREF","name":"t.e","addr":"(BQB)","loc":"d,24:9,24:10","dtypep":"(M)","access":"WR","varp":"(L)","varScopep":"UNLINKED","classOrPackagep":"UNLINKED"} ],"timingControlp": []}, - {"type":"ASSIGN","name":"","addr":"(CQB)","loc":"d,24:9,24:10","dtypep":"(M)", + {"type":"ASSIGN","name":"","addr":"(CQB)","loc":"d,11:8,11:9","dtypep":"(W)", "rhsp": [ - {"type":"CRESET","name":"","addr":"(DQB)","loc":"d,24:9,24:10","dtypep":"(M)","constructing":true} + {"type":"CRESET","name":"","addr":"(DQB)","loc":"d,11:8,11:9","dtypep":"(W)","constructing":true} ], "lhsp": [ - {"type":"VARREF","name":"t.e","addr":"(EQB)","loc":"d,24:9,24:10","dtypep":"(M)","access":"WR","varp":"(L)","varScopep":"UNLINKED","classOrPackagep":"UNLINKED"} + {"type":"VARREF","name":"__VactTriggered","addr":"(EQB)","loc":"d,11:8,11:9","dtypep":"(W)","access":"WR","varp":"(V)","varScopep":"UNLINKED","classOrPackagep":"UNLINKED"} ],"timingControlp": []}, - {"type":"ASSIGN","name":"","addr":"(FQB)","loc":"d,11:8,11:9","dtypep":"(W)", + {"type":"ASSIGN","name":"","addr":"(FQB)","loc":"d,11:8,11:9","dtypep":"(K)", "rhsp": [ - {"type":"CRESET","name":"","addr":"(GQB)","loc":"d,11:8,11:9","dtypep":"(W)","constructing":true} + {"type":"CRESET","name":"","addr":"(GQB)","loc":"d,11:8,11:9","dtypep":"(K)","constructing":true} ], "lhsp": [ - {"type":"VARREF","name":"__VactTriggered","addr":"(HQB)","loc":"d,11:8,11:9","dtypep":"(W)","access":"WR","varp":"(V)","varScopep":"UNLINKED","classOrPackagep":"UNLINKED"} + {"type":"VARREF","name":"__Vtrigprevexpr___TOP__clk__0","addr":"(HQB)","loc":"d,11:8,11:9","dtypep":"(K)","access":"WR","varp":"(N)","varScopep":"UNLINKED","classOrPackagep":"UNLINKED"} ],"timingControlp": []}, - {"type":"ASSIGN","name":"","addr":"(IQB)","loc":"d,11:8,11:9","dtypep":"(K)", + {"type":"ASSIGN","name":"","addr":"(IQB)","loc":"d,11:8,11:9","dtypep":"(W)", "rhsp": [ - {"type":"CRESET","name":"","addr":"(JQB)","loc":"d,11:8,11:9","dtypep":"(K)","constructing":true} + {"type":"CRESET","name":"","addr":"(JQB)","loc":"d,11:8,11:9","dtypep":"(W)","constructing":true} ], "lhsp": [ - {"type":"VARREF","name":"__Vtrigprevexpr___TOP__clk__0","addr":"(KQB)","loc":"d,11:8,11:9","dtypep":"(K)","access":"WR","varp":"(N)","varScopep":"UNLINKED","classOrPackagep":"UNLINKED"} - ],"timingControlp": []}, - {"type":"ASSIGN","name":"","addr":"(LQB)","loc":"d,11:8,11:9","dtypep":"(W)", - "rhsp": [ - {"type":"CRESET","name":"","addr":"(MQB)","loc":"d,11:8,11:9","dtypep":"(W)","constructing":true} - ], - "lhsp": [ - {"type":"VARREF","name":"__VnbaTriggered","addr":"(NQB)","loc":"d,11:8,11:9","dtypep":"(W)","access":"WR","varp":"(X)","varScopep":"UNLINKED","classOrPackagep":"UNLINKED"} + {"type":"VARREF","name":"__VnbaTriggered","addr":"(KQB)","loc":"d,11:8,11:9","dtypep":"(W)","access":"WR","varp":"(X)","varScopep":"UNLINKED","classOrPackagep":"UNLINKED"} ],"timingControlp": []} ]}, - {"type":"CUSE","name":"$unit","addr":"(OQB)","loc":"a,0:0,0:0","useType":"INT_FWD"} + {"type":"CUSE","name":"$unit","addr":"(LQB)","loc":"a,0:0,0:0","useType":"INT_FWD"} ]}, {"type":"PACKAGE","name":"$unit","addr":"(E)","loc":"a,0:0,0:0","origName":"__024unit","verilogName":"\\$unit ","level":2,"inLibrary":true,"timeunit":"NONE","inlinesp": [], "stmtsp": [ {"type":"VAR","name":"__Venumtab_enum_next1","addr":"(DC)","loc":"d,17:12,17:16","dtypep":"(CC)","origName":"__Venumtab_enum_next1","verilogName":"__Venumtab_enum_next1","direction":"NONE","isConst":true,"lifetime":"VSTATIC","varType":"MODULETEMP","dtypeName":"","sensIfacep":"UNLINKED","childDTypep": [],"delayp": [], "valuep": [ - {"type":"INITARRAY","name":"","addr":"(PQB)","loc":"d,17:12,17:16","dtypep":"(CC)","initList":" [1]=(QQB) [3]=(RQB) [4]=(SQB)", + {"type":"INITARRAY","name":"","addr":"(MQB)","loc":"d,17:12,17:16","dtypep":"(CC)","initList":" [1]=(NQB) [3]=(OQB) [4]=(PQB)", "defaultp": [ - {"type":"CONST","name":"4'h0","addr":"(TQB)","loc":"d,17:12,17:16","dtypep":"(UB)"} + {"type":"CONST","name":"4'h0","addr":"(QQB)","loc":"d,17:12,17:16","dtypep":"(UB)"} ], "initsp": [ - {"type":"INITITEM","name":"","addr":"(QQB)","loc":"d,17:12,17:16", + {"type":"INITITEM","name":"","addr":"(NQB)","loc":"d,17:12,17:16", "valuep": [ - {"type":"CONST","name":"4'h3","addr":"(UQB)","loc":"d,19:30,19:31","dtypep":"(UB)"} + {"type":"CONST","name":"4'h3","addr":"(RQB)","loc":"d,19:30,19:31","dtypep":"(UB)"} ]}, - {"type":"INITITEM","name":"","addr":"(RQB)","loc":"d,17:12,17:16", + {"type":"INITITEM","name":"","addr":"(OQB)","loc":"d,17:12,17:16", "valuep": [ - {"type":"CONST","name":"4'h4","addr":"(VQB)","loc":"d,20:30,20:31","dtypep":"(UB)"} + {"type":"CONST","name":"4'h4","addr":"(SQB)","loc":"d,20:30,20:31","dtypep":"(UB)"} ]}, - {"type":"INITITEM","name":"","addr":"(SQB)","loc":"d,17:12,17:16", + {"type":"INITITEM","name":"","addr":"(PQB)","loc":"d,17:12,17:16", "valuep": [ - {"type":"CONST","name":"4'h1","addr":"(WQB)","loc":"d,18:30,18:31","dtypep":"(UB)"} + {"type":"CONST","name":"4'h1","addr":"(TQB)","loc":"d,18:30,18:31","dtypep":"(UB)"} ]} ]} ],"attrsp": []}, {"type":"VAR","name":"__Venumtab_enum_prev1","addr":"(XI)","loc":"d,17:12,17:16","dtypep":"(WI)","origName":"__Venumtab_enum_prev1","verilogName":"__Venumtab_enum_prev1","direction":"NONE","isConst":true,"lifetime":"VSTATIC","varType":"MODULETEMP","dtypeName":"","sensIfacep":"UNLINKED","childDTypep": [],"delayp": [], "valuep": [ - {"type":"INITARRAY","name":"","addr":"(XQB)","loc":"d,17:12,17:16","dtypep":"(WI)","initList":" [1]=(YQB) [3]=(ZQB) [4]=(ARB)", + {"type":"INITARRAY","name":"","addr":"(UQB)","loc":"d,17:12,17:16","dtypep":"(WI)","initList":" [1]=(VQB) [3]=(WQB) [4]=(XQB)", "defaultp": [ - {"type":"CONST","name":"4'h0","addr":"(BRB)","loc":"d,17:12,17:16","dtypep":"(UB)"} + {"type":"CONST","name":"4'h0","addr":"(YQB)","loc":"d,17:12,17:16","dtypep":"(UB)"} ], "initsp": [ - {"type":"INITITEM","name":"","addr":"(YQB)","loc":"d,17:12,17:16", + {"type":"INITITEM","name":"","addr":"(VQB)","loc":"d,17:12,17:16", "valuep": [ - {"type":"CONST","name":"4'h4","addr":"(CRB)","loc":"d,20:30,20:31","dtypep":"(UB)"} + {"type":"CONST","name":"4'h4","addr":"(ZQB)","loc":"d,20:30,20:31","dtypep":"(UB)"} ]}, - {"type":"INITITEM","name":"","addr":"(ZQB)","loc":"d,17:12,17:16", + {"type":"INITITEM","name":"","addr":"(WQB)","loc":"d,17:12,17:16", "valuep": [ - {"type":"CONST","name":"4'h1","addr":"(DRB)","loc":"d,18:30,18:31","dtypep":"(UB)"} + {"type":"CONST","name":"4'h1","addr":"(ARB)","loc":"d,18:30,18:31","dtypep":"(UB)"} ]}, - {"type":"INITITEM","name":"","addr":"(ARB)","loc":"d,17:12,17:16", + {"type":"INITITEM","name":"","addr":"(XQB)","loc":"d,17:12,17:16", "valuep": [ - {"type":"CONST","name":"4'h3","addr":"(ERB)","loc":"d,19:30,19:31","dtypep":"(UB)"} + {"type":"CONST","name":"4'h3","addr":"(BRB)","loc":"d,19:30,19:31","dtypep":"(UB)"} ]} ]} ],"attrsp": []}, {"type":"VAR","name":"__Venumtab_enum_name1","addr":"(JM)","loc":"d,17:12,17:16","dtypep":"(IM)","origName":"__Venumtab_enum_name1","verilogName":"__Venumtab_enum_name1","direction":"NONE","isConst":true,"lifetime":"VSTATIC","varType":"MODULETEMP","dtypeName":"","sensIfacep":"UNLINKED","childDTypep": [],"delayp": [], "valuep": [ - {"type":"INITARRAY","name":"","addr":"(FRB)","loc":"d,17:12,17:16","dtypep":"(IM)","initList":" [1]=(GRB) [3]=(HRB) [4]=(IRB)", + {"type":"INITARRAY","name":"","addr":"(CRB)","loc":"d,17:12,17:16","dtypep":"(IM)","initList":" [1]=(DRB) [3]=(ERB) [4]=(FRB)", "defaultp": [ - {"type":"CONST","name":"\\\"\\\"","addr":"(JRB)","loc":"d,17:12,17:16","dtypep":"(SB)"} + {"type":"CONST","name":"\\\"\\\"","addr":"(GRB)","loc":"d,17:12,17:16","dtypep":"(SB)"} ], "initsp": [ - {"type":"INITITEM","name":"","addr":"(GRB)","loc":"d,17:12,17:16", + {"type":"INITITEM","name":"","addr":"(DRB)","loc":"d,17:12,17:16", "valuep": [ - {"type":"CONST","name":"\\\"E01\\\"","addr":"(KRB)","loc":"d,17:12,17:16","dtypep":"(SB)"} + {"type":"CONST","name":"\\\"E01\\\"","addr":"(HRB)","loc":"d,17:12,17:16","dtypep":"(SB)"} ]}, - {"type":"INITITEM","name":"","addr":"(HRB)","loc":"d,17:12,17:16", + {"type":"INITITEM","name":"","addr":"(ERB)","loc":"d,17:12,17:16", "valuep": [ - {"type":"CONST","name":"\\\"E03\\\"","addr":"(LRB)","loc":"d,17:12,17:16","dtypep":"(SB)"} + {"type":"CONST","name":"\\\"E03\\\"","addr":"(IRB)","loc":"d,17:12,17:16","dtypep":"(SB)"} ]}, - {"type":"INITITEM","name":"","addr":"(IRB)","loc":"d,17:12,17:16", + {"type":"INITITEM","name":"","addr":"(FRB)","loc":"d,17:12,17:16", "valuep": [ - {"type":"CONST","name":"\\\"E04\\\"","addr":"(MRB)","loc":"d,17:12,17:16","dtypep":"(SB)"} + {"type":"CONST","name":"\\\"E04\\\"","addr":"(JRB)","loc":"d,17:12,17:16","dtypep":"(SB)"} ]} ]} ],"attrsp": []}, - {"type":"SCOPE","name":"$unit","addr":"(NRB)","loc":"a,0:0,0:0","aboveScopep":"(Z)","aboveCellp":"(Y)","modp":"(E)","varsp": [],"blocksp": [],"inlinesp": []}, - {"type":"CFUNC","name":"_ctor_var_reset","addr":"(ORB)","loc":"a,0:0,0:0","slow":true,"scopep":"UNLINKED","argsp": [],"varsp": [], + {"type":"SCOPE","name":"$unit","addr":"(KRB)","loc":"a,0:0,0:0","aboveScopep":"(Z)","aboveCellp":"(Y)","modp":"(E)","varsp": [],"blocksp": [],"inlinesp": []}, + {"type":"CFUNC","name":"_ctor_var_reset","addr":"(LRB)","loc":"a,0:0,0:0","slow":true,"scopep":"UNLINKED","argsp": [],"varsp": [], "stmtsp": [ - {"type":"ASSIGN","name":"","addr":"(PRB)","loc":"d,17:12,17:16","dtypep":"(CC)", + {"type":"ASSIGN","name":"","addr":"(MRB)","loc":"d,17:12,17:16","dtypep":"(CC)", "rhsp": [ - {"type":"CRESET","name":"","addr":"(QRB)","loc":"d,17:12,17:16","dtypep":"(CC)","constructing":true} + {"type":"CRESET","name":"","addr":"(NRB)","loc":"d,17:12,17:16","dtypep":"(CC)","constructing":true} ], "lhsp": [ - {"type":"VARREF","name":"__Venumtab_enum_next1","addr":"(RRB)","loc":"d,17:12,17:16","dtypep":"(CC)","access":"WR","varp":"(DC)","varScopep":"UNLINKED","classOrPackagep":"UNLINKED"} + {"type":"VARREF","name":"__Venumtab_enum_next1","addr":"(ORB)","loc":"d,17:12,17:16","dtypep":"(CC)","access":"WR","varp":"(DC)","varScopep":"UNLINKED","classOrPackagep":"UNLINKED"} ],"timingControlp": []}, - {"type":"ASSIGN","name":"","addr":"(SRB)","loc":"d,17:12,17:16","dtypep":"(WI)", + {"type":"ASSIGN","name":"","addr":"(PRB)","loc":"d,17:12,17:16","dtypep":"(WI)", "rhsp": [ - {"type":"CRESET","name":"","addr":"(TRB)","loc":"d,17:12,17:16","dtypep":"(WI)","constructing":true} + {"type":"CRESET","name":"","addr":"(QRB)","loc":"d,17:12,17:16","dtypep":"(WI)","constructing":true} ], "lhsp": [ - {"type":"VARREF","name":"__Venumtab_enum_prev1","addr":"(URB)","loc":"d,17:12,17:16","dtypep":"(WI)","access":"WR","varp":"(XI)","varScopep":"UNLINKED","classOrPackagep":"UNLINKED"} + {"type":"VARREF","name":"__Venumtab_enum_prev1","addr":"(RRB)","loc":"d,17:12,17:16","dtypep":"(WI)","access":"WR","varp":"(XI)","varScopep":"UNLINKED","classOrPackagep":"UNLINKED"} ],"timingControlp": []}, - {"type":"ASSIGN","name":"","addr":"(VRB)","loc":"d,17:12,17:16","dtypep":"(IM)", + {"type":"ASSIGN","name":"","addr":"(SRB)","loc":"d,17:12,17:16","dtypep":"(IM)", "rhsp": [ - {"type":"CRESET","name":"","addr":"(WRB)","loc":"d,17:12,17:16","dtypep":"(IM)","constructing":true} + {"type":"CRESET","name":"","addr":"(TRB)","loc":"d,17:12,17:16","dtypep":"(IM)","constructing":true} ], "lhsp": [ - {"type":"VARREF","name":"__Venumtab_enum_name1","addr":"(XRB)","loc":"d,17:12,17:16","dtypep":"(IM)","access":"WR","varp":"(JM)","varScopep":"UNLINKED","classOrPackagep":"UNLINKED"} + {"type":"VARREF","name":"__Venumtab_enum_name1","addr":"(URB)","loc":"d,17:12,17:16","dtypep":"(IM)","access":"WR","varp":"(JM)","varScopep":"UNLINKED","classOrPackagep":"UNLINKED"} ],"timingControlp": []} ]} ]} ], "filesp": [ - {"type":"CFILE","name":"obj_vlt/t_json_only_debugcheck/Vt_json_only_debugcheck__Syms__Slow.cpp","addr":"(YRB)","loc":"a,0:0,0:0","source":true,"slow":true,"tblockp": []}, - {"type":"CFILE","name":"obj_vlt/t_json_only_debugcheck/Vt_json_only_debugcheck__Syms.h","addr":"(ZRB)","loc":"a,0:0,0:0","tblockp": []}, - {"type":"CFILE","name":"obj_vlt/t_json_only_debugcheck/Vt_json_only_debugcheck.h","addr":"(ASB)","loc":"a,0:0,0:0","tblockp": []}, - {"type":"CFILE","name":"obj_vlt/t_json_only_debugcheck/Vt_json_only_debugcheck.cpp","addr":"(BSB)","loc":"a,0:0,0:0","source":true,"tblockp": []}, - {"type":"CFILE","name":"obj_vlt/t_json_only_debugcheck/Vt_json_only_debugcheck__pch.h","addr":"(CSB)","loc":"a,0:0,0:0","tblockp": []}, - {"type":"CFILE","name":"obj_vlt/t_json_only_debugcheck/Vt_json_only_debugcheck_$root.h","addr":"(DSB)","loc":"a,0:0,0:0","tblockp": []}, - {"type":"CFILE","name":"obj_vlt/t_json_only_debugcheck/Vt_json_only_debugcheck_$unit.h","addr":"(ESB)","loc":"a,0:0,0:0","tblockp": []}, - {"type":"CFILE","name":"obj_vlt/t_json_only_debugcheck/Vt_json_only_debugcheck_$root__Slow.cpp","addr":"(FSB)","loc":"a,0:0,0:0","source":true,"slow":true,"tblockp": []}, - {"type":"CFILE","name":"obj_vlt/t_json_only_debugcheck/Vt_json_only_debugcheck_$root__0__Slow.cpp","addr":"(GSB)","loc":"a,0:0,0:0","source":true,"slow":true,"tblockp": []}, - {"type":"CFILE","name":"obj_vlt/t_json_only_debugcheck/Vt_json_only_debugcheck_$root__0.cpp","addr":"(HSB)","loc":"a,0:0,0:0","source":true,"tblockp": []}, - {"type":"CFILE","name":"obj_vlt/t_json_only_debugcheck/Vt_json_only_debugcheck_$unit__Slow.cpp","addr":"(ISB)","loc":"a,0:0,0:0","source":true,"slow":true,"tblockp": []}, - {"type":"CFILE","name":"obj_vlt/t_json_only_debugcheck/Vt_json_only_debugcheck_$unit__0__Slow.cpp","addr":"(JSB)","loc":"a,0:0,0:0","source":true,"slow":true,"tblockp": []} + {"type":"CFILE","name":"obj_vlt/t_json_only_debugcheck/Vt_json_only_debugcheck__Syms__Slow.cpp","addr":"(VRB)","loc":"a,0:0,0:0","source":true,"slow":true,"tblockp": []}, + {"type":"CFILE","name":"obj_vlt/t_json_only_debugcheck/Vt_json_only_debugcheck__Syms.h","addr":"(WRB)","loc":"a,0:0,0:0","tblockp": []}, + {"type":"CFILE","name":"obj_vlt/t_json_only_debugcheck/Vt_json_only_debugcheck.h","addr":"(XRB)","loc":"a,0:0,0:0","tblockp": []}, + {"type":"CFILE","name":"obj_vlt/t_json_only_debugcheck/Vt_json_only_debugcheck.cpp","addr":"(YRB)","loc":"a,0:0,0:0","source":true,"tblockp": []}, + {"type":"CFILE","name":"obj_vlt/t_json_only_debugcheck/Vt_json_only_debugcheck__pch.h","addr":"(ZRB)","loc":"a,0:0,0:0","tblockp": []}, + {"type":"CFILE","name":"obj_vlt/t_json_only_debugcheck/Vt_json_only_debugcheck_$root.h","addr":"(ASB)","loc":"a,0:0,0:0","tblockp": []}, + {"type":"CFILE","name":"obj_vlt/t_json_only_debugcheck/Vt_json_only_debugcheck_$unit.h","addr":"(BSB)","loc":"a,0:0,0:0","tblockp": []}, + {"type":"CFILE","name":"obj_vlt/t_json_only_debugcheck/Vt_json_only_debugcheck_$root__Slow.cpp","addr":"(CSB)","loc":"a,0:0,0:0","source":true,"slow":true,"tblockp": []}, + {"type":"CFILE","name":"obj_vlt/t_json_only_debugcheck/Vt_json_only_debugcheck_$root__0__Slow.cpp","addr":"(DSB)","loc":"a,0:0,0:0","source":true,"slow":true,"tblockp": []}, + {"type":"CFILE","name":"obj_vlt/t_json_only_debugcheck/Vt_json_only_debugcheck_$root__0.cpp","addr":"(ESB)","loc":"a,0:0,0:0","source":true,"tblockp": []}, + {"type":"CFILE","name":"obj_vlt/t_json_only_debugcheck/Vt_json_only_debugcheck_$unit__Slow.cpp","addr":"(FSB)","loc":"a,0:0,0:0","source":true,"slow":true,"tblockp": []}, + {"type":"CFILE","name":"obj_vlt/t_json_only_debugcheck/Vt_json_only_debugcheck_$unit__0__Slow.cpp","addr":"(GSB)","loc":"a,0:0,0:0","source":true,"slow":true,"tblockp": []} ], "miscsp": [ {"type":"TYPETABLE","name":"","addr":"(C)","loc":"a,0:0,0:0","constraintRefp":"UNLINKED","emptyQueuep":"UNLINKED","queueIndexp":"UNLINKED","streamp":"UNLINKED","voidp":"(DB)", "typesp": [ {"type":"BASICDTYPE","name":"logic","addr":"(K)","loc":"d,33:24,33:27","dtypep":"(K)","keyword":"logic","generic":true,"rangep": []}, {"type":"BASICDTYPE","name":"logic","addr":"(HC)","loc":"d,53:16,53:17","dtypep":"(HC)","keyword":"logic","range":"31:0","generic":true,"rangep": []}, - {"type":"BASICDTYPE","name":"logic","addr":"(KSB)","loc":"d,17:17,17:18","dtypep":"(KSB)","keyword":"logic","range":"3:0","generic":true,"rangep": []}, - {"type":"ENUMDTYPE","name":"t.my_t","addr":"(LSB)","loc":"d,17:12,17:16","dtypep":"(LSB)","enum":true,"refDTypep":"(KSB)","childDTypep": [], + {"type":"BASICDTYPE","name":"logic","addr":"(HSB)","loc":"d,17:17,17:18","dtypep":"(HSB)","keyword":"logic","range":"3:0","generic":true,"rangep": []}, + {"type":"ENUMDTYPE","name":"t.my_t","addr":"(ISB)","loc":"d,17:12,17:16","dtypep":"(ISB)","enum":true,"refDTypep":"(HSB)","childDTypep": [], "itemsp": [ - {"type":"ENUMITEM","name":"E01","addr":"(MSB)","loc":"d,18:24,18:27","dtypep":"(UB)","rangep": [], + {"type":"ENUMITEM","name":"E01","addr":"(JSB)","loc":"d,18:24,18:27","dtypep":"(UB)","rangep": [], "valuep": [ - {"type":"CONST","name":"4'h1","addr":"(NSB)","loc":"d,18:30,18:31","dtypep":"(UB)"} + {"type":"CONST","name":"4'h1","addr":"(KSB)","loc":"d,18:30,18:31","dtypep":"(UB)"} ]}, - {"type":"ENUMITEM","name":"E03","addr":"(OSB)","loc":"d,19:24,19:27","dtypep":"(UB)","rangep": [], + {"type":"ENUMITEM","name":"E03","addr":"(LSB)","loc":"d,19:24,19:27","dtypep":"(UB)","rangep": [], "valuep": [ - {"type":"CONST","name":"4'h3","addr":"(PSB)","loc":"d,19:30,19:31","dtypep":"(UB)"} + {"type":"CONST","name":"4'h3","addr":"(MSB)","loc":"d,19:30,19:31","dtypep":"(UB)"} ]}, - {"type":"ENUMITEM","name":"E04","addr":"(QSB)","loc":"d,20:24,20:27","dtypep":"(UB)","rangep": [], + {"type":"ENUMITEM","name":"E04","addr":"(NSB)","loc":"d,20:24,20:27","dtypep":"(UB)","rangep": [], "valuep": [ - {"type":"CONST","name":"4'h4","addr":"(RSB)","loc":"d,20:30,20:31","dtypep":"(UB)"} + {"type":"CONST","name":"4'h4","addr":"(OSB)","loc":"d,20:30,20:31","dtypep":"(UB)"} ]} ]}, {"type":"BASICDTYPE","name":"integer","addr":"(S)","loc":"d,23:4,23:11","dtypep":"(S)","keyword":"integer","range":"31:0","generic":true,"signed":true,"rangep": []}, - {"type":"REFDTYPE","name":"my_t","addr":"(M)","loc":"d,24:4,24:8","dtypep":"(LSB)","typedefp":"UNLINKED","refDTypep":"(LSB)","classOrPackagep":"UNLINKED","typeofp": [],"classOrPackageOpp": [],"paramsp": []}, + {"type":"REFDTYPE","name":"my_t","addr":"(M)","loc":"d,24:4,24:8","dtypep":"(ISB)","typedefp":"UNLINKED","refDTypep":"(ISB)","classOrPackagep":"UNLINKED","typeofp": [],"classOrPackageOpp": [],"paramsp": []}, {"type":"BASICDTYPE","name":"string","addr":"(SB)","loc":"d,28:4,28:10","dtypep":"(SB)","keyword":"string","generic":true,"rangep": []}, - {"type":"UNPACKARRAYDTYPE","name":"","addr":"(CC)","loc":"d,17:12,17:16","dtypep":"(CC)","declRange":"[7:0]","refDTypep":"(LSB)","childDTypep": [], + {"type":"UNPACKARRAYDTYPE","name":"","addr":"(CC)","loc":"d,17:12,17:16","dtypep":"(CC)","declRange":"[7:0]","refDTypep":"(ISB)","childDTypep": [], + "rangep": [ + {"type":"RANGE","name":"","addr":"(PSB)","loc":"d,17:12,17:16", + "leftp": [ + {"type":"CONST","name":"32'h7","addr":"(QSB)","loc":"d,17:12,17:16","dtypep":"(HC)"} + ], + "rightp": [ + {"type":"CONST","name":"32'h0","addr":"(RSB)","loc":"d,17:12,17:16","dtypep":"(HC)"} + ]} + ]}, + {"type":"UNPACKARRAYDTYPE","name":"","addr":"(WI)","loc":"d,17:12,17:16","dtypep":"(WI)","declRange":"[7:0]","refDTypep":"(ISB)","childDTypep": [], "rangep": [ {"type":"RANGE","name":"","addr":"(SSB)","loc":"d,17:12,17:16", "leftp": [ @@ -3037,7 +3040,7 @@ {"type":"CONST","name":"32'h0","addr":"(USB)","loc":"d,17:12,17:16","dtypep":"(HC)"} ]} ]}, - {"type":"UNPACKARRAYDTYPE","name":"","addr":"(WI)","loc":"d,17:12,17:16","dtypep":"(WI)","declRange":"[7:0]","refDTypep":"(LSB)","childDTypep": [], + {"type":"UNPACKARRAYDTYPE","name":"","addr":"(IM)","loc":"d,17:12,17:16","dtypep":"(IM)","isCompound":true,"declRange":"[7:0]","refDTypep":"(SB)","childDTypep": [], "rangep": [ {"type":"RANGE","name":"","addr":"(VSB)","loc":"d,17:12,17:16", "leftp": [ @@ -3047,27 +3050,17 @@ {"type":"CONST","name":"32'h0","addr":"(XSB)","loc":"d,17:12,17:16","dtypep":"(HC)"} ]} ]}, - {"type":"UNPACKARRAYDTYPE","name":"","addr":"(IM)","loc":"d,17:12,17:16","dtypep":"(IM)","isCompound":true,"declRange":"[7:0]","refDTypep":"(SB)","childDTypep": [], - "rangep": [ - {"type":"RANGE","name":"","addr":"(YSB)","loc":"d,17:12,17:16", - "leftp": [ - {"type":"CONST","name":"32'h7","addr":"(ZSB)","loc":"d,17:12,17:16","dtypep":"(HC)"} - ], - "rightp": [ - {"type":"CONST","name":"32'h0","addr":"(ATB)","loc":"d,17:12,17:16","dtypep":"(HC)"} - ]} - ]}, {"type":"BASICDTYPE","name":"logic","addr":"(LB)","loc":"d,23:23,23:24","dtypep":"(LB)","keyword":"logic","range":"31:0","generic":true,"signed":true,"rangep": []}, {"type":"VOIDDTYPE","name":"","addr":"(DB)","loc":"a,0:0,0:0","dtypep":"(DB)"}, {"type":"BASICDTYPE","name":"bit","addr":"(HN)","loc":"a,0:0,0:0","dtypep":"(HN)","keyword":"bit","range":"63:0","generic":true,"rangep": []}, {"type":"UNPACKARRAYDTYPE","name":"","addr":"(W)","loc":"d,11:8,11:9","dtypep":"(W)","declRange":"[0:0]","refDTypep":"(HN)","childDTypep": [], "rangep": [ - {"type":"RANGE","name":"","addr":"(BTB)","loc":"d,11:8,11:9", + {"type":"RANGE","name":"","addr":"(YSB)","loc":"d,11:8,11:9", "leftp": [ - {"type":"CONST","name":"32'h0","addr":"(CTB)","loc":"d,11:8,11:9","dtypep":"(HC)"} + {"type":"CONST","name":"32'h0","addr":"(ZSB)","loc":"d,11:8,11:9","dtypep":"(HC)"} ], "rightp": [ - {"type":"CONST","name":"32'h0","addr":"(DTB)","loc":"d,11:8,11:9","dtypep":"(HC)"} + {"type":"CONST","name":"32'h0","addr":"(ATB)","loc":"d,11:8,11:9","dtypep":"(HC)"} ]} ]}, {"type":"BASICDTYPE","name":"IData","addr":"(IP)","loc":"a,0:0,0:0","dtypep":"(IP)","keyword":"IData","range":"31:0","generic":true,"rangep": []}, @@ -3081,9 +3074,9 @@ ]}, {"type":"CONSTPOOL","name":"","addr":"(D)","loc":"a,0:0,0:0", "modulep": [ - {"type":"MODULE","name":"@CONST-POOL@","addr":"(ETB)","loc":"a,0:0,0:0","origName":"@CONST-POOL@","verilogName":"@CONST-POOL@","level":0,"timeunit":"NONE","inlinesp": [], + {"type":"MODULE","name":"@CONST-POOL@","addr":"(BTB)","loc":"a,0:0,0:0","origName":"@CONST-POOL@","verilogName":"@CONST-POOL@","level":0,"timeunit":"NONE","inlinesp": [], "stmtsp": [ - {"type":"SCOPE","name":"TOP","addr":"(FTB)","loc":"a,0:0,0:0","aboveScopep":"UNLINKED","aboveCellp":"UNLINKED","modp":"(ETB)","varsp": [],"blocksp": [],"inlinesp": []} + {"type":"SCOPE","name":"TOP","addr":"(CTB)","loc":"a,0:0,0:0","aboveScopep":"UNLINKED","aboveCellp":"UNLINKED","modp":"(BTB)","varsp": [],"blocksp": [],"inlinesp": []} ]} ]} ]} diff --git a/test_regress/t/t_json_only_flat_vlvbound.out b/test_regress/t/t_json_only_flat_vlvbound.out index 6117b9a80..e0c3a714a 100644 --- a/test_regress/t/t_json_only_flat_vlvbound.out +++ b/test_regress/t/t_json_only_flat_vlvbound.out @@ -82,26 +82,26 @@ "lhsp": [ {"type":"VARREF","name":"__Vfunc_vlvbound_test.foo__0__val","addr":"(KC)","loc":"d,15:57,15:60","dtypep":"(H)","access":"WR","varp":"(SB)","varScopep":"(RB)","classOrPackagep":"UNLINKED"} ],"timingControlp": []}, - {"type":"ASSIGN","name":"","addr":"(LC)","loc":"d,16:17,16:20","dtypep":"(K)", + {"type":"ASSIGN","name":"","addr":"(LC)","loc":"d,15:34,15:37","dtypep":"(K)", "rhsp": [ - {"type":"CRESET","name":"","addr":"(MC)","loc":"d,16:17,16:20","dtypep":"(K)"} + {"type":"CRESET","name":"","addr":"(MC)","loc":"d,15:34,15:37","dtypep":"(K)"} ], "lhsp": [ - {"type":"VARREF","name":"__Vfunc_vlvbound_test.foo__0__ret","addr":"(NC)","loc":"d,16:17,16:20","dtypep":"(K)","access":"WR","varp":"(UB)","varScopep":"(TB)","classOrPackagep":"UNLINKED"} + {"type":"VARREF","name":"__Vfunc_vlvbound_test.foo__0__Vfuncout","addr":"(NC)","loc":"d,15:34,15:37","dtypep":"(K)","access":"WR","varp":"(QB)","varScopep":"(PB)","classOrPackagep":"UNLINKED"} ],"timingControlp": []}, - {"type":"ASSIGN","name":"","addr":"(OC)","loc":"d,17:13,17:14","dtypep":"(WB)", + {"type":"ASSIGN","name":"","addr":"(OC)","loc":"d,16:17,16:20","dtypep":"(K)", "rhsp": [ - {"type":"CRESET","name":"","addr":"(PC)","loc":"d,17:13,17:14","dtypep":"(WB)"} + {"type":"CRESET","name":"","addr":"(PC)","loc":"d,16:17,16:20","dtypep":"(K)"} ], "lhsp": [ - {"type":"VARREF","name":"__Vfunc_vlvbound_test.foo__0__i","addr":"(QC)","loc":"d,17:13,17:14","dtypep":"(WB)","access":"WR","varp":"(XB)","varScopep":"(VB)","classOrPackagep":"UNLINKED"} + {"type":"VARREF","name":"__Vfunc_vlvbound_test.foo__0__ret","addr":"(QC)","loc":"d,16:17,16:20","dtypep":"(K)","access":"WR","varp":"(UB)","varScopep":"(TB)","classOrPackagep":"UNLINKED"} ],"timingControlp": []}, - {"type":"ASSIGN","name":"","addr":"(RC)","loc":"d,15:34,15:37","dtypep":"(K)", + {"type":"ASSIGN","name":"","addr":"(RC)","loc":"d,17:13,17:14","dtypep":"(WB)", "rhsp": [ - {"type":"CRESET","name":"","addr":"(SC)","loc":"d,15:34,15:37","dtypep":"(K)"} + {"type":"CRESET","name":"","addr":"(SC)","loc":"d,17:13,17:14","dtypep":"(WB)"} ], "lhsp": [ - {"type":"VARREF","name":"__Vfunc_vlvbound_test.foo__0__Vfuncout","addr":"(TC)","loc":"d,15:34,15:37","dtypep":"(K)","access":"WR","varp":"(QB)","varScopep":"(PB)","classOrPackagep":"UNLINKED"} + {"type":"VARREF","name":"__Vfunc_vlvbound_test.foo__0__i","addr":"(TC)","loc":"d,17:13,17:14","dtypep":"(WB)","access":"WR","varp":"(XB)","varScopep":"(VB)","classOrPackagep":"UNLINKED"} ],"timingControlp": []}, {"type":"ASSIGN","name":"","addr":"(UC)","loc":"d,18:11,18:12","dtypep":"(WB)", "rhsp": [ @@ -204,26 +204,26 @@ "lhsp": [ {"type":"VARREF","name":"__Vfunc_vlvbound_test.foo__1__val","addr":"(ME)","loc":"d,15:57,15:60","dtypep":"(H)","access":"WR","varp":"(BC)","varScopep":"(AC)","classOrPackagep":"UNLINKED"} ],"timingControlp": []}, - {"type":"ASSIGN","name":"","addr":"(NE)","loc":"d,16:17,16:20","dtypep":"(K)", + {"type":"ASSIGN","name":"","addr":"(NE)","loc":"d,15:34,15:37","dtypep":"(K)", "rhsp": [ - {"type":"CRESET","name":"","addr":"(OE)","loc":"d,16:17,16:20","dtypep":"(K)"} + {"type":"CRESET","name":"","addr":"(OE)","loc":"d,15:34,15:37","dtypep":"(K)"} ], "lhsp": [ - {"type":"VARREF","name":"__Vfunc_vlvbound_test.foo__1__ret","addr":"(PE)","loc":"d,16:17,16:20","dtypep":"(K)","access":"WR","varp":"(DC)","varScopep":"(CC)","classOrPackagep":"UNLINKED"} + {"type":"VARREF","name":"__Vfunc_vlvbound_test.foo__1__Vfuncout","addr":"(PE)","loc":"d,15:34,15:37","dtypep":"(K)","access":"WR","varp":"(ZB)","varScopep":"(YB)","classOrPackagep":"UNLINKED"} ],"timingControlp": []}, - {"type":"ASSIGN","name":"","addr":"(QE)","loc":"d,17:13,17:14","dtypep":"(WB)", + {"type":"ASSIGN","name":"","addr":"(QE)","loc":"d,16:17,16:20","dtypep":"(K)", "rhsp": [ - {"type":"CRESET","name":"","addr":"(RE)","loc":"d,17:13,17:14","dtypep":"(WB)"} + {"type":"CRESET","name":"","addr":"(RE)","loc":"d,16:17,16:20","dtypep":"(K)"} ], "lhsp": [ - {"type":"VARREF","name":"__Vfunc_vlvbound_test.foo__1__i","addr":"(SE)","loc":"d,17:13,17:14","dtypep":"(WB)","access":"WR","varp":"(FC)","varScopep":"(EC)","classOrPackagep":"UNLINKED"} + {"type":"VARREF","name":"__Vfunc_vlvbound_test.foo__1__ret","addr":"(SE)","loc":"d,16:17,16:20","dtypep":"(K)","access":"WR","varp":"(DC)","varScopep":"(CC)","classOrPackagep":"UNLINKED"} ],"timingControlp": []}, - {"type":"ASSIGN","name":"","addr":"(TE)","loc":"d,15:34,15:37","dtypep":"(K)", + {"type":"ASSIGN","name":"","addr":"(TE)","loc":"d,17:13,17:14","dtypep":"(WB)", "rhsp": [ - {"type":"CRESET","name":"","addr":"(UE)","loc":"d,15:34,15:37","dtypep":"(K)"} + {"type":"CRESET","name":"","addr":"(UE)","loc":"d,17:13,17:14","dtypep":"(WB)"} ], "lhsp": [ - {"type":"VARREF","name":"__Vfunc_vlvbound_test.foo__1__Vfuncout","addr":"(VE)","loc":"d,15:34,15:37","dtypep":"(K)","access":"WR","varp":"(ZB)","varScopep":"(YB)","classOrPackagep":"UNLINKED"} + {"type":"VARREF","name":"__Vfunc_vlvbound_test.foo__1__i","addr":"(VE)","loc":"d,17:13,17:14","dtypep":"(WB)","access":"WR","varp":"(FC)","varScopep":"(EC)","classOrPackagep":"UNLINKED"} ],"timingControlp": []}, {"type":"ASSIGN","name":"","addr":"(WE)","loc":"d,18:11,18:12","dtypep":"(WB)", "rhsp": [ diff --git a/test_regress/t/t_static_in_loop_unsup.py b/test_regress/t/t_static_in_loop.py similarity index 89% rename from test_regress/t/t_static_in_loop_unsup.py rename to test_regress/t/t_static_in_loop.py index 715e8f4a9..60a79a36b 100755 --- a/test_regress/t/t_static_in_loop_unsup.py +++ b/test_regress/t/t_static_in_loop.py @@ -12,6 +12,8 @@ import vltest_bootstrap test.scenarios('vlt') test.top_filename = "t/t_static_in_loop.v" -test.lint(fails=True, expect_filename=test.golden_filename) +test.compile() + +test.execute() test.passes() diff --git a/test_regress/t/t_static_in_loop.v b/test_regress/t/t_static_in_loop.v index 164fe3f5e..4cf527329 100644 --- a/test_regress/t/t_static_in_loop.v +++ b/test_regress/t/t_static_in_loop.v @@ -6,9 +6,9 @@ module t; initial begin - automatic int x = 0; + static int x = 0; while (x < 10) begin : outer_loop - automatic int y = 0; + static int y = 0; while (y < x) begin : inner_loop static int a = 0; a++; @@ -16,7 +16,7 @@ module t; end x++; end - if (outer_loop.inner_loop.a != 45) $stop; + if (outer_loop.inner_loop.a != 9) $stop; $write("*-* All Finished *-*\n"); $finish; diff --git a/test_regress/t/t_timing_debug2.out b/test_regress/t/t_timing_debug2.out index 66c5f4f0e..15008c9d5 100644 --- a/test_regress/t/t_timing_debug2.out +++ b/test_regress/t/t_timing_debug2.out @@ -34,19 +34,6 @@ -V{t#,#}+ Vt_timing_debug2_t__03a__03aLocalWaitClass::_ctor_var_reset -V{t#,#}+ Vt_timing_debug2_t__03a__03aClkClass::new -V{t#,#}+ Vt_timing_debug2_t__03a__03aClkClass::_ctor_var_reset --V{t#,#}+ Vt_timing_debug2___024root___timing_ready --V{t#,#}+ Vt_timing_debug2___024root___eval_initial --V{t#,#}+ Vt_timing_debug2_t___eval_initial__TOP__t__Vtiming__0 --V{t#,#}+ Vt_timing_debug2___024root____VbeforeTrig_h########__0 --V{t#,#} Suspending process waiting for @([event] t.ec.e) at t/t_timing_class.v:111 --V{t#,#}+ Vt_timing_debug2_t___eval_initial__TOP__t__Vtiming__1 --V{t#,#}+ Vt_timing_debug2_t___eval_initial__TOP__t__Vtiming__2 --V{t#,#}+ Vt_timing_debug2_t___eval_initial__TOP__t__Vtiming__3 --V{t#,#}+ Vt_timing_debug2_t___eval_initial__TOP__t__Vtiming__4 --V{t#,#}+ Vt_timing_debug2_t__03a__03aClkClass::__VnoInFunc_count_5 --V{t#,#} Suspending process waiting for @(posedge t::ClkClass.clk) at t/t_timing_class.v:97 --V{t#,#}+ Vt_timing_debug2_t___eval_initial__TOP__t__Vtiming__5 --V{t#,#}+ Vt_timing_debug2_t___eval_initial__TOP__t__Vtiming__6 -V{t#,#}+ Vt_timing_debug2_t__03a__03aDelayClass::new -V{t#,#}+ Vt_timing_debug2_t__03a__03aDelayClass::_ctor_var_reset -V{t#,#}+ Vt_timing_debug2_t__03a__03aDelay10::new @@ -65,6 +52,19 @@ -V{t#,#}+ Vt_timing_debug2_t__03a__03aNoDelay::_ctor_var_reset -V{t#,#}+ Vt_timing_debug2_t__03a__03aAssignDelayClass::new -V{t#,#}+ Vt_timing_debug2_t__03a__03aAssignDelayClass::_ctor_var_reset +-V{t#,#}+ Vt_timing_debug2___024root___timing_ready +-V{t#,#}+ Vt_timing_debug2___024root___eval_initial +-V{t#,#}+ Vt_timing_debug2_t___eval_initial__TOP__t__Vtiming__0 +-V{t#,#}+ Vt_timing_debug2___024root____VbeforeTrig_h########__0 +-V{t#,#} Suspending process waiting for @([event] t.ec.e) at t/t_timing_class.v:111 +-V{t#,#}+ Vt_timing_debug2_t___eval_initial__TOP__t__Vtiming__1 +-V{t#,#}+ Vt_timing_debug2_t___eval_initial__TOP__t__Vtiming__2 +-V{t#,#}+ Vt_timing_debug2_t___eval_initial__TOP__t__Vtiming__3 +-V{t#,#}+ Vt_timing_debug2_t___eval_initial__TOP__t__Vtiming__4 +-V{t#,#}+ Vt_timing_debug2_t__03a__03aClkClass::__VnoInFunc_count_5 +-V{t#,#} Suspending process waiting for @(posedge t::ClkClass.clk) at t/t_timing_class.v:97 +-V{t#,#}+ Vt_timing_debug2_t___eval_initial__TOP__t__Vtiming__5 +-V{t#,#}+ Vt_timing_debug2_t___eval_initial__TOP__t__Vtiming__6 -V{t#,#}+ Vt_timing_debug2_t__03a__03aDelay10::__VnoInFunc_do_delay -V{t#,#}+ Vt_timing_debug2_t___eval_initial__TOP__t__Vtiming__7 -V{t#,#}+ Vt_timing_debug2_t__03a__03aForkClass::new diff --git a/test_regress/t/t_var_init_static_automatic.py b/test_regress/t/t_var_init_static_automatic.py new file mode 100755 index 000000000..f090e5249 --- /dev/null +++ b/test_regress/t/t_var_init_static_automatic.py @@ -0,0 +1,18 @@ +#!/usr/bin/env python3 +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# This program is free software; you can redistribute it and/or modify it +# under the terms of either the GNU Lesser General Public License Version 3 +# or the Perl Artistic License Version 2.0. +# SPDX-FileCopyrightText: 2026 Wilson Snyder +# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 + +import vltest_bootstrap + +test.scenarios('simulator') + +test.compile(verilator_flags2=['--timing']) + +test.execute() + +test.passes() diff --git a/test_regress/t/t_var_init_static_automatic.v b/test_regress/t/t_var_init_static_automatic.v new file mode 100644 index 000000000..2a469e67b --- /dev/null +++ b/test_regress/t/t_var_init_static_automatic.v @@ -0,0 +1,226 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain. +// SPDX-FileCopyrightText: 2026 Wilson Snyder +// SPDX-License-Identifier: CC0-1.0 + +// verilog_format: off +`define stop $stop +`define checkd(gotv,expv) if ((gotv) !== (expv)) begin $write("%%Error: %s:%0d: got=%0d exp=%0d\n", `__FILE__,`__LINE__, (gotv), (expv)); `stop; end +`define checkd_elab(gotv,expv) if ((gotv) !== (expv)) begin $error("%%Error: %s:%0d: got=%0d exp=%0d", `__FILE__,`__LINE__, (gotv), (expv)); end +// verilog_format: on + +class Cls; + + task tsk(); + for (int i = 0; i < 3; i++) begin + /*automatic*/ int tj_auto; + /*automatic*/ int tj_auto_init = 10; + /*automatic*/ int tqueue_auto[$]; + /*automatic*/ int tqueue_auto_init[$] = '{1}; + static int tj_static; // = 0 + static int tj_static_init = 10; + static int tqueue_static[$]; + static int tqueue_static_init[$] = '{1}; + + $display("Function iteration %0d:", i); + tj_auto = tj_auto + 1; + `checkd(tj_auto, 1); + + tj_auto_init = tj_auto_init + 1; + `checkd(tj_auto_init, 11); + + `checkd(tqueue_auto.size(), 0); + tqueue_auto.push_back(i + 10); + `checkd(tqueue_auto.size(), 1); + + `checkd(tqueue_auto_init.size(), 1); + tqueue_auto_init.push_back(i + 20); + `checkd(tqueue_auto_init.size(), 2); + + tj_static = tj_static + 1; + `checkd(tj_static, i + 1); + + tj_static_init = tj_static_init + 1; + `checkd(tj_static_init, i + 1 + 10); + + tqueue_static.push_back(i + 20); + `checkd(tqueue_static.size(), i + 1); + + tqueue_static_init.push_back(i + 20); + `checkd(tqueue_static_init.size(), i + 2); + end + endtask + +endclass + +module t; + + function int func_const_kj_init(); + int r; + for (int i = 0; i < 3; i++) begin + automatic int kj; + automatic int kj_init = 10; + + kj = kj + 1; + `checkd_elab(kj, 1); + + kj_init = kj_init + 1; + `checkd_elab(kj_init, 11); + r = kj_init; + end + return r; + endfunction + + localparam FUNC_CONST_KJ_INIT = func_const_kj_init(); + + task forked; + automatic int forktop = 100; + for (int i = 0; i < 3; i++) begin + // fork declarations are executed before all parallel statements (IEEE 1800-2023 9.3.2) + fork : f_named + // Automatics-in-forks Verilator will move to a VDynScope class + automatic int fj_auto; + automatic int fj_auto_init = 10; + automatic int fqueue_auto[$]; + automatic int fqueue_auto_init[$] = '{1}; + // Statics-in-forks will stay in the original task + static int fj_static; // = 0 + static int fj_static_init = 10; + static int fqueue_static[$]; + static int fqueue_static_init[$] = '{1}; + begin + $display("Fork iteration %0d:", i); + ++forktop; + + fj_auto = fj_auto + 1; + `checkd(fj_auto, 1); + + fj_auto_init = fj_auto_init + 1; + `checkd(fj_auto_init, 11); + + `checkd(fqueue_auto.size(), 0); + fqueue_auto.push_back(i + 10); + `checkd(fqueue_auto.size(), 1); + + `checkd(fqueue_auto_init.size(), 1); + fqueue_auto_init.push_back(i + 20); + `checkd(fqueue_auto_init.size(), 2); + + fj_static = fj_static + 1; + `checkd(fj_static, i + 1); + + fj_static_init = fj_static_init + 1; + `checkd(fj_static_init, i + 1 + 10); + + fqueue_static.push_back(i + 20); + `checkd(fqueue_static.size(), i + 1); + + fqueue_static_init.push_back(i + 20); + `checkd(fqueue_static_init.size(), i + 2); + end + join + end + `checkd(forktop, 100 + 3); + endtask + + task forked_begin; + // fork declarations are executed before all parallel statements (IEEE 1800-2023 9.3.2) + fork : f_named + for (int i = 0; i < 3; i++) begin + // Automatics-in-zorks Verilator will move to a VDynScope class + automatic int zj_auto; + automatic int zj_auto_init = 10; + automatic int zqueue_auto[$]; + automatic int zqueue_auto_init[$] = '{1}; + // Statics-in-forks will stay in the original task + static int zj_static; // = 0 + static int zj_static_init = 10; + static int zqueue_static[$]; + static int zqueue_static_init[$] = '{1}; + begin + $display("Fork-begin iteration %0d:", i); + + zj_auto = zj_auto + 1; + `checkd(zj_auto, 1); + + zj_auto_init = zj_auto_init + 1; + `checkd(zj_auto_init, 11); + + `checkd(zqueue_auto.size(), 0); + zqueue_auto.push_back(i + 10); + `checkd(zqueue_auto.size(), 1); + + `checkd(zqueue_auto_init.size(), 1); + zqueue_auto_init.push_back(i + 20); + `checkd(zqueue_auto_init.size(), 2); + + zj_static = zj_static + 1; + `checkd(zj_static, i + 1); + + zj_static_init = zj_static_init + 1; + `checkd(zj_static_init, i + 1 + 10); + + zqueue_static.push_back(i + 20); + `checkd(zqueue_static.size(), i + 1); + + zqueue_static_init.push_back(i + 20); + `checkd(zqueue_static_init.size(), i + 2); + end + end + join + endtask + + initial begin + Cls c; + c = new(); + c.tsk(); + + `checkd(FUNC_CONST_KJ_INIT, 11); + + for (int i = 0; i < 3; i++) begin : p_named + automatic int pj_auto; + automatic int pj_auto_init = 10; + automatic int pqueue_auto[$]; + automatic int pqueue_auto_init[$] = '{1}; + static int pj_static; // = 0 + static int pj_static_init = 10; + static int pqueue_static[$]; + static int pqueue_static_init[$] = '{1}; + + $display("Process iteration %0d:", i); + pj_auto = pj_auto + 1; + `checkd(pj_auto, 1); + `checkd(p_named.pj_auto, 1); + + pj_auto_init = pj_auto_init + 1; + `checkd(pj_auto_init, 11); + + `checkd(pqueue_auto.size(), 0); + pqueue_auto.push_back(i + 10); + `checkd(pqueue_auto.size(), 1); + + `checkd(pqueue_auto_init.size(), 1); + pqueue_auto_init.push_back(i + 20); + `checkd(pqueue_auto_init.size(), 2); + + pj_static = pj_static + 1; + `checkd(pj_static, i + 1); + + pj_static_init = pj_static_init + 1; + `checkd(pj_static_init, i + 1 + 10); + + pqueue_static.push_back(i + 10); + `checkd(pqueue_static.size(), i + 1); + + pqueue_static_init.push_back(i + 20); + `checkd(pqueue_static_init.size(), i + 2); + end + + forked(); + forked_begin(); + + $finish; + end + +endmodule diff --git a/test_regress/t/t_wrapper_context__top0.dat.out b/test_regress/t/t_wrapper_context__top0.dat.out index 2bb1345d8..07d4800da 100644 --- a/test_regress/t/t_wrapper_context__top0.dat.out +++ b/test_regress/t/t_wrapper_context__top0.dat.out @@ -135,7 +135,7 @@ C 'ft/t_wrapper_context.vl17n23ttogglepagev_toggle/topocounter[9]:0- C 'ft/t_wrapper_context.vl17n23ttogglepagev_toggle/topocounter[9]:1->0htop0.top' 0 C 'ft/t_wrapper_context.vl18n16ttogglepagev_toggle/topodone_o:0->1htop0.top' 1 C 'ft/t_wrapper_context.vl18n16ttogglepagev_toggle/topodone_o:1->0htop0.top' 0 -C 'ft/t_wrapper_context.vl21n3tlinepagev_line/topoblockS21,24,28,30-32htop0.top' 1 +C 'ft/t_wrapper_context.vl21n3tlinepagev_line/topoblockS21-24,28,30-32htop0.top' 1 C 'ft/t_wrapper_context.vl35n3tlinepagev_line/topoblockS35htop0.top' 11 C 'ft/t_wrapper_context.vl36n5tbranchpagev_branch/topoifS36htop0.top' 1 C 'ft/t_wrapper_context.vl36n6tbranchpagev_branch/topoelseS37htop0.top' 10 diff --git a/test_regress/t/t_wrapper_context__top1.dat.out b/test_regress/t/t_wrapper_context__top1.dat.out index 273e471db..8ef66f3d0 100644 --- a/test_regress/t/t_wrapper_context__top1.dat.out +++ b/test_regress/t/t_wrapper_context__top1.dat.out @@ -135,7 +135,7 @@ C 'ft/t_wrapper_context.vl17n23ttogglepagev_toggle/topocounter[9]:0- C 'ft/t_wrapper_context.vl17n23ttogglepagev_toggle/topocounter[9]:1->0htop1.top' 0 C 'ft/t_wrapper_context.vl18n16ttogglepagev_toggle/topodone_o:0->1htop1.top' 1 C 'ft/t_wrapper_context.vl18n16ttogglepagev_toggle/topodone_o:1->0htop1.top' 0 -C 'ft/t_wrapper_context.vl21n3tlinepagev_line/topoblockS21,24,28,30-32htop1.top' 1 +C 'ft/t_wrapper_context.vl21n3tlinepagev_line/topoblockS21-24,28,30-32htop1.top' 1 C 'ft/t_wrapper_context.vl35n3tlinepagev_line/topoblockS35htop1.top' 6 C 'ft/t_wrapper_context.vl36n5tbranchpagev_branch/topoifS36htop1.top' 1 C 'ft/t_wrapper_context.vl36n6tbranchpagev_branch/topoelseS37htop1.top' 5