Per-vertex GS fog end-to-end (gs_stub emit incl. persp_emit5, gs_prim_list_feeder XYZ2->XYZF2 on PRIM.FGE, gs_make_sh3_scheduler_fixture.py F/FGE packing), new fog TBs, fidelity attribution tooling. Functional baseline before removing the dead bilinear lerp8 clamps (Codex: 161-node comb loop -> -0.042ns setup fail). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
15 KiB
Ch439 — measured FIFO right-sizing and scanout write-port timing convergence
Why this chapter exists
The second Ch438 GUI fit completed successfully but was not timing-clean and
was not deployed. Its RBF SHA-256 was
b5865b599101d429b86c67c25ae9688c0f6dda334aa7ebbcbd664f31226aa602.
The fit used 39,442 ALMs, 56,446 registers, 349/358 M20Ks, and 160 DSPs.
The actual post-fit STA report showed three concrete families:
- setup WNS -0.924 ns / TNS -12.931 ns in the 310 MHz EMIF domain;
- six of the top ten setup paths were
u_zc_emit|u_req|raddr_lo_q[1]to physicalmem_loRAM address ports; - one setup path at -0.403 ns was
u_lpddr_scan_lb|r_data_q[240]to thelb1RAM write port; - the only negative design-clock hold path was -4.221 ns from the bridge's
quasi-static
lpddr_video_src_qtovsrc_cap_dacross unrelated clocks.
The preceding two-way width bank did not reduce the request RAM count and made placement worse than the original packed 16K FIFO. This chapter therefore removes that banked form from the production instance instead of chasing it with another seed.
Structural correction
Request FIFO: 16K to 8K from measured occupancy
The complete 311-epoch f52 production replay was rerun at depth 16,384 while recording the per-epoch request occupancy. The maximum was 6,115 entries at epoch 148. The next power-of-two depth, 8,192, therefore leaves 2,077 entries or 34 percent measured headroom. It also halves the packed 93-bit request FIFO's depth, expected M20K footprint, and physical read-address tree.
The production u_zc_emit instance now uses REQ_DEPTH=8192 and the ordinary
monolithic registered-read FIFO. zc_g_drops remains the fail-closed runtime
guard if a future fixture exceeds the measured envelope.
Scanout line buffers: RAM-local physical write stage
The response stage no longer drives all three line-buffer RAM write ports.
L_R copies each returned beat directly into data/address/enable registers
dedicated to the selected physical RAM. Those registers commit independently
while the FSM issues or waits for the next single-beat read; L_C is used only
once to flush the final beat of a row. The fitter can place each 256-bit launch
bank beside its RAM without adding a state to every beat.
LPDDR video-source bundled CDC
lpddr_video_src_q is written before lpddr_ctrl_commit_w toggles.
vsrc_cap_d samples the stable data only after that toggle traverses the
three-flop commit_d_sync. The raw zero-cycle hold analysis between unrelated
clocks is therefore non-functional. The SDC now cuts only HOLD for this exact
source/destination pair and retains a 2 ns maximum net-delay bound. Setup is
not false-pathed.
Verification before the next GUI compile
- binomial scanout: 2,400/2,400 exact pixels, zero underflow/read errors, PASS;
- horizontal-stretch scanout: 2,400/2,400 exact pixels, zero underflow/read errors, PASS;
- registered asynchronous FIFO stress: 3,285 writes/reads, zero errors, PASS;
- directed Z/color integration: 1,500 fragments, zero color overflow/BRESP errors, PASS;
- complete f52 replay at the shipping 8K request depth:
- 311 epochs;
- 2,339,914 fragments fed and 2,286,292 passed;
- zero drops, Z mismatches, color mismatches, color overflow, or BRESP errors;
- PASS;
- Ch439 framebuffer SHA-256:
d0047677371a0f6e4e319458926f604a8599c92baaf34d09b8e1fd452e31662b; - byte-identical to the accepted Ch437 framebuffer and the prior Ch438 production simulation.
No Ch438 timing-red RBF has been deployed. A fresh Quartus 26.1 GUI compile is required for this consolidated Ch439 correction.
First Ch439 fit and hardware feedback
The first owner GUI fit of the resource-relieved design was fully signoff-clean:
EMIF setup +0.098 ns, all hold classes nonnegative, 39,514 ALMs, 57,331
registers, 309/358 M20Ks, and 160 DSPs. It also proved that the 8K cut removed
exactly 40 RAM blocks as predicted. The generated RBF SHA-256 was
7167deb651c08057828a360b6083ec27eb140d59eb08b7b06315cbc1d235ec13.
It loaded successfully and the complete 311-epoch hardware replay passed every
renderer gate; its framebuffer was byte-identical to simulation at SHA-256
d0047677371a0f6e4e319458926f604a8599c92baaf34d09b8e1fd452e31662b.
However, the HDMI line-buffer status was not acceptable. LPDDR_STATUS held
0xF1, with bit 5 set. Disabling LPDDR scanout cleared it to 0xD1, and
re-enabling scanout restored 0xF1, proving sustained line-buffer underflow
rather than a sticky AXI read error or startup-only event.
Root cause was the first Ch439 L_R -> L_C -> L_W write pipeline, which added
one EMIF cycle to every 32-byte beat and crossed the real just-in-time refill
margin. Ch439b removed L_W, but board testing proved that retaining L_C
after every beat was still too slow. Its clean fit used 39,616 ALMs, 57,109
registers, 309/358 M20Ks, and 160 DSPs; EMIF setup was +0.050 ns and every
other timing class was also clean. RBF SHA-256 was
56e45346338907eb6c307320757774ac65efa56dabb644906a5600f5ea73a982.
The full 311-epoch board replay again passed every renderer gate and produced
the exact expected framebuffer, but four live samples across advancing frames
all read LPDDR_STATUS=0xF1. Source-off cleared status to 0xD1; source-on
restored 0xF1 immediately. Ch439b is therefore rejected as well.
Its board evidence is retained as
sim/data/top_psmct32_raster_demo/sh3_zsrt139f52_ch439b_board_run.log and
sh3_zsrt139f52_ch439b_board_fb.mem; the framebuffer is byte-identical to the
8K production simulation at SHA-256
d0047677371a0f6e4e319458926f604a8599c92baaf34d09b8e1fd452e31662b.
Ch439c turns the RAM-local write stage into an actual pipeline. A captured
beat commits from its local register while the AXI FSM advances to the next
read. Only the final beat takes L_C, as a one-cycle row-end flush before
next_fetch is published. This restores the accepted pre-Ch439 per-beat
cadence while retaining the physical timing cut. Directed binomial and
horizontal-stretch tests are exact at 2,400/2,400 pixels with zero underflow or
read errors; the 640x192 and 256x768 PSMCT32 tests are exact at 49,152/49,152
and 196,608/196,608 pixels with zero underflow or read errors. A fresh owner
GUI compile is required for Ch439c.
Ch439c fit feedback and Ch439d address-tree cut
The owner Ch439c GUI compile completed successfully but was not deployed. It used 39,472 ALMs, 56,640 registers, 309/358 M20Ks, and 160 DSPs. Hold, recovery, removal, and minimum-pulse-width checks were clean, but EMIF setup failed at -1.009 ns / -60.117 ns TNS across 166 endpoints. All ten reported worst paths were the same zero-logic-level route:
- launch:
u_zc_emit|u_req|raddr_q[7]; - capture: the monolithic request FIFO's physical
mem_rtl_0port-B address registers; - data delay: 4.077 ns, of which 3.759 ns was interconnect.
This is not a scanout-pipeline path. The Ch439c placement exposed the remaining
8K request-RAM address tree. Ch439d enables the already-regressed two-way
payload bank only on u_zc_emit.u_req. At the present 8K depth, each preserved
read-address copy drives half the width at half the original Ch438 depth: about
one quarter of the physical RAM load that defeated the earlier 16K banked fit.
Depth, ordering, registered-read latency, and the measured 2,077-entry capacity
margin are unchanged.
Post-cut verification is complete:
- banked asynchronous FIFO stress: 3,285 writes and reads, zero errors, PASS;
- directed Z/color integration: 1,500 fragments, zero overflow/BRESP errors, PASS;
- complete 311-epoch f52 replay at 8K: 2,339,914 fragments fed, 2,286,292 passed, zero drops/mismatches/errors, PASS;
- framebuffer remains byte-identical at SHA-256
d0047677371a0f6e4e319458926f604a8599c92baaf34d09b8e1fd452e31662b.
The Ch439c timing-red RBF SHA-256 is
d006cc1ede2db1eeb5b8ae961eafc047eff3e6ef3ce58a173ae4f8e3bf7c3cac and
was not deployed. A fresh owner GUI compile is required for Ch439d.
Board evidence is retained as
sim/data/top_psmct32_raster_demo/sh3_zsrt139f52_ch439_board_run.log and
sh3_zsrt139f52_ch439_board_fb.mem. The HDMI-equivalent filtered preview is
captures/gs/silenthill3/extracted/recon/sh3_zsrt139f52_ch439_hdmi.png and
remains MAE 13.1111 / RMSE 19.1051 against the PCSX2 reference.
Ch439d fit feedback and Ch439e quadrant cut
The owner Ch439d GUI compile completed successfully and the two width banks
were inferred as intended, but the RBF was not deployed because EMIF setup
still failed. Its RBF SHA-256 is
fe6eb909b8d875b617587f8afafdc510f77e4b5369c66c225ba9cea404ef6ba9.
The actual post-fit results were:
- 39,410 required ALMs and 42,843 final-placement ALMs (91 percent);
- 56,822 dedicated logic registers, 309/358 M20Ks, and 160 DSPs;
- setup WNS -0.515 ns / TNS -36.152 ns, with 120 failing endpoints;
- hold, recovery, removal, and minimum-pulse-width checks all clean.
Every reported worst setup path remained one zero-logic-level physical-route
family from u_req|raddr_{lo,hi}_q[*] to the corresponding mem_{lo,hi} M20K
address input register. The worst path was raddr_lo_q[10] to a mem_lo
address register, with 3.615 ns data delay into the 3.225 ns EMIF period.
Width banking improved WNS by about 0.5 ns versus Ch439c but left each address
copy spanning the full 8K depth, so Ch439d is rejected rather than reseeded.
Reducing the FIFO below 8K is not valid for the current producer. The existing
instrumented complete f52 replay measured a peak request occupancy of 6,115 at
epoch 148, and the producer drops fragments when zc_g_ready deasserts. The
8,192-entry depth and its measured 2,077-entry margin therefore remain fixed.
Similarly, directly feeding the next binary pointer into the RAM address port
was already exercised before Ch420 and exposed pointer logic plus the same
high-fanout physical address family.
Ch439e instead crosses two depth banks with the existing two payload-width
banks. The request FIFO is physically four 4K-deep RAM quadrants:
mem_lo0, mem_lo1, mem_hi0, and mem_hi1. Each has its own preserved
11-bit RAM-facing read-address register, reducing one launch tree to roughly
one quarter of the original physical RAM load. A one-bit selector delayed with
the synchronous RAM data performs only a 2:1 lower/upper-depth selection at
the registered output. Capacity, ordering, CDC publication, accepted-read
latency, and atomic tuple writes are unchanged.
Ch439e prefit verification is complete:
- quadrant asynchronous FIFO stress: 3,285 writes and reads, zero errors, PASS;
- directed Z/color integration: 1,500 fragments, zero overflow/BRESP errors, PASS;
- complete 311-epoch f52 production replay at 8K: 2,339,914 fragments fed, 2,286,292 passed, zero drops/mismatches/errors, PASS;
- binomial and horizontal-stretch scanout: 2,400/2,400 exact pixels apiece, zero underflow/read errors, PASS;
- framebuffer SHA-256 remains byte-identical at
d0047677371a0f6e4e319458926f604a8599c92baaf34d09b8e1fd452e31662b.
The next owner GUI compile must confirm that all four quadrant memories and four independent read-address trees survive synthesis, that setup closes, and that the new RAM-output depth selector does not become a replacement setup family. Only a fully signoff-clean Ch439e artifact is eligible for deployment.
Ch439e fit feedback and Ch439f arithmetic-boundary correction
The owner Ch439e GUI compile completed successfully and confirmed the intended request-FIFO result. All four quadrant memories were inferred, request-memory usage stayed at 309/358 M20Ks, and the 310 MHz EMIF setup domain closed at +0.019 ns. Hold, recovery, removal, and minimum-pulse-width checks were also clean. The design used 38,849 required ALMs, 42,880 final-placement ALMs (92 percent), 57,233 dedicated registers, and 160/376 DSP blocks.
The artifact is nevertheless rejected because the 25 MHz design clock failed
at WNS -1.294 ns / TNS -89.732 ns across 208 endpoints. Its rejected RBF
SHA-256 is
4deb590b83036e250e042158896a3a69c731bbccc09eef04c06f523cc382c6e5.
Every reported worst path was the same 27-logic-level, 41.141 ns arithmetic
family:
- launch:
u_demo|u_gs|u_tex|g_bilinear.tap[0][11]; - capture:
u_texcache|tex_mem...portbaddr[10]; - middle: both bilinear lerps, GS modulation/blend arithmetic, and the next texture-coordinate/address arithmetic.
The initial hypothesis was that the project-wide AUTO_RESOURCE_SHARING ON
setting caused this apparently cross-transaction path. The fit report records
GS arithmetic operators packed with u_tex bilinear operators, including
u_demo|u_gs|mult_66 merged into u_demo|u_gs|u_tex|mult_9; Intel's Quartus
26.1 setting reference also warns that sharing mux/control logic can reduce
Fmax. Ch439f tests that hypothesis directly below rather than assuming it.
Ch439f disabled automatic resource sharing globally while retaining
AGGRESSIVE AREA. This was a controlled synthesis experiment, not a seed or
RTL-latency change.
The fresh owner Ch439f compile conclusively rejected that hypothesis.
Synthesis reported Auto Resource Sharing: Off, but the complete result was
bit-for-bit structurally unchanged at report precision: 38,849 required ALMs,
42,880 final-placement ALMs, 57,233 registers, 309 M20Ks, 160 DSPs, EMIF setup
+0.019 ns, and the identical design-clock -1.294 ns / -89.732 ns / 208-endpoint
tap-to-texture-cache family with the same 41.141 ns path. The project setting
is therefore restored to its area-oriented value.
Ch439g functional exception for the impossible packed-DSP arc
The RTL cone proves that a captured bilinear tap cannot reach the texture read
address combinationally. tap[*] feeds the two lerp levels only in BS_DONE,
where the result is captured into tex_color_hold; the external filtered
result is exposed from that register only in the distinct BS_OUT cycle.
Texture-memory address capture occurs under tex_rd_en in BS_ISSUE or a
nearest-read issue cycle. Those state conditions are mutually exclusive.
The remaining path is therefore a conservative physical arc introduced by
packing mutually exclusive arithmetic into Agilex DSP structures, not a
single-cycle functional requirement. Ch439g adds a fail-closed SDC exception
from exactly the architectural 128 g_bilinear.tap[0:3][31:0] registers to
the existing u_texcache.tex_mem endpoint collection. The exception does not
cut any walker, affine-UV, perspective-UV, descriptor, or address register;
all real texture-address launches remain timed normally. The SDC halts the
compile if the tap population is not exactly 128 or the cache collection is
empty.
No functional RTL changed after the already-exact Ch439e simulations. The next owner GUI compile must show the Ch439g collection-count message, retain the four request quadrants and EMIF closure, and expose the true next design-clock family. Deployment remains forbidden unless every timing class is clean.