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