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