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