Signed-off-by: Matheus Tavares Bernardino <matheus.bernardino@oss.qualcomm.com>
---
tests/tcg/hexagon/hex_test.h | 13 +++++++++
tests/tcg/hexagon/hvx_misc.h | 30 ++++++++++++++++++++
tests/tcg/hexagon/fp_hvx.c | 41 +++++++++++++++++++++++++++
tests/tcg/hexagon/fp_hvx_cmp.c | 52 ++++++++++++++++++++++++++++++++++
tests/tcg/hexagon/fp_hvx_cvt.c | 31 ++++++++++++++++++++
5 files changed, 167 insertions(+)
diff --git a/tests/tcg/hexagon/hex_test.h b/tests/tcg/hexagon/hex_test.h
index 79d30ec61c..f86e6e1a69 100644
--- a/tests/tcg/hexagon/hex_test.h
+++ b/tests/tcg/hexagon/hex_test.h
@@ -126,6 +126,19 @@ const uint16_t HF_small_neg = 0x8010;
const uint16_t HF_any = 0x3c00;
const uint16_t HF_neg_two = 0xc000;
+const uint16_t BF_INF = 0x7f80;
+const uint16_t BF_INF_neg = 0xff80;
+const uint16_t BF_QNaN = 0x7fc0;
+const uint16_t BF_SNaN = 0x7f81;
+const uint16_t BF_QNaN_neg = 0xffc0;
+const uint16_t BF_SNaN_neg = 0xff81;
+const uint16_t BF_HEX_NaN = 0x7fff;
+const uint16_t BF_zero = 0x0000;
+const uint16_t BF_zero_neg = 0x8000;
+const uint16_t BF_one = 0x3f80;
+const uint16_t BF_two = 0x4000;
+const uint16_t BF_four = 0x4080;
+
const uint32_t SF_INF = 0x7f800000;
const uint32_t SF_INF_neg = 0xff800000;
const uint32_t SF_QNaN = 0x7fc00000;
diff --git a/tests/tcg/hexagon/hvx_misc.h b/tests/tcg/hexagon/hvx_misc.h
index 43de20da6a..c21ea975c1 100644
--- a/tests/tcg/hexagon/hvx_misc.h
+++ b/tests/tcg/hexagon/hvx_misc.h
@@ -41,6 +41,7 @@ typedef union {
uint16_t uh[MAX_VEC_SIZE_BYTES / 2];
uint16_t hf[MAX_VEC_SIZE_BYTES / 2]; /* convenience alias */
int16_t h[MAX_VEC_SIZE_BYTES / 2];
+ uint16_t bf[MAX_VEC_SIZE_BYTES / 2];
uint8_t ub[MAX_VEC_SIZE_BYTES / 1];
int8_t b[MAX_VEC_SIZE_BYTES / 1];
} MMVector;
@@ -73,6 +74,7 @@ CHECK_OUTPUT_FUNC(uh, 2)
CHECK_OUTPUT_FUNC(hf, 2)
CHECK_OUTPUT_FUNC(ub, 1)
CHECK_OUTPUT_FUNC(b, 1)
+CHECK_OUTPUT_FUNC(bf, 2)
static inline void init_buffers(void)
{
@@ -97,6 +99,12 @@ static const uint32_t FP_VALUES[] = {
};
#define FP_VALUES_MAX ARRAY_SIZE(FP_VALUES)
+static const uint16_t BF_VALUES[] = {
+ BF_INF, BF_INF_neg, BF_QNaN, BF_SNaN, BF_QNaN_neg, BF_SNaN_neg,
+ BF_HEX_NaN, BF_zero, BF_zero_neg, BF_one, BF_two, BF_four,
+};
+#define BF_VALUES_MAX ARRAY_SIZE(BF_VALUES)
+
static inline void init_buffers_fp(void)
{
_Static_assert(BUFSIZE * (MAX_VEC_SIZE_BYTES / 4) >
@@ -116,6 +124,25 @@ static inline void init_buffers_fp(void)
}
}
+static inline void init_buffers_bf(void)
+{
+ _Static_assert(BUFSIZE * (MAX_VEC_SIZE_BYTES / 2) >
+ BF_VALUES_MAX * BF_VALUES_MAX,
+ "test arrays can't fit all BF_VALUES combinations");
+ int counter1 = 0, counter2 = 0;
+ for (int i = 0; i < BUFSIZE; i++) {
+ for (int j = 0; j < MAX_VEC_SIZE_BYTES / 2; j++) {
+ buffer0[i].bf[j] = BF_VALUES[counter1];
+ buffer1[i].bf[j] = BF_VALUES[counter2];
+ counter2++;
+ if (counter2 == BF_VALUES_MAX) {
+ counter2 = 0;
+ counter1 = (counter1 + 1) % BF_VALUES_MAX;
+ }
+ }
+ }
+}
+
#define VEC_OP1(ASM, EL, IN, OUT) \
asm("v2 = vmem(%0 + #0)\n\t" \
"v2" #EL " = " #ASM "(v2" #EL ")\n\t" \
@@ -212,10 +239,13 @@ static inline void test_##NAME(bool invert) \
#define float_sf(x) ({ typeof(x) _x = (x); *((float *)&(_x)); })
#define float_hf(x) ({ typeof(x) _x = (x); *((_Float16 *) &(_x)); })
+#define float_bf(x) ({ uint32_t _u = ((uint32_t)(x)) << 16; *((float *)&(_u)); })
#define raw_sf(x) ({ typeof(x) _x = (x); *((uint32_t *)&(_x)); })
#define raw_hf(x) ({ typeof(x) _x = (x); *((uint16_t *)&(_x)); })
+#define raw_bf(x) ({ typeof(x) _x = (x); (uint16_t)(*((uint32_t *)&(_x)) >> 16); })
#define float_hf_to_sf(x) ((float)x)
#define bytes_hf 2
#define bytes_sf 4
+#define bytes_bf 2
#endif
diff --git a/tests/tcg/hexagon/fp_hvx.c b/tests/tcg/hexagon/fp_hvx.c
index 46f49c0d3c..f22514b4bf 100644
--- a/tests/tcg/hexagon/fp_hvx.c
+++ b/tests/tcg/hexagon/fp_hvx.c
@@ -29,6 +29,7 @@ int err;
#define CHECK_NAN(A, DEF_NAN) (isnan(A) ? DEF_NAN : (A))
#define NAN_SF float_sf(0x7FFFFFFF)
#define NAN_HF float_hf(0x7FFF)
+#define NAN_BF float_hf(0x7FFF)
/******************************************************************************
* Binary operations
@@ -91,11 +92,43 @@ DEF_TEST_OP_2(vmpy, MULT_HF, hf, hf);
#define MAX_HF(X, Y) MAX(X, Y, NAN_HF)
#define MIN_SF(X, Y) MIN(X, Y, NAN_SF)
#define MAX_SF(X, Y) MAX(X, Y, NAN_SF)
+#define MIN_BF(X, Y) MIN(X, Y, NAN_BF)
+#define MAX_BF(X, Y) MAX(X, Y, NAN_BF)
DEF_TEST_OP_2(vfmin, MIN_SF, sf, sf);
DEF_TEST_OP_2(vfmax, MAX_SF, sf, sf);
DEF_TEST_OP_2(vfmin, MIN_HF, hf, hf);
DEF_TEST_OP_2(vfmax, MAX_HF, hf, hf);
+DEF_TEST_OP_2(vmin, MIN_BF, bf, bf);
+DEF_TEST_OP_2(vmax, MAX_BF, bf, bf);
+
+#define DEF_TEST_OP_2_INTERLEAVED(vop, op, type_res, type_arg) \
+ static void test_##vop##_##type_res##_##type_arg(void) \
+ { \
+ memset(expect, 0xff, sizeof(expect)); \
+ memset(output, 0xff, sizeof(output)); \
+ for (int i = 0; i < BUFSIZE / 2; i++) { \
+ HVX_VectorPair *hvx_output = (HVX_VectorPair *)&output[2 * i]; \
+ HVX_Vector hvx_buffer0 = *(HVX_Vector *)&buffer0[i]; \
+ HVX_Vector hvx_buffer1 = *(HVX_Vector *)&buffer1[i]; \
+ *hvx_output = \
+ Q6_W##type_res##_##vop##_V##type_arg##V##type_arg(hvx_buffer0, \
+ hvx_buffer1); \
+ for (int j = 0; j < MAX_VEC_SIZE_BYTES / bytes_##type_res; j++) { \
+ expect[2 * i].type_res[j] = \
+ raw_##type_res(op(float_##type_arg(buffer0[i].type_arg[2 * j]), \
+ float_##type_arg(buffer1[i].type_arg[2 * j]))); \
+ expect[2 * i + 1].type_res[j] = \
+ raw_##type_res(op(float_##type_arg(buffer0[i].type_arg[2 * j + 1]), \
+ float_##type_arg(buffer1[i].type_arg[2 * j + 1]))); \
+ } \
+ } \
+ check_output_##type_res(__LINE__, BUFSIZE); \
+ }
+
+DEF_TEST_OP_2_INTERLEAVED(vadd, SUM_SF, sf, bf);
+DEF_TEST_OP_2_INTERLEAVED(vsub, SUB_SF, sf, bf);
+DEF_TEST_OP_2_INTERLEAVED(vmpy, MULT_SF, sf, bf);
/******************************************************************************
* Other tests
@@ -180,6 +213,14 @@ int main(void)
test_vfmax_sf_sf();
test_vfmax_hf_hf();
+ /* bfloat */
+ init_buffers_bf();
+ test_vmin_bf_bf();
+ test_vmax_bf_bf();
+ test_vadd_sf_bf();
+ test_vsub_sf_bf();
+ test_vmpy_sf_bf();
+
puts(err ? "FAIL" : "PASS");
return err ? 1 : 0;
}
diff --git a/tests/tcg/hexagon/fp_hvx_cmp.c b/tests/tcg/hexagon/fp_hvx_cmp.c
index c4e1c81ce5..4417e736f9 100644
--- a/tests/tcg/hexagon/fp_hvx_cmp.c
+++ b/tests/tcg/hexagon/fp_hvx_cmp.c
@@ -22,9 +22,11 @@ int err;
#define MAX_TESTS_hf (MAX_VEC_SIZE_BYTES / 2)
#define MAX_TESTS_sf (MAX_VEC_SIZE_BYTES / 4)
+#define MAX_TESTS_bf (MAX_VEC_SIZE_BYTES / 4)
#define TRUE_MASK_sf 0xffffffff
#define TRUE_MASK_hf 0xffff
+#define TRUE_MASK_bf 0xffff
static const char *comparisons[MAX_TESTS_sf][2];
static HVX_Vector *hvx_output = (HVX_Vector *)&output[0];
@@ -160,6 +162,55 @@ static void test_cmp_hf(void)
CHECK(hf, 2);
}
+
+static void test_cmp_bf(void)
+{
+ /*
+ * General ordering for bf:
+ * QNaN > SNaN > +Inf > numbers > -Inf > SNaN_neg > QNaN_neg
+ */
+
+ /* Test equality */
+ PREP_TEST();
+ ADD_TEST_CMP(bf, 0, 0, false);
+ ADD_TEST_CMP(bf, BF_SNaN, BF_SNaN, false);
+ CHECK(bf, 2);
+
+ /* Common numbers */
+ PREP_TEST();
+ TEST_CMP_GT(bf, raw_hf((_Float16)2.2), raw_hf((_Float16)2.1));
+ TEST_CMP_GT(bf, raw_hf((_Float16)0), raw_hf((_Float16)-2.2));
+ CHECK(bf, 2);
+
+ /* Infinity vs Infinity/NaN */
+ PREP_TEST();
+ TEST_CMP_GT(bf, BF_QNaN, BF_INF);
+ TEST_CMP_GT(bf, BF_SNaN, BF_INF);
+ TEST_CMP_GT(bf, BF_INF, BF_INF_neg);
+ TEST_CMP_GT(bf, BF_INF, BF_SNaN_neg);
+ TEST_CMP_GT(bf, BF_INF, BF_QNaN_neg);
+ TEST_CMP_GT(bf, BF_INF_neg, BF_SNaN_neg);
+ TEST_CMP_GT(bf, BF_INF_neg, BF_QNaN_neg);
+ TEST_CMP_GT(bf, BF_SNaN, BF_INF_neg);
+ TEST_CMP_GT(bf, BF_QNaN, BF_INF_neg);
+ CHECK(bf, 2);
+
+ /* NaN vs NaN */
+ PREP_TEST();
+ TEST_CMP_GT(bf, BF_QNaN, BF_SNaN);
+ TEST_CMP_GT(bf, BF_SNaN, BF_SNaN_neg);
+ TEST_CMP_GT(bf, BF_SNaN_neg, BF_QNaN_neg);
+ CHECK(bf, 2);
+
+ /* NaN vs non-NaN */
+ PREP_TEST();
+ TEST_CMP_GT(bf, BF_QNaN, BF_one);
+ TEST_CMP_GT(bf, BF_SNaN, BF_one);
+ TEST_CMP_GT(bf, BF_one, BF_QNaN_neg);
+ TEST_CMP_GT(bf, BF_one, BF_SNaN_neg);
+ CHECK(bf, 2);
+}
+
static void test_cmp_variants(void)
{
HVX_VectorPred true_pred, false_pred, pred;
@@ -220,6 +271,7 @@ int main(void)
test_cmp_sf();
test_cmp_hf();
+ test_cmp_bf();
test_cmp_variants();
puts(err ? "FAIL" : "PASS");
diff --git a/tests/tcg/hexagon/fp_hvx_cvt.c b/tests/tcg/hexagon/fp_hvx_cvt.c
index 71c3f0fd4f..bd8d39d6b6 100644
--- a/tests/tcg/hexagon/fp_hvx_cvt.c
+++ b/tests/tcg/hexagon/fp_hvx_cvt.c
@@ -19,6 +19,8 @@ int err;
#include "hvx_misc.h"
#include "hex_test.h"
+#define NAN_BF 0x7FFF
+
#define TEST_EXP(TO, FROM, VAL, EXP) do { \
((MMVector *)&buffer)->FROM[index] = VAL; \
expect[0].TO[index] = EXP; \
@@ -172,6 +174,34 @@ DEF_TEST_VCONV(sf, w, { \
TEST_EXP(sf, w, 16777219, raw_sf((float)16777220)); /* rounds UP */ \
})
+#define TEST_EXP_BF(VAL, EXP) do { \
+ ((MMVector *)&buffers[1])->sf[index] = VAL; \
+ ((MMVector *)&buffers[0])->sf[index] = VAL; \
+ expect[0].bf[2 * index] = EXP; \
+ expect[0].bf[2 * index + 1] = EXP; \
+ index++; \
+} while (0)
+
+static void test_vconv_bf_sf(void)
+{
+ HVX_Vector *hvx_output = (HVX_Vector *)&output[0];
+ HVX_Vector buffers[2];
+ int index = 0;
+ memset(&buffers, 0, sizeof(buffers));
+ memset(expect, 0, sizeof(expect));
+
+ TEST_EXP_BF(SF_QNaN, NAN_BF);
+ TEST_EXP_BF(SF_SNaN, NAN_BF);
+ TEST_EXP_BF(SF_QNaN_neg, NAN_BF);
+ TEST_EXP_BF(SF_INF, BF_INF);
+ TEST_EXP_BF(SF_INF_neg, BF_INF_neg);
+ TEST_EXP_BF(SF_one, BF_one);
+ TEST_EXP_BF(SF_zero_neg, BF_zero_neg);
+
+ *hvx_output = Q6_Vbf_vcvt_VsfVsf(buffers[0], buffers[1]);
+ check_output_hf(__LINE__, 1);
+}
+
int main(void)
{
test_vcvt_uh_hf();
@@ -182,6 +212,7 @@ int main(void)
test_vconv_sf_w();
test_vconv_h_hf();
test_vconv_hf_h();
+ test_vconv_bf_sf();
puts(err ? "FAIL" : "PASS");
return err ? 1 : 0;
--
2.37.2