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