add test_nop general test case
[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 "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 def test_loop(self):
216 """in godbolt.org:
217 register unsigned long i asm ("r12");
218 void square(void) {
219 i = 5;
220 do {
221 i = i - 1;
222 } while (i != 0);
223 }
224 """
225 lst = ["addi 9, 0, 0x10", # i = 16
226 "addi 9,9,-1", # i = i - 1
227 "cmpi 0,1,9,12", # compare 9 to value 0, store in CR2
228 "bc 4,0,-8" # branch if CR2 "test was != 0"
229 ]
230 with Program(lst, bigendian) as program:
231 self.run_tst_program(program, [9], initial_mem={})
232
233 def test_30_addis(self):
234 lst = [ # "addi 0, 0, 5",
235 "addis 12, 0, 0",
236 ]
237 with Program(lst, bigendian) as program:
238 self.run_tst_program(program, [12])
239
240 def run_tst_program(self, prog, initial_regs=None, initial_sprs=None,
241 initial_mem=None):
242 initial_regs = [0] * 32
243 tc = TestCase(prog, self.test_name, initial_regs, initial_sprs, 0,
244 initial_mem, 0)
245 self.test_data.append(tc)
246
247
248 class DecoderBase:
249
250 def run_tst(self, generator, initial_mem=None, initial_pc=0):
251 m = Module()
252 comb = m.d.comb
253
254 gen = list(generator.generate_instructions())
255 insn_code = generator.assembly.splitlines()
256 instructions = list(zip(gen, insn_code))
257
258 pdecode = create_pdecode()
259 m.submodules.pdecode2 = pdecode2 = PowerDecode2(pdecode)
260
261 # place program at requested address
262 gen = (initial_pc, gen)
263
264 simulator = ISA(pdecode2, [0] * 32, {}, 0, initial_mem, 0,
265 initial_insns=gen, respect_pc=True,
266 disassembly=insn_code,
267 initial_pc=initial_pc,
268 bigendian=bigendian)
269
270 sim = Simulator(m)
271
272 def process():
273 # yield pdecode2.dec.bigendian.eq(bigendian)
274 yield Settle()
275
276 while True:
277 try:
278 yield from simulator.setup_one()
279 except KeyError: # indicates instruction not in imem: stop
280 break
281 yield Settle()
282 yield from simulator.execute_one()
283 yield Settle()
284
285 sim.add_process(process)
286 with sim.write_vcd("simulator.vcd", "simulator.gtkw",
287 traces=[]):
288 sim.run()
289
290 return simulator
291
292 def run_tst_program(self, prog, reglist, initial_mem=None,
293 extra_break_addr=None):
294 import sys
295 simulator = self.run_tst(prog, initial_mem=initial_mem,
296 initial_pc=0x20000000)
297 prog.reset()
298 with run_program(prog, initial_mem, extra_break_addr,
299 bigendian=bigendian) as q:
300 self.qemu_register_compare(simulator, q, reglist)
301 self.qemu_mem_compare(simulator, q, True)
302 print(simulator.gpr.dump())
303
304 def qemu_mem_compare(self, sim, qemu, check=True):
305 if False: # disable convenient large interesting debugging memory dump
306 addr = 0x0
307 qmemdump = qemu.get_mem(addr, 2048)
308 for i in range(len(qmemdump)):
309 s = hex(int(qmemdump[i]))
310 print("qemu mem %06x %s" % (addr+i*8, s))
311 for k, v in sim.mem.mem.items():
312 qmemdump = qemu.get_mem(k*8, 8)
313 s = hex(int(qmemdump[0]))[2:]
314 print("qemu mem %06x %16s" % (k*8, s))
315 for k, v in sim.mem.mem.items():
316 print("sim mem %06x %016x" % (k*8, v))
317 if not check:
318 return
319 for k, v in sim.mem.mem.items():
320 qmemdump = qemu.get_mem(k*8, 1)
321 self.assertEqual(int(qmemdump[0]), v)
322
323 def qemu_register_compare(self, sim, qemu, regs):
324 qpc, qxer, qcr = qemu.get_pc(), qemu.get_xer(), qemu.get_cr()
325 sim_cr = sim.cr.get_range().value
326 sim_pc = sim.pc.CIA.value
327 sim_xer = sim.spr['XER'].value
328 print("qemu pc", hex(qpc))
329 print("qemu cr", hex(qcr))
330 print("qemu xer", bin(qxer))
331 print("sim nia", hex(sim.pc.NIA.value))
332 print("sim pc", hex(sim.pc.CIA.value))
333 print("sim cr", hex(sim_cr))
334 print("sim xer", hex(sim_xer))
335 self.assertEqual(qpc, sim_pc)
336 for reg in regs:
337 qemu_val = qemu.get_register(reg)
338 sim_val = sim.gpr(reg).value
339 self.assertEqual(qemu_val, sim_val,
340 "expect %x got %x" % (qemu_val, sim_val))
341 self.assertEqual(qcr, sim_cr)
342
343
344 class DecoderTestCase(DecoderBase, GeneralTestCases):
345 pass
346
347
348 if __name__ == "__main__":
349 unittest.main()