Fix force not substituted into an unpacked array index (#8002)
This commit is contained in:
parent
b5fa4212b0
commit
2e4dbb846c
|
|
@ -1389,7 +1389,12 @@ class ForceReplaceVisitor final : public VNVisitor {
|
||||||
|
|
||||||
void visit(AstVarRef* nodep) override {
|
void visit(AstVarRef* nodep) override {
|
||||||
if (ForceState::isNotReplaceable(nodep)) return;
|
if (ForceState::isNotReplaceable(nodep)) return;
|
||||||
if (nodep->backp() && VN_IS(nodep->backp(), ArraySel)) return;
|
// The array an ArraySel selects from is left to visit(AstArraySel), which builds
|
||||||
|
// the force-aware read for the whole select. The index is an ordinary read and
|
||||||
|
// must still be substituted here, so check which child this is.
|
||||||
|
if (const AstArraySel* const backSelp = VN_CAST(nodep->backp(), ArraySel)) {
|
||||||
|
if (backSelp->fromp() == nodep) return;
|
||||||
|
}
|
||||||
|
|
||||||
const ForceState::VarForceInfo* const varInfo = m_state.getVarInfo(nodep->varScopep());
|
const ForceState::VarForceInfo* const varInfo = m_state.getVarInfo(nodep->varScopep());
|
||||||
if (!varInfo) return;
|
if (!varInfo) return;
|
||||||
|
|
|
||||||
|
|
@ -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()
|
||||||
|
|
||||||
|
test.execute()
|
||||||
|
|
||||||
|
test.passes()
|
||||||
|
|
@ -0,0 +1,104 @@
|
||||||
|
// 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
|
||||||
|
|
||||||
|
// A forced signal used as the index of an unpacked array select must read as
|
||||||
|
// forced, exactly as it does everywhere else (IEEE 1800-2023 10.6.2).
|
||||||
|
//
|
||||||
|
// Before the accompanying fix the array select kept reading the unforced
|
||||||
|
// value, while arithmetic on the same signal read the forced one.
|
||||||
|
//
|
||||||
|
// Both the continuous and the procedural read of the array are checked. The
|
||||||
|
// controls are arithmetic on the same signal and a packed select on it, both
|
||||||
|
// of which were already correct.
|
||||||
|
|
||||||
|
// verilog_format: off
|
||||||
|
`define stop $stop
|
||||||
|
`define checkh(gotv,expv) do if ((gotv) !== (expv)) begin $write("%%Error: %s:%0d: got=%0x exp=%0x\n", `__FILE__,`__LINE__, (gotv), (expv)); `stop; end while(0);
|
||||||
|
// verilog_format: on
|
||||||
|
|
||||||
|
module rf (
|
||||||
|
input logic [3:0] raddr_i,
|
||||||
|
output logic [7:0] rdata_o,
|
||||||
|
output logic [7:0] plus_o,
|
||||||
|
output logic [7:0] proc_o,
|
||||||
|
output logic [7:0] packed_o
|
||||||
|
);
|
||||||
|
logic [7:0] mem[16];
|
||||||
|
logic [127:0] packed_mem;
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
for (int i = 0; i < 16; ++i) mem[i] = 8'h10 + i[7:0];
|
||||||
|
packed_mem = 128'h1f1e1d1c_1b1a1918_17161514_13121110;
|
||||||
|
end
|
||||||
|
|
||||||
|
// Array select on the forced index.
|
||||||
|
assign rdata_o = mem[raddr_i];
|
||||||
|
// Arithmetic on the same forced index, as the reference.
|
||||||
|
assign plus_o = {4'h0, raddr_i} + 8'h1;
|
||||||
|
// Packed select on the same forced index, as a second reference.
|
||||||
|
assign packed_o = packed_mem[8*raddr_i+:8];
|
||||||
|
|
||||||
|
// The same array select read procedurally rather than continuously.
|
||||||
|
always_comb proc_o = mem[raddr_i];
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
module t (
|
||||||
|
input clk
|
||||||
|
);
|
||||||
|
int cyc = 0;
|
||||||
|
logic [3:0] addr;
|
||||||
|
logic [7:0] rdata, plus, proc, packd;
|
||||||
|
|
||||||
|
rf u_rf (
|
||||||
|
.raddr_i(addr),
|
||||||
|
.rdata_o(rdata),
|
||||||
|
.plus_o(plus),
|
||||||
|
.proc_o(proc),
|
||||||
|
.packed_o(packd)
|
||||||
|
);
|
||||||
|
|
||||||
|
// Runtime-varying so the reads cannot be constant folded.
|
||||||
|
assign addr = cyc[3:0];
|
||||||
|
|
||||||
|
always @(posedge clk) begin
|
||||||
|
cyc <= cyc + 1;
|
||||||
|
if (cyc == 4) force u_rf.raddr_i = 4'h7;
|
||||||
|
if (cyc == 8) force u_rf.raddr_i = 4'ha;
|
||||||
|
if (cyc == 12) release u_rf.raddr_i;
|
||||||
|
end
|
||||||
|
|
||||||
|
always @(negedge clk) begin
|
||||||
|
case (cyc)
|
||||||
|
2: begin // Unforced: addr follows cyc.
|
||||||
|
`checkh(rdata, 8'h12)
|
||||||
|
`checkh(proc, 8'h12)
|
||||||
|
`checkh(plus, 8'h03)
|
||||||
|
`checkh(packd, 8'h12)
|
||||||
|
end
|
||||||
|
6: begin // Forced to 7 while cyc says 6.
|
||||||
|
`checkh(plus, 8'h08)
|
||||||
|
`checkh(packd, 8'h17)
|
||||||
|
`checkh(rdata, 8'h17)
|
||||||
|
`checkh(proc, 8'h17)
|
||||||
|
end
|
||||||
|
10: begin // Re-forced to 10 while cyc says 10, so only the value proves it.
|
||||||
|
`checkh(plus, 8'h0b)
|
||||||
|
`checkh(packd, 8'h1a)
|
||||||
|
`checkh(rdata, 8'h1a)
|
||||||
|
`checkh(proc, 8'h1a)
|
||||||
|
end
|
||||||
|
14: begin // Released: back to following cyc.
|
||||||
|
`checkh(plus, 8'h0f)
|
||||||
|
`checkh(packd, 8'h1e)
|
||||||
|
`checkh(rdata, 8'h1e)
|
||||||
|
`checkh(proc, 8'h1e)
|
||||||
|
$write("*-* All Finished *-*\n");
|
||||||
|
$finish;
|
||||||
|
end
|
||||||
|
default: ;
|
||||||
|
endcase
|
||||||
|
end
|
||||||
|
endmodule
|
||||||
Loading…
Reference in New Issue