convert branch test to PowerDecodeSubset form
[soc.git] / src / soc / fu / branch / 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, MicrOp)
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.regfile.regfiles import FastRegs
13 from soc.config.endian import bigendian
14
15 from soc.fu.test.common import TestAccumulatorBase, TestCase, ALUHelpers
16 from soc.fu.branch.pipeline import BranchBasePipe
17 from soc.fu.branch.pipe_data import BranchPipeSpec
18 import random
19
20 from soc.regfile.util import fast_reg_to_spr # HACK!
21
22
23 def get_rec_width(rec):
24 recwidth = 0
25 # Setup random inputs for dut.op
26 for p in rec.ports():
27 width = p.width
28 recwidth += width
29 return recwidth
30
31
32 def get_cu_inputs(dec2, sim):
33 """naming (res) must conform to BranchFunctionUnit input regspec
34 """
35 res = {}
36
37 # CIA (PC)
38 #res['cia'] = sim.pc.CIA.value
39
40 yield from ALUHelpers.get_sim_fast_spr1(res, sim, dec2)
41 yield from ALUHelpers.get_sim_fast_spr2(res, sim, dec2)
42 yield from ALUHelpers.get_sim_cr_a(res, sim, dec2)
43
44 print("get inputs", res)
45 return res
46
47
48 class BranchTestCase(TestAccumulatorBase):
49
50 def case_0_regression_unconditional(self):
51 for i in range(2):
52 imm = random.randrange(-1 << 23, (1 << 23)-1) * 4
53 lst = [f"bl {imm}"]
54 initial_regs = [0] * 32
55 self.add_case(Program(lst, bigendian), initial_regs)
56
57 def case_unconditional(self):
58 choices = ["b", "ba", "bl", "bla"]
59 for i in range(20):
60 choice = random.choice(choices)
61 imm = random.randrange(-1 << 23, (1 << 23)-1) * 4
62 lst = [f"{choice} {imm}"]
63 initial_regs = [0] * 32
64 self.add_case(Program(lst, bigendian), initial_regs)
65
66 def case_bc_cr(self):
67 for i in range(20):
68 bc = random.randrange(-1 << 13, (1 << 13)-1) * 4
69 bo = random.choice([0b01100, 0b00100, 0b10100])
70 bi = random.randrange(0, 31)
71 cr = random.randrange(0, (1 << 32)-1)
72 lst = [f"bc {bo}, {bi}, {bc}"]
73 initial_regs = [0] * 32
74 self.add_case(Program(lst, bigendian), initial_cr=cr)
75
76 def case_bc_ctr(self):
77 for i in range(20):
78 bc = random.randrange(-1 << 13, (1 << 13)-1) * 4
79 bo = random.choice([0, 2, 8, 10, 16, 18])
80 bi = random.randrange(0, 31)
81 cr = random.randrange(0, (1 << 32)-1)
82 ctr = random.randint(0, (1 << 32)-1)
83 lst = [f"bc {bo}, {bi}, {bc}"]
84 initial_sprs = {9: SelectableInt(ctr, 64)}
85 self.add_case(Program(lst, bigendian),
86 initial_sprs=initial_sprs,
87 initial_cr=cr)
88
89 def case_bc_reg(self):
90 # XXX: bcctr and bcctrl time out (irony: they're counters)
91 choices = ["bclr", "bclrl", "bcctr", "bcctrl", "bctar", "bctarl"]
92 for insn in choices:
93 for i in range(20):
94 bh = random.randrange(0, 3)
95 bo = random.choice([4, 12])
96 bi = random.randrange(0, 31)
97 cr = random.randrange(0, (1 << 32)-1)
98 ctr = random.randint(0, (1 << 32)-1)
99 lr = random.randint(0, (1 << 64)-1) & ~3
100 tar = random.randint(0, (1 << 64)-1) & ~3
101 lst = [f"{insn} {bo}, {bi}, {bh}"]
102 initial_sprs = {9: SelectableInt(ctr, 64),
103 8: SelectableInt(lr, 64),
104 815: SelectableInt(tar, 64)}
105 self.add_case(Program(lst, bigendian),
106 initial_sprs=initial_sprs,
107 initial_cr=cr)
108
109 def case_bc_microwatt_1_regression(self):
110 """bc found to be testing ctr rather than (ctr-1)
111 11fb4: 08 00 49 40 bc 2,4*cr2+gt,0x11fbc
112 cr_file.vhdl:83:13:@136835ns:(report note): Reading CR 33209703
113 """
114 lst = ["bc 2, 9, 8"]
115 initial_regs = [0] * 32
116 cr = 0x33209703
117 self.add_case(Program(lst, bigendian), initial_regs,
118 initial_cr=cr)
119
120 def case_bc_microwatt_2_regression(self):
121 """modified version, set CTR=1 so that it hits zero in BC
122 """
123 lst = ["bc 2, 9, 8"]
124 initial_regs = [0] * 32
125 cr = 0x33209703
126 ctr = 1
127 initial_sprs = {9: SelectableInt(ctr, 64),
128 }
129 self.add_case(Program(lst, bigendian), initial_regs,
130 initial_sprs=initial_sprs,
131 initial_cr=cr)
132
133 def case_ilang(self):
134 pspec = BranchPipeSpec(id_wid=2)
135 alu = BranchBasePipe(pspec)
136 vl = rtlil.convert(alu, ports=alu.ports())
137 with open("branch_pipeline.il", "w") as f:
138 f.write(vl)
139
140
141 class TestRunner(unittest.TestCase):
142 def test_it(self):
143 test_data = BranchTestCase().test_data
144 m = Module()
145 comb = m.d.comb
146 instruction = Signal(32)
147
148 fn_name = "BRANCH"
149 opkls = BranchPipeSpec.opsubsetkls
150
151 m.submodules.pdecode2 = pdecode2 = PowerDecode2(None, opkls, fn_name)
152 pdecode = pdecode2.dec
153
154 pspec = BranchPipeSpec(id_wid=2)
155 m.submodules.branch = branch = BranchBasePipe(pspec)
156
157 comb += branch.p.data_i.ctx.op.eq_from_execute1(pdecode2.e)
158 comb += branch.p.valid_i.eq(1)
159 comb += branch.n.ready_i.eq(1)
160 comb += pdecode2.dec.raw_opcode_in.eq(instruction)
161 sim = Simulator(m)
162
163 sim.add_clock(1e-6)
164
165 def process():
166 for test in test_data:
167 print(test.name)
168 program = test.program
169 with self.subTest(test.name):
170 simulator = ISA(pdecode2, test.regs, test.sprs, test.cr,
171 test.mem, test.msr,
172 bigendian=bigendian)
173 initial_cia = 0x2000
174 simulator.set_pc(initial_cia)
175 gen = program.generate_instructions()
176 instructions = list(
177 zip(gen, program.assembly.splitlines()))
178
179 pc = simulator.pc.CIA.value
180 msr = simulator.msr.value
181 index = (pc - initial_cia)//4
182 while index < len(instructions) and index >= 0:
183 print(index)
184 ins, code = instructions[index]
185
186 print("0x{:X}".format(ins & 0xffffffff))
187 print(code)
188
189 # ask the decoder to decode this binary data (endian'd)
190 # little / big?
191 yield pdecode2.dec.bigendian.eq(bigendian)
192 yield pdecode2.state.msr.eq(msr) # set MSR in pdecode2
193 yield pdecode2.state.pc.eq(pc) # set PC in pdecode2
194 yield instruction.eq(ins) # raw binary instr.
195 # note, here, the op will need further decoding in order
196 # to set the correct SPRs on SPR1/2/3. op_bc* require
197 # spr1 to be set to CTR, op_bctar require spr2 to be
198 # set to TAR, op_bclr* require spr2 to be set to LR.
199 # if op_sc*, op_rf* and op_hrfid are to be added here
200 # then additional op-decoding is required, accordingly
201 yield Settle()
202 lk = yield pdecode2.e.do.lk
203 print("lk:", lk)
204 yield from self.set_inputs(branch, pdecode2, simulator)
205 fn_unit = yield pdecode2.e.do.fn_unit
206 self.assertEqual(fn_unit, Function.BRANCH.value, code)
207 yield
208 yield
209 opname = code.split(' ')[0]
210 prev_nia = simulator.pc.NIA.value
211 yield from simulator.call(opname)
212 pc = simulator.pc.CIA.value
213 msr = simulator.msr.value
214 index = (pc - initial_cia)//4
215
216 yield from self.assert_outputs(branch, pdecode2,
217 simulator, prev_nia, code)
218
219 sim.add_sync_process(process)
220 with sim.write_vcd("branch_simulator.vcd"):
221 sim.run()
222
223 def assert_outputs(self, branch, dec2, sim, prev_nia, code):
224 branch_taken = yield branch.n.data_o.nia.ok
225 sim_branch_taken = prev_nia != sim.pc.CIA
226 self.assertEqual(branch_taken, sim_branch_taken, code)
227 if branch_taken:
228 branch_addr = yield branch.n.data_o.nia.data
229 print(f"real: {branch_addr:x}, sim: {sim.pc.CIA.value:x}")
230 self.assertEqual(branch_addr, sim.pc.CIA.value, code)
231
232 # TODO: check write_fast1 as well (should contain CTR)
233
234 # TODO: this should be checking write_fast2
235 lk = yield dec2.e.do.lk
236 branch_lk = yield branch.n.data_o.lr.ok
237 self.assertEqual(lk, branch_lk, code)
238 if lk:
239 branch_lr = yield branch.n.data_o.lr.data
240 self.assertEqual(sim.spr['LR'], branch_lr, code)
241
242 def set_inputs(self, branch, dec2, sim):
243 print(f"cr0: {sim.crl[0].get_range()}")
244
245 inp = yield from get_cu_inputs(dec2, sim)
246
247 yield from ALUHelpers.set_fast_spr1(branch, dec2, inp)
248 yield from ALUHelpers.set_fast_spr2(branch, dec2, inp)
249 yield from ALUHelpers.set_cr_a(branch, dec2, inp)
250
251
252 if __name__ == "__main__":
253 unittest.main()