Merge branch 'master' of git.libre-soc.org:soc
[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 def test_0_litex_bios_cmp(self):
71 """litex bios cmp test
72 """
73 lst = [ "addis 26, 0, 21845",
74 "ori 26, 26, 21845",
75 "addi 5, 26, 0",
76 "rldicr 5,5,32,31",
77 "addi 5, 26, 0",
78 "cmp 0, 0, 5, 26",
79 "bc 12, 2, 28",
80 "addis 6, 0, 1",
81 "addis 7, 0, 1",
82 ]
83 with Program(lst, bigendian) as program:
84 self.run_tst_program(program, [5,6,7,26], initial_mem={})
85
86 @unittest.skip("disable")
87 def test_0_litex_bios_r1(self):
88 """litex bios IMM64 macro test
89 """
90 lst = [ "addis 1,0,0",
91 "ori 1,1,0",
92 "rldicr 1,1,32,31",
93 "oris 1,1,256",
94 "ori 1,1,3832",
95 ]
96 with Program(lst, bigendian) as program:
97 self.run_tst_program(program, [1], initial_mem={})
98
99 @unittest.skip("disable")
100 def test_0_litex_trampoline(self):
101 lst = ["tdi 0,0,0x48",
102 "b 0x28",
103 "mfmsr r11",
104 "bcl 20,31,4",
105 "mflr r10",
106 "addi r10,r10,20",
107 "mthsrr0 r10",
108 "mthsrr1 r11",
109 "hrfid",
110 ]
111 with Program(lst, bigendian) as program:
112 self.run_tst_program(program, [], initial_mem={})
113
114 @unittest.skip("disable")
115 def test_0_cmp(self):
116 lst = ["addi 6, 0, 0x10",
117 "addi 7, 0, 0x05",
118 "subf. 1, 6, 7",
119 "cmp cr2, 1, 6, 7",
120 ]
121 with Program(lst, bigendian) as program:
122 self.run_tst_program(program, [1])
123
124 @unittest.skip("disable")
125 def test_example(self):
126 lst = ["addi 1, 0, 0x5678",
127 "addi 2, 0, 0x1234",
128 "add 3, 1, 2",
129 "and 4, 1, 2"]
130 with Program(lst, bigendian) as program:
131 self.run_tst_program(program, [1, 2, 3, 4])
132
133 @unittest.skip("disable")
134 def test_ldst(self):
135 lst = ["addi 1, 0, 0x5678",
136 "addi 2, 0, 0x1234",
137 "stw 1, 0(2)",
138 "lwz 3, 0(2)"
139 ]
140 initial_mem = {0x1230: (0x5432123412345678, 8),
141 0x1238: (0xabcdef0187654321, 8),
142 }
143 with Program(lst, bigendian) as program:
144 self.run_tst_program(program,
145 [1, 2, 3],
146 initial_mem)
147
148 #@unittest.skip("disable")
149 def test_ldst_update(self):
150 lst = ["addi 1, 0, 0x5678",
151 "addi 2, 0, 0x1234",
152 "stwu 1, 0(2)",
153 "lwz 3, 0(2)"
154 ]
155 initial_mem = {0x1230: (0x5432123412345678, 8),
156 0x1238: (0xabcdef0187654321, 8),
157 }
158 with Program(lst, bigendian) as program:
159 self.run_tst_program(program,
160 [1, 2, 3],
161 initial_mem)
162
163 @unittest.skip("disable")
164 def test_ld_rev_ext(self):
165 lst = ["addi 1, 0, 0x5678",
166 "addi 2, 0, 0x1234",
167 "addi 4, 0, 0x40",
168 "stw 1, 0x40(2)",
169 "lwbrx 3, 4, 2"]
170 with Program(lst, bigendian) as program:
171 self.run_tst_program(program, [1, 2, 3])
172
173 #@unittest.skip("disable")
174 def test_st_rev_ext(self):
175 lst = ["addi 1, 0, 0x5678",
176 "addi 2, 0, 0x1234",
177 "addi 4, 0, 0x40",
178 "stwbrx 1, 4, 2",
179 "lwzx 3, 4, 2"]
180 with Program(lst, bigendian) as program:
181 self.run_tst_program(program, [1, 2, 3])
182
183 @unittest.skip("disable")
184 def test_ldst_extended(self):
185 lst = ["addi 1, 0, 0x5678",
186 "addi 2, 0, 0x1234",
187 "addi 4, 0, 0x40",
188 "stw 1, 0x40(2)",
189 "lwzx 3, 4, 2"]
190 with Program(lst, bigendian) as program:
191 self.run_tst_program(program, [1, 2, 3])
192
193 @unittest.skip("disable")
194 def test_0_ldst_widths(self):
195 lst = ["addis 1, 0, 0xdead",
196 "ori 1, 1, 0xbeef",
197 "addi 2, 0, 0x1000",
198 "std 1, 0(2)",
199 "lbz 1, 5(2)",
200 "lhz 3, 4(2)",
201 "lwz 4, 4(2)",
202 "addi 5, 0, 0x12",
203 "stb 5, 5(2)",
204 "ld 5, 0(2)"]
205 with Program(lst, bigendian) as program:
206 self.run_tst_program(program, [1, 2, 3, 4, 5])
207
208 @unittest.skip("disable")
209 def test_sub(self):
210 lst = ["addi 1, 0, 0x1234",
211 "addi 2, 0, 0x5678",
212 "subf 3, 1, 2",
213 "subfic 4, 1, 0x1337",
214 "neg 5, 1"]
215 with Program(lst, bigendian) as program:
216 self.run_tst_program(program, [1, 2, 3, 4, 5])
217
218 @unittest.skip("disable")
219 def test_add_with_carry(self):
220 lst = ["addi 1, 0, 5",
221 "neg 1, 1",
222 "addi 2, 0, 7",
223 "neg 2, 2",
224 "addc 3, 2, 1",
225 "addi 3, 3, 1"
226 ]
227 with Program(lst, bigendian) as program:
228 self.run_tst_program(program, [1, 2, 3])
229
230 @unittest.skip("disable")
231 def test_addis(self):
232 lst = ["addi 1, 0, 0x0FFF",
233 "addis 1, 1, 0x0F"
234 ]
235 with Program(lst, bigendian) as program:
236 self.run_tst_program(program, [1])
237
238 @unittest.skip("broken")
239 def test_mulli(self):
240 lst = ["addi 1, 0, 3",
241 "mulli 1, 1, 2"
242 ]
243 with Program(lst, bigendian) as program:
244 self.run_tst_program(program, [1])
245
246 @unittest.skip("disable")
247 def test_2_load_store(self):
248 lst = ["addi 1, 0, 0x1004",
249 "addi 2, 0, 0x1008",
250 "addi 3, 0, 0x00ee",
251 "stb 3, 1(2)",
252 "lbz 4, 1(2)",
253 ]
254 initial_regs = [0] * 32
255 initial_regs[1] = 0x1004
256 initial_regs[2] = 0x1008
257 initial_regs[3] = 0x00ee
258 initial_mem = {0x1000: (0x5432123412345678, 8),
259 0x1008: (0xabcdef0187654321, 8),
260 0x1020: (0x1828384822324252, 8),
261 }
262 with Program(lst, bigendian) as program:
263 self.run_tst_program(program, [3, 4], initial_mem)
264
265 @unittest.skip("disable")
266 def test_3_load_store(self):
267 lst = ["addi 1, 0, 0x1004",
268 "addi 2, 0, 0x1002",
269 "addi 3, 0, 0x15eb",
270 "sth 4, 0(2)",
271 "lhz 4, 0(2)"]
272 initial_regs = [0] * 32
273 initial_regs[1] = 0x1004
274 initial_regs[2] = 0x1002
275 initial_regs[3] = 0x15eb
276 initial_mem = {0x1000: (0x5432123412345678, 8),
277 0x1008: (0xabcdef0187654321, 8),
278 0x1020: (0x1828384822324252, 8),
279 }
280 with Program(lst, bigendian) as program:
281 self.run_tst_program(program, [1, 2, 3, 4], initial_mem)
282
283 @unittest.skip("disable")
284 def test_nop(self):
285 lst = ["addi 1, 0, 0x1004",
286 "ori 0,0,0", # "preferred" form of nop
287 "addi 3, 0, 0x15eb",
288 ]
289 initial_regs = [0] * 32
290 with Program(lst, bigendian) as program:
291 self.run_tst_program(program, [1, 3])
292
293 @unittest.skip("disable")
294 def test_zero_illegal(self):
295 lst = bytes([0x10,0x00,0x20,0x39,
296 0x0,0x0,0x0,0x0,
297 0x0,0x0,0x0,0x0 ])
298 disassembly = ["addi 9, 0, 0x10",
299 "nop", # not quite
300 "nop"] # not quite
301 initial_regs = [0] * 32
302 with Program(lst, bigendian) as program:
303 program.assembly = '\n'.join(disassembly) + '\n' # XXX HACK!
304 self.run_tst_program(program, [1, 3])
305
306 @unittest.skip("disable")
307 def test_loop(self):
308 """in godbolt.org:
309 register unsigned long i asm ("r12");
310 void square(void) {
311 i = 5;
312 do {
313 i = i - 1;
314 } while (i != 0);
315 }
316 """
317 lst = ["addi 9, 0, 0x10", # i = 16
318 "addi 9,9,-1", # i = i - 1
319 "cmpi 0,1,9,12", # compare 9 to value 0, store in CR2
320 "bc 4,0,-8" # branch if CR2 "test was != 0"
321 ]
322 with Program(lst, bigendian) as program:
323 self.run_tst_program(program, [9], initial_mem={})
324
325 @unittest.skip("disable")
326 def test_30_addis(self):
327 lst = [ # "addi 0, 0, 5",
328 "addis 12, 0, 0",
329 ]
330 with Program(lst, bigendian) as program:
331 self.run_tst_program(program, [12])
332
333 #@unittest.skip("disable")
334 def test_31_addis(self):
335 """tests for zero not in register zero
336 """
337 lst = [ "rldicr 0, 0, 32, 31",
338 "oris 0, 0, 32767",
339 "ori 0, 0, 65535",
340 "addis 1, 0, 1",
341 "ori 1, 1, 515",
342 "rldicr 1, 1, 32, 31",
343 "oris 1, 1, 1029",
344 "ori 1, 1, 1543",
345 "addis 2, 0, -1",
346 ]
347 with Program(lst, bigendian) as program:
348 self.run_tst_program(program, [0, 1, 2])
349
350 def run_tst_program(self, prog, initial_regs=None, initial_sprs=None,
351 initial_mem=None):
352 initial_regs = [0] * 32
353 tc = TestCase(prog, self.test_name, initial_regs, initial_sprs, 0,
354 initial_mem, 0)
355 self.test_data.append(tc)
356
357
358 class DecoderBase:
359
360 def run_tst(self, generator, initial_mem=None, initial_pc=0):
361 m = Module()
362 comb = m.d.comb
363
364 gen = list(generator.generate_instructions())
365 insn_code = generator.assembly.splitlines()
366 instructions = list(zip(gen, insn_code))
367
368 pdecode = create_pdecode()
369 m.submodules.pdecode2 = pdecode2 = PowerDecode2(pdecode)
370
371 # place program at requested address
372 gen = (initial_pc, gen)
373
374 simulator = ISA(pdecode2, [0] * 32, {}, 0, initial_mem, 0,
375 initial_insns=gen, respect_pc=True,
376 disassembly=insn_code,
377 initial_pc=initial_pc,
378 bigendian=bigendian)
379
380 sim = Simulator(m)
381
382 def process():
383 # yield pdecode2.dec.bigendian.eq(bigendian)
384 yield Settle()
385
386 while True:
387 try:
388 yield from simulator.setup_one()
389 except KeyError: # indicates instruction not in imem: stop
390 break
391 yield Settle()
392 yield from simulator.execute_one()
393 yield Settle()
394
395 sim.add_process(process)
396 with sim.write_vcd("pdecode_simulator.vcd"):
397 sim.run()
398
399 return simulator
400
401 def run_tst_program(self, prog, reglist, initial_mem=None,
402 extra_break_addr=None):
403 import sys
404 simulator = self.run_tst(prog, initial_mem=initial_mem,
405 initial_pc=0x20000000)
406 prog.reset()
407 with run_program(prog, initial_mem, extra_break_addr,
408 bigendian=bigendian) as q:
409 self.qemu_register_compare(simulator, q, reglist)
410 self.qemu_mem_compare(simulator, q, True)
411 print(simulator.gpr.dump())
412
413 def qemu_mem_compare(self, sim, qemu, check=True):
414 if False: # disable convenient large interesting debugging memory dump
415 addr = 0x0
416 qmemdump = qemu.get_mem(addr, 2048)
417 for i in range(len(qmemdump)):
418 s = hex(int(qmemdump[i]))
419 print("qemu mem %06x %s" % (addr+i*8, s))
420 for k, v in sim.mem.mem.items():
421 qmemdump = qemu.get_mem(k*8, 8)
422 s = hex(int(qmemdump[0]))[2:]
423 print("qemu mem %06x %16s" % (k*8, s))
424 for k, v in sim.mem.mem.items():
425 print("sim mem %06x %016x" % (k*8, v))
426 if not check:
427 return
428 for k, v in sim.mem.mem.items():
429 qmemdump = qemu.get_mem(k*8, 1)
430 self.assertEqual(int(qmemdump[0]), v)
431
432 def qemu_register_compare(self, sim, qemu, regs):
433 qpc, qxer, qcr = qemu.get_pc(), qemu.get_xer(), qemu.get_cr()
434 sim_cr = sim.cr.get_range().value
435 sim_pc = sim.pc.CIA.value
436 sim_xer = sim.spr['XER'].value
437 print("qemu pc", hex(qpc))
438 print("qemu cr", hex(qcr))
439 print("qemu xer", bin(qxer))
440 print("sim nia", hex(sim.pc.NIA.value))
441 print("sim pc", hex(sim.pc.CIA.value))
442 print("sim cr", hex(sim_cr))
443 print("sim xer", hex(sim_xer))
444 self.assertEqual(qpc, sim_pc)
445 for reg in regs:
446 qemu_val = qemu.get_register(reg)
447 sim_val = sim.gpr(reg).value
448 self.assertEqual(qemu_val, sim_val,
449 "expect %x got %x" % (qemu_val, sim_val))
450 self.assertEqual(qcr, sim_cr)
451
452
453 class DecoderTestCase(DecoderBase, GeneralTestCases):
454 pass
455
456
457 if __name__ == "__main__":
458 unittest.main()