move more files to openpower-isa
[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 yield fregs.regs[fast].reg.eq(val)
123 print("setting fast reg %d (%s) to %x" %
124 (fast, sprname, val))
125
126 # allow changes to settle before reporting on XER
127 yield Settle()
128
129 # XER
130 so = yield xregs.regs[xregs.SO].reg
131 ov = yield xregs.regs[xregs.OV].reg
132 ca = yield xregs.regs[xregs.CA].reg
133 oe = yield pdecode2.e.do.oe.oe
134 oe_ok = yield pdecode2.e.do.oe.oe_ok
135
136 print("before: so/ov-32/ca-32", so, bin(ov), bin(ca))
137 print("oe:", oe, oe_ok)
138
139
140 def check_regs(dut, sim, core, test, code):
141 # int regs
142 intregs = []
143 for i in range(32):
144 if core.regs.int.unary:
145 rval = yield core.regs.int.regs[i].reg
146 else:
147 rval = yield core.regs.int.memory._array[i]
148 intregs.append(rval)
149 print("int regs", list(map(hex, intregs)))
150 for i in range(32):
151 simregval = sim.gpr[i].asint()
152 dut.assertEqual(simregval, intregs[i],
153 "int reg %d not equal %s" % (i, repr(code)))
154
155 # CRs
156 crregs = []
157 for i in range(8):
158 rval = yield core.regs.cr.regs[i].reg
159 crregs.append(rval)
160 print("cr regs", list(map(hex, crregs)))
161 for i in range(8):
162 rval = crregs[i]
163 cri = sim.crl[7-i].get_range().value
164 print("cr reg", i, hex(cri), i, hex(rval))
165 # XXX https://bugs.libre-soc.org/show_bug.cgi?id=363
166 dut.assertEqual(cri, rval,
167 "cr reg %d not equal %s" % (i, repr(code)))
168
169 # XER
170 xregs = core.regs.xer
171 so = yield xregs.regs[xregs.SO].reg
172 ov = yield xregs.regs[xregs.OV].reg
173 ca = yield xregs.regs[xregs.CA].reg
174
175 print("sim SO", sim.spr['XER'][XER_bits['SO']])
176 e_so = sim.spr['XER'][XER_bits['SO']].value
177 e_ov = sim.spr['XER'][XER_bits['OV']].value
178 e_ov32 = sim.spr['XER'][XER_bits['OV32']].value
179 e_ca = sim.spr['XER'][XER_bits['CA']].value
180 e_ca32 = sim.spr['XER'][XER_bits['CA32']].value
181
182 e_ov = e_ov | (e_ov32 << 1)
183 e_ca = e_ca | (e_ca32 << 1)
184
185 print("after: so/ov-32/ca-32", so, bin(ov), bin(ca))
186 dut.assertEqual(e_so, so, "so mismatch %s" % (repr(code)))
187 dut.assertEqual(e_ov, ov, "ov mismatch %s" % (repr(code)))
188 dut.assertEqual(e_ca, ca, "ca mismatch %s" % (repr(code)))
189
190 # Check the PC as well
191 state = core.regs.state
192 pc = yield state.r_ports['cia'].data_o
193 e_pc = sim.pc.CIA.value
194 dut.assertEqual(e_pc, pc)
195
196
197 def wait_for_busy_hi(cu):
198 while True:
199 busy_o = yield cu.busy_o
200 terminate_o = yield cu.core_terminate_o
201 if busy_o:
202 print("busy/terminate:", busy_o, terminate_o)
203 break
204 print("!busy", busy_o, terminate_o)
205 yield
206
207
208 def set_issue(core, dec2, sim):
209 yield core.issue_i.eq(1)
210 yield
211 yield core.issue_i.eq(0)
212 yield from wait_for_busy_hi(core)
213
214
215 def wait_for_busy_clear(cu):
216 while True:
217 busy_o = yield cu.busy_o
218 terminate_o = yield cu.core_terminate_o
219 if not busy_o:
220 print("busy/terminate:", busy_o, terminate_o)
221 break
222 print("busy",)
223 yield
224
225
226 class TestRunner(FHDLTestCase):
227 def __init__(self, tst_data):
228 super().__init__("run_all")
229 self.test_data = tst_data
230
231 def run_all(self):
232 m = Module()
233 comb = m.d.comb
234 instruction = Signal(32)
235 ivalid_i = Signal()
236
237 pspec = TestMemPspec(ldst_ifacetype='testpi',
238 imem_ifacetype='',
239 addr_wid=48,
240 mask_wid=8,
241 reg_wid=64)
242
243 m.submodules.core = core = NonProductionCore(pspec)
244 pdecode2 = core.pdecode2
245 l0 = core.l0
246
247 comb += core.raw_opcode_i.eq(instruction)
248 comb += core.ivalid_i.eq(ivalid_i)
249
250 # temporary hack: says "go" immediately for both address gen and ST
251 ldst = core.fus.fus['ldst0']
252 m.d.comb += ldst.ad.go.eq(ldst.ad.rel) # link addr-go direct to rel
253 m.d.comb += ldst.st.go.eq(ldst.st.rel) # link store-go direct to rel
254
255 # nmigen Simulation
256 sim = Simulator(m)
257 sim.add_clock(1e-6)
258
259 def process():
260 yield core.issue_i.eq(0)
261 yield
262
263 for test in self.test_data:
264 print(test.name)
265 program = test.program
266 self.subTest(test.name)
267 sim = ISA(pdecode2, test.regs, test.sprs, test.cr, test.mem,
268 test.msr,
269 bigendian=bigendian)
270 gen = program.generate_instructions()
271 instructions = list(zip(gen, program.assembly.splitlines()))
272
273 yield from setup_test_memory(l0, sim)
274 yield from setup_regs(core, test)
275
276 index = sim.pc.CIA.value//4
277 while index < len(instructions):
278 ins, code = instructions[index]
279
280 print("instruction: 0x{:X}".format(ins & 0xffffffff))
281 print(code)
282
283 # ask the decoder to decode this binary data (endian'd)
284 yield core.bigendian_i.eq(bigendian) # little / big?
285 yield instruction.eq(ins) # raw binary instr.
286 yield ivalid_i.eq(1)
287 yield Settle()
288 # fn_unit = yield pdecode2.e.fn_unit
289 #fuval = self.funit.value
290 #self.assertEqual(fn_unit & fuval, fuval)
291
292 # set operand and get inputs
293 yield from set_issue(core, pdecode2, sim)
294 yield Settle()
295
296 yield from wait_for_busy_clear(core)
297 yield ivalid_i.eq(0)
298 yield
299
300 print("sim", code)
301 # call simulated operation
302 opname = code.split(' ')[0]
303 yield from sim.call(opname)
304 index = sim.pc.CIA.value//4
305
306 # register check
307 yield from check_regs(self, sim, core, test, code)
308
309 # Memory check
310 yield from check_sim_memory(self, l0, sim, code)
311
312 sim.add_sync_process(process)
313 with sim.write_vcd("core_simulator.vcd", "core_simulator.gtkw",
314 traces=[]):
315 sim.run()
316
317
318 if __name__ == "__main__":
319 unittest.main(exit=False)
320 suite = unittest.TestSuite()
321 suite.addTest(TestRunner(LDSTTestCase().test_data))
322 suite.addTest(TestRunner(CRTestCase().test_data))
323 suite.addTest(TestRunner(ShiftRotTestCase().test_data))
324 suite.addTest(TestRunner(LogicalTestCase().test_data))
325 suite.addTest(TestRunner(ALUTestCase().test_data))
326 suite.addTest(TestRunner(BranchTestCase().test_data))
327
328 runner = unittest.TextTestRunner()
329 runner.run(suite)