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