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