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