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