From 08854223725b684428c091b153f8fd327a794a56 Mon Sep 17 00:00:00 2001 From: Ryszard Rozak Date: Mon, 19 Jan 2026 13:54:44 +0100 Subject: [PATCH] WIP: Create nested loops in recursive function Signed-off-by: Ryszard Rozak --- src/V3Force.cpp | 55 ++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 47 insertions(+), 8 deletions(-) diff --git a/src/V3Force.cpp b/src/V3Force.cpp index 7e2fae5da..0b7b12042 100644 --- a/src/V3Force.cpp +++ b/src/V3Force.cpp @@ -154,7 +154,7 @@ public: toInsertp->addNextHere(stmtp); stmtp = outerStmtp; } - activeInitp->addStmtsp(new AstInitial{flp, stmtp->cloneTree(true)}); + activeInitp->addStmtsp(new AstInitial{flp, stmtp}); { // Add the combinational override // Explicitly list dependencies for update. // Note: rdVscp is also needed to retrigger assignment for the first time. @@ -174,16 +174,55 @@ public: // Reuse the statements created for __VforceEn initialization // and replace var ref on the LHS and the RHS AstVarRef* const rdRefp = new AstVarRef{flp, m_rdVscp, VAccess::WRITE}; - AstNodeExpr* const rdRhsp = forcedUpdate(vscp, loopVarRefs); - enRefp->replaceWith(rdRefp); - VL_DO_DANGLING(enRefp->deleteTree(), enRefp); - enRhsp->replaceWith(rdRhsp); - VL_DO_DANGLING(enRhsp->deleteTree(), enRhsp); - - activep->addStmtsp(new AstAlways{flp, VAlwaysKwd::ALWAYS, nullptr, stmtp}); + AstVarRef* origRefp = new AstVarRef{flp, vscp, VAccess::READ}; + ForceState::markNonReplaceable(origRefp); + activep->addStmtsp(new AstAlways{flp, VAlwaysKwd::ALWAYS, nullptr, + getAssignStmtsp(rdRefp, origRefp)}); vscp->scopep()->addBlocksp(activep); } } + AstNodeStmt* getAssignStmtsp(AstNodeExpr* lhsp, AstNodeExpr* rhsp) { + static int cnt = 0; + FileLine* const flp = lhsp->fileline(); + const AstNodeDType* const lhsDtypep = lhsp->dtypep()->skipRefp(); + if (lhsDtypep->isIntegralOrPacked()) { + return new AstAssign{flp, lhsp, rhsp}; + } else if (const AstStructDType* const structDtypep + = VN_CAST(lhsDtypep, StructDType)) { + + } else if (const AstUnpackArrayDType* const arrayDtypep + = VN_CAST(lhsDtypep, UnpackArrayDType)) { + AstVar* const loopVarp = new AstVar{flp, VVarType::MODULETEMP, + m_rdVscp->varp()->name() + "__VwhileIter_new" + + std::to_string(cnt++), + VFlagBitPacked{}, 32}; + m_rdVscp->varp()->addNext(loopVarp); + AstVarScope* const loopVarScopep + = new AstVarScope{flp, m_rdVscp->scopep(), loopVarp}; + m_rdVscp->addNext(loopVarScopep); + AstVarRef* const readRefp = new AstVarRef{flp, loopVarScopep, VAccess::READ}; + AstNodeStmt* const currInitp = new AstAssign{ + flp, new AstVarRef{flp, loopVarScopep, VAccess::WRITE}, new AstConst{flp, 0}}; + AstLoop* const currWhilep = new AstLoop{flp}; + currInitp->addNextHere(currWhilep); + AstLoopTest* const loopTestp = new AstLoopTest{ + flp, currWhilep, + new AstNeq{ + flp, readRefp, + new AstConst{flp, static_cast(arrayDtypep->elementsConst())}}}; + currWhilep->addStmtsp(loopTestp); + AstArraySel* const lhsSelp + = new AstArraySel{flp, lhsp, readRefp->cloneTree(false)}; + AstArraySel* const rhsSelp + = new AstArraySel{flp, rhsp, readRefp->cloneTree(false)}; + currWhilep->addStmtsp(getAssignStmtsp(lhsSelp, rhsSelp)); + AstAssign* const currIncrp = new AstAssign{ + flp, new AstVarRef{flp, loopVarScopep, VAccess::WRITE}, + new AstAdd{flp, readRefp->cloneTree(false), new AstConst{flp, 1}}}; + currWhilep->addStmtsp(currIncrp); + return currInitp; + } + } static AstNodeExpr* applySelects(AstNodeExpr* exprp, const std::vector& selectExprs) { for (AstNodeExpr* const sp : selectExprs) {