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_sld_rb_too_big(self
):
129 lst
= ["sld 3, 1, 4",
131 initial_regs
= [0] * 32
132 initial_regs
[1] = 0xffffffffffffffff
133 initial_regs
[4] = 64 # too big, output should be zero
134 self
.add_case(Program(lst
, bigendian
), initial_regs
)
136 def case_shift_once(self
):
137 lst
= ["slw 3, 1, 4",
139 initial_regs
= [0] * 32
140 initial_regs
[1] = 0x80000000
141 initial_regs
[2] = 0x40
142 initial_regs
[4] = 0x00
143 self
.add_case(Program(lst
, bigendian
), initial_regs
)
145 def case_rlwinm(self
):
147 mb
= random
.randint(0, 31)
148 me
= random
.randint(0, 31)
149 sh
= random
.randint(0, 31)
150 lst
= [f
"rlwinm 3, 1, {mb}, {me}, {sh}",
151 #f"rlwinm. 3, 1, {mb}, {me}, {sh}"
153 initial_regs
= [0] * 32
154 initial_regs
[1] = random
.randint(0, (1 << 64)-1)
155 self
.add_case(Program(lst
, bigendian
), initial_regs
)
157 def case_rlwimi(self
):
158 lst
= ["rlwimi 3, 1, 5, 20, 6"]
159 initial_regs
= [0] * 32
160 initial_regs
[1] = 0xdeadbeef
161 initial_regs
[3] = 0x12345678
162 self
.add_case(Program(lst
, bigendian
), initial_regs
)
164 def case_rlwnm(self
):
165 lst
= ["rlwnm 3, 1, 2, 20, 6"]
166 initial_regs
= [0] * 32
167 initial_regs
[1] = random
.randint(0, (1 << 64)-1)
168 initial_regs
[2] = random
.randint(0, 63)
169 self
.add_case(Program(lst
, bigendian
), initial_regs
)
171 def case_rldicl(self
):
172 lst
= ["rldicl 3, 1, 5, 20"]
173 initial_regs
= [0] * 32
174 initial_regs
[1] = random
.randint(0, (1 << 64)-1)
175 self
.add_case(Program(lst
, bigendian
), initial_regs
)
177 def case_rldicr(self
):
178 lst
= ["rldicr 3, 1, 5, 20"]
179 initial_regs
= [0] * 32
180 initial_regs
[1] = random
.randint(0, (1 << 64)-1)
181 self
.add_case(Program(lst
, bigendian
), initial_regs
)
183 def case_regression_extswsli(self
):
184 lst
= [f
"extswsli 3, 1, 34"]
185 initial_regs
= [0] * 32
186 initial_regs
[1] = 0x5678
187 self
.add_case(Program(lst
, bigendian
), initial_regs
)
189 def case_regression_extswsli_2(self
):
190 lst
= [f
"extswsli 3, 1, 7"]
191 initial_regs
= [0] * 32
192 initial_regs
[1] = 0x3ffffd7377f19fdd
193 self
.add_case(Program(lst
, bigendian
), initial_regs
)
195 def case_regression_extswsli_3(self
):
196 lst
= [f
"extswsli 3, 1, 0"]
197 initial_regs
= [0] * 32
198 #initial_regs[1] = 0x80000000fb4013e2
199 #initial_regs[1] = 0xffffffffffffffff
200 #initial_regs[1] = 0x00000000ffffffff
201 initial_regs
[1] = 0x0000010180122900
202 #initial_regs[1] = 0x3ffffd73f7f19fdd
203 self
.add_case(Program(lst
, bigendian
), initial_regs
)
205 def case_extswsli(self
):
207 sh
= random
.randint(0, 63)
208 lst
= [f
"extswsli 3, 1, {sh}"]
209 initial_regs
= [0] * 32
210 initial_regs
[1] = random
.randint(0, (1 << 64)-1)
211 self
.add_case(Program(lst
, bigendian
), initial_regs
)
214 insns
= ["rldic", "rldicl", "rldicr"]
216 choice
= random
.choice(insns
)
217 sh
= random
.randint(0, 63)
218 m
= random
.randint(0, 63)
219 lst
= [f
"{choice} 3, 1, {sh}, {m}"]
220 initial_regs
= [0] * 32
221 initial_regs
[1] = random
.randint(0, (1 << 64)-1)
222 self
.add_case(Program(lst
, bigendian
), initial_regs
)
224 def case_ilang(self
):
225 pspec
= ShiftRotPipeSpec(id_wid
=2)
226 alu
= ShiftRotBasePipe(pspec
)
227 vl
= rtlil
.convert(alu
, ports
=alu
.ports())
228 with
open("shift_rot_pipeline.il", "w") as f
:
232 class TestRunner(unittest
.TestCase
):
233 def __init__(self
, test_data
):
234 super().__init
__("run_all")
235 self
.test_data
= test_data
237 def execute(self
, alu
, instruction
, pdecode2
, test
):
238 program
= test
.program
239 simulator
= ISA(pdecode2
, test
.regs
, test
.sprs
, test
.cr
,
242 gen
= program
.generate_instructions()
243 instructions
= list(zip(gen
, program
.assembly
.splitlines()))
245 index
= simulator
.pc
.CIA
.value
//4
246 while index
< len(instructions
):
247 ins
, code
= instructions
[index
]
249 print("0x{:X}".format(ins
& 0xffffffff))
252 # ask the decoder to decode this binary data (endian'd)
253 yield pdecode2
.dec
.bigendian
.eq(bigendian
) # little / big?
254 yield instruction
.eq(ins
) # raw binary instr.
256 fn_unit
= yield pdecode2
.e
.do
.fn_unit
257 self
.assertEqual(fn_unit
, Function
.SHIFT_ROT
.value
)
258 yield from set_alu_inputs(alu
, pdecode2
, simulator
)
260 # set valid for one cycle, propagate through pipeline...
261 yield alu
.p
.valid_i
.eq(1)
263 yield alu
.p
.valid_i
.eq(0)
265 opname
= code
.split(' ')[0]
266 yield from simulator
.call(opname
)
267 index
= simulator
.pc
.CIA
.value
//4
269 vld
= yield alu
.n
.valid_o
272 vld
= yield alu
.n
.valid_o
274 alu_out
= yield alu
.n
.data_o
.o
.data
276 yield from self
.check_alu_outputs(alu
, pdecode2
,
283 instruction
= Signal(32)
285 pdecode
= create_pdecode()
287 m
.submodules
.pdecode2
= pdecode2
= PowerDecode2(pdecode
)
289 pspec
= ShiftRotPipeSpec(id_wid
=2)
290 m
.submodules
.alu
= alu
= ShiftRotBasePipe(pspec
)
292 comb
+= alu
.p
.data_i
.ctx
.op
.eq_from_execute1(pdecode2
.e
)
293 comb
+= alu
.n
.ready_i
.eq(1)
294 comb
+= pdecode2
.dec
.raw_opcode_in
.eq(instruction
)
300 for test
in self
.test_data
:
302 program
= test
.program
303 with self
.subTest(test
.name
):
304 yield from self
.execute(alu
, instruction
, pdecode2
, test
)
306 sim
.add_sync_process(process
)
311 with sim
.write_vcd("shift_rot_simulator.vcd"):
314 def check_alu_outputs(self
, alu
, dec2
, sim
, code
):
316 rc
= yield dec2
.e
.do
.rc
.data
317 cridx_ok
= yield dec2
.e
.write_cr
.ok
318 cridx
= yield dec2
.e
.write_cr
.data
320 print("check extra output", repr(code
), cridx_ok
, cridx
)
322 self
.assertEqual(cridx
, 0, code
)
327 yield from ALUHelpers
.get_cr_a(res
, alu
, dec2
)
328 yield from ALUHelpers
.get_xer_ca(res
, alu
, dec2
)
329 yield from ALUHelpers
.get_int_o(res
, alu
, dec2
)
331 print ("hw outputs", res
)
333 yield from ALUHelpers
.get_sim_int_o(sim_o
, sim
, dec2
)
334 yield from ALUHelpers
.get_wr_sim_cr_a(sim_o
, sim
, dec2
)
335 yield from ALUHelpers
.get_wr_sim_xer_ca(sim_o
, sim
, dec2
)
337 print ("sim outputs", sim_o
)
339 ALUHelpers
.check_cr_a(self
, res
, sim_o
, "CR%d %s" % (cridx
, code
))
340 ALUHelpers
.check_xer_ca(self
, res
, sim_o
, code
)
341 ALUHelpers
.check_int_o(self
, res
, sim_o
, code
)
344 if __name__
== "__main__":
345 unittest
.main(exit
=False)
346 suite
= unittest
.TestSuite()
347 suite
.addTest(TestRunner(ShiftRotTestCase().test_data
))
349 runner
= unittest
.TextTestRunner()