a66902091436d79466d26d34ef4b52817e010bb2
[soc.git] / src / soc / fu / bitmanip / test / test_pipe_caller.py
1 import random
2 from soc.fu.bitmanip.pipe_data import BitManipPipeSpec
3 from soc.fu.bitmanip.pipeline import BitManipBasePipe
4 from openpower.test.common import TestAccumulatorBase, TestCase, ALUHelpers
5 from openpower.endian import bigendian
6 from openpower.decoder.isa.all import ISA
7 from openpower.simulator.program import Program
8 from openpower.decoder.power_enums import (XER_bits, Function, CryIn)
9 from openpower.decoder.power_decoder2 import (PowerDecode2)
10 from openpower.decoder.power_decoder import (create_pdecode)
11 import unittest
12 from nmigen.cli import rtlil
13 from nmigen import Module, Signal
14
15 # NOTE: to use cxxsim, export NMIGEN_SIM_MODE=cxxsim from the shell
16 # Also, check out the cxxsim nmigen branch, and latest yosys from git
17 from nmutil.sim_tmp_alternative import Simulator, Settle
18
19 from openpower.test.bitmanip.bitmanip_cases import BitManipTestCase
20
21
22 def get_cu_inputs(dec2, sim):
23 """naming (res) must conform to BitManipFunctionUnit input regspec
24 """
25 res = {}
26
27 yield from ALUHelpers.get_sim_int_ra(res, sim, dec2) # RA
28 yield from ALUHelpers.get_sim_int_rb(res, sim, dec2) # RB
29 yield from ALUHelpers.get_sim_int_rc(res, sim, dec2) # RC
30 yield from ALUHelpers.get_sim_xer_so(res, sim, dec2) # XER.so
31
32 print("alu get_cu_inputs", res)
33
34 return res
35
36
37 def set_alu_inputs(alu, dec2, sim):
38 inp = yield from get_cu_inputs(dec2, sim)
39 yield from ALUHelpers.set_int_ra(alu, dec2, inp)
40 yield from ALUHelpers.set_int_rb(alu, dec2, inp)
41 yield from ALUHelpers.set_int_rc(alu, dec2, inp)
42 yield from ALUHelpers.set_xer_so(alu, dec2, inp)
43
44
45 # This test bench is a bit different than is usual. Initially when I
46 # was writing it, I had all of the tests call a function to create a
47 # device under test and simulator, initialize the dut, run the
48 # simulation for ~2 cycles, and assert that the dut output what it
49 # should have. However, this was really slow, since it needed to
50 # create and tear down the dut and simulator for every test case.
51
52 # Now, instead of doing that, every test case in BitManipTestCase puts some
53 # data into the test_data list below, describing the instructions to
54 # be tested and the initial state. Once all the tests have been run,
55 # test_data gets passed to TestRunner which then sets up the DUT and
56 # simulator once, runs all the data through it, and asserts that the
57 # results match the pseudocode sim at every cycle.
58
59 # By doing this, I've reduced the time it takes to run the test suite
60 # massively. Before, it took around 1 minute on my computer, now it
61 # takes around 3 seconds
62
63
64 class BitManipIlangCase(TestAccumulatorBase):
65
66 def case_ilang(self):
67 pspec = BitManipPipeSpec(id_wid=2)
68 alu = BitManipBasePipe(pspec)
69 vl = rtlil.convert(alu, ports=alu.ports())
70 with open("bitmanip_pipeline.il", "w") as f:
71 f.write(vl)
72
73
74 class TestRunner(unittest.TestCase):
75 def __init__(self, test_data):
76 super().__init__("run_all")
77 self.test_data = test_data
78
79 def execute(self, alu, instruction, pdecode2, test):
80 program = test.program
81 simulator = ISA(pdecode2, test.regs, test.sprs, test.cr,
82 test.mem, test.msr,
83 bigendian=bigendian)
84 gen = program.generate_instructions()
85 instructions = list(zip(gen, program.assembly.splitlines()))
86
87 index = simulator.pc.CIA.value//4
88 while index < len(instructions):
89 ins, code = instructions[index]
90
91 print("0x{:X}".format(ins & 0xffffffff))
92 print(code)
93
94 # ask the decoder to decode this binary data (endian'd)
95 yield pdecode2.dec.bigendian.eq(bigendian) # little / big?
96 yield instruction.eq(ins) # raw binary instr.
97 yield Settle()
98 fn_unit = yield pdecode2.e.do.fn_unit
99 self.assertEqual(fn_unit, Function.BITMANIP.value)
100 yield from set_alu_inputs(alu, pdecode2, simulator)
101
102 # set valid for one cycle, propagate through pipeline...
103 yield alu.p.i_valid.eq(1)
104 yield
105 yield alu.p.i_valid.eq(0)
106
107 opname = code.split(' ')[0]
108 yield from simulator.call(opname)
109 index = simulator.pc.CIA.value//4
110
111 vld = yield alu.n.o_valid
112 while not vld:
113 yield
114 vld = yield alu.n.o_valid
115 yield
116 alu_out = yield alu.n.o_data.o.data
117
118 yield from self.check_alu_outputs(alu, pdecode2,
119 simulator, code)
120 yield Settle()
121
122 def run_all(self):
123 m = Module()
124 comb = m.d.comb
125 instruction = Signal(32)
126
127 fn_name = "BITMANIP"
128 opkls = BitManipPipeSpec.opsubsetkls
129
130 m.submodules.pdecode2 = pdecode2 = PowerDecode2(None, opkls, fn_name)
131 pdecode = pdecode2.dec
132
133 pspec = BitManipPipeSpec(id_wid=2)
134 m.submodules.alu = alu = BitManipBasePipe(pspec)
135
136 comb += alu.p.i_data.ctx.op.eq_from_execute1(pdecode2.do)
137 comb += alu.n.i_ready.eq(1)
138 comb += pdecode2.dec.raw_opcode_in.eq(instruction)
139 sim = Simulator(m)
140
141 sim.add_clock(1e-6)
142
143 def process():
144 for test in self.test_data:
145 print(test.name)
146 program = test.program
147 with self.subTest(test.name):
148 yield from self.execute(alu, instruction, pdecode2, test)
149
150 sim.add_sync_process(process)
151 with sim.write_vcd("bitmanip_simulator.vcd"):
152 sim.run()
153
154 def check_alu_outputs(self, alu, dec2, sim, code):
155
156 rc = yield dec2.e.do.rc.rc
157 cridx_ok = yield dec2.e.write_cr.ok
158 cridx = yield dec2.e.write_cr.data
159
160 print("check extra output", repr(code), cridx_ok, cridx)
161 if rc:
162 self.assertEqual(cridx, 0, code)
163
164 sim_o = {}
165 res = {}
166
167 yield from ALUHelpers.get_cr_a(res, alu, dec2)
168 yield from ALUHelpers.get_xer_ca(res, alu, dec2)
169 yield from ALUHelpers.get_int_o(res, alu, dec2)
170
171 print("hw outputs", res)
172
173 yield from ALUHelpers.get_sim_int_o(sim_o, sim, dec2)
174 yield from ALUHelpers.get_wr_sim_cr_a(sim_o, sim, dec2)
175 yield from ALUHelpers.get_wr_sim_xer_ca(sim_o, sim, dec2)
176
177 print("sim outputs", sim_o)
178
179 ALUHelpers.check_cr_a(self, res, sim_o, "CR%d %s" % (cridx, code))
180 ALUHelpers.check_xer_ca(self, res, sim_o, code)
181 ALUHelpers.check_int_o(self, res, sim_o, code)
182
183
184 if __name__ == "__main__":
185 unittest.main(exit=False)
186 suite = unittest.TestSuite()
187 suite.addTest(TestRunner(BitManipTestCase().test_data))
188 suite.addTest(TestRunner(BitManipIlangCase().test_data))
189
190 runner = unittest.TextTestRunner()
191 runner.run(suite)