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
13 from soc
.config
.endian
import bigendian
15 from soc
.fu
.test
.common
import TestCase
, ALUHelpers
16 from soc
.fu
.cr
.pipeline
import CRBasePipe
17 from soc
.fu
.cr
.pipe_data
import CRPipeSpec
21 # This test bench is a bit different than is usual. Initially when I
22 # was writing it, I had all of the tests call a function to create a
23 # device under test and simulator, initialize the dut, run the
24 # simulation for ~2 cycles, and assert that the dut output what it
25 # should have. However, this was really slow, since it needed to
26 # create and tear down the dut and simulator for every test case.
28 # Now, instead of doing that, every test case in ALUTestCase puts some
29 # data into the test_data list below, describing the instructions to
30 # be tested and the initial state. Once all the tests have been run,
31 # test_data gets passed to TestRunner which then sets up the DUT and
32 # simulator once, runs all the data through it, and asserts that the
33 # results match the pseudocode sim at every cycle.
35 # By doing this, I've reduced the time it takes to run the test suite
36 # massively. Before, it took around 1 minute on my computer, now it
37 # takes around 3 seconds
40 class CRTestCase(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
)
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
, bigendian
), initial_cr
=cr
)
67 lst
= ["crand 0, 11, 13"]
68 cr
= random
.randint(0, (1 << 32)-1)
69 self
.run_tst_program(Program(lst
, bigendian
), initial_cr
=cr
)
71 def test_1_mcrf(self
):
73 src
= random
.randint(0, 7)
74 dst
= random
.randint(0, 7)
75 lst
= [f
"mcrf {src}, {dst}"]
76 cr
= random
.randint(0, (1 << 32)-1)
77 self
.run_tst_program(Program(lst
, bigendian
), initial_cr
=cr
)
79 def test_0_mcrf(self
):
81 lst
= [f
"mcrf 5, {i}"]
83 self
.run_tst_program(Program(lst
, bigendian
), initial_cr
=cr
)
87 mask
= random
.randint(0, 255)
88 lst
= [f
"mtcrf {mask}, 2"]
89 cr
= random
.randint(0, (1 << 32)-1)
90 initial_regs
= [0] * 32
91 initial_regs
[2] = random
.randint(0, (1 << 32)-1)
92 self
.run_tst_program(Program(lst
, bigendian
), initial_regs
=initial_regs
,
95 def test_mtocrf(self
):
97 mask
= 1 << random
.randint(0, 7)
98 lst
= [f
"mtocrf {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
, bigendian
), initial_regs
=initial_regs
,
108 cr
= random
.randint(0, (1 << 32)-1)
109 self
.run_tst_program(Program(lst
, bigendian
), initial_cr
=cr
)
111 def test_mfocrf(self
):
113 mask
= 1 << random
.randint(0, 7)
114 lst
= [f
"mfocrf 2, {mask}"]
115 cr
= random
.randint(0, (1 << 32)-1)
116 self
.run_tst_program(Program(lst
, bigendian
), initial_cr
=cr
)
120 bc
= random
.randint(0, 31)
121 lst
= [f
"isel 1, 2, 3, {bc}"]
122 cr
= random
.randint(0, (1 << 32)-1)
123 initial_regs
= [0] * 32
124 initial_regs
[2] = random
.randint(0, (1 << 64)-1)
125 initial_regs
[3] = random
.randint(0, (1 << 64)-1)
126 #initial_regs[2] = i*2
127 #initial_regs[3] = i*2+1
128 self
.run_tst_program(Program(lst
, bigendian
),
129 initial_regs
=initial_regs
, initial_cr
=cr
)
133 bfa
= random
.randint(0, 7)
134 lst
= [f
"setb 1, {bfa}"]
135 cr
= random
.randint(0, (1 << 32)-1)
136 self
.run_tst_program(Program(lst
, bigendian
), initial_cr
=cr
)
138 def test_regression_setb(self
):
140 cr
= random
.randint(0, 0x66f6b106)
141 self
.run_tst_program(Program(lst
, bigendian
), initial_cr
=cr
)
143 def test_ilang(self
):
144 pspec
= CRPipeSpec(id_wid
=2)
145 alu
= CRBasePipe(pspec
)
146 vl
= rtlil
.convert(alu
, ports
=alu
.ports())
147 with
open("cr_pipeline.il", "w") as f
:
151 def get_cu_inputs(dec2
, sim
):
152 """naming (res) must conform to CRFunctionUnit input regspec
155 full_reg
= yield dec2
.e
.do
.read_cr_whole
158 print(sim
.cr
.get_range().value
)
160 res
['full_cr'] = sim
.cr
.get_range().value
163 cr1_en
= yield dec2
.e
.read_cr1
.ok
165 cr1_sel
= yield dec2
.e
.read_cr1
.data
166 res
['cr_a'] = sim
.crl
[cr1_sel
].get_range().value
167 cr2_en
= yield dec2
.e
.read_cr2
.ok
170 cr2_sel
= yield dec2
.e
.read_cr2
.data
171 res
['cr_b'] = sim
.crl
[cr2_sel
].get_range().value
172 cr3_en
= yield dec2
.e
.read_cr3
.ok
175 cr3_sel
= yield dec2
.e
.read_cr3
.data
176 res
['cr_c'] = sim
.crl
[cr3_sel
].get_range().value
179 reg1_ok
= yield dec2
.e
.read_reg1
.ok
181 data1
= yield dec2
.e
.read_reg1
.data
182 res
['ra'] = sim
.gpr(data1
).value
185 reg2_ok
= yield dec2
.e
.read_reg2
.ok
187 data2
= yield dec2
.e
.read_reg2
.data
188 res
['rb'] = sim
.gpr(data2
).value
190 print("get inputs", res
)
194 class TestRunner(FHDLTestCase
):
195 def __init__(self
, test_data
):
196 super().__init
__("run_all")
197 self
.test_data
= test_data
199 def set_inputs(self
, alu
, dec2
, simulator
):
200 inp
= yield from get_cu_inputs(dec2
, simulator
)
201 yield from ALUHelpers
.set_full_cr(alu
, dec2
, inp
)
202 yield from ALUHelpers
.set_cr_a(alu
, dec2
, inp
)
203 yield from ALUHelpers
.set_cr_b(alu
, dec2
, inp
)
204 yield from ALUHelpers
.set_cr_c(alu
, dec2
, inp
)
205 yield from ALUHelpers
.set_int_ra(alu
, dec2
, inp
)
206 yield from ALUHelpers
.set_int_rb(alu
, dec2
, inp
)
208 def assert_outputs(self
, alu
, dec2
, simulator
, code
):
209 whole_reg
= yield dec2
.e
.do
.write_cr_whole
210 cr_en
= yield dec2
.e
.write_cr
.ok
212 full_cr
= yield alu
.n
.data_o
.full_cr
.data
213 expected_cr
= simulator
.cr
.get_range().value
214 print(f
"CR whole: expected {expected_cr:x}, actual: {full_cr:x}")
215 self
.assertEqual(expected_cr
, full_cr
, code
)
217 cr_sel
= yield dec2
.e
.write_cr
.data
218 expected_cr
= simulator
.cr
.get_range().value
219 print(f
"CR whole: {expected_cr:x}, sel {cr_sel}")
220 expected_cr
= simulator
.crl
[cr_sel
].get_range().value
221 real_cr
= yield alu
.n
.data_o
.cr
.data
222 print(f
"CR part: expected {expected_cr:x}, actual: {real_cr:x}")
223 self
.assertEqual(expected_cr
, real_cr
, code
)
224 alu_out
= yield alu
.n
.data_o
.o
.data
225 out_reg_valid
= yield dec2
.e
.write_reg
.ok
227 write_reg_idx
= yield dec2
.e
.write_reg
.data
228 expected
= simulator
.gpr(write_reg_idx
).value
229 print(f
"expected {expected:x}, actual: {alu_out:x}")
230 self
.assertEqual(expected
, alu_out
, code
)
235 instruction
= Signal(32)
237 pdecode
= create_pdecode()
239 m
.submodules
.pdecode2
= pdecode2
= PowerDecode2(pdecode
)
241 pspec
= CRPipeSpec(id_wid
=2)
242 m
.submodules
.alu
= alu
= CRBasePipe(pspec
)
244 comb
+= alu
.p
.data_i
.ctx
.op
.eq_from_execute1(pdecode2
.e
)
245 comb
+= alu
.n
.ready_i
.eq(1)
246 comb
+= pdecode2
.dec
.raw_opcode_in
.eq(instruction
)
252 for test
in self
.test_data
:
254 program
= test
.program
255 self
.subTest(test
.name
)
256 sim
= ISA(pdecode2
, test
.regs
, test
.sprs
, test
.cr
, test
.mem
,
259 gen
= program
.generate_instructions()
260 instructions
= list(zip(gen
, program
.assembly
.splitlines()))
262 index
= sim
.pc
.CIA
.value
//4
263 while index
< len(instructions
):
264 ins
, code
= instructions
[index
]
266 print("0x{:X}".format(ins
& 0xffffffff))
269 # ask the decoder to decode this binary data (endian'd)
270 yield pdecode2
.dec
.bigendian
.eq(bigendian
) # little / big?
271 yield instruction
.eq(ins
) # raw binary instr.
273 yield from self
.set_inputs(alu
, pdecode2
, sim
)
274 yield alu
.p
.valid_i
.eq(1)
275 fn_unit
= yield pdecode2
.e
.do
.fn_unit
276 self
.assertEqual(fn_unit
, Function
.CR
.value
, code
)
278 opname
= code
.split(' ')[0]
279 yield from sim
.call(opname
)
280 index
= sim
.pc
.CIA
.value
//4
282 vld
= yield alu
.n
.valid_o
285 vld
= yield alu
.n
.valid_o
287 yield from self
.assert_outputs(alu
, pdecode2
, sim
, code
)
289 sim
.add_sync_process(process
)
290 with sim
.write_vcd("simulator.vcd", "simulator.gtkw",
295 if __name__
== "__main__":
296 unittest
.main(exit
=False)
297 suite
= unittest
.TestSuite()
298 suite
.addTest(TestRunner(CRTestCase
.test_data
))
300 runner
= unittest
.TextTestRunner()