gqa(adr-0064/0065): flat-ops CompositeCmd (P1) + structural dispatch cost (ADR-0064 Rev2); promote ADR-0064

ADR-0065 P1: CompositeCmd -> flat ordered ops list (drop legacy op/a/b/out_addr fields); OpSpec.operands dict + out handle. Meaning-preserving (op_log byte-equal); pe_scheduler + op_log read the head op.

ADR-0064 Rev2: replace Rev1 per-op cost table with structural FIXED + logical_bytes*R formula. logical_bytes on every PeCommand; new common/pe_cost_model.py; cost centralized in TLContext._emit (load/recv_async charge explicitly); pe_cpu/kernel_runner wire the per-PE model + clock. D7: cap exceeded -> ValueError (no auto-segmentation). Remove Rev1 cpu_issue_cost.py + its tests. No goldens churn.

Promote ADR-0064 Rev2 Proposed->Accepted (docs/adr/ + docs/adr-ko/); amend D7 (error not segmentation) + record P1-before-P0 ordering in ADR-0064/0065 Migration notes (EN+KO).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-10 19:18:04 -07:00
parent 79ddb12b42
commit 47e2c78c66
18 changed files with 703 additions and 550 deletions
+4 -2
View File
@@ -56,12 +56,14 @@ def test_composite_epilogue_roundtrip():
("scale", Scope.OUTPUT_TILE),
]
# Single-op call (no epilogue) keeps the legacy code path: ops stays empty.
# Single-op call (no epilogue): flat-ops still emits one head op
# (ADR-0065 D1 — every composite carries a head op, no legacy empty path).
tl2 = TLContext()
tl2.composite(op="gemm", a=a, b=b, out_ptr=0x2000)
cmd2 = tl2._commands[-1]
assert isinstance(cmd2, CompositeCmd)
assert cmd2.ops == ()
assert len(cmd2.ops) == 1
assert cmd2.ops[0].kind == "gemm"
@pytest.mark.parametrize("bad,match", [