OR-1 dataflow CPU sketch
1"""
2ALU execution engine for OR1 dataflow CPU.
3
4Pure-function ALU with no state or SimPy dependency. Implements full v0 opcode
5dispatch for arithmetic, logic, and routing operations.
6"""
7
8from cm_inst import ALUOp, ArithOp, LogicOp, RoutingOp
9
10UINT16_MASK = 0xFFFF
11
12
13def to_signed(val: int) -> int:
14 """Interpret a 16-bit unsigned value as signed 2's complement."""
15 return val - 0x10000 if val & 0x8000 else val
16
17
18def _compare(op_fn, left: int, right: int) -> bool:
19 """Helper for comparison operations with signed semantics.
20
21 Args:
22 op_fn: A comparison function (e.g., lambda a, b: a == b)
23 left: Left operand (interpreted as signed)
24 right: Right operand (interpreted as signed)
25
26 Returns:
27 Boolean result of the comparison
28 """
29 return op_fn(to_signed(left), to_signed(right))
30
31
32def execute(op: ALUOp, left: int, right: int | None, const: int | None) -> tuple[int, bool]:
33 """
34 Execute an ALU operation.
35
36 Returns (result & 0xFFFF, bool_out).
37 All values stored as unsigned 16-bit. Comparisons interpret as signed 2's complement.
38
39 Args:
40 op: ALU operation (ArithOp, LogicOp, or RoutingOp)
41 left: Left operand (always required)
42 right: Right operand (required for dyadic ops)
43 const: Constant field (required for shift ops and CONST op)
44
45 Returns:
46 Tuple of (result, bool_out) where:
47 - result is masked to 16-bit unsigned
48 - bool_out is Python bool for routing decisions
49 """
50 if isinstance(op, ArithOp):
51 return _execute_arith(op, left, right, const)
52 if isinstance(op, LogicOp):
53 return _execute_logic(op, left, right)
54 if isinstance(op, RoutingOp):
55 return _execute_routing(op, left, right, const)
56 raise ValueError(f"Unknown ALU operation: {op}")
57
58
59def _execute_arith(op: ArithOp, left: int, right: int | None, const: int | None) -> tuple[int, bool]:
60 """Execute arithmetic operations."""
61 match op:
62 case ArithOp.ADD:
63 result = (left + right) & UINT16_MASK
64 case ArithOp.SUB:
65 result = (left - right) & UINT16_MASK
66 case ArithOp.INC:
67 result = (left + 1) & UINT16_MASK
68 case ArithOp.DEC:
69 result = (left - 1) & UINT16_MASK
70 case ArithOp.SHL:
71 result = (left << const) & UINT16_MASK
72 case ArithOp.SHR:
73 result = (left >> const) & UINT16_MASK
74 case ArithOp.ASR:
75 signed = to_signed(left)
76 result = (signed >> const) & UINT16_MASK
77 case _:
78 raise ValueError(f"Unknown arithmetic op: {op}")
79 return result, False
80
81
82def _execute_logic(op: LogicOp, left: int, right: int | None) -> tuple[int, bool]:
83 """Execute logic operations."""
84 match op:
85 case LogicOp.AND:
86 return (left & right) & UINT16_MASK, False
87 case LogicOp.OR:
88 return (left | right) & UINT16_MASK, False
89 case LogicOp.XOR:
90 return (left ^ right) & UINT16_MASK, False
91 case LogicOp.NOT:
92 return (~left) & UINT16_MASK, False
93 case LogicOp.EQ:
94 cmp = _compare(lambda a, b: a == b, left, right)
95 return (0x0001 if cmp else 0x0000), cmp
96 case LogicOp.LT:
97 cmp = _compare(lambda a, b: a < b, left, right)
98 return (0x0001 if cmp else 0x0000), cmp
99 case LogicOp.LTE:
100 cmp = _compare(lambda a, b: a <= b, left, right)
101 return (0x0001 if cmp else 0x0000), cmp
102 case LogicOp.GT:
103 cmp = _compare(lambda a, b: a > b, left, right)
104 return (0x0001 if cmp else 0x0000), cmp
105 case LogicOp.GTE:
106 cmp = _compare(lambda a, b: a >= b, left, right)
107 return (0x0001 if cmp else 0x0000), cmp
108 case _:
109 raise ValueError(f"Unknown logic op: {op}")
110
111
112def _execute_routing(op: RoutingOp, left: int, right: int | None, const: int | None) -> tuple[int, bool]:
113 """Execute routing operations."""
114 match op:
115 case RoutingOp.BREQ | RoutingOp.SWEQ:
116 cmp = _compare(lambda a, b: a == b, left, right)
117 return left, cmp
118 case RoutingOp.BRGT | RoutingOp.SWGT:
119 cmp = _compare(lambda a, b: a > b, left, right)
120 return left, cmp
121 case RoutingOp.BRGE | RoutingOp.SWGE:
122 cmp = _compare(lambda a, b: a >= b, left, right)
123 return left, cmp
124 case RoutingOp.BROF | RoutingOp.SWOF:
125 raw = left + right
126 cmp = raw > UINT16_MASK
127 return left, cmp
128 case RoutingOp.GATE:
129 cmp = right != 0
130 return left, cmp
131 case RoutingOp.PASS:
132 return left, False
133 case RoutingOp.CONST:
134 return const & UINT16_MASK, False
135 case RoutingOp.FREE_FRAME:
136 return 0, False
137 case RoutingOp.EXTRACT_TAG:
138 return 0, False
139 case RoutingOp.ALLOC_REMOTE:
140 return 0, False
141 case RoutingOp.SEL:
142 cmp = left != 0
143 return (right if cmp else left), cmp
144 case RoutingOp.MRGE:
145 return left, False
146 case _:
147 raise ValueError(f"Unknown routing op: {op}")