OR-1 dataflow CPU sketch
1"""
2Tests for network topology and routing.
3
4Verifies restricted topology functionality for ProcessingElement network.
5"""
6
7import simpy
8
9from cm_inst import OutputStyle, ArithOp, Port, RoutingOp, Instruction, FrameDest, TokenKind
10from emu.network import build_topology
11from emu.types import PEConfig, SMConfig
12from tokens import MonadToken, DyadToken
13
14
15class TestRestrictedTopology:
16 """Test restricted topology via PEConfig allowed routes (AC7.6–AC7.7).
17
18 Verifies:
19 - AC7.6: build_topology applies route restrictions from PEConfig
20 - AC7.7: PEConfig with None routes preserves full-mesh (backward compatibility)
21 """
22
23 def test_ac76_restricted_topology_pe_routes(self):
24 """AC7.6: build_topology restricts PE routes based on allowed_pe_routes."""
25 env = simpy.Environment()
26
27 # Create 3 PEs but restrict PE 0 to only route to PE 1
28 pe0_config = PEConfig(pe_id=0, iram={}, allowed_pe_routes={1})
29 pe1_config = PEConfig(pe_id=1, iram={})
30 pe2_config = PEConfig(pe_id=2, iram={})
31
32 sys = build_topology(env, [pe0_config, pe1_config, pe2_config], [])
33
34 # PE 0 should only have PE 1 in its route_table
35 pe0 = sys.pes[0]
36 assert set(pe0.route_table.keys()) == {1}
37
38 def test_ac76_restricted_topology_sm_routes(self):
39 """AC7.6: build_topology restricts SM routes based on allowed_sm_routes."""
40 env = simpy.Environment()
41
42 # Create PE 0 restricted to SM 0 only (not SM 1)
43 pe0_config = PEConfig(pe_id=0, iram={}, allowed_sm_routes={0})
44 sm0_config = SMConfig(sm_id=0)
45 sm1_config = SMConfig(sm_id=1)
46
47 sys = build_topology(env, [pe0_config], [sm0_config, sm1_config])
48
49 # PE 0 should only have SM 0 in its sm_routes
50 pe0 = sys.pes[0]
51 assert set(pe0.sm_routes.keys()) == {0}
52
53 def test_ac76_restricted_topology_both_pe_and_sm(self):
54 """AC7.6: build_topology applies both PE and SM route restrictions."""
55 env = simpy.Environment()
56
57 # Create PE 0 restricted to PE 1 and SM 0 only
58 pe0_config = PEConfig(
59 pe_id=0,
60 iram={},
61 allowed_pe_routes={1},
62 allowed_sm_routes={0}
63 )
64 pe1_config = PEConfig(pe_id=1, iram={})
65 pe2_config = PEConfig(pe_id=2, iram={})
66 sm0_config = SMConfig(sm_id=0)
67 sm1_config = SMConfig(sm_id=1)
68
69 sys = build_topology(
70 env,
71 [pe0_config, pe1_config, pe2_config],
72 [sm0_config, sm1_config]
73 )
74
75 # PE 0 should be restricted in both dimensions
76 pe0 = sys.pes[0]
77 assert set(pe0.route_table.keys()) == {1}
78 assert set(pe0.sm_routes.keys()) == {0}
79
80 # PE 1 and PE 2 should have full-mesh (no restrictions)
81 pe1 = sys.pes[1]
82 assert set(pe1.route_table.keys()) == {0, 1, 2}
83 assert set(pe1.sm_routes.keys()) == {0, 1}
84
85 pe2 = sys.pes[2]
86 assert set(pe2.route_table.keys()) == {0, 1, 2}
87 assert set(pe2.sm_routes.keys()) == {0, 1}
88
89 def test_ac77_none_routes_preserves_full_mesh(self):
90 """AC7.7: PEConfig with None routes preserves full-mesh topology (backward compat)."""
91 env = simpy.Environment()
92
93 # Create 3 PEs with no route restrictions (None)
94 pe0_config = PEConfig(pe_id=0, iram={}) # allowed_pe_routes=None, allowed_sm_routes=None
95 pe1_config = PEConfig(pe_id=1, iram={})
96 pe2_config = PEConfig(pe_id=2, iram={})
97 sm0_config = SMConfig(sm_id=0)
98 sm1_config = SMConfig(sm_id=1)
99
100 sys = build_topology(
101 env,
102 [pe0_config, pe1_config, pe2_config],
103 [sm0_config, sm1_config]
104 )
105
106 # All PEs should have full-mesh routes
107 for pe_id in [0, 1, 2]:
108 pe = sys.pes[pe_id]
109 assert set(pe.route_table.keys()) == {0, 1, 2}
110 assert set(pe.sm_routes.keys()) == {0, 1}