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