Fix forcing unpacked variables (#7149)

This commit is contained in:
Ryszard Rozak 2026-02-28 15:53:41 +01:00 committed by GitHub
parent df6b808c49
commit 6f892d58ac
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 47 additions and 32 deletions

View File

@ -442,40 +442,30 @@ class ForceConvertVisitor final : public VNVisitor {
// continuous assignment shall reestablish that assignment and schedule a reevaluation in // continuous assignment shall reestablish that assignment and schedule a reevaluation in
// the continuous assignment's scheduling region. // the continuous assignment's scheduling region.
AstAssign* const resetRdp AstAssign* const resetRdp
= new AstAssign{flp, lhsp->cloneTreePure(false), lhsp->unlinkFrBack()}; = new AstAssign{flp, lhsp->unlinkFrBack(), lhsp->cloneTreePure(false)};
resetRdp->user2(true); resetRdp->user2(true);
// Replace write refs on the LHS AstVarRef* const refp = VN_AS(AstNodeVarRef::varRefLValueRecurse(lhsp), VarRef);
resetRdp->lhsp()->foreach([this](AstVarRef* refp) { AstVarScope* const vscp = refp->varScopep();
if (refp->access() != VAccess::WRITE) return; AstVarRef* const rhsRefp = refp->clonep();
AstVarScope* const vscp = refp->varScopep();
if (vscp->varp()->isContinuously()) { if (vscp->varp()->isContinuously()) {
AstVarRef* const newpRefp = new AstVarRef{ AstVarRef* const lhsRefp = new AstVarRef{
refp->fileline(), m_state.getForceComponents(vscp).m_rdVscp, VAccess::WRITE}; refp->fileline(), m_state.getForceComponents(vscp).m_rdVscp, VAccess::WRITE};
refp->replaceWith(newpRefp); refp->replaceWith(lhsRefp);
VL_DO_DANGLING(refp->deleteTree(), refp); VL_DO_DANGLING(refp->deleteTree(), refp);
} rhsRefp->access(VAccess::READ);
}); ForceState::markNonReplaceable(rhsRefp);
// 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);
} else { } else {
resetRdp->rhsp()->foreach([this](AstVarRef* refp) { if (rhsRefp->dtypep()->skipRefp()->isIntegralOrPacked()) {
if (refp->access() != VAccess::WRITE) return; // In this case var ref can be replaced with expression
AstVarScope* const vscp = refp->varScopep(); rhsRefp->replaceWith(m_state.getForceComponents(vscp).forcedUpdate(vscp));
if (vscp->varp()->isContinuously()) { VL_DO_DANGLING(rhsRefp->deleteTree(), rhsRefp);
refp->access(VAccess::READ); } else {
ForceState::markNonReplaceable(refp); AstNodeExpr* const origRhsp = resetRdp->rhsp();
} else { origRhsp->replaceWith(
refp->replaceWith(m_state.getForceComponents(vscp).forcedUpdate(vscp)); m_state.getForceComponents(vscp).forcedUpdate(vscp, origRhsp, rhsRefp));
VL_DO_DANGLING(refp->deleteTree(), refp); VL_DO_DANGLING(origRhsp->deleteTree(), origRhsp);
} }
});
} }
resetRdp->addNext(resetEnp); resetRdp->addNext(resetEnp);

View File

@ -16,8 +16,17 @@ module t (
integer cyc = 0; integer cyc = 0;
typedef union packed {
int x;
bit [31:0] y;
} union_t;
logic logic_arr[2][-2:2][-3:-5]; logic logic_arr[2][-2:2][-3:-5];
int int_arr[-1:2][1][3]; 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 // Test loop
always @(posedge clk) begin always @(posedge clk) begin
@ -25,38 +34,54 @@ module t (
if (cyc == 0) begin if (cyc == 0) begin
logic_arr[0][2][-4] <= 1; logic_arr[0][2][-4] <= 1;
int_arr[0][0][2] <= 1; int_arr[0][0][2] <= 1;
union_arr[1].x <= 1;
end end
else if (cyc == 1) begin else if (cyc == 1) begin
`checkh(logic_arr[0][2][-4], 1); `checkh(logic_arr[0][2][-4], 1);
`checkh(int_arr[0][0][2], 1); `checkh(int_arr[0][0][2], 1);
`checkh(bit_arr[2][3], 1);
`checkh(union_arr[1].x, 1);
end end
else if (cyc == 2) begin else if (cyc == 2) begin
force logic_arr[0][2][-4] = 0; force logic_arr[0][2][-4] = 0;
force int_arr[0][0][2] = 0; force int_arr[0][0][2] = 0;
force bit_arr[2][3] = 0;
force union_arr[1].y = 2;
end end
else if (cyc == 3) begin else if (cyc == 3) begin
`checkh(logic_arr[0][2][-4], 0); `checkh(logic_arr[0][2][-4], 0);
logic_arr[0][2][-4] <= 1; logic_arr[0][2][-4] <= 1;
`checkh(int_arr[0][0][2], 0); `checkh(int_arr[0][0][2], 0);
int_arr[0][0][2] <= 1; int_arr[0][0][2] <= 1;
`checkh(bit_arr[2][3], 0);
`checkh(union_arr[1].x, 2);
union_arr[1].x <= 3;
end end
else if (cyc == 4) begin else if (cyc == 4) begin
`checkh(logic_arr[0][2][-4], 0); `checkh(logic_arr[0][2][-4], 0);
`checkh(int_arr[0][0][2], 0); `checkh(int_arr[0][0][2], 0);
`checkh(union_arr[1].y, 2);
end end
else if (cyc == 5) begin else if (cyc == 5) begin
release logic_arr[0][2][-4]; release logic_arr[0][2][-4];
release int_arr[0][0][2]; release int_arr[0][0][2];
release bit_arr[2][3];
`checkh(bit_arr[2][3], 1);
release union_arr[1].x;
end end
else if (cyc == 6) begin else if (cyc == 6) begin
`checkh(logic_arr[0][2][-4], 0); `checkh(logic_arr[0][2][-4], 0);
logic_arr[0][2][-4] <= 1; logic_arr[0][2][-4] <= 1;
`checkh(int_arr[0][0][2], 0); `checkh(int_arr[0][0][2], 0);
int_arr[0][0][2] <= 1; int_arr[0][0][2] <= 1;
`checkh(bit_arr[2][3], 1);
`checkh(union_arr[1].x, 2);
union_arr[1].y <= 4;
end end
else if (cyc == 7) begin else if (cyc == 7) begin
`checkh(logic_arr[0][2][-4], 1); `checkh(logic_arr[0][2][-4], 1);
`checkh(int_arr[0][0][2], 1); `checkh(int_arr[0][0][2], 1);
`checkh(union_arr[1].x, 4);
end end
else if (cyc == 8) begin else if (cyc == 8) begin
$write("*-* All Finished *-*\n"); $write("*-* All Finished *-*\n");