2 from hashlib
import sha256
3 from textwrap
import dedent
5 from nmutil
.formaltest
import FHDLTestCase
6 from openpower
.decoder
.isa
.test_runner
import run_tst
7 from openpower
.decoder
.power_decoder
import create_pdecode
8 from openpower
.decoder
.power_decoder2
import PowerDecode2
9 from openpower
.decoder
.selectable_int
import SelectableInt
10 from openpower
.simulator
.program
import Program
14 class InstructionInput
:
15 def __init__(self
, ra
=None, rb
=None, rc
=None, immediate
=None, carry
=None, overflow
=None):
19 self
.immediate
= immediate
21 self
.overflow
= overflow
23 class InstructionOutput
:
24 def __init__(self
, rt
=None, overflow
=None, carry
=None, cr0
=None, cr1
=None, cr2
=None,
25 cr3
=None, cr4
=None, cr5
=None, cr6
=None, cr7
=None):
27 self
.overflow
= overflow
46 def unpack_bits(bits
, count
):
47 return tuple(((bits
>> i
) & 1) != 0
48 for i
in reversed(range(count
)))
51 # expressions taken from PowerISA v2.07B section B.2 (page 697 (728))
52 p
, q
, r
, s
, t
, u
, v
, w
, x
, y
= unpack_bits(dpd
, 10)
53 a
= (not s
and v
and w
) or (t
and v
and w
and s
) or (v
and w
and not x
)
54 b
= (p
and s
and x
and not t
) or (p
and not w
) or (p
and not v
)
55 c
= (q
and s
and x
and not t
) or (q
and not w
) or (q
and not v
)
57 e
= (v
and not w
and x
) or (
58 s
and v
and w
and x
) or (not t
and v
and x
and w
)
59 f
= (p
and t
and v
and w
and x
and not s
) or (
60 s
and not x
and v
) or (s
and not v
)
61 g
= (q
and t
and w
and v
and x
and not s
) or (
62 t
and not x
and v
) or (t
and not v
)
64 i
= (t
and v
and w
and x
) or (
65 s
and v
and w
and x
) or (v
and not w
and not x
)
66 j
= (p
and not s
and not t
and w
and v
) or (s
and v
and not w
and x
) or (
67 p
and w
and not x
and v
) or (w
and not v
)
68 k
= (q
and not s
and not t
and v
and w
) or (t
and v
and not w
and x
) or (
69 q
and v
and w
and not x
) or (x
and not v
)
71 return pack_bits(a
, b
, c
, d
, e
, f
, g
, h
, i
, j
, k
, m
)
74 # expressions taken from PowerISA v2.07B section B.1 (page 697 (728))
75 a
, b
, c
, d
, e
, f
, g
, h
, i
, j
, k
, m
= unpack_bits(bcd
, 12)
76 p
= (f
and a
and i
and not e
) or (j
and a
and not i
) or (b
and not a
)
77 q
= (g
and a
and i
and not e
) or (k
and a
and not i
) or (c
and not a
)
79 s
= (j
and not a
and e
and not i
) or (f
and not i
and not e
) or (
80 f
and not a
and not e
) or (e
and i
)
81 t
= (k
and not a
and e
and not i
) or (g
and not i
and not e
) or (
82 g
and not a
and not e
) or (a
and i
)
85 w
= (not e
and j
and not i
) or (e
and i
) or a
86 x
= (not a
and k
and not i
) or (a
and i
) or e
88 return pack_bits(p
, q
, r
, s
, t
, u
, v
, w
, x
, y
)
93 ra
= inputs
.ra
& ((1 << 64) - 1)
95 rt |
= dpd_to_bcd(ra
& 0x3FF)
96 rt |
= dpd_to_bcd((ra
>> 10) & 0x3FF) << 12
97 rt |
= dpd_to_bcd((ra
>> 32) & 0x3FF) << 32
98 rt |
= dpd_to_bcd((ra
>> 42) & 0x3FF) << 44
99 return InstructionOutput(rt
=rt
)
103 ra
= inputs
.ra
& ((1 << 64) - 1)
105 rt |
= bcd_to_dpd(ra
& 0xFFF)
106 rt |
= bcd_to_dpd((ra
>> 12) & 0xFFF) << 10
107 rt |
= bcd_to_dpd((ra
>> 32) & 0xFFF) << 32
108 rt |
= bcd_to_dpd((ra
>> 44) & 0xFFF) << 42
109 return InstructionOutput(rt
=rt
)
113 ra
= inputs
.ra
& ((1 << 64) - 1)
114 rb
= inputs
.rb
& ((1 << 64) - 1)
116 need_sixes
= ((~
sum >> 4) ^
(ra
>> 4) ^
(
117 rb
>> 4)) & 0x1111_1111_1111_1111
119 return InstructionOutput(rt
=rt
)
121 pia
.InstructionInput
= InstructionInput
122 pia
.InstructionOutput
= InstructionOutput
126 MOCK_PIA
= True # until pia is ported to python
130 import power_instruction_analyzer
as pia
133 class BCDFullTestCase(FHDLTestCase
):
134 """test full arbitrary bit patterns, including invalid BCD (not
135 supported by above reference code), against power-instruction-analyzer"""
140 def __init__(self
, *args
, **kwargs
):
141 super().__init
__(*args
, **kwargs
)
142 if BCDFullTestCase
.pdecode2
is None:
143 pdecode
= create_pdecode()
144 BCDFullTestCase
.pdecode2
= PowerDecode2(pdecode
)
147 return int.from_bytes(
148 sha256(bytes(str(v
), encoding
='ascii')).digest(),
152 def addg6s_tst_cases(self
):
154 for i
in range(1024):
156 yield (v
& mask
, (v
>> 64) & mask
)
158 def bcd_dpd_tst_cases(self
):
161 for i
in range(limit
):
163 v
&= mask
# mask to 64-bits
164 # replace lower bits with `i` to ensure we cover all patterns
169 def run_cases(self
, test_index
, test_cases
, instr
, arg_in_count
):
170 pia_func
= getattr(pia
, instr
.replace('.', '_'))
172 for i
in range(0, 32, arg_in_count
):
173 input_args
= ', '.join(str(i
+ j
)
174 for j
in range(arg_in_count
))
175 lst
.append(f
"{instr} {i}, {input_args}")
176 with
Program(lst
, bigendian
=False) as program
:
178 test_cases
= list(test_cases
)
179 outer_start_index
= test_index \
180 * len(test_cases
) // self
.TEST_INDEX_COUNT
181 outer_end_index
= (test_index
+ 1) \
182 * len(test_cases
) // self
.TEST_INDEX_COUNT
183 for outer_index
in range(outer_start_index
, outer_end_index
, len(lst
)):
184 inner_start_index
= outer_index
185 inner_end_index
= min(outer_end_index
,
186 inner_start_index
+ len(lst
))
187 inner_range
= range(inner_start_index
, inner_end_index
)
188 initial_regs
= [0 for i
in range(32)]
189 expected_outputs
= initial_regs
.copy()
191 for i
in inner_range
:
192 for j
in range(arg_in_count
):
194 initial_regs
[reg_num
+ j
] = v
195 expected_outputs
[reg_num
+ j
] = v
196 inputs
= pia
.InstructionInput(ra
=test_cases
[i
][0])
198 inputs
.rb
= test_cases
[i
][1]
199 outputs
= pia_func(inputs
)
200 expected_outputs
[reg_num
] = outputs
.rt
201 reg_num
+= arg_in_count
202 with self
.subTest(inner_range
=inner_range
):
203 sim
= run_tst(program
, initial_regs
, pdecode2
=self
.pdecode2
)
204 for reg_num
in range(32):
205 with self
.subTest(reg_num
=reg_num
):
206 self
.assertEqual(sim
.gpr(reg_num
),
207 SelectableInt(expected_outputs
[reg_num
], 64))
210 def tst_addg6s(self
, test_index
):
211 self
.run_cases(test_index
, self
.addg6s_tst_cases(), 'addg6s', 2)
213 def tst_cdtbcd(self
, test_index
):
214 self
.run_cases(test_index
, self
.bcd_dpd_tst_cases(), 'cdtbcd', 1)
216 def tst_cbcdtd(self
, test_index
):
217 self
.run_cases(test_index
, self
.bcd_dpd_tst_cases(), 'cbcdtd', 1)
220 for i
in range(BCDFullTestCase
.TEST_INDEX_COUNT
):
221 for j
in 'addg6s', 'cdtbcd', 'cbcdtd':
223 def tst_{j}_{i}(self):
225 BCDFullTestCase.test_{j}_{i} = tst_{j}_{i}
228 if __name__
== "__main__":