sorting out bigendian/littleendian including in qemu
[soc.git] / src / soc / fu / spr / test / test_pipe_caller.py
1 from nmigen import Module, Signal
2 from nmigen.back.pysim import Simulator, Delay, Settle
3 from nmutil.formaltest import FHDLTestCase
4 from nmigen.cli import rtlil
5 import unittest
6 from soc.decoder.isa.caller import ISACaller, special_sprs
7 from soc.decoder.power_decoder import (create_pdecode)
8 from soc.decoder.power_decoder2 import (PowerDecode2)
9 from soc.decoder.power_enums import (XER_bits, Function, InternalOp, CryIn)
10 from soc.decoder.selectable_int import SelectableInt
11 from soc.simulator.program import Program
12 from soc.decoder.isa.all import ISA
13 from soc.config.endian import bigendian
14
15 from soc.fu.test.common import (TestCase, ALUHelpers)
16 from soc.fu.spr.pipeline import SPRBasePipe
17 from soc.fu.spr.pipe_data import SPRPipeSpec
18 import random
19
20
21 def get_cu_inputs(dec2, sim):
22 """naming (res) must conform to SPRFunctionUnit input regspec
23 """
24 res = {}
25
26 yield from ALUHelpers.get_sim_int_ra(res, sim, dec2) # RA
27 yield from ALUHelpers.get_sim_int_rb(res, sim, dec2) # RB
28 yield from ALUHelpers.get_sim_slow_spr1(res, sim, dec2) # FAST1
29 yield from ALUHelpers.get_sim_fast_spr1(res, sim, dec2) # FAST1
30 yield from ALUHelpers.get_rd_sim_xer_ca(res, sim, dec2) # XER.ca
31 yield from ALUHelpers.get_sim_xer_ov(res, sim, dec2) # XER.ov
32 yield from ALUHelpers.get_sim_xer_so(res, sim, dec2) # XER.so
33
34 print ("spr get_cu_inputs", res)
35
36 return res
37
38
39
40 def set_alu_inputs(alu, dec2, sim):
41 # TODO: see https://bugs.libre-soc.org/show_bug.cgi?id=305#c43
42 # detect the immediate here (with m.If(self.i.ctx.op.imm_data.imm_ok))
43 # and place it into data_i.b
44
45 inp = yield from get_cu_inputs(dec2, sim)
46 yield from ALUHelpers.set_int_ra(alu, dec2, inp)
47 yield from ALUHelpers.set_xer_ca(alu, dec2, inp)
48 yield from ALUHelpers.set_xer_ov(alu, dec2, inp)
49 yield from ALUHelpers.set_xer_so(alu, dec2, inp)
50
51 yield from ALUHelpers.set_fast_spr1(alu, dec2, inp)
52 yield from ALUHelpers.set_slow_spr1(alu, dec2, inp)
53
54
55 # This test bench is a bit different than is usual. Initially when I
56 # was writing it, I had all of the tests call a function to create a
57 # device under test and simulator, initialize the dut, run the
58 # simulation for ~2 cycles, and assert that the dut output what it
59 # should have. However, this was really slow, since it needed to
60 # create and tear down the dut and simulator for every test case.
61
62 # Now, instead of doing that, every test case in SPRTestCase puts some
63 # data into the test_data list below, describing the instructions to
64 # be tested and the initial state. Once all the tests have been run,
65 # test_data gets passed to TestRunner which then sets up the DUT and
66 # simulator once, runs all the data through it, and asserts that the
67 # results match the pseudocode sim at every cycle.
68
69 # By doing this, I've reduced the time it takes to run the test suite
70 # massively. Before, it took around 1 minute on my computer, now it
71 # takes around 3 seconds
72
73
74 class SPRTestCase(FHDLTestCase):
75 test_data = []
76
77 def __init__(self, name):
78 super().__init__(name)
79 self.test_name = name
80
81 def run_tst_program(self, prog, initial_regs=None, initial_sprs=None):
82 tc = TestCase(prog, self.test_name, initial_regs, initial_sprs)
83 self.test_data.append(tc)
84
85 def test_1_mfspr(self):
86 lst = ["mfspr 1, 26", # SRR0
87 "mfspr 2, 27", # SRR1
88 "mfspr 3, 8", # LR
89 "mfspr 4, 1",] # XER
90 initial_regs = [0] * 32
91 initial_sprs = {'SRR0': 0x12345678, 'SRR1': 0x5678, 'LR': 0x1234,
92 'XER': 0xe00c0000}
93 self.run_tst_program(Program(lst, bigendian), initial_regs, initial_sprs)
94
95 def test_1_mtspr(self):
96 lst = ["mtspr 26, 1", # SRR0
97 "mtspr 27, 2", # SRR1
98 "mtspr 1, 3", # XER
99 "mtspr 9, 4",] # CTR
100 initial_regs = [0] * 32
101 initial_regs[1] = 0x129518230011feed
102 initial_regs[2] = 0x123518230011feed
103 initial_regs[3] = 0xe00c0000
104 initial_regs[4] = 0x1010101010101010
105 initial_sprs = {'SRR0': 0x12345678, 'SRR1': 0x5678, 'LR': 0x1234,
106 'XER': 0x0}
107 self.run_tst_program(Program(lst, bigendian),
108 initial_regs, initial_sprs)
109
110 def test_2_mtspr_mfspr(self):
111 lst = ["mtspr 26, 1", # SRR0
112 "mtspr 27, 2", # SRR1
113 "mtspr 1, 3", # XER
114 "mtspr 9, 4", # CTR
115 "mfspr 2, 26", # SRR0
116 "mfspr 3, 27", # and into reg 2
117 "mfspr 4, 1", # XER
118 "mfspr 5, 9",] # CTR
119 initial_regs = [0] * 32
120 initial_regs[1] = 0x129518230011feed
121 initial_regs[2] = 0x123518230011feed
122 initial_regs[3] = 0xe00c0000
123 initial_regs[4] = 0x1010101010101010
124 initial_sprs = {'SRR0': 0x12345678, 'SRR1': 0x5678, 'LR': 0x1234,
125 'XER': 0x0}
126 self.run_tst_program(Program(lst, bigendian),
127 initial_regs, initial_sprs)
128
129 def test_ilang(self):
130 pspec = SPRPipeSpec(id_wid=2)
131 alu = SPRBasePipe(pspec)
132 vl = rtlil.convert(alu, ports=alu.ports())
133 with open("trap_pipeline.il", "w") as f:
134 f.write(vl)
135
136
137 class TestRunner(FHDLTestCase):
138 def __init__(self, test_data):
139 super().__init__("run_all")
140 self.test_data = test_data
141
142 def run_all(self):
143 m = Module()
144 comb = m.d.comb
145 instruction = Signal(32)
146
147 pdecode = create_pdecode()
148
149 m.submodules.pdecode2 = pdecode2 = PowerDecode2(pdecode)
150
151 pspec = SPRPipeSpec(id_wid=2)
152 m.submodules.alu = alu = SPRBasePipe(pspec)
153
154 comb += alu.p.data_i.ctx.op.eq_from_execute1(pdecode2.e)
155 comb += alu.p.valid_i.eq(1)
156 comb += alu.n.ready_i.eq(1)
157 comb += pdecode2.dec.raw_opcode_in.eq(instruction)
158 sim = Simulator(m)
159
160 sim.add_clock(1e-6)
161 def process():
162 for test in self.test_data:
163 print("test", test.name)
164 print ("sprs", test.sprs)
165 program = test.program
166 self.subTest(test.name)
167 sim = ISA(pdecode2, test.regs, test.sprs, test.cr,
168 test.mem, test.msr,
169 bigendian=bigendian)
170 gen = program.generate_instructions()
171 instructions = list(zip(gen, program.assembly.splitlines()))
172
173 pc = sim.pc.CIA.value
174 index = pc//4
175 while index < len(instructions):
176 ins, code = instructions[index]
177
178 print("pc %08x instr: %08x" % (pc, ins & 0xffffffff))
179 print(code)
180
181 if 'XER' in sim.spr:
182 so = 1 if sim.spr['XER'][XER_bits['SO']] else 0
183 ov = 1 if sim.spr['XER'][XER_bits['OV']] else 0
184 ov32 = 1 if sim.spr['XER'][XER_bits['OV32']] else 0
185 print ("before: so/ov/32", so, ov, ov32)
186
187 # ask the decoder to decode this binary data (endian'd)
188 yield pdecode2.dec.bigendian.eq(bigendian) # little / big?
189 yield instruction.eq(ins) # raw binary instr.
190 yield Settle()
191
192 fast_in = yield pdecode2.e.read_fast1.data
193 spr_in = yield pdecode2.e.read_spr1.data
194 print ("dec2 spr/fast in", fast_in, spr_in)
195
196 fast_out = yield pdecode2.e.write_fast1.data
197 spr_out = yield pdecode2.e.write_spr.data
198 print ("dec2 spr/fast in", fast_out, spr_out)
199
200 fn_unit = yield pdecode2.e.do.fn_unit
201 self.assertEqual(fn_unit, Function.SPR.value)
202 yield from set_alu_inputs(alu, pdecode2, sim)
203 yield
204 opname = code.split(' ')[0]
205 yield from sim.call(opname)
206 pc = sim.pc.CIA.value
207 index = pc//4
208 print("pc after %08x" % (pc))
209
210 vld = yield alu.n.valid_o
211 while not vld:
212 yield
213 vld = yield alu.n.valid_o
214 yield
215
216 yield from self.check_alu_outputs(alu, pdecode2, sim, code)
217
218 sim.add_sync_process(process)
219 with sim.write_vcd("alu_simulator.vcd", "simulator.gtkw",
220 traces=[]):
221 sim.run()
222
223 def check_alu_outputs(self, alu, dec2, sim, code):
224
225 rc = yield dec2.e.do.rc.data
226 cridx_ok = yield dec2.e.write_cr.ok
227 cridx = yield dec2.e.write_cr.data
228
229 print ("check extra output", repr(code), cridx_ok, cridx)
230 if rc:
231 self.assertEqual(cridx, 0, code)
232
233 sim_o = {}
234 res = {}
235
236 yield from ALUHelpers.get_int_o(res, alu, dec2)
237 yield from ALUHelpers.get_fast_spr1(res, alu, dec2)
238 yield from ALUHelpers.get_slow_spr1(res, alu, dec2)
239 yield from ALUHelpers.get_xer_ov(res, alu, dec2)
240 yield from ALUHelpers.get_xer_ca(res, alu, dec2)
241 yield from ALUHelpers.get_xer_so(res, alu, dec2)
242
243 print ("output", res)
244
245 yield from ALUHelpers.get_sim_int_o(sim_o, sim, dec2)
246 yield from ALUHelpers.get_wr_sim_xer_so(sim_o, sim, alu, dec2)
247 yield from ALUHelpers.get_wr_sim_xer_ov(sim_o, sim, alu, dec2)
248 yield from ALUHelpers.get_wr_sim_xer_ca(sim_o, sim, dec2)
249 yield from ALUHelpers.get_wr_fast_spr1(sim_o, sim, dec2)
250 yield from ALUHelpers.get_wr_slow_spr1(sim_o, sim, dec2)
251
252 print ("sim output", sim_o)
253
254 ALUHelpers.check_xer_ov(self, res, sim_o, code)
255 ALUHelpers.check_xer_ca(self, res, sim_o, code)
256 ALUHelpers.check_xer_so(self, res, sim_o, code)
257 ALUHelpers.check_int_o(self, res, sim_o, code)
258 ALUHelpers.check_fast_spr1(self, res, sim_o, code)
259 ALUHelpers.check_slow_spr1(self, res, sim_o, code)
260
261
262 if __name__ == "__main__":
263 unittest.main(exit=False)
264 suite = unittest.TestSuite()
265 suite.addTest(TestRunner(SPRTestCase.test_data))
266
267 runner = unittest.TextTestRunner()
268 runner.run(suite)