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
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
)
10 from soc
.decoder
.selectable_int
import SelectableInt
11 from soc
.simulator
.program
import Program
12 from soc
.decoder
.isa
.all
import ISA
15 from soc
.fu
.test
.common
import TestCase
16 #from soc.fu.cr.pipeline import CRBasePipe
17 #from soc.fu.cr.pipe_data import CRPipeSpec
22 # This test bench is a bit different than is usual. Initially when I
23 # was writing it, I had all of the tests call a function to create a
24 # device under test and simulator, initialize the dut, run the
25 # simulation for ~2 cycles, and assert that the dut output what it
26 # should have. However, this was really slow, since it needed to
27 # create and tear down the dut and simulator for every test case.
29 # Now, instead of doing that, every test case in ALUTestCase puts some
30 # data into the test_data list below, describing the instructions to
31 # be tested and the initial state. Once all the tests have been run,
32 # test_data gets passed to TestRunner which then sets up the DUT and
33 # simulator once, runs all the data through it, and asserts that the
34 # results match the pseudocode sim at every cycle.
36 # By doing this, I've reduced the time it takes to run the test suite
37 # massively. Before, it took around 1 minute on my computer, now it
38 # takes around 3 seconds
41 class TrapTestCase(FHDLTestCase
):
43 def __init__(self
, name
):
44 super().__init
__(name
)
47 # def run_tst_program(self, prog, initial_regs=None, initial_sprs=None,
49 # tc = TestCase(prog, self.test_name,
50 # regs=initial_regs, sprs=initial_sprs, cr=initial_cr)
51 # self.test_data.append(tc)
53 # def test_crop(self):
54 # insns = ["crand", "cror", "crnand", "crnor", "crxor", "creqv",
57 # choice = random.choice(insns)
58 # ba = random.randint(0, 31)
59 # bb = random.randint(0, 31)
60 # bt = random.randint(0, 31)
61 # lst = [f"{choice} {ba}, {bb}, {bt}"]
62 # cr = random.randint(0, (1<<32)-1)
63 # self.run_tst_program(Program(lst), initial_cr=cr)
65 # def test_crand(self):
67 # lst = ["crand 0, 11, 13"]
68 # cr = random.randint(0, (1<<32)-1)
69 # self.run_tst_program(Program(lst), initial_cr=cr)
71 # def test_mcrf(self):
74 # self.run_tst_program(Program(lst), initial_cr=cr)
76 # def test_mtcrf(self):
78 # mask = random.randint(0, 255)
79 # lst = [f"mtcrf {mask}, 2"]
80 # cr = random.randint(0, (1<<32)-1)
81 # initial_regs = [0] * 32
82 # initial_regs[2] = random.randint(0, (1<<32)-1)
83 # self.run_tst_program(Program(lst), initial_regs=initial_regs,
87 # def get_cu_inputs(dec2, sim):
88 # """naming (res) must conform to CRFunctionUnit input regspec
91 # full_reg = yield dec2.e.read_cr_whole
94 # print(sim.cr.get_range().value)
96 # res['full_cr'] = sim.cr.get_range().value
99 # cr1_en = yield dec2.e.read_cr1.ok
101 # cr1_sel = yield dec2.e.read_cr1.data
102 # res['cr_a'] = sim.crl[cr1_sel].get_range().value
103 # cr2_en = yield dec2.e.read_cr2.ok
106 # cr2_sel = yield dec2.e.read_cr2.data
107 # res['cr_b'] = sim.crl[cr2_sel].get_range().value
108 # cr3_en = yield dec2.e.read_cr3.ok
111 # cr3_sel = yield dec2.e.read_cr3.data
112 # res['cr_c'] = sim.crl[cr3_sel].get_range().value
115 # reg1_ok = yield dec2.e.read_reg1.ok
117 # data1 = yield dec2.e.read_reg1.data
118 # res['ra'] = sim.gpr(data1).value
120 # # RB (or immediate)
121 # reg2_ok = yield dec2.e.read_reg2.ok
123 # data2 = yield dec2.e.read_reg2.data
124 # res['rb'] = sim.gpr(data2).value
126 # print ("get inputs", res)
130 class TestRunner(FHDLTestCase
):
131 def __init__(self
, test_data
):
132 super().__init
__("run_all")
133 self
.test_data
= test_data
135 # def set_inputs(self, alu, dec2, simulator):
136 # inp = yield from get_cu_inputs(dec2, simulator)
137 # if 'full_cr' in inp:
138 # yield alu.p.data_i.full_cr.eq(inp['full_cr'])
140 # yield alu.p.data_i.full_cr.eq(0)
142 # yield alu.p.data_i.cr_a.eq(inp['cr_a'])
144 # yield alu.p.data_i.cr_b.eq(inp['cr_b'])
146 # yield alu.p.data_i.cr_c.eq(inp['cr_c'])
148 # yield alu.p.data_i.ra.eq(inp['ra'])
150 # yield alu.p.data_i.ra.eq(0)
152 # yield alu.p.data_i.rb.eq(inp['rb'])
154 # yield alu.p.data_i.rb.eq(0)
156 # def assert_outputs(self, alu, dec2, simulator, code):
157 # whole_reg = yield dec2.e.write_cr_whole
158 # cr_en = yield dec2.e.write_cr.ok
160 # full_cr = yield alu.n.data_o.full_cr.data
161 # expected_cr = simulator.cr.get_range().value
162 # self.assertEqual(expected_cr, full_cr, code)
164 # cr_sel = yield dec2.e.write_cr.data
165 # expected_cr = simulator.crl[cr_sel].get_range().value
166 # real_cr = yield alu.n.data_o.cr.data
167 # self.assertEqual(expected_cr, real_cr, code)
168 # alu_out = yield alu.n.data_o.o.data
169 # out_reg_valid = yield dec2.e.write_reg.ok
171 # write_reg_idx = yield dec2.e.write_reg.data
172 # expected = simulator.gpr(write_reg_idx).value
173 # print(f"expected {expected:x}, actual: {alu_out:x}")
174 # self.assertEqual(expected, alu_out, code)
179 instruction
= Signal(32)
181 pdecode
= create_pdecode()
183 m
.submodules
.pdecode2
= pdecode2
= PowerDecode2(pdecode
)
185 # pspec = CRPipeSpec(id_wid=2)
186 # m.submodules.alu = alu = CRBasePipe(pspec)
188 # comb += alu.p.data_i.ctx.op.eq_from_execute1(pdecode2.e)
189 # comb += alu.n.ready_i.eq(1)
190 comb
+= pdecode2
.dec
.raw_opcode_in
.eq(instruction
)
195 for test
in self
.test_data
:
197 program
= test
.program
198 self
.subTest(test
.name
)
199 sim
= ISA(pdecode2
, test
.regs
, test
.sprs
, test
.cr
)
200 gen
= program
.generate_instructions()
201 instructions
= list(zip(gen
, program
.assembly
.splitlines()))
203 index
= sim
.pc
.CIA
.value
//4
204 while index
< len(instructions
):
205 ins
, code
= instructions
[index
]
207 print("0x{:X}".format(ins
& 0xffffffff))
210 # ask the decoder to decode this binary data (endian'd)
211 yield pdecode2
.dec
.bigendian
.eq(0) # little / big?
212 yield instruction
.eq(ins
) # raw binary instr.
214 yield from self
.set_inputs(alu
, pdecode2
, sim
)
215 yield alu
.p
.valid_i
.eq(1)
216 fn_unit
= yield pdecode2
.e
.fn_unit
217 self
.assertEqual(fn_unit
, Function
.CR
.value
, code
)
219 opname
= code
.split(' ')[0]
220 yield from sim
.call(opname
)
221 index
= sim
.pc
.CIA
.value
//4
223 vld
= yield alu
.n
.valid_o
226 vld
= yield alu
.n
.valid_o
228 yield from self
.assert_outputs(alu
, pdecode2
, sim
, code
)
230 sim
.add_sync_process(process
)
231 with sim
.write_vcd("simulator.vcd", "simulator.gtkw",
236 if __name__
== "__main__":
237 unittest
.main(exit
=False)
238 suite
= unittest
.TestSuite()
239 suite
.addTest(TestRunner(TrapTestCase
.test_data
))
241 runner
= unittest
.TextTestRunner()