testcase for dcbz
[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 soc.decoder.isa.caller import ISACaller, special_sprs
10 from soc.decoder.power_decoder import (create_pdecode)
11 from soc.decoder.power_decoder2 import (PowerDecode2)
12 from soc.decoder.power_enums import (XER_bits, Function, MicrOp, CryIn)
13 from soc.decoder.selectable_int import SelectableInt
14 from soc.simulator.program import Program
15 from soc.decoder.isa.all import ISA
16 from soc.config.endian import bigendian
17 from soc.consts import MSR
18
19
20 from soc.fu.test.common import (
21 TestAccumulatorBase, skip_case, TestCase, ALUHelpers)
22 #from soc.fu.spr.pipeline import SPRBasePipe
23 #from soc.fu.spr.pipe_data import SPRPipeSpec
24 from soc.fu.mmu.fsm import FSMMMUStage
25 from soc.fu.mmu.pipe_data import MMUPipeSpec
26 import random
27
28 from soc.fu.div.test.helper import (log_rand, get_cu_inputs,
29 set_alu_inputs, DivTestHelper)
30
31 import power_instruction_analyzer as pia
32
33 debughang = 1
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 data_i.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 class MMUTestCase(TestAccumulatorBase):
73
74 def case_1_mmu(self):
75 # test case for MTSPR, MFSPR, DCBZ and TLBIE.
76 #lst = ["dcbz 2,3"] not yet implemented
77 lst = [#"mtspr 18, 1", # DSISR
78 #"mtspr 19, 2", # DAR
79 #"mtspr 26, 3", # SRR0
80 #"mtspr 27, 4", # SRR1
81
82 #"mfspr 18, 1", # DSISR
83 #"mfspr 19, 2", # DAR
84 #"mfspr 26, 3", # SRR0
85 #"mfspr 27, 4", # SRR1
86
87 #next two need to be added to the simulator
88 "dcbz 5,6" # Data Cache Block set to Zero - RA,RB (hangs)
89 #"tlbie 1,1,1,1,1" #does not hang -- not verified yet
90 ]
91
92 initial_regs = [0] * 32
93 initial_regs[1] = 0xBADCAB1E
94 initial_regs[2] = 0xDEADC0DE
95 initial_regs[5] = 0x100
96 initial_regs[6] = 0x100
97
98 initial_sprs = {'SRR0': 0x12345678, 'SRR1': 0x5678, 'LR': 0x1234,
99 'XER': 0xe00c0000}
100 self.add_case(Program(lst, bigendian),
101 initial_regs, initial_sprs)
102
103 #def case_ilang(self):
104 # pspec = SPRPipeSpec(id_wid=2)
105 # alu = SPRBasePipe(pspec)
106 # vl = rtlil.convert(alu, ports=alu.ports())
107 # with open("trap_pipeline.il", "w") as f:
108 # f.write(vl)
109
110
111 class TestRunner(unittest.TestCase):
112 def __init__(self, test_data):
113 super().__init__("run_all")
114 self.test_data = test_data
115
116 def check_fsm_outputs(self, alu, dec2, sim, code, pia_res):
117
118 rc = yield dec2.e.do.rc.data
119 cridx_ok = yield dec2.e.write_cr.ok
120 cridx = yield dec2.e.write_cr.data
121
122 print("check extra output", repr(code), cridx_ok, cridx)
123 if rc:
124 self.assertEqual(cridx, 0, code)
125
126 sim_o = {}
127 res = {}
128
129 #MMUOutputData does not have xer
130
131 yield from ALUHelpers.get_cr_a(res, alu, dec2)
132 #yield from ALUHelpers.get_xer_ov(res, alu, dec2)
133 yield from ALUHelpers.get_int_o(res, alu, dec2)
134 #yield from ALUHelpers.get_xer_so(res, alu, dec2)
135
136
137 print("res output", res)
138
139 yield from ALUHelpers.get_sim_int_o(sim_o, sim, dec2)
140 yield from ALUHelpers.get_wr_sim_cr_a(sim_o, sim, dec2)
141 #yield from ALUHelpers.get_sim_xer_ov(sim_o, sim, dec2)
142 #yield from ALUHelpers.get_sim_xer_so(sim_o, sim, dec2)
143
144 print("sim output", sim_o)
145
146 print("power-instruction-analyzer result:")
147 print(pia_res)
148 #if pia_res is not None:
149 # with self.subTest(check="pia", sim_o=sim_o, pia_res=str(pia_res)):
150 # pia_o = pia_res_to_output(pia_res)
151 # ALUHelpers.check_int_o(self, res, pia_o, code)
152 # ALUHelpers.check_cr_a(self, res, pia_o, code)
153 # #ALUHelpers.check_xer_ov(self, res, pia_o, code)
154 # #ALUHelpers.check_xer_so(self, res, pia_o, code)
155
156 with self.subTest(check="sim", sim_o=sim_o, pia_res=str(pia_res)):
157 #ALUHelpers.check_int_o(self, res, sim_o, code) # mmu is not an alu
158 ALUHelpers.check_cr_a(self, res, sim_o, code)
159 #ALUHelpers.check_xer_ov(self, res, sim_o, code)
160 #ALUHelpers.check_xer_so(self, res, sim_o, code)
161
162 #oe = yield dec2.e.do.oe.oe
163 #oe_ok = yield dec2.e.do.oe.ok
164 #print("oe, oe_ok", oe, oe_ok)
165 #if not oe or not oe_ok:
166 # # if OE not enabled, XER SO and OV must not be activated
167 # so_ok = yield alu.n.data_o.xer_so.ok
168 # ov_ok = yield alu.n.data_o.xer_ov.ok
169 # print("so, ov", so_ok, ov_ok)
170 # self.assertEqual(ov_ok, False, code)
171 # self.assertEqual(so_ok, False, code)
172
173 def execute(self, fsm, instruction, pdecode2, test):
174 program = test.program
175 sim = ISA(pdecode2, test.regs, test.sprs, test.cr,
176 test.mem, test.msr,
177 bigendian=bigendian)
178 gen = program.generate_instructions()
179 instructions = list(zip(gen, program.assembly.splitlines()))
180
181 pc = sim.pc.CIA.value
182 msr = sim.msr.value
183 index = pc//4
184 while index < len(instructions):
185 ins, code = instructions[index]
186
187 print("pc %08x instr: %08x" % (pc, ins & 0xffffffff))
188 print(code)
189
190 if 'XER' in sim.spr:
191 so = 1 if sim.spr['XER'][XER_bits['SO']] else 0
192 ov = 1 if sim.spr['XER'][XER_bits['OV']] else 0
193 ov32 = 1 if sim.spr['XER'][XER_bits['OV32']] else 0
194 print("before: so/ov/32", so, ov, ov32)
195
196 # ask the decoder to decode this binary data (endian'd)
197 yield pdecode2.dec.bigendian.eq(bigendian) # little / big?
198 yield pdecode2.state.msr.eq(msr) # set MSR in pdecode2
199 yield pdecode2.state.pc.eq(pc) # set PC in pdecode2
200 yield instruction.eq(ins) # raw binary instr.
201 yield Settle()
202
203 fast_in = yield pdecode2.e.read_fast1.data
204 spr_in = yield pdecode2.e.read_spr1.data
205 print("dec2 spr/fast in", fast_in, spr_in)
206
207 fast_out = yield pdecode2.e.write_fast1.data
208 spr_out = yield pdecode2.e.write_spr.data
209 print("dec2 spr/fast in", fast_out, spr_out)
210
211 fn_unit = yield pdecode2.e.do.fn_unit
212 #FIXME this fails -- self.assertEqual(fn_unit, Function.SPR.value)
213 pia_res = yield from set_fsm_inputs(fsm, pdecode2, sim)
214 yield
215 opname = code.split(' ')[0]
216 yield from sim.call(opname)
217 pc = sim.pc.CIA.value
218 msr = sim.msr.value
219 index = pc//4
220 print("pc after %08x" % (pc))
221
222 vld = yield fsm.n.valid_o #fsm
223 while not vld:
224 yield
225 if debughang: print("not valid -- hang")
226 vld = yield fsm.n.valid_o
227 if debughang==2: vld=1
228 yield
229
230 yield from self.check_fsm_outputs(fsm, pdecode2, sim, code, pia_res)
231
232 def run_all(self):
233 m = Module()
234 comb = m.d.comb
235 instruction = Signal(32)
236
237 pdecode = create_pdecode()
238
239 m.submodules.pdecode2 = pdecode2 = PowerDecode2(pdecode)
240
241 pspec = MMUPipeSpec(id_wid=2)
242 m.submodules.fsm = fsm = FSMMMUStage(pspec)
243
244 #FIXME connect fsm inputs
245
246 comb += fsm.p.data_i.ctx.op.eq_from_execute1(pdecode2.do)
247 comb += fsm.p.valid_i.eq(1)
248 comb += fsm.n.ready_i.eq(1)
249 comb += pdecode2.dec.raw_opcode_in.eq(instruction)
250 sim = Simulator(m)
251
252 sim.add_clock(1e-6)
253
254 def process():
255 for test in self.test_data:
256 print("test", test.name)
257 print("sprs", test.sprs)
258 program = test.program
259 with self.subTest(test.name):
260 yield from self.execute(fsm, instruction, pdecode2, test)
261
262 sim.add_sync_process(process)
263 with sim.write_vcd("alu_simulator.vcd", "simulator.gtkw",
264 traces=[]):
265 sim.run()
266
267 if __name__ == "__main__":
268 unittest.main(exit=False)
269 suite = unittest.TestSuite()
270 suite.addTest(TestRunner(MMUTestCase().test_data))
271
272 runner = unittest.TextTestRunner()
273 runner.run(suite)