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>
105 lines
3.1 KiB
Python
105 lines
3.1 KiB
Python
#!/usr/bin/env python3
|
|
"""Compact ZSCHED trace-vs-model summary.
|
|
|
|
Use after tb_top_psmct32_sh3_zsched regenerates sim/traces/rtl/zsched_*.txt.
|
|
It compares the current feeder-derived fixed-point model against the RTL issue
|
|
and fragment traces, split by epoch.
|
|
"""
|
|
import contextlib
|
|
import io
|
|
import os
|
|
import sys
|
|
|
|
HERE = os.path.dirname(os.path.abspath(__file__))
|
|
ROOT = os.path.normpath(os.path.join(HERE, ".."))
|
|
sys.path.insert(0, HERE)
|
|
|
|
with contextlib.redirect_stdout(io.StringIO()):
|
|
import diagnose_zsched_persp as D
|
|
|
|
|
|
def load_frags(path):
|
|
out = []
|
|
with open(path) as f:
|
|
for ln in f:
|
|
p = ln.split()
|
|
if len(p) >= 5:
|
|
out.append((int(p[0]), int(p[1]), int(p[2]), int(p[3]), int(p[4], 16) & 0xFFFFFF))
|
|
return out
|
|
|
|
|
|
def load_issue(path):
|
|
out = []
|
|
with open(path) as f:
|
|
for ln in f:
|
|
p = ln.split()
|
|
if len(p) >= 7:
|
|
out.append((int(p[0]), int(p[1]), int(p[2]), int(p[3]), int(p[4]), int(p[5]), int(p[6])))
|
|
return out
|
|
|
|
|
|
def pct(ok, n):
|
|
return 100.0 * ok / n if n else 0.0
|
|
|
|
|
|
def main(argv):
|
|
trace_dir = os.path.join(ROOT, "sim", "traces", "rtl")
|
|
frag_path = argv[1] if len(argv) > 1 else os.path.join(trace_dir, "zsched_frags.txt")
|
|
issue_path = argv[2] if len(argv) > 2 else os.path.join(trace_dir, "zsched_issue.txt")
|
|
|
|
with contextlib.redirect_stdout(io.StringIO()):
|
|
_draw_idxs, _tris, _fb, _owner, _emitted, _accepted, model = D.render("zsched")
|
|
frags = load_frags(frag_path)
|
|
issue = load_issue(issue_path)
|
|
n = min(len(model), len(frags), len(issue))
|
|
|
|
by_ep = {}
|
|
coord_miss = z_miss = 0
|
|
for i in range(n):
|
|
me = model[i]
|
|
hwf = frags[i]
|
|
hwi = issue[i]
|
|
ep = hwf[0]
|
|
st = by_ep.setdefault(ep, {
|
|
"n": 0, "color": 0, "u": 0, "v": 0, "uv": 0,
|
|
"u_ge512": 0, "v_ge512": 0,
|
|
})
|
|
st["n"] += 1
|
|
if me[:3] != hwf[:3]:
|
|
coord_miss += 1
|
|
if abs(me[3] - hwf[3]) > 256:
|
|
z_miss += 1
|
|
if (me[4] & 0xFFFFFF) != hwf[4]:
|
|
st["color"] += 1
|
|
if me[5] != hwi[4]:
|
|
st["u"] += 1
|
|
if me[6] != hwi[5]:
|
|
st["v"] += 1
|
|
if me[5] != hwi[4] or me[6] != hwi[5]:
|
|
st["uv"] += 1
|
|
if hwi[4] >= 512:
|
|
st["u_ge512"] += 1
|
|
if hwi[5] >= 512:
|
|
st["v_ge512"] += 1
|
|
|
|
print(f"[uv] model={len(model)} frags={len(frags)} issue={len(issue)} compared={n} coord_miss={coord_miss} z_gt256={z_miss}")
|
|
for ep in sorted(by_ep):
|
|
st = by_ep[ep]
|
|
n_ep = st["n"]
|
|
u_ok = n_ep - st["u"]
|
|
v_ok = n_ep - st["v"]
|
|
uv_ok = n_ep - st["uv"]
|
|
c_ok = n_ep - st["color"]
|
|
print(
|
|
f"[uv] e{ep}: n={n_ep} "
|
|
f"color_ok={c_ok}/{n_ep} ({pct(c_ok,n_ep):.2f}%) "
|
|
f"u_ok={u_ok}/{n_ep} ({pct(u_ok,n_ep):.2f}%) "
|
|
f"v_ok={v_ok}/{n_ep} ({pct(v_ok,n_ep):.2f}%) "
|
|
f"uv_ok={uv_ok}/{n_ep} ({pct(uv_ok,n_ep):.2f}%) "
|
|
f"rtl_u_ge512={st['u_ge512']} rtl_v_ge512={st['v_ge512']}"
|
|
)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
raise SystemExit(main(sys.argv))
|