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