identifying locations where big/little endian is in place, adding args
[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
17
18 class AttnTestCase(FHDLTestCase):
19 test_data = []
20
21 def __init__(self, name="general"):
22 super().__init__(name)
23 self.test_name = name
24
25 def test_0_attn(self):
26 """simple test of attn. program is 4 long: should halt at 2nd op
27 """
28 lst = ["addi 6, 0, 0x10",
29 "attn",
30 "subf. 1, 6, 7",
31 "cmp cr2, 1, 6, 7",
32 ]
33 with Program(lst) as program:
34 self.run_tst_program(program, [1])
35
36 def run_tst_program(self, prog, initial_regs=None, initial_sprs=None,
37 initial_mem=None):
38 initial_regs = [0] * 32
39 tc = TestCase(prog, self.test_name, initial_regs, initial_sprs, 0,
40 initial_mem, 0)
41 self.test_data.append(tc)
42
43
44 class GeneralTestCases(FHDLTestCase):
45 test_data = []
46
47 def __init__(self, name="general"):
48 super().__init__(name)
49 self.test_name = name
50
51 @unittest.skip("disable")
52 def test_0_cmp(self):
53 lst = ["addi 6, 0, 0x10",
54 "addi 7, 0, 0x05",
55 "subf. 1, 6, 7",
56 "cmp cr2, 1, 6, 7",
57 ]
58 with Program(lst) as program:
59 self.run_tst_program(program, [1])
60
61 @unittest.skip("disable")
62 def test_example(self):
63 lst = ["addi 1, 0, 0x5678",
64 "addi 2, 0, 0x1234",
65 "add 3, 1, 2",
66 "and 4, 1, 2"]
67 with Program(lst) as program:
68 self.run_tst_program(program, [1, 2, 3, 4])
69
70 @unittest.skip("disable")
71 def test_ldst(self):
72 lst = ["addi 1, 0, 0x5678",
73 "addi 2, 0, 0x1234",
74 "stw 1, 0(2)",
75 "lwz 3, 0(2)"
76 ]
77 initial_mem = {0x1230: (0x5432123412345678, 8),
78 0x1238: (0xabcdef0187654321, 8),
79 }
80 with Program(lst) as program:
81 self.run_tst_program(program,
82 [1, 2, 3],
83 initial_mem)
84
85 @unittest.skip("disable")
86 def test_ld_rev_ext(self):
87 lst = ["addi 1, 0, 0x5678",
88 "addi 2, 0, 0x1234",
89 "addi 4, 0, 0x40",
90 "stw 1, 0x40(2)",
91 "lwbrx 3, 4, 2"]
92 with Program(lst) as program:
93 self.run_tst_program(program, [1, 2, 3])
94
95 @unittest.skip("disable")
96 def test_st_rev_ext(self):
97 lst = ["addi 1, 0, 0x5678",
98 "addi 2, 0, 0x1234",
99 "addi 4, 0, 0x40",
100 "stwbrx 1, 4, 2",
101 "lwzx 3, 4, 2"]
102 with Program(lst) as program:
103 self.run_tst_program(program, [1, 2, 3])
104
105 @unittest.skip("disable")
106 def test_ldst_extended(self):
107 lst = ["addi 1, 0, 0x5678",
108 "addi 2, 0, 0x1234",
109 "addi 4, 0, 0x40",
110 "stw 1, 0x40(2)",
111 "lwzx 3, 4, 2"]
112 with Program(lst) as program:
113 self.run_tst_program(program, [1, 2, 3])
114
115 @unittest.skip("disable")
116 def test_0_ldst_widths(self):
117 lst = ["addis 1, 0, 0xdead",
118 "ori 1, 1, 0xbeef",
119 "addi 2, 0, 0x1000",
120 "std 1, 0(2)",
121 "lbz 1, 5(2)",
122 "lhz 3, 4(2)",
123 "lwz 4, 4(2)",
124 "addi 5, 0, 0x12",
125 "stb 5, 5(2)",
126 "ld 5, 0(2)"]
127 with Program(lst) as program:
128 self.run_tst_program(program, [1, 2, 3, 4, 5])
129
130 @unittest.skip("disable")
131 def test_sub(self):
132 lst = ["addi 1, 0, 0x1234",
133 "addi 2, 0, 0x5678",
134 "subf 3, 1, 2",
135 "subfic 4, 1, 0x1337",
136 "neg 5, 1"]
137 with Program(lst) as program:
138 self.run_tst_program(program, [1, 2, 3, 4, 5])
139
140 @unittest.skip("disable")
141 def test_add_with_carry(self):
142 lst = ["addi 1, 0, 5",
143 "neg 1, 1",
144 "addi 2, 0, 7",
145 "neg 2, 2",
146 "addc 3, 2, 1",
147 "addi 3, 3, 1"
148 ]
149 with Program(lst) as program:
150 self.run_tst_program(program, [1, 2, 3])
151
152 @unittest.skip("disable")
153 def test_addis(self):
154 lst = ["addi 1, 0, 0x0FFF",
155 "addis 1, 1, 0x0F"
156 ]
157 with Program(lst) as program:
158 self.run_tst_program(program, [1])
159
160 @unittest.skip("broken")
161 def test_mulli(self):
162 lst = ["addi 1, 0, 3",
163 "mulli 1, 1, 2"
164 ]
165 with Program(lst) as program:
166 self.run_tst_program(program, [1])
167
168 @unittest.skip("disable")
169 def test_2_load_store(self):
170 lst = ["addi 1, 0, 0x1004",
171 "addi 2, 0, 0x1008",
172 "addi 3, 0, 0x00ee",
173 "stb 3, 1(2)",
174 "lbz 4, 1(2)",
175 ]
176 initial_regs = [0] * 32
177 initial_regs[1] = 0x1004
178 initial_regs[2] = 0x1008
179 initial_regs[3] = 0x00ee
180 initial_mem = {0x1000: (0x5432123412345678, 8),
181 0x1008: (0xabcdef0187654321, 8),
182 0x1020: (0x1828384822324252, 8),
183 }
184 with Program(lst) as program:
185 self.run_tst_program(program, [3,4], initial_mem)
186
187 @unittest.skip("disable")
188 def test_3_load_store(self):
189 lst = ["addi 1, 0, 0x1004",
190 "addi 2, 0, 0x1002",
191 "addi 3, 0, 0x15eb",
192 "sth 4, 0(2)",
193 "lhz 4, 0(2)"]
194 initial_regs = [0] * 32
195 initial_regs[1] = 0x1004
196 initial_regs[2] = 0x1002
197 initial_regs[3] = 0x15eb
198 initial_mem = {0x1000: (0x5432123412345678, 8),
199 0x1008: (0xabcdef0187654321, 8),
200 0x1020: (0x1828384822324252, 8),
201 }
202 with Program(lst) as program:
203 self.run_tst_program(program, [1,2,3,4], initial_mem)
204
205 def test_loop(self):
206 """in godbolt.org:
207 register unsigned long i asm ("r12");
208 void square(void) {
209 i = 5;
210 do {
211 i = i - 1;
212 } while (i != 0);
213 }
214 """
215 lst = ["addi 9, 0, 0x10", # i = 16
216 "addi 9,9,-1", # i = i - 1
217 "cmpi 0,1,9,12", # compare 9 to value 0, store in CR2
218 "bc 4,0,-8" # branch if CR2 "test was != 0"
219 ]
220 with Program(lst) as program:
221 self.run_tst_program(program, [9], initial_mem={})
222
223 def test_30_addis(self):
224 lst = [#"addi 0, 0, 5",
225 "addis 12, 0, 0",
226 ]
227 with Program(lst) as program:
228 self.run_tst_program(program, [12])
229
230 def run_tst_program(self, prog, initial_regs=None, initial_sprs=None,
231 initial_mem=None):
232 initial_regs = [0] * 32
233 tc = TestCase(prog, self.test_name, initial_regs, initial_sprs, 0,
234 initial_mem, 0)
235 self.test_data.append(tc)
236
237
238 class DecoderBase:
239
240 def run_tst(self, generator, initial_mem=None, initial_pc=0):
241 m = Module()
242 comb = m.d.comb
243
244 gen = list(generator.generate_instructions())
245 insn_code = generator.assembly.splitlines()
246 instructions = list(zip(gen, insn_code))
247 bigendian = False
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(1)
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) as q:
291 self.qemu_register_compare(simulator, q, reglist)
292 self.qemu_mem_compare(simulator, q, True)
293 print(simulator.gpr.dump())
294
295 def qemu_mem_compare(self, sim, qemu, check=True):
296 if False: # disable convenient large interesting debugging memory dump
297 addr = 0x0
298 qmemdump = qemu.get_mem(addr, 2048)
299 for i in range(len(qmemdump)):
300 s = hex(int(qmemdump[i]))
301 print ("qemu mem %06x %s" % (addr+i*8, s))
302 for k, v in sim.mem.mem.items():
303 qmemdump = qemu.get_mem(k*8, 8)
304 s = hex(int(qmemdump[0]))[2:]
305 print ("qemu mem %06x %16s" % (k*8, s))
306 for k, v in sim.mem.mem.items():
307 print ("sim mem %06x %016x" % (k*8, v))
308 if not check:
309 return
310 for k, v in sim.mem.mem.items():
311 qmemdump = qemu.get_mem(k*8, 1)
312 self.assertEqual(int(qmemdump[0]), v)
313
314 def qemu_register_compare(self, sim, qemu, regs):
315 qpc, qxer, qcr = qemu.get_pc(), qemu.get_xer(), qemu.get_cr()
316 sim_cr = sim.cr.get_range().value
317 sim_pc = sim.pc.CIA.value
318 sim_xer = sim.spr['XER'].value
319 print("qemu pc", hex(qpc))
320 print("qemu cr", hex(qcr))
321 print("qemu xer", bin(qxer))
322 print("sim nia", hex(sim.pc.NIA.value))
323 print("sim pc", hex(sim.pc.CIA.value))
324 print("sim cr", hex(sim_cr))
325 print("sim xer", hex(sim_xer))
326 self.assertEqual(qpc, sim_pc)
327 for reg in regs:
328 qemu_val = qemu.get_register(reg)
329 sim_val = sim.gpr(reg).value
330 self.assertEqual(qemu_val, sim_val,
331 "expect %x got %x" % (qemu_val, sim_val))
332 self.assertEqual(qcr, sim_cr)
333
334
335 class DecoderTestCase(DecoderBase, GeneralTestCases):
336 pass
337
338
339 if __name__ == "__main__":
340 unittest.main()