a87bb89689bb293282435ab53689a86e62738ca7
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
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 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
,
94 def test_mtocrf(self
):
96 mask
= 1<<random
.randint(0, 7)
97 lst
= [f
"mtocrf {mask}, 2"]
98 cr
= random
.randint(0, (1<<32)-1)
99 initial_regs
= [0] * 32
100 initial_regs
[2] = random
.randint(0, (1<<32)-1)
101 self
.run_tst_program(Program(lst
, bigendian
), initial_regs
=initial_regs
,
107 cr
= random
.randint(0, (1<<32)-1)
108 self
.run_tst_program(Program(lst
, bigendian
), initial_cr
=cr
)
110 def test_mfocrf(self
):
112 mask
= 1<<random
.randint(0, 7)
113 lst
= [f
"mfocrf 2, {mask}"]
114 cr
= random
.randint(0, (1<<32)-1)
115 self
.run_tst_program(Program(lst
, bigendian
), initial_cr
=cr
)
119 bc
= random
.randint(0, 31)
120 lst
= [f
"isel 1, 2, 3, {bc}"]
121 cr
= random
.randint(0, (1<<32)-1)
122 initial_regs
= [0] * 32
123 initial_regs
[2] = random
.randint(0, (1<<64)-1)
124 initial_regs
[3] = random
.randint(0, (1<<64)-1)
125 #initial_regs[2] = i*2
126 #initial_regs[3] = i*2+1
127 self
.run_tst_program(Program(lst
, bigendian
),
128 initial_regs
=initial_regs
, initial_cr
=cr
)
132 bfa
= random
.randint(0, 7)
133 lst
= [f
"setb 1, {bfa}"]
134 cr
= random
.randint(0, (1<<32)-1)
135 self
.run_tst_program(Program(lst
, bigendian
), initial_cr
=cr
)
137 def test_regression_setb(self
):
139 cr
= random
.randint(0, 0x66f6b106)
140 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
)
251 for test
in self
.test_data
:
253 program
= test
.program
254 self
.subTest(test
.name
)
255 sim
= ISA(pdecode2
, test
.regs
, test
.sprs
, test
.cr
, test
.mem
,
258 gen
= program
.generate_instructions()
259 instructions
= list(zip(gen
, program
.assembly
.splitlines()))
261 index
= sim
.pc
.CIA
.value
//4
262 while index
< len(instructions
):
263 ins
, code
= instructions
[index
]
265 print("0x{:X}".format(ins
& 0xffffffff))
268 # ask the decoder to decode this binary data (endian'd)
269 yield pdecode2
.dec
.bigendian
.eq(bigendian
) # little / big?
270 yield instruction
.eq(ins
) # raw binary instr.
272 yield from self
.set_inputs(alu
, pdecode2
, sim
)
273 yield alu
.p
.valid_i
.eq(1)
274 fn_unit
= yield pdecode2
.e
.do
.fn_unit
275 self
.assertEqual(fn_unit
, Function
.CR
.value
, code
)
277 opname
= code
.split(' ')[0]
278 yield from sim
.call(opname
)
279 index
= sim
.pc
.CIA
.value
//4
281 vld
= yield alu
.n
.valid_o
284 vld
= yield alu
.n
.valid_o
286 yield from self
.assert_outputs(alu
, pdecode2
, sim
, code
)
288 sim
.add_sync_process(process
)
289 with sim
.write_vcd("simulator.vcd", "simulator.gtkw",
294 if __name__
== "__main__":
295 unittest
.main(exit
=False)
296 suite
= unittest
.TestSuite()
297 suite
.addTest(TestRunner(CRTestCase
.test_data
))
299 runner
= unittest
.TextTestRunner()