Allow the formal engine to perform a same-cycle result in the ALU
[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.test.state import (SimState, teststate_check_regs,
15 teststate_check_mem)
16 from soc.simple.test.teststate import HDLState
17 from openpower.decoder.isa.caller import special_sprs
18 from openpower.decoder.power_decoder import create_pdecode
19 from openpower.decoder.power_decoder2 import PowerDecode2
20 from openpower.decoder.selectable_int import SelectableInt
21 from openpower.decoder.isa.all import ISA
22 from openpower.decoder.decode2execute1 import IssuerDecode2ToOperand
23 from openpower.state import CoreState
24
25 # note that using SPRreduced has to be done to match the
26 # PowerDecoder2 SPR map
27 from openpower.decoder.power_enums import SPRreduced as SPR
28 from openpower.decoder.power_enums import spr_dict, Function, XER_bits
29 from soc.config.test.test_loadstore import TestMemPspec
30 from openpower.endian import bigendian
31 from soc.regfile.regfiles import StateRegs
32
33 from soc.simple.core import NonProductionCore
34 from soc.experiment.compalu_multi import find_ok # hack
35
36 from soc.fu.compunits.test.test_compunit import (setup_tst_memory,
37 check_sim_memory)
38
39 # test with ALU data and Logical data
40 from soc.fu.alu.test.test_pipe_caller import ALUTestCase
41 from soc.fu.logical.test.test_pipe_caller import LogicalTestCase
42 from soc.fu.shift_rot.test.test_pipe_caller import ShiftRotTestCase
43 from soc.fu.cr.test.test_pipe_caller import CRTestCase
44 from soc.fu.branch.test.test_pipe_caller import BranchTestCase
45 from soc.fu.ldst.test.test_pipe_caller import LDSTTestCase
46 from openpower.test.general.overlap_hazards import (HazardTestCase,
47 RandomHazardTestCase)
48 from openpower.util import spr_to_fast_reg, spr_to_state_reg
49
50 from openpower.consts import StateRegsEnum
51
52 # list of SPRs that are controlled and managed by the MMU
53 mmu_sprs = ["PRTBL", "PIDR"]
54 ldst_sprs = ["DAR", "DSISR"]
55
56
57 def set_mmu_spr(name, i, val, core): # important keep pep8 formatting
58 fsm = core.fus.get_fu("mmu0").alu
59 yield fsm.mmu.l_in.mtspr.eq(1)
60 yield fsm.mmu.l_in.sprn.eq(i)
61 yield fsm.mmu.l_in.rs.eq(val)
62 yield
63 yield fsm.mmu.l_in.mtspr.eq(0)
64 while True:
65 done = yield fsm.mmu.l_out.done
66 if done:
67 break
68 yield
69 yield
70 print("mmu_spr %s %d was updated %x" % (name, i, val))
71
72
73 def set_ldst_spr(name, i, val, core): # important keep pep8 formatting
74 ldst = core.fus.get_fu("mmu0").alu.ldst # awkward to get at but it works
75 yield ldst.sprval_in.eq(val)
76 yield ldst.mmu_set_spr.eq(1)
77 if name == 'DAR':
78 yield ldst.mmu_set_dar.eq(1)
79 yield
80 yield ldst.mmu_set_dar.eq(0)
81 else:
82 yield ldst.mmu_set_dsisr.eq(1)
83 yield
84 yield ldst.mmu_set_dsisr.eq(0)
85 yield ldst.mmu_set_spr.eq(0)
86 print("ldst_spr %s %d was updated %x" % (name, i, val))
87
88
89 def setup_regs(pdecode2, core, test):
90
91 # set up INT regfile, "direct" write (bypass rd/write ports)
92 intregs = core.regs.int
93 for i in range(32):
94 if intregs.unary:
95 yield intregs.regs[i].reg.eq(test.regs[i])
96 else:
97 yield intregs.memory._array[i].eq(test.regs[i])
98 yield Settle()
99
100 # set up MSR in STATE regfile, "direct" write (bypass rd/write ports)
101 stateregs = core.regs.state
102 yield stateregs.regs[StateRegsEnum.MSR].reg.eq(test.msr)
103
104 # set up CR regfile, "direct" write across all CRs
105 cr = test.cr
106 crregs = core.regs.cr
107 #cr = int('{:32b}'.format(cr)[::-1], 2)
108 print("setup cr reg", hex(cr))
109 for i in range(8):
110 #j = 7-i
111 cri = (cr >> (i * 4)) & 0xf
112 #cri = int('{:04b}'.format(cri)[::-1], 2)
113 print("setup cr reg", hex(cri), i,
114 crregs.regs[i].reg.shape())
115 yield crregs.regs[i].reg.eq(cri)
116
117 # set up XER. "direct" write (bypass rd/write ports)
118 xregs = core.regs.xer
119 print("setup sprs", test.sprs)
120 xer = None
121 if 'XER' in test.sprs:
122 xer = test.sprs['XER']
123 if 1 in test.sprs:
124 xer = test.sprs[1]
125 if xer is not None:
126 if isinstance(xer, int):
127 xer = SelectableInt(xer, 64)
128 sobit = xer[XER_bits['SO']].value
129 yield xregs.regs[xregs.SO].reg.eq(sobit)
130 cabit = xer[XER_bits['CA']].value
131 ca32bit = xer[XER_bits['CA32']].value
132 yield xregs.regs[xregs.CA].reg.eq(Cat(cabit, ca32bit))
133 ovbit = xer[XER_bits['OV']].value
134 ov32bit = xer[XER_bits['OV32']].value
135 yield xregs.regs[xregs.OV].reg.eq(Cat(ovbit, ov32bit))
136 print("setting XER so %d ca %d ca32 %d ov %d ov32 %d" %
137 (sobit, cabit, ca32bit, ovbit, ov32bit))
138 else:
139 yield xregs.regs[xregs.SO].reg.eq(0)
140 yield xregs.regs[xregs.OV].reg.eq(0)
141 yield xregs.regs[xregs.CA].reg.eq(0)
142
143 # setting both fast and slow SPRs from test data
144
145 fregs = core.regs.fast
146 stateregs = core.regs.state
147 sregs = core.regs.spr
148 for sprname, val in test.sprs.items():
149 if isinstance(val, SelectableInt):
150 val = val.value
151 if isinstance(sprname, int):
152 sprname = spr_dict[sprname].SPR
153 if sprname == 'XER':
154 continue
155 print ('set spr %s val %x' % (sprname, val))
156
157 fast = spr_to_fast_reg(sprname)
158 state = spr_to_state_reg(sprname)
159
160 if fast is None and state is None:
161 # match behaviour of SPRMap in power_decoder2.py
162 for i, x in enumerate(SPR):
163 if sprname == x.name:
164 print("setting slow SPR %d (%s/%d) to %x" %
165 (i, sprname, x.value, val))
166 if sprname in mmu_sprs:
167 yield from set_mmu_spr(sprname, x.value, val, core)
168 elif sprname in ldst_sprs:
169 yield from set_ldst_spr(sprname, x.value, val, core)
170 else:
171 yield sregs.memory._array[i].eq(val)
172 elif state is not None:
173 print("setting state reg %d (%s) to %x" %
174 (state, sprname, val))
175 if stateregs.unary:
176 rval = stateregs.regs[state].reg
177 else:
178 rval = stateregs.memory._array[state]
179 yield rval.eq(val)
180 else:
181 print("setting fast reg %d (%s) to %x" %
182 (fast, sprname, val))
183 if fregs.unary:
184 rval = fregs.int.regs[fast].reg
185 else:
186 rval = fregs.memory._array[fast]
187 yield rval.eq(val)
188
189 # allow changes to settle before reporting on XER
190 yield Settle()
191
192 # XER
193 so = yield xregs.regs[xregs.SO].reg
194 ov = yield xregs.regs[xregs.OV].reg
195 ca = yield xregs.regs[xregs.CA].reg
196 oe = yield pdecode2.e.do.oe.oe
197 oe_ok = yield pdecode2.e.do.oe.oe_ok
198
199 print("before: so/ov-32/ca-32", so, bin(ov), bin(ca))
200 print("oe:", oe, oe_ok)
201
202
203 def check_regs(dut, sim, core, test, code):
204 # create the two states and compare
205 testdic = {'sim': sim, 'hdl': core}
206 yield from teststate_check_regs(dut, testdic, test, code)
207
208
209 def check_mem(dut, sim, core, test, code):
210 # create the two states and compare mem
211 testdic = {'sim': sim, 'hdl': core}
212 yield from teststate_check_mem(dut, testdic, test, code)
213
214
215 def wait_for_busy_hi(cu):
216 while True:
217 busy_o = yield cu.busy_o
218 terminate_o = yield cu.core_terminate_o
219 if busy_o:
220 print("busy/terminate:", busy_o, terminate_o)
221 break
222 print("!busy", busy_o, terminate_o)
223 yield
224
225
226 def set_issue(core, dec2, sim):
227 yield core.issue_i.eq(1)
228 yield
229 yield core.issue_i.eq(0)
230 yield from wait_for_busy_hi(core)
231
232
233 def wait_for_busy_clear(cu):
234 while True:
235 busy_o = yield cu.o.busy_o
236 terminate_o = yield cu.o.core_terminate_o
237 if not busy_o:
238 print("busy/terminate:", busy_o, terminate_o)
239 break
240 print("busy",)
241 yield
242
243
244 class TestRunner(FHDLTestCase):
245 def __init__(self, tst_data):
246 super().__init__("run_all")
247 self.test_data = tst_data
248
249 def run_all(self):
250 m = Module()
251 comb = m.d.comb
252 instruction = Signal(32)
253
254 units = {'alu': 3, 'cr': 1, 'branch': 1, 'trap': 1,
255 'spr': 1,
256 'logical': 1,
257 'mul': 3,
258 'div': 1, 'shiftrot': 1}
259
260 pspec = TestMemPspec(ldst_ifacetype='testpi',
261 imem_ifacetype='',
262 addr_wid=48,
263 mask_wid=8,
264 units=units,
265 allow_overlap=True,
266 reg_wid=64)
267
268 cur_state = CoreState("cur") # current state (MSR/PC/SVSTATE)
269 pdecode2 = PowerDecode2(None, state=cur_state,
270 #opkls=IssuerDecode2ToOperand,
271 svp64_en=True, # self.svp64_en,
272 regreduce_en=False, #self.regreduce_en
273 )
274
275 m.submodules.core = core = NonProductionCore(pspec)
276 m.submodules.pdecode2 = pdecode2
277 core.pdecode2 = pdecode2
278 l0 = core.l0
279
280 comb += pdecode2.dec.raw_opcode_in.eq(instruction)
281 comb += pdecode2.dec.bigendian.eq(bigendian) # little / big?
282 comb += core.i.e.eq(pdecode2.e)
283 comb += core.i.state.eq(cur_state)
284 comb += core.i.raw_insn_i.eq(instruction)
285 comb += core.i.bigendian_i.eq(bigendian)
286
287 # set the PC StateRegs read port to always send back the PC
288 stateregs = core.regs.state
289 pc_regnum = StateRegs.PC
290 comb += stateregs.r_ports['cia'].ren.eq(1<<pc_regnum)
291
292 # temporary hack: says "go" immediately for both address gen and ST
293 ldst = core.fus.fus['ldst0']
294 m.d.comb += ldst.ad.go_i.eq(ldst.ad.rel_o) # link addr-go to rel
295 m.d.comb += ldst.st.go_i.eq(ldst.st.rel_o) # link store-go to rel
296
297 # nmigen Simulation
298 sim = Simulator(m)
299 sim.add_clock(1e-6)
300
301 def process():
302 yield
303
304 for test in self.test_data:
305 print(test.name)
306 program = test.program
307 with self.subTest(test.name):
308 sim = ISA(pdecode2, test.regs, test.sprs, test.cr,
309 test.mem,
310 test.msr,
311 bigendian=bigendian)
312 gen = program.generate_instructions()
313 instructions = list(zip(gen, program.assembly.splitlines()))
314
315 yield from setup_tst_memory(l0, test.mem)
316 yield from setup_regs(pdecode2, core, test)
317
318 index = sim.pc.CIA.value // 4
319 while index < len(instructions):
320 ins, code = instructions[index]
321
322 print("instruction: 0x{:X}".format(ins & 0xffffffff))
323 print(code)
324
325 # ask the decoder to decode this binary data (endian'd)
326 yield instruction.eq(ins) # raw binary instr.
327 yield Settle()
328
329 print("sim", code)
330 # call simulated operation
331 opname = code.split(' ')[0]
332 yield from sim.call(opname)
333 pc = sim.pc.CIA.value
334 nia = sim.pc.NIA.value
335 index = pc // 4
336
337 # set the PC to the same simulated value
338 # (core is not able to do this itself, except
339 # for branch / TRAP)
340 print ("after call, pc nia", pc, nia)
341 yield stateregs.regs[pc_regnum].reg.eq(pc)
342 yield Settle()
343
344 yield core.p.i_valid.eq(1)
345 yield
346 o_ready = yield core.p.o_ready
347 while True:
348 if o_ready:
349 break
350 yield
351 o_ready = yield core.p.o_ready
352 yield core.p.i_valid.eq(0)
353
354 # set operand and get inputs
355 yield from wait_for_busy_clear(core)
356
357 # synchronised (non-overlap) is fine to check
358 if not core.allow_overlap:
359 # register check
360 yield from check_regs(self, sim, core, test, code)
361
362 # Memory check
363 yield from check_mem(self, sim, core, test, code)
364
365 # non-overlap mode is only fine to check right at the end
366 if core.allow_overlap:
367 # wait until all settled
368 # XXX really this should be in DMI, which should in turn
369 # use issuer.any_busy to not send back "stopped" signal
370 while (yield core.o.any_busy_o):
371 yield
372 yield Settle()
373
374 # register check
375 yield from check_regs(self, sim, core, test, code)
376
377 # Memory check
378 yield from check_mem(self, sim, core, test, code)
379
380 # give a couple extra clock cycles for gtkwave display to be happy
381 yield
382 yield
383
384 sim.add_sync_process(process)
385 with sim.write_vcd("core_simulator.vcd", "core_simulator.gtkw",
386 traces=[]):
387 sim.run()
388
389
390 if __name__ == "__main__":
391 unittest.main(exit=False)
392 suite = unittest.TestSuite()
393 suite.addTest(TestRunner(HazardTestCase().test_data))
394 suite.addTest(TestRunner(RandomHazardTestCase().test_data))
395 #suite.addTest(TestRunner(LDSTTestCase().test_data))
396 #suite.addTest(TestRunner(CRTestCase().test_data))
397 #suite.addTest(TestRunner(ShiftRotTestCase().test_data))
398 #suite.addTest(TestRunner(LogicalTestCase().test_data))
399 #suite.addTest(TestRunner(ALUTestCase().test_data))
400 #suite.addTest(TestRunner(BranchTestCase().test_data))
401
402 runner = unittest.TextTestRunner()
403 runner.run(suite)