add isel CR tests to run on qemu (confirmed working)
[soc.git] / src / soc / simulator / test_sim.py
1 from nmigen import Module, Signal
2 from nmigen.back.pysim import Simulator, Delay, Settle
3 from nmutil.formaltest import FHDLTestCase
4 import unittest
5 from soc.decoder.power_decoder import (create_pdecode)
6 from soc.decoder.power_enums import (Function, MicrOp,
7 In1Sel, In2Sel, In3Sel,
8 OutSel, RC, LdstLen, CryIn,
9 single_bit_flags, Form, SPR,
10 get_signal_name, get_csv)
11 from soc.decoder.power_decoder2 import (PowerDecode2)
12 from soc.simulator.program import Program
13 from soc.simulator.qemu import run_program
14 from soc.decoder.isa.all import ISA
15 from soc.fu.test.common import TestCase
16 from soc.config.endian import bigendian
17
18
19 class AttnTestCase(FHDLTestCase):
20 test_data = []
21
22 def __init__(self, name="general"):
23 super().__init__(name)
24 self.test_name = name
25
26 def test_0_attn(self):
27 """simple test of attn. program is 4 long: should halt at 2nd op
28 """
29 lst = ["addi 6, 0, 0x10",
30 "attn",
31 "subf. 1, 6, 7",
32 "cmp cr2, 1, 6, 7",
33 ]
34 with Program(lst, bigendian) as program:
35 self.run_tst_program(program, [1])
36
37 def run_tst_program(self, prog, initial_regs=None, initial_sprs=None,
38 initial_mem=None):
39 initial_regs = [0] * 32
40 tc = TestCase(prog, self.test_name, initial_regs, initial_sprs, 0,
41 initial_mem, 0)
42 self.test_data.append(tc)
43
44
45 class GeneralTestCases(FHDLTestCase):
46 test_data = []
47
48 def __init__(self, name="general"):
49 super().__init__(name)
50 self.test_name = name
51
52 def test_0_litex_bios_ctr_loop(self):
53 """
54 32a4: ff ff 63 38 addi r3,r3,-1
55 32a8: 20 00 63 78 clrldi r3,r3,32
56 32ac: 01 00 23 39 addi r9,r3,1
57 32b0: a6 03 29 7d mtctr r9
58 32b4: 00 00 00 60 nop
59 32b8: fc ff 00 42 bdnz 32b4 <cdelay+0x10>
60 32bc: 20 00 80 4e blr
61
62 notes on converting pseudo-assembler to actual:
63
64 * bdnz target (equivalent to: bc 16,0,target)
65 * Clear left immediate clrldi ra,rs,n (n < 64) rldicl ra,rs,0,n
66 * CTR mtctr Rx mtspr 9,Rx
67 """
68 pass
69
70 @unittest.skip("disable")
71 def test_0_litex_bios_cmp(self):
72 """litex bios cmp test
73 """
74 lst = [ "addis 26, 0, 21845",
75 "ori 26, 26, 21845",
76 "addi 5, 26, 0",
77 "rldicr 5,5,32,31",
78 "addi 5, 26, 0",
79 "cmp 0, 0, 5, 26",
80 "bc 12, 2, 28",
81 "addis 6, 0, 1",
82 "addis 7, 0, 1",
83 ]
84 with Program(lst, bigendian) as program:
85 self.run_tst_program(program, [5,6,7,26], initial_mem={})
86
87 @unittest.skip("disable")
88 def test_0_litex_bios_r1(self):
89 """litex bios IMM64 macro test
90 """
91 lst = [ "addis 1,0,0",
92 "ori 1,1,0",
93 "rldicr 1,1,32,31",
94 "oris 1,1,256",
95 "ori 1,1,3832",
96 ]
97 with Program(lst, bigendian) as program:
98 self.run_tst_program(program, [1], initial_mem={})
99
100 @unittest.skip("disable")
101 def test_0_litex_trampoline(self):
102 lst = ["tdi 0,0,0x48",
103 "b 0x28",
104 "mfmsr r11",
105 "bcl 20,31,4",
106 "mflr r10",
107 "addi r10,r10,20",
108 "mthsrr0 r10",
109 "mthsrr1 r11",
110 "hrfid",
111 ]
112 with Program(lst, bigendian) as program:
113 self.run_tst_program(program, [], initial_mem={})
114
115 @unittest.skip("disable")
116 def test_0_cmp(self):
117 lst = ["addi 6, 0, 0x10",
118 "addi 7, 0, 0x05",
119 "subf. 1, 6, 7",
120 "cmp cr2, 1, 6, 7",
121 ]
122 with Program(lst, bigendian) as program:
123 self.run_tst_program(program, [1])
124
125 @unittest.skip("disable")
126 def test_example(self):
127 lst = ["addi 1, 0, 0x5678",
128 "addi 2, 0, 0x1234",
129 "add 3, 1, 2",
130 "and 4, 1, 2"]
131 with Program(lst, bigendian) as program:
132 self.run_tst_program(program, [1, 2, 3, 4])
133
134 @unittest.skip("disable")
135 def test_ldst(self):
136 lst = ["addi 1, 0, 0x5678",
137 "addi 2, 0, 0x1234",
138 "stw 1, 0(2)",
139 "lwz 3, 0(2)"
140 ]
141 initial_mem = {0x1230: (0x5432123412345678, 8),
142 0x1238: (0xabcdef0187654321, 8),
143 }
144 with Program(lst, bigendian) as program:
145 self.run_tst_program(program,
146 [1, 2, 3],
147 initial_mem)
148
149 @unittest.skip("disable")
150 def test_ldst_update(self):
151 lst = ["addi 1, 0, 0x5678",
152 "addi 2, 0, 0x1234",
153 "stwu 1, 0(2)",
154 "lwz 3, 0(2)"
155 ]
156 initial_mem = {0x1230: (0x5432123412345678, 8),
157 0x1238: (0xabcdef0187654321, 8),
158 }
159 with Program(lst, bigendian) as program:
160 self.run_tst_program(program,
161 [1, 2, 3],
162 initial_mem)
163
164 @unittest.skip("disable")
165 def test_ld_rev_ext(self):
166 lst = ["addi 1, 0, 0x5678",
167 "addi 2, 0, 0x1234",
168 "addi 4, 0, 0x40",
169 "stw 1, 0x40(2)",
170 "lwbrx 3, 4, 2"]
171 with Program(lst, bigendian) as program:
172 self.run_tst_program(program, [1, 2, 3])
173
174 @unittest.skip("disable")
175 def test_st_rev_ext(self):
176 lst = ["addi 1, 0, 0x5678",
177 "addi 2, 0, 0x1234",
178 "addi 4, 0, 0x40",
179 "stwbrx 1, 4, 2",
180 "lwzx 3, 4, 2"]
181 with Program(lst, bigendian) as program:
182 self.run_tst_program(program, [1, 2, 3])
183
184 @unittest.skip("disable")
185 def test_ldst_extended(self):
186 lst = ["addi 1, 0, 0x5678",
187 "addi 2, 0, 0x1234",
188 "addi 4, 0, 0x40",
189 "stw 1, 0x40(2)",
190 "lwzx 3, 4, 2"]
191 with Program(lst, bigendian) as program:
192 self.run_tst_program(program, [1, 2, 3])
193
194 @unittest.skip("disable")
195 def test_0_ldst_widths(self):
196 lst = ["addis 1, 0, 0xdead",
197 "ori 1, 1, 0xbeef",
198 "addi 2, 0, 0x1000",
199 "std 1, 0(2)",
200 "lbz 1, 5(2)",
201 "lhz 3, 4(2)",
202 "lwz 4, 4(2)",
203 "addi 5, 0, 0x12",
204 "stb 5, 5(2)",
205 "ld 5, 0(2)"]
206 with Program(lst, bigendian) as program:
207 self.run_tst_program(program, [1, 2, 3, 4, 5])
208
209 @unittest.skip("disable")
210 def test_sub(self):
211 lst = ["addi 1, 0, 0x1234",
212 "addi 2, 0, 0x5678",
213 "subf 3, 1, 2",
214 "subfic 4, 1, 0x1337",
215 "neg 5, 1"]
216 with Program(lst, bigendian) as program:
217 self.run_tst_program(program, [1, 2, 3, 4, 5])
218
219 @unittest.skip("disable")
220 def test_add_with_carry(self):
221 lst = ["addi 1, 0, 5",
222 "neg 1, 1",
223 "addi 2, 0, 7",
224 "neg 2, 2",
225 "addc 3, 2, 1",
226 "addi 3, 3, 1"
227 ]
228 with Program(lst, bigendian) as program:
229 self.run_tst_program(program, [1, 2, 3])
230
231 @unittest.skip("disable")
232 def test_addis(self):
233 lst = ["addi 1, 0, 0x0FFF",
234 "addis 1, 1, 0x0F"
235 ]
236 with Program(lst, bigendian) as program:
237 self.run_tst_program(program, [1])
238
239 @unittest.skip("broken")
240 def test_mulli(self):
241 lst = ["addi 1, 0, 3",
242 "mulli 1, 1, 2"
243 ]
244 with Program(lst, bigendian) as program:
245 self.run_tst_program(program, [1])
246
247 def test_isel_1(self):
248 lst = ["addi 1, 0, 0x1004",
249 "addi 2, 0, 0x1008",
250 "addi 3, 0, 0x01ee",
251 "mtcrf 0b1111111, 3",
252 "isel 4, 1, 2, 2"
253 ]
254 initial_regs = [0] * 32
255 initial_regs[1] = 0x1004
256 initial_regs[2] = 0x1008
257 initial_regs[3] = 0x00ee
258 with Program(lst, bigendian) as program:
259 self.run_tst_program(program, [3, 4])
260
261 def test_isel_2(self):
262 lst = ["addi 1, 0, 0x1004",
263 "addi 2, 0, 0x1008",
264 "addi 3, 0, 0x01ee",
265 "mtcrf 0b1111111, 3",
266 "isel 4, 1, 2, 30"
267 ]
268 initial_regs = [0] * 32
269 initial_regs[1] = 0x1004
270 initial_regs[2] = 0x1008
271 initial_regs[3] = 0x00ee
272 with Program(lst, bigendian) as program:
273 self.run_tst_program(program, [3, 4])
274
275 @unittest.skip("disable")
276 def test_2_load_store(self):
277 lst = ["addi 1, 0, 0x1004",
278 "addi 2, 0, 0x1008",
279 "addi 3, 0, 0x00ee",
280 "stb 3, 1(2)",
281 "lbz 4, 1(2)",
282 ]
283 initial_regs = [0] * 32
284 initial_regs[1] = 0x1004
285 initial_regs[2] = 0x1008
286 initial_regs[3] = 0x00ee
287 initial_mem = {0x1000: (0x5432123412345678, 8),
288 0x1008: (0xabcdef0187654321, 8),
289 0x1020: (0x1828384822324252, 8),
290 }
291 with Program(lst, bigendian) as program:
292 self.run_tst_program(program, [3, 4], initial_mem)
293
294 @unittest.skip("disable")
295 def test_3_load_store(self):
296 lst = ["addi 1, 0, 0x1004",
297 "addi 2, 0, 0x1002",
298 "addi 3, 0, 0x15eb",
299 "sth 4, 0(2)",
300 "lhz 4, 0(2)"]
301 initial_regs = [0] * 32
302 initial_regs[1] = 0x1004
303 initial_regs[2] = 0x1002
304 initial_regs[3] = 0x15eb
305 initial_mem = {0x1000: (0x5432123412345678, 8),
306 0x1008: (0xabcdef0187654321, 8),
307 0x1020: (0x1828384822324252, 8),
308 }
309 with Program(lst, bigendian) as program:
310 self.run_tst_program(program, [1, 2, 3, 4], initial_mem)
311
312 @unittest.skip("disable")
313 def test_nop(self):
314 lst = ["addi 1, 0, 0x1004",
315 "ori 0,0,0", # "preferred" form of nop
316 "addi 3, 0, 0x15eb",
317 ]
318 initial_regs = [0] * 32
319 with Program(lst, bigendian) as program:
320 self.run_tst_program(program, [1, 3])
321
322 @unittest.skip("disable")
323 def test_zero_illegal(self):
324 lst = bytes([0x10,0x00,0x20,0x39,
325 0x0,0x0,0x0,0x0,
326 0x0,0x0,0x0,0x0 ])
327 disassembly = ["addi 9, 0, 0x10",
328 "nop", # not quite
329 "nop"] # not quite
330 initial_regs = [0] * 32
331 with Program(lst, bigendian) as program:
332 program.assembly = '\n'.join(disassembly) + '\n' # XXX HACK!
333 self.run_tst_program(program, [1, 3])
334
335 @unittest.skip("disable")
336 def test_loop(self):
337 """in godbolt.org:
338 register unsigned long i asm ("r12");
339 void square(void) {
340 i = 5;
341 do {
342 i = i - 1;
343 } while (i != 0);
344 }
345 """
346 lst = ["addi 9, 0, 0x10", # i = 16
347 "addi 9,9,-1", # i = i - 1
348 "cmpi 0,1,9,12", # compare 9 to value 0, store in CR2
349 "bc 4,0,-8" # branch if CR2 "test was != 0"
350 ]
351 with Program(lst, bigendian) as program:
352 self.run_tst_program(program, [9], initial_mem={})
353
354 @unittest.skip("disable")
355 def test_30_addis(self):
356 lst = [ # "addi 0, 0, 5",
357 "addis 12, 0, 0",
358 ]
359 with Program(lst, bigendian) as program:
360 self.run_tst_program(program, [12])
361
362 @unittest.skip("disable")
363 def test_31_addis(self):
364 """tests for zero not in register zero
365 """
366 lst = [ "rldicr 0, 0, 32, 31",
367 "oris 0, 0, 32767",
368 "ori 0, 0, 65535",
369 "addis 1, 0, 1",
370 "ori 1, 1, 515",
371 "rldicr 1, 1, 32, 31",
372 "oris 1, 1, 1029",
373 "ori 1, 1, 1543",
374 "addis 2, 0, -1",
375 ]
376 with Program(lst, bigendian) as program:
377 self.run_tst_program(program, [0, 1, 2])
378
379 def run_tst_program(self, prog, initial_regs=None, initial_sprs=None,
380 initial_mem=None):
381 initial_regs = [0] * 32
382 tc = TestCase(prog, self.test_name, initial_regs, initial_sprs, 0,
383 initial_mem, 0)
384 self.test_data.append(tc)
385
386
387 class DecoderBase:
388
389 def run_tst(self, generator, initial_mem=None, initial_pc=0):
390 m = Module()
391 comb = m.d.comb
392
393 gen = list(generator.generate_instructions())
394 insn_code = generator.assembly.splitlines()
395 instructions = list(zip(gen, insn_code))
396
397 pdecode = create_pdecode()
398 m.submodules.pdecode2 = pdecode2 = PowerDecode2(pdecode)
399
400 # place program at requested address
401 gen = (initial_pc, gen)
402
403 simulator = ISA(pdecode2, [0] * 32, {}, 0, initial_mem, 0,
404 initial_insns=gen, respect_pc=True,
405 disassembly=insn_code,
406 initial_pc=initial_pc,
407 bigendian=bigendian)
408
409 sim = Simulator(m)
410
411 def process():
412 # yield pdecode2.dec.bigendian.eq(bigendian)
413 yield Settle()
414
415 while True:
416 try:
417 yield from simulator.setup_one()
418 except KeyError: # indicates instruction not in imem: stop
419 break
420 yield Settle()
421 yield from simulator.execute_one()
422 yield Settle()
423
424 sim.add_process(process)
425 with sim.write_vcd("pdecode_simulator.vcd"):
426 sim.run()
427
428 return simulator
429
430 def run_tst_program(self, prog, reglist, initial_mem=None,
431 extra_break_addr=None):
432 import sys
433 simulator = self.run_tst(prog, initial_mem=initial_mem,
434 initial_pc=0x20000000)
435 prog.reset()
436 with run_program(prog, initial_mem, extra_break_addr,
437 bigendian=bigendian) as q:
438 self.qemu_register_compare(simulator, q, reglist)
439 self.qemu_mem_compare(simulator, q, True)
440 print(simulator.gpr.dump())
441
442 def qemu_mem_compare(self, sim, qemu, check=True):
443 if False: # disable convenient large interesting debugging memory dump
444 addr = 0x0
445 qmemdump = qemu.get_mem(addr, 2048)
446 for i in range(len(qmemdump)):
447 s = hex(int(qmemdump[i]))
448 print("qemu mem %06x %s" % (addr+i*8, s))
449 for k, v in sim.mem.mem.items():
450 qmemdump = qemu.get_mem(k*8, 8)
451 s = hex(int(qmemdump[0]))[2:]
452 print("qemu mem %06x %16s" % (k*8, s))
453 for k, v in sim.mem.mem.items():
454 print("sim mem %06x %016x" % (k*8, v))
455 if not check:
456 return
457 for k, v in sim.mem.mem.items():
458 qmemdump = qemu.get_mem(k*8, 1)
459 self.assertEqual(int(qmemdump[0]), v)
460
461 def qemu_register_compare(self, sim, qemu, regs):
462 qpc, qxer, qcr = qemu.get_pc(), qemu.get_xer(), qemu.get_cr()
463 sim_cr = sim.cr.get_range().value
464 sim_pc = sim.pc.CIA.value
465 sim_xer = sim.spr['XER'].value
466 print("qemu pc", hex(qpc))
467 print("qemu cr", hex(qcr))
468 print("qemu xer", bin(qxer))
469 print("sim nia", hex(sim.pc.NIA.value))
470 print("sim pc", hex(sim.pc.CIA.value))
471 print("sim cr", hex(sim_cr))
472 print("sim xer", hex(sim_xer))
473 self.assertEqual(qpc, sim_pc)
474 for reg in regs:
475 qemu_val = qemu.get_register(reg)
476 sim_val = sim.gpr(reg).value
477 self.assertEqual(qemu_val, sim_val,
478 "expect %x got %x" % (qemu_val, sim_val))
479 self.assertEqual(qcr, sim_cr)
480
481
482 class DecoderTestCase(DecoderBase, GeneralTestCases):
483 pass
484
485
486 if __name__ == "__main__":
487 unittest.main()