From 761e1c675e73502f95fc9e70aaeb4f228985cc44 Mon Sep 17 00:00:00 2001 From: Taylor Simpson Date: Thu, 6 Apr 2023 10:42:41 -0700 Subject: [PATCH] Hexagon (tests/tcg/hexagon) Move HVX test infra to header file MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This will facilitate adding additional tests in separate .c files Signed-off-by: Taylor Simpson Reviewed-by: Philippe Mathieu-Daudé Message-Id: <20230406174241.853296-1-tsimpson@quicinc.com> --- tests/tcg/hexagon/Makefile.target | 1 + tests/tcg/hexagon/hvx_misc.c | 160 +-------------------------- tests/tcg/hexagon/hvx_misc.h | 178 ++++++++++++++++++++++++++++++ 3 files changed, 181 insertions(+), 158 deletions(-) create mode 100644 tests/tcg/hexagon/hvx_misc.h diff --git a/tests/tcg/hexagon/Makefile.target b/tests/tcg/hexagon/Makefile.target index 0d82dfa76e..7c94db4bc4 100644 --- a/tests/tcg/hexagon/Makefile.target +++ b/tests/tcg/hexagon/Makefile.target @@ -84,6 +84,7 @@ usr: usr.c scatter_gather: CFLAGS += -mhvx vector_add_int: CFLAGS += -mhvx -fvectorize +hvx_misc: hvx_misc.c hvx_misc.h hvx_misc: CFLAGS += -mhvx hvx_histogram: CFLAGS += -mhvx -Wno-gnu-folding-constant diff --git a/tests/tcg/hexagon/hvx_misc.c b/tests/tcg/hexagon/hvx_misc.c index 53d5c9b44f..d0e64e035f 100644 --- a/tests/tcg/hexagon/hvx_misc.c +++ b/tests/tcg/hexagon/hvx_misc.c @@ -1,5 +1,5 @@ /* - * Copyright(c) 2021-2022 Qualcomm Innovation Center, Inc. All Rights Reserved. + * Copyright(c) 2021-2023 Qualcomm Innovation Center, Inc. All Rights Reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -23,69 +23,7 @@ int err; -static void __check(int line, int i, int j, uint64_t result, uint64_t expect) -{ - if (result != expect) { - printf("ERROR at line %d: [%d][%d] 0x%016llx != 0x%016llx\n", - line, i, j, result, expect); - err++; - } -} - -#define check(RES, EXP) __check(__LINE__, RES, EXP) - -#define MAX_VEC_SIZE_BYTES 128 - -typedef union { - uint64_t ud[MAX_VEC_SIZE_BYTES / 8]; - int64_t d[MAX_VEC_SIZE_BYTES / 8]; - uint32_t uw[MAX_VEC_SIZE_BYTES / 4]; - int32_t w[MAX_VEC_SIZE_BYTES / 4]; - uint16_t uh[MAX_VEC_SIZE_BYTES / 2]; - int16_t h[MAX_VEC_SIZE_BYTES / 2]; - uint8_t ub[MAX_VEC_SIZE_BYTES / 1]; - int8_t b[MAX_VEC_SIZE_BYTES / 1]; -} MMVector; - -#define BUFSIZE 16 -#define OUTSIZE 16 -#define MASKMOD 3 - -MMVector buffer0[BUFSIZE] __attribute__((aligned(MAX_VEC_SIZE_BYTES))); -MMVector buffer1[BUFSIZE] __attribute__((aligned(MAX_VEC_SIZE_BYTES))); -MMVector mask[BUFSIZE] __attribute__((aligned(MAX_VEC_SIZE_BYTES))); -MMVector output[OUTSIZE] __attribute__((aligned(MAX_VEC_SIZE_BYTES))); -MMVector expect[OUTSIZE] __attribute__((aligned(MAX_VEC_SIZE_BYTES))); - -#define CHECK_OUTPUT_FUNC(FIELD, FIELDSZ) \ -static void check_output_##FIELD(int line, size_t num_vectors) \ -{ \ - for (int i = 0; i < num_vectors; i++) { \ - for (int j = 0; j < MAX_VEC_SIZE_BYTES / FIELDSZ; j++) { \ - __check(line, i, j, output[i].FIELD[j], expect[i].FIELD[j]); \ - } \ - } \ -} - -CHECK_OUTPUT_FUNC(d, 8) -CHECK_OUTPUT_FUNC(w, 4) -CHECK_OUTPUT_FUNC(h, 2) -CHECK_OUTPUT_FUNC(b, 1) - -static void init_buffers(void) -{ - int counter0 = 0; - int counter1 = 17; - for (int i = 0; i < BUFSIZE; i++) { - for (int j = 0; j < MAX_VEC_SIZE_BYTES; j++) { - buffer0[i].b[j] = counter0++; - buffer1[i].b[j] = counter1++; - } - for (int j = 0; j < MAX_VEC_SIZE_BYTES / 4; j++) { - mask[i].w[j] = (i + j % MASKMOD == 0) ? 0 : 1; - } - } -} +#include "hvx_misc.h" static void test_load_tmp(void) { @@ -322,100 +260,6 @@ static void test_max_temps() check_output_b(__LINE__, 5); } -#define VEC_OP1(ASM, EL, IN, OUT) \ - asm("v2 = vmem(%0 + #0)\n\t" \ - "v2" #EL " = " #ASM "(v2" #EL ")\n\t" \ - "vmem(%1 + #0) = v2\n\t" \ - : : "r"(IN), "r"(OUT) : "v2", "memory") - -#define VEC_OP2(ASM, EL, IN0, IN1, OUT) \ - asm("v2 = vmem(%0 + #0)\n\t" \ - "v3 = vmem(%1 + #0)\n\t" \ - "v2" #EL " = " #ASM "(v2" #EL ", v3" #EL ")\n\t" \ - "vmem(%2 + #0) = v2\n\t" \ - : : "r"(IN0), "r"(IN1), "r"(OUT) : "v2", "v3", "memory") - -#define TEST_VEC_OP1(NAME, ASM, EL, FIELD, FIELDSZ, OP) \ -static void test_##NAME(void) \ -{ \ - void *pin = buffer0; \ - void *pout = output; \ - for (int i = 0; i < BUFSIZE; i++) { \ - VEC_OP1(ASM, EL, pin, pout); \ - pin += sizeof(MMVector); \ - pout += sizeof(MMVector); \ - } \ - for (int i = 0; i < BUFSIZE; i++) { \ - for (int j = 0; j < MAX_VEC_SIZE_BYTES / FIELDSZ; j++) { \ - expect[i].FIELD[j] = OP buffer0[i].FIELD[j]; \ - } \ - } \ - check_output_##FIELD(__LINE__, BUFSIZE); \ -} - -#define TEST_VEC_OP2(NAME, ASM, EL, FIELD, FIELDSZ, OP) \ -static void test_##NAME(void) \ -{ \ - void *p0 = buffer0; \ - void *p1 = buffer1; \ - void *pout = output; \ - for (int i = 0; i < BUFSIZE; i++) { \ - VEC_OP2(ASM, EL, p0, p1, pout); \ - p0 += sizeof(MMVector); \ - p1 += sizeof(MMVector); \ - pout += sizeof(MMVector); \ - } \ - for (int i = 0; i < BUFSIZE; i++) { \ - for (int j = 0; j < MAX_VEC_SIZE_BYTES / FIELDSZ; j++) { \ - expect[i].FIELD[j] = buffer0[i].FIELD[j] OP buffer1[i].FIELD[j]; \ - } \ - } \ - check_output_##FIELD(__LINE__, BUFSIZE); \ -} - -#define THRESHOLD 31 - -#define PRED_OP2(ASM, IN0, IN1, OUT, INV) \ - asm("r4 = #%3\n\t" \ - "v1.b = vsplat(r4)\n\t" \ - "v2 = vmem(%0 + #0)\n\t" \ - "q0 = vcmp.gt(v2.b, v1.b)\n\t" \ - "v3 = vmem(%1 + #0)\n\t" \ - "q1 = vcmp.gt(v3.b, v1.b)\n\t" \ - "q2 = " #ASM "(q0, " INV "q1)\n\t" \ - "r4 = #0xff\n\t" \ - "v1.b = vsplat(r4)\n\t" \ - "if (q2) vmem(%2 + #0) = v1\n\t" \ - : : "r"(IN0), "r"(IN1), "r"(OUT), "i"(THRESHOLD) \ - : "r4", "v1", "v2", "v3", "q0", "q1", "q2", "memory") - -#define TEST_PRED_OP2(NAME, ASM, OP, INV) \ -static void test_##NAME(bool invert) \ -{ \ - void *p0 = buffer0; \ - void *p1 = buffer1; \ - void *pout = output; \ - memset(output, 0, sizeof(expect)); \ - for (int i = 0; i < BUFSIZE; i++) { \ - PRED_OP2(ASM, p0, p1, pout, INV); \ - p0 += sizeof(MMVector); \ - p1 += sizeof(MMVector); \ - pout += sizeof(MMVector); \ - } \ - for (int i = 0; i < BUFSIZE; i++) { \ - for (int j = 0; j < MAX_VEC_SIZE_BYTES; j++) { \ - bool p0 = (buffer0[i].b[j] > THRESHOLD); \ - bool p1 = (buffer1[i].b[j] > THRESHOLD); \ - if (invert) { \ - expect[i].b[j] = (p0 OP !p1) ? 0xff : 0x00; \ - } else { \ - expect[i].b[j] = (p0 OP p1) ? 0xff : 0x00; \ - } \ - } \ - } \ - check_output_b(__LINE__, BUFSIZE); \ -} - TEST_VEC_OP2(vadd_w, vadd, .w, w, 4, +) TEST_VEC_OP2(vadd_h, vadd, .h, h, 2, +) TEST_VEC_OP2(vadd_b, vadd, .b, b, 1, +) diff --git a/tests/tcg/hexagon/hvx_misc.h b/tests/tcg/hexagon/hvx_misc.h new file mode 100644 index 0000000000..2e868340fd --- /dev/null +++ b/tests/tcg/hexagon/hvx_misc.h @@ -0,0 +1,178 @@ +/* + * Copyright(c) 2021-2023 Qualcomm Innovation Center, Inc. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ + +#ifndef HVX_MISC_H +#define HVX_MISC_H + +static inline void check(int line, int i, int j, + uint64_t result, uint64_t expect) +{ + if (result != expect) { + printf("ERROR at line %d: [%d][%d] 0x%016llx != 0x%016llx\n", + line, i, j, result, expect); + err++; + } +} + +#define MAX_VEC_SIZE_BYTES 128 + +typedef union { + uint64_t ud[MAX_VEC_SIZE_BYTES / 8]; + int64_t d[MAX_VEC_SIZE_BYTES / 8]; + uint32_t uw[MAX_VEC_SIZE_BYTES / 4]; + int32_t w[MAX_VEC_SIZE_BYTES / 4]; + uint16_t uh[MAX_VEC_SIZE_BYTES / 2]; + int16_t h[MAX_VEC_SIZE_BYTES / 2]; + uint8_t ub[MAX_VEC_SIZE_BYTES / 1]; + int8_t b[MAX_VEC_SIZE_BYTES / 1]; +} MMVector; + +#define BUFSIZE 16 +#define OUTSIZE 16 +#define MASKMOD 3 + +MMVector buffer0[BUFSIZE] __attribute__((aligned(MAX_VEC_SIZE_BYTES))); +MMVector buffer1[BUFSIZE] __attribute__((aligned(MAX_VEC_SIZE_BYTES))); +MMVector mask[BUFSIZE] __attribute__((aligned(MAX_VEC_SIZE_BYTES))); +MMVector output[OUTSIZE] __attribute__((aligned(MAX_VEC_SIZE_BYTES))); +MMVector expect[OUTSIZE] __attribute__((aligned(MAX_VEC_SIZE_BYTES))); + +#define CHECK_OUTPUT_FUNC(FIELD, FIELDSZ) \ +static inline void check_output_##FIELD(int line, size_t num_vectors) \ +{ \ + for (int i = 0; i < num_vectors; i++) { \ + for (int j = 0; j < MAX_VEC_SIZE_BYTES / FIELDSZ; j++) { \ + check(line, i, j, output[i].FIELD[j], expect[i].FIELD[j]); \ + } \ + } \ +} + +CHECK_OUTPUT_FUNC(d, 8) +CHECK_OUTPUT_FUNC(w, 4) +CHECK_OUTPUT_FUNC(h, 2) +CHECK_OUTPUT_FUNC(b, 1) + +static inline void init_buffers(void) +{ + int counter0 = 0; + int counter1 = 17; + for (int i = 0; i < BUFSIZE; i++) { + for (int j = 0; j < MAX_VEC_SIZE_BYTES; j++) { + buffer0[i].b[j] = counter0++; + buffer1[i].b[j] = counter1++; + } + for (int j = 0; j < MAX_VEC_SIZE_BYTES / 4; j++) { + mask[i].w[j] = (i + j % MASKMOD == 0) ? 0 : 1; + } + } +} + +#define VEC_OP1(ASM, EL, IN, OUT) \ + asm("v2 = vmem(%0 + #0)\n\t" \ + "v2" #EL " = " #ASM "(v2" #EL ")\n\t" \ + "vmem(%1 + #0) = v2\n\t" \ + : : "r"(IN), "r"(OUT) : "v2", "memory") + +#define VEC_OP2(ASM, EL, IN0, IN1, OUT) \ + asm("v2 = vmem(%0 + #0)\n\t" \ + "v3 = vmem(%1 + #0)\n\t" \ + "v2" #EL " = " #ASM "(v2" #EL ", v3" #EL ")\n\t" \ + "vmem(%2 + #0) = v2\n\t" \ + : : "r"(IN0), "r"(IN1), "r"(OUT) : "v2", "v3", "memory") + +#define TEST_VEC_OP1(NAME, ASM, EL, FIELD, FIELDSZ, OP) \ +static inline void test_##NAME(void) \ +{ \ + void *pin = buffer0; \ + void *pout = output; \ + for (int i = 0; i < BUFSIZE; i++) { \ + VEC_OP1(ASM, EL, pin, pout); \ + pin += sizeof(MMVector); \ + pout += sizeof(MMVector); \ + } \ + for (int i = 0; i < BUFSIZE; i++) { \ + for (int j = 0; j < MAX_VEC_SIZE_BYTES / FIELDSZ; j++) { \ + expect[i].FIELD[j] = OP buffer0[i].FIELD[j]; \ + } \ + } \ + check_output_##FIELD(__LINE__, BUFSIZE); \ +} + +#define TEST_VEC_OP2(NAME, ASM, EL, FIELD, FIELDSZ, OP) \ +static inline void test_##NAME(void) \ +{ \ + void *p0 = buffer0; \ + void *p1 = buffer1; \ + void *pout = output; \ + for (int i = 0; i < BUFSIZE; i++) { \ + VEC_OP2(ASM, EL, p0, p1, pout); \ + p0 += sizeof(MMVector); \ + p1 += sizeof(MMVector); \ + pout += sizeof(MMVector); \ + } \ + for (int i = 0; i < BUFSIZE; i++) { \ + for (int j = 0; j < MAX_VEC_SIZE_BYTES / FIELDSZ; j++) { \ + expect[i].FIELD[j] = buffer0[i].FIELD[j] OP buffer1[i].FIELD[j]; \ + } \ + } \ + check_output_##FIELD(__LINE__, BUFSIZE); \ +} + +#define THRESHOLD 31 + +#define PRED_OP2(ASM, IN0, IN1, OUT, INV) \ + asm("r4 = #%3\n\t" \ + "v1.b = vsplat(r4)\n\t" \ + "v2 = vmem(%0 + #0)\n\t" \ + "q0 = vcmp.gt(v2.b, v1.b)\n\t" \ + "v3 = vmem(%1 + #0)\n\t" \ + "q1 = vcmp.gt(v3.b, v1.b)\n\t" \ + "q2 = " #ASM "(q0, " INV "q1)\n\t" \ + "r4 = #0xff\n\t" \ + "v1.b = vsplat(r4)\n\t" \ + "if (q2) vmem(%2 + #0) = v1\n\t" \ + : : "r"(IN0), "r"(IN1), "r"(OUT), "i"(THRESHOLD) \ + : "r4", "v1", "v2", "v3", "q0", "q1", "q2", "memory") + +#define TEST_PRED_OP2(NAME, ASM, OP, INV) \ +static inline void test_##NAME(bool invert) \ +{ \ + void *p0 = buffer0; \ + void *p1 = buffer1; \ + void *pout = output; \ + memset(output, 0, sizeof(expect)); \ + for (int i = 0; i < BUFSIZE; i++) { \ + PRED_OP2(ASM, p0, p1, pout, INV); \ + p0 += sizeof(MMVector); \ + p1 += sizeof(MMVector); \ + pout += sizeof(MMVector); \ + } \ + for (int i = 0; i < BUFSIZE; i++) { \ + for (int j = 0; j < MAX_VEC_SIZE_BYTES; j++) { \ + bool p0 = (buffer0[i].b[j] > THRESHOLD); \ + bool p1 = (buffer1[i].b[j] > THRESHOLD); \ + if (invert) { \ + expect[i].b[j] = (p0 OP !p1) ? 0xff : 0x00; \ + } else { \ + expect[i].b[j] = (p0 OP p1) ? 0xff : 0x00; \ + } \ + } \ + } \ + check_output_b(__LINE__, BUFSIZE); \ +} + +#endif