Split out of #1985, which reported two independent defects in two different modules. The
first — weight_prefetch_ctrl never retiring prefetch_done — is fixed on master by #2340.
This issue carries the second half, which lives in a different file and is a different change.
The defect
multilayer_sequencer (bootstrap/src/bitnet_pipeline.rs) waits on prefetch_done with a
level test:
PREFETCH: begin start_prefetch<=1'b1; state<=WAIT_PF; end
WAIT_PF: if(prefetch_done) state<=RUN;
A level-triggered handshake cannot distinguish "done already" from "done still". WAIT_PF
samples the flag in the same cycle it holds start_prefetch high, so its correctness depends
entirely on the producer having lowered the flag by then.
Status after #2340
#2340 makes weight_prefetch_ctrl retire prefetch_done on entry to IDLE, so the flag is
genuinely a one-cycle pulse. Measured end-to-end with the real sequencer and the real
controller, two layers:
| controller |
overlap_cycles |
layer_start_during_prefetch |
| before #2340 |
1 |
1 |
| after #2340 |
0 |
0 |
So the observable overlap is closed today. What is not closed is the coupling: the
sequencer is correct only because the producer happens to clear the flag in time. Any future
producer that holds prefetch_done for more than the idle gap — or any added latency between
PREFETCH and WAIT_PF — reintroduces the fall-through silently, with no assertion to catch it.
Suggested shape
#1985 proposed an explicit request/acknowledge, which makes the handshake edge-insensitive
rather than relying on producer timing:
if (!prefetch_done) pf_ack <= 1'b1; // observe it low = acknowledged
if (pf_ack && prefetch_done) begin ... end
Why this is filed rather than bundled
It is a different module from the one #2340 touches, and #2340's diff was kept to the defect
it proved. Worth noting for whoever picks this up: no workflow runs cargo test -p t27c
(corpus-ratchet.yml records the step being removed by #2292 after going red on master), so
a guard added here will not be executed by any required check as things stand.
Split out of #1985, which reported two independent defects in two different modules. The
first —
weight_prefetch_ctrlnever retiringprefetch_done— is fixed on master by #2340.This issue carries the second half, which lives in a different file and is a different change.
The defect
multilayer_sequencer(bootstrap/src/bitnet_pipeline.rs) waits onprefetch_donewith alevel test:
A level-triggered handshake cannot distinguish "done already" from "done still".
WAIT_PFsamples the flag in the same cycle it holds
start_prefetchhigh, so its correctness dependsentirely on the producer having lowered the flag by then.
Status after #2340
#2340 makes
weight_prefetch_ctrlretireprefetch_doneon entry toIDLE, so the flag isgenuinely a one-cycle pulse. Measured end-to-end with the real sequencer and the real
controller, two layers:
overlap_cycleslayer_start_during_prefetchSo the observable overlap is closed today. What is not closed is the coupling: the
sequencer is correct only because the producer happens to clear the flag in time. Any future
producer that holds
prefetch_donefor more than the idle gap — or any added latency betweenPREFETCHandWAIT_PF— reintroduces the fall-through silently, with no assertion to catch it.Suggested shape
#1985 proposed an explicit request/acknowledge, which makes the handshake edge-insensitive
rather than relying on producer timing:
Why this is filed rather than bundled
It is a different module from the one #2340 touches, and #2340's diff was kept to the defect
it proved. Worth noting for whoever picks this up: no workflow runs
cargo test -p t27c(
corpus-ratchet.ymlrecords the step being removed by #2292 after going red on master), soa guard added here will not be executed by any required check as things stand.