moving teststate_check_regs written by klehman into 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_check_regs
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 check_regs(dut, sim, core, test, code):
154 # create the two states and compare
155 testdic = {'sim': sim, 'hdl': core}
156 yield from teststate_check_regs(dut, testdic, test, code)
157
158
159 def wait_for_busy_hi(cu):
160 while True:
161 busy_o = yield cu.busy_o
162 terminate_o = yield cu.core_terminate_o
163 if busy_o:
164 print("busy/terminate:", busy_o, terminate_o)
165 break
166 print("!busy", busy_o, terminate_o)
167 yield
168
169
170 def set_issue(core, dec2, sim):
171 yield core.issue_i.eq(1)
172 yield
173 yield core.issue_i.eq(0)
174 yield from wait_for_busy_hi(core)
175
176
177 def wait_for_busy_clear(cu):
178 while True:
179 busy_o = yield cu.busy_o
180 terminate_o = yield cu.core_terminate_o
181 if not busy_o:
182 print("busy/terminate:", busy_o, terminate_o)
183 break
184 print("busy",)
185 yield
186
187
188 class TestRunner(FHDLTestCase):
189 def __init__(self, tst_data):
190 super().__init__("run_all")
191 self.test_data = tst_data
192
193 def run_all(self):
194 m = Module()
195 comb = m.d.comb
196 instruction = Signal(32)
197 ivalid_i = Signal()
198
199 pspec = TestMemPspec(ldst_ifacetype='testpi',
200 imem_ifacetype='',
201 addr_wid=48,
202 mask_wid=8,
203 reg_wid=64)
204
205 m.submodules.core = core = NonProductionCore(pspec)
206 pdecode2 = core.pdecode2
207 l0 = core.l0
208
209 comb += core.raw_opcode_i.eq(instruction)
210 comb += core.ivalid_i.eq(ivalid_i)
211
212 # temporary hack: says "go" immediately for both address gen and ST
213 ldst = core.fus.fus['ldst0']
214 m.d.comb += ldst.ad.go.eq(ldst.ad.rel) # link addr-go direct to rel
215 m.d.comb += ldst.st.go.eq(ldst.st.rel) # link store-go direct to rel
216
217 # nmigen Simulation
218 sim = Simulator(m)
219 sim.add_clock(1e-6)
220
221 def process():
222 yield core.issue_i.eq(0)
223 yield
224
225 for test in self.test_data:
226 print(test.name)
227 program = test.program
228 self.subTest(test.name)
229 sim = ISA(pdecode2, test.regs, test.sprs, test.cr, test.mem,
230 test.msr,
231 bigendian=bigendian)
232 gen = program.generate_instructions()
233 instructions = list(zip(gen, program.assembly.splitlines()))
234
235 yield from setup_tst_memory(l0, sim)
236 yield from setup_regs(core, test)
237
238 index = sim.pc.CIA.value // 4
239 while index < len(instructions):
240 ins, code = instructions[index]
241
242 print("instruction: 0x{:X}".format(ins & 0xffffffff))
243 print(code)
244
245 # ask the decoder to decode this binary data (endian'd)
246 yield core.bigendian_i.eq(bigendian) # little / big?
247 yield instruction.eq(ins) # raw binary instr.
248 yield ivalid_i.eq(1)
249 yield Settle()
250 # fn_unit = yield pdecode2.e.fn_unit
251 #fuval = self.funit.value
252 #self.assertEqual(fn_unit & fuval, fuval)
253
254 # set operand and get inputs
255 yield from set_issue(core, pdecode2, sim)
256 yield Settle()
257
258 yield from wait_for_busy_clear(core)
259 yield ivalid_i.eq(0)
260 yield
261
262 print("sim", code)
263 # call simulated operation
264 opname = code.split(' ')[0]
265 yield from sim.call(opname)
266 index = sim.pc.CIA.value // 4
267
268 # register check
269 yield from check_regs(self, sim, core, test, code)
270
271 # Memory check
272 yield from check_sim_memory(self, l0, sim, code)
273
274 sim.add_sync_process(process)
275 with sim.write_vcd("core_simulator.vcd", "core_simulator.gtkw",
276 traces=[]):
277 sim.run()
278
279
280 if __name__ == "__main__":
281 unittest.main(exit=False)
282 suite = unittest.TestSuite()
283 suite.addTest(TestRunner(LDSTTestCase().test_data))
284 suite.addTest(TestRunner(CRTestCase().test_data))
285 suite.addTest(TestRunner(ShiftRotTestCase().test_data))
286 suite.addTest(TestRunner(LogicalTestCase().test_data))
287 suite.addTest(TestRunner(ALUTestCase().test_data))
288 suite.addTest(TestRunner(BranchTestCase().test_data))
289
290 runner = unittest.TextTestRunner()
291 runner.run(suite)