resolving old and new behaviour for lookup of SPRs
[soc.git] / src / soc / simple / test / test_core.py
1 """simple core test
2
3 related bugs:
4
5 * https://bugs.libre-soc.org/show_bug.cgi?id=363
6 """
7 from nmigen import Module, Signal, Cat
8 from nmigen.back.pysim import Simulator, Delay, Settle
9 from nmutil.formaltest import FHDLTestCase
10 from nmigen.cli import rtlil
11 import unittest
12 from soc.decoder.isa.caller import special_sprs
13 from soc.decoder.power_decoder import create_pdecode
14 from soc.decoder.power_decoder2 import PowerDecode2
15 from soc.decoder.selectable_int import SelectableInt
16 from soc.decoder.isa.all import ISA
17 from soc.decoder.power_enums import SPR, spr_dict, Function, XER_bits
18 from soc.config.test.test_loadstore import TestMemPspec
19
20 from soc.simple.core import NonProductionCore
21 from soc.experiment.compalu_multi import find_ok # hack
22
23 from soc.fu.compunits.test.test_compunit import (setup_test_memory,
24 check_sim_memory)
25
26 # test with ALU data and Logical data
27 from soc.fu.alu.test.test_pipe_caller import ALUTestCase
28 from soc.fu.logical.test.test_pipe_caller import LogicalTestCase
29 from soc.fu.shift_rot.test.test_pipe_caller import ShiftRotTestCase
30 from soc.fu.cr.test.test_pipe_caller import CRTestCase
31 from soc.fu.branch.test.test_pipe_caller import BranchTestCase
32 from soc.fu.ldst.test.test_pipe_caller import LDSTTestCase
33 from soc.regfile.util import spr_to_fast_reg
34
35
36 def setup_regs(core, test):
37
38 # set up INT regfile, "direct" write (bypass rd/write ports)
39 intregs = core.regs.int
40 for i in range(32):
41 yield intregs.regs[i].reg.eq(test.regs[i])
42
43 # set up CR regfile, "direct" write across all CRs
44 cr = test.cr
45 crregs = core.regs.cr
46 #cr = int('{:32b}'.format(cr)[::-1], 2)
47 print ("cr reg", hex(cr))
48 for i in range(8):
49 #j = 7-i
50 cri = (cr>>(i*4)) & 0xf
51 #cri = int('{:04b}'.format(cri)[::-1], 2)
52 print ("cr reg", hex(cri), i,
53 crregs.regs[i].reg.shape())
54 yield crregs.regs[i].reg.eq(cri)
55
56 # set up XER. "direct" write (bypass rd/write ports)
57 xregs = core.regs.xer
58 print ("sprs", test.sprs)
59 xer = None
60 if 'XER' in test.sprs:
61 xer = test.sprs['XER']
62 if 1 in test.sprs:
63 xer = test.sprs[1]
64 if xer is not None:
65 if isinstance(xer, int):
66 xer = SelectableInt(xer, 64)
67 sobit = xer[XER_bits['SO']].value
68 yield xregs.regs[xregs.SO].reg.eq(sobit)
69 cabit = xer[XER_bits['CA']].value
70 ca32bit = xer[XER_bits['CA32']].value
71 yield xregs.regs[xregs.CA].reg.eq(Cat(cabit, ca32bit))
72 ovbit = xer[XER_bits['OV']].value
73 ov32bit = xer[XER_bits['OV32']].value
74 yield xregs.regs[xregs.OV].reg.eq(Cat(ovbit, ov32bit))
75 print ("setting XER so %d ca %d ca32 %d ov %d ov32 %d" % \
76 (sobit, cabit, ca32bit, ovbit, ov32bit))
77 else:
78 yield xregs.regs[xregs.SO].reg.eq(0)
79 yield xregs.regs[xregs.OV].reg.eq(0)
80 yield xregs.regs[xregs.CA].reg.eq(0)
81
82 # setting both fast and slow SPRs from test data
83
84 fregs = core.regs.fast
85 sregs = core.regs.spr
86 for sprname, val in test.sprs.items():
87 if isinstance(sprname, int):
88 sprname = spr_dict[sprname].name
89 if sprname == 'XER':
90 continue
91 fast = spr_to_fast_reg(sprname)
92 if fast is None:
93 # match behaviour of SPRMap in power_decoder2.py
94 for i, x in enumerate(SPR):
95 if sprname == x.name:
96 yield sregs[i].reg.eq(val)
97 print ("setting slow SPR %d (%s) to %x" % \
98 (i, sprname, val))
99 else:
100 yield fregs.regs[fast].reg.eq(val)
101 print ("setting fast reg %d (%s) to %x" % \
102 (fast, sprname, val))
103
104
105 # allow changes to settle before reporting on XER
106 yield Settle()
107
108 # XER
109 pdecode2 = core.pdecode2
110 so = yield xregs.regs[xregs.SO].reg
111 ov = yield xregs.regs[xregs.OV].reg
112 ca = yield xregs.regs[xregs.CA].reg
113 oe = yield pdecode2.e.do.oe.oe
114 oe_ok = yield pdecode2.e.do.oe.oe_ok
115
116 print ("before: so/ov-32/ca-32", so, bin(ov), bin(ca))
117 print ("oe:", oe, oe_ok)
118
119
120 def check_regs(dut, sim, core, test, code):
121 # int regs
122 intregs = []
123 for i in range(32):
124 rval = yield core.regs.int.regs[i].reg
125 intregs.append(rval)
126 print ("int regs", list(map(hex, intregs)))
127 for i in range(32):
128 simregval = sim.gpr[i].asint()
129 dut.assertEqual(simregval, intregs[i],
130 "int reg %d not equal %s" % (i, repr(code)))
131
132 # CRs
133 crregs = []
134 for i in range(8):
135 rval = yield core.regs.cr.regs[i].reg
136 crregs.append(rval)
137 print ("cr regs", list(map(hex, crregs)))
138 for i in range(8):
139 rval = crregs[i]
140 cri = sim.crl[7-i].get_range().value
141 print ("cr reg", i, hex(cri), i, hex(rval))
142 # XXX https://bugs.libre-soc.org/show_bug.cgi?id=363
143 dut.assertEqual(cri, rval,
144 "cr reg %d not equal %s" % (i, repr(code)))
145
146 # XER
147 xregs = core.regs.xer
148 so = yield xregs.regs[xregs.SO].reg
149 ov = yield xregs.regs[xregs.OV].reg
150 ca = yield xregs.regs[xregs.CA].reg
151
152 print ("sim SO", sim.spr['XER'][XER_bits['SO']])
153 e_so = sim.spr['XER'][XER_bits['SO']].value
154 e_ov = sim.spr['XER'][XER_bits['OV']].value
155 e_ov32 = sim.spr['XER'][XER_bits['OV32']].value
156 e_ca = sim.spr['XER'][XER_bits['CA']].value
157 e_ca32 = sim.spr['XER'][XER_bits['CA32']].value
158
159 e_ov = e_ov | (e_ov32<<1)
160 e_ca = e_ca | (e_ca32<<1)
161
162 print ("after: so/ov-32/ca-32", so, bin(ov), bin(ca))
163 dut.assertEqual(e_so, so, "so mismatch %s" % (repr(code)))
164 dut.assertEqual(e_ov, ov, "ov mismatch %s" % (repr(code)))
165 dut.assertEqual(e_ca, ca, "ca mismatch %s" % (repr(code)))
166
167
168 def wait_for_busy_hi(cu):
169 while True:
170 busy_o = yield cu.busy_o
171 terminated_o = yield cu.core_terminated_o
172 if busy_o or terminated_o:
173 print("busy/terminated:", busy_o, terminated_o)
174 break
175 print("!busy", busy_o, terminated_o)
176 yield
177
178 def set_issue(core, dec2, sim):
179 yield core.issue_i.eq(1)
180 yield
181 yield core.issue_i.eq(0)
182 yield from wait_for_busy_hi(core)
183
184
185 def wait_for_busy_clear(cu):
186 while True:
187 busy_o = yield cu.busy_o
188 terminated_o = yield cu.core_terminated_o
189 if not busy_o or terminated_o:
190 print("busy/terminated:", busy_o, terminated_o)
191 break
192 print("busy",)
193 yield
194
195
196 class TestRunner(FHDLTestCase):
197 def __init__(self, tst_data):
198 super().__init__("run_all")
199 self.test_data = tst_data
200
201 def run_all(self):
202 m = Module()
203 comb = m.d.comb
204 instruction = Signal(32)
205 ivalid_i = Signal()
206
207 pspec = TestMemPspec(ldst_ifacetype='testpi',
208 imem_ifacetype='',
209 addr_wid=48,
210 mask_wid=8,
211 reg_wid=64)
212
213 m.submodules.core = core = NonProductionCore(pspec)
214 pdecode2 = core.pdecode2
215 l0 = core.l0
216
217 comb += core.raw_opcode_i.eq(instruction)
218 comb += core.ivalid_i.eq(ivalid_i)
219
220 # temporary hack: says "go" immediately for both address gen and ST
221 ldst = core.fus.fus['ldst0']
222 m.d.comb += ldst.ad.go.eq(ldst.ad.rel) # link addr-go direct to rel
223 m.d.comb += ldst.st.go.eq(ldst.st.rel) # link store-go direct to rel
224
225 # nmigen Simulation
226 sim = Simulator(m)
227 sim.add_clock(1e-6)
228
229 def process():
230 yield core.issue_i.eq(0)
231 yield
232
233 for test in self.test_data:
234 print(test.name)
235 program = test.program
236 self.subTest(test.name)
237 sim = ISA(pdecode2, test.regs, test.sprs, test.cr, test.mem,
238 test.msr)
239 gen = program.generate_instructions()
240 instructions = list(zip(gen, program.assembly.splitlines()))
241
242 yield from setup_test_memory(l0, sim)
243 yield from setup_regs(core, test)
244
245 index = sim.pc.CIA.value//4
246 while index < len(instructions):
247 ins, code = instructions[index]
248
249 print("instruction: 0x{:X}".format(ins & 0xffffffff))
250 print(code)
251
252 # ask the decoder to decode this binary data (endian'd)
253 yield core.bigendian_i.eq(0) # little / big?
254 yield instruction.eq(ins) # raw binary instr.
255 yield ivalid_i.eq(1)
256 yield Settle()
257 #fn_unit = yield pdecode2.e.fn_unit
258 #fuval = self.funit.value
259 #self.assertEqual(fn_unit & fuval, fuval)
260
261 # set operand and get inputs
262 yield from set_issue(core, pdecode2, sim)
263 yield Settle()
264
265 yield from wait_for_busy_clear(core)
266 yield ivalid_i.eq(0)
267 yield
268
269 print ("sim", code)
270 # call simulated operation
271 opname = code.split(' ')[0]
272 yield from sim.call(opname)
273 index = sim.pc.CIA.value//4
274
275 # register check
276 yield from check_regs(self, sim, core, test, code)
277
278 # Memory check
279 yield from check_sim_memory(self, l0, sim, code)
280
281 sim.add_sync_process(process)
282 with sim.write_vcd("core_simulator.vcd", "core_simulator.gtkw",
283 traces=[]):
284 sim.run()
285
286
287 if __name__ == "__main__":
288 unittest.main(exit=False)
289 suite = unittest.TestSuite()
290 suite.addTest(TestRunner(LDSTTestCase.test_data))
291 suite.addTest(TestRunner(CRTestCase.test_data))
292 suite.addTest(TestRunner(ShiftRotTestCase.test_data))
293 suite.addTest(TestRunner(LogicalTestCase.test_data))
294 suite.addTest(TestRunner(ALUTestCase.test_data))
295 suite.addTest(TestRunner(BranchTestCase.test_data))
296
297 runner = unittest.TextTestRunner()
298 runner.run(suite)
299