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_addme_ca_so_3(self
):
133 """bug where SO does not get passed through to CR0
135 lst
= ["addme. 6, 16"]
136 initial_regs
= [0] * 32
137 initial_regs
[16] = 0x7ffffffff
139 xer
= SelectableInt(0, 64)
140 xer
[XER_bits
['CA']] = 1
141 xer
[XER_bits
['SO']] = 1
142 initial_sprs
[special_sprs
['XER']] = xer
143 self
.add_case(Program(lst
, bigendian
),
144 initial_regs
, initial_sprs
)
146 def case_addze(self
):
147 insns
= ["addze", "addze.", "addzeo", "addzeo."]
149 lst
= [f
"{choice} 6, 16"]
150 initial_regs
= [0] * 32
151 initial_regs
[16] = 0x00ff00ff00ff0080
152 self
.add_case(Program(lst
, bigendian
), initial_regs
)
154 self
.add_case(Program(lst
, bigendian
), initial_regs
)
156 def case_addis_nonzero_r0_regression(self
):
157 lst
= [f
"addis 3, 0, 1"]
159 initial_regs
= [0] * 32
161 self
.add_case(Program(lst
, bigendian
), initial_regs
)
163 def case_addis_nonzero_r0(self
):
165 imm
= random
.randint(-(1 << 15), (1 << 15)-1)
166 lst
= [f
"addis 3, 0, {imm}"]
168 initial_regs
= [0] * 32
169 initial_regs
[0] = random
.randint(0, (1 << 64)-1)
170 self
.add_case(Program(lst
, bigendian
), initial_regs
)
172 def case_rand_imm(self
):
173 insns
= ["addi", "addis", "subfic"]
175 choice
= random
.choice(insns
)
176 imm
= random
.randint(-(1 << 15), (1 << 15)-1)
177 lst
= [f
"{choice} 3, 1, {imm}"]
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_0_adde(self
):
184 lst
= ["adde. 5, 6, 7"]
186 initial_regs
= [0] * 32
187 initial_regs
[6] = random
.randint(0, (1 << 64)-1)
188 initial_regs
[7] = random
.randint(0, (1 << 64)-1)
190 xer
= SelectableInt(0, 64)
191 xer
[XER_bits
['CA']] = 1
192 initial_sprs
[special_sprs
['XER']] = xer
193 self
.add_case(Program(lst
, bigendian
),
194 initial_regs
, initial_sprs
)
197 lst
= ["subf. 1, 6, 7",
199 initial_regs
= [0] * 32
200 initial_regs
[6] = 0x10
201 initial_regs
[7] = 0x05
202 self
.add_case(Program(lst
, bigendian
), initial_regs
, {})
205 lst
= ["cmp cr2, 0, 2, 3"]
206 initial_regs
= [0] * 32
207 initial_regs
[2] = 0xffffffffaaaaaaaa
208 initial_regs
[3] = 0x00000000aaaaaaaa
209 self
.add_case(Program(lst
, bigendian
), initial_regs
, {})
211 lst
= ["cmp cr2, 0, 4, 5"]
212 initial_regs
= [0] * 32
213 initial_regs
[4] = 0x00000000aaaaaaaa
214 initial_regs
[5] = 0xffffffffaaaaaaaa
215 self
.add_case(Program(lst
, bigendian
), initial_regs
, {})
218 lst
= ["cmp cr2, 1, 2, 3"]
219 initial_regs
= [0] * 32
220 initial_regs
[2] = 0xffffffffaaaaaaaa
221 initial_regs
[3] = 0x00000000aaaaaaaa
222 self
.add_case(Program(lst
, bigendian
), initial_regs
, {})
224 lst
= ["cmp cr2, 1, 4, 5"]
225 initial_regs
= [0] * 32
226 initial_regs
[4] = 0x00000000aaaaaaaa
227 initial_regs
[5] = 0xffffffffaaaaaaaa
228 self
.add_case(Program(lst
, bigendian
), initial_regs
, {})
230 def case_extsb(self
):
231 insns
= ["extsb", "extsh", "extsw"]
233 choice
= random
.choice(insns
)
234 lst
= [f
"{choice} 3, 1"]
236 initial_regs
= [0] * 32
237 initial_regs
[1] = random
.randint(0, (1 << 64)-1)
238 self
.add_case(Program(lst
, bigendian
), initial_regs
)
240 def case_cmpeqb(self
):
241 lst
= ["cmpeqb cr1, 1, 2"]
243 initial_regs
= [0] * 32
245 initial_regs
[2] = 0x0001030507090b0f
246 self
.add_case(Program(lst
, bigendian
), initial_regs
, {})
248 def case_ilang(self
):
249 pspec
= ALUPipeSpec(id_wid
=2)
250 alu
= ALUBasePipe(pspec
)
251 vl
= rtlil
.convert(alu
, ports
=alu
.ports())
252 with
open("alu_pipeline.il", "w") as f
:
256 class TestRunner(unittest
.TestCase
):
258 def execute(self
, alu
,instruction
, pdecode2
, test
):
259 program
= test
.program
260 sim
= ISA(pdecode2
, test
.regs
, test
.sprs
, test
.cr
,
263 gen
= program
.generate_instructions()
264 instructions
= list(zip(gen
, program
.assembly
.splitlines()))
266 index
= sim
.pc
.CIA
.value
//4
267 while index
< len(instructions
):
268 ins
, code
= instructions
[index
]
270 print("instruction: 0x{:X}".format(ins
& 0xffffffff))
273 so
= 1 if sim
.spr
['XER'][XER_bits
['SO']] else 0
274 ov
= 1 if sim
.spr
['XER'][XER_bits
['OV']] else 0
275 ov32
= 1 if sim
.spr
['XER'][XER_bits
['OV32']] else 0
276 print("before: so/ov/32", so
, ov
, ov32
)
278 # ask the decoder to decode this binary data (endian'd)
280 yield pdecode2
.dec
.bigendian
.eq(bigendian
)
281 yield instruction
.eq(ins
) # raw binary instr.
283 fn_unit
= yield pdecode2
.e
.do
.fn_unit
284 self
.assertEqual(fn_unit
, Function
.ALU
.value
)
285 yield from set_alu_inputs(alu
, pdecode2
, sim
)
287 # set valid for one cycle, propagate through pipeline...
288 yield alu
.p
.valid_i
.eq(1)
290 yield alu
.p
.valid_i
.eq(0)
292 opname
= code
.split(' ')[0]
293 yield from sim
.call(opname
)
294 index
= sim
.pc
.CIA
.value
//4
296 vld
= yield alu
.n
.valid_o
299 vld
= yield alu
.n
.valid_o
302 yield from self
.check_alu_outputs(alu
, pdecode2
, sim
, code
)
306 test_data
= ALUTestCase().test_data
309 instruction
= Signal(32)
311 pdecode
= create_pdecode()
313 m
.submodules
.pdecode2
= pdecode2
= PowerDecode2(pdecode
)
315 pspec
= ALUPipeSpec(id_wid
=2)
316 m
.submodules
.alu
= alu
= ALUBasePipe(pspec
)
318 comb
+= alu
.p
.data_i
.ctx
.op
.eq_from_execute1(pdecode2
.e
)
319 comb
+= alu
.n
.ready_i
.eq(1)
320 comb
+= pdecode2
.dec
.raw_opcode_in
.eq(instruction
)
326 for test
in test_data
:
328 program
= test
.program
329 with self
.subTest(test
.name
):
330 yield from self
.execute(alu
, instruction
, pdecode2
, test
)
332 sim
.add_sync_process(process
)
333 with sim
.write_vcd("alu_simulator.vcd"):
336 def check_alu_outputs(self
, alu
, dec2
, sim
, code
):
338 rc
= yield dec2
.e
.do
.rc
.data
339 cridx_ok
= yield dec2
.e
.write_cr
.ok
340 cridx
= yield dec2
.e
.write_cr
.data
342 print("check extra output", repr(code
), cridx_ok
, cridx
)
344 self
.assertEqual(cridx
, 0, code
)
346 oe
= yield dec2
.e
.do
.oe
.oe
347 oe_ok
= yield dec2
.e
.do
.oe
.ok
348 if not oe
or not oe_ok
:
349 # if OE not enabled, XER SO and OV must correspondingly be false
350 so_ok
= yield alu
.n
.data_o
.xer_so
.ok
351 ov_ok
= yield alu
.n
.data_o
.xer_ov
.ok
352 self
.assertEqual(so_ok
, False, code
)
353 self
.assertEqual(ov_ok
, False, code
)
358 yield from ALUHelpers
.get_cr_a(res
, alu
, dec2
)
359 yield from ALUHelpers
.get_xer_ov(res
, alu
, dec2
)
360 yield from ALUHelpers
.get_xer_ca(res
, alu
, dec2
)
361 yield from ALUHelpers
.get_int_o(res
, alu
, dec2
)
362 yield from ALUHelpers
.get_xer_so(res
, alu
, dec2
)
364 yield from ALUHelpers
.get_sim_int_o(sim_o
, sim
, dec2
)
365 yield from ALUHelpers
.get_wr_sim_cr_a(sim_o
, sim
, dec2
)
366 yield from ALUHelpers
.get_sim_xer_ov(sim_o
, sim
, dec2
)
367 yield from ALUHelpers
.get_wr_sim_xer_ca(sim_o
, sim
, dec2
)
368 yield from ALUHelpers
.get_sim_xer_so(sim_o
, sim
, dec2
)
370 ALUHelpers
.check_cr_a(self
, res
, sim_o
, "CR%d %s" % (cridx
, code
))
371 ALUHelpers
.check_xer_ov(self
, res
, sim_o
, code
)
372 ALUHelpers
.check_xer_ca(self
, res
, sim_o
, code
)
373 ALUHelpers
.check_int_o(self
, res
, sim_o
, code
)
374 ALUHelpers
.check_xer_so(self
, res
, sim_o
, code
)
377 if __name__
== "__main__":