diff --git a/src/V3Force.cpp b/src/V3Force.cpp index 7f3a4f8b5..edbd0fb20 100644 --- a/src/V3Force.cpp +++ b/src/V3Force.cpp @@ -442,40 +442,30 @@ class ForceConvertVisitor final : public VNVisitor { // continuous assignment shall reestablish that assignment and schedule a reevaluation in // the continuous assignment's scheduling region. AstAssign* const resetRdp - = new AstAssign{flp, lhsp->cloneTreePure(false), lhsp->unlinkFrBack()}; + = new AstAssign{flp, lhsp->unlinkFrBack(), lhsp->cloneTreePure(false)}; resetRdp->user2(true); - // Replace write refs on the LHS - resetRdp->lhsp()->foreach([this](AstVarRef* refp) { - if (refp->access() != VAccess::WRITE) return; - AstVarScope* const vscp = refp->varScopep(); - if (vscp->varp()->isContinuously()) { - AstVarRef* const newpRefp = new AstVarRef{ - refp->fileline(), m_state.getForceComponents(vscp).m_rdVscp, VAccess::WRITE}; - refp->replaceWith(newpRefp); - VL_DO_DANGLING(refp->deleteTree(), refp); - } - }); - // Replace write refs on RHS - if (VN_IS(resetRdp->rhsp(), ArraySel) || VN_IS(resetRdp->rhsp(), StructSel)) { - AstVarRef* const refp - = VN_AS(AstNodeVarRef::varRefLValueRecurse(resetRdp->rhsp()), VarRef); - AstVarScope* const vscp = refp->varScopep(); - AstNodeExpr* const origRhsp = resetRdp->rhsp(); - origRhsp->replaceWith( - m_state.getForceComponents(vscp).forcedUpdate(vscp, origRhsp, refp)); - VL_DO_DANGLING(origRhsp->deleteTree(), origRhsp); + AstVarRef* const refp = VN_AS(AstNodeVarRef::varRefLValueRecurse(lhsp), VarRef); + AstVarScope* const vscp = refp->varScopep(); + AstVarRef* const rhsRefp = refp->clonep(); + + if (vscp->varp()->isContinuously()) { + AstVarRef* const lhsRefp = new AstVarRef{ + refp->fileline(), m_state.getForceComponents(vscp).m_rdVscp, VAccess::WRITE}; + refp->replaceWith(lhsRefp); + VL_DO_DANGLING(refp->deleteTree(), refp); + rhsRefp->access(VAccess::READ); + ForceState::markNonReplaceable(rhsRefp); } else { - resetRdp->rhsp()->foreach([this](AstVarRef* refp) { - if (refp->access() != VAccess::WRITE) return; - AstVarScope* const vscp = refp->varScopep(); - if (vscp->varp()->isContinuously()) { - refp->access(VAccess::READ); - ForceState::markNonReplaceable(refp); - } else { - refp->replaceWith(m_state.getForceComponents(vscp).forcedUpdate(vscp)); - VL_DO_DANGLING(refp->deleteTree(), refp); - } - }); + if (rhsRefp->dtypep()->skipRefp()->isIntegralOrPacked()) { + // In this case var ref can be replaced with expression + rhsRefp->replaceWith(m_state.getForceComponents(vscp).forcedUpdate(vscp)); + VL_DO_DANGLING(rhsRefp->deleteTree(), rhsRefp); + } else { + AstNodeExpr* const origRhsp = resetRdp->rhsp(); + origRhsp->replaceWith( + m_state.getForceComponents(vscp).forcedUpdate(vscp, origRhsp, rhsRefp)); + VL_DO_DANGLING(origRhsp->deleteTree(), origRhsp); + } } resetRdp->addNext(resetEnp); diff --git a/test_regress/t/t_force_unpacked.v b/test_regress/t/t_force_unpacked.v index e942d8523..8335035e5 100644 --- a/test_regress/t/t_force_unpacked.v +++ b/test_regress/t/t_force_unpacked.v @@ -16,8 +16,17 @@ module t ( integer cyc = 0; + typedef union packed { + int x; + bit [31:0] y; + } union_t; + logic logic_arr[2][-2:2][-3:-5]; int int_arr[-1:2][1][3]; + bit [5:0] bit_arr[5]; + union_t union_arr[4]; + + assign bit_arr[2][3] = 1; // Test loop always @(posedge clk) begin @@ -25,38 +34,54 @@ module t ( if (cyc == 0) begin logic_arr[0][2][-4] <= 1; int_arr[0][0][2] <= 1; + union_arr[1].x <= 1; end else if (cyc == 1) begin `checkh(logic_arr[0][2][-4], 1); `checkh(int_arr[0][0][2], 1); + `checkh(bit_arr[2][3], 1); + `checkh(union_arr[1].x, 1); end else if (cyc == 2) begin force logic_arr[0][2][-4] = 0; force int_arr[0][0][2] = 0; + force bit_arr[2][3] = 0; + force union_arr[1].y = 2; end else if (cyc == 3) begin `checkh(logic_arr[0][2][-4], 0); logic_arr[0][2][-4] <= 1; `checkh(int_arr[0][0][2], 0); int_arr[0][0][2] <= 1; + `checkh(bit_arr[2][3], 0); + `checkh(union_arr[1].x, 2); + union_arr[1].x <= 3; end else if (cyc == 4) begin `checkh(logic_arr[0][2][-4], 0); `checkh(int_arr[0][0][2], 0); + `checkh(union_arr[1].y, 2); end else if (cyc == 5) begin release logic_arr[0][2][-4]; release int_arr[0][0][2]; + release bit_arr[2][3]; + `checkh(bit_arr[2][3], 1); + release union_arr[1].x; end else if (cyc == 6) begin `checkh(logic_arr[0][2][-4], 0); logic_arr[0][2][-4] <= 1; `checkh(int_arr[0][0][2], 0); int_arr[0][0][2] <= 1; + `checkh(bit_arr[2][3], 1); + `checkh(union_arr[1].x, 2); + union_arr[1].y <= 4; end else if (cyc == 7) begin `checkh(logic_arr[0][2][-4], 1); `checkh(int_arr[0][0][2], 1); + `checkh(union_arr[1].x, 4); end else if (cyc == 8) begin $write("*-* All Finished *-*\n");