OR-1 dataflow CPU sketch

docs: update CLAUDE.md for frame matching lanes contracts

Orual 3bf3e391 f77e1cd6

+13
+13
CLAUDE.md
··· 106 106 - `tests/test_migration_cleanup.py` — Verifies removed types (SysToken, CfgOp, etc.) are absent from codebase 107 107 - `tests/test_pe_events.py` — PE event emission tests (TokenReceived, Matched, Executed, Emitted, IRAMWritten, FrameAllocated, FrameFreed, FrameSlotWritten, TokenRejected) 108 108 - `tests/test_pe_frames.py` — Frame-based PE matching, routing, and lifecycle tests 109 + - `tests/test_pe_lanes.py` — Lane-based matching tests (ALLOC_SHARED, FREE_LANE, smart FREE, lane exhaustion, pipelining) 109 110 - `tests/test_sm_events.py` — SM event emission tests (CellWritten, DeferredRead, DeferredSatisfied, ResultSent) 110 111 - `tests/test_cycle_timing.py` — Cycle-accurate timing verification tests 111 112 - `tests/test_network_events.py` — Network-level event propagation tests ··· 187 188 - `presence: list[list[list[bool]]]` -- 3D array [frame_id][match_slot][lane] for dyadic operand waiting state 188 189 - `port_store: list[list[list[Optional[Port]]]]` -- 3D array [frame_id][match_slot][lane] for operand port metadata 189 190 - `lane_count: int` -- number of matching lanes per frame 191 + - `lane_free: dict[int, set[int]]` -- per-frame set of available lane IDs (created on ALLOC, deleted on full FREE) 190 192 - `free_frames: list[int]` -- pool of unallocated frame IDs 191 193 - `iram: dict[int, Instruction]` -- instruction memory indexed by offset 192 194 ··· 216 218 217 219 **Output logging:** 218 220 - `PE.output_log: list` records every token emitted (for testing and tracing) 221 + 222 + **Frame Control Operations** (`_handle_frame_control`): 223 + - `ALLOC` -- allocates a fresh frame from free_frames, assigns lane 0, initializes lane_free with remaining lanes 224 + - `FREE` -- smart free: removes act_id from tag_store, clears lane match state. If other activations share the frame, returns lane to lane_free (frame_freed=False). If last lane, returns frame to free_frames and clears frame slots (frame_freed=True) 225 + - `ALLOC_SHARED` -- shared allocation: looks up parent act_id (from payload) in tag_store, finds parent's frame_id, assigns next free lane from lane_free. Rejects if parent not found or no free lanes 226 + - `FREE_LANE` -- lane-only free: removes act_id, clears lane match state, returns lane to lane_free. Never returns frame to free_frames (frame_freed always False) 227 + 228 + **ALLOC_REMOTE** (RoutingOp in `_run` pipeline): 229 + - Reads fref+0 (target PE), fref+1 (target act_id), fref+2 (parent act_id) from frame constants 230 + - If fref+2 is non-zero: emits FrameControlToken with ALLOC_SHARED op and parent act_id as payload 231 + - If fref+2 is zero: emits FrameControlToken with ALLOC op (fresh frame allocation) 219 232 220 233 **PELocalWriteToken handling:** 221 234 - Writes data to frame slot at specified region/slot within the act_id's frame (1 cycle)