add trampoline test from litex
[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 0x24",
249 ]
250 with Program(lst, bigendian) as program:
251 self.run_tst_program(program, [], initial_mem={})
252
253 def test_30_addis(self):
254 lst = [ # "addi 0, 0, 5",
255 "addis 12, 0, 0",
256 ]
257 with Program(lst, bigendian) as program:
258 self.run_tst_program(program, [12])
259
260 def run_tst_program(self, prog, initial_regs=None, initial_sprs=None,
261 initial_mem=None):
262 initial_regs = [0] * 32
263 tc = TestCase(prog, self.test_name, initial_regs, initial_sprs, 0,
264 initial_mem, 0)
265 self.test_data.append(tc)
266
267
268 class DecoderBase:
269
270 def run_tst(self, generator, initial_mem=None, initial_pc=0):
271 m = Module()
272 comb = m.d.comb
273
274 gen = list(generator.generate_instructions())
275 insn_code = generator.assembly.splitlines()
276 instructions = list(zip(gen, insn_code))
277
278 pdecode = create_pdecode()
279 m.submodules.pdecode2 = pdecode2 = PowerDecode2(pdecode)
280
281 # place program at requested address
282 gen = (initial_pc, gen)
283
284 simulator = ISA(pdecode2, [0] * 32, {}, 0, initial_mem, 0,
285 initial_insns=gen, respect_pc=True,
286 disassembly=insn_code,
287 initial_pc=initial_pc,
288 bigendian=bigendian)
289
290 sim = Simulator(m)
291
292 def process():
293 # yield pdecode2.dec.bigendian.eq(bigendian)
294 yield Settle()
295
296 while True:
297 try:
298 yield from simulator.setup_one()
299 except KeyError: # indicates instruction not in imem: stop
300 break
301 yield Settle()
302 yield from simulator.execute_one()
303 yield Settle()
304
305 sim.add_process(process)
306 with sim.write_vcd("simulator.vcd", "simulator.gtkw",
307 traces=[]):
308 sim.run()
309
310 return simulator
311
312 def run_tst_program(self, prog, reglist, initial_mem=None,
313 extra_break_addr=None):
314 import sys
315 simulator = self.run_tst(prog, initial_mem=initial_mem,
316 initial_pc=0x20000000)
317 prog.reset()
318 with run_program(prog, initial_mem, extra_break_addr,
319 bigendian=bigendian) as q:
320 self.qemu_register_compare(simulator, q, reglist)
321 self.qemu_mem_compare(simulator, q, True)
322 print(simulator.gpr.dump())
323
324 def qemu_mem_compare(self, sim, qemu, check=True):
325 if False: # disable convenient large interesting debugging memory dump
326 addr = 0x0
327 qmemdump = qemu.get_mem(addr, 2048)
328 for i in range(len(qmemdump)):
329 s = hex(int(qmemdump[i]))
330 print("qemu mem %06x %s" % (addr+i*8, s))
331 for k, v in sim.mem.mem.items():
332 qmemdump = qemu.get_mem(k*8, 8)
333 s = hex(int(qmemdump[0]))[2:]
334 print("qemu mem %06x %16s" % (k*8, s))
335 for k, v in sim.mem.mem.items():
336 print("sim mem %06x %016x" % (k*8, v))
337 if not check:
338 return
339 for k, v in sim.mem.mem.items():
340 qmemdump = qemu.get_mem(k*8, 1)
341 self.assertEqual(int(qmemdump[0]), v)
342
343 def qemu_register_compare(self, sim, qemu, regs):
344 qpc, qxer, qcr = qemu.get_pc(), qemu.get_xer(), qemu.get_cr()
345 sim_cr = sim.cr.get_range().value
346 sim_pc = sim.pc.CIA.value
347 sim_xer = sim.spr['XER'].value
348 print("qemu pc", hex(qpc))
349 print("qemu cr", hex(qcr))
350 print("qemu xer", bin(qxer))
351 print("sim nia", hex(sim.pc.NIA.value))
352 print("sim pc", hex(sim.pc.CIA.value))
353 print("sim cr", hex(sim_cr))
354 print("sim xer", hex(sim_xer))
355 self.assertEqual(qpc, sim_pc)
356 for reg in regs:
357 qemu_val = qemu.get_register(reg)
358 sim_val = sim.gpr(reg).value
359 self.assertEqual(qemu_val, sim_val,
360 "expect %x got %x" % (qemu_val, sim_val))
361 self.assertEqual(qcr, sim_cr)
362
363
364 class DecoderTestCase(DecoderBase, GeneralTestCases):
365 pass
366
367
368 if __name__ == "__main__":
369 unittest.main()