"""Tests for tl.send / tl.recv API (ADR-0023 D4 + D9.5).""" from __future__ import annotations from typing import Any import simpy from greenlet import greenlet from kernbench.common.ipcq_types import ( IpcqRecvCmd, IpcqRequest, IpcqSendCmd, ) from kernbench.triton_emu.tl_context import TLContext # ── Command-list mode (no runner) ──────────────────────────────────── def test_tl_send_command_list_mode(): tl = TLContext(pe_id=0, num_programs=4, dispatch_cycles=0) tl.send(dir="E", src_addr=0x500, nbytes=64, shape=(8,), dtype="f16") cmds = tl.commands sends = [c for c in cmds if isinstance(c, IpcqSendCmd)] assert len(sends) == 1 assert sends[0].direction == "E" assert sends[0].src_addr == 0x500 assert sends[0].nbytes == 64 def test_tl_recv_command_list_mode(): tl = TLContext(pe_id=0, num_programs=4, dispatch_cycles=0) handle = tl.recv(dir="W", shape=(8,), dtype="f16") cmds = tl.commands recvs = [c for c in cmds if isinstance(c, IpcqRecvCmd)] assert len(recvs) == 1 assert recvs[0].direction == "W" # In command-list mode (no runner), tl.recv returns a placeholder # TensorHandle (no actual data movement happens until SimPy) assert handle.shape == (8,) assert handle.dtype == "f16" def test_tl_recv_round_robin_no_dir(): tl = TLContext(pe_id=0, num_programs=4, dispatch_cycles=0) tl.recv(shape=(8,), dtype="f16") cmds = tl.commands recvs = [c for c in cmds if isinstance(c, IpcqRecvCmd)] assert recvs[0].direction is None # ── Runner mode (greenlet) ────────────────────────────────────────── class _StubRunner: """Minimal runner that auto-responds to IpcqSendCmd / IpcqRecvCmd.""" def __init__(self) -> None: self.received: list[Any] = [] def switch_to_simpy(self, cmd: Any) -> Any: self.received.append(cmd) if isinstance(cmd, IpcqSendCmd): return None if isinstance(cmd, IpcqRecvCmd): # Return a fake slot dict return { "data": None, "src_space": "tcm", "src_addr": 0xABCD, "direction": cmd.direction or "E", "dtype": cmd.dtype, "shape": cmd.shape, "nbytes": 16, } return None def test_tl_send_runner_mode(): runner = _StubRunner() tl = TLContext(pe_id=0, num_programs=4, dispatch_cycles=0, runner=runner) tl.send(dir="E", src_addr=0x500, nbytes=64, shape=(8,), dtype="f16") assert len(runner.received) == 1 assert isinstance(runner.received[0], IpcqSendCmd) def test_tl_recv_runner_mode_returns_handle_with_slot_addr(): runner = _StubRunner() tl = TLContext(pe_id=0, num_programs=4, dispatch_cycles=0, runner=runner) h = tl.recv(dir="W", shape=(8,), dtype="f16") assert isinstance(runner.received[0], IpcqRecvCmd) # The returned TensorHandle's addr should reflect the slot assert h.addr == 0xABCD assert h.shape == (8,) assert h.dtype == "f16"