31da549669def3ebf89257607d095b3c2ff28161
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
29 def get_rec_width(rec
):
31 # Setup random inputs for dut.op
38 # This test bench is a bit different than is usual. Initially when I
39 # was writing it, I had all of the tests call a function to create a
40 # device under test and simulator, initialize the dut, run the
41 # simulation for ~2 cycles, and assert that the dut output what it
42 # should have. However, this was really slow, since it needed to
43 # create and tear down the dut and simulator for every test case.
45 # Now, instead of doing that, every test case in ALUTestCase puts some
46 # data into the test_data list below, describing the instructions to
47 # be tested and the initial state. Once all the tests have been run,
48 # test_data gets passed to TestRunner which then sets up the DUT and
49 # simulator once, runs all the data through it, and asserts that the
50 # results match the pseudocode sim at every cycle.
52 # By doing this, I've reduced the time it takes to run the test suite
53 # massively. Before, it took around 1 minute on my computer, now it
54 # takes around 3 seconds
59 class CRTestCase(FHDLTestCase
):
60 def __init__(self
, name
):
61 super().__init
__(name
)
63 def run_tst_program(self
, prog
, initial_regs
=[0] * 32, initial_sprs
={},
65 tc
= TestCase(prog
, initial_regs
, initial_sprs
, initial_cr
,
70 insns
= ["crand", "cror", "crnand", "crnor", "crxor", "creqv",
73 choice
= random
.choice(insns
)
74 ba
= random
.randint(0, 31)
75 bb
= random
.randint(0, 31)
76 bt
= random
.randint(0, 31)
77 lst
= [f
"{choice} {ba}, {bb}, {bt}"]
78 cr
= random
.randint(0, 7)
79 self
.run_tst_program(Program(lst
), initial_cr
=cr
)
84 self
.run_tst_program(Program(lst
), initial_cr
=cr
)
88 mask
= random
.randint(0, 255)
89 lst
= [f
"mtcrf {mask}, 2"]
90 cr
= random
.randint(0, (1<<32)-1)
91 initial_regs
= [0] * 32
92 initial_regs
[2] = random
.randint(0, (1<<32)-1)
93 self
.run_tst_program(Program(lst
), 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
), initial_regs
=initial_regs
,
108 cr
= random
.randint(0, (1<<32)-1)
109 self
.run_tst_program(Program(lst
), 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
), initial_cr
=cr
)
119 def test_ilang(self
):
120 rec
= CRPipeSpec
.opsubsetkls()
122 pspec
= CRPipeSpec(id_wid
=2, op_wid
=get_rec_width(rec
))
123 alu
= CRBasePipe(pspec
)
124 vl
= rtlil
.convert(alu
, ports
=alu
.ports())
125 with
open("cr_pipeline.il", "w") as f
:
129 class TestRunner(FHDLTestCase
):
130 def __init__(self
, test_data
):
131 super().__init
__("run_all")
132 self
.test_data
= test_data
134 def set_inputs(self
, alu
, dec2
, simulator
):
135 yield alu
.p
.data_i
.cr
.eq(simulator
.cr
.get_range().value
)
137 reg3_ok
= yield dec2
.e
.read_reg3
.ok
139 reg3_sel
= yield dec2
.e
.read_reg3
.data
140 reg3
= simulator
.gpr(reg3_sel
).value
141 yield alu
.p
.data_i
.a
.eq(reg3
)
146 instruction
= Signal(32)
148 pdecode
= create_pdecode()
150 m
.submodules
.pdecode2
= pdecode2
= PowerDecode2(pdecode
)
152 rec
= CRPipeSpec
.opsubsetkls()
154 pspec
= CRPipeSpec(id_wid
=2, op_wid
=get_rec_width(rec
))
155 m
.submodules
.alu
= alu
= CRBasePipe(pspec
)
157 comb
+= alu
.p
.data_i
.ctx
.op
.eq_from_execute1(pdecode2
.e
)
158 comb
+= alu
.p
.valid_i
.eq(1)
159 comb
+= alu
.n
.ready_i
.eq(1)
160 comb
+= pdecode2
.dec
.raw_opcode_in
.eq(instruction
)
165 for test
in self
.test_data
:
167 program
= test
.program
168 self
.subTest(test
.name
)
169 simulator
= ISA(pdecode2
, test
.regs
, test
.sprs
, test
.cr
)
170 gen
= program
.generate_instructions()
171 instructions
= list(zip(gen
, program
.assembly
.splitlines()))
173 index
= simulator
.pc
.CIA
.value
//4
174 while index
< len(instructions
):
175 ins
, code
= instructions
[index
]
177 print("0x{:X}".format(ins
& 0xffffffff))
180 # ask the decoder to decode this binary data (endian'd)
181 yield pdecode2
.dec
.bigendian
.eq(0) # little / big?
182 yield instruction
.eq(ins
) # raw binary instr.
184 yield from self
.set_inputs(alu
, pdecode2
, simulator
)
185 fn_unit
= yield pdecode2
.e
.fn_unit
186 self
.assertEqual(fn_unit
, Function
.CR
.value
, code
)
188 opname
= code
.split(' ')[0]
189 yield from simulator
.call(opname
)
190 index
= simulator
.pc
.CIA
.value
//4
192 vld
= yield alu
.n
.valid_o
195 vld
= yield alu
.n
.valid_o
197 cr_out
= yield pdecode2
.e
.output_cr
199 cr_expected
= simulator
.cr
.get_range().value
200 cr_real
= yield alu
.n
.data_o
.cr
201 msg
= f
"real: {cr_expected:x}, actual: {cr_real:x}"
202 msg
+= " code: %s" % code
203 self
.assertEqual(cr_expected
, cr_real
, msg
)
205 reg_out
= yield pdecode2
.e
.write_reg
.ok
207 reg_sel
= yield pdecode2
.e
.write_reg
.data
208 reg_data
= simulator
.gpr(reg_sel
).value
209 output
= yield alu
.n
.data_o
.o
210 msg
= f
"real: {reg_data:x}, actual: {output:x}"
211 self
.assertEqual(reg_data
, output
)
213 sim
.add_sync_process(process
)
214 with sim
.write_vcd("simulator.vcd", "simulator.gtkw",
217 def check_extra_alu_outputs(self
, alu
, dec2
, sim
):
218 rc
= yield dec2
.e
.rc
.data
220 cr_expected
= sim
.crl
[0].get_range().value
221 cr_actual
= yield alu
.n
.data_o
.cr0
222 self
.assertEqual(cr_expected
, cr_actual
)
225 if __name__
== "__main__":
226 unittest
.main(exit
=False)
227 suite
= unittest
.TestSuite()
228 suite
.addTest(TestRunner(test_data
))
230 runner
= unittest
.TextTestRunner()