OR-1 dataflow CPU sketch
at main 253 lines 9.0 kB view raw
1"""Tests for macro IR types (MacroParam, ParamRef, MacroDef, IRMacroCall). 2 3Tests verify: 4- MacroParam can be constructed with a name 5- ParamRef can be constructed with param, prefix, and suffix 6- MacroDef can be constructed with name, params, and body IRGraph 7- IRMacroCall can be constructed with name, positional and named args 8- IRNode.const field accepts ParamRef values 9- IRGraph.macro_defs and IRGraph.macro_calls fields can be populated 10- RegionKind.MACRO enum value exists and has correct value 11""" 12 13import pytest 14 15from asm.ir import ( 16 IRGraph, 17 IRNode, 18 IREdge, 19 IRDataDef, 20 MacroParam, 21 ParamRef, 22 MacroDef, 23 IRMacroCall, 24 RegionKind, 25 SourceLoc, 26) 27from cm_inst import ArithOp, Port 28 29 30class TestMacroParam: 31 """Tests for MacroParam dataclass.""" 32 33 def test_macro_param_construction(self): 34 """MacroParam can be constructed with a name.""" 35 param = MacroParam(name="x") 36 assert param.name == "x" 37 38 def test_macro_param_frozen(self): 39 """MacroParam is frozen (immutable).""" 40 param = MacroParam(name="x") 41 with pytest.raises(AttributeError): 42 param.name = "y" 43 44 45class TestParamRef: 46 """Tests for ParamRef dataclass.""" 47 48 def test_param_ref_basic_construction(self): 49 """ParamRef can be constructed with param name.""" 50 ref = ParamRef(param="x") 51 assert ref.param == "x" 52 assert ref.prefix == "" 53 assert ref.suffix == "" 54 55 def test_param_ref_with_prefix(self): 56 """ParamRef can include an optional prefix.""" 57 ref = ParamRef(param="x", prefix="pre_") 58 assert ref.param == "x" 59 assert ref.prefix == "pre_" 60 assert ref.suffix == "" 61 62 def test_param_ref_with_suffix(self): 63 """ParamRef can include an optional suffix.""" 64 ref = ParamRef(param="x", suffix="_suf") 65 assert ref.param == "x" 66 assert ref.prefix == "" 67 assert ref.suffix == "_suf" 68 69 def test_param_ref_with_prefix_and_suffix(self): 70 """ParamRef can include both prefix and suffix for token pasting.""" 71 ref = ParamRef(param="label", prefix="&", suffix="_out") 72 assert ref.param == "label" 73 assert ref.prefix == "&" 74 assert ref.suffix == "_out" 75 76 def test_param_ref_frozen(self): 77 """ParamRef is frozen (immutable).""" 78 ref = ParamRef(param="x") 79 with pytest.raises(AttributeError): 80 ref.param = "y" 81 82 83class TestMacroDef: 84 """Tests for MacroDef dataclass.""" 85 86 def test_macro_def_basic_construction(self): 87 """MacroDef can be constructed with name, params, and body.""" 88 body = IRGraph() 89 macro = MacroDef(name="loop", params=(), body=body) 90 assert macro.name == "loop" 91 assert macro.params == () 92 assert macro.body is body 93 assert macro.loc == SourceLoc(0, 0) 94 95 def test_macro_def_with_params(self): 96 """MacroDef can include formal parameters.""" 97 params = (MacroParam(name="init"), MacroParam(name="limit")) 98 body = IRGraph() 99 macro = MacroDef(name="loop_counted", params=params, body=body) 100 assert macro.name == "loop_counted" 101 assert len(macro.params) == 2 102 assert macro.params[0].name == "init" 103 assert macro.params[1].name == "limit" 104 105 def test_macro_def_with_location(self): 106 """MacroDef can include a source location.""" 107 loc = SourceLoc(line=5, column=10) 108 body = IRGraph() 109 macro = MacroDef(name="test", params=(), body=body, loc=loc) 110 assert macro.loc == loc 111 112 def test_macro_def_body_with_nodes(self): 113 """MacroDef body IRGraph can contain nodes.""" 114 node = IRNode(name="&add", opcode=ArithOp.ADD) 115 body = IRGraph(nodes={"&add": node}) 116 macro = MacroDef(name="simple", params=(), body=body) 117 assert "&add" in macro.body.nodes 118 assert macro.body.nodes["&add"].opcode == ArithOp.ADD 119 120 def test_macro_def_frozen(self): 121 """MacroDef is frozen (immutable).""" 122 macro = MacroDef(name="test", params=(), body=IRGraph()) 123 with pytest.raises(AttributeError): 124 macro.name = "other" 125 126 127class TestIRMacroCall: 128 """Tests for IRMacroCall dataclass.""" 129 130 def test_macro_call_basic_construction(self): 131 """IRMacroCall can be constructed with name.""" 132 call = IRMacroCall(name="loop") 133 assert call.name == "loop" 134 assert call.positional_args == () 135 assert call.named_args == () 136 137 def test_macro_call_with_positional_args(self): 138 """IRMacroCall can include positional arguments.""" 139 args = ("&init", "&limit") 140 call = IRMacroCall(name="loop_counted", positional_args=args) 141 assert call.name == "loop_counted" 142 assert call.positional_args == args 143 assert len(call.positional_args) == 2 144 145 def test_macro_call_with_named_args(self): 146 """IRMacroCall can include named arguments.""" 147 named = (("gate", "&my_gate"), ("trigger", "&my_trigger")) 148 call = IRMacroCall(name="inject", named_args=named) 149 assert call.name == "inject" 150 assert call.named_args == named 151 assert len(call.named_args) == 2 152 153 def test_macro_call_with_location(self): 154 """IRMacroCall can include a source location.""" 155 loc = SourceLoc(line=12, column=5) 156 call = IRMacroCall(name="loop", loc=loc) 157 assert call.loc == loc 158 159 def test_macro_call_frozen(self): 160 """IRMacroCall is frozen (immutable).""" 161 call = IRMacroCall(name="test") 162 with pytest.raises(AttributeError): 163 call.name = "other" 164 165 166class TestIRNodeWithParamRef: 167 """Tests for IRNode accepting ParamRef in const field.""" 168 169 def test_ir_node_const_with_int(self): 170 """IRNode.const can hold an integer.""" 171 node = IRNode(name="&test", opcode=ArithOp.ADD, const=42) 172 assert node.const == 42 173 174 def test_ir_node_const_with_param_ref(self): 175 """IRNode.const can hold a ParamRef.""" 176 ref = ParamRef(param="x") 177 node = IRNode(name="&test", opcode=ArithOp.ADD, const=ref) 178 assert isinstance(node.const, ParamRef) 179 assert node.const.param == "x" 180 181 def test_ir_node_const_with_param_ref_and_prefix(self): 182 """IRNode.const can hold a ParamRef with prefix/suffix.""" 183 ref = ParamRef(param="addr", prefix="0x", suffix="00") 184 node = IRNode(name="&test", opcode=ArithOp.ADD, const=ref) 185 assert node.const.param == "addr" 186 assert node.const.prefix == "0x" 187 assert node.const.suffix == "00" 188 189 def test_ir_node_const_none(self): 190 """IRNode.const can be None.""" 191 node = IRNode(name="&test", opcode=ArithOp.ADD, const=None) 192 assert node.const is None 193 194 195class TestIRGraphMacroFields: 196 """Tests for IRGraph.macro_defs and IRGraph.macro_calls fields.""" 197 198 def test_ir_graph_empty_macro_defs(self): 199 """IRGraph starts with empty macro_defs list.""" 200 graph = IRGraph() 201 assert graph.macro_defs == [] 202 203 def test_ir_graph_empty_macro_calls(self): 204 """IRGraph starts with empty macro_calls list.""" 205 graph = IRGraph() 206 assert graph.macro_calls == [] 207 208 def test_ir_graph_with_macro_defs(self): 209 """IRGraph can store macro definitions.""" 210 body = IRGraph() 211 macro = MacroDef(name="loop", params=(), body=body) 212 graph = IRGraph(macro_defs=[macro]) 213 assert len(graph.macro_defs) == 1 214 assert graph.macro_defs[0].name == "loop" 215 216 def test_ir_graph_with_macro_calls(self): 217 """IRGraph can store macro invocations.""" 218 call = IRMacroCall(name="loop", positional_args=("&src", "&dest")) 219 graph = IRGraph(macro_calls=[call]) 220 assert len(graph.macro_calls) == 1 221 assert graph.macro_calls[0].name == "loop" 222 223 def test_ir_graph_with_both_macro_defs_and_calls(self): 224 """IRGraph can store both macro definitions and invocations.""" 225 body = IRGraph() 226 macro_def = MacroDef(name="loop", params=(), body=body) 227 macro_call = IRMacroCall(name="loop", positional_args=("&a", "&b")) 228 graph = IRGraph(macro_defs=[macro_def], macro_calls=[macro_call]) 229 assert len(graph.macro_defs) == 1 230 assert len(graph.macro_calls) == 1 231 232 233class TestRegionKindMacro: 234 """Tests for RegionKind.MACRO enum value.""" 235 236 def test_region_kind_macro_exists(self): 237 """RegionKind.MACRO enum value exists.""" 238 assert hasattr(RegionKind, "MACRO") 239 240 def test_region_kind_macro_value(self): 241 """RegionKind.MACRO has correct string value.""" 242 assert RegionKind.MACRO.value == "macro" 243 244 def test_region_kind_macro_type(self): 245 """RegionKind.MACRO is an enum member.""" 246 assert isinstance(RegionKind.MACRO, RegionKind) 247 248 def test_all_region_kinds(self): 249 """RegionKind contains expected members.""" 250 kinds = {kind.name for kind in RegionKind} 251 assert "FUNCTION" in kinds 252 assert "LOCATION" in kinds 253 assert "MACRO" in kinds