Ch443f timing: preload Z-RMW eviction awaddr at fill (kill cache_dirty->awaddr cone)
The Seed-3 fit of the Ch443f scanout hardening exposed one setup family in the EMIF (iopll_0_outclk0, 3.225 ns) domain: u_zc_emit|u_z|cache_dirty -> awaddr[*], WNS -0.062 / TNS -0.203, skew-dominated (-0.064 clock skew; the 5-level logic path itself would land ~+0.002 at zero skew). Not the Ch443f logic — the added EMIF-domain logic nudged this marginal Ch357-era control path negative. Fix (Codex-directed, minimal): the normal-eviction AW address is a pure function of the cache line's beat, known when the line is installed. Preload it in S_FILL_C alongside cache_beat<=pf_beat (awaddr <= ZBASE + (pf_beat<<5)), and drop the two later awaddr assignments gated by cache_dirty (the scene_flush branch and the dirty cache-miss branch) — those now only assert awvalid on the already-prepared address. Clear-path awaddr assignments unchanged. No new FSM state, pipeline stage, buffer, or protocol change. Safe: a freshly filled line cannot be dirty before S_FILL_C installs it; the address is stable across hits and scene flushes; after a dirty eviction the next fill re-runs S_FILL_C; clear invalidates the cache so the first subsequent fill overwrites the clear address before any normal eviction. This removes the control cone rather than placing around it, so closure is seed-robust. Regressions green: z_rmw/zc_emit/axi_master_elastic/zbuffer/z_flush_writer/ tile_zflush, full Ch443f scanout set, sh3_zint (Z 0/53760, COLOR 0/11092), sh3_zrop (errors=0), and f52 byte-identity (Z 0/307200, COLOR 0/245760, drops=0). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -256,7 +256,7 @@ module gs_lpddr_z_rmw #(
|
||||
// scene-end flush (ordered after all fragments): push the dirty line, keep it cached (persist across
|
||||
// epochs). Waits for every pipeline stage to drain so nothing is stranded.
|
||||
if (scene_flush && !d_valid && !rmw_valid && !cmp_valid && cache_valid && cache_dirty) begin
|
||||
awaddr<=ZBASE + (cache_beat<<5); awvalid<=1'b1;
|
||||
awvalid<=1'b1; // Ch443f — awaddr already prepared at S_FILL_C install
|
||||
wdata<=cache_data; wvalid<=1'b1; wlast<=1'b1; st<=S_SFLUSH_AW;
|
||||
end
|
||||
// STAGE 2 — barrel READ of the target lane into the RMW register (hit), or promote+fill (miss). Fires
|
||||
@@ -272,7 +272,7 @@ module gs_lpddr_z_rmw #(
|
||||
// MISS: promote the decoded fragment to pf_*, backpressure, flush-if-dirty then fill
|
||||
pf_x<=d_x; pf_y<=d_y; pf_zq<=d_zq; pf_zmsk<=d_zmsk; pf_ztst<=d_ztst; pf_beat<=d_beat; pf_lane<=d_lane;
|
||||
if (cache_valid && cache_dirty) begin
|
||||
awaddr<=ZBASE + (cache_beat<<5); awvalid<=1'b1;
|
||||
awvalid<=1'b1; // Ch443f — awaddr already prepared at S_FILL_C install
|
||||
wdata<=cache_data; wvalid<=1'b1; wlast<=1'b1; st<=S_FLUSH_AW;
|
||||
end else begin
|
||||
araddr<=ZBASE + (d_beat<<5); arvalid<=1'b1; st<=S_FILL_AR;
|
||||
@@ -318,6 +318,12 @@ module gs_lpddr_z_rmw #(
|
||||
// RMW stage (barrel READ of the target lane off the just-read beat). Stage 3 does the GEQUAL + 16-way
|
||||
// lane write next cycle in S_RUN (a guaranteed hit). Same result as the old single-cycle fill, staged.
|
||||
cache_data<=z_rd_q; cache_beat<=pf_beat; cache_valid<=1'b1; cache_dirty<=1'b0;
|
||||
// Ch443f — PRELOAD the line's normal-eviction AW address at install. The address
|
||||
// is a pure function of this line's beat (== cache_beat after this cycle) and is
|
||||
// stable across every hit/flush until the next fill re-installs it. Preparing it
|
||||
// here removes the 5-level cache_dirty -> awaddr control cone that was the EMIF
|
||||
// setup leader; the eviction branches below now only assert awvalid.
|
||||
awaddr<=ZBASE + (pf_beat<<5);
|
||||
rmw_valid<=1'b1; rmw_dz<=z_rd_q[pf_lane*16 +: 16];
|
||||
rmw_lane<=pf_lane; rmw_zq<=pf_zq; rmw_zmsk<=pf_zmsk; rmw_ztst<=pf_ztst; rmw_x<=pf_x; rmw_y<=pf_y;
|
||||
st<=S_RUN;
|
||||
|
||||
Reference in New Issue
Block a user