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