add parent_pspec everywhere
[soc.git] / src / soc / fu / branch / test / test_pipe_caller.py
1 from nmigen import Module, Signal
2
3 # NOTE: to use cxxsim, export NMIGEN_SIM_MODE=cxxsim from the shell
4 # Also, check out the cxxsim nmigen branch, and latest yosys from git
5 from nmutil.sim_tmp_alternative import Simulator, Settle
6
7 from nmigen.cli import rtlil
8 import unittest
9 from openpower.decoder.power_decoder import (create_pdecode)
10 from openpower.decoder.power_decoder2 import (PowerDecode2)
11 from openpower.decoder.power_enums import Function
12 from openpower.simulator.program import Program
13 from openpower.decoder.isa.all import ISA
14 from soc.regfile.regfiles import FastRegs
15 from openpower.endian import bigendian
16
17 from openpower.test.common import ALUHelpers
18 from soc.fu.branch.pipeline import BranchBasePipe
19 from soc.fu.branch.pipe_data import BranchPipeSpec
20 import random
21
22 from openpower.test.branch.branch_cases import BranchTestCase
23
24
25 def get_rec_width(rec):
26 recwidth = 0
27 # Setup random inputs for dut.op
28 for p in rec.ports():
29 width = p.width
30 recwidth += width
31 return recwidth
32
33
34 def get_cu_inputs(dec2, sim):
35 """naming (res) must conform to BranchFunctionUnit input regspec
36 """
37 res = {}
38
39 # CIA (PC)
40 #res['cia'] = sim.pc.CIA.value
41
42 yield from ALUHelpers.get_sim_fast_spr1(res, sim, dec2)
43 yield from ALUHelpers.get_sim_fast_spr2(res, sim, dec2)
44 yield from ALUHelpers.get_sim_cr_a(res, sim, dec2)
45
46 print("get inputs", res)
47 return res
48
49
50 class BranchAllCases(BranchTestCase):
51
52 def case_ilang(self):
53 pspec = BranchPipeSpec(id_wid=2, parent_pspec=None)
54 alu = BranchBasePipe(pspec)
55 vl = rtlil.convert(alu, ports=alu.ports())
56 with open("branch_pipeline.il", "w") as f:
57 f.write(vl)
58
59
60 class TestRunner(unittest.TestCase):
61 def test_it(self):
62 test_data = BranchAllCases().test_data
63 m = Module()
64 comb = m.d.comb
65 instruction = Signal(32)
66
67 fn_name = "BRANCH"
68 opkls = BranchPipeSpec.opsubsetkls
69
70 m.submodules.pdecode2 = pdecode2 = PowerDecode2(None, opkls, fn_name)
71 pdecode = pdecode2.dec
72
73 pspec = BranchPipeSpec(id_wid=2, parent_pspec=None)
74 m.submodules.branch = branch = BranchBasePipe(pspec)
75
76 comb += branch.p.i_data.ctx.op.eq_from_execute1(pdecode2.do)
77 comb += branch.p.i_valid.eq(1)
78 comb += branch.n.i_ready.eq(1)
79 comb += pdecode2.dec.raw_opcode_in.eq(instruction)
80 sim = Simulator(m)
81
82 sim.add_clock(1e-6)
83
84 def process():
85 for test in test_data:
86 print(test.name)
87 program = test.program
88 with self.subTest(test.name):
89 simulator = ISA(pdecode2, test.regs, test.sprs, test.cr,
90 test.mem, test.msr,
91 bigendian=bigendian)
92 initial_cia = 0x2000
93 simulator.set_pc(initial_cia)
94 gen = program.generate_instructions()
95 instructions = list(
96 zip(gen, program.assembly.splitlines()))
97
98 pc = simulator.pc.CIA.value
99 msr = simulator.msr.value
100 index = (pc - initial_cia)//4
101 while index < len(instructions) and index >= 0:
102 print(index)
103 ins, code = instructions[index]
104
105 print("0x{:X}".format(ins & 0xffffffff))
106 print(code)
107
108 # ask the decoder to decode this binary data (endian'd)
109 # little / big?
110 yield pdecode2.dec.bigendian.eq(bigendian)
111 yield pdecode2.state.msr.eq(msr) # set MSR in pdecode2
112 yield pdecode2.state.pc.eq(pc) # set PC in pdecode2
113 yield instruction.eq(ins) # raw binary instr.
114 # note, here, the op will need further decoding in order
115 # to set the correct SPRs on SPR1/2/3. op_bc* require
116 # spr1 to be set to CTR, op_bctar require spr2 to be
117 # set to TAR, op_bclr* require spr2 to be set to LR.
118 # if op_sc*, op_rf* and op_hrfid are to be added here
119 # then additional op-decoding is required, accordingly
120 yield Settle()
121 lk = yield pdecode2.e.do.lk
122 print("lk:", lk)
123 yield from self.set_inputs(branch, pdecode2, simulator)
124 fn_unit = yield pdecode2.e.do.fn_unit
125 self.assertEqual(fn_unit, Function.BRANCH.value, code)
126 yield
127 yield
128 opname = code.split(' ')[0]
129 prev_nia = simulator.pc.NIA.value
130 yield from simulator.call(opname)
131 pc = simulator.pc.CIA.value
132 msr = simulator.msr.value
133 index = (pc - initial_cia)//4
134
135 yield from self.assert_outputs(branch, pdecode2,
136 simulator, prev_nia,
137 code)
138
139 sim.add_sync_process(process)
140 with sim.write_vcd("branch_simulator.vcd"):
141 sim.run()
142
143 def assert_outputs(self, branch, dec2, sim, prev_nia, code):
144 branch_taken = yield branch.n.o_data.nia.ok
145 sim_branch_taken = prev_nia != sim.pc.CIA
146 self.assertEqual(branch_taken, sim_branch_taken, code)
147 if branch_taken:
148 branch_addr = yield branch.n.o_data.nia.data
149 print(f"real: {branch_addr:x}, sim: {sim.pc.CIA.value:x}")
150 self.assertEqual(branch_addr, sim.pc.CIA.value, code)
151
152 # TODO: check write_fast1 as well (should contain CTR)
153
154 # TODO: this should be checking write_fast2
155 lk = yield dec2.e.do.lk
156 branch_lk = yield branch.n.o_data.lr.ok
157 self.assertEqual(lk, branch_lk, code)
158 if lk:
159 branch_lr = yield branch.n.o_data.lr.data
160 self.assertEqual(sim.spr['LR'], branch_lr, code)
161
162 def set_inputs(self, branch, dec2, sim):
163 print(f"cr0: {sim.crl[0].get_range()}")
164
165 inp = yield from get_cu_inputs(dec2, sim)
166
167 yield from ALUHelpers.set_fast_spr1(branch, dec2, inp)
168 yield from ALUHelpers.set_fast_spr2(branch, dec2, inp)
169 yield from ALUHelpers.set_cr_a(branch, dec2, inp)
170
171
172 if __name__ == "__main__":
173 unittest.main()