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