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