2 from soc
.fu
.shift_rot
.pipe_data
import ShiftRotPipeSpec
3 from soc
.fu
.alu
.alu_input_record
import CompALUOpSubset
4 from soc
.fu
.shift_rot
.pipeline
import ShiftRotBasePipe
5 from soc
.fu
.test
.common
import TestCase
, ALUHelpers
6 from soc
.config
.endian
import bigendian
7 from soc
.decoder
.isa
.all
import ISA
8 from soc
.simulator
.program
import Program
9 from soc
.decoder
.selectable_int
import SelectableInt
10 from soc
.decoder
.power_enums
import (XER_bits
, Function
, CryIn
)
11 from soc
.decoder
.power_decoder2
import (PowerDecode2
)
12 from soc
.decoder
.power_decoder
import (create_pdecode
)
13 from soc
.decoder
.isa
.caller
import ISACaller
, special_sprs
15 from nmigen
.cli
import rtlil
16 from nmutil
.formaltest
import FHDLTestCase
17 from nmigen
import Module
, Signal
18 from nmigen
.back
.pysim
import Delay
, Settle
19 # NOTE: to use this (set to True), at present it is necessary to check
20 # out the cxxsim nmigen branch
24 from nmigen
.sim
.cxxsim
import Simulator
26 print("nope, sorry, have to use nmigen cxxsim branch for now")
28 from nmigen
.back
.pysim
import Simulator
30 from nmigen
.back
.pysim
import Simulator
33 def get_cu_inputs(dec2
, sim
):
34 """naming (res) must conform to ShiftRotFunctionUnit input regspec
38 yield from ALUHelpers
.get_sim_int_ra(res
, sim
, dec2
) # RA
39 yield from ALUHelpers
.get_sim_int_rb(res
, sim
, dec2
) # RB
40 yield from ALUHelpers
.get_sim_int_rc(res
, sim
, dec2
) # RC
41 yield from ALUHelpers
.get_rd_sim_xer_ca(res
, sim
, dec2
) # XER.ca
48 def set_alu_inputs(alu
, dec2
, sim
):
49 # TODO: see https://bugs.libre-soc.org/show_bug.cgi?id=305#c43
50 # detect the immediate here (with m.If(self.i.ctx.op.imm_data.imm_ok))
51 # and place it into data_i.b
53 inp
= yield from get_cu_inputs(dec2
, sim
)
54 yield from ALUHelpers
.set_int_ra(alu
, dec2
, inp
)
55 yield from ALUHelpers
.set_int_rb(alu
, dec2
, inp
)
56 yield from ALUHelpers
.set_int_rc(alu
, dec2
, inp
)
57 yield from ALUHelpers
.set_xer_ca(alu
, dec2
, inp
)
60 # This test bench is a bit different than is usual. Initially when I
61 # was writing it, I had all of the tests call a function to create a
62 # device under test and simulator, initialize the dut, run the
63 # simulation for ~2 cycles, and assert that the dut output what it
64 # should have. However, this was really slow, since it needed to
65 # create and tear down the dut and simulator for every test case.
67 # Now, instead of doing that, every test case in ShiftRotTestCase puts some
68 # data into the test_data list below, describing the instructions to
69 # be tested and the initial state. Once all the tests have been run,
70 # test_data gets passed to TestRunner which then sets up the DUT and
71 # simulator once, runs all the data through it, and asserts that the
72 # results match the pseudocode sim at every cycle.
74 # By doing this, I've reduced the time it takes to run the test suite
75 # massively. Before, it took around 1 minute on my computer, now it
76 # takes around 3 seconds
79 class ShiftRotTestCase(FHDLTestCase
):
82 def __init__(self
, name
):
83 super().__init
__(name
)
86 def run_tst_program(self
, prog
, initial_regs
=None, initial_sprs
=None):
87 tc
= TestCase(prog
, self
.test_name
, initial_regs
, initial_sprs
)
88 self
.test_data
.append(tc
)
91 insns
= ["slw", "sld", "srw", "srd", "sraw", "srad"]
93 choice
= random
.choice(insns
)
94 lst
= [f
"{choice} 3, 1, 2"]
95 initial_regs
= [0] * 32
96 initial_regs
[1] = random
.randint(0, (1 << 64)-1)
97 initial_regs
[2] = random
.randint(0, 63)
98 print(initial_regs
[1], initial_regs
[2])
99 self
.run_tst_program(Program(lst
, bigendian
), initial_regs
)
101 def test_shift_arith(self
):
102 lst
= ["sraw 3, 1, 2"]
103 initial_regs
= [0] * 32
104 initial_regs
[1] = random
.randint(0, (1 << 64)-1)
105 initial_regs
[2] = random
.randint(0, 63)
106 print(initial_regs
[1], initial_regs
[2])
107 self
.run_tst_program(Program(lst
, bigendian
), initial_regs
)
109 def test_shift_once(self
):
110 lst
= ["slw 3, 1, 4",
112 initial_regs
= [0] * 32
113 initial_regs
[1] = 0x80000000
114 initial_regs
[2] = 0x40
115 initial_regs
[4] = 0x00
116 self
.run_tst_program(Program(lst
, bigendian
), initial_regs
)
118 def test_rlwinm(self
):
120 mb
= random
.randint(0, 31)
121 me
= random
.randint(0, 31)
122 sh
= random
.randint(0, 31)
123 lst
= [f
"rlwinm 3, 1, {mb}, {me}, {sh}",
124 #f"rlwinm. 3, 1, {mb}, {me}, {sh}"
126 initial_regs
= [0] * 32
127 initial_regs
[1] = random
.randint(0, (1 << 64)-1)
128 self
.run_tst_program(Program(lst
, bigendian
), initial_regs
)
130 def test_rlwimi(self
):
131 lst
= ["rlwimi 3, 1, 5, 20, 6"]
132 initial_regs
= [0] * 32
133 initial_regs
[1] = 0xdeadbeef
134 initial_regs
[3] = 0x12345678
135 self
.run_tst_program(Program(lst
, bigendian
), initial_regs
)
137 def test_rlwnm(self
):
138 lst
= ["rlwnm 3, 1, 2, 20, 6"]
139 initial_regs
= [0] * 32
140 initial_regs
[1] = random
.randint(0, (1 << 64)-1)
141 initial_regs
[2] = random
.randint(0, 63)
142 self
.run_tst_program(Program(lst
, bigendian
), initial_regs
)
144 def test_rldicl(self
):
145 lst
= ["rldicl 3, 1, 5, 20"]
146 initial_regs
= [0] * 32
147 initial_regs
[1] = random
.randint(0, (1 << 64)-1)
148 self
.run_tst_program(Program(lst
, bigendian
), initial_regs
)
150 def test_rldicr(self
):
151 lst
= ["rldicr 3, 1, 5, 20"]
152 initial_regs
= [0] * 32
153 initial_regs
[1] = random
.randint(0, (1 << 64)-1)
154 self
.run_tst_program(Program(lst
, bigendian
), initial_regs
)
156 def test_regression_extswsli(self
):
157 lst
= [f
"extswsli 3, 1, 34"]
158 initial_regs
= [0] * 32
159 initial_regs
[1] = 0x5678
160 self
.run_tst_program(Program(lst
, bigendian
), initial_regs
)
162 def test_regression_extswsli_2(self
):
163 lst
= [f
"extswsli 3, 1, 7"]
164 initial_regs
= [0] * 32
165 initial_regs
[1] = 0x3ffffd7377f19fdd
166 self
.run_tst_program(Program(lst
, bigendian
), initial_regs
)
168 def test_regression_extswsli_3(self
):
169 lst
= [f
"extswsli 3, 1, 0"]
170 initial_regs
= [0] * 32
171 #initial_regs[1] = 0x80000000fb4013e2
172 #initial_regs[1] = 0xffffffffffffffff
173 #initial_regs[1] = 0x00000000ffffffff
174 initial_regs
[1] = 0x0000010180122900
175 #initial_regs[1] = 0x3ffffd73f7f19fdd
176 self
.run_tst_program(Program(lst
, bigendian
), initial_regs
)
178 def test_extswsli(self
):
180 sh
= random
.randint(0, 63)
181 lst
= [f
"extswsli 3, 1, {sh}"]
182 initial_regs
= [0] * 32
183 initial_regs
[1] = random
.randint(0, (1 << 64)-1)
184 self
.run_tst_program(Program(lst
, bigendian
), initial_regs
)
187 insns
= ["rldic", "rldicl", "rldicr"]
189 choice
= random
.choice(insns
)
190 sh
= random
.randint(0, 63)
191 m
= random
.randint(0, 63)
192 lst
= [f
"{choice} 3, 1, {sh}, {m}"]
193 initial_regs
= [0] * 32
194 initial_regs
[1] = random
.randint(0, (1 << 64)-1)
195 self
.run_tst_program(Program(lst
, bigendian
), initial_regs
)
197 def test_ilang(self
):
198 pspec
= ShiftRotPipeSpec(id_wid
=2)
199 alu
= ShiftRotBasePipe(pspec
)
200 vl
= rtlil
.convert(alu
, ports
=alu
.ports())
201 with
open("pipeline.il", "w") as f
:
205 class TestRunner(FHDLTestCase
):
206 def __init__(self
, test_data
):
207 super().__init
__("run_all")
208 self
.test_data
= test_data
213 instruction
= Signal(32)
215 pdecode
= create_pdecode()
217 m
.submodules
.pdecode2
= pdecode2
= PowerDecode2(pdecode
)
219 pspec
= ShiftRotPipeSpec(id_wid
=2)
220 m
.submodules
.alu
= alu
= ShiftRotBasePipe(pspec
)
222 comb
+= alu
.p
.data_i
.ctx
.op
.eq_from_execute1(pdecode2
.e
)
223 comb
+= alu
.p
.valid_i
.eq(1)
224 comb
+= alu
.n
.ready_i
.eq(1)
225 comb
+= pdecode2
.dec
.raw_opcode_in
.eq(instruction
)
231 for test
in self
.test_data
:
233 program
= test
.program
234 self
.subTest(test
.name
)
235 simulator
= ISA(pdecode2
, test
.regs
, test
.sprs
, test
.cr
,
238 gen
= program
.generate_instructions()
239 instructions
= list(zip(gen
, program
.assembly
.splitlines()))
241 index
= simulator
.pc
.CIA
.value
//4
242 while index
< len(instructions
):
243 ins
, code
= instructions
[index
]
245 print("0x{:X}".format(ins
& 0xffffffff))
248 # ask the decoder to decode this binary data (endian'd)
249 yield pdecode2
.dec
.bigendian
.eq(bigendian
) # little / big?
250 yield instruction
.eq(ins
) # raw binary instr.
252 fn_unit
= yield pdecode2
.e
.do
.fn_unit
253 self
.assertEqual(fn_unit
, Function
.SHIFT_ROT
.value
)
254 yield from set_alu_inputs(alu
, pdecode2
, simulator
)
256 opname
= code
.split(' ')[0]
257 yield from simulator
.call(opname
)
258 index
= simulator
.pc
.CIA
.value
//4
260 vld
= yield alu
.n
.valid_o
263 vld
= yield alu
.n
.valid_o
265 alu_out
= yield alu
.n
.data_o
.o
.data
267 yield from self
.check_alu_outputs(alu
, pdecode2
,
271 sim
.add_sync_process(process
)
276 with sim
.write_vcd("simulator.vcd", "simulator.gtkw",
280 def check_alu_outputs(self
, alu
, dec2
, sim
, code
):
282 rc
= yield dec2
.e
.do
.rc
.data
283 cridx_ok
= yield dec2
.e
.write_cr
.ok
284 cridx
= yield dec2
.e
.write_cr
.data
286 print("check extra output", repr(code
), cridx_ok
, cridx
)
288 self
.assertEqual(cridx
, 0, code
)
293 yield from ALUHelpers
.get_cr_a(res
, alu
, dec2
)
294 yield from ALUHelpers
.get_xer_ca(res
, alu
, dec2
)
295 yield from ALUHelpers
.get_int_o(res
, alu
, dec2
)
297 yield from ALUHelpers
.get_sim_int_o(sim_o
, sim
, dec2
)
298 yield from ALUHelpers
.get_wr_sim_cr_a(sim_o
, sim
, dec2
)
299 yield from ALUHelpers
.get_wr_sim_xer_ca(sim_o
, sim
, dec2
)
301 ALUHelpers
.check_cr_a(self
, res
, sim_o
, "CR%d %s" % (cridx
, code
))
302 ALUHelpers
.check_xer_ca(self
, res
, sim_o
, code
)
303 ALUHelpers
.check_int_o(self
, res
, sim_o
, code
)
306 if __name__
== "__main__":
307 unittest
.main(exit
=False)
308 suite
= unittest
.TestSuite()
309 suite
.addTest(TestRunner(ShiftRotTestCase
.test_data
))
311 runner
= unittest
.TextTestRunner()