6164fdd19c7c0c231537a6bd7e582c52423e7ca0
[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 def set_alu_inputs(alu, dec2, sim):
42 # TODO: see https://bugs.libre-soc.org/show_bug.cgi?id=305#c43
43 # detect the immediate here (with m.If(self.i.ctx.op.imm_data.imm_ok))
44 # and place it into data_i.b
45
46 inp = yield from get_cu_inputs(dec2, sim)
47 yield from ALUHelpers.set_int_ra(alu, dec2, inp)
48 yield from ALUHelpers.set_xer_ca(alu, dec2, inp)
49 yield from ALUHelpers.set_xer_ov(alu, dec2, inp)
50 yield from ALUHelpers.set_xer_so(alu, dec2, inp)
51
52 yield from ALUHelpers.set_fast_spr1(alu, dec2, inp)
53 yield from ALUHelpers.set_slow_spr1(alu, dec2, inp)
54 return inp
55
56
57 # This test bench is a bit different than is usual. Initially when I
58 # was writing it, I had all of the tests call a function to create a
59 # device under test and simulator, initialize the dut, run the
60 # simulation for ~2 cycles, and assert that the dut output what it
61 # should have. However, this was really slow, since it needed to
62 # create and tear down the dut and simulator for every test case.
63
64 # Now, instead of doing that, every test case in SPRTestCase puts some
65 # data into the test_data list below, describing the instructions to
66 # be tested and the initial state. Once all the tests have been run,
67 # test_data gets passed to TestRunner which then sets up the DUT and
68 # simulator once, runs all the data through it, and asserts that the
69 # results match the pseudocode sim at every cycle.
70
71 # By doing this, I've reduced the time it takes to run the test suite
72 # massively. Before, it took around 1 minute on my computer, now it
73 # takes around 3 seconds
74
75
76 class SPRTestCase(FHDLTestCase):
77 test_data = []
78
79 def __init__(self, name):
80 super().__init__(name)
81 self.test_name = name
82
83 def run_tst_program(self, prog, initial_regs=None, initial_sprs=None,
84 initial_msr=0):
85 tc = TestCase(prog, self.test_name, initial_regs, initial_sprs,
86 msr=initial_msr)
87 self.test_data.append(tc)
88
89 def test_1_mfspr(self):
90 lst = ["mfspr 1, 26", # SRR0
91 "mfspr 2, 27", # SRR1
92 "mfspr 3, 8", # LR
93 "mfspr 4, 1", ] # XER
94 initial_regs = [0] * 32
95 initial_sprs = {'SRR0': 0x12345678, 'SRR1': 0x5678, 'LR': 0x1234,
96 'XER': 0xe00c0000}
97 self.run_tst_program(Program(lst, bigendian),
98 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
184 def process():
185 for test in self.test_data:
186 print("test", test.name)
187 print("sprs", test.sprs)
188 program = test.program
189 self.subTest(test.name)
190 sim = ISA(pdecode2, test.regs, test.sprs, test.cr,
191 test.mem, test.msr,
192 bigendian=bigendian)
193 gen = program.generate_instructions()
194 instructions = list(zip(gen, program.assembly.splitlines()))
195
196 pc = sim.pc.CIA.value
197 msr = sim.msr.value
198 index = pc//4
199 while index < len(instructions):
200 ins, code = instructions[index]
201
202 print("pc %08x instr: %08x" % (pc, ins & 0xffffffff))
203 print(code)
204
205 if 'XER' in sim.spr:
206 so = 1 if sim.spr['XER'][XER_bits['SO']] else 0
207 ov = 1 if sim.spr['XER'][XER_bits['OV']] else 0
208 ov32 = 1 if sim.spr['XER'][XER_bits['OV32']] else 0
209 print("before: so/ov/32", so, ov, ov32)
210
211 # ask the decoder to decode this binary data (endian'd)
212 yield pdecode2.dec.bigendian.eq(bigendian) # little / big?
213 yield pdecode2.msr.eq(msr) # set MSR in pdecode2
214 yield pdecode2.cia.eq(pc) # set PC in pdecode2
215 yield instruction.eq(ins) # raw binary instr.
216 yield Settle()
217
218 fast_in = yield pdecode2.e.read_fast1.data
219 spr_in = yield pdecode2.e.read_spr1.data
220 print("dec2 spr/fast in", fast_in, spr_in)
221
222 fast_out = yield pdecode2.e.write_fast1.data
223 spr_out = yield pdecode2.e.write_spr.data
224 print("dec2 spr/fast in", fast_out, spr_out)
225
226 fn_unit = yield pdecode2.e.do.fn_unit
227 self.assertEqual(fn_unit, Function.SPR.value)
228 alu_o = yield from set_alu_inputs(alu, pdecode2, sim)
229 yield
230 opname = code.split(' ')[0]
231 yield from sim.call(opname)
232 pc = sim.pc.CIA.value
233 msr = sim.msr.value
234 index = pc//4
235 print("pc after %08x" % (pc))
236
237 vld = yield alu.n.valid_o
238 while not vld:
239 yield
240 vld = yield alu.n.valid_o
241 yield
242
243 yield from self.check_alu_outputs(alu, pdecode2, sim, code)
244
245 sim.add_sync_process(process)
246 with sim.write_vcd("alu_simulator.vcd", "simulator.gtkw",
247 traces=[]):
248 sim.run()
249
250 def check_alu_outputs(self, alu, dec2, sim, code):
251
252 rc = yield dec2.e.do.rc.data
253 cridx_ok = yield dec2.e.write_cr.ok
254 cridx = yield dec2.e.write_cr.data
255
256 print("check extra output", repr(code), cridx_ok, cridx)
257 if rc:
258 self.assertEqual(cridx, 0, code)
259
260 sim_o = {}
261 res = {}
262
263 yield from ALUHelpers.get_int_o(res, alu, dec2)
264 yield from ALUHelpers.get_fast_spr1(res, alu, dec2)
265 yield from ALUHelpers.get_slow_spr1(res, alu, dec2)
266 yield from ALUHelpers.get_xer_ov(res, alu, dec2)
267 yield from ALUHelpers.get_xer_ca(res, alu, dec2)
268 yield from ALUHelpers.get_xer_so(res, alu, dec2)
269
270 print("output", res)
271
272 yield from ALUHelpers.get_sim_int_o(sim_o, sim, dec2)
273 yield from ALUHelpers.get_wr_sim_xer_so(sim_o, sim, alu, dec2)
274 yield from ALUHelpers.get_wr_sim_xer_ov(sim_o, sim, alu, dec2)
275 yield from ALUHelpers.get_wr_sim_xer_ca(sim_o, sim, dec2)
276 yield from ALUHelpers.get_wr_fast_spr1(sim_o, sim, dec2)
277 yield from ALUHelpers.get_wr_slow_spr1(sim_o, sim, dec2)
278
279 print("sim output", sim_o)
280
281 ALUHelpers.check_xer_ov(self, res, sim_o, code)
282 ALUHelpers.check_xer_ca(self, res, sim_o, code)
283 ALUHelpers.check_xer_so(self, res, sim_o, code)
284 ALUHelpers.check_int_o(self, res, sim_o, code)
285 ALUHelpers.check_fast_spr1(self, res, sim_o, code)
286 ALUHelpers.check_slow_spr1(self, res, sim_o, code)
287
288
289 if __name__ == "__main__":
290 unittest.main(exit=False)
291 suite = unittest.TestSuite()
292 suite.addTest(TestRunner(SPRTestCase.test_data))
293
294 runner = unittest.TextTestRunner()
295 runner.run(suite)