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 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
), initial_cr
=cr
)
67 lst
= ["crand 0, 11, 13"]
68 cr
= random
.randint(0, (1<<32)-1)
69 self
.run_tst_program(Program(lst
), 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
), initial_cr
=cr
)
79 def test_0_mcrf(self
):
81 lst
= [f
"mcrf 5, {i}"]
83 self
.run_tst_program(Program(lst
), 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
), 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
), initial_regs
=initial_regs
,
107 cr
= random
.randint(0, (1<<32)-1)
108 self
.run_tst_program(Program(lst
), 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
), 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
),
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
), 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 def get_cu_inputs(dec2
, sim
):
148 """naming (res) must conform to CRFunctionUnit input regspec
151 full_reg
= yield dec2
.e
.read_cr_whole
154 print(sim
.cr
.get_range().value
)
156 res
['full_cr'] = sim
.cr
.get_range().value
159 cr1_en
= yield dec2
.e
.read_cr1
.ok
161 cr1_sel
= yield dec2
.e
.read_cr1
.data
162 res
['cr_a'] = sim
.crl
[cr1_sel
].get_range().value
163 cr2_en
= yield dec2
.e
.read_cr2
.ok
166 cr2_sel
= yield dec2
.e
.read_cr2
.data
167 res
['cr_b'] = sim
.crl
[cr2_sel
].get_range().value
168 cr3_en
= yield dec2
.e
.read_cr3
.ok
171 cr3_sel
= yield dec2
.e
.read_cr3
.data
172 res
['cr_c'] = sim
.crl
[cr3_sel
].get_range().value
175 reg1_ok
= yield dec2
.e
.read_reg1
.ok
177 data1
= yield dec2
.e
.read_reg1
.data
178 res
['ra'] = sim
.gpr(data1
).value
181 reg2_ok
= yield dec2
.e
.read_reg2
.ok
183 data2
= yield dec2
.e
.read_reg2
.data
184 res
['rb'] = sim
.gpr(data2
).value
186 print ("get inputs", res
)
190 class TestRunner(FHDLTestCase
):
191 def __init__(self
, test_data
):
192 super().__init
__("run_all")
193 self
.test_data
= test_data
195 def set_inputs(self
, alu
, dec2
, simulator
):
196 inp
= yield from get_cu_inputs(dec2
, simulator
)
198 yield alu
.p
.data_i
.full_cr
.eq(inp
['full_cr'])
200 yield alu
.p
.data_i
.full_cr
.eq(0)
202 yield alu
.p
.data_i
.cr_a
.eq(inp
['cr_a'])
204 yield alu
.p
.data_i
.cr_b
.eq(inp
['cr_b'])
206 yield alu
.p
.data_i
.cr_c
.eq(inp
['cr_c'])
208 yield alu
.p
.data_i
.ra
.eq(inp
['ra'])
210 yield alu
.p
.data_i
.ra
.eq(0)
212 yield alu
.p
.data_i
.rb
.eq(inp
['rb'])
214 yield alu
.p
.data_i
.rb
.eq(0)
216 def assert_outputs(self
, alu
, dec2
, simulator
, code
):
217 whole_reg
= yield dec2
.e
.write_cr_whole
218 cr_en
= yield dec2
.e
.write_cr
.ok
220 full_cr
= yield alu
.n
.data_o
.full_cr
.data
221 expected_cr
= simulator
.cr
.get_range().value
222 print(f
"CR whole: expected {expected_cr:x}, actual: {full_cr:x}")
223 self
.assertEqual(expected_cr
, full_cr
, code
)
225 cr_sel
= yield dec2
.e
.write_cr
.data
226 expected_cr
= simulator
.cr
.get_range().value
227 print(f
"CR whole: {expected_cr:x}, sel {cr_sel}")
228 expected_cr
= simulator
.crl
[cr_sel
].get_range().value
229 real_cr
= yield alu
.n
.data_o
.cr
.data
230 print(f
"CR part: expected {expected_cr:x}, actual: {real_cr:x}")
231 self
.assertEqual(expected_cr
, real_cr
, code
)
232 alu_out
= yield alu
.n
.data_o
.o
.data
233 out_reg_valid
= yield dec2
.e
.write_reg
.ok
235 write_reg_idx
= yield dec2
.e
.write_reg
.data
236 expected
= simulator
.gpr(write_reg_idx
).value
237 print(f
"expected {expected:x}, actual: {alu_out:x}")
238 self
.assertEqual(expected
, alu_out
, code
)
243 instruction
= Signal(32)
245 pdecode
= create_pdecode()
247 m
.submodules
.pdecode2
= pdecode2
= PowerDecode2(pdecode
)
249 pspec
= CRPipeSpec(id_wid
=2)
250 m
.submodules
.alu
= alu
= CRBasePipe(pspec
)
252 comb
+= alu
.p
.data_i
.ctx
.op
.eq_from_execute1(pdecode2
.e
)
253 comb
+= alu
.n
.ready_i
.eq(1)
254 comb
+= pdecode2
.dec
.raw_opcode_in
.eq(instruction
)
259 for test
in self
.test_data
:
261 program
= test
.program
262 self
.subTest(test
.name
)
263 sim
= ISA(pdecode2
, test
.regs
, test
.sprs
, test
.cr
, test
.mem
,
265 gen
= program
.generate_instructions()
266 instructions
= list(zip(gen
, program
.assembly
.splitlines()))
268 index
= sim
.pc
.CIA
.value
//4
269 while index
< len(instructions
):
270 ins
, code
= instructions
[index
]
272 print("0x{:X}".format(ins
& 0xffffffff))
275 # ask the decoder to decode this binary data (endian'd)
276 yield pdecode2
.dec
.bigendian
.eq(0) # little / big?
277 yield instruction
.eq(ins
) # raw binary instr.
279 yield from self
.set_inputs(alu
, pdecode2
, sim
)
280 yield alu
.p
.valid_i
.eq(1)
281 fn_unit
= yield pdecode2
.e
.fn_unit
282 self
.assertEqual(fn_unit
, Function
.CR
.value
, code
)
284 opname
= code
.split(' ')[0]
285 yield from sim
.call(opname
)
286 index
= sim
.pc
.CIA
.value
//4
288 vld
= yield alu
.n
.valid_o
291 vld
= yield alu
.n
.valid_o
293 yield from self
.assert_outputs(alu
, pdecode2
, sim
, code
)
295 sim
.add_sync_process(process
)
296 with sim
.write_vcd("simulator.vcd", "simulator.gtkw",
301 if __name__
== "__main__":
302 unittest
.main(exit
=False)
303 suite
= unittest
.TestSuite()
304 suite
.addTest(TestRunner(CRTestCase
.test_data
))
306 runner
= unittest
.TextTestRunner()