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