format some tests
[soc.git] / src / soc / fu / cr / test / test_pipe_caller.py
1 from nmigen import Module, Signal
2 from nmigen.back.pysim import Simulator, Delay, Settle
3 from nmigen.cli import rtlil
4 import unittest
5 from soc.decoder.isa.caller import ISACaller, special_sprs
6 from soc.decoder.power_decoder import (create_pdecode)
7 from soc.decoder.power_decoder2 import (PowerDecode2)
8 from soc.decoder.power_enums import (XER_bits, Function)
9 from soc.decoder.selectable_int import SelectableInt
10 from soc.simulator.program import Program
11 from soc.decoder.isa.all import ISA
12 from soc.config.endian import bigendian
13
14 from soc.fu.test.common import TestAccumulatorBase, TestCase, ALUHelpers
15 from soc.fu.cr.pipeline import CRBasePipe
16 from soc.fu.cr.pipe_data import CRPipeSpec
17 import random
18
19
20 # This test bench is a bit different than is usual. Initially when I
21 # was writing it, I had all of the tests call a function to create a
22 # device under test and simulator, initialize the dut, run the
23 # simulation for ~2 cycles, and assert that the dut output what it
24 # should have. However, this was really slow, since it needed to
25 # create and tear down the dut and simulator for every test case.
26
27 # Now, instead of doing that, every test case in ALUTestCase puts some
28 # data into the test_data list below, describing the instructions to
29 # be tested and the initial state. Once all the tests have been run,
30 # test_data gets passed to TestRunner which then sets up the DUT and
31 # simulator once, runs all the data through it, and asserts that the
32 # results match the pseudocode sim at every cycle.
33
34 # By doing this, I've reduced the time it takes to run the test suite
35 # massively. Before, it took around 1 minute on my computer, now it
36 # takes around 3 seconds
37
38
39 class CRTestCase(TestAccumulatorBase):
40
41 def case_crop(self):
42 insns = ["crand", "cror", "crnand", "crnor", "crxor", "creqv",
43 "crandc", "crorc"]
44 for i in range(40):
45 choice = random.choice(insns)
46 ba = random.randint(0, 31)
47 bb = random.randint(0, 31)
48 bt = random.randint(0, 31)
49 lst = [f"{choice} {ba}, {bb}, {bt}"]
50 cr = random.randint(0, (1 << 32)-1)
51 self.add_case(Program(lst, bigendian), initial_cr=cr)
52
53 def case_crand(self):
54 for i in range(20):
55 lst = ["crand 0, 11, 13"]
56 cr = random.randint(0, (1 << 32)-1)
57 self.add_case(Program(lst, bigendian), initial_cr=cr)
58
59 def case_1_mcrf(self):
60 for i in range(20):
61 src = random.randint(0, 7)
62 dst = random.randint(0, 7)
63 lst = [f"mcrf {src}, {dst}"]
64 cr = random.randint(0, (1 << 32)-1)
65 self.add_case(Program(lst, bigendian), initial_cr=cr)
66
67 def case_0_mcrf(self):
68 for i in range(8):
69 lst = [f"mcrf 5, {i}"]
70 cr = 0xfeff0001
71 self.add_case(Program(lst, bigendian), initial_cr=cr)
72
73 def case_mtcrf(self):
74 for i in range(20):
75 mask = random.randint(0, 255)
76 lst = [f"mtcrf {mask}, 2"]
77 cr = random.randint(0, (1 << 32)-1)
78 initial_regs = [0] * 32
79 initial_regs[2] = random.randint(0, (1 << 32)-1)
80 self.add_case(Program(lst, bigendian), initial_regs=initial_regs,
81 initial_cr=cr)
82
83 def case_mtocrf(self):
84 for i in range(20):
85 mask = 1 << random.randint(0, 7)
86 lst = [f"mtocrf {mask}, 2"]
87 cr = random.randint(0, (1 << 32)-1)
88 initial_regs = [0] * 32
89 initial_regs[2] = random.randint(0, (1 << 32)-1)
90 self.add_case(Program(lst, bigendian), initial_regs=initial_regs,
91 initial_cr=cr)
92
93 def case_mfcr(self):
94 for i in range(5):
95 lst = ["mfcr 2"]
96 cr = random.randint(0, (1 << 32)-1)
97 self.add_case(Program(lst, bigendian), initial_cr=cr)
98
99 def case_mfocrf(self):
100 for i in range(20):
101 mask = 1 << random.randint(0, 7)
102 lst = [f"mfocrf 2, {mask}"]
103 cr = random.randint(0, (1 << 32)-1)
104 self.add_case(Program(lst, bigendian), initial_cr=cr)
105
106 def case_isel(self):
107 for i in range(20):
108 bc = random.randint(0, 31)
109 lst = [f"isel 1, 2, 3, {bc}"]
110 cr = random.randint(0, (1 << 32)-1)
111 initial_regs = [0] * 32
112 initial_regs[2] = random.randint(0, (1 << 64)-1)
113 initial_regs[3] = random.randint(0, (1 << 64)-1)
114 #initial_regs[2] = i*2
115 #initial_regs[3] = i*2+1
116 self.add_case(Program(lst, bigendian),
117 initial_regs=initial_regs, initial_cr=cr)
118
119 def case_setb(self):
120 for i in range(20):
121 bfa = random.randint(0, 7)
122 lst = [f"setb 1, {bfa}"]
123 cr = random.randint(0, (1 << 32)-1)
124 self.add_case(Program(lst, bigendian), initial_cr=cr)
125
126 def case_regression_setb(self):
127 lst = [f"setb 1, 6"]
128 cr = random.randint(0, 0x66f6b106)
129 self.add_case(Program(lst, bigendian), initial_cr=cr)
130
131 def case_ilang(self):
132 pspec = CRPipeSpec(id_wid=2)
133 alu = CRBasePipe(pspec)
134 vl = rtlil.convert(alu, ports=alu.ports())
135 with open("cr_pipeline.il", "w") as f:
136 f.write(vl)
137
138
139 def get_cu_inputs(dec2, sim):
140 """naming (res) must conform to CRFunctionUnit input regspec
141 """
142 res = {}
143 full_reg = yield dec2.e.do.read_cr_whole
144
145 # full CR
146 print(sim.cr.get_range().value)
147 if full_reg:
148 res['full_cr'] = sim.cr.get_range().value
149 else:
150 # CR A
151 cr1_en = yield dec2.e.read_cr1.ok
152 if cr1_en:
153 cr1_sel = yield dec2.e.read_cr1.data
154 res['cr_a'] = sim.crl[cr1_sel].get_range().value
155 cr2_en = yield dec2.e.read_cr2.ok
156 # CR B
157 if cr2_en:
158 cr2_sel = yield dec2.e.read_cr2.data
159 res['cr_b'] = sim.crl[cr2_sel].get_range().value
160 cr3_en = yield dec2.e.read_cr3.ok
161 # CR C
162 if cr3_en:
163 cr3_sel = yield dec2.e.read_cr3.data
164 res['cr_c'] = sim.crl[cr3_sel].get_range().value
165
166 # RA/RC
167 reg1_ok = yield dec2.e.read_reg1.ok
168 if reg1_ok:
169 data1 = yield dec2.e.read_reg1.data
170 res['ra'] = sim.gpr(data1).value
171
172 # RB (or immediate)
173 reg2_ok = yield dec2.e.read_reg2.ok
174 if reg2_ok:
175 data2 = yield dec2.e.read_reg2.data
176 res['rb'] = sim.gpr(data2).value
177
178 print("get inputs", res)
179 return res
180
181
182 class TestRunner(unittest.TestCase):
183 def __init__(self, test_data):
184 super().__init__("run_all")
185 self.test_data = test_data
186
187 def set_inputs(self, alu, dec2, simulator):
188 inp = yield from get_cu_inputs(dec2, simulator)
189 yield from ALUHelpers.set_full_cr(alu, dec2, inp)
190 yield from ALUHelpers.set_cr_a(alu, dec2, inp)
191 yield from ALUHelpers.set_cr_b(alu, dec2, inp)
192 yield from ALUHelpers.set_cr_c(alu, dec2, inp)
193 yield from ALUHelpers.set_int_ra(alu, dec2, inp)
194 yield from ALUHelpers.set_int_rb(alu, dec2, inp)
195
196 def assert_outputs(self, alu, dec2, simulator, code):
197 whole_reg = yield dec2.e.do.write_cr_whole
198 cr_en = yield dec2.e.write_cr.ok
199 if whole_reg:
200 full_cr = yield alu.n.data_o.full_cr.data
201 expected_cr = simulator.cr.get_range().value
202 print(f"CR whole: expected {expected_cr:x}, actual: {full_cr:x}")
203 self.assertEqual(expected_cr, full_cr, code)
204 elif cr_en:
205 cr_sel = yield dec2.e.write_cr.data
206 expected_cr = simulator.cr.get_range().value
207 print(f"CR whole: {expected_cr:x}, sel {cr_sel}")
208 expected_cr = simulator.crl[cr_sel].get_range().value
209 real_cr = yield alu.n.data_o.cr.data
210 print(f"CR part: expected {expected_cr:x}, actual: {real_cr:x}")
211 self.assertEqual(expected_cr, real_cr, code)
212 alu_out = yield alu.n.data_o.o.data
213 out_reg_valid = yield dec2.e.write_reg.ok
214 if out_reg_valid:
215 write_reg_idx = yield dec2.e.write_reg.data
216 expected = simulator.gpr(write_reg_idx).value
217 print(f"expected {expected:x}, actual: {alu_out:x}")
218 self.assertEqual(expected, alu_out, code)
219
220 def run_all(self):
221 m = Module()
222 comb = m.d.comb
223 instruction = Signal(32)
224
225 pdecode = create_pdecode()
226
227 m.submodules.pdecode2 = pdecode2 = PowerDecode2(pdecode)
228
229 pspec = CRPipeSpec(id_wid=2)
230 m.submodules.alu = alu = CRBasePipe(pspec)
231
232 comb += alu.p.data_i.ctx.op.eq_from_execute1(pdecode2.e)
233 comb += alu.n.ready_i.eq(1)
234 comb += pdecode2.dec.raw_opcode_in.eq(instruction)
235 sim = Simulator(m)
236
237 sim.add_clock(1e-6)
238
239 def process():
240 for test in self.test_data:
241 print(test.name)
242 program = test.program
243 self.subTest(test.name)
244 sim = ISA(pdecode2, test.regs, test.sprs, test.cr, test.mem,
245 test.msr,
246 bigendian=bigendian)
247 gen = program.generate_instructions()
248 instructions = list(zip(gen, program.assembly.splitlines()))
249
250 index = sim.pc.CIA.value//4
251 while index < len(instructions):
252 ins, code = instructions[index]
253
254 print("0x{:X}".format(ins & 0xffffffff))
255 print(code)
256
257 # ask the decoder to decode this binary data (endian'd)
258 yield pdecode2.dec.bigendian.eq(bigendian) # little / big?
259 yield instruction.eq(ins) # raw binary instr.
260 yield Settle()
261 yield from self.set_inputs(alu, pdecode2, sim)
262 yield alu.p.valid_i.eq(1)
263 fn_unit = yield pdecode2.e.do.fn_unit
264 self.assertEqual(fn_unit, Function.CR.value, code)
265 yield
266 opname = code.split(' ')[0]
267 yield from sim.call(opname)
268 index = sim.pc.CIA.value//4
269
270 vld = yield alu.n.valid_o
271 while not vld:
272 yield
273 vld = yield alu.n.valid_o
274 yield
275 yield from self.assert_outputs(alu, pdecode2, sim, code)
276
277 sim.add_sync_process(process)
278 with sim.write_vcd("simulator.vcd", "simulator.gtkw",
279 traces=[]):
280 sim.run()
281
282
283 if __name__ == "__main__":
284 unittest.main(exit=False)
285 suite = unittest.TestSuite()
286 suite.addTest(TestRunner(CRTestCase().test_data))
287
288 runner = unittest.TextTestRunner()
289 runner.run(suite)