92c12f632fdea9b382fdb18d2f7d00200fb39fa1
[soc.git] / src / soc / fu / alu / test / test_pipe_caller.py
1 import random
2 from soc.fu.alu.pipe_data import ALUPipeSpec
3 from soc.fu.alu.pipeline import ALUBasePipe
4 from soc.fu.test.common import (TestCase, TestAccumulatorBase, ALUHelpers)
5 from soc.config.endian import bigendian
6 from soc.decoder.isa.all import ISA
7 from soc.simulator.program import Program
8 from soc.decoder.selectable_int import SelectableInt
9 from soc.decoder.power_enums import (XER_bits, Function, MicrOp, CryIn)
10 from soc.decoder.power_decoder2 import (PowerDecode2)
11 from soc.decoder.power_decoder import (create_pdecode)
12 from soc.decoder.isa.caller import ISACaller, special_sprs
13 import unittest
14 from nmigen.cli import rtlil
15 from nmutil.formaltest import FHDLTestCase
16 from nmigen import Module, Signal
17
18 # NOTE: to use cxxsim, export NMIGEN_SIM_MODE=cxxsim from the shell
19 # Also, check out the cxxsim nmigen branch, and latest yosys from git
20 from nmutil.sim_tmp_alternative import Simulator, Settle
21
22
23 def get_cu_inputs(dec2, sim):
24 """naming (res) must conform to ALUFunctionUnit input regspec
25 """
26 res = {}
27
28 yield from ALUHelpers.get_sim_int_ra(res, sim, dec2) # RA
29 yield from ALUHelpers.get_sim_int_rb(res, sim, dec2) # RB
30 yield from ALUHelpers.get_rd_sim_xer_ca(res, sim, dec2) # XER.ca
31 yield from ALUHelpers.get_sim_xer_so(res, sim, dec2) # XER.so
32
33 print("alu get_cu_inputs", res)
34
35 return res
36
37
38 def set_alu_inputs(alu, dec2, sim):
39 # TODO: see https://bugs.libre-soc.org/show_bug.cgi?id=305#c43
40 # detect the immediate here (with m.If(self.i.ctx.op.imm_data.imm_ok))
41 # and place it into data_i.b
42
43 inp = yield from get_cu_inputs(dec2, sim)
44 yield from ALUHelpers.set_int_ra(alu, dec2, inp)
45 yield from ALUHelpers.set_int_rb(alu, dec2, inp)
46
47 yield from ALUHelpers.set_xer_ca(alu, dec2, inp)
48 yield from ALUHelpers.set_xer_so(alu, dec2, inp)
49
50
51 class ALUTestCase(TestAccumulatorBase):
52
53 def case_1_regression(self):
54 lst = [f"extsw 3, 1"]
55 initial_regs = [0] * 32
56 initial_regs[1] = 0xb6a1fc6c8576af91
57 self.add_case(Program(lst, bigendian), initial_regs)
58 lst = [f"subf 3, 1, 2"]
59 initial_regs = [0] * 32
60 initial_regs[1] = 0x3d7f3f7ca24bac7b
61 initial_regs[2] = 0xf6b2ac5e13ee15c2
62 self.add_case(Program(lst, bigendian), initial_regs)
63 lst = [f"subf 3, 1, 2"]
64 initial_regs = [0] * 32
65 initial_regs[1] = 0x833652d96c7c0058
66 initial_regs[2] = 0x1c27ecff8a086c1a
67 self.add_case(Program(lst, bigendian), initial_regs)
68 lst = [f"extsb 3, 1"]
69 initial_regs = [0] * 32
70 initial_regs[1] = 0x7f9497aaff900ea0
71 self.add_case(Program(lst, bigendian), initial_regs)
72 lst = [f"add. 3, 1, 2"]
73 initial_regs = [0] * 32
74 initial_regs[1] = 0xc523e996a8ff6215
75 initial_regs[2] = 0xe1e5b9cc9864c4a8
76 self.add_case(Program(lst, bigendian), initial_regs)
77 lst = [f"add 3, 1, 2"]
78 initial_regs = [0] * 32
79 initial_regs[1] = 0x2e08ae202742baf8
80 initial_regs[2] = 0x86c43ece9efe5baa
81 self.add_case(Program(lst, bigendian), initial_regs)
82
83 def case_rand(self):
84 insns = ["add", "add.", "subf"]
85 for i in range(40):
86 choice = random.choice(insns)
87 lst = [f"{choice} 3, 1, 2"]
88 initial_regs = [0] * 32
89 initial_regs[1] = random.randint(0, (1 << 64)-1)
90 initial_regs[2] = random.randint(0, (1 << 64)-1)
91 self.add_case(Program(lst, bigendian), initial_regs)
92
93 def case_addme_ca_0(self):
94 insns = ["addme", "addme.", "addmeo", "addmeo."]
95 for choice in insns:
96 lst = [f"{choice} 6, 16"]
97 for value in [0x7ffffffff,
98 0xffff80000]:
99 initial_regs = [0] * 32
100 initial_regs[16] = value
101 initial_sprs = {}
102 xer = SelectableInt(0, 64)
103 xer[XER_bits['CA']] = 0
104 initial_sprs[special_sprs['XER']] = xer
105 self.add_case(Program(lst, bigendian),
106 initial_regs, initial_sprs)
107
108 def case_addme_ca_1(self):
109 insns = ["addme", "addme.", "addmeo", "addmeo."]
110 for choice in insns:
111 lst = [f"{choice} 6, 16"]
112 for value in [0x7ffffffff, # fails, bug #476
113 0xffff80000]:
114 initial_regs = [0] * 32
115 initial_regs[16] = value
116 initial_sprs = {}
117 xer = SelectableInt(0, 64)
118 xer[XER_bits['CA']] = 1
119 initial_sprs[special_sprs['XER']] = xer
120 self.add_case(Program(lst, bigendian),
121 initial_regs, initial_sprs)
122
123 def case_addme_ca_so_3(self):
124 """bug where SO does not get passed through to CR0
125 """
126 lst = ["addme. 6, 16"]
127 initial_regs = [0] * 32
128 initial_regs[16] = 0x7ffffffff
129 initial_sprs = {}
130 xer = SelectableInt(0, 64)
131 xer[XER_bits['CA']] = 1
132 xer[XER_bits['SO']] = 1
133 initial_sprs[special_sprs['XER']] = xer
134 self.add_case(Program(lst, bigendian),
135 initial_regs, initial_sprs)
136
137 def case_addze(self):
138 insns = ["addze", "addze.", "addzeo", "addzeo."]
139 for choice in insns:
140 lst = [f"{choice} 6, 16"]
141 initial_regs = [0] * 32
142 initial_regs[16] = 0x00ff00ff00ff0080
143 self.add_case(Program(lst, bigendian), initial_regs)
144
145 self.add_case(Program(lst, bigendian), initial_regs)
146
147 def case_addis_nonzero_r0_regression(self):
148 lst = [f"addis 3, 0, 1"]
149 print(lst)
150 initial_regs = [0] * 32
151 initial_regs[0] = 5
152 self.add_case(Program(lst, bigendian), initial_regs)
153
154 def case_addis_nonzero_r0(self):
155 for i in range(10):
156 imm = random.randint(-(1 << 15), (1 << 15)-1)
157 lst = [f"addis 3, 0, {imm}"]
158 print(lst)
159 initial_regs = [0] * 32
160 initial_regs[0] = random.randint(0, (1 << 64)-1)
161 self.add_case(Program(lst, bigendian), initial_regs)
162
163 def case_rand_imm(self):
164 insns = ["addi", "addis", "subfic"]
165 for i in range(10):
166 choice = random.choice(insns)
167 imm = random.randint(-(1 << 15), (1 << 15)-1)
168 lst = [f"{choice} 3, 1, {imm}"]
169 print(lst)
170 initial_regs = [0] * 32
171 initial_regs[1] = random.randint(0, (1 << 64)-1)
172 self.add_case(Program(lst, bigendian), initial_regs)
173
174 def case_0_adde(self):
175 lst = ["adde. 5, 6, 7"]
176 for i in range(10):
177 initial_regs = [0] * 32
178 initial_regs[6] = random.randint(0, (1 << 64)-1)
179 initial_regs[7] = random.randint(0, (1 << 64)-1)
180 initial_sprs = {}
181 xer = SelectableInt(0, 64)
182 xer[XER_bits['CA']] = 1
183 initial_sprs[special_sprs['XER']] = xer
184 self.add_case(Program(lst, bigendian),
185 initial_regs, initial_sprs)
186
187 def case_cmp(self):
188 lst = ["subf. 1, 6, 7",
189 "cmp cr2, 1, 6, 7"]
190 initial_regs = [0] * 32
191 initial_regs[6] = 0x10
192 initial_regs[7] = 0x05
193 self.add_case(Program(lst, bigendian), initial_regs, {})
194
195 def case_cmp2(self):
196 lst = ["cmp cr2, 0, 2, 3"]
197 initial_regs = [0] * 32
198 initial_regs[2] = 0xffffffffaaaaaaaa
199 initial_regs[3] = 0x00000000aaaaaaaa
200 self.add_case(Program(lst, bigendian), initial_regs, {})
201
202 lst = ["cmp cr2, 0, 4, 5"]
203 initial_regs = [0] * 32
204 initial_regs[4] = 0x00000000aaaaaaaa
205 initial_regs[5] = 0xffffffffaaaaaaaa
206 self.add_case(Program(lst, bigendian), initial_regs, {})
207
208 def case_cmp3(self):
209 lst = ["cmp cr2, 1, 2, 3"]
210 initial_regs = [0] * 32
211 initial_regs[2] = 0xffffffffaaaaaaaa
212 initial_regs[3] = 0x00000000aaaaaaaa
213 self.add_case(Program(lst, bigendian), initial_regs, {})
214
215 lst = ["cmp cr2, 1, 4, 5"]
216 initial_regs = [0] * 32
217 initial_regs[4] = 0x00000000aaaaaaaa
218 initial_regs[5] = 0xffffffffaaaaaaaa
219 self.add_case(Program(lst, bigendian), initial_regs, {})
220
221 def case_cmpl_microwatt_0(self):
222 """microwatt 1.bin:
223 115b8: 40 50 d1 7c .long 0x7cd15040 # cmpl 6, 0, 17, 10
224 register_file.vhdl: Reading GPR 11 000000000001C026
225 register_file.vhdl: Reading GPR 0A FEDF3FFF0001C025
226 cr_file.vhdl: Reading CR 35055050
227 cr_file.vhdl: Writing 35055058 to CR mask 01 35055058
228 """
229
230 lst = ["cmpl 6, 0, 17, 10"]
231 initial_regs = [0] * 32
232 initial_regs[0x11] = 0x1c026
233 initial_regs[0xa] = 0xFEDF3FFF0001C025
234 XER = 0xe00c0000
235 CR = 0x35055050
236
237 self.add_case(Program(lst, bigendian), initial_regs,
238 initial_sprs = {'XER': XER},
239 initial_cr = CR)
240
241 def case_cmpl_microwatt_0_disasm(self):
242 """microwatt 1.bin: disassembled version
243 115b8: 40 50 d1 7c .long 0x7cd15040 # cmpl 6, 0, 17, 10
244 register_file.vhdl: Reading GPR 11 000000000001C026
245 register_file.vhdl: Reading GPR 0A FEDF3FFF0001C025
246 cr_file.vhdl: Reading CR 35055050
247 cr_file.vhdl: Writing 35055058 to CR mask 01 35055058
248 """
249
250 dis = ["cmpl 6, 0, 17, 10"]
251 lst = bytes([0x40, 0x50, 0xd1, 0x7c]) # 0x7cd15040
252 initial_regs = [0] * 32
253 initial_regs[0x11] = 0x1c026
254 initial_regs[0xa] = 0xFEDF3FFF0001C025
255 XER = 0xe00c0000
256 CR = 0x35055050
257
258 p = Program(lst, bigendian)
259 p.assembly = '\n'.join(dis)+'\n'
260 self.add_case(p, initial_regs,
261 initial_sprs = {'XER': XER},
262 initial_cr = CR)
263
264 def case_cmplw_microwatt_1(self):
265 """microwatt 1.bin:
266 10d94: 40 20 96 7c cmplw cr1,r22,r4
267 gpr: 00000000ffff6dc1 <- r4
268 gpr: 0000000000000000 <- r22
269 """
270
271 lst = ["cmpl 1, 0, 22, 4"]
272 initial_regs = [0] * 32
273 initial_regs[4] = 0xffff6dc1
274 initial_regs[22] = 0
275 XER = 0xe00c0000
276 CR = 0x50759999
277
278 self.add_case(Program(lst, bigendian), initial_regs,
279 initial_sprs = {'XER': XER},
280 initial_cr = CR)
281
282 def case_cmpli_microwatt(self):
283 """microwatt 1.bin: cmpli
284 123ac: 9c 79 8d 2a cmpli cr5,0,r13,31132
285 gpr: 00000000301fc7a7 <- r13
286 cr : 0000000090215393
287 xer: so 1 ca 0 32 0 ov 0 32 0
288
289 """
290
291 lst = ["cmpli 5, 0, 13, 31132"]
292 initial_regs = [0] * 32
293 initial_regs[13] = 0x301fc7a7
294 XER = 0xe00c0000
295 CR = 0x90215393
296
297 self.add_case(Program(lst, bigendian), initial_regs,
298 initial_sprs = {'XER': XER},
299 initial_cr = CR)
300
301 def case_extsb(self):
302 insns = ["extsb", "extsh", "extsw"]
303 for i in range(10):
304 choice = random.choice(insns)
305 lst = [f"{choice} 3, 1"]
306 print(lst)
307 initial_regs = [0] * 32
308 initial_regs[1] = random.randint(0, (1 << 64)-1)
309 self.add_case(Program(lst, bigendian), initial_regs)
310
311 def case_cmpeqb(self):
312 lst = ["cmpeqb cr1, 1, 2"]
313 for i in range(20):
314 initial_regs = [0] * 32
315 initial_regs[1] = i
316 initial_regs[2] = 0x0001030507090b0f
317 self.add_case(Program(lst, bigendian), initial_regs, {})
318
319 def case_ilang(self):
320 pspec = ALUPipeSpec(id_wid=2)
321 alu = ALUBasePipe(pspec)
322 vl = rtlil.convert(alu, ports=alu.ports())
323 with open("alu_pipeline.il", "w") as f:
324 f.write(vl)
325
326
327 class TestRunner(unittest.TestCase):
328
329 def execute(self, alu,instruction, pdecode2, test):
330 program = test.program
331 sim = ISA(pdecode2, test.regs, test.sprs, test.cr,
332 test.mem, test.msr,
333 bigendian=bigendian)
334 gen = program.generate_instructions()
335 instructions = list(zip(gen, program.assembly.splitlines()))
336
337 index = sim.pc.CIA.value//4
338 while index < len(instructions):
339 ins, code = instructions[index]
340
341 print("instruction: 0x{:X}".format(ins & 0xffffffff))
342 print(code)
343 if 'XER' in sim.spr:
344 so = 1 if sim.spr['XER'][XER_bits['SO']] else 0
345 ov = 1 if sim.spr['XER'][XER_bits['OV']] else 0
346 ov32 = 1 if sim.spr['XER'][XER_bits['OV32']] else 0
347 print("before: so/ov/32", so, ov, ov32)
348
349 # ask the decoder to decode this binary data (endian'd)
350 # little / big?
351 yield pdecode2.dec.bigendian.eq(bigendian)
352 yield instruction.eq(ins) # raw binary instr.
353 yield Settle()
354 fn_unit = yield pdecode2.e.do.fn_unit
355 asmcode = yield pdecode2.e.asmcode
356 dec_asmcode = yield pdecode2.dec.op.asmcode
357 print ("asmcode", asmcode, dec_asmcode)
358 self.assertEqual(fn_unit, Function.ALU.value)
359 yield from set_alu_inputs(alu, pdecode2, sim)
360
361 # set valid for one cycle, propagate through pipeline...
362 yield alu.p.valid_i.eq(1)
363 yield
364 yield alu.p.valid_i.eq(0)
365
366 opname = code.split(' ')[0]
367 yield from sim.call(opname)
368 index = sim.pc.CIA.value//4
369
370 vld = yield alu.n.valid_o
371 while not vld:
372 yield
373 vld = yield alu.n.valid_o
374 yield
375
376 yield from self.check_alu_outputs(alu, pdecode2, sim, code)
377 yield Settle()
378
379 def test_it(self):
380 test_data = ALUTestCase().test_data
381 m = Module()
382 comb = m.d.comb
383 instruction = Signal(32)
384
385 fn_name = "ALU"
386 opkls = ALUPipeSpec.opsubsetkls
387
388 pdecode = create_pdecode()
389 m.submodules.pdecode2 = pdecode2 = PowerDecode2(pdecode, opkls, fn_name)
390 pdecode = pdecode2.dec
391
392 pspec = ALUPipeSpec(id_wid=2)
393 m.submodules.alu = alu = ALUBasePipe(pspec)
394
395 comb += alu.p.data_i.ctx.op.eq_from_execute1(pdecode2.do)
396 comb += alu.n.ready_i.eq(1)
397 comb += pdecode2.dec.raw_opcode_in.eq(instruction)
398 sim = Simulator(m)
399
400 sim.add_clock(1e-6)
401
402 def process():
403 for test in test_data:
404 print(test.name)
405 program = test.program
406 with self.subTest(test.name):
407 yield from self.execute(alu, instruction, pdecode2, test)
408
409 sim.add_sync_process(process)
410 with sim.write_vcd("alu_simulator.vcd"):
411 sim.run()
412
413 def check_alu_outputs(self, alu, dec2, sim, code):
414
415 rc = yield dec2.e.do.rc.rc
416 cridx_ok = yield dec2.e.write_cr.ok
417 cridx = yield dec2.e.write_cr.data
418
419 print("check extra output", repr(code), cridx_ok, cridx)
420 if rc:
421 self.assertEqual(cridx, 0, code)
422
423 oe = yield dec2.e.do.oe.oe
424 oe_ok = yield dec2.e.do.oe.ok
425 if not oe or not oe_ok:
426 # if OE not enabled, XER SO and OV must correspondingly be false
427 so_ok = yield alu.n.data_o.xer_so.ok
428 ov_ok = yield alu.n.data_o.xer_ov.ok
429 self.assertEqual(so_ok, False, code)
430 self.assertEqual(ov_ok, False, code)
431
432 sim_o = {}
433 res = {}
434
435 yield from ALUHelpers.get_cr_a(res, alu, dec2)
436 yield from ALUHelpers.get_xer_ov(res, alu, dec2)
437 yield from ALUHelpers.get_xer_ca(res, alu, dec2)
438 yield from ALUHelpers.get_int_o(res, alu, dec2)
439 yield from ALUHelpers.get_xer_so(res, alu, dec2)
440
441 yield from ALUHelpers.get_sim_int_o(sim_o, sim, dec2)
442 yield from ALUHelpers.get_wr_sim_cr_a(sim_o, sim, dec2)
443 yield from ALUHelpers.get_sim_xer_ov(sim_o, sim, dec2)
444 yield from ALUHelpers.get_wr_sim_xer_ca(sim_o, sim, dec2)
445 yield from ALUHelpers.get_sim_xer_so(sim_o, sim, dec2)
446
447 ALUHelpers.check_cr_a(self, res, sim_o, "CR%d %s" % (cridx, code))
448 ALUHelpers.check_xer_ov(self, res, sim_o, code)
449 ALUHelpers.check_xer_ca(self, res, sim_o, code)
450 ALUHelpers.check_int_o(self, res, sim_o, code)
451 ALUHelpers.check_xer_so(self, res, sim_o, code)
452
453
454 if __name__ == "__main__":
455 unittest.main()