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
)
48 # def get_cu_inputs(dec2, sim):
49 # """naming (res) must conform to CRFunctionUnit input regspec
52 # full_reg = yield dec2.e.read_cr_whole
55 # print(sim.cr.get_range().value)
57 # res['full_cr'] = sim.cr.get_range().value
60 # cr1_en = yield dec2.e.read_cr1.ok
62 # cr1_sel = yield dec2.e.read_cr1.data
63 # res['cr_a'] = sim.crl[cr1_sel].get_range().value
64 # cr2_en = yield dec2.e.read_cr2.ok
67 # cr2_sel = yield dec2.e.read_cr2.data
68 # res['cr_b'] = sim.crl[cr2_sel].get_range().value
69 # cr3_en = yield dec2.e.read_cr3.ok
72 # cr3_sel = yield dec2.e.read_cr3.data
73 # res['cr_c'] = sim.crl[cr3_sel].get_range().value
76 # reg1_ok = yield dec2.e.read_reg1.ok
78 # data1 = yield dec2.e.read_reg1.data
79 # res['ra'] = sim.gpr(data1).value
82 # reg2_ok = yield dec2.e.read_reg2.ok
84 # data2 = yield dec2.e.read_reg2.data
85 # res['rb'] = sim.gpr(data2).value
87 # print ("get inputs", res)
91 class TestRunner(FHDLTestCase
):
92 def __init__(self
, test_data
):
93 super().__init
__("run_all")
94 self
.test_data
= test_data
96 # def set_inputs(self, alu, dec2, simulator):
97 # inp = yield from get_cu_inputs(dec2, simulator)
98 # if 'full_cr' in inp:
99 # yield alu.p.data_i.full_cr.eq(inp['full_cr'])
101 # yield alu.p.data_i.full_cr.eq(0)
103 # yield alu.p.data_i.cr_a.eq(inp['cr_a'])
105 # yield alu.p.data_i.cr_b.eq(inp['cr_b'])
107 # yield alu.p.data_i.cr_c.eq(inp['cr_c'])
109 # yield alu.p.data_i.ra.eq(inp['ra'])
111 # yield alu.p.data_i.ra.eq(0)
113 # yield alu.p.data_i.rb.eq(inp['rb'])
115 # yield alu.p.data_i.rb.eq(0)
117 # def assert_outputs(self, alu, dec2, simulator, code):
118 # whole_reg = yield dec2.e.write_cr_whole
119 # cr_en = yield dec2.e.write_cr.ok
121 # full_cr = yield alu.n.data_o.full_cr.data
122 # expected_cr = simulator.cr.get_range().value
123 # self.assertEqual(expected_cr, full_cr, code)
125 # cr_sel = yield dec2.e.write_cr.data
126 # expected_cr = simulator.crl[cr_sel].get_range().value
127 # real_cr = yield alu.n.data_o.cr.data
128 # self.assertEqual(expected_cr, real_cr, code)
129 # alu_out = yield alu.n.data_o.o.data
130 # out_reg_valid = yield dec2.e.write_reg.ok
132 # write_reg_idx = yield dec2.e.write_reg.data
133 # expected = simulator.gpr(write_reg_idx).value
134 # print(f"expected {expected:x}, actual: {alu_out:x}")
135 # self.assertEqual(expected, alu_out, code)
140 instruction
= Signal(32)
142 pdecode
= create_pdecode()
144 m
.submodules
.pdecode2
= pdecode2
= PowerDecode2(pdecode
)
146 # pspec = CRPipeSpec(id_wid=2)
147 # m.submodules.alu = alu = CRBasePipe(pspec)
149 # comb += alu.p.data_i.ctx.op.eq_from_execute1(pdecode2.e)
150 # comb += alu.n.ready_i.eq(1)
151 comb
+= pdecode2
.dec
.raw_opcode_in
.eq(instruction
)
156 for test
in self
.test_data
:
158 program
= test
.program
159 self
.subTest(test
.name
)
160 sim
= ISA(pdecode2
, test
.regs
, test
.sprs
, test
.cr
)
161 gen
= program
.generate_instructions()
162 instructions
= list(zip(gen
, program
.assembly
.splitlines()))
164 index
= sim
.pc
.CIA
.value
//4
165 while index
< len(instructions
):
166 ins
, code
= instructions
[index
]
168 print("0x{:X}".format(ins
& 0xffffffff))
171 # ask the decoder to decode this binary data (endian'd)
172 yield pdecode2
.dec
.bigendian
.eq(0) # little / big?
173 yield instruction
.eq(ins
) # raw binary instr.
175 yield from self
.set_inputs(alu
, pdecode2
, sim
)
176 yield alu
.p
.valid_i
.eq(1)
177 fn_unit
= yield pdecode2
.e
.fn_unit
178 self
.assertEqual(fn_unit
, Function
.CR
.value
, code
)
180 opname
= code
.split(' ')[0]
181 yield from sim
.call(opname
)
182 index
= sim
.pc
.CIA
.value
//4
184 vld
= yield alu
.n
.valid_o
187 vld
= yield alu
.n
.valid_o
189 yield from self
.assert_outputs(alu
, pdecode2
, sim
, code
)
191 sim
.add_sync_process(process
)
192 with sim
.write_vcd("simulator.vcd", "simulator.gtkw",
197 if __name__
== "__main__":
198 unittest
.main(exit
=False)
199 suite
= unittest
.TestSuite()
200 suite
.addTest(TestRunner(TrapTestCase
.test_data
))
202 runner
= unittest
.TextTestRunner()