gqa(adr-0065): D8 — composite returns output handle + output-space DMA
tl.composite now returns the output TensorHandle (not a CompletionHandle) so its result chains like tl.dot's; the handle carries the completion in a CompositeFuture pending so downstream ops and tl.wait auto-await it. out is a handle: out=tl.ref(addr,shape) (HBM, DMA_WRITE inside the composite) or an in-place TCM handle (STORE only); omitted -> TLContext auto-allocates a TCM scratch. out_ptr kept as HBM shorthand (= out=tl.ref(out_ptr, shape)) to avoid churning ~30 existing call sites. tl.ref now returns space=hbm (it references HBM data; operand-input DMA stays pinned-based per D4 so input streaming is unchanged). tiling: the tile loop's DMA_WRITE is gated on out.space==hbm (out analog of the operand pinned rule) — a TCM output stays on-chip (chainable) and its high-bit scratch address no longer hits the DMA PA decoder. Fixes the opt2 data-mode crash: the recipe accumulator O is TCM -> no DMA_WRITE -> opt2 now RUNS end-to-end in data mode (enable_data=True). Numeric parity of the recipe MATH ops is the next step. Suite 812 pass / 3 pre-existing fail; existing composite benches use out_ptr->hbm->DMA_WRITE unchanged (byte-equal). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -175,7 +175,10 @@ def test_tl_composite_nonblocking():
|
||||
a = tl.load(0x1000, shape=(32, 64), dtype="f16")
|
||||
b = tl.load(0x2000, shape=(64, 32), dtype="f16")
|
||||
h = tl.composite(op="gemm", a=a, b=b, out_ptr=0x3000)
|
||||
assert isinstance(h, CompletionHandle)
|
||||
# ADR-0065 D8: composite returns the output TensorHandle (chainable),
|
||||
# carrying the completion in its `pending` field.
|
||||
assert isinstance(h, TensorHandle)
|
||||
assert h.addr == 0x3000 and h.space == "hbm"
|
||||
comp_cmds = [c for c in tl.commands if isinstance(c, CompositeCmd)]
|
||||
assert len(comp_cmds) == 1
|
||||
# Flat-ops shape (ADR-0065 D1): head op carries kind + write-back handle.
|
||||
@@ -195,7 +198,8 @@ def test_tl_wait_specific():
|
||||
tl.wait(h)
|
||||
wait_cmds = [c for c in tl.commands if isinstance(c, WaitCmd)]
|
||||
assert len(wait_cmds) == 1
|
||||
assert wait_cmds[0].handle == h
|
||||
# ADR-0065 D8: h is the output handle; tl.wait targets its completion.
|
||||
assert wait_cmds[0].handle == h.pending.completion
|
||||
|
||||
|
||||
# ── 9. tl.wait() → WaitCmd(handle=None) ──────────────────────────
|
||||
|
||||
Reference in New Issue
Block a user