ba74bbd5aa
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>
78 lines
4.3 KiB
Python
78 lines
4.3 KiB
Python
#!/usr/bin/env python3
|
|
"""retroDE_ps2 — Ch357: verify the RASTER's emitted per-fragment Z (persp_z5) end-to-end.
|
|
|
|
Replays the captured raster fragment stream {epoch, x, y, persp_z, color} (from tb_top_psmct32_sh3_zsched -> zsched_frags.txt)
|
|
through the SAME clamp16 persistent-Z model the RTL ROP (gs_lpddr_zc_emit) implements, and compares the resulting per-pixel
|
|
OWNER + reject-vs-paint-order to the software oracle (gs_sh3_z_oracle emits sh3_zsched_zowner.mem / _reject.mem).
|
|
|
|
If persp_z5 is the authentic screen-linear Z (right value, right pixel), the replay reproduces the oracle: covered=21692,
|
|
reject=3971 for the primary [8634,12757,145742]. A wrong Z value or a pipeline-stage misalignment shows up as a reject/owner
|
|
mismatch — so this is the decisive check on the new gs_stub RTL, independent of the (separately unit-proven) ROP.
|
|
|
|
Usage: verify_persp_z.py [frags.txt] [--tag zsched] [--fbpxw 256]
|
|
"""
|
|
import sys, os
|
|
HERE=os.path.dirname(os.path.abspath(__file__)); ROOT=os.path.normpath(os.path.join(HERE,".."))
|
|
DATA=os.path.join(ROOT,"sim","data","top_psmct32_raster_demo")
|
|
|
|
def clamp16(z): z=int(z); return 0xFFFF if z>0xFFFF else (0 if z<0 else z)
|
|
|
|
def main(argv):
|
|
a=argv[1:]
|
|
frags = a[0] if a and not a[0].startswith("--") else os.path.join(ROOT,"sim","traces","rtl","zsched_frags.txt")
|
|
tag = a[a.index("--tag")+1] if "--tag" in a else "zsched"
|
|
if not os.path.exists(frags): sys.exit(f"[perspZ] no fragment capture at {frags} (run make tb_top_psmct32_sh3_zsched)")
|
|
|
|
# load the oracle owner map: [31]cov [30]reject [27:24]z_owner(+1) [23:8]zq16 [3:0]paint_owner(+1)
|
|
owner_fn=os.path.join(DATA,f"sh3_{tag}_zowner.mem")
|
|
if not os.path.exists(owner_fn): sys.exit(f"[perspZ] no oracle map {owner_fn} (run gs_sh3_z_oracle.py --draw-list ... --emit)")
|
|
orc=[int(l,16)&0xFFFFFFFF for l in open(owner_fn) if l.strip() and not l.startswith("//")]
|
|
NPX=len(orc)
|
|
# infer FB width: prefer param, else from the oracle geometry note isn't stored — require --fbpxw or default 256
|
|
FBPXW = int(a[a.index("--fbpxw")+1]) if "--fbpxw" in a else 256
|
|
|
|
# replay the captured fragments (in emit order == dump/paint order across epochs) through persistent clamp16 GEQUAL
|
|
zbuf=[-1]*NPX; z_owner=[-1]*NPX; paint_owner=[-1]*NPX; cov=[0]*NPX
|
|
nfr=0; oob=0
|
|
for ln in open(frags):
|
|
p=ln.split()
|
|
if len(p)<5: continue
|
|
ep=int(p[0]); x=int(p[1]); y=int(p[2]); z=int(p[3])
|
|
o=y*FBPXW+x
|
|
if o<0 or o>=NPX: oob+=1; continue
|
|
nfr+=1; cov[o]=1
|
|
zq=clamp16(z)
|
|
paint_owner[o]=ep
|
|
if zq>=zbuf[o]: zbuf[o]=zq; z_owner[o]=ep # GEQUAL, persistent across epochs, ZMSK=0
|
|
|
|
# compare to the oracle
|
|
covered=sum(cov); reject=sum(1 for o in range(NPX) if cov[o] and z_owner[o]!=paint_owner[o])
|
|
# oracle covered/reject
|
|
orc_cov=sum(1 for w in orc if w>>31); orc_rej=sum(1 for w in orc if (w>>30)&1)
|
|
# per-pixel owner agreement (where both cover)
|
|
owner_mismatch=0; both=0
|
|
for o in range(NPX):
|
|
if cov[o] and (orc[o]>>31):
|
|
both+=1
|
|
orc_owner=((orc[o]>>24)&0xF)-1
|
|
if z_owner[o]!=orc_owner: owner_mismatch+=1
|
|
|
|
print(f"[perspZ] replayed {nfr} captured fragments (oob={oob}); FBPXW={FBPXW}, NPX={NPX}")
|
|
print(f"[perspZ] REPLAY : covered={covered} reject-vs-paint={reject}")
|
|
print(f"[perspZ] ORACLE : covered={orc_cov} reject={orc_rej}")
|
|
agree = 100.0*(both-owner_mismatch)/max(both,1)
|
|
rej_ratio = reject/max(orc_rej,1)
|
|
print(f"[perspZ] per-pixel z-owner agreement (both-covered {both}): {agree:.2f}% ({owner_mismatch} mismatch)")
|
|
print(f"[perspZ] reject ratio replay/oracle = {rej_ratio:.3f} (1.0 = persp_z5 authentic; ~0 or >>1 = broken/misaligned)")
|
|
# tolerate RTL-vs-float edge/coverage + fixed-point-Z noise; catch a GROSS persp_z5 error (wrong stage/value).
|
|
ok = (agree >= 95.0) and (0.80 <= rej_ratio <= 1.20)
|
|
if ok:
|
|
print(f"[perspZ] PASS — the raster's persp_z5 reproduces the clamp16 oracle owner/reject within edge tolerance. "
|
|
f"persp_z5 is the authentic screen-linear Z, correctly aligned to the emit.")
|
|
return 0
|
|
print(f"[perspZ] FAIL — persp_z5 diverges from the oracle (wrong Z value or pipeline-stage misalignment). Numbers above.")
|
|
return 1
|
|
|
|
if __name__=="__main__":
|
|
raise SystemExit(main(sys.argv))
|