"""Phase 1 spec tests for ADR-0065 P1 — flat-ops ``CompositeCmd`` refactor. P1 restructures ``CompositeCmd`` from the legacy ``(op, a, b, out_addr, out_nbytes, math_op, ops)`` shape into a flat ordered op list ``(completion, ops, rw_handles, data_op)`` (ADR-0065 D1/D2). The user-facing ``tl.composite(op=..., a, b, epilogue=[...])`` API is preserved (D6.4) and lowers internally to the flat shape. This is a *meaning-preserving* refactor: every existing bench's op_log must stay byte-equal (the existing integration suite is the regression net). The tests here pin the new lowering *shape* only. Phase 1 (this commit): tests only. All FAIL until the P2 production refactor: - current ``CompositeCmd`` requires ``op/a/b/out_addr`` (no flat-only ctor), - current ``OpSpec.operands`` is a tuple and there is no ``out`` field. """ from __future__ import annotations from kernbench.common.pe_commands import CompositeCmd, OpSpec, Scope, TensorHandle from kernbench.triton_emu.tl_context import TLContext _LEGACY_FIELDS = ("op", "a", "b", "out_addr", "out_nbytes", "math_op") def _tl() -> TLContext: return TLContext(pe_id=0, num_programs=1, dispatch_cycles=0) def _composites(tl: TLContext) -> list[CompositeCmd]: return [c for c in tl.commands if isinstance(c, CompositeCmd)] # ── plain GEMM composite (no epilogue) ─────────────────────────────── def test_plain_gemm_composite_lowers_to_single_head_op(): """A composite with no epilogue still emits exactly one flat head op.""" tl = _tl() a = tl.ref(0x1000, shape=(8, 16), dtype="f16") b = tl.ref(0x2000, shape=(16, 8), dtype="f16") tl.composite("gemm", a, b, out_ptr=0x3000) comps = _composites(tl) assert len(comps) == 1, f"expected 1 composite; got {len(comps)}" cmd = comps[0] assert len(cmd.ops) == 1, f"plain gemm must have 1 head op; got {len(cmd.ops)}" head = cmd.ops[0] assert head.kind == "gemm" assert head.operands == {"a": a, "b": b}, head.operands assert head.out is not None and head.out.addr == 0x3000, head.out assert cmd.rw_handles == () def test_composite_has_no_legacy_fields(): """Legacy ``op/a/b/out_addr/out_nbytes/math_op`` are gone from the cmd.""" tl = _tl() a = tl.ref(0x1000, shape=(8, 16), dtype="f16") b = tl.ref(0x2000, shape=(16, 8), dtype="f16") tl.composite("gemm", a, b, out_ptr=0x3000) cmd = _composites(tl)[0] for f in _LEGACY_FIELDS: assert not hasattr(cmd, f), f"legacy field {f!r} must be removed" # ── GEMM + epilogue ────────────────────────────────────────────────── def test_gemm_composite_with_epilogue_lowers_to_flat_ops(): """``epilogue=[relu, bias]`` lowers to flat ops after the head, with the epilogue operand migrated from positional tuple to a named dict.""" tl = _tl() a = tl.ref(0x1000, shape=(8, 16), dtype="f16") b = tl.ref(0x2000, shape=(16, 8), dtype="f16") bias = tl.ref(0x4000, shape=(8, 8), dtype="f16") tl.composite( "gemm", a, b, out_ptr=0x3000, epilogue=[{"op": "relu"}, {"op": "bias", "bias": bias}], ) cmd = _composites(tl)[0] assert [o.kind for o in cmd.ops] == ["gemm", "relu", "bias"] assert cmd.ops[0].scope == Scope.OUTPUT_TILE # head scope preserved assert cmd.ops[1].kind == "relu" assert cmd.ops[1].scope == Scope.OUTPUT_TILE # bias handle migrated to a named dict keyed by the EPILOGUE_OPS field. assert cmd.ops[2].operands == {"bias": bias}, cmd.ops[2].operands # ── MATH composite ─────────────────────────────────────────────────── def test_math_composite_lowers_to_flat_ops(): """``op="math", math_op="exp"`` lowers to a single head op carrying the math op kind in ``extra`` and its input as a named operand.""" tl = _tl() a = tl.ref(0x1000, shape=(8, 16), dtype="f16") tl.composite("math", a, math_op="exp", out_ptr=0x3000) cmd = _composites(tl)[0] assert len(cmd.ops) == 1 head = cmd.ops[0] assert head.kind == "math" assert head.extra.get("math_op") == "exp", head.extra assert head.operands == {"a": a}, head.operands assert head.out is not None and head.out.addr == 0x3000 # ── dataclass shape (unit) ─────────────────────────────────────────── def test_opspec_accepts_dict_operands_and_out_handle(): h = TensorHandle(id="t1", addr=0x10, shape=(4, 4), dtype="f16", nbytes=32) op = OpSpec(kind="gemm", scope=Scope.OUTPUT_TILE, operands={"a": h}, out=h) assert op.operands == {"a": h} assert op.out is h def test_compositecmd_flat_ctor_and_rw_handles_default(): from kernbench.common.pe_commands import CompletionHandle h = TensorHandle(id="t1", addr=0x10, shape=(4, 4), dtype="f16", nbytes=32) head = OpSpec(kind="math", scope=Scope.KERNEL, operands={"a": h}, out=h) cmd = CompositeCmd(completion=CompletionHandle(id="c1"), ops=(head,)) assert cmd.ops == (head,) assert cmd.rw_handles == () assert cmd.data_op is True