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