move unused directory out of src, to indicate "ignore completely"
[soc.git] / unused_please_ignore_completely / simulator / internalop_sim.py
1 from soc.decoder.power_enums import (Function, Form, InternalOp,
2 In1Sel, In2Sel, In3Sel, OutSel,
3 RC, LdstLen, CryIn, get_csv,
4 single_bit_flags,
5 get_signal_name, default_values)
6 import math
7
8
9 class MemorySim:
10 def __init__(self, bytes_per_word=8):
11 self.mem = {}
12 self.bytes_per_word = bytes_per_word
13 self.word_log2 = math.ceil(math.log2(bytes_per_word))
14
15 def _get_shifter_mask(self, width, remainder):
16 shifter = ((self.bytes_per_word - width) - remainder) * \
17 8 # bits per byte
18 mask = (1 << (width * 8)) - 1
19 return shifter, mask
20
21 # TODO: Implement ld/st of lesser width
22 def ld(self, address, width=8):
23 remainder = address & (self.bytes_per_word - 1)
24 address = address >> self.word_log2
25 assert remainder & (width - 1) == 0, "Unaligned access unsupported!"
26 if address in self.mem:
27 val = self.mem[address]
28 else:
29 val = 0
30
31 if width != self.bytes_per_word:
32 shifter, mask = self._get_shifter_mask(width, remainder)
33 val = val & (mask << shifter)
34 val >>= shifter
35 print("Read {:x} from addr {:x}".format(val, address))
36 return val
37
38 def st(self, address, value, width=8):
39 remainder = address & (self.bytes_per_word - 1)
40 address = address >> self.word_log2
41 assert remainder & (width - 1) == 0, "Unaligned access unsupported!"
42 print("Writing {:x} to addr {:x}".format(value, address))
43 if width != self.bytes_per_word:
44 if address in self.mem:
45 val = self.mem[address]
46 else:
47 val = 0
48 shifter, mask = self._get_shifter_mask(width, remainder)
49 val &= ~(mask << shifter)
50 val |= value << shifter
51 self.mem[address] = val
52 else:
53 self.mem[address] = value
54
55
56 class RegFile:
57 def __init__(self):
58 self.regfile = [0] * 32
59 self.sprs = {}
60
61 def write_reg(self, regnum, value):
62 all1s = (1 << 64)-1 # 64 bits worth of 1s
63 value &= all1s
64 print("Writing {:x} to reg r{}".format(value, regnum))
65 self.regfile[regnum] = value
66
67 def read_reg(self, regnum):
68 val = self.regfile[regnum]
69 print("Read {:x} from reg r{}".format(val, regnum))
70 return val
71
72 def assert_gpr(self, gpr, val):
73 reg_val = self.read_reg(gpr)
74 msg = "reg r{} got {:x}, expecting {:x}".format(
75 gpr, reg_val, val)
76 assert reg_val == val, msg
77
78 def assert_gprs(self, gprs):
79 for k, v in list(gprs.items()):
80 self.assert_gpr(k, v)
81
82 def set_xer(self, result, operanda, operandb):
83 xer = 0
84 if result & 1 << 64:
85 xer |= XER.CA
86
87 self.xer = xer
88
89
90 class InternalOpSimulator:
91 def __init__(self):
92 self.mem_sim = MemorySim()
93 self.regfile = RegFile()
94
95 def execute_alu_op(self, op1, op2, internal_op, carry=0):
96 print(internal_op)
97 if internal_op == InternalOp.OP_ADD.value:
98 return op1 + op2 + carry
99 elif internal_op == InternalOp.OP_AND.value:
100 return op1 & op2
101 elif internal_op == InternalOp.OP_OR.value:
102 return op1 | op2
103 elif internal_op == InternalOp.OP_MUL_L64.value:
104 return op1 * op2
105 else:
106 assert False, "Not implemented"
107
108 def update_cr0(self, result):
109 if result == 0:
110 self.cr0 = 0b001
111 elif result >> 63:
112 self.cr0 = 0b100
113 else:
114 self.cr0 = 0b010
115 print("update_cr0", self.cr0)
116
117 def alu_op(self, pdecode2):
118 all1s = (1 << 64)-1 # 64 bits worth of 1s
119 internal_op = yield pdecode2.dec.op.internal_op
120 operand1 = 0
121 operand2 = 0
122 result = 0
123 carry = 0
124 r1_ok = yield pdecode2.e.read_reg1.ok
125 r2_ok = yield pdecode2.e.read_reg2.ok
126 r3_ok = yield pdecode2.e.read_reg3.ok
127 imm_ok = yield pdecode2.e.imm_data.ok
128 if r1_ok:
129 r1_sel = yield pdecode2.e.read_reg1.data
130 operand1 = self.regfile.read_reg(r1_sel)
131 elif r3_ok:
132 r3_sel = yield pdecode2.e.read_reg3.data
133 operand1 = self.regfile.read_reg(r3_sel)
134 if r2_ok:
135 r2_sel = yield pdecode2.e.read_reg2.data
136 operand2 = self.regfile.read_reg(r2_sel)
137 if imm_ok:
138 operand2 = yield pdecode2.e.imm_data.data
139
140 inv_a = yield pdecode2.dec.op.inv_a
141 if inv_a:
142 operand1 = (~operand1) & all1s
143
144 cry_in = yield pdecode2.dec.op.cry_in
145 if cry_in == CryIn.ONE.value:
146 carry = 1
147 elif cry_in == CryIn.CA.value:
148 carry = self.carry_out
149
150 # TODO rc_sel = yield pdecode2.dec.op.rc_sel
151 result = self.execute_alu_op(operand1, operand2, internal_op,
152 carry=carry)
153
154 cry_out = yield pdecode2.dec.op.cry_out
155 rc = yield pdecode2.e.rc.data
156
157 if rc:
158 self.update_cr0(result)
159 if cry_out == 1:
160 self.carry_out = (result >> 64)
161 print("setting carry_out", self.carry_out)
162
163 ro_ok = yield pdecode2.e.write_reg.ok
164 if ro_ok:
165 ro_sel = yield pdecode2.e.write_reg.data
166 self.regfile.write_reg(ro_sel, result)
167
168 def mem_op(self, pdecode2):
169 internal_op = yield pdecode2.dec.op.internal_op
170 addr_reg = yield pdecode2.e.read_reg1.data
171 addr = self.regfile.read_reg(addr_reg)
172
173 imm_ok = yield pdecode2.e.imm_data.ok
174 r2_ok = yield pdecode2.e.read_reg2.ok
175 width = yield pdecode2.e.data_len
176 if imm_ok:
177 imm = yield pdecode2.e.imm_data.data
178 addr += imm
179 elif r2_ok:
180 r2_sel = yield pdecode2.e.read_reg2.data
181 addr += self.regfile.read_reg(r2_sel)
182 if internal_op == InternalOp.OP_STORE.value:
183 val_reg = yield pdecode2.e.read_reg3.data
184 val = self.regfile.read_reg(val_reg)
185 self.mem_sim.st(addr, val, width)
186 elif internal_op == InternalOp.OP_LOAD.value:
187 dest_reg = yield pdecode2.e.write_reg.data
188 val = self.mem_sim.ld(addr, width)
189 self.regfile.write_reg(dest_reg, val)
190
191 def execute_op(self, pdecode2):
192 function = yield pdecode2.dec.op.function_unit
193 if function == Function.ALU.value:
194 yield from self.alu_op(pdecode2)
195 elif function == Function.LDST.value:
196 yield from self.mem_op(pdecode2)