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
47 def set_alu_inputs(alu
, dec2
, sim
):
48 # TODO: see https://bugs.libre-soc.org/show_bug.cgi?id=305#c43
49 # detect the immediate here (with m.If(self.i.ctx.op.imm_data.imm_ok))
50 # and place it into data_i.b
52 inp
= yield from get_cu_inputs(dec2
, sim
)
53 yield from ALUHelpers
.set_int_ra(alu
, dec2
, inp
)
54 yield from ALUHelpers
.set_int_rb(alu
, dec2
, inp
)
55 yield from ALUHelpers
.set_int_rc(alu
, dec2
, inp
)
56 yield from ALUHelpers
.set_xer_ca(alu
, dec2
, inp
)
59 # This test bench is a bit different than is usual. Initially when I
60 # was writing it, I had all of the tests call a function to create a
61 # device under test and simulator, initialize the dut, run the
62 # simulation for ~2 cycles, and assert that the dut output what it
63 # should have. However, this was really slow, since it needed to
64 # create and tear down the dut and simulator for every test case.
66 # Now, instead of doing that, every test case in ShiftRotTestCase puts some
67 # data into the test_data list below, describing the instructions to
68 # be tested and the initial state. Once all the tests have been run,
69 # test_data gets passed to TestRunner which then sets up the DUT and
70 # simulator once, runs all the data through it, and asserts that the
71 # results match the pseudocode sim at every cycle.
73 # By doing this, I've reduced the time it takes to run the test suite
74 # massively. Before, it took around 1 minute on my computer, now it
75 # takes around 3 seconds
78 class ShiftRotTestCase(TestAccumulatorBase
):
81 insns
= ["slw", "sld", "srw", "srd", "sraw", "srad"]
83 choice
= random
.choice(insns
)
84 lst
= [f
"{choice} 3, 1, 2"]
85 initial_regs
= [0] * 32
86 initial_regs
[1] = random
.randint(0, (1 << 64)-1)
87 initial_regs
[2] = random
.randint(0, 63)
88 print(initial_regs
[1], initial_regs
[2])
89 self
.add_case(Program(lst
, bigendian
), initial_regs
)
91 def case_shift_arith(self
):
92 lst
= ["sraw 3, 1, 2"]
93 initial_regs
= [0] * 32
94 initial_regs
[1] = random
.randint(0, (1 << 64)-1)
95 initial_regs
[2] = random
.randint(0, 63)
96 print(initial_regs
[1], initial_regs
[2])
97 self
.add_case(Program(lst
, bigendian
), initial_regs
)
99 def case_shift_once(self
):
100 lst
= ["slw 3, 1, 4",
102 initial_regs
= [0] * 32
103 initial_regs
[1] = 0x80000000
104 initial_regs
[2] = 0x40
105 initial_regs
[4] = 0x00
106 self
.add_case(Program(lst
, bigendian
), initial_regs
)
108 def case_rlwinm(self
):
110 mb
= random
.randint(0, 31)
111 me
= random
.randint(0, 31)
112 sh
= random
.randint(0, 31)
113 lst
= [f
"rlwinm 3, 1, {mb}, {me}, {sh}",
114 #f"rlwinm. 3, 1, {mb}, {me}, {sh}"
116 initial_regs
= [0] * 32
117 initial_regs
[1] = random
.randint(0, (1 << 64)-1)
118 self
.add_case(Program(lst
, bigendian
), initial_regs
)
120 def case_rlwimi(self
):
121 lst
= ["rlwimi 3, 1, 5, 20, 6"]
122 initial_regs
= [0] * 32
123 initial_regs
[1] = 0xdeadbeef
124 initial_regs
[3] = 0x12345678
125 self
.add_case(Program(lst
, bigendian
), initial_regs
)
127 def case_rlwnm(self
):
128 lst
= ["rlwnm 3, 1, 2, 20, 6"]
129 initial_regs
= [0] * 32
130 initial_regs
[1] = random
.randint(0, (1 << 64)-1)
131 initial_regs
[2] = random
.randint(0, 63)
132 self
.add_case(Program(lst
, bigendian
), initial_regs
)
134 def case_rldicl(self
):
135 lst
= ["rldicl 3, 1, 5, 20"]
136 initial_regs
= [0] * 32
137 initial_regs
[1] = random
.randint(0, (1 << 64)-1)
138 self
.add_case(Program(lst
, bigendian
), initial_regs
)
140 def case_rldicr(self
):
141 lst
= ["rldicr 3, 1, 5, 20"]
142 initial_regs
= [0] * 32
143 initial_regs
[1] = random
.randint(0, (1 << 64)-1)
144 self
.add_case(Program(lst
, bigendian
), initial_regs
)
146 def case_regression_extswsli(self
):
147 lst
= [f
"extswsli 3, 1, 34"]
148 initial_regs
= [0] * 32
149 initial_regs
[1] = 0x5678
150 self
.add_case(Program(lst
, bigendian
), initial_regs
)
152 def case_regression_extswsli_2(self
):
153 lst
= [f
"extswsli 3, 1, 7"]
154 initial_regs
= [0] * 32
155 initial_regs
[1] = 0x3ffffd7377f19fdd
156 self
.add_case(Program(lst
, bigendian
), initial_regs
)
158 def case_regression_extswsli_3(self
):
159 lst
= [f
"extswsli 3, 1, 0"]
160 initial_regs
= [0] * 32
161 #initial_regs[1] = 0x80000000fb4013e2
162 #initial_regs[1] = 0xffffffffffffffff
163 #initial_regs[1] = 0x00000000ffffffff
164 initial_regs
[1] = 0x0000010180122900
165 #initial_regs[1] = 0x3ffffd73f7f19fdd
166 self
.add_case(Program(lst
, bigendian
), initial_regs
)
168 def case_extswsli(self
):
170 sh
= random
.randint(0, 63)
171 lst
= [f
"extswsli 3, 1, {sh}"]
172 initial_regs
= [0] * 32
173 initial_regs
[1] = random
.randint(0, (1 << 64)-1)
174 self
.add_case(Program(lst
, bigendian
), initial_regs
)
177 insns
= ["rldic", "rldicl", "rldicr"]
179 choice
= random
.choice(insns
)
180 sh
= random
.randint(0, 63)
181 m
= random
.randint(0, 63)
182 lst
= [f
"{choice} 3, 1, {sh}, {m}"]
183 initial_regs
= [0] * 32
184 initial_regs
[1] = random
.randint(0, (1 << 64)-1)
185 self
.add_case(Program(lst
, bigendian
), initial_regs
)
187 def case_ilang(self
):
188 pspec
= ShiftRotPipeSpec(id_wid
=2)
189 alu
= ShiftRotBasePipe(pspec
)
190 vl
= rtlil
.convert(alu
, ports
=alu
.ports())
191 with
open("pipeline.il", "w") as f
:
195 class TestRunner(unittest
.TestCase
):
196 def __init__(self
, test_data
):
197 super().__init
__("run_all")
198 self
.test_data
= test_data
203 instruction
= Signal(32)
205 pdecode
= create_pdecode()
207 m
.submodules
.pdecode2
= pdecode2
= PowerDecode2(pdecode
)
209 pspec
= ShiftRotPipeSpec(id_wid
=2)
210 m
.submodules
.alu
= alu
= ShiftRotBasePipe(pspec
)
212 comb
+= alu
.p
.data_i
.ctx
.op
.eq_from_execute1(pdecode2
.e
)
213 comb
+= alu
.p
.valid_i
.eq(1)
214 comb
+= alu
.n
.ready_i
.eq(1)
215 comb
+= pdecode2
.dec
.raw_opcode_in
.eq(instruction
)
221 for test
in self
.test_data
:
223 program
= test
.program
224 self
.subTest(test
.name
)
225 simulator
= ISA(pdecode2
, test
.regs
, test
.sprs
, test
.cr
,
228 gen
= program
.generate_instructions()
229 instructions
= list(zip(gen
, program
.assembly
.splitlines()))
231 index
= simulator
.pc
.CIA
.value
//4
232 while index
< len(instructions
):
233 ins
, code
= instructions
[index
]
235 print("0x{:X}".format(ins
& 0xffffffff))
238 # ask the decoder to decode this binary data (endian'd)
239 yield pdecode2
.dec
.bigendian
.eq(bigendian
) # little / big?
240 yield instruction
.eq(ins
) # raw binary instr.
242 fn_unit
= yield pdecode2
.e
.do
.fn_unit
243 self
.assertEqual(fn_unit
, Function
.SHIFT_ROT
.value
)
244 yield from set_alu_inputs(alu
, pdecode2
, simulator
)
246 opname
= code
.split(' ')[0]
247 yield from simulator
.call(opname
)
248 index
= simulator
.pc
.CIA
.value
//4
250 vld
= yield alu
.n
.valid_o
253 vld
= yield alu
.n
.valid_o
255 alu_out
= yield alu
.n
.data_o
.o
.data
257 yield from self
.check_alu_outputs(alu
, pdecode2
,
261 sim
.add_sync_process(process
)
266 with sim
.write_vcd("simulator.vcd", "simulator.gtkw",
270 def check_alu_outputs(self
, alu
, dec2
, sim
, code
):
272 rc
= yield dec2
.e
.do
.rc
.data
273 cridx_ok
= yield dec2
.e
.write_cr
.ok
274 cridx
= yield dec2
.e
.write_cr
.data
276 print("check extra output", repr(code
), cridx_ok
, cridx
)
278 self
.assertEqual(cridx
, 0, code
)
283 yield from ALUHelpers
.get_cr_a(res
, alu
, dec2
)
284 yield from ALUHelpers
.get_xer_ca(res
, alu
, dec2
)
285 yield from ALUHelpers
.get_int_o(res
, alu
, dec2
)
287 yield from ALUHelpers
.get_sim_int_o(sim_o
, sim
, dec2
)
288 yield from ALUHelpers
.get_wr_sim_cr_a(sim_o
, sim
, dec2
)
289 yield from ALUHelpers
.get_wr_sim_xer_ca(sim_o
, sim
, dec2
)
291 ALUHelpers
.check_cr_a(self
, res
, sim_o
, "CR%d %s" % (cridx
, code
))
292 ALUHelpers
.check_xer_ca(self
, res
, sim_o
, code
)
293 ALUHelpers
.check_int_o(self
, res
, sim_o
, code
)
296 if __name__
== "__main__":
297 unittest
.main(exit
=False)
298 suite
= unittest
.TestSuite()
299 suite
.addTest(TestRunner(ShiftRotTestCase().test_data
))
301 runner
= unittest
.TextTestRunner()