1 from nmigen
import Module
, Signal
2 from nmigen
.back
.pysim
import Simulator
, Delay
, Settle
3 from nmigen
.test
.utils
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
.cr
.pipeline
import CRBasePipe
16 from soc
.fu
.cr
.pipe_data
import CRPipeSpec
21 def __init__(self
, program
, regs
, sprs
, cr
, name
):
22 self
.program
= program
29 # This test bench is a bit different than is usual. Initially when I
30 # was writing it, I had all of the tests call a function to create a
31 # device under test and simulator, initialize the dut, run the
32 # simulation for ~2 cycles, and assert that the dut output what it
33 # should have. However, this was really slow, since it needed to
34 # create and tear down the dut and simulator for every test case.
36 # Now, instead of doing that, every test case in ALUTestCase puts some
37 # data into the test_data list below, describing the instructions to
38 # be tested and the initial state. Once all the tests have been run,
39 # test_data gets passed to TestRunner which then sets up the DUT and
40 # simulator once, runs all the data through it, and asserts that the
41 # results match the pseudocode sim at every cycle.
43 # By doing this, I've reduced the time it takes to run the test suite
44 # massively. Before, it took around 1 minute on my computer, now it
45 # takes around 3 seconds
50 class CRTestCase(FHDLTestCase
):
51 def __init__(self
, name
):
52 super().__init
__(name
)
54 def run_tst_program(self
, prog
, initial_regs
=[0] * 32, initial_sprs
={},
56 tc
= TestCase(prog
, initial_regs
, initial_sprs
, initial_cr
,
62 bi
= random
.randint(0, 31)
63 lst
= [f
"isel 3, 1, 2, {bi}"]
64 cr
= random
.randint(0, (1<<32)-1)
65 initial_regs
= [0] * 32
66 initial_regs
[1] = random
.randint(0, (1<<32)-1)
67 initial_regs
[2] = random
.randint(0, (1<<32)-1)
68 initial_regs
[3] = random
.randint(0, (1<<32)-1)
69 self
.run_tst_program(Program(lst
), initial_regs
=initial_regs
,
73 insns
= ["crand", "cror", "crnand", "crnor", "crxor", "creqv",
76 choice
= random
.choice(insns
)
77 ba
= random
.randint(0, 31)
78 bb
= random
.randint(0, 31)
79 bt
= random
.randint(0, 31)
80 lst
= [f
"{choice} {ba}, {bb}, {bt}"]
81 cr
= random
.randint(0, (1<<32)-1)
82 self
.run_tst_program(Program(lst
), initial_cr
=cr
)
86 lst
= ["crand 0, 11, 13"]
87 cr
= random
.randint(0, (1<<32)-1)
88 self
.run_tst_program(Program(lst
), initial_cr
=cr
)
93 self
.run_tst_program(Program(lst
), initial_cr
=cr
)
97 mask
= random
.randint(0, 255)
98 lst
= [f
"mtcrf {mask}, 2"]
99 cr
= random
.randint(0, (1<<32)-1)
100 initial_regs
= [0] * 32
101 initial_regs
[2] = random
.randint(0, (1<<32)-1)
102 self
.run_tst_program(Program(lst
), initial_regs
=initial_regs
,
104 def test_mtocrf(self
):
106 mask
= 1<<random
.randint(0, 7)
107 lst
= [f
"mtocrf {mask}, 2"]
108 cr
= random
.randint(0, (1<<32)-1)
109 initial_regs
= [0] * 32
110 initial_regs
[2] = random
.randint(0, (1<<32)-1)
111 self
.run_tst_program(Program(lst
), initial_regs
=initial_regs
,
117 cr
= random
.randint(0, (1<<32)-1)
118 self
.run_tst_program(Program(lst
), initial_cr
=cr
)
120 def test_mfocrf(self
):
122 mask
= 1<<random
.randint(0, 7)
123 lst
= [f
"mfocrf 2, {mask}"]
124 cr
= random
.randint(0, (1<<32)-1)
125 self
.run_tst_program(Program(lst
), initial_cr
=cr
)
129 bc
= random
.randint(0, 31)
130 lst
= [f
"isel 1, 2, 3, {bc}"]
131 cr
= random
.randint(0, (1<<32)-1)
132 initial_regs
= [0] * 32
133 initial_regs
[2] = random
.randint(0, (1<<64)-1)
134 initial_regs
[3] = random
.randint(0, (1<<64)-1)
135 self
.run_tst_program(Program(lst
), initial_cr
=cr
)
139 def test_ilang(self
):
140 pspec
= CRPipeSpec(id_wid
=2)
141 alu
= CRBasePipe(pspec
)
142 vl
= rtlil
.convert(alu
, ports
=alu
.ports())
143 with
open("cr_pipeline.il", "w") as f
:
147 class TestRunner(FHDLTestCase
):
148 def __init__(self
, test_data
):
149 super().__init
__("run_all")
150 self
.test_data
= test_data
152 def set_inputs(self
, alu
, dec2
, simulator
):
153 full_reg
= yield dec2
.e
.read_cr_whole
155 print(simulator
.cr
.get_range().value
)
157 yield alu
.p
.data_i
.full_cr
.eq(simulator
.cr
.get_range().value
)
159 cr1_en
= yield dec2
.e
.read_cr1
.ok
161 cr1_sel
= yield dec2
.e
.read_cr1
.data
162 cr1
= simulator
.crl
[cr1_sel
].get_range().value
163 yield alu
.p
.data_i
.cr_a
.eq(cr1
)
164 cr2_en
= yield dec2
.e
.read_cr2
.ok
166 cr2_sel
= yield dec2
.e
.read_cr2
.data
167 cr2
= simulator
.crl
[cr2_sel
].get_range().value
168 yield alu
.p
.data_i
.cr_b
.eq(cr2
)
169 cr3_en
= yield dec2
.e
.read_cr3
.ok
171 cr3_sel
= yield dec2
.e
.read_cr3
.data
172 cr3
= simulator
.crl
[cr3_sel
].get_range().value
173 yield alu
.p
.data_i
.cr_c
.eq(cr3
)
175 reg3_ok
= yield dec2
.e
.read_reg3
.ok
177 reg3_sel
= yield dec2
.e
.read_reg3
.data
178 reg3
= simulator
.gpr(reg3_sel
).value
179 yield alu
.p
.data_i
.a
.eq(reg3
)
181 def assert_outputs(self
, alu
, dec2
, simulator
):
182 whole_reg
= yield dec2
.e
.write_cr_whole
183 cr_en
= yield dec2
.e
.write_cr
.ok
185 full_cr
= yield alu
.n
.data_o
.full_cr
.data
186 expected_cr
= simulator
.cr
.get_range().value
187 self
.assertEqual(expected_cr
, full_cr
)
189 cr_sel
= yield dec2
.e
.write_cr
.data
190 expected_cr
= simulator
.crl
[cr_sel
].get_range().value
191 real_cr
= yield alu
.n
.data_o
.cr_o
.data
192 self
.assertEqual(expected_cr
, real_cr
)
197 instruction
= Signal(32)
199 pdecode
= create_pdecode()
201 m
.submodules
.pdecode2
= pdecode2
= PowerDecode2(pdecode
)
203 pspec
= CRPipeSpec(id_wid
=2)
204 m
.submodules
.alu
= alu
= CRBasePipe(pspec
)
206 comb
+= alu
.p
.data_i
.ctx
.op
.eq_from_execute1(pdecode2
.e
)
207 comb
+= alu
.n
.ready_i
.eq(1)
208 comb
+= pdecode2
.dec
.raw_opcode_in
.eq(instruction
)
213 for test
in self
.test_data
:
215 program
= test
.program
216 self
.subTest(test
.name
)
217 simulator
= ISA(pdecode2
, test
.regs
, test
.sprs
, test
.cr
)
218 gen
= program
.generate_instructions()
219 instructions
= list(zip(gen
, program
.assembly
.splitlines()))
221 index
= simulator
.pc
.CIA
.value
//4
222 while index
< len(instructions
):
223 ins
, code
= instructions
[index
]
225 print("0x{:X}".format(ins
& 0xffffffff))
228 # ask the decoder to decode this binary data (endian'd)
229 yield pdecode2
.dec
.bigendian
.eq(0) # little / big?
230 yield instruction
.eq(ins
) # raw binary instr.
232 yield from self
.set_inputs(alu
, pdecode2
, simulator
)
233 yield alu
.p
.valid_i
.eq(1)
234 fn_unit
= yield pdecode2
.e
.fn_unit
235 self
.assertEqual(fn_unit
, Function
.CR
.value
, code
)
237 opname
= code
.split(' ')[0]
238 yield from simulator
.call(opname
)
239 index
= simulator
.pc
.CIA
.value
//4
241 vld
= yield alu
.n
.valid_o
244 vld
= yield alu
.n
.valid_o
246 yield from self
.assert_outputs(alu
, pdecode2
, simulator
)
248 sim
.add_sync_process(process
)
249 with sim
.write_vcd("simulator.vcd", "simulator.gtkw",
253 def check_extra_alu_outputs(self
, alu
, dec2
, sim
):
254 rc
= yield dec2
.e
.rc
.data
256 cr_expected
= sim
.crl
[0].get_range().value
257 cr_actual
= yield alu
.n
.data_o
.cr0
258 self
.assertEqual(cr_expected
, cr_actual
)
261 if __name__
== "__main__":
262 unittest
.main(exit
=False)
263 suite
= unittest
.TestSuite()
264 suite
.addTest(TestRunner(test_data
))
266 runner
= unittest
.TextTestRunner()