exp: fix pulse-race hang in tb_layer_reuse_vs_zero_reuse.v (EXP-0058 follow-up); real remaining bug still open, 7.16x NOT yet re-verified

Same class of testbench-vs-DUT scheduling race documented in EXP-0058
(tb_layer_prefetch_ctrl.v, tb_neural_processor_layer_reuse.v) was also
present here on ctrl_req/fill_done/consume_done: clearing a one-cycle
pulse on the very next @(posedge clk) let the clear land in the same
active-region pass as the edge the DUT needed to sample it at, so the
pulse could be silently missed. Confirmed via direct state tracing:
sdram_controller_openrow.v sat in S_IDLE with busy=0 forever after the
first burst, never latching req_pending for the second -- this is why
the file hung indefinitely rather than completing. Fixed with the same
#1-before-clear hardening as the other files.

Honesty note: fixing this hang exposed a SECOND, still-unfixed bug in
prefetch_layer's own fill_addr sequencing (real data-correctness
failures once the run actually completes, not just a hang) -- so
EXP-0057's own headline "7.16x real measured speedup" number is NOT
re-verified by this commit and should not be treated as confirmed. Not
pursued further -- see decisions.log for why (project paused).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MUG92aM9m68TRc4rG55BcC
This commit is contained in:
2026-09-16 15:38:12 +02:00
co-authored by Claude Sonnet 5
parent 80c89fa10d
commit 3416b8d3cf
+19 -5
View File
@@ -77,11 +77,25 @@ module tb;
.ba(ba), .a(a), .dq(dq), .dqm(dqm)
);
// Pulse-hardening note (found while debugging this exact file,
// EXP-0058 follow-up): clearing ctrl_req on the very next
// @(posedge clk) after setting it puts the clear in the SAME
// active-region pass as the edge sdram_controller_openrow.v's own
// synchronous `if (req) req_pending <= 1'b1;` latch needs to sample
// it at -- their relative execution order is implementation-
// defined, so the one-cycle req pulse can be silently missed
// (confirmed via direct state/req tracing: the controller sat in
// S_IDLE with busy=0 forever after the first burst, never latching
// req_pending for the second). Same class of bug as the
// consume_done/pf_start races fixed in tb_layer_prefetch_ctrl.v
// and tb_neural_processor_layer_reuse.v -- fixed the same way, by
// holding the pulse past the edge with a real time delay (#1)
// before clearing.
task automatic sdram_write_burst(input [ADDR_WIDTH-1:0] word_addr, input [16*BURST_LEN-1:0] data);
begin
@(posedge clk); while (ctrl_busy) @(posedge clk);
ctrl_req = 1'b1; ctrl_wr = 1'b1; ctrl_addr = word_addr; ctrl_wdata = data; ctrl_wmask = {(2*BURST_LEN){1'b0}};
@(posedge clk); ctrl_req = 1'b0;
@(posedge clk); #1; ctrl_req = 1'b0;
while (!ctrl_ready) @(posedge clk);
end
endtask
@@ -89,7 +103,7 @@ module tb;
begin
@(posedge clk); while (ctrl_busy) @(posedge clk);
ctrl_req = 1'b1; ctrl_wr = 1'b0; ctrl_addr = word_addr; ctrl_wmask = {(2*BURST_LEN){1'b0}};
@(posedge clk); ctrl_req = 1'b0;
@(posedge clk); #1; ctrl_req = 1'b0;
while (!ctrl_ready) @(posedge clk);
data = ctrl_rdata;
end
@@ -150,7 +164,7 @@ module tb;
end
end
@(posedge clk); fill_we = 1'b0;
fill_done = 1'b1; @(posedge clk); fill_done = 1'b0;
fill_done = 1'b1; @(posedge clk); #1; fill_done = 1'b0;
end
endtask
@@ -175,7 +189,7 @@ module tb;
@(posedge clk);
end
end
consume_done = 1'b1; @(posedge clk); consume_done = 1'b0;
consume_done = 1'b1; @(posedge clk); #1; consume_done = 1'b0;
end
endtask
@@ -213,7 +227,7 @@ module tb;
$display("=== REUSE case correctness pass: %0d layers x %0d reuses, double-buffered background prefetch (data check only, not timed) ===", L, M);
prefetch_layer(0);
consume_done = 1'b1; @(posedge clk); consume_done = 1'b0; // trigger initial swap
consume_done = 1'b1; @(posedge clk); #1; consume_done = 1'b0; // trigger initial swap
for (li_i = 0; li_i < L; li_i = li_i + 1) begin
fork
consume_layer_check(li_i, errors, errors);