#!/usr/bin/env python3 """Rank one-triangle runtime-scheduler epochs by 640x480 pixel coverage. Usage: rank_sched_triangle_coverage.py TAG [--top N] The generated feeder format stores an eight-word header followed by three {RGBAQ, ST, XYZ2} vertex triplets. This is a capacity preflight: it uses the same center-sample inside test as the fixture reference and reports epochs whose unthrottled fragment burst may exceed the production request FIFO. """ import os import sys ROOT = os.path.normpath(os.path.join(os.path.dirname(__file__), "..")) DATA = os.path.join(ROOT, "sim", "data", "top_psmct32_raster_demo") def edge(ax, ay, bx, by, px, py): return (px - ax) * (by - ay) - (py - ay) * (bx - ax) def coverage(vertices, width=640, height=480): (x0, y0), (x1, y1), (x2, y2) = vertices area = edge(x0, y0, x1, y1, x2, y2) if not area: return 0 inv = 1.0 / area minx = max(0, int(min(x0, x1, x2))) maxx = min(width - 1, int(max(x0, x1, x2)) + 1) miny = max(0, int(min(y0, y1, y2))) maxy = min(height - 1, int(max(y0, y1, y2)) + 1) count = 0 for py in range(miny, maxy + 1): cy = py + 0.5 for px in range(minx, maxx + 1): cx = px + 0.5 w0 = edge(x1, y1, x2, y2, cx, cy) * inv w1 = edge(x2, y2, x0, y0, cx, cy) * inv w2 = 1.0 - w0 - w1 if w0 >= -0.001 and w1 >= -0.001 and w2 >= -0.001: count += 1 return count def main(argv): if len(argv) < 2: print(__doc__.strip()) return 2 tag = argv[1] top = int(argv[argv.index("--top") + 1]) if "--top" in argv else 12 rows = [] table = os.path.join(DATA, f"sh3_{tag}_epochs.txt") with open(table) as source: for line in source: fields = line.split() if not fields or not fields[0].isdigit(): continue epoch, list_name, ntris = int(fields[0]), fields[8], int(fields[10]) words = [] with open(os.path.join(DATA, list_name)) as feeder: for text in feeder: text = text.strip() if text and not text.startswith("//"): words.append(int(text, 16)) total = 0 peak = 0 peak_vertices = None for ti in range(ntris): base = 8 + ti * 9 xyz = [words[base + 2], words[base + 5], words[base + 8]] vertices = [((word >> 4) & 0xFFF, (word >> 20) & 0xFFF) for word in xyz] count = coverage(vertices) total += count if count > peak: peak = count peak_vertices = vertices rows.append((total, epoch, ntris, peak, peak_vertices)) rows.sort(reverse=True) print(f"[coverage] tag={tag} epochs={len(rows)}") for count, epoch, ntris, peak, vertices in rows[:top]: print(f"[coverage] epoch={epoch:4d} pixels={count:6d} tris={ntris:3d} peak_tri={peak:6d} vertices={vertices}") return 0 if __name__ == "__main__": raise SystemExit(main(sys.argv))