do mix-in for test_sim.py so that jacob can write some div tests without
[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 Register:
19 def __init__(self, num):
20 self.num = num
21
22
23 class GeneralTestCases(FHDLTestCase):
24 test_data = []
25
26 def __init__(self, name="general"):
27 super().__init__(name)
28 self.test_name = name
29
30 @unittest.skip("disable")
31 def test_0_cmp(self):
32 lst = ["addi 6, 0, 0x10",
33 "addi 7, 0, 0x05",
34 "subf. 1, 6, 7",
35 "cmp cr2, 1, 6, 7",
36 ]
37 with Program(lst) as program:
38 self.run_tst_program(program, [1])
39
40 @unittest.skip("disable")
41 def test_example(self):
42 lst = ["addi 1, 0, 0x5678",
43 "addi 2, 0, 0x1234",
44 "add 3, 1, 2",
45 "and 4, 1, 2"]
46 with Program(lst) as program:
47 self.run_tst_program(program, [1, 2, 3, 4])
48
49 @unittest.skip("disable")
50 def test_ldst(self):
51 lst = ["addi 1, 0, 0x5678",
52 "addi 2, 0, 0x1234",
53 "stw 1, 0(2)",
54 "lwz 3, 0(2)"
55 ]
56 initial_mem = {0x1230: (0x5432123412345678, 8),
57 0x1238: (0xabcdef0187654321, 8),
58 }
59 with Program(lst) as program:
60 self.run_tst_program(program,
61 [1, 2, 3],
62 initial_mem)
63
64 @unittest.skip("disable")
65 def test_ld_rev_ext(self):
66 lst = ["addi 1, 0, 0x5678",
67 "addi 2, 0, 0x1234",
68 "addi 4, 0, 0x40",
69 "stw 1, 0x40(2)",
70 "lwbrx 3, 4, 2"]
71 with Program(lst) as program:
72 self.run_tst_program(program, [1, 2, 3])
73
74 @unittest.skip("disable")
75 def test_st_rev_ext(self):
76 lst = ["addi 1, 0, 0x5678",
77 "addi 2, 0, 0x1234",
78 "addi 4, 0, 0x40",
79 "stwbrx 1, 4, 2",
80 "lwzx 3, 4, 2"]
81 with Program(lst) as program:
82 self.run_tst_program(program, [1, 2, 3])
83
84 @unittest.skip("disable")
85 def test_ldst_extended(self):
86 lst = ["addi 1, 0, 0x5678",
87 "addi 2, 0, 0x1234",
88 "addi 4, 0, 0x40",
89 "stw 1, 0x40(2)",
90 "lwzx 3, 4, 2"]
91 with Program(lst) as program:
92 self.run_tst_program(program, [1, 2, 3])
93
94 @unittest.skip("disable")
95 def test_0_ldst_widths(self):
96 lst = ["addis 1, 0, 0xdead",
97 "ori 1, 1, 0xbeef",
98 "addi 2, 0, 0x1000",
99 "std 1, 0(2)",
100 "lbz 1, 5(2)",
101 "lhz 3, 4(2)",
102 "lwz 4, 4(2)",
103 "addi 5, 0, 0x12",
104 "stb 5, 5(2)",
105 "ld 5, 0(2)"]
106 with Program(lst) as program:
107 self.run_tst_program(program, [1, 2, 3, 4, 5])
108
109 @unittest.skip("disable")
110 def test_sub(self):
111 lst = ["addi 1, 0, 0x1234",
112 "addi 2, 0, 0x5678",
113 "subf 3, 1, 2",
114 "subfic 4, 1, 0x1337",
115 "neg 5, 1"]
116 with Program(lst) as program:
117 self.run_tst_program(program, [1, 2, 3, 4, 5])
118
119 @unittest.skip("disable")
120 def test_add_with_carry(self):
121 lst = ["addi 1, 0, 5",
122 "neg 1, 1",
123 "addi 2, 0, 7",
124 "neg 2, 2",
125 "addc 3, 2, 1",
126 "addi 3, 3, 1"
127 ]
128 with Program(lst) as program:
129 self.run_tst_program(program, [1, 2, 3])
130
131 @unittest.skip("disable")
132 def test_addis(self):
133 lst = ["addi 1, 0, 0x0FFF",
134 "addis 1, 1, 0x0F"
135 ]
136 with Program(lst) as program:
137 self.run_tst_program(program, [1])
138
139 @unittest.skip("broken")
140 def test_mulli(self):
141 lst = ["addi 1, 0, 3",
142 "mulli 1, 1, 2"
143 ]
144 with Program(lst) as program:
145 self.run_tst_program(program, [1])
146
147 @unittest.skip("disable")
148 def test_2_load_store(self):
149 lst = ["addi 1, 0, 0x1004",
150 "addi 2, 0, 0x1008",
151 "addi 3, 0, 0x00ee",
152 "stb 3, 1(2)",
153 "lbz 4, 1(2)",
154 ]
155 initial_regs = [0] * 32
156 initial_regs[1] = 0x1004
157 initial_regs[2] = 0x1008
158 initial_regs[3] = 0x00ee
159 initial_mem = {0x1000: (0x5432123412345678, 8),
160 0x1008: (0xabcdef0187654321, 8),
161 0x1020: (0x1828384822324252, 8),
162 }
163 with Program(lst) as program:
164 self.run_tst_program(program, [3,4], initial_mem)
165
166 @unittest.skip("disable")
167 def test_3_load_store(self):
168 lst = ["addi 1, 0, 0x1004",
169 "addi 2, 0, 0x1002",
170 "addi 3, 0, 0x15eb",
171 "sth 4, 0(2)",
172 "lhz 4, 0(2)"]
173 initial_regs = [0] * 32
174 initial_regs[1] = 0x1004
175 initial_regs[2] = 0x1002
176 initial_regs[3] = 0x15eb
177 initial_mem = {0x1000: (0x5432123412345678, 8),
178 0x1008: (0xabcdef0187654321, 8),
179 0x1020: (0x1828384822324252, 8),
180 }
181 with Program(lst) as program:
182 self.run_tst_program(program, [1,2,3,4], initial_mem)
183
184 def test_loop(self):
185 """in godbolt.org:
186 register unsigned long i asm ("r12");
187 void square(void) {
188 i = 5;
189 do {
190 i = i - 1;
191 } while (i != 0);
192 }
193 """
194 lst = ["addi 9, 0, 0x10", # i = 16
195 "addi 9,9,-1", # i = i - 1
196 "cmpi 0,1,9,12", # compare 9 to value 0, store in CR2
197 "bc 4,0,-8" # branch if CR2 "test was != 0"
198 ]
199 with Program(lst) as program:
200 self.run_tst_program(program, [9], initial_mem={})
201
202 def run_tst_program(self, prog, initial_regs=None, initial_sprs=None,
203 initial_mem=None):
204 initial_regs = [0] * 32
205 tc = TestCase(prog, self.test_name, initial_regs, initial_sprs, 0,
206 initial_mem, 0)
207 self.test_data.append(tc)
208
209
210 class DecoderBase:
211
212 def run_tst(self, generator, initial_mem=None):
213 m = Module()
214 comb = m.d.comb
215
216 gen = list(generator.generate_instructions())
217 insn_code = generator.assembly.splitlines()
218 instructions = list(zip(gen, insn_code))
219
220 pdecode = create_pdecode()
221 m.submodules.pdecode2 = pdecode2 = PowerDecode2(pdecode)
222
223 simulator = ISA(pdecode2, [0] * 32, {}, 0, initial_mem, 0,
224 initial_insns=gen, respect_pc=True,
225 disassembly=insn_code)
226
227 sim = Simulator(m)
228
229 def process():
230 while True:
231 try:
232 yield from simulator.setup_one()
233 except KeyError: # indicates instruction not in imem: stop
234 break
235 yield Settle()
236 yield from simulator.execute_one()
237 yield Settle()
238
239
240 sim.add_process(process)
241 with sim.write_vcd("simulator.vcd", "simulator.gtkw",
242 traces=[]):
243 sim.run()
244
245 return simulator
246
247 def run_tst_program(self, prog, reglist, initial_mem=None):
248 import sys
249 simulator = self.run_tst(prog, initial_mem=initial_mem)
250 prog.reset()
251 with run_program(prog, initial_mem) as q:
252 self.qemu_register_compare(simulator, q, reglist)
253 self.qemu_mem_compare(simulator, q, reglist)
254 print(simulator.gpr.dump())
255
256 def qemu_mem_compare(self, sim, qemu, check=True):
257 if False: # disable convenient large interesting debugging memory dump
258 addr = 0x0
259 qmemdump = qemu.get_mem(addr, 2048)
260 for i in range(len(qmemdump)):
261 s = hex(int(qmemdump[i]))
262 print ("qemu mem %06x %s" % (addr+i*8, s))
263 for k, v in sim.mem.mem.items():
264 qmemdump = qemu.get_mem(k*8, 8)
265 s = hex(int(qmemdump[0]))[2:]
266 print ("qemu mem %06x %16s" % (k*8, s))
267 for k, v in sim.mem.mem.items():
268 print ("sim mem %06x %016x" % (k*8, v))
269 if not check:
270 return
271 for k, v in sim.mem.mem.items():
272 qmemdump = qemu.get_mem(k*8, 1)
273 self.assertEqual(int(qmemdump[0]), v)
274
275 def qemu_register_compare(self, sim, qemu, regs):
276 qpc, qxer, qcr = qemu.get_pc(), qemu.get_xer(), qemu.get_cr()
277 sim_cr = sim.cr.get_range().value
278 sim_pc = sim.pc.CIA.value
279 sim_xer = sim.spr['XER'].value
280 print("qemu pc", hex(qpc))
281 print("qemu cr", hex(qcr))
282 print("qemu xer", bin(qxer))
283 print("sim pc", hex(sim.pc.CIA.value))
284 print("sim cr", hex(sim_cr))
285 print("sim xer", hex(sim_xer))
286 self.assertEqual(qcr, sim_cr)
287 for reg in regs:
288 qemu_val = qemu.get_register(reg)
289 sim_val = sim.gpr(reg).value
290 self.assertEqual(qemu_val, sim_val)
291
292
293 class DecoderTestCase(DecoderBase, GeneralTestCases):
294 pass
295
296
297 if __name__ == "__main__":
298 unittest.main()