OR-1 dataflow CPU sketch
at 5df3bf850390e76fdfe4e03946f1bc9a16e5ee71 245 lines 8.3 kB view raw
1"""Opcode mnemonic mapping and arity classification for OR1 assembly. 2 3This module provides: 4- MNEMONIC_TO_OP: Maps assembly mnemonic strings to ALUOp or MemOp enum values 5- OP_TO_MNEMONIC: Reverse mapping for serialization (handles IntEnum value collisions) 6- MONADIC_OPS: Set of opcodes that are always monadic 7- is_monadic() and is_dyadic(): Functions to check operand arity 8""" 9 10from typing import Optional, Union 11from cm_inst import ArithOp, CfgOp, LogicOp, MemOp, RoutingOp, is_monadic_alu 12 13 14# Build mnemonic to opcode mapping 15MNEMONIC_TO_OP: dict[str, Union[ArithOp, LogicOp, RoutingOp, MemOp, CfgOp]] = { 16 # Arithmetic operations 17 "add": ArithOp.ADD, 18 "sub": ArithOp.SUB, 19 "inc": ArithOp.INC, 20 "dec": ArithOp.DEC, 21 "shiftl": ArithOp.SHIFT_L, 22 "shiftr": ArithOp.SHIFT_R, 23 "ashiftr": ArithOp.ASHFT_R, 24 # Logic operations 25 "and": LogicOp.AND, 26 "or": LogicOp.OR, 27 "xor": LogicOp.XOR, 28 "not": LogicOp.NOT, 29 "eq": LogicOp.EQ, 30 "lt": LogicOp.LT, 31 "lte": LogicOp.LTE, 32 "gt": LogicOp.GT, 33 "gte": LogicOp.GTE, 34 # Routing/branch operations 35 "breq": RoutingOp.BREQ, 36 "brgt": RoutingOp.BRGT, 37 "brge": RoutingOp.BRGE, 38 "brof": RoutingOp.BROF, 39 "sweq": RoutingOp.SWEQ, 40 "swgt": RoutingOp.SWGT, 41 "swge": RoutingOp.SWGE, 42 "swof": RoutingOp.SWOF, 43 "gate": RoutingOp.GATE, 44 "sel": RoutingOp.SEL, 45 "merge": RoutingOp.MRGE, 46 "pass": RoutingOp.PASS, 47 "const": RoutingOp.CONST, 48 "free_ctx": RoutingOp.FREE_CTX, # ALU free (deallocate context slot) 49 # Memory operations 50 "read": MemOp.READ, 51 "write": MemOp.WRITE, 52 "clear": MemOp.CLEAR, 53 "alloc": MemOp.ALLOC, 54 "free": MemOp.FREE, # SM free 55 "rd_inc": MemOp.RD_INC, 56 "rd_dec": MemOp.RD_DEC, 57 "cmp_sw": MemOp.CMP_SW, 58 # Configuration operations (system-level) 59 "load_inst": CfgOp.LOAD_INST, 60 "route_set": CfgOp.ROUTE_SET, 61} 62 63 64# Build reverse mapping with type information to avoid IntEnum collisions 65_reverse_mapping: dict[tuple[type, int], str] = {} 66for mnemonic, op in MNEMONIC_TO_OP.items(): 67 _reverse_mapping[(type(op), int(op))] = mnemonic 68 69 70class TypeAwareOpToMnemonicDict: 71 """Collision-free reverse mapping from opcodes to mnemonics. 72 73 Handles IntEnum cross-type equality by using (type, value) tuples internally. 74 Supports dict-like access: OP_TO_MNEMONIC[ArithOp.ADD] returns "add", 75 OP_TO_MNEMONIC[MemOp.READ] returns "read", etc. 76 """ 77 78 def __init__(self, mapping: dict[tuple[type, int], str]): 79 """Initialize with a type-indexed mapping. 80 81 Args: 82 mapping: dict from (type, value) tuples to mnemonic strings 83 """ 84 self._mapping = mapping 85 86 def __getitem__(self, op: Union[ArithOp, LogicOp, RoutingOp, MemOp, CfgOp]) -> str: 87 """Get the mnemonic for an opcode. 88 89 Args: 90 op: The opcode enum value 91 92 Returns: 93 The mnemonic string 94 95 Raises: 96 KeyError: If the opcode is not in the mapping 97 """ 98 key = (type(op), int(op)) 99 if key not in self._mapping: 100 raise KeyError(f"Opcode {op} ({type(op).__name__}) not found in mapping") 101 return self._mapping[key] 102 103 def __contains__(self, op: Union[ArithOp, LogicOp, RoutingOp, MemOp, CfgOp]) -> bool: 104 """Check if an opcode is in the mapping.""" 105 return (type(op), int(op)) in self._mapping 106 107 def __iter__(self): 108 """Iterate over mnemonic strings.""" 109 return iter(self._mapping.values()) 110 111 def __len__(self) -> int: 112 """Return the number of opcode-mnemonic pairs.""" 113 return len(self._mapping) 114 115 def items(self): 116 """Return an iterator of (opcode_type, mnemonic) pairs for testing. 117 118 This reconstructs the original enum instances from the stored types/values. 119 """ 120 result = [] 121 for (op_type, op_val), mnemonic in self._mapping.items(): 122 result.append((op_type(op_val), mnemonic)) 123 return result 124 125 126OP_TO_MNEMONIC: TypeAwareOpToMnemonicDict = TypeAwareOpToMnemonicDict(_reverse_mapping) 127 128 129# Set of opcodes that are always monadic (single input operand). 130# We use a frozenset of (type, value) tuples to avoid IntEnum collisions. 131_MONADIC_OPS_TUPLES: frozenset[tuple[type, int]] = frozenset([ 132 # ALU ops: duplicated from cm_inst.is_monadic_alu() for MONADIC_OPS membership testing. 133 # is_monadic() short-circuits to is_monadic_alu() for ALU ops, so these entries 134 # are only reached via `op in MONADIC_OPS` (TypeAwareMonadicOpsSet). 135 (ArithOp, int(ArithOp.INC)), 136 (ArithOp, int(ArithOp.DEC)), 137 (ArithOp, int(ArithOp.SHIFT_L)), 138 (ArithOp, int(ArithOp.SHIFT_R)), 139 (ArithOp, int(ArithOp.ASHFT_R)), 140 # Logic: single input 141 (LogicOp, int(LogicOp.NOT)), 142 # Routing: single input or no ALU involvement 143 (RoutingOp, int(RoutingOp.PASS)), 144 (RoutingOp, int(RoutingOp.CONST)), 145 (RoutingOp, int(RoutingOp.FREE_CTX)), 146 # Memory: single input (monadic SM operations) 147 (MemOp, int(MemOp.READ)), 148 (MemOp, int(MemOp.ALLOC)), 149 (MemOp, int(MemOp.FREE)), 150 (MemOp, int(MemOp.CLEAR)), 151 (MemOp, int(MemOp.RD_INC)), 152 (MemOp, int(MemOp.RD_DEC)), 153]) 154 155 156class TypeAwareMonadicOpsSet: 157 """Collision-free set of monadic opcodes. 158 159 Handles IntEnum cross-type equality by using (type, value) tuples internally. 160 Supports membership testing: ArithOp.INC in MONADIC_OPS returns True, 161 but ArithOp.ADD in MONADIC_OPS returns False (collision-free). 162 """ 163 164 def __init__(self, tuples: frozenset[tuple[type, int]]): 165 """Initialize with type-indexed tuples. 166 167 Args: 168 tuples: frozenset of (type, value) tuples 169 """ 170 self._tuples = tuples 171 172 def __contains__(self, op: Union[ArithOp, LogicOp, RoutingOp, MemOp, CfgOp]) -> bool: 173 """Check if an opcode is in the set, handling IntEnum collisions. 174 175 Args: 176 op: The opcode enum value 177 178 Returns: 179 True if the opcode is monadic, False otherwise 180 """ 181 return (type(op), int(op)) in self._tuples 182 183 def __iter__(self): 184 """Iterate over opcode instances in the set.""" 185 for op_type, op_val in self._tuples: 186 yield op_type(op_val) 187 188 def __len__(self) -> int: 189 """Return the number of monadic opcodes.""" 190 return len(self._tuples) 191 192 def __repr__(self) -> str: 193 """Return a string representation of the set.""" 194 ops = list(self) 195 return f"TypeAwareMonadicOpsSet({ops})" 196 197 198MONADIC_OPS: TypeAwareMonadicOpsSet = TypeAwareMonadicOpsSet(_MONADIC_OPS_TUPLES) 199 200 201def is_monadic(op: Union[ArithOp, LogicOp, RoutingOp, MemOp, CfgOp], const: Optional[int] = None) -> bool: 202 """Check if an opcode is monadic (single input operand). 203 204 Args: 205 op: The ALUOp, MemOp, or CfgOp enum value 206 const: Optional const value. Used to determine monadic form of WRITE. 207 If const is not None, WRITE is monadic (cell_addr from const). 208 If const is None, WRITE is dyadic (cell_addr from left operand). 209 210 Returns: 211 True if the opcode is always monadic, or if it's WRITE with const set. 212 False for CMP_SW (always dyadic) and WRITE with const=None (dyadic). 213 CfgOp operations are always monadic (system-level, no ALU involvement). 214 """ 215 # CfgOp operations are always monadic (system-level configuration) 216 if type(op) is CfgOp: 217 return True 218 219 # Use canonical is_monadic_alu for ALU operations 220 if isinstance(op, (ArithOp, LogicOp, RoutingOp)): 221 return is_monadic_alu(op) 222 223 # Handle MemOp operations 224 op_tuple = (type(op), int(op)) 225 if op_tuple in _MONADIC_OPS_TUPLES: 226 return True 227 228 # Special case: WRITE can be monadic (const given) or dyadic (const not given) 229 if type(op) is MemOp and op == MemOp.WRITE: 230 return const is not None 231 232 return False 233 234 235def is_dyadic(op: Union[ArithOp, LogicOp, RoutingOp, MemOp, CfgOp], const: Optional[int] = None) -> bool: 236 """Check if an opcode is dyadic (two input operands). 237 238 Args: 239 op: The ALUOp, MemOp, or CfgOp enum value 240 const: Optional const value. Used for context-dependent operations like WRITE. 241 242 Returns: 243 True if the opcode is dyadic, False otherwise. 244 """ 245 return not is_monadic(op, const)