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