OR-1 dataflow CPU sketch
at main 192 lines 7.1 kB view raw
1"""Tests for the Placement validation pass. 2 3Tests verify: 4- or1-asm.AC5.1: Valid placements are accepted 5- or1-asm.AC5.2: Placement on nonexistent PE produces error 6- or1-asm.AC5.3: Unplaced node produces error 7""" 8 9from asm.place import place 10from asm.ir import IRGraph, IRNode, SystemConfig, SourceLoc 11from asm.errors import ErrorCategory 12from cm_inst import ArithOp 13 14 15class TestValidPlacement: 16 """AC5.1: All nodes with explicit PE placements are accepted when PE exists.""" 17 18 def test_single_node_pe0(self): 19 """Single node on PE0.""" 20 node = IRNode( 21 name="&add", 22 opcode=ArithOp.ADD, 23 pe=0, 24 loc=SourceLoc(1, 1), 25 ) 26 graph = IRGraph({"&add": node}) 27 result = place(graph) 28 29 assert len(result.errors) == 0 30 assert result.system is not None 31 assert result.system.pe_count >= 1 32 33 def test_multiple_nodes_different_pes(self): 34 """Multiple nodes on different PEs.""" 35 nodes = { 36 "&add": IRNode(name="&add", opcode=ArithOp.ADD, pe=0, loc=SourceLoc(1, 1)), 37 "&sub": IRNode(name="&sub", opcode=ArithOp.SUB, pe=1, loc=SourceLoc(2, 1)), 38 "&inc": IRNode(name="&inc", opcode=ArithOp.INC, pe=2, loc=SourceLoc(3, 1)), 39 "&dec": IRNode(name="&dec", opcode=ArithOp.DEC, pe=3, loc=SourceLoc(4, 1)), 40 } 41 system = SystemConfig(pe_count=4, sm_count=1, iram_capacity=64, frame_count=4) 42 graph = IRGraph(nodes, system=system) 43 result = place(graph) 44 45 assert len(result.errors) == 0 46 assert result.system.pe_count == 4 47 48 def test_system_config_inferred(self): 49 """System config is inferred from max PE ID.""" 50 node = IRNode( 51 name="&add", 52 opcode=ArithOp.ADD, 53 pe=3, 54 loc=SourceLoc(1, 1), 55 ) 56 graph = IRGraph({"&add": node}, system=None) 57 result = place(graph) 58 59 assert len(result.errors) == 0 60 assert result.system is not None 61 assert result.system.pe_count >= 4 # At least 4 PEs (0-3) 62 63 64class TestNonexistentPE: 65 """AC5.2: Node placed on nonexistent PE produces error.""" 66 67 def test_node_on_pe9_with_4_pes(self): 68 """Node on PE9 when system only has 4 PEs.""" 69 node = IRNode( 70 name="&add", 71 opcode=ArithOp.ADD, 72 pe=9, 73 loc=SourceLoc(5, 10), 74 ) 75 system = SystemConfig(pe_count=4, sm_count=1, iram_capacity=64, frame_count=4) 76 graph = IRGraph({"&add": node}, system=system) 77 result = place(graph) 78 79 assert len(result.errors) == 1 80 error = result.errors[0] 81 assert error.category == ErrorCategory.PLACEMENT 82 assert "PE9" in error.message 83 assert "4 PEs" in error.message 84 assert "0-3" in error.message 85 86 def test_node_on_pe1_with_1_pe(self): 87 """Node on PE1 when system only has 1 PE.""" 88 node = IRNode( 89 name="&add", 90 opcode=ArithOp.ADD, 91 pe=1, 92 loc=SourceLoc(1, 1), 93 ) 94 system = SystemConfig(pe_count=1, sm_count=1, iram_capacity=64, frame_count=4) 95 graph = IRGraph({"&add": node}, system=system) 96 result = place(graph) 97 98 assert len(result.errors) == 1 99 error = result.errors[0] 100 assert error.category == ErrorCategory.PLACEMENT 101 assert "PE1" in error.message 102 assert "0-0" in error.message 103 104 def test_multiple_nodes_one_invalid_pe(self): 105 """Multiple nodes, one on invalid PE.""" 106 nodes = { 107 "&add": IRNode(name="&add", opcode=ArithOp.ADD, pe=0, loc=SourceLoc(1, 1)), 108 "&sub": IRNode(name="&sub", opcode=ArithOp.SUB, pe=5, loc=SourceLoc(2, 1)), 109 "&inc": IRNode(name="&inc", opcode=ArithOp.INC, pe=1, loc=SourceLoc(3, 1)), 110 } 111 system = SystemConfig(pe_count=4, sm_count=1, iram_capacity=64, frame_count=4) 112 graph = IRGraph(nodes, system=system) 113 result = place(graph) 114 115 assert len(result.errors) == 1 116 error = result.errors[0] 117 assert error.category == ErrorCategory.PLACEMENT 118 assert "&sub" in error.message 119 assert "PE5" in error.message 120 121 122class TestUnplacedNode: 123 """AC10.1: Unplaced nodes are auto-placed without explicit annotations (Phase 7).""" 124 125 def test_single_unplaced_node(self): 126 """Single unplaced node gets auto-placed.""" 127 node = IRNode( 128 name="&add", 129 opcode=ArithOp.ADD, 130 pe=None, 131 loc=SourceLoc(5, 3), 132 ) 133 graph = IRGraph({"&add": node}) 134 result = place(graph) 135 136 # Phase 7: auto-placement should succeed 137 assert len(result.errors) == 0 138 assert result.nodes["&add"].pe is not None 139 140 def test_multiple_nodes_some_unplaced(self): 141 """Unplaced nodes get auto-placed (Phase 7).""" 142 nodes = { 143 "&add": IRNode(name="&add", opcode=ArithOp.ADD, pe=0, loc=SourceLoc(1, 1)), 144 "&sub": IRNode(name="&sub", opcode=ArithOp.SUB, pe=None, loc=SourceLoc(2, 1)), 145 "&inc": IRNode(name="&inc", opcode=ArithOp.INC, pe=None, loc=SourceLoc(3, 1)), 146 } 147 system = SystemConfig(pe_count=2, sm_count=1, iram_capacity=64, frame_count=4) 148 graph = IRGraph(nodes, system=system) 149 result = place(graph) 150 151 # Phase 7: auto-placement should succeed 152 assert len(result.errors) == 0 153 assert result.nodes["&sub"].pe is not None 154 assert result.nodes["&inc"].pe is not None 155 156 def test_all_nodes_unplaced(self): 157 """All unplaced nodes get auto-placed (Phase 7).""" 158 nodes = { 159 "&add": IRNode(name="&add", opcode=ArithOp.ADD, pe=None, loc=SourceLoc(1, 1)), 160 "&sub": IRNode(name="&sub", opcode=ArithOp.SUB, pe=None, loc=SourceLoc(2, 1)), 161 } 162 graph = IRGraph(nodes) 163 result = place(graph) 164 165 # Phase 7: auto-placement should succeed 166 assert len(result.errors) == 0 167 for node in result.nodes.values(): 168 assert node.pe is not None 169 170 171class TestMixedErrors: 172 """Combined placement errors.""" 173 174 def test_unplaced_and_invalid_pe(self): 175 """Invalid PE placement produces error; unplaced nodes are auto-placed.""" 176 nodes = { 177 "&add": IRNode(name="&add", opcode=ArithOp.ADD, pe=0, loc=SourceLoc(1, 1)), 178 "&sub": IRNode(name="&sub", opcode=ArithOp.SUB, pe=None, loc=SourceLoc(2, 1)), 179 "&inc": IRNode(name="&inc", opcode=ArithOp.INC, pe=9, loc=SourceLoc(3, 1)), 180 } 181 system = SystemConfig(pe_count=4, sm_count=1, iram_capacity=64, frame_count=4) 182 graph = IRGraph(nodes, system=system) 183 result = place(graph) 184 185 # Should have 1 error for invalid PE placement on &inc; &sub is auto-placed 186 assert len(result.errors) == 1 187 error = result.errors[0] 188 assert error.category == ErrorCategory.PLACEMENT 189 assert "&inc" in error.message 190 assert "PE9" in error.message 191 # &sub should be auto-placed 192 assert result.nodes["&sub"].pe is not None