1 from nmutil
.formaltest
import FHDLTestCase
3 from openpower
.decoder
.power_decoder
import create_pdecode
4 from openpower
.decoder
.power_decoder2
import (PowerDecode2
)
5 from openpower
.simulator
.program
import Program
6 from openpower
.decoder
.selectable_int
import SelectableInt
7 from openpower
.decoder
.isa
.test_runner
import run_tst
8 from hashlib
import sha256
9 from textwrap
import dedent
13 class InstructionInput
:
14 def __init__(self
, ra
=None, rb
=None, rc
=None, immediate
=None, carry
=None, overflow
=None):
18 self
.immediate
= immediate
20 self
.overflow
= overflow
22 class InstructionOutput
:
23 def __init__(self
, rt
=None, overflow
=None, carry
=None, cr0
=None, cr1
=None, cr2
=None,
24 cr3
=None, cr4
=None, cr5
=None, cr6
=None, cr7
=None):
26 self
.overflow
= overflow
45 def unpack_bits(bits
, count
):
46 return tuple(((bits
>> i
) & 1) != 0
47 for i
in reversed(range(count
)))
50 # expressions taken from PowerISA v2.07B section B.2 (page 697 (728))
51 p
, q
, r
, s
, t
, u
, v
, w
, x
, y
= unpack_bits(dpd
, 10)
52 a
= (not s
and v
and w
) or (t
and v
and w
and s
) or (v
and w
and not x
)
53 b
= (p
and s
and x
and not t
) or (p
and not w
) or (p
and not v
)
54 c
= (q
and s
and x
and not t
) or (q
and not w
) or (q
and not v
)
56 e
= (v
and not w
and x
) or (
57 s
and v
and w
and x
) or (not t
and v
and x
and w
)
58 f
= (p
and t
and v
and w
and x
and not s
) or (
59 s
and not x
and v
) or (s
and not v
)
60 g
= (q
and t
and w
and v
and x
and not s
) or (
61 t
and not x
and v
) or (t
and not v
)
63 i
= (t
and v
and w
and x
) or (
64 s
and v
and w
and x
) or (v
and not w
and not x
)
65 j
= (p
and not s
and not t
and w
and v
) or (s
and v
and not w
and x
) or (
66 p
and w
and not x
and v
) or (w
and not v
)
67 k
= (q
and not s
and not t
and v
and w
) or (t
and v
and not w
and x
) or (
68 q
and v
and w
and not x
) or (x
and not v
)
70 return pack_bits(a
, b
, c
, d
, e
, f
, g
, h
, i
, j
, k
, m
)
73 # expressions taken from PowerISA v2.07B section B.1 (page 697 (728))
74 a
, b
, c
, d
, e
, f
, g
, h
, i
, j
, k
, m
= unpack_bits(bcd
, 12)
75 p
= (f
and a
and i
and not e
) or (j
and a
and not i
) or (b
and not a
)
76 q
= (g
and a
and i
and not e
) or (k
and a
and not i
) or (c
and not a
)
78 s
= (j
and not a
and e
and not i
) or (f
and not i
and not e
) or (
79 f
and not a
and not e
) or (e
and i
)
80 t
= (k
and not a
and e
and not i
) or (g
and not i
and not e
) or (
81 g
and not a
and not e
) or (a
and i
)
84 w
= (not e
and j
and not i
) or (e
and i
) or a
85 x
= (not a
and k
and not i
) or (a
and i
) or e
87 return pack_bits(p
, q
, r
, s
, t
, u
, v
, w
, x
, y
)
92 ra
= inputs
.ra
& ((1 << 64) - 1)
94 rt |
= dpd_to_bcd(ra
& 0x3FF)
95 rt |
= dpd_to_bcd((ra
>> 10) & 0x3FF) << 12
96 rt |
= dpd_to_bcd((ra
>> 32) & 0x3FF) << 32
97 rt |
= dpd_to_bcd((ra
>> 42) & 0x3FF) << 44
98 return InstructionOutput(rt
=rt
)
102 ra
= inputs
.ra
& ((1 << 64) - 1)
104 rt |
= bcd_to_dpd(ra
& 0xFFF)
105 rt |
= bcd_to_dpd((ra
>> 12) & 0xFFF) << 10
106 rt |
= bcd_to_dpd((ra
>> 32) & 0xFFF) << 32
107 rt |
= bcd_to_dpd((ra
>> 44) & 0xFFF) << 42
108 return InstructionOutput(rt
=rt
)
112 ra
= inputs
.ra
& ((1 << 64) - 1)
113 rb
= inputs
.rb
& ((1 << 64) - 1)
115 need_sixes
= ((~
sum >> 4) ^
(ra
>> 4) ^
(
116 rb
>> 4)) & 0x1111_1111_1111_1111
118 return InstructionOutput(rt
=rt
)
120 pia
.InstructionInput
= InstructionInput
121 pia
.InstructionOutput
= InstructionOutput
125 MOCK_PIA
= True # until pia is ported to python
129 import power_instruction_analyzer
as pia
132 class BCDFullTestCase(FHDLTestCase
):
133 """test full arbitrary bit patterns, including invalid BCD (not
134 supported by above reference code), against power-instruction-analyzer"""
139 def __init__(self
, *args
, **kwargs
):
140 super().__init
__(*args
, **kwargs
)
141 if BCDFullTestCase
.pdecode2
is None:
142 pdecode
= create_pdecode()
143 BCDFullTestCase
.pdecode2
= PowerDecode2(pdecode
)
146 return int.from_bytes(
147 sha256(bytes(str(v
), encoding
='ascii')).digest(),
151 def addg6s_tst_cases(self
):
153 for i
in range(1024):
155 yield (v
& mask
, (v
>> 64) & mask
)
157 def bcd_dpd_tst_cases(self
):
160 for i
in range(limit
):
162 v
&= mask
# mask to 64-bits
163 # replace lower bits with `i` to ensure we cover all patterns
168 def run_cases(self
, test_index
, test_cases
, instr
, arg_in_count
):
169 pia_func
= getattr(pia
, instr
.replace('.', '_'))
171 for i
in range(0, 32, arg_in_count
):
172 input_args
= ', '.join(str(i
+ j
)
173 for j
in range(arg_in_count
))
174 lst
.append(f
"{instr} {i}, {input_args}")
175 with
Program(lst
, bigendian
=False) as program
:
177 test_cases
= list(test_cases
)
178 outer_start_index
= test_index \
179 * len(test_cases
) // self
.TEST_INDEX_COUNT
180 outer_end_index
= (test_index
+ 1) \
181 * len(test_cases
) // self
.TEST_INDEX_COUNT
182 for outer_index
in range(outer_start_index
, outer_end_index
, len(lst
)):
183 inner_start_index
= outer_index
184 inner_end_index
= min(outer_end_index
,
185 inner_start_index
+ len(lst
))
186 inner_range
= range(inner_start_index
, inner_end_index
)
187 initial_regs
= [0 for i
in range(32)]
188 expected_outputs
= initial_regs
.copy()
190 for i
in inner_range
:
191 for j
in range(arg_in_count
):
193 initial_regs
[reg_num
+ j
] = v
194 expected_outputs
[reg_num
+ j
] = v
195 inputs
= pia
.InstructionInput(ra
=test_cases
[i
][0])
197 inputs
.rb
= test_cases
[i
][1]
198 outputs
= pia_func(inputs
)
199 expected_outputs
[reg_num
] = outputs
.rt
200 reg_num
+= arg_in_count
201 with self
.subTest(inner_range
=inner_range
):
202 sim
= run_tst(program
, initial_regs
, pdecode2
=self
.pdecode2
)
203 for reg_num
in range(32):
204 with self
.subTest(reg_num
=reg_num
):
205 self
.assertEqual(sim
.gpr(reg_num
),
206 SelectableInt(expected_outputs
[reg_num
], 64))
209 def tst_addg6s(self
, test_index
):
210 self
.run_cases(test_index
, self
.addg6s_tst_cases(), 'addg6s', 2)
212 def tst_cdtbcd(self
, test_index
):
213 self
.run_cases(test_index
, self
.bcd_dpd_tst_cases(), 'cdtbcd', 1)
215 def tst_cbcdtd(self
, test_index
):
216 self
.run_cases(test_index
, self
.bcd_dpd_tst_cases(), 'cbcdtd', 1)
219 for i
in range(BCDFullTestCase
.TEST_INDEX_COUNT
):
220 for j
in 'addg6s', 'cdtbcd', 'cbcdtd':
222 def tst_{j}_{i}(self):
224 BCDFullTestCase.test_{j}_{i} = tst_{j}_{i}
227 if __name__
== "__main__":