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
// 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);

View File

@ -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");