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
.alu
.alu_input_record
import CompALUOpSubset
17 from soc
.fu
.cr
.pipe_data
import CRPipeSpec
22 def __init__(self
, program
, regs
, sprs
, cr
, name
):
23 self
.program
= program
30 # This test bench is a bit different than is usual. Initially when I
31 # was writing it, I had all of the tests call a function to create a
32 # device under test and simulator, initialize the dut, run the
33 # simulation for ~2 cycles, and assert that the dut output what it
34 # should have. However, this was really slow, since it needed to
35 # create and tear down the dut and simulator for every test case.
37 # Now, instead of doing that, every test case in ALUTestCase puts some
38 # data into the test_data list below, describing the instructions to
39 # be tested and the initial state. Once all the tests have been run,
40 # test_data gets passed to TestRunner which then sets up the DUT and
41 # simulator once, runs all the data through it, and asserts that the
42 # results match the pseudocode sim at every cycle.
44 # By doing this, I've reduced the time it takes to run the test suite
45 # massively. Before, it took around 1 minute on my computer, now it
46 # takes around 3 seconds
51 class CRTestCase(FHDLTestCase
):
52 def __init__(self
, name
):
53 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
)
117 def test_ilang(self
):
118 pspec
= CRPipeSpec(id_wid
=2)
119 alu
= CRBasePipe(pspec
)
120 vl
= rtlil
.convert(alu
, ports
=alu
.ports())
121 with
open("cr_pipeline.il", "w") as f
:
125 class TestRunner(FHDLTestCase
):
126 def __init__(self
, test_data
):
127 super().__init
__("run_all")
128 self
.test_data
= test_data
130 def set_inputs(self
, alu
, dec2
, simulator
):
131 full_reg
= yield dec2
.e
.read_cr_whole
133 print(simulator
.cr
.get_range().value
)
135 yield alu
.p
.data_i
.full_cr
.eq(simulator
.cr
.get_range().value
)
137 cr1_en
= yield dec2
.e
.read_cr1
.ok
139 cr1_sel
= yield dec2
.e
.read_cr1
.data
140 cr1
= simulator
.crl
[cr1_sel
].get_range().value
141 yield alu
.p
.data_i
.cr_a
.eq(cr1
)
142 cr2_en
= yield dec2
.e
.read_cr2
.ok
144 cr2_sel
= yield dec2
.e
.read_cr2
.data
145 cr2
= simulator
.crl
[cr2_sel
].get_range().value
146 yield alu
.p
.data_i
.cr_b
.eq(cr2
)
147 cr3_en
= yield dec2
.e
.read_cr3
.ok
149 cr3_sel
= yield dec2
.e
.read_cr3
.data
150 cr3
= simulator
.crl
[cr3_sel
].get_range().value
151 yield alu
.p
.data_i
.cr_c
.eq(cr3
)
153 reg3_ok
= yield dec2
.e
.read_reg3
.ok
155 reg3_sel
= yield dec2
.e
.read_reg3
.data
156 reg3
= simulator
.gpr(reg3_sel
).value
157 yield alu
.p
.data_i
.a
.eq(reg3
)
159 def assert_outputs(self
, alu
, dec2
, simulator
):
160 whole_reg
= yield dec2
.e
.write_cr_whole
161 cr_en
= yield dec2
.e
.write_cr
.ok
163 full_cr
= yield alu
.n
.data_o
.full_cr
.data
164 expected_cr
= simulator
.cr
.get_range().value
165 self
.assertEqual(expected_cr
, full_cr
)
167 cr_sel
= yield dec2
.e
.write_cr
.data
168 expected_cr
= simulator
.crl
[cr_sel
].get_range().value
169 real_cr
= yield alu
.n
.data_o
.cr_o
.data
170 self
.assertEqual(expected_cr
, real_cr
)
176 instruction
= Signal(32)
178 pdecode
= create_pdecode()
180 m
.submodules
.pdecode2
= pdecode2
= PowerDecode2(pdecode
)
182 pspec
= CRPipeSpec(id_wid
=2)
183 m
.submodules
.alu
= alu
= CRBasePipe(pspec
)
185 comb
+= alu
.p
.data_i
.ctx
.op
.eq_from_execute1(pdecode2
.e
)
186 comb
+= alu
.n
.ready_i
.eq(1)
187 comb
+= pdecode2
.dec
.raw_opcode_in
.eq(instruction
)
192 for test
in self
.test_data
:
194 program
= test
.program
195 self
.subTest(test
.name
)
196 simulator
= ISA(pdecode2
, test
.regs
, test
.sprs
, test
.cr
)
197 gen
= program
.generate_instructions()
198 instructions
= list(zip(gen
, program
.assembly
.splitlines()))
200 index
= simulator
.pc
.CIA
.value
//4
201 while index
< len(instructions
):
202 ins
, code
= instructions
[index
]
204 print("0x{:X}".format(ins
& 0xffffffff))
207 # ask the decoder to decode this binary data (endian'd)
208 yield pdecode2
.dec
.bigendian
.eq(0) # little / big?
209 yield instruction
.eq(ins
) # raw binary instr.
211 yield from self
.set_inputs(alu
, pdecode2
, simulator
)
212 yield alu
.p
.valid_i
.eq(1)
213 fn_unit
= yield pdecode2
.e
.fn_unit
214 self
.assertEqual(fn_unit
, Function
.CR
.value
, code
)
216 opname
= code
.split(' ')[0]
217 yield from simulator
.call(opname
)
218 index
= simulator
.pc
.CIA
.value
//4
220 vld
= yield alu
.n
.valid_o
223 vld
= yield alu
.n
.valid_o
225 yield from self
.assert_outputs(alu
, pdecode2
, simulator
)
227 sim
.add_sync_process(process
)
228 with sim
.write_vcd("simulator.vcd", "simulator.gtkw",
231 def check_extra_alu_outputs(self
, alu
, dec2
, sim
):
232 rc
= yield dec2
.e
.rc
.data
234 cr_expected
= sim
.crl
[0].get_range().value
235 cr_actual
= yield alu
.n
.data_o
.cr0
236 self
.assertEqual(cr_expected
, cr_actual
)
239 if __name__
== "__main__":
240 unittest
.main(exit
=False)
241 suite
= unittest
.TestSuite()
242 suite
.addTest(TestRunner(test_data
))
244 runner
= unittest
.TextTestRunner()