2 from soc
.fu
.alu
.pipe_data
import ALUPipeSpec
3 from soc
.fu
.alu
.pipeline
import ALUBasePipe
4 from soc
.fu
.test
.common
import (TestCase
, TestAccumulatorBase
, ALUHelpers
)
5 from soc
.config
.endian
import bigendian
6 from soc
.decoder
.isa
.all
import ISA
7 from soc
.simulator
.program
import Program
8 from soc
.decoder
.selectable_int
import SelectableInt
9 from soc
.decoder
.power_enums
import (XER_bits
, Function
, MicrOp
, CryIn
)
10 from soc
.decoder
.power_decoder2
import (PowerDecode2
)
11 from soc
.decoder
.power_decoder
import (create_pdecode
)
12 from soc
.decoder
.isa
.caller
import ISACaller
, special_sprs
14 from nmigen
.cli
import rtlil
15 from nmutil
.formaltest
import FHDLTestCase
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 ALUFunctionUnit 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_rd_sim_xer_ca(res
, sim
, dec2
) # XER.ca
40 yield from ALUHelpers
.get_sim_xer_so(res
, sim
, dec2
) # XER.so
42 print("alu get_cu_inputs", res
)
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
)
56 yield from ALUHelpers
.set_xer_ca(alu
, dec2
, inp
)
57 yield from ALUHelpers
.set_xer_so(alu
, dec2
, inp
)
60 class ALUTestCase(TestAccumulatorBase
):
62 def case_1_regression(self
):
64 initial_regs
= [0] * 32
65 initial_regs
[1] = 0xb6a1fc6c8576af91
66 self
.add_case(Program(lst
, bigendian
), initial_regs
)
67 lst
= [f
"subf 3, 1, 2"]
68 initial_regs
= [0] * 32
69 initial_regs
[1] = 0x3d7f3f7ca24bac7b
70 initial_regs
[2] = 0xf6b2ac5e13ee15c2
71 self
.add_case(Program(lst
, bigendian
), initial_regs
)
72 lst
= [f
"subf 3, 1, 2"]
73 initial_regs
= [0] * 32
74 initial_regs
[1] = 0x833652d96c7c0058
75 initial_regs
[2] = 0x1c27ecff8a086c1a
76 self
.add_case(Program(lst
, bigendian
), initial_regs
)
78 initial_regs
= [0] * 32
79 initial_regs
[1] = 0x7f9497aaff900ea0
80 self
.add_case(Program(lst
, bigendian
), initial_regs
)
81 lst
= [f
"add. 3, 1, 2"]
82 initial_regs
= [0] * 32
83 initial_regs
[1] = 0xc523e996a8ff6215
84 initial_regs
[2] = 0xe1e5b9cc9864c4a8
85 self
.add_case(Program(lst
, bigendian
), initial_regs
)
86 lst
= [f
"add 3, 1, 2"]
87 initial_regs
= [0] * 32
88 initial_regs
[1] = 0x2e08ae202742baf8
89 initial_regs
[2] = 0x86c43ece9efe5baa
90 self
.add_case(Program(lst
, bigendian
), initial_regs
)
93 insns
= ["add", "add.", "subf"]
95 choice
= random
.choice(insns
)
96 lst
= [f
"{choice} 3, 1, 2"]
97 initial_regs
= [0] * 32
98 initial_regs
[1] = random
.randint(0, (1 << 64)-1)
99 initial_regs
[2] = random
.randint(0, (1 << 64)-1)
100 self
.add_case(Program(lst
, bigendian
), initial_regs
)
102 def case_addme_ca_0(self
):
103 insns
= ["addme", "addme.", "addmeo", "addmeo."]
105 lst
= [f
"{choice} 6, 16"]
106 for value
in [0x7ffffffff,
108 initial_regs
= [0] * 32
109 initial_regs
[16] = value
111 xer
= SelectableInt(0, 64)
112 xer
[XER_bits
['CA']] = 0
113 initial_sprs
[special_sprs
['XER']] = xer
114 self
.add_case(Program(lst
, bigendian
),
115 initial_regs
, initial_sprs
)
117 def case_addme_ca_1(self
):
118 insns
= ["addme", "addme.", "addmeo", "addmeo."]
120 lst
= [f
"{choice} 6, 16"]
121 for value
in [0x7ffffffff, # fails, bug #476
123 initial_regs
= [0] * 32
124 initial_regs
[16] = value
126 xer
= SelectableInt(0, 64)
127 xer
[XER_bits
['CA']] = 1
128 initial_sprs
[special_sprs
['XER']] = xer
129 self
.add_case(Program(lst
, bigendian
),
130 initial_regs
, initial_sprs
)
132 def case_addze(self
):
133 insns
= ["addze", "addze.", "addzeo", "addzeo."]
135 lst
= [f
"{choice} 6, 16"]
136 initial_regs
= [0] * 32
137 initial_regs
[16] = 0x00ff00ff00ff0080
138 self
.add_case(Program(lst
, bigendian
), initial_regs
)
140 self
.add_case(Program(lst
, bigendian
), initial_regs
)
142 def case_addis_nonzero_r0_regression(self
):
143 lst
= [f
"addis 3, 0, 1"]
145 initial_regs
= [0] * 32
147 self
.add_case(Program(lst
, bigendian
), initial_regs
)
149 def case_addis_nonzero_r0(self
):
151 imm
= random
.randint(-(1 << 15), (1 << 15)-1)
152 lst
= [f
"addis 3, 0, {imm}"]
154 initial_regs
= [0] * 32
155 initial_regs
[0] = random
.randint(0, (1 << 64)-1)
156 self
.add_case(Program(lst
, bigendian
), initial_regs
)
158 def case_rand_imm(self
):
159 insns
= ["addi", "addis", "subfic"]
161 choice
= random
.choice(insns
)
162 imm
= random
.randint(-(1 << 15), (1 << 15)-1)
163 lst
= [f
"{choice} 3, 1, {imm}"]
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_0_adde(self
):
170 lst
= ["adde. 5, 6, 7"]
172 initial_regs
= [0] * 32
173 initial_regs
[6] = random
.randint(0, (1 << 64)-1)
174 initial_regs
[7] = random
.randint(0, (1 << 64)-1)
176 xer
= SelectableInt(0, 64)
177 xer
[XER_bits
['CA']] = 1
178 initial_sprs
[special_sprs
['XER']] = xer
179 self
.add_case(Program(lst
, bigendian
),
180 initial_regs
, initial_sprs
)
183 lst
= ["subf. 1, 6, 7",
185 initial_regs
= [0] * 32
186 initial_regs
[6] = 0x10
187 initial_regs
[7] = 0x05
188 self
.add_case(Program(lst
, bigendian
), initial_regs
, {})
191 lst
= ["cmp cr2, 0, 2, 3"]
192 initial_regs
= [0] * 32
193 initial_regs
[2] = 0xffffffffaaaaaaaa
194 initial_regs
[3] = 0x00000000aaaaaaaa
195 self
.add_case(Program(lst
, bigendian
), initial_regs
, {})
197 lst
= ["cmp cr2, 0, 4, 5"]
198 initial_regs
= [0] * 32
199 initial_regs
[4] = 0x00000000aaaaaaaa
200 initial_regs
[5] = 0xffffffffaaaaaaaa
201 self
.add_case(Program(lst
, bigendian
), initial_regs
, {})
204 lst
= ["cmp cr2, 1, 2, 3"]
205 initial_regs
= [0] * 32
206 initial_regs
[2] = 0xffffffffaaaaaaaa
207 initial_regs
[3] = 0x00000000aaaaaaaa
208 self
.add_case(Program(lst
, bigendian
), initial_regs
, {})
210 lst
= ["cmp cr2, 1, 4, 5"]
211 initial_regs
= [0] * 32
212 initial_regs
[4] = 0x00000000aaaaaaaa
213 initial_regs
[5] = 0xffffffffaaaaaaaa
214 self
.add_case(Program(lst
, bigendian
), initial_regs
, {})
216 def case_extsb(self
):
217 insns
= ["extsb", "extsh", "extsw"]
219 choice
= random
.choice(insns
)
220 lst
= [f
"{choice} 3, 1"]
222 initial_regs
= [0] * 32
223 initial_regs
[1] = random
.randint(0, (1 << 64)-1)
224 self
.add_case(Program(lst
, bigendian
), initial_regs
)
226 def case_cmpeqb(self
):
227 lst
= ["cmpeqb cr1, 1, 2"]
229 initial_regs
= [0] * 32
231 initial_regs
[2] = 0x0001030507090b0f
232 self
.add_case(Program(lst
, bigendian
), initial_regs
, {})
234 def case_ilang(self
):
235 pspec
= ALUPipeSpec(id_wid
=2)
236 alu
= ALUBasePipe(pspec
)
237 vl
= rtlil
.convert(alu
, ports
=alu
.ports())
238 with
open("alu_pipeline.il", "w") as f
:
242 class TestRunner(unittest
.TestCase
):
244 def execute(self
, alu
,instruction
, pdecode2
, test
):
245 program
= test
.program
246 sim
= ISA(pdecode2
, test
.regs
, test
.sprs
, test
.cr
,
249 gen
= program
.generate_instructions()
250 instructions
= list(zip(gen
, program
.assembly
.splitlines()))
252 index
= sim
.pc
.CIA
.value
//4
253 while index
< len(instructions
):
254 ins
, code
= instructions
[index
]
256 print("instruction: 0x{:X}".format(ins
& 0xffffffff))
259 so
= 1 if sim
.spr
['XER'][XER_bits
['SO']] else 0
260 ov
= 1 if sim
.spr
['XER'][XER_bits
['OV']] else 0
261 ov32
= 1 if sim
.spr
['XER'][XER_bits
['OV32']] else 0
262 print("before: so/ov/32", so
, ov
, ov32
)
264 # ask the decoder to decode this binary data (endian'd)
266 yield pdecode2
.dec
.bigendian
.eq(bigendian
)
267 yield instruction
.eq(ins
) # raw binary instr.
269 fn_unit
= yield pdecode2
.e
.do
.fn_unit
270 self
.assertEqual(fn_unit
, Function
.ALU
.value
)
271 yield from set_alu_inputs(alu
, pdecode2
, sim
)
273 # set valid for one cycle, propagate through pipeline...
274 yield alu
.p
.valid_i
.eq(1)
276 yield alu
.p
.valid_i
.eq(0)
278 opname
= code
.split(' ')[0]
279 yield from sim
.call(opname
)
280 index
= sim
.pc
.CIA
.value
//4
282 vld
= yield alu
.n
.valid_o
285 vld
= yield alu
.n
.valid_o
288 yield from self
.check_alu_outputs(alu
, pdecode2
, sim
, code
)
292 test_data
= ALUTestCase().test_data
295 instruction
= Signal(32)
297 pdecode
= create_pdecode()
299 m
.submodules
.pdecode2
= pdecode2
= PowerDecode2(pdecode
)
301 pspec
= ALUPipeSpec(id_wid
=2)
302 m
.submodules
.alu
= alu
= ALUBasePipe(pspec
)
304 comb
+= alu
.p
.data_i
.ctx
.op
.eq_from_execute1(pdecode2
.e
)
305 comb
+= alu
.n
.ready_i
.eq(1)
306 comb
+= pdecode2
.dec
.raw_opcode_in
.eq(instruction
)
312 for test
in test_data
:
314 program
= test
.program
315 with self
.subTest(test
.name
):
316 yield from self
.execute(alu
, instruction
, pdecode2
, test
)
318 sim
.add_sync_process(process
)
319 with sim
.write_vcd("alu_simulator.vcd"):
322 def check_alu_outputs(self
, alu
, dec2
, sim
, code
):
324 rc
= yield dec2
.e
.do
.rc
.data
325 cridx_ok
= yield dec2
.e
.write_cr
.ok
326 cridx
= yield dec2
.e
.write_cr
.data
328 print("check extra output", repr(code
), cridx_ok
, cridx
)
330 self
.assertEqual(cridx
, 0, code
)
332 oe
= yield dec2
.e
.do
.oe
.oe
333 oe_ok
= yield dec2
.e
.do
.oe
.ok
334 if not oe
or not oe_ok
:
335 # if OE not enabled, XER SO and OV must correspondingly be false
336 so_ok
= yield alu
.n
.data_o
.xer_so
.ok
337 ov_ok
= yield alu
.n
.data_o
.xer_ov
.ok
338 self
.assertEqual(so_ok
, False, code
)
339 self
.assertEqual(ov_ok
, False, code
)
344 yield from ALUHelpers
.get_cr_a(res
, alu
, dec2
)
345 yield from ALUHelpers
.get_xer_ov(res
, alu
, dec2
)
346 yield from ALUHelpers
.get_xer_ca(res
, alu
, dec2
)
347 yield from ALUHelpers
.get_int_o(res
, alu
, dec2
)
348 yield from ALUHelpers
.get_xer_so(res
, alu
, dec2
)
350 yield from ALUHelpers
.get_sim_int_o(sim_o
, sim
, dec2
)
351 yield from ALUHelpers
.get_wr_sim_cr_a(sim_o
, sim
, dec2
)
352 yield from ALUHelpers
.get_sim_xer_ov(sim_o
, sim
, dec2
)
353 yield from ALUHelpers
.get_wr_sim_xer_ca(sim_o
, sim
, dec2
)
354 yield from ALUHelpers
.get_sim_xer_so(sim_o
, sim
, dec2
)
356 ALUHelpers
.check_cr_a(self
, res
, sim_o
, "CR%d %s" % (cridx
, code
))
357 ALUHelpers
.check_xer_ov(self
, res
, sim_o
, code
)
358 ALUHelpers
.check_xer_ca(self
, res
, sim_o
, code
)
359 ALUHelpers
.check_int_o(self
, res
, sim_o
, code
)
360 ALUHelpers
.check_xer_so(self
, res
, sim_o
, code
)
363 if __name__
== "__main__":