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 TestAccumulatorBase
, 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 nmigen
import Module
, Signal
17 from nmigen
.back
.pysim
import Delay
, Settle
18 # NOTE: to use this (set to True), at present it is necessary to check
19 # out the cxxsim nmigen branch
23 from nmigen
.sim
.cxxsim
import Simulator
25 print("nope, sorry, have to use nmigen cxxsim branch for now")
27 from nmigen
.back
.pysim
import Simulator
29 from nmigen
.back
.pysim
import Simulator
32 def get_cu_inputs(dec2
, sim
):
33 """naming (res) must conform to ShiftRotFunctionUnit input regspec
37 yield from ALUHelpers
.get_sim_int_ra(res
, sim
, dec2
) # RA
38 yield from ALUHelpers
.get_sim_int_rb(res
, sim
, dec2
) # RB
39 yield from ALUHelpers
.get_sim_int_rc(res
, sim
, dec2
) # RC
40 yield from ALUHelpers
.get_rd_sim_xer_ca(res
, sim
, dec2
) # XER.ca
41 yield from ALUHelpers
.get_sim_xer_so(res
, sim
, dec2
) # XER.so
43 print("alu get_cu_inputs", res
)
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
)
58 yield from ALUHelpers
.set_xer_so(alu
, dec2
, inp
)
61 # This test bench is a bit different than is usual. Initially when I
62 # was writing it, I had all of the tests call a function to create a
63 # device under test and simulator, initialize the dut, run the
64 # simulation for ~2 cycles, and assert that the dut output what it
65 # should have. However, this was really slow, since it needed to
66 # create and tear down the dut and simulator for every test case.
68 # Now, instead of doing that, every test case in ShiftRotTestCase puts some
69 # data into the test_data list below, describing the instructions to
70 # be tested and the initial state. Once all the tests have been run,
71 # test_data gets passed to TestRunner which then sets up the DUT and
72 # simulator once, runs all the data through it, and asserts that the
73 # results match the pseudocode sim at every cycle.
75 # By doing this, I've reduced the time it takes to run the test suite
76 # massively. Before, it took around 1 minute on my computer, now it
77 # takes around 3 seconds
80 class ShiftRotTestCase(TestAccumulatorBase
):
82 def case_0_proof_regression_rlwnm(self
):
83 lst
= ["rlwnm 3, 1, 2, 16, 20"]
84 initial_regs
= [0] * 32
85 initial_regs
[1] = 0x7ffdbffb91b906b9
87 print(initial_regs
[1], initial_regs
[2])
88 self
.add_case(Program(lst
, bigendian
), initial_regs
)
90 def case_regression_rldicr_0(self
):
91 lst
= ["rldicr. 29, 19, 1, 21"]
92 initial_regs
= [0] * 32
93 initial_regs
[1] = 0x3f
94 initial_regs
[19] = 0x00000000ffff8000
96 initial_sprs
= {'XER': 0xe00c0000}
98 self
.add_case(Program(lst
, bigendian
), initial_regs
,
99 initial_sprs
=initial_sprs
)
101 def case_regression_rldicr_1(self
):
102 lst
= ["rldicr. 29, 19, 1, 21"]
103 initial_regs
= [0] * 32
104 initial_regs
[1] = 0x3f
105 initial_regs
[19] = 0x00000000ffff8000
107 self
.add_case(Program(lst
, bigendian
), initial_regs
)
109 def case_shift(self
):
110 insns
= ["slw", "sld", "srw", "srd", "sraw", "srad"]
112 choice
= random
.choice(insns
)
113 lst
= [f
"{choice} 3, 1, 2"]
114 initial_regs
= [0] * 32
115 initial_regs
[1] = random
.randint(0, (1 << 64)-1)
116 initial_regs
[2] = random
.randint(0, 63)
117 print(initial_regs
[1], initial_regs
[2])
118 self
.add_case(Program(lst
, bigendian
), initial_regs
)
120 def case_shift_arith(self
):
121 lst
= ["sraw 3, 1, 2"]
122 initial_regs
= [0] * 32
123 initial_regs
[1] = random
.randint(0, (1 << 64)-1)
124 initial_regs
[2] = random
.randint(0, 63)
125 print(initial_regs
[1], initial_regs
[2])
126 self
.add_case(Program(lst
, bigendian
), initial_regs
)
128 def case_shift_once(self
):
129 lst
= ["slw 3, 1, 4",
131 initial_regs
= [0] * 32
132 initial_regs
[1] = 0x80000000
133 initial_regs
[2] = 0x40
134 initial_regs
[4] = 0x00
135 self
.add_case(Program(lst
, bigendian
), initial_regs
)
137 def case_rlwinm(self
):
139 mb
= random
.randint(0, 31)
140 me
= random
.randint(0, 31)
141 sh
= random
.randint(0, 31)
142 lst
= [f
"rlwinm 3, 1, {mb}, {me}, {sh}",
143 #f"rlwinm. 3, 1, {mb}, {me}, {sh}"
145 initial_regs
= [0] * 32
146 initial_regs
[1] = random
.randint(0, (1 << 64)-1)
147 self
.add_case(Program(lst
, bigendian
), initial_regs
)
149 def case_rlwimi(self
):
150 lst
= ["rlwimi 3, 1, 5, 20, 6"]
151 initial_regs
= [0] * 32
152 initial_regs
[1] = 0xdeadbeef
153 initial_regs
[3] = 0x12345678
154 self
.add_case(Program(lst
, bigendian
), initial_regs
)
156 def case_rlwnm(self
):
157 lst
= ["rlwnm 3, 1, 2, 20, 6"]
158 initial_regs
= [0] * 32
159 initial_regs
[1] = random
.randint(0, (1 << 64)-1)
160 initial_regs
[2] = random
.randint(0, 63)
161 self
.add_case(Program(lst
, bigendian
), initial_regs
)
163 def case_rldicl(self
):
164 lst
= ["rldicl 3, 1, 5, 20"]
165 initial_regs
= [0] * 32
166 initial_regs
[1] = random
.randint(0, (1 << 64)-1)
167 self
.add_case(Program(lst
, bigendian
), initial_regs
)
169 def case_rldicr(self
):
170 lst
= ["rldicr 3, 1, 5, 20"]
171 initial_regs
= [0] * 32
172 initial_regs
[1] = random
.randint(0, (1 << 64)-1)
173 self
.add_case(Program(lst
, bigendian
), initial_regs
)
175 def case_regression_extswsli(self
):
176 lst
= [f
"extswsli 3, 1, 34"]
177 initial_regs
= [0] * 32
178 initial_regs
[1] = 0x5678
179 self
.add_case(Program(lst
, bigendian
), initial_regs
)
181 def case_regression_extswsli_2(self
):
182 lst
= [f
"extswsli 3, 1, 7"]
183 initial_regs
= [0] * 32
184 initial_regs
[1] = 0x3ffffd7377f19fdd
185 self
.add_case(Program(lst
, bigendian
), initial_regs
)
187 def case_regression_extswsli_3(self
):
188 lst
= [f
"extswsli 3, 1, 0"]
189 initial_regs
= [0] * 32
190 #initial_regs[1] = 0x80000000fb4013e2
191 #initial_regs[1] = 0xffffffffffffffff
192 #initial_regs[1] = 0x00000000ffffffff
193 initial_regs
[1] = 0x0000010180122900
194 #initial_regs[1] = 0x3ffffd73f7f19fdd
195 self
.add_case(Program(lst
, bigendian
), initial_regs
)
197 def case_extswsli(self
):
199 sh
= random
.randint(0, 63)
200 lst
= [f
"extswsli 3, 1, {sh}"]
201 initial_regs
= [0] * 32
202 initial_regs
[1] = random
.randint(0, (1 << 64)-1)
203 self
.add_case(Program(lst
, bigendian
), initial_regs
)
206 insns
= ["rldic", "rldicl", "rldicr"]
208 choice
= random
.choice(insns
)
209 sh
= random
.randint(0, 63)
210 m
= random
.randint(0, 63)
211 lst
= [f
"{choice} 3, 1, {sh}, {m}"]
212 initial_regs
= [0] * 32
213 initial_regs
[1] = random
.randint(0, (1 << 64)-1)
214 self
.add_case(Program(lst
, bigendian
), initial_regs
)
216 def case_ilang(self
):
217 pspec
= ShiftRotPipeSpec(id_wid
=2)
218 alu
= ShiftRotBasePipe(pspec
)
219 vl
= rtlil
.convert(alu
, ports
=alu
.ports())
220 with
open("pipeline.il", "w") as f
:
224 class TestRunner(unittest
.TestCase
):
225 def __init__(self
, test_data
):
226 super().__init
__("run_all")
227 self
.test_data
= test_data
229 def execute(self
, alu
, instruction
, pdecode2
, test
):
230 program
= test
.program
231 simulator
= ISA(pdecode2
, test
.regs
, test
.sprs
, test
.cr
,
234 gen
= program
.generate_instructions()
235 instructions
= list(zip(gen
, program
.assembly
.splitlines()))
237 index
= simulator
.pc
.CIA
.value
//4
238 while index
< len(instructions
):
239 ins
, code
= instructions
[index
]
241 print("0x{:X}".format(ins
& 0xffffffff))
244 # ask the decoder to decode this binary data (endian'd)
245 yield pdecode2
.dec
.bigendian
.eq(bigendian
) # little / big?
246 yield instruction
.eq(ins
) # raw binary instr.
248 fn_unit
= yield pdecode2
.e
.do
.fn_unit
249 self
.assertEqual(fn_unit
, Function
.SHIFT_ROT
.value
)
250 yield from set_alu_inputs(alu
, pdecode2
, simulator
)
252 # set valid for one cycle, propagate through pipeline...
253 yield alu
.p
.valid_i
.eq(1)
255 yield alu
.p
.valid_i
.eq(0)
257 opname
= code
.split(' ')[0]
258 yield from simulator
.call(opname
)
259 index
= simulator
.pc
.CIA
.value
//4
261 vld
= yield alu
.n
.valid_o
264 vld
= yield alu
.n
.valid_o
266 alu_out
= yield alu
.n
.data_o
.o
.data
268 yield from self
.check_alu_outputs(alu
, pdecode2
,
275 instruction
= Signal(32)
277 pdecode
= create_pdecode()
279 m
.submodules
.pdecode2
= pdecode2
= PowerDecode2(pdecode
)
281 pspec
= ShiftRotPipeSpec(id_wid
=2)
282 m
.submodules
.alu
= alu
= ShiftRotBasePipe(pspec
)
284 comb
+= alu
.p
.data_i
.ctx
.op
.eq_from_execute1(pdecode2
.e
)
285 comb
+= alu
.n
.ready_i
.eq(1)
286 comb
+= pdecode2
.dec
.raw_opcode_in
.eq(instruction
)
292 for test
in self
.test_data
:
294 program
= test
.program
295 with self
.subTest(test
.name
):
296 yield from self
.execute(alu
, instruction
, pdecode2
, test
)
298 sim
.add_sync_process(process
)
303 with sim
.write_vcd("shift_rot_simulator.vcd"):
306 def check_alu_outputs(self
, alu
, dec2
, sim
, code
):
308 rc
= yield dec2
.e
.do
.rc
.data
309 cridx_ok
= yield dec2
.e
.write_cr
.ok
310 cridx
= yield dec2
.e
.write_cr
.data
312 print("check extra output", repr(code
), cridx_ok
, cridx
)
314 self
.assertEqual(cridx
, 0, code
)
319 yield from ALUHelpers
.get_cr_a(res
, alu
, dec2
)
320 yield from ALUHelpers
.get_xer_ca(res
, alu
, dec2
)
321 yield from ALUHelpers
.get_xer_ov(res
, alu
, dec2
)
322 yield from ALUHelpers
.get_xer_so(res
, alu
, dec2
)
323 yield from ALUHelpers
.get_int_o(res
, alu
, dec2
)
325 print ("hw outputs", res
)
327 yield from ALUHelpers
.get_sim_int_o(sim_o
, sim
, dec2
)
328 yield from ALUHelpers
.get_wr_sim_cr_a(sim_o
, sim
, dec2
)
329 yield from ALUHelpers
.get_wr_sim_xer_ca(sim_o
, sim
, dec2
)
330 yield from ALUHelpers
.get_sim_xer_ov(sim_o
, sim
, dec2
)
331 yield from ALUHelpers
.get_sim_xer_so(sim_o
, sim
, dec2
)
333 print ("sim outputs", sim_o
)
335 ALUHelpers
.check_cr_a(self
, res
, sim_o
, "CR%d %s" % (cridx
, code
))
336 ALUHelpers
.check_xer_ca(self
, res
, sim_o
, code
)
337 ALUHelpers
.check_xer_so(self
, res
, sim_o
, code
)
338 ALUHelpers
.check_xer_ov(self
, res
, sim_o
, code
)
339 ALUHelpers
.check_int_o(self
, res
, sim_o
, code
)
342 if __name__
== "__main__":
343 unittest
.main(exit
=False)
344 suite
= unittest
.TestSuite()
345 suite
.addTest(TestRunner(ShiftRotTestCase().test_data
))
347 runner
= unittest
.TextTestRunner()