OR-1 dataflow CPU sketch
at main 288 lines 9.6 kB view raw
1""" 2Tests for network routing with frame-based PE. 3 4Verifies pe-frame-redesign.AC1.5: 5- Network routing uses isinstance(token, PEToken) for all PE-bound tokens 6- CMToken, PELocalWriteToken, FrameControlToken all route to target PE 7- SMToken routes to target SM 8- build_topology() constructs PE with frame_count, frame_slots, matchable_offsets 9- build_topology() loads initial_frames and initial_tag_store 10""" 11 12import simpy 13import pytest 14 15from emu import build_topology, PEConfig, SMConfig 16from emu.types import PEConfig as PECfg 17from tokens import ( 18 CMToken, DyadToken, MonadToken, PELocalWriteToken, FrameControlToken, 19 SMToken, 20) 21from cm_inst import MemOp, Port, FrameOp 22 23 24class TestPETokenRouting: 25 """AC1.5: All PE-bound tokens (CMToken, PELocalWriteToken, FrameControlToken) route to target PE.""" 26 27 def test_cmtoken_routes_to_target_pe(self): 28 """CMToken (as DyadToken subclass) routes to target PE.""" 29 env = simpy.Environment() 30 pe_configs = [ 31 PECfg(pe_id=0), 32 PECfg(pe_id=1), 33 ] 34 sm_configs = [SMConfig(sm_id=0)] 35 system = build_topology(env, pe_configs, sm_configs) 36 37 # Inject DyadToken to PE 1 38 token = DyadToken( 39 target=1, 40 offset=0, 41 act_id=0, 42 data=42, 43 port=Port.L, 44 ) 45 system.inject(token) 46 47 # Verify token arrived at PE 1's input store 48 assert len(system.pes[1].input_store.items) > 0 49 assert system.pes[1].input_store.items[0] == token 50 51 def test_pelocal_write_token_routes_to_target_pe(self): 52 """PELocalWriteToken routes to target PE.""" 53 env = simpy.Environment() 54 pe_configs = [ 55 PECfg(pe_id=0), 56 PECfg(pe_id=1), 57 ] 58 sm_configs = [SMConfig(sm_id=0)] 59 system = build_topology(env, pe_configs, sm_configs) 60 61 # Inject PELocalWriteToken to PE 1 62 token = PELocalWriteToken( 63 target=1, 64 act_id=0, 65 region=0, 66 slot=10, 67 data=99, 68 is_dest=False, 69 ) 70 system.inject(token) 71 72 # Verify token arrived at PE 1's input store 73 assert len(system.pes[1].input_store.items) > 0 74 assert system.pes[1].input_store.items[0] == token 75 76 def test_frame_control_token_routes_to_target_pe(self): 77 """FrameControlToken routes to target PE.""" 78 env = simpy.Environment() 79 pe_configs = [ 80 PECfg(pe_id=0), 81 PECfg(pe_id=1), 82 ] 83 sm_configs = [SMConfig(sm_id=0)] 84 system = build_topology(env, pe_configs, sm_configs) 85 86 # Inject FrameControlToken to PE 1 87 token = FrameControlToken( 88 target=1, 89 act_id=0, 90 op=FrameOp.ALLOC, 91 payload=0, 92 ) 93 system.inject(token) 94 95 # Verify token arrived at PE 1's input store 96 assert len(system.pes[1].input_store.items) > 0 97 assert system.pes[1].input_store.items[0] == token 98 99 def test_smtoken_routes_to_target_sm(self): 100 """SMToken routes to target SM, not PE.""" 101 env = simpy.Environment() 102 pe_configs = [PECfg(pe_id=0)] 103 sm_configs = [ 104 SMConfig(sm_id=0), 105 SMConfig(sm_id=1), 106 ] 107 system = build_topology(env, pe_configs, sm_configs) 108 109 # Inject SMToken to SM 1 110 token = SMToken( 111 target=1, 112 addr=100, 113 op=MemOp.WRITE, 114 flags=None, 115 data=42, 116 ret=None, 117 ) 118 system.inject(token) 119 120 # Verify token arrived at SM 1's input store 121 assert len(system.sms[1].input_store.items) > 0 122 assert system.sms[1].input_store.items[0] == token 123 # And NOT at PE 0 124 assert len(system.pes[0].input_store.items) == 0 125 126 127class TestBuildTopologyFrameConfig: 128 """AC1.5: build_topology passes frame config fields to PE constructor.""" 129 130 def test_frame_config_params_passed(self): 131 """build_topology passes frame_count, frame_slots, matchable_offsets.""" 132 env = simpy.Environment() 133 pe_configs = [ 134 PECfg( 135 pe_id=0, 136 frame_count=16, 137 frame_slots=128, 138 matchable_offsets=16, 139 ), 140 ] 141 sm_configs = [SMConfig(sm_id=0)] 142 system = build_topology(env, pe_configs, sm_configs) 143 144 pe = system.pes[0] 145 assert pe.frame_count == 16 146 assert pe.frame_slots == 128 147 assert pe.matchable_offsets == 16 148 149 def test_loads_initial_frames(self): 150 """build_topology loads initial_frames into PE.""" 151 env = simpy.Environment() 152 initial_frames = { 153 0: [1, 2, 3, 4, 5], 154 1: [10, 20, 30, 40, 50], 155 } 156 pe_configs = [ 157 PECfg( 158 pe_id=0, 159 frame_count=8, 160 frame_slots=64, 161 initial_frames=initial_frames, 162 ), 163 ] 164 sm_configs = [SMConfig(sm_id=0)] 165 system = build_topology(env, pe_configs, sm_configs) 166 167 pe = system.pes[0] 168 # Frames are initialized with slots filled from the list 169 assert pe.frames[0][:5] == [1, 2, 3, 4, 5] 170 assert pe.frames[1][:5] == [10, 20, 30, 40, 50] 171 172 def test_loads_initial_tag_store(self): 173 """build_topology loads initial_tag_store into PE and removes frames from free_frames.""" 174 env = simpy.Environment() 175 initial_tag_store = { 176 0: (2, 0), # act_id 0 → frame 2, lane 0 177 1: (3, 0), # act_id 1 → frame 3, lane 0 178 } 179 pe_configs = [ 180 PECfg( 181 pe_id=0, 182 frame_count=8, 183 initial_tag_store=initial_tag_store, 184 ), 185 ] 186 sm_configs = [SMConfig(sm_id=0)] 187 system = build_topology(env, pe_configs, sm_configs) 188 189 pe = system.pes[0] 190 assert pe.tag_store[0] == (2, 0) 191 assert pe.tag_store[1] == (3, 0) 192 # Frames 2 and 3 should be removed from free_frames 193 assert 2 not in pe.free_frames 194 assert 3 not in pe.free_frames 195 # Other frames should still be in free_frames 196 assert 0 in pe.free_frames 197 assert 1 in pe.free_frames 198 199 def test_initial_frames_and_tag_store_together(self): 200 """build_topology correctly initializes both frames and tag_store.""" 201 env = simpy.Environment() 202 initial_frames = { 203 0: [1, 2, 3], 204 1: [4, 5, 6], 205 2: [7, 8, 9], 206 } 207 initial_tag_store = { 208 0: (0, 0), # act_id 0 uses frame 0, lane 0 209 1: (1, 0), # act_id 1 uses frame 1, lane 0 210 } 211 pe_configs = [ 212 PECfg( 213 pe_id=0, 214 frame_count=4, 215 initial_frames=initial_frames, 216 initial_tag_store=initial_tag_store, 217 ), 218 ] 219 sm_configs = [SMConfig(sm_id=0)] 220 system = build_topology(env, pe_configs, sm_configs) 221 222 pe = system.pes[0] 223 # Verify frames loaded (first N slots should match) 224 assert pe.frames[0][:3] == [1, 2, 3] 225 assert pe.frames[1][:3] == [4, 5, 6] 226 assert pe.frames[2][:3] == [7, 8, 9] 227 # Verify tag_store loaded 228 assert pe.tag_store[0] == (0, 0) 229 assert pe.tag_store[1] == (1, 0) 230 # Verify free_frames reflects allocations 231 assert 0 not in pe.free_frames 232 assert 1 not in pe.free_frames 233 assert 2 in pe.free_frames 234 assert 3 in pe.free_frames 235 236 237class TestMultiplePEs: 238 """Test network routing with multiple PEs and SMs.""" 239 240 def test_multiple_pe_network(self): 241 """Multiple PEs route tokens correctly.""" 242 env = simpy.Environment() 243 pe_configs = [ 244 PECfg(pe_id=0), 245 PECfg(pe_id=1), 246 PECfg(pe_id=2), 247 ] 248 sm_configs = [SMConfig(sm_id=0)] 249 system = build_topology(env, pe_configs, sm_configs) 250 251 # Send tokens to different PEs 252 t0 = DyadToken(target=0, offset=0, act_id=0, data=10, port=Port.L) 253 t1 = DyadToken(target=1, offset=0, act_id=0, data=20, port=Port.L) 254 t2 = DyadToken(target=2, offset=0, act_id=0, data=30, port=Port.L) 255 256 system.inject(t0) 257 system.inject(t1) 258 system.inject(t2) 259 260 # Verify each PE received correct token 261 assert system.pes[0].input_store.items[0].data == 10 262 assert system.pes[1].input_store.items[0].data == 20 263 assert system.pes[2].input_store.items[0].data == 30 264 265 def test_multiple_sm_network(self): 266 """Multiple SMs route tokens correctly.""" 267 env = simpy.Environment() 268 pe_configs = [PECfg(pe_id=0)] 269 sm_configs = [ 270 SMConfig(sm_id=0), 271 SMConfig(sm_id=1), 272 SMConfig(sm_id=2), 273 ] 274 system = build_topology(env, pe_configs, sm_configs) 275 276 # Send tokens to different SMs 277 t0 = SMToken(target=0, addr=100, op=MemOp.READ, flags=None, data=None, ret=None) 278 t1 = SMToken(target=1, addr=100, op=MemOp.READ, flags=None, data=None, ret=None) 279 t2 = SMToken(target=2, addr=100, op=MemOp.READ, flags=None, data=None, ret=None) 280 281 system.inject(t0) 282 system.inject(t1) 283 system.inject(t2) 284 285 # Verify each SM received correct token 286 assert system.sms[0].input_store.items[0].target == 0 287 assert system.sms[1].input_store.items[0].target == 1 288 assert system.sms[2].input_store.items[0].target == 2