create a register cache for qemu machine interface, very slow
[openpower-isa.git] / src / openpower / simulator / test_sim.py
1 import unittest
2 from nmigen import Module
3 from nmigen.back.pysim 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 run_tst_program(self, prog, initial_regs=None, initial_sprs=None,
457 initial_mem=None):
458 initial_regs = [0] * 32
459 tc = TestCase(prog, self.test_name, initial_regs, initial_sprs, 0,
460 initial_mem, 0)
461 self.test_data.append(tc)
462
463
464 class DecoderBase:
465
466 def run_tst(self, generator, initial_mem=None, initial_pc=0):
467 m = Module()
468 comb = m.d.comb
469
470 gen = list(generator.generate_instructions())
471 insn_code = generator.assembly.splitlines()
472 instructions = list(zip(gen, insn_code))
473
474 pdecode = create_pdecode()
475 m.submodules.pdecode2 = pdecode2 = PowerDecode2(pdecode)
476
477 # place program at requested address
478 gen = (initial_pc, gen)
479
480 simulator = ISA(pdecode2, [0] * 32, {}, 0, initial_mem, 0,
481 initial_insns=gen, respect_pc=True,
482 disassembly=insn_code,
483 initial_pc=initial_pc,
484 bigendian=bigendian)
485
486 sim = Simulator(m)
487
488 def process():
489 # yield pdecode2.dec.bigendian.eq(bigendian)
490 yield Settle()
491
492 while True:
493 try:
494 yield from simulator.setup_one()
495 except KeyError: # indicates instruction not in imem: stop
496 break
497 yield Settle()
498 yield from simulator.execute_one()
499 yield Settle()
500
501 sim.add_process(process)
502 with sim.write_vcd("pdecode_simulator.vcd"):
503 sim.run()
504
505 return simulator
506
507 def run_tst_program(self, prog, reglist, initial_mem=None,
508 extra_break_addr=None):
509 import sys
510 simulator = self.run_tst(prog, initial_mem=initial_mem,
511 initial_pc=0x20000000)
512 prog.reset()
513 with run_program(prog, initial_mem, extra_break_addr,
514 bigendian=bigendian) as q:
515 self.qemu_register_compare(simulator, q, reglist)
516 self.qemu_mem_compare(simulator, q, True)
517 print(simulator.gpr.dump())
518
519 def qemu_mem_compare(self, sim, qemu, check=True):
520 if False: # disable convenient large interesting debugging memory dump
521 addr = 0x0
522 qmemdump = qemu.get_mem(addr, 2048)
523 for i in range(len(qmemdump)):
524 s = hex(int(qmemdump[i]))
525 print("qemu mem %06x %s" % (addr+i*8, s))
526 for k, v in sim.mem.mem.items():
527 qmemdump = qemu.get_mem(k*8, 8)
528 s = hex(int(qmemdump[0]))[2:]
529 print("qemu mem %06x %16s" % (k*8, s))
530 for k, v in sim.mem.mem.items():
531 print("sim mem %06x %016x" % (k*8, v))
532 if not check:
533 return
534 for k, v in sim.mem.mem.items():
535 qmemdump = qemu.get_mem(k*8, 1)
536 self.assertEqual(int(qmemdump[0]), v)
537
538 def qemu_register_compare(self, sim, qemu, regs):
539 qpc, qxer, qcr = qemu.get_pc(), qemu.get_xer(), qemu.get_cr()
540 sim_cr = sim.cr.value
541 sim_pc = sim.pc.CIA.value
542 sim_xer = sim.spr['XER'].value
543 print("qemu pc", hex(qpc))
544 print("qemu cr", hex(qcr))
545 print("qemu xer", bin(qxer))
546 print("sim nia", hex(sim.pc.NIA.value))
547 print("sim pc", hex(sim.pc.CIA.value))
548 print("sim cr", hex(sim_cr))
549 print("sim xer", hex(sim_xer))
550 self.assertEqual(qpc, sim_pc)
551 for reg in regs:
552 qemu_val = qemu.get_gpr(reg)
553 sim_val = sim.gpr(reg).value
554 self.assertEqual(qemu_val, sim_val,
555 "expect %x got %x" % (qemu_val, sim_val))
556 self.assertEqual(qcr, sim_cr)
557
558
559 class DecoderTestCase(DecoderBase, GeneralTestCases):
560 pass
561
562
563 if __name__ == "__main__":
564 unittest.main()