fecac44e51fe24f70bbc93838f144907c40ec034
[openpower-isa.git] / src / openpower / test / alu / maddsubrs_cases.py
1 from openpower.insndb.asm import SVP64Asm
2 from openpower.test.common import TestAccumulatorBase, skip_case
3 from openpower.endian import bigendian
4 from openpower.simulator.program import Program
5 from openpower.decoder.isa.caller import SVP64State
6 from openpower.test.state import ExpectedState
7 from nmutil.sim_util import hash_256
8 import math
9 from fractions import Fraction
10
11
12 class MADDSUBRSTestCase(TestAccumulatorBase):
13 def case_0_maddsubrs(self):
14 isa = SVP64Asm(["maddsubrs 1,10,14,11"])
15 lst = list(isa)
16
17 initial_regs = [0] * 32
18 initial_regs[1] = 0x00000a71
19 initial_regs[10] = 0x0000e6b8
20 initial_regs[11] = 0x00002d41
21
22 e = ExpectedState(pc=4)
23 e.intregs[1] = 0x0000aa86
24 e.intregs[2] = 0xffffffffffff643e
25 e.intregs[10] = 0x0000e6b8
26 e.intregs[11] = 0x00002d41
27 self.add_case(Program(lst, bigendian), initial_regs, expected=e)
28
29 def case_1_maddsubrs(self):
30 isa = SVP64Asm(["maddsubrs 1,10,0,11"])
31 lst = list(isa)
32
33 initial_regs = [0] * 32
34 initial_regs[1] = 0x00000a71
35 initial_regs[10] = 0x0000e6b8
36 initial_regs[11] = 0x00002d41
37
38 e = ExpectedState(pc=4)
39 e.intregs[1] = 0x2aa17069
40 e.intregs[2] = 0xffffffffd90f96f9
41 e.intregs[10] = 0x0000e6b8
42 e.intregs[11] = 0x00002d41
43 self.add_case(Program(lst, bigendian), initial_regs, expected=e)
44
45 def case_2_maddsubrs(self):
46 isa = SVP64Asm(["maddsubrs 1,10,2,11"])
47 lst = list(isa)
48
49 initial_regs = [0] * 32
50 initial_regs[1] = 0x100000000
51 initial_regs[10] = 0x000000003
52 initial_regs[11] = 0x10000000
53
54 e = ExpectedState(pc=4)
55 e.intregs[1] = 0x40000000c000000
56 e.intregs[2] = 0x3fffffff4000000
57 e.intregs[10] = 0x00000003
58 e.intregs[11] = 0x10000000
59 self.add_case(Program(lst, bigendian), initial_regs, expected=e)
60
61 def case_3_maddsubrs(self):
62 isa = SVP64Asm(["maddsubrs 1,10,16,11"])
63 lst = list(isa)
64
65 initial_regs = [0] * 32
66 initial_regs[1] = 0x100000000
67 initial_regs[10] = 0x000000003
68 initial_regs[11] = 0x10000000
69
70 e = ExpectedState(pc=4)
71 e.intregs[1] = 0x100000003000
72 e.intregs[2] = 0x0fffffffd000
73 e.intregs[10] = 0x00000003
74 e.intregs[11] = 0x10000000
75 self.add_case(Program(lst, bigendian), initial_regs, expected=e)
76
77 def case_4_maddsubrs(self):
78 isa = SVP64Asm(["maddsubrs 1,10,1,11"])
79 lst = list(isa)
80
81 initial_regs = [0] * 32
82 initial_regs[1] = 0x100000000
83 initial_regs[10] = 0x000000003
84 initial_regs[11] = 0xff0000000
85
86 e = ExpectedState(pc=4)
87 e.intregs[1] = 0xf8000017e8000000
88 e.intregs[2] = 0xf7ffffe818000000
89 e.intregs[10] = 0x000000003
90 e.intregs[11] = 0xff0000000
91 self.add_case(Program(lst, bigendian), initial_regs, expected=e)
92
93 def case_maddsubrs_16bit_s14(self):
94 p = Program(list(SVP64Asm([
95 "sv.maddsubrs/w=16 *10,*20,14,*30",
96 ])), bigendian)
97
98 initial_regs = [0] * 32
99
100 # use somewhat reasonable i16 values since we're working in
101 # 2.14-bit fixed-point
102
103 initial_regs[10] = 0x1000_2000_3000_4000 # 0x0.4, 0x0.8, 0x0.c, 0x1.0
104
105 # 0x0.48d0, -0x0.0490, 0x0.d158, -0x0.48d4
106 initial_regs[20] = 0x1234_fedc_3456_edcb
107 cospi_16_64 = 11585 # from libvpx -- 0x0.b504 ~ 0.70709 ~ cos(pi/4)
108 initial_regs[30] = cospi_16_64 * 0x1_0001_0001_0001 # splat 4x
109
110 svstate = SVP64State()
111 svstate.vl = 4
112 svstate.maxvl = 4
113
114 e = ExpectedState(pc=8, int_regs=initial_regs)
115 e.intregs[10] = 0
116 e.intregs[11] = 0
117 for i in range(svstate.vl):
118 rt = (initial_regs[10] >> (i * 16)) & 0xFFFF # extract element
119 rt -= (rt & 0x8000) << 1 # sign extend rt
120 ra = (initial_regs[20] >> (i * 16)) & 0xFFFF
121 ra -= (ra & 0x8000) << 1 # sign extend ra
122 rb = (initial_regs[30] >> (i * 16)) & 0xFFFF
123 rb -= (rb & 0x8000) << 1 # sign extend rb
124 s = rt + ra
125 d = rt - ra
126 # f64 is big enough to represent all relevant values exactly,
127 # so we can use float
128 rt = math.floor((s * rb) / (2 ** 14) + 0.5) # mul & round & shr
129 rs = math.floor((d * rb) / (2 ** 14) + 0.5)
130 e.intregs[10] |= (rt & 0xFFFF) << (16 * i) # insert element
131 e.intregs[11] |= (rs & 0xFFFF) << (16 * i)
132
133 # asserts so you can read the expected values
134 assert e.intregs[10] == 0x182f_15d2_46f2_2061
135 assert e.intregs[11] == 0xfe71_176f_fcef_3a21
136
137 self.add_case(p, initial_regs, expected=e, initial_svstate=svstate)
138
139 def maddsubrs_many_helper(self, width, shift, prog, case_idx):
140 # if {'width': width, 'shift': shift, 'case_idx': case_idx} \
141 # != {'width': 8, 'shift': 1, 'case_idx': 0}:
142 # return # for debugging
143 gprs = [0] * 32
144 # make some reproducible random inputs
145 k = f"maddsubrs {width} {shift} {case_idx}"
146 gprs[10] = hash_256(k + " r10") % 2**64
147 gprs[20] = hash_256(k + " r20") % 2**64
148 gprs[30] = hash_256(k + " r30") % 2**64
149
150 svstate = SVP64State()
151 svstate.vl = 64 // width # one full 64-bit register
152 svstate.maxvl = 64 // width
153
154 e = ExpectedState(pc=8, int_regs=gprs)
155 e.intregs[10] = 0
156 e.intregs[11] = 0
157 for i in range(svstate.vl):
158 # extract elements
159 rt = (gprs[10] >> (i * width)) % 2 ** width
160 ra = (gprs[20] >> (i * width)) % 2 ** width
161 rb = (gprs[30] >> (i * width)) % 2 ** width
162 if rt >= 2 ** (width - 1):
163 rt -= 2 ** width # sign extend rt
164 if ra >= 2 ** (width - 1):
165 ra -= 2 ** width # sign extend ra
166 if rb >= 2 ** (width - 1):
167 rb -= 2 ** width # sign extend rb
168 s = rt + ra
169 d = rt - ra
170 factor = Fraction(1, 2 ** shift) # shr factor
171 round_up = Fraction(1, 2)
172 # mul & round & shr
173 rt = math.floor((s * rb) * factor + round_up)
174 rs = math.floor((d * rb) * factor + round_up)
175 # insert elements
176 e.intregs[10] |= (rt % 2 ** width) << (width * i)
177 e.intregs[11] |= (rs % 2 ** width) << (width * i)
178
179 with self.subTest(
180 width=width, shift=shift, case_idx=case_idx,
181 RT_in=hex(gprs[10]), RA_in=hex(gprs[20]), RB_in=hex(gprs[30]),
182 expected_RT=hex(e.intregs[10]), expected_RS=hex(e.intregs[11]),
183 ):
184 self.add_case(prog, gprs, expected=e, initial_svstate=svstate)
185
186 def case_maddsubrs_many(self):
187 for width in 8, 16, 32, 64:
188 shift_end = min(32, width)
189 for shift in range(0, shift_end, shift_end // 8):
190 w = "" if width == 64 else f"/w={width}"
191 prog = Program(list(SVP64Asm([
192 f"sv.maddsubrs{w} *10,*20,{shift},*30",
193 ])), bigendian)
194
195 for case_idx in range(25):
196 self.maddsubrs_many_helper(width, shift, prog, case_idx)
197
198 def case_0_maddrs(self):
199 isa = SVP64Asm(["maddsubrs 1,10,0,11",
200 "maddrs 1,10,0,12"])
201 lst = list(isa)
202
203 initial_regs = [0] * 32
204 initial_regs[1] = 0x00000a71
205 initial_regs[10] = 0x0000e6b8
206 initial_regs[11] = 0x00002d41
207 initial_regs[12] = 0x00000d00
208
209 e = ExpectedState(pc=8)
210 e.intregs[1] = 0x3658c869
211 e.intregs[2] = 0xffffffffcd583ef9
212 e.intregs[10] = 0x0000e6b8
213 e.intregs[11] = 0x00002d41
214 e.intregs[12] = 0x00000d00
215 self.add_case(Program(lst, bigendian), initial_regs, expected=e)
216
217 def case_1_maddrs(self):
218 isa = SVP64Asm(["maddsubrs 1,10,0,11",
219 "maddrs 1,10,14,12"])
220 lst = list(isa)
221
222 initial_regs = [0] * 32
223 initial_regs[1] = 0x00000a71
224 initial_regs[10] = 0x0000e6b8
225 initial_regs[11] = 0x00002d41
226 initial_regs[12] = 0x00000d00
227
228 e = ExpectedState(pc=8)
229 e.intregs[1] = 0x0000d963
230 e.intregs[2] = 0xffffffffffff3561
231 e.intregs[10] = 0x0000e6b8
232 e.intregs[11] = 0x00002d41
233 e.intregs[12] = 0x00000d00
234 self.add_case(Program(lst, bigendian), initial_regs, expected=e)