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_rand_imm(self
):
103 insns
= ["addi", "addis", "subfic"]
105 choice
= random
.choice(insns
)
106 imm
= random
.randint(-(1 << 15), (1 << 15)-1)
107 lst
= [f
"{choice} 3, 1, {imm}"]
109 initial_regs
= [0] * 32
110 initial_regs
[1] = random
.randint(0, (1 << 64)-1)
111 self
.add_case(Program(lst
, bigendian
), initial_regs
)
113 def case_0_adde(self
):
114 lst
= ["adde. 5, 6, 7"]
116 initial_regs
= [0] * 32
117 initial_regs
[6] = random
.randint(0, (1 << 64)-1)
118 initial_regs
[7] = random
.randint(0, (1 << 64)-1)
120 xer
= SelectableInt(0, 64)
121 xer
[XER_bits
['CA']] = 1
122 initial_sprs
[special_sprs
['XER']] = xer
123 self
.add_case(Program(lst
, bigendian
),
124 initial_regs
, initial_sprs
)
127 lst
= ["subf. 1, 6, 7",
129 initial_regs
= [0] * 32
130 initial_regs
[6] = 0x10
131 initial_regs
[7] = 0x05
132 self
.add_case(Program(lst
, bigendian
), initial_regs
, {})
135 lst
= ["cmp cr2, 0, 2, 3"]
136 initial_regs
= [0] * 32
137 initial_regs
[2] = 0xffffffffaaaaaaaa
138 initial_regs
[3] = 0x00000000aaaaaaaa
139 self
.add_case(Program(lst
, bigendian
), initial_regs
, {})
141 lst
= ["cmp cr2, 0, 4, 5"]
142 initial_regs
= [0] * 32
143 initial_regs
[4] = 0x00000000aaaaaaaa
144 initial_regs
[5] = 0xffffffffaaaaaaaa
145 self
.add_case(Program(lst
, bigendian
), initial_regs
, {})
148 lst
= ["cmp cr2, 1, 2, 3"]
149 initial_regs
= [0] * 32
150 initial_regs
[2] = 0xffffffffaaaaaaaa
151 initial_regs
[3] = 0x00000000aaaaaaaa
152 self
.add_case(Program(lst
, bigendian
), initial_regs
, {})
154 lst
= ["cmp cr2, 1, 4, 5"]
155 initial_regs
= [0] * 32
156 initial_regs
[4] = 0x00000000aaaaaaaa
157 initial_regs
[5] = 0xffffffffaaaaaaaa
158 self
.add_case(Program(lst
, bigendian
), initial_regs
, {})
160 def case_extsb(self
):
161 insns
= ["extsb", "extsh", "extsw"]
163 choice
= random
.choice(insns
)
164 lst
= [f
"{choice} 3, 1"]
166 initial_regs
= [0] * 32
167 initial_regs
[1] = random
.randint(0, (1 << 64)-1)
168 self
.add_case(Program(lst
, bigendian
), initial_regs
)
170 def case_cmpeqb(self
):
171 lst
= ["cmpeqb cr1, 1, 2"]
173 initial_regs
= [0] * 32
175 initial_regs
[2] = 0x0001030507090b0f
176 self
.add_case(Program(lst
, bigendian
), initial_regs
, {})
178 def case_ilang(self
):
179 pspec
= ALUPipeSpec(id_wid
=2)
180 alu
= ALUBasePipe(pspec
)
181 vl
= rtlil
.convert(alu
, ports
=alu
.ports())
182 with
open("alu_pipeline.il", "w") as f
:
186 class TestRunner(unittest
.TestCase
):
188 def execute(self
, alu
,instruction
, pdecode2
, test
):
189 program
= test
.program
190 sim
= ISA(pdecode2
, test
.regs
, test
.sprs
, test
.cr
,
193 gen
= program
.generate_instructions()
194 instructions
= list(zip(gen
, program
.assembly
.splitlines()))
196 index
= sim
.pc
.CIA
.value
//4
197 while index
< len(instructions
):
198 ins
, code
= instructions
[index
]
200 print("instruction: 0x{:X}".format(ins
& 0xffffffff))
203 so
= 1 if sim
.spr
['XER'][XER_bits
['SO']] else 0
204 ov
= 1 if sim
.spr
['XER'][XER_bits
['OV']] else 0
205 ov32
= 1 if sim
.spr
['XER'][XER_bits
['OV32']] else 0
206 print("before: so/ov/32", so
, ov
, ov32
)
208 # ask the decoder to decode this binary data (endian'd)
210 yield pdecode2
.dec
.bigendian
.eq(bigendian
)
211 yield instruction
.eq(ins
) # raw binary instr.
213 fn_unit
= yield pdecode2
.e
.do
.fn_unit
214 self
.assertEqual(fn_unit
, Function
.ALU
.value
)
215 yield from set_alu_inputs(alu
, pdecode2
, sim
)
217 # set valid for one cycle, propagate through pipeline...
218 yield alu
.p
.valid_i
.eq(1)
220 yield alu
.p
.valid_i
.eq(0)
222 opname
= code
.split(' ')[0]
223 yield from sim
.call(opname
)
224 index
= sim
.pc
.CIA
.value
//4
226 vld
= yield alu
.n
.valid_o
229 vld
= yield alu
.n
.valid_o
232 yield from self
.check_alu_outputs(alu
, pdecode2
, sim
, code
)
236 test_data
= ALUTestCase().test_data
239 instruction
= Signal(32)
241 pdecode
= create_pdecode()
243 m
.submodules
.pdecode2
= pdecode2
= PowerDecode2(pdecode
)
245 pspec
= ALUPipeSpec(id_wid
=2)
246 m
.submodules
.alu
= alu
= ALUBasePipe(pspec
)
248 comb
+= alu
.p
.data_i
.ctx
.op
.eq_from_execute1(pdecode2
.e
)
249 comb
+= alu
.n
.ready_i
.eq(1)
250 comb
+= pdecode2
.dec
.raw_opcode_in
.eq(instruction
)
256 for test
in test_data
:
258 program
= test
.program
259 with self
.subTest(test
.name
):
260 yield from self
.execute(alu
, instruction
, pdecode2
, test
)
262 sim
.add_sync_process(process
)
263 with sim
.write_vcd("alu_simulator.vcd"):
266 def check_alu_outputs(self
, alu
, dec2
, sim
, code
):
268 rc
= yield dec2
.e
.do
.rc
.data
269 cridx_ok
= yield dec2
.e
.write_cr
.ok
270 cridx
= yield dec2
.e
.write_cr
.data
272 print("check extra output", repr(code
), cridx_ok
, cridx
)
274 self
.assertEqual(cridx
, 0, code
)
276 oe
= yield dec2
.e
.do
.oe
.oe
277 oe_ok
= yield dec2
.e
.do
.oe
.ok
278 if not oe
or not oe_ok
:
279 # if OE not enabled, XER SO and OV must correspondingly be false
280 so_ok
= yield alu
.n
.data_o
.xer_so
.ok
281 ov_ok
= yield alu
.n
.data_o
.xer_ov
.ok
282 self
.assertEqual(so_ok
, False, code
)
283 self
.assertEqual(ov_ok
, False, code
)
288 yield from ALUHelpers
.get_cr_a(res
, alu
, dec2
)
289 yield from ALUHelpers
.get_xer_ov(res
, alu
, dec2
)
290 yield from ALUHelpers
.get_xer_ca(res
, alu
, dec2
)
291 yield from ALUHelpers
.get_int_o(res
, alu
, dec2
)
292 yield from ALUHelpers
.get_xer_so(res
, alu
, dec2
)
294 yield from ALUHelpers
.get_sim_int_o(sim_o
, sim
, dec2
)
295 yield from ALUHelpers
.get_wr_sim_cr_a(sim_o
, sim
, dec2
)
296 yield from ALUHelpers
.get_sim_xer_ov(sim_o
, sim
, dec2
)
297 yield from ALUHelpers
.get_wr_sim_xer_ca(sim_o
, sim
, dec2
)
298 yield from ALUHelpers
.get_sim_xer_so(sim_o
, sim
, dec2
)
300 ALUHelpers
.check_cr_a(self
, res
, sim_o
, "CR%d %s" % (cridx
, code
))
301 ALUHelpers
.check_xer_ov(self
, res
, sim_o
, code
)
302 ALUHelpers
.check_xer_ca(self
, res
, sim_o
, code
)
303 ALUHelpers
.check_int_o(self
, res
, sim_o
, code
)
304 ALUHelpers
.check_xer_so(self
, res
, sim_o
, code
)
307 if __name__
== "__main__":