pub fn from_causal_conv(
spec: &CausalConvSpec,
names: &StageNames,
target: &SpatialTarget,
) -> Result<Vec<SpatialProgram>, SpatialReject>Expand description
Y[c] = Σ_t CS'[t, c]·WC[t, c] where CS' = shift(CS) ← X — the depthwise causal conv1d over a
taps-deep decode ring, as TWO sections.
★ THE RING IS WRITTEN IN ONE SECTION AND READ IN THE NEXT, AND THAT IS THE WHOLE POINT. The update
and the reduction are separated by a barrier, so the order between them is a fact the certificate
checks (StateOrder) and the evaluator enforces (StaleStateRead) rather than an accident of which
engine happened to run first. Fold them into one section and a reversed scheduler would compute the
convolution against LAST token’s ring and nothing would notice.