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