From: Matheus Tavares Bernardino <[email protected]>
Reviewed-by: Taylor Simpson <[email protected]> Signed-off-by: Matheus Tavares Bernardino <[email protected]> Reviewed-by: Brian Cain <[email protected]> Link: https://lore.kernel.org/qemu-devel/392114c4c16e6f7f2835a6513987aafea82b565c.1776339451.git.matheus.bernard...@oss.qualcomm.com Signed-off-by: Brian Cain <[email protected]> --- 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 | 51 ++++++++++++++++++++++++++++++++++ tests/tcg/hexagon/fp_hvx_cvt.c | 31 +++++++++++++++++++++ 5 files changed, 166 insertions(+) diff --git a/tests/tcg/hexagon/hex_test.h b/tests/tcg/hexagon/hex_test.h index 79d30ec61c6..f86e6e1a69e 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 43de20da6ac..c21ea975c16 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 dee0781bd72..4543a0aa8c7 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 8068d1c3ee4..63fb423941b 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 / 2) #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,54 @@ 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, BF_two, BF_one); + TEST_CMP_GT(bf, BF_one, BF_zero); + 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 check_byte_pred(HVX_VectorPred pred, int byte_idx, uint8_t exp_mask, int line) { @@ -217,6 +267,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 b08eba92da8..7196bc9a33d 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.34.1
