3 import power_instruction_analyzer
as pia
4 from nmigen
import Module
, Signal
5 from nmigen
.back
.pysim
import Simulator
, Delay
6 from soc
.decoder
.power_decoder
import (create_pdecode
)
7 from soc
.decoder
.power_decoder2
import (PowerDecode2
)
8 from soc
.decoder
.power_enums
import XER_bits
, Function
9 from soc
.decoder
.isa
.all
import ISA
10 from soc
.config
.endian
import bigendian
12 from soc
.fu
.test
.common
import ALUHelpers
13 from soc
.fu
.div
.pipeline
import DivBasePipe
14 from soc
.fu
.div
.pipe_data
import DivPipeSpec
17 def log_rand(n
, min_val
=1):
18 logrange
= random
.randint(1, n
)
19 return random
.randint(min_val
, (1 << logrange
)-1)
22 def get_cu_inputs(dec2
, sim
):
23 """naming (res) must conform to DivFunctionUnit input regspec
27 yield from ALUHelpers
.get_sim_int_ra(res
, sim
, dec2
) # RA
28 yield from ALUHelpers
.get_sim_int_rb(res
, sim
, dec2
) # RB
29 yield from ALUHelpers
.get_sim_xer_so(res
, sim
, dec2
) # XER.so
31 print("alu get_cu_inputs", res
)
36 def pia_res_to_output(pia_res
):
38 if pia_res
.rt
is not None:
39 retval
["o"] = pia_res
.rt
40 if pia_res
.cr0
is not None:
52 if pia_res
.overflow
is not None:
53 overflow
= pia_res
.overflow
60 retval
["xer_so"] = overflow
.so
67 def set_alu_inputs(alu
, dec2
, sim
):
68 # TODO: see https://bugs.libre-soc.org/show_bug.cgi?id=305#c43
69 # detect the immediate here (with m.If(self.i.ctx.op.imm_data.imm_ok))
70 # and place it into data_i.b
72 inp
= yield from get_cu_inputs(dec2
, sim
)
73 yield from ALUHelpers
.set_int_ra(alu
, dec2
, inp
)
74 yield from ALUHelpers
.set_int_rb(alu
, dec2
, inp
)
76 yield from ALUHelpers
.set_xer_so(alu
, dec2
, inp
)
77 return pia
.InstructionInput(ra
=inp
["ra"], rb
=inp
["rb"], rc
=0)
80 class DivTestHelper(unittest
.TestCase
):
81 def execute(self
, alu
, instruction
, pdecode2
, test
, div_pipe_kind
):
83 isa_sim
= ISA(pdecode2
, test
.regs
, test
.sprs
, test
.cr
,
86 gen
= prog
.generate_instructions()
87 instructions
= list(zip(gen
, prog
.assembly
.splitlines()))
90 index
= isa_sim
.pc
.CIA
.value
//4
91 while index
< len(instructions
):
92 ins
, code
= instructions
[index
]
94 print("instruction: 0x{:X}".format(ins
& 0xffffffff))
98 so
= 1 if spr
['XER'][XER_bits
['SO']] else 0
99 ov
= 1 if spr
['XER'][XER_bits
['OV']] else 0
100 ov32
= 1 if spr
['XER'][XER_bits
['OV32']] else 0
101 xer_zero
= not (so
or ov
or ov32
)
102 print("before: so/ov/32", so
, ov
, ov32
)
106 # ask the decoder to decode this binary data (endian'd)
108 yield pdecode2
.dec
.bigendian
.eq(bigendian
)
109 yield instruction
.eq(ins
) # raw binary instr.
111 fn_unit
= yield pdecode2
.e
.do
.fn_unit
112 self
.assertEqual(fn_unit
, Function
.DIV
.value
)
113 pia_inputs
= yield from set_alu_inputs(alu
, pdecode2
,
116 # set valid for one cycle, propagate through pipeline..
117 # note that it is critically important to do this
118 # for DIV otherwise it starts trying to produce
120 yield alu
.p
.valid_i
.eq(1)
122 yield alu
.p
.valid_i
.eq(0)
124 opname
= code
.split(' ')[0]
126 fnname
= opname
.replace(".", "_")
127 print(f
"{fnname}({pia_inputs})")
129 pia
, opname
.replace(".", "_"))(pia_inputs
)
130 print(f
"-> {pia_res}")
134 yield from isa_sim
.call(opname
)
135 index
= isa_sim
.pc
.CIA
.value
//4
137 vld
= yield alu
.n
.valid_o
141 vld
= yield alu
.n
.valid_o
142 # bug #425 investigation
143 do
= alu
.pipe_end
.div_out
145 is_32bit
= yield ctx_op
.is_32bit
146 is_signed
= yield ctx_op
.is_signed
147 quotient_root
= yield do
.i
.core
.quotient_root
148 quotient_65
= yield do
.quotient_65
149 dive_abs_ov32
= yield do
.i
.dive_abs_ov32
150 div_by_zero
= yield do
.i
.div_by_zero
151 quotient_neg
= yield do
.quotient_neg
152 print("32bit", hex(is_32bit
))
153 print("signed", hex(is_signed
))
154 print("quotient_root", hex(quotient_root
))
155 print("quotient_65", hex(quotient_65
))
156 print("div_by_zero", hex(div_by_zero
))
157 print("dive_abs_ov32", hex(dive_abs_ov32
))
158 print("quotient_neg", hex(quotient_neg
))
163 # XXX sim._state is an internal variable
164 # and timeline does not exist
165 # AttributeError: '_SimulatorState' object
166 # has no attribute 'timeline'
167 # TODO: raise bugreport with whitequark
168 # requesting a public API to access this "officially"
169 # XXX print("time:", sim._state.timeline.now)
170 msg
= "%s: %s" % (div_pipe_kind
.name
, code
)
171 msg
+= " %s" % (repr(prog
.assembly
))
172 msg
+= " %s" % (repr(test
.regs
))
173 yield from self
.check_alu_outputs(alu
, pdecode2
,
177 def run_all(self
, test_data
, div_pipe_kind
, file_name_prefix
):
180 instruction
= Signal(32)
182 pdecode
= create_pdecode()
184 m
.submodules
.pdecode2
= pdecode2
= PowerDecode2(pdecode
)
186 pspec
= DivPipeSpec(id_wid
=2, div_pipe_kind
=div_pipe_kind
)
187 m
.submodules
.alu
= alu
= DivBasePipe(pspec
)
189 comb
+= alu
.p
.data_i
.ctx
.op
.eq_from_execute1(pdecode2
.e
)
190 comb
+= alu
.n
.ready_i
.eq(1)
191 comb
+= pdecode2
.dec
.raw_opcode_in
.eq(instruction
)
197 for test
in test_data
:
199 with self
.subTest(test
.name
):
200 yield from self
.execute(alu
, instruction
, pdecode2
,
203 sim
.add_sync_process(process
)
204 with sim
.write_vcd(f
"{file_name_prefix}_{div_pipe_kind.name}.vcd"):
207 def check_alu_outputs(self
, alu
, dec2
, sim
, code
, pia_res
):
209 rc
= yield dec2
.e
.do
.rc
.data
210 cridx_ok
= yield dec2
.e
.write_cr
.ok
211 cridx
= yield dec2
.e
.write_cr
.data
213 print("check extra output", repr(code
), cridx_ok
, cridx
)
215 self
.assertEqual(cridx
, 0, code
)
220 yield from ALUHelpers
.get_cr_a(res
, alu
, dec2
)
221 yield from ALUHelpers
.get_xer_ov(res
, alu
, dec2
)
222 yield from ALUHelpers
.get_int_o(res
, alu
, dec2
)
223 yield from ALUHelpers
.get_xer_so(res
, alu
, dec2
)
225 print("res output", res
)
227 yield from ALUHelpers
.get_sim_int_o(sim_o
, sim
, dec2
)
228 yield from ALUHelpers
.get_wr_sim_cr_a(sim_o
, sim
, dec2
)
229 yield from ALUHelpers
.get_sim_xer_ov(sim_o
, sim
, dec2
)
230 yield from ALUHelpers
.get_sim_xer_so(sim_o
, sim
, dec2
)
232 print("sim output", sim_o
)
234 print("power-instruction-analyzer result:")
236 if pia_res
is not None:
237 with self
.subTest(check
="pia", sim_o
=sim_o
, pia_res
=str(pia_res
)):
238 pia_o
= pia_res_to_output(pia_res
)
239 ALUHelpers
.check_int_o(self
, res
, pia_o
, code
)
240 ALUHelpers
.check_cr_a(self
, res
, pia_o
, code
)
241 ALUHelpers
.check_xer_ov(self
, res
, pia_o
, code
)
242 ALUHelpers
.check_xer_so(self
, res
, pia_o
, code
)
244 with self
.subTest(check
="sim", sim_o
=sim_o
, pia_res
=str(pia_res
)):
245 ALUHelpers
.check_int_o(self
, res
, sim_o
, code
)
246 ALUHelpers
.check_cr_a(self
, res
, sim_o
, code
)
247 ALUHelpers
.check_xer_ov(self
, res
, sim_o
, code
)
248 ALUHelpers
.check_xer_so(self
, res
, sim_o
, code
)
250 oe
= yield dec2
.e
.do
.oe
.oe
251 oe_ok
= yield dec2
.e
.do
.oe
.ok
252 print("oe, oe_ok", oe
, oe_ok
)
253 if not oe
or not oe_ok
:
254 # if OE not enabled, XER SO and OV must not be activated
255 so_ok
= yield alu
.n
.data_o
.xer_so
.ok
256 ov_ok
= yield alu
.n
.data_o
.xer_ov
.ok
257 print("so, ov", so_ok
, ov_ok
)
258 self
.assertEqual(ov_ok
, False, code
)
259 self
.assertEqual(so_ok
, False, code
)