OR-1 dataflow CPU sketch

feat: update PESnapshot for 3D match storage and match_data field

Update snapshot capture to handle new 3D storage arrays:
- PESnapshot.presence now 3D: tuple[tuple[tuple[bool, ...], ...], ...]
- PESnapshot.port_store now 3D: tuple[tuple[tuple[Port | None, ...], ...], ...]
- Add PESnapshot.match_data 3D field: tuple[tuple[tuple[int | None, ...], ...], ...]
- Add PESnapshot.lane_count field to track lanes per PE
- Update capture() function to iterate through 3D arrays correctly

Verification:
- test_snapshot.py: 14 tests pass

Orual eeeaf1ac 6405d135

+21 -4
+21 -4
monitor/snapshot.py
··· 23 23 iram: dict[int, Instruction] 24 24 frames: tuple[tuple[FrameSlotValue, ...], ...] 25 25 tag_store: dict[int, tuple[int, int]] 26 - presence: tuple[tuple[bool, ...], ...] 27 - port_store: tuple[tuple[Port | None, ...], ...] 26 + presence: tuple[tuple[tuple[bool, ...], ...], ...] 27 + port_store: tuple[tuple[tuple[Port | None, ...], ...], ...] 28 + match_data: tuple[tuple[tuple[int | None, ...], ...], ...] 28 29 free_frames: tuple[int, ...] 30 + lane_count: int 29 31 input_queue: tuple[Token, ...] 30 32 output_log: tuple[Token, ...] 31 33 ··· 80 82 ) 81 83 tag_store = dict(pe.tag_store) 82 84 presence = tuple( 83 - tuple(p for p in frame_presence) 85 + tuple( 86 + tuple(lane_val for lane_val in offset_lanes) 87 + for offset_lanes in frame_presence 88 + ) 84 89 for frame_presence in pe.presence 85 90 ) 86 91 port_store = tuple( 87 - tuple(p for p in frame_ports) 92 + tuple( 93 + tuple(lane_val for lane_val in offset_lanes) 94 + for offset_lanes in frame_ports 95 + ) 88 96 for frame_ports in pe.port_store 89 97 ) 98 + match_data = tuple( 99 + tuple( 100 + tuple(lane_val for lane_val in offset_lanes) 101 + for offset_lanes in frame_match 102 + ) 103 + for frame_match in pe.match_data 104 + ) 90 105 free_frames = tuple(pe.free_frames) 91 106 92 107 pes[pe_id] = PESnapshot( ··· 96 111 tag_store=tag_store, 97 112 presence=presence, 98 113 port_store=port_store, 114 + match_data=match_data, 99 115 free_frames=free_frames, 116 + lane_count=pe.lane_count, 100 117 input_queue=tuple(pe.input_store.items), 101 118 output_log=tuple(pe.output_log), 102 119 )