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
)
55 def run_tst_program(self
, prog
, initial_regs
=[0] * 32, initial_sprs
={},
57 tc
= TestCase(prog
, initial_regs
, initial_sprs
, initial_cr
,
62 insns
= ["crand", "cror", "crnand", "crnor", "crxor", "creqv",
65 choice
= random
.choice(insns
)
66 ba
= random
.randint(0, 31)
67 bb
= random
.randint(0, 31)
68 bt
= random
.randint(0, 31)
69 lst
= [f
"{choice} {ba}, {bb}, {bt}"]
70 cr
= random
.randint(0, (1<<32)-1)
71 self
.run_tst_program(Program(lst
), initial_cr
=cr
)
75 lst
= ["crand 0, 11, 13"]
76 cr
= random
.randint(0, (1<<32)-1)
77 self
.run_tst_program(Program(lst
), initial_cr
=cr
)
82 self
.run_tst_program(Program(lst
), initial_cr
=cr
)
86 mask
= random
.randint(0, 255)
87 lst
= [f
"mtcrf {mask}, 2"]
88 cr
= random
.randint(0, (1<<32)-1)
89 initial_regs
= [0] * 32
90 initial_regs
[2] = random
.randint(0, (1<<32)-1)
91 self
.run_tst_program(Program(lst
), initial_regs
=initial_regs
,
93 def test_mtocrf(self
):
95 mask
= 1<<random
.randint(0, 7)
96 lst
= [f
"mtocrf {mask}, 2"]
97 cr
= random
.randint(0, (1<<32)-1)
98 initial_regs
= [0] * 32
99 initial_regs
[2] = random
.randint(0, (1<<32)-1)
100 self
.run_tst_program(Program(lst
), initial_regs
=initial_regs
,
106 cr
= random
.randint(0, (1<<32)-1)
107 self
.run_tst_program(Program(lst
), initial_cr
=cr
)
109 def test_mfocrf(self
):
111 mask
= 1<<random
.randint(0, 7)
112 lst
= [f
"mfocrf 2, {mask}"]
113 cr
= random
.randint(0, (1<<32)-1)
114 self
.run_tst_program(Program(lst
), initial_cr
=cr
)
118 bc
= random
.randint(0, 31)
119 lst
= [f
"isel 1, 2, 3, {bc}"]
120 cr
= random
.randint(0, (1<<32)-1)
121 initial_regs
= [0] * 32
122 initial_regs
[2] = random
.randint(0, (1<<64)-1)
123 initial_regs
[3] = random
.randint(0, (1<<64)-1)
124 self
.run_tst_program(Program(lst
), initial_cr
=cr
)
128 def test_ilang(self
):
129 pspec
= CRPipeSpec(id_wid
=2)
130 alu
= CRBasePipe(pspec
)
131 vl
= rtlil
.convert(alu
, ports
=alu
.ports())
132 with
open("cr_pipeline.il", "w") as f
:
136 class TestRunner(FHDLTestCase
):
137 def __init__(self
, test_data
):
138 super().__init
__("run_all")
139 self
.test_data
= test_data
141 def set_inputs(self
, alu
, dec2
, simulator
):
142 full_reg
= yield dec2
.e
.read_cr_whole
144 print(simulator
.cr
.get_range().value
)
146 yield alu
.p
.data_i
.full_cr
.eq(simulator
.cr
.get_range().value
)
148 cr1_en
= yield dec2
.e
.read_cr1
.ok
150 cr1_sel
= yield dec2
.e
.read_cr1
.data
151 cr1
= simulator
.crl
[cr1_sel
].get_range().value
152 yield alu
.p
.data_i
.cr_a
.eq(cr1
)
153 cr2_en
= yield dec2
.e
.read_cr2
.ok
155 cr2_sel
= yield dec2
.e
.read_cr2
.data
156 cr2
= simulator
.crl
[cr2_sel
].get_range().value
157 yield alu
.p
.data_i
.cr_b
.eq(cr2
)
158 cr3_en
= yield dec2
.e
.read_cr3
.ok
160 cr3_sel
= yield dec2
.e
.read_cr3
.data
161 cr3
= simulator
.crl
[cr3_sel
].get_range().value
162 yield alu
.p
.data_i
.cr_c
.eq(cr3
)
164 reg3_ok
= yield dec2
.e
.read_reg3
.ok
166 reg3_sel
= yield dec2
.e
.read_reg3
.data
167 reg3
= simulator
.gpr(reg3_sel
).value
168 yield alu
.p
.data_i
.a
.eq(reg3
)
170 def assert_outputs(self
, alu
, dec2
, simulator
):
171 whole_reg
= yield dec2
.e
.write_cr_whole
172 cr_en
= yield dec2
.e
.write_cr
.ok
174 full_cr
= yield alu
.n
.data_o
.full_cr
.data
175 expected_cr
= simulator
.cr
.get_range().value
176 self
.assertEqual(expected_cr
, full_cr
)
178 cr_sel
= yield dec2
.e
.write_cr
.data
179 expected_cr
= simulator
.crl
[cr_sel
].get_range().value
180 real_cr
= yield alu
.n
.data_o
.cr_o
.data
181 self
.assertEqual(expected_cr
, real_cr
)
186 instruction
= Signal(32)
188 pdecode
= create_pdecode()
190 m
.submodules
.pdecode2
= pdecode2
= PowerDecode2(pdecode
)
192 pspec
= CRPipeSpec(id_wid
=2)
193 m
.submodules
.alu
= alu
= CRBasePipe(pspec
)
195 comb
+= alu
.p
.data_i
.ctx
.op
.eq_from_execute1(pdecode2
.e
)
196 comb
+= alu
.n
.ready_i
.eq(1)
197 comb
+= pdecode2
.dec
.raw_opcode_in
.eq(instruction
)
202 for test
in self
.test_data
:
204 program
= test
.program
205 self
.subTest(test
.name
)
206 simulator
= ISA(pdecode2
, test
.regs
, test
.sprs
, test
.cr
)
207 gen
= program
.generate_instructions()
208 instructions
= list(zip(gen
, program
.assembly
.splitlines()))
210 index
= simulator
.pc
.CIA
.value
//4
211 while index
< len(instructions
):
212 ins
, code
= instructions
[index
]
214 print("0x{:X}".format(ins
& 0xffffffff))
217 # ask the decoder to decode this binary data (endian'd)
218 yield pdecode2
.dec
.bigendian
.eq(0) # little / big?
219 yield instruction
.eq(ins
) # raw binary instr.
221 yield from self
.set_inputs(alu
, pdecode2
, simulator
)
222 yield alu
.p
.valid_i
.eq(1)
223 fn_unit
= yield pdecode2
.e
.fn_unit
224 self
.assertEqual(fn_unit
, Function
.CR
.value
, code
)
226 opname
= code
.split(' ')[0]
227 yield from simulator
.call(opname
)
228 index
= simulator
.pc
.CIA
.value
//4
230 vld
= yield alu
.n
.valid_o
233 vld
= yield alu
.n
.valid_o
235 yield from self
.assert_outputs(alu
, pdecode2
, simulator
)
237 sim
.add_sync_process(process
)
238 with sim
.write_vcd("simulator.vcd", "simulator.gtkw",
242 def check_extra_alu_outputs(self
, alu
, dec2
, sim
):
243 rc
= yield dec2
.e
.rc
.data
245 cr_expected
= sim
.crl
[0].get_range().value
246 cr_actual
= yield alu
.n
.data_o
.cr0
247 self
.assertEqual(cr_expected
, cr_actual
)
250 if __name__
== "__main__":
251 unittest
.main(exit
=False)
252 suite
= unittest
.TestSuite()
253 suite
.addTest(TestRunner(test_data
))
255 runner
= unittest
.TextTestRunner()