-
Notifications
You must be signed in to change notification settings - Fork 446
[FIRRTL] Suspected incorrect memory mask lowering for aggregate partial write with dynamic subaccess #10105
Copy link
Copy link
Open
Description
firtool-1.144.0 (LLVM 23.0.0git)
Reproducer
FIRRTL version 6.0.0
circuit MaskNested :
public module MaskNested :
input clock : Clock
input wen : UInt<1>
input addr : UInt<2>
input sel : UInt<1>
input in_a : UInt<3>
input in_b : UInt<1>
output out_a : UInt<3>
output out_b : UInt<1>
cmem mem : { a : UInt<3>, b : UInt<1>[2] }[4]
infer mport rd = mem[addr], clock
infer mport wr = mem[addr], clock
when wen :
connect wr.a, in_a
connect wr.b[sel], in_b
connect out_a, rd.a
connect out_b, rd.b[sel]./firtool m.fir -o m.sv
Generated Verilog
module MaskNested(
input clock, wen,
input [1:0] addr,
input sel,
input [2:0] in_a,
input in_b,
output [2:0] out_a,
output out_b
);
wire mem_wr_mask_b_0 = wen & ~sel;
wire mem_wr_mask_b_1 = wen & sel;
mem_4x5 mem_ext (
...
.W0_data ({in_a, {2{in_b}}}),
.W0_mask ({wen, mem_wr_mask_b_1, {3{mem_wr_mask_b_0}}})
);
assign out_a = _mem_ext_R0_data[4:2];
assign out_b = sel ? _mem_ext_R0_data[1] : _mem_ext_R0_data[0];
endmoduleMemory writes are bit-granular:
always @(posedge W0_clk) begin
if (W0_en & W0_mask[0]) Memory[W0_addr][0] <= W0_data[0];
if (W0_en & W0_mask[1]) Memory[W0_addr][1] <= W0_data[1];
if (W0_en & W0_mask[2]) Memory[W0_addr][2] <= W0_data[2];
if (W0_en & W0_mask[3]) Memory[W0_addr][3] <= W0_data[3];
if (W0_en & W0_mask[4]) Memory[W0_addr][4] <= W0_data[4];
endThe Bug
Read-side confirms the bit packing:
bit [4:2] = a (3 bits)
bit [1] = b[1] (1 bit)
bit [0] = b[0] (1 bit)
Mask should match this layout. Expanding the generated mask concatenation:
Generated: {wen, mem_wr_mask_b_1, mem_wr_mask_b_0, mem_wr_mask_b_0, mem_wr_mask_b_0}
[4] [3] [2] [1] [0]
bit 4 a[2] → wen ✓
bit 3 a[1] → wen & sel ✗ (should be wen)
bit 2 a[0] → wen & ~sel ✗ (should be wen)
bit 1 b[1] → wen & ~sel ✗ (should be wen & sel)
bit 0 b[0] → wen & ~sel ✓
Expected: {wen, wen, wen, (wen & sel), (wen & ~sel)}
[4] [3] [2] [1] [0]
a[2] a[1] a[0] b[1] b[0]
The b[sel] per-element masks bleed into the a field; only a's MSB and b[0] are correctly masked.
AI-Assisted-By
Claude-Opus-4.6
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
No labels