70c853ebf172b61b5299949ddbd1e26c19d69316
[soc.git] / src / soc / fu / mmu / test / test_pipe_caller.py
1 from nmigen import Module, Signal
2
3 # NOTE: to use cxxsim, export NMIGEN_SIM_MODE=cxxsim from the shell
4 # Also, check out the cxxsim nmigen branch, and latest yosys from git
5 from nmutil.sim_tmp_alternative import Simulator, Settle
6
7 from nmigen.cli import rtlil
8 import unittest
9 from openpower.decoder.power_decoder import create_pdecode
10 from openpower.decoder.power_decoder2 import PowerDecode2
11 from openpower.decoder.power_enums import (XER_bits, Function, MicrOp, CryIn)
12 from openpower.simulator.program import Program
13 from openpower.decoder.isa.all import ISA
14 from openpower.endian import bigendian
15 from openpower.consts import MSR
16
17 from openpower.test.mmu.mmu_cases import MMUTestCase
18
19 from openpower.test.common import (TestAccumulatorBase, skip_case, ALUHelpers)
20 from soc.config.test.test_loadstore import TestMemPspec
21 #from soc.fu.spr.pipeline import SPRBasePipe
22 #from soc.fu.spr.pipe_data import SPRPipeSpec
23 from soc.fu.mmu.fsm import FSMMMUStage, LoadStore1
24 from soc.fu.mmu.pipe_data import MMUPipeSpec
25 import random
26
27 from soc.fu.div.test.helper import (log_rand, get_cu_inputs,
28 set_alu_inputs)
29
30 import power_instruction_analyzer as pia
31
32 debughang = 1
33
34
35 def set_fsm_inputs(alu, dec2, sim):
36 # TODO: see https://bugs.libre-soc.org/show_bug.cgi?id=305#c43
37 # detect the immediate here (with m.If(self.i.ctx.op.imm_data.imm_ok))
38 # and place it into i_data.b
39
40 print("Error here")
41 inp = yield from get_cu_inputs(dec2, sim)
42 # set int registers a and b
43 yield from ALUHelpers.set_int_ra(alu, dec2, inp)
44 yield from ALUHelpers.set_int_rb(alu, dec2, inp)
45 # TODO set spr register
46 # yield from ALUHelpers.set_spr_spr1(alu, dec2, inp)
47
48 overflow = None
49 a = None
50 b = None
51 # TODO
52 if 'xer_so' in inp:
53 print("xer_so::::::::::::::::::::::::::::::::::::::::::::::::")
54 so = inp['xer_so']
55 print(so)
56 overflow = pia.OverflowFlags(so=bool(so),
57 ov=False,
58 ov32=False)
59 if 'ra' in inp:
60 a = inp['ra']
61 if 'rb' in inp:
62 b = inp['rb']
63 print(inp)
64 return pia.InstructionInput(ra=a, rb=b, overflow=overflow)
65
66
67 def check_fsm_outputs(fsm, pdecode2, sim, code):
68 # check that MMUOutputData is correct
69 return None # TODO
70
71 # incomplete test - connect fsm inputs first
72
73
74 class MMUIlangCase(TestAccumulatorBase):
75 # def case_ilang(self):
76 # pspec = SPRPipeSpec(id_wid=2)
77 # alu = SPRBasePipe(pspec)
78 # vl = rtlil.convert(alu, ports=alu.ports())
79 # with open("trap_pipeline.il", "w") as f:
80 # f.write(vl)
81 pass
82
83
84 class TestRunner(unittest.TestCase):
85 def __init__(self, test_data):
86 super().__init__("run_all")
87 self.test_data = test_data
88 # hack here -- all unit tests are affected
89 self.run_all()
90
91 def check_fsm_outputs(self, alu, dec2, sim, code, pia_res):
92
93 rc = yield dec2.e.do.rc.data
94 cridx_ok = yield dec2.e.write_cr.ok
95 cridx = yield dec2.e.write_cr.data
96
97 print("check extra output", repr(code), cridx_ok, cridx)
98 if rc:
99 self.assertEqual(cridx, 0, code)
100
101 sim_o = {}
102 res = {}
103
104 # MMUOutputData does not have xer
105
106 yield from ALUHelpers.get_cr_a(res, alu, dec2)
107 # yield from ALUHelpers.get_xer_ov(res, alu, dec2)
108 yield from ALUHelpers.get_int_o(res, alu, dec2)
109 # yield from ALUHelpers.get_xer_so(res, alu, dec2)
110
111 print("res output", res)
112
113 yield from ALUHelpers.get_sim_int_o(sim_o, sim, dec2)
114 yield from ALUHelpers.get_wr_sim_cr_a(sim_o, sim, dec2)
115 # yield from ALUHelpers.get_sim_xer_ov(sim_o, sim, dec2)
116 # yield from ALUHelpers.get_sim_xer_so(sim_o, sim, dec2)
117
118 print("sim output", sim_o)
119
120 print("power-instruction-analyzer result:")
121 print(pia_res)
122 # if pia_res is not None:
123 # with self.subTest(check="pia", sim_o=sim_o, pia_res=str(pia_res)):
124 # pia_o = pia_res_to_output(pia_res)
125 # ALUHelpers.check_int_o(self, res, pia_o, code)
126 # ALUHelpers.check_cr_a(self, res, pia_o, code)
127 # #ALUHelpers.check_xer_ov(self, res, pia_o, code)
128 # #ALUHelpers.check_xer_so(self, res, pia_o, code)
129
130 with self.subTest(check="sim", sim_o=sim_o, pia_res=str(pia_res)):
131 # ALUHelpers.check_int_o(self, res, sim_o, code) # mmu is not an alu
132 ALUHelpers.check_cr_a(self, res, sim_o, code)
133 #ALUHelpers.check_xer_ov(self, res, sim_o, code)
134 #ALUHelpers.check_xer_so(self, res, sim_o, code)
135
136 # oe = yield dec2.e.do.oe.oe
137 # oe_ok = yield dec2.e.do.oe.ok
138 #print("oe, oe_ok", oe, oe_ok)
139 # if not oe or not oe_ok:
140 # # if OE not enabled, XER SO and OV must not be activated
141 # so_ok = yield alu.n.o_data.xer_so.ok
142 # ov_ok = yield alu.n.o_data.xer_ov.ok
143 # print("so, ov", so_ok, ov_ok)
144 # self.assertEqual(ov_ok, False, code)
145 # self.assertEqual(so_ok, False, code)
146
147 def execute(self, fsm, instruction, pdecode2, test):
148 program = test.program
149 sim = ISA(pdecode2, test.regs, test.sprs, test.cr,
150 test.mem, test.msr,
151 bigendian=bigendian)
152 gen = program.generate_instructions()
153 instructions = list(zip(gen, program.assembly.splitlines()))
154
155 pc = sim.pc.CIA.value
156 msr = sim.msr.value
157 index = pc//4
158 while index < len(instructions):
159 ins, code = instructions[index]
160
161 print("pc %08x instr: %08x" % (pc, ins & 0xffffffff))
162 print(code)
163
164 if 'XER' in sim.spr:
165 so = 1 if sim.spr['XER'][XER_bits['SO']] else 0
166 ov = 1 if sim.spr['XER'][XER_bits['OV']] else 0
167 ov32 = 1 if sim.spr['XER'][XER_bits['OV32']] else 0
168 print("before: so/ov/32", so, ov, ov32)
169
170 # ask the decoder to decode this binary data (endian'd)
171 yield pdecode2.dec.bigendian.eq(bigendian) # little / big?
172 yield pdecode2.state.msr.eq(msr) # set MSR in pdecode2
173 yield pdecode2.state.pc.eq(pc) # set PC in pdecode2
174 yield instruction.eq(ins) # raw binary instr.
175 yield Settle()
176
177 fast_in = yield pdecode2.e.read_fast1.data
178 spr_in = yield pdecode2.e.read_spr1.data
179 print("dec2 spr/fast in", fast_in, spr_in)
180
181 fast_out = yield pdecode2.e.write_fast1.data
182 spr_out = yield pdecode2.e.write_spr.data
183 print("dec2 spr/fast in", fast_out, spr_out)
184
185 fn_unit = yield pdecode2.e.do.fn_unit
186 # FIXME this fails -- self.assertEqual(fn_unit, Function.SPR.value)
187 pia_res = yield from set_fsm_inputs(fsm, pdecode2, sim)
188 yield
189 opname = code.split(' ')[0]
190 yield from sim.call(opname)
191 pc = sim.pc.CIA.value
192 msr = sim.msr.value
193 index = pc//4
194 print("pc after %08x" % (pc))
195
196 vld = yield fsm.n.o_valid # fsm
197 while not vld:
198 yield
199 if debughang:
200 print("not valid -- hang")
201 return
202 vld = yield fsm.n.o_valid
203 if debughang == 2:
204 vld = 1
205 yield
206
207 yield from self.check_fsm_outputs(fsm, pdecode2, sim, code, pia_res)
208
209 def run_all(self):
210 m = Module()
211 comb = m.d.comb
212 instruction = Signal(32)
213
214 pspec = TestMemPspec(addr_wid=48,
215 mask_wid=8,
216 reg_wid=64,
217 )
218
219 pdecode = create_pdecode()
220
221 m.submodules.pdecode2 = pdecode2 = PowerDecode2(pdecode)
222
223 pipe_spec = MMUPipeSpec(id_wid=2)
224 ldst = LoadStore1(pspec)
225 fsm = FSMMMUStage(pipe_spec)
226 fsm.set_ldst_interface(ldst)
227 m.submodules.fsm = fsm
228 m.submodules.ldst = ldst
229
230 # FIXME connect fsm inputs
231
232 comb += fsm.p.i_data.ctx.op.eq_from_execute1(pdecode2.do)
233 comb += fsm.p.i_valid.eq(1)
234 comb += fsm.n.i_ready.eq(1)
235 comb += pdecode2.dec.raw_opcode_in.eq(instruction)
236 sim = Simulator(m)
237
238 sim.add_clock(1e-6)
239
240 def process():
241 for test in self.test_data:
242 print("test", test.name)
243 print("sprs", test.sprs)
244 program = test.program
245 with self.subTest(test.name):
246 yield from self.execute(fsm, instruction, pdecode2, test)
247
248 sim.add_sync_process(process)
249 with sim.write_vcd("alu_simulator.vcd", "simulator.gtkw",
250 traces=[]):
251 sim.run()
252
253
254 if __name__ == "__main__":
255 unittest.main(exit=False)
256 suite = unittest.TestSuite()
257 suite.addTest(TestRunner(MMUTestCase().test_data))
258 suite.addTest(TestRunner(MMUIlangCase().test_data))
259
260 runner = unittest.TextTestRunner()
261 runner.run(suite)