master
c 219 lines 6.75 KB
Raw
1 /*
2 * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
3 *
4 * SPDX-License-Identifier: GPL-2.0-or-later
5 */
6
7 #include <stdio.h>
8 #include <stdint.h>
9 #include <stdbool.h>
10 #include <string.h>
11 #include <hexagon_types.h>
12 #include <hvx_hexagon_protos.h>
13
14 #if __HEXAGON_ARCH__ > 75
15 #error "After v75, compiler will replace some FP HVX instructions."
16 #endif
17
18 int err;
19 #include "hvx_misc.h"
20 #include "hex_test.h"
21
22 #define NAN_BF 0x7FFF
23
24 #define TEST_EXP(TO, FROM, VAL, EXP) do { \
25 ((MMVector *)&buffer)->FROM[index] = VAL; \
26 expect[0].TO[index] = EXP; \
27 index++; \
28 } while (0)
29
30 #define DEF_TEST_CVT(TO, FROM, TESTS) \
31 static void test_vcvt_##TO##_##FROM(void) \
32 { \
33 HVX_Vector *hvx_output = (HVX_Vector *)&output[0]; \
34 HVX_Vector buffer; \
35 int index = 0; \
36 memset(&buffer, 0, sizeof(buffer)); \
37 memset(expect, 0, sizeof(expect)); \
38 TESTS \
39 * hvx_output = Q6_V##TO##_vcvt_V##FROM(buffer); \
40 check_output_##TO(__LINE__, 1); \
41 }
42
43 DEF_TEST_CVT(uh, hf, { \
44 TEST_EXP(uh, hf, HF_QNaN, UINT16_MAX); \
45 TEST_EXP(uh, hf, HF_SNaN, UINT16_MAX); \
46 TEST_EXP(uh, hf, HF_QNaN_neg, UINT16_MAX); \
47 TEST_EXP(uh, hf, HF_INF, UINT16_MAX); \
48 TEST_EXP(uh, hf, HF_INF_neg, 0); \
49 TEST_EXP(uh, hf, HF_neg_two, 0); \
50 TEST_EXP(uh, hf, HF_zero_neg, 0); \
51 TEST_EXP(uh, hf, raw_hf((_Float16)2.1), 2); \
52 TEST_EXP(uh, hf, HF_one_recip, 1); \
53 })
54
55 DEF_TEST_CVT(h, hf, { \
56 TEST_EXP(h, hf, HF_QNaN, INT16_MAX); \
57 TEST_EXP(h, hf, HF_SNaN, INT16_MAX); \
58 TEST_EXP(h, hf, HF_QNaN_neg, INT16_MAX); \
59 TEST_EXP(h, hf, HF_INF, INT16_MAX); \
60 TEST_EXP(h, hf, HF_INF_neg, INT16_MIN); \
61 TEST_EXP(h, hf, HF_neg_two, -2); \
62 TEST_EXP(h, hf, HF_zero_neg, 0); \
63 TEST_EXP(h, hf, raw_hf((_Float16)2.1), 2); \
64 TEST_EXP(h, hf, HF_one_recip, 1); \
65 })
66
67 /*
68 * Some cvt operations take two vectors as input and perform the following:
69 * VdV.TO[4*i] = OP(VuV.FROM[2*i]);
70 * VdV.TO[4*i+1] = OP(VuV.FROM[2*i+1]);
71 * VdV.TO[4*i+2] = OP(VvV.FROM[2*i]);
72 * VdV.TO[4*i+3] = OP(VvV.FROM[2*i+1]))
73 * We use bf_index and index in a way that the tests are always done either
74 * using the first or third line of the above snippet.
75 */
76 #define TEST_EXP_2(TO, FROM, VAL, EXP) do { \
77 ((MMVector *)&buffers[bf_index])->FROM[2 * index] = VAL; \
78 expect[0].TO[(4 * index) + (2 * bf_index)] = EXP; \
79 index++; \
80 bf_index = (bf_index + 1) % 2; \
81 } while (0)
82
83 #define DEF_TEST_CVT_2(TO, FROM, TESTS) \
84 static void test_vcvt_##TO##_##FROM(void) \
85 { \
86 HVX_Vector *hvx_output = (HVX_Vector *)&output[0]; \
87 HVX_Vector buffers[2]; \
88 int index = 0, bf_index = 0; \
89 memset(&buffers, 0, sizeof(buffers)); \
90 memset(expect, 0, sizeof(expect)); \
91 TESTS \
92 * hvx_output = Q6_V##TO##_vcvt_V##FROM##V##FROM(buffers[0], buffers[1]); \
93 check_output_##TO(__LINE__, 1); \
94 }
95
96 DEF_TEST_CVT_2(ub, hf, { \
97 TEST_EXP_2(ub, hf, HF_QNaN, UINT8_MAX); \
98 TEST_EXP_2(ub, hf, HF_SNaN, UINT8_MAX); \
99 TEST_EXP_2(ub, hf, HF_QNaN_neg, UINT8_MAX); \
100 TEST_EXP_2(ub, hf, HF_INF, UINT8_MAX); \
101 TEST_EXP_2(ub, hf, HF_INF_neg, 0); \
102 TEST_EXP_2(ub, hf, HF_small_neg, 0); \
103 TEST_EXP_2(ub, hf, HF_neg_two, 0); \
104 TEST_EXP_2(ub, hf, HF_zero_neg, 0); \
105 TEST_EXP_2(ub, hf, raw_hf((_Float16)2.1), 2); \
106 TEST_EXP_2(ub, hf, HF_one_recip, 1); \
107 })
108
109 DEF_TEST_CVT_2(b, hf, { \
110 TEST_EXP_2(b, hf, HF_QNaN, INT8_MAX); \
111 TEST_EXP_2(b, hf, HF_SNaN, INT8_MAX); \
112 TEST_EXP_2(b, hf, HF_QNaN_neg, INT8_MAX); \
113 TEST_EXP_2(b, hf, HF_INF, INT8_MAX); \
114 TEST_EXP_2(b, hf, HF_INF_neg, INT8_MIN); \
115 TEST_EXP_2(b, hf, HF_small_neg, 0); \
116 TEST_EXP_2(b, hf, HF_neg_two, -2); \
117 TEST_EXP_2(b, hf, HF_zero_neg, 0); \
118 TEST_EXP_2(b, hf, raw_hf((_Float16)2.1), 2); \
119 TEST_EXP_2(b, hf, HF_one_recip, 1); \
120 })
121
122 #define DEF_TEST_VCONV(TO, FROM, TESTS) \
123 static void test_vconv_##TO##_##FROM(void) \
124 { \
125 HVX_Vector *hvx_output = (HVX_Vector *)&output[0]; \
126 HVX_Vector buffer; \
127 int index = 0; \
128 memset(&buffer, 0, sizeof(buffer)); \
129 memset(expect, 0, sizeof(expect)); \
130 TESTS \
131 * hvx_output = Q6_V##TO##_equals_V##FROM(buffer); \
132 check_output_##TO(__LINE__, 1); \
133 }
134
135 DEF_TEST_VCONV(w, sf, { \
136 TEST_EXP(w, sf, SF_QNaN, INT32_MAX); \
137 TEST_EXP(w, sf, SF_SNaN, INT32_MAX); \
138 TEST_EXP(w, sf, SF_QNaN_neg, INT32_MIN); \
139 TEST_EXP(w, sf, SF_INF, INT32_MAX); \
140 TEST_EXP(w, sf, SF_INF_neg, INT32_MIN); \
141 TEST_EXP(w, sf, SF_small_neg, 0); \
142 TEST_EXP(w, sf, SF_neg_two, -2); \
143 TEST_EXP(w, sf, SF_zero_neg, 0); \
144 TEST_EXP(w, sf, raw_sf(2.1f), 2); \
145 TEST_EXP(w, sf, raw_sf(2.8f), 2); \
146 })
147
148 DEF_TEST_VCONV(h, hf, { \
149 TEST_EXP(h, hf, HF_QNaN, INT16_MAX); \
150 TEST_EXP(h, hf, HF_SNaN, INT16_MAX); \
151 TEST_EXP(h, hf, HF_QNaN_neg, INT16_MIN); \
152 TEST_EXP(h, hf, HF_INF, INT16_MAX); \
153 TEST_EXP(h, hf, HF_INF_neg, INT16_MIN); \
154 TEST_EXP(h, hf, HF_small_neg, 0); \
155 TEST_EXP(h, hf, HF_neg_two, -2); \
156 TEST_EXP(h, hf, HF_zero_neg, 0); \
157 TEST_EXP(h, hf, raw_hf((_Float16)2.1), 2); \
158 TEST_EXP(h, hf, raw_hf((_Float16)2.8), 2); \
159 })
160
161 DEF_TEST_VCONV(hf, h, { \
162 TEST_EXP(hf, h, 0, HF_zero); \
163 TEST_EXP(hf, h, 2, HF_two); \
164 TEST_EXP(hf, h, -2, HF_neg_two); \
165 TEST_EXP(hf, h, 2049, raw_hf((_Float16)2048)); /* rounds DOWN */ \
166 TEST_EXP(hf, h, 2051, raw_hf((_Float16)2052)); /* rounds UP */ \
167 })
168
169 DEF_TEST_VCONV(sf, w, { \
170 TEST_EXP(sf, w, 0, SF_zero); \
171 TEST_EXP(sf, w, 2, SF_two); \
172 TEST_EXP(sf, w, -2, SF_neg_two); \
173 TEST_EXP(sf, w, 16777217, raw_sf((float)16777216)); /* rounds DOWN */ \
174 TEST_EXP(sf, w, 16777219, raw_sf((float)16777220)); /* rounds UP */ \
175 })
176
177 #define TEST_EXP_BF(VAL, EXP) do { \
178 ((MMVector *)&buffers[1])->sf[index] = VAL; \
179 ((MMVector *)&buffers[0])->sf[index] = VAL; \
180 expect[0].bf[2 * index] = EXP; \
181 expect[0].bf[2 * index + 1] = EXP; \
182 index++; \
183 } while (0)
184
185 static void test_vconv_bf_sf(void)
186 {
187 HVX_Vector *hvx_output = (HVX_Vector *)&output[0];
188 HVX_Vector buffers[2];
189 int index = 0;
190 memset(&buffers, 0, sizeof(buffers));
191 memset(expect, 0, sizeof(expect));
192
193 TEST_EXP_BF(SF_QNaN, NAN_BF);
194 TEST_EXP_BF(SF_SNaN, NAN_BF);
195 TEST_EXP_BF(SF_QNaN_neg, NAN_BF);
196 TEST_EXP_BF(SF_INF, BF_INF);
197 TEST_EXP_BF(SF_INF_neg, BF_INF_neg);
198 TEST_EXP_BF(SF_one, BF_one);
199 TEST_EXP_BF(SF_zero_neg, BF_zero_neg);
200
201 *hvx_output = Q6_Vbf_vcvt_VsfVsf(buffers[0], buffers[1]);
202 check_output_hf(__LINE__, 1);
203 }
204
205 int main(void)
206 {
207 test_vcvt_uh_hf();
208 test_vcvt_h_hf();
209 test_vcvt_ub_hf();
210 test_vcvt_b_hf();
211 test_vconv_w_sf();
212 test_vconv_sf_w();
213 test_vconv_h_hf();
214 test_vconv_hf_h();
215 test_vconv_bf_sf();
216
217 puts(err ? "FAIL" : "PASS");
218 return err ? 1 : 0;
219 }