Merge changes from topic "widening" * changes: Add vwadd/vwaddu/vwsub/vwsubu to softrvv. Add support for unsigned instructions. Modify template to support widening instructions.
diff --git a/softrvv/CMakeLists.txt b/softrvv/CMakeLists.txt index 76a12e8..9672211 100644 --- a/softrvv/CMakeLists.txt +++ b/softrvv/CMakeLists.txt
@@ -1,35 +1,4 @@ add_library(softrvv INTERFACE) target_include_directories(softrvv INTERFACE include) -vec_cc_test( - NAME - vec_disable_test - SRCS - tests/vec_disable_test.cpp - DEPS - softrvv - LINKOPTS - -Xlinker --defsym=__itcm_length__=256K -) - -vec_cc_test( - NAME - softrvv_vadd - SRCS - tests/softrvv_vadd_test.cpp - DEPS - softrvv - LINKOPTS - -Xlinker --defsym=__itcm_length__=128K -) - -vec_cc_test( - NAME - softrvv_vsub - SRCS - tests/softrvv_vsub_test.cpp - DEPS - softrvv - LINKOPTS - -Xlinker --defsym=__itcm_length__=128K -) \ No newline at end of file +add_subdirectory(tests)
diff --git a/softrvv/include/softrvv.h b/softrvv/include/softrvv.h index 18402a6..299fbb0 100644 --- a/softrvv/include/softrvv.h +++ b/softrvv/include/softrvv.h
@@ -6,7 +6,8 @@ #include "encoding.h" #include "softrvv_vadd.h" #include "softrvv_vsub.h" - +#include "softrvv_vwadd.h" +#include "softrvv_vwsub.h" namespace softrvv {
diff --git a/softrvv/include/softrvv_vwadd.h b/softrvv/include/softrvv_vwadd.h new file mode 100644 index 0000000..c420493 --- /dev/null +++ b/softrvv/include/softrvv_vwadd.h
@@ -0,0 +1,26 @@ +#ifndef SOFTRVV_VWADD_H +#define SOFTRVV_VWADD_H + +#include <stddef.h> + +namespace softrvv { + +template <typename T1, typename T2> +void vwadd_vx(T1 *dest, T2 *src1, const T2 *src2, int32_t avl) { + static_assert(sizeof(T1) == 2 * sizeof(T2)); + for (int32_t idx = 0; idx < avl; idx++) { + dest[idx] = src1[idx] + *src2; + } +} + +template <typename T1, typename T2> +void vwadd_vv(T1 *dest, T2 *src1, T2 *src2, int32_t avl) { + static_assert(sizeof(T1) == 2 * sizeof(T2)); + for (int32_t idx = 0; idx < avl; idx++) { + dest[idx] = src1[idx] + src2[idx]; + } +} + +} // namespace softrvv + +#endif // SOFTRVV_VADD_H
diff --git a/softrvv/include/softrvv_vwsub.h b/softrvv/include/softrvv_vwsub.h new file mode 100644 index 0000000..1d62761 --- /dev/null +++ b/softrvv/include/softrvv_vwsub.h
@@ -0,0 +1,26 @@ +#ifndef SOFTRVV_VWSUB_H +#define SOFTRVV_VWSUB_H + +#include <stddef.h> + +namespace softrvv { + +template <typename T1, typename T2> +void vwsub_vx(T1 *dest, T2 *src1, const T2 *src2, int32_t avl) { + static_assert(sizeof(T1) == 2 * sizeof(T2)); + for (int32_t idx = 0; idx < avl; idx++) { + dest[idx] = src1[idx] - *src2; + } +} + +template <typename T1, typename T2> +void vwsub_vv(T1 *dest, T2 *src1, T2 *src2, int32_t avl) { + static_assert(sizeof(T1) == 2 * sizeof(T2)); + for (int32_t idx = 0; idx < avl; idx++) { + dest[idx] = src1[idx] - src2[idx]; + } +} + +} // namespace softrvv + +#endif // SOFTRVV_VSUB_H
diff --git a/softrvv/tests/CMakeLists.txt b/softrvv/tests/CMakeLists.txt new file mode 100644 index 0000000..68c5364 --- /dev/null +++ b/softrvv/tests/CMakeLists.txt
@@ -0,0 +1,77 @@ + +vec_cc_test( + NAME + vec_disable_test + SRCS + vec_disable_test.cpp + DEPS + softrvv + LINKOPTS + -Xlinker --defsym=__itcm_length__=256K +) + +vec_cc_test( + NAME + softrvv_vadd + SRCS + softrvv_vadd_test.cpp + DEPS + softrvv + LINKOPTS + -Xlinker --defsym=__itcm_length__=128K +) + +vec_cc_test( + NAME + softrvv_vsub + SRCS + softrvv_vsub_test.cpp + DEPS + softrvv + LINKOPTS + -Xlinker --defsym=__itcm_length__=128K +) + +vec_cc_test( + NAME + softrvv_vwadd + SRCS + softrvv_vwadd_test.cpp + DEPS + softrvv + LINKOPTS + -Xlinker --defsym=__itcm_length__=128K +) + +vec_cc_test( + NAME + softrvv_vwaddu + SRCS + softrvv_vwaddu_test.cpp + DEPS + softrvv + LINKOPTS + -Xlinker --defsym=__itcm_length__=128K +) + +vec_cc_test( + NAME + softrvv_vwsub + SRCS + softrvv_vwsub_test.cpp + DEPS + softrvv + LINKOPTS + -Xlinker --defsym=__itcm_length__=128K +) + +vec_cc_test( + NAME + softrvv_vwsubu + SRCS + softrvv_vwsubu_test.cpp + DEPS + softrvv + LINKOPTS + -Xlinker --defsym=__itcm_length__=128K +)
diff --git a/softrvv/tests/softrvv_vwadd_test.cpp b/softrvv/tests/softrvv_vwadd_test.cpp new file mode 100644 index 0000000..6935a42 --- /dev/null +++ b/softrvv/tests/softrvv_vwadd_test.cpp
@@ -0,0 +1,37 @@ +#include <riscv_vector.h> +#include <springbok.h> +#include <stdio.h> +#include <stdlib.h> + +#include "pw_unit_test/framework.h" +#include "softrvv.h" + +namespace softrvv_vadd_test { +namespace { + +int16_t src1[] = {1, 2, 3, -4, 5}; +int16_t src2[] = {1, 2, 3, 4, -6}; +int16_t rs1 = 3; +const uint32_t AVL_CONST = sizeof(src1)/sizeof(src1[0]); +int32_t dest[AVL_CONST]; + +int32_t ref_vv[] = {2, 4, 6, 0, -1}; +int32_t ref_vx[] = {4, 5, 6, -1, 8}; + +class SoftRvvVwaddTest : public ::testing::Test { + protected: + void SetUp() override { memset(dest, 0, sizeof(dest)); } +}; + +TEST_F(SoftRvvVwaddTest, VV) { + softrvv::vwadd_vv<int32_t, int16_t>(dest, src1, src2, AVL_CONST); + ASSERT_EQ(memcmp(dest, ref_vv, sizeof(dest)), 0); +} + +TEST_F(SoftRvvVwaddTest, VX) { + softrvv::vwadd_vx<int32_t, int16_t>(dest, src1, &rs1, AVL_CONST); + ASSERT_EQ(memcmp(dest, ref_vx, sizeof(dest)), 0); +} + +} // namespace +} // namespace softrvv_vwadd_test
diff --git a/softrvv/tests/softrvv_vwaddu_test.cpp b/softrvv/tests/softrvv_vwaddu_test.cpp new file mode 100644 index 0000000..871a62f --- /dev/null +++ b/softrvv/tests/softrvv_vwaddu_test.cpp
@@ -0,0 +1,37 @@ +#include <riscv_vector.h> +#include <springbok.h> +#include <stdio.h> +#include <stdlib.h> + +#include "pw_unit_test/framework.h" +#include "softrvv.h" + +namespace softrvv_vaddu_test { +namespace { + +uint16_t src1[] = {1, 2, 3, 4, 5}; +uint16_t src2[] = {1, 2, 3, 4, 5}; +uint16_t rs1 = 3; +const uint32_t AVL_CONST = sizeof(src1)/sizeof(src1[0]); +uint32_t dest[AVL_CONST]; + +uint32_t ref_vv[] = {2, 4, 6, 8, 10}; +uint32_t ref_vx[] = {4, 5, 6, 7, 8}; + +class SoftRvvVwaddTest : public ::testing::Test { + protected: + void SetUp() override { memset(dest, 0, sizeof(dest)); } +}; + +TEST_F(SoftRvvVwaddTest, UVV) { + softrvv::vwadd_vv<uint32_t, uint16_t>(dest, src1, src2, AVL_CONST); + ASSERT_EQ(memcmp(dest, ref_vv, sizeof(dest)), 0); +} + +TEST_F(SoftRvvVwaddTest, UVX) { + softrvv::vwadd_vx<uint32_t, uint16_t>(dest, src1, &rs1, AVL_CONST); + ASSERT_EQ(memcmp(dest, ref_vx, sizeof(dest)), 0); +} + +} // namespace +} // namespace softrvv_vwaddu_test
diff --git a/softrvv/tests/softrvv_vwsub_test.cpp b/softrvv/tests/softrvv_vwsub_test.cpp new file mode 100644 index 0000000..db44f4d --- /dev/null +++ b/softrvv/tests/softrvv_vwsub_test.cpp
@@ -0,0 +1,37 @@ +#include <riscv_vector.h> +#include <springbok.h> +#include <stdio.h> +#include <stdlib.h> + +#include "pw_unit_test/framework.h" +#include "softrvv.h" + +namespace softrvv_vwsub_test { +namespace { + +int16_t src1[] = {2, 4, -6, 8, 10}; +int16_t src2[] = {1, 2, 3, -4, 5}; +int16_t rs1 = 3; +const uint32_t AVL_CONST = sizeof(src1)/sizeof(src1[0]); +int32_t dest[AVL_CONST]; + +int32_t ref_vv[] = {1, 2, -9, 12, 5}; +int32_t ref_vx[] = {-1, 1, -9, 5, 7}; + +class SoftRvvVwsubTest : public ::testing::Test { + protected: + void SetUp() override { memset(dest, 0, sizeof(dest)); } +}; + +TEST_F(SoftRvvVwsubTest, VV) { + softrvv::vwsub_vv<int32_t, int16_t>(dest, src1, src2, AVL_CONST); + ASSERT_EQ(memcmp(dest, ref_vv, sizeof(dest)), 0); +} + +TEST_F(SoftRvvVwsubTest, VX) { + softrvv::vwsub_vx<int32_t, int16_t>(dest, src1, &rs1, AVL_CONST); + ASSERT_EQ(memcmp(dest, ref_vx, sizeof(dest)), 0); +} + +} // namespace +} // namespace softrvv_vwsub_test
diff --git a/softrvv/tests/softrvv_vwsubu_test.cpp b/softrvv/tests/softrvv_vwsubu_test.cpp new file mode 100644 index 0000000..c23d6c2 --- /dev/null +++ b/softrvv/tests/softrvv_vwsubu_test.cpp
@@ -0,0 +1,37 @@ +#include <riscv_vector.h> +#include <springbok.h> +#include <stdio.h> +#include <stdlib.h> + +#include "pw_unit_test/framework.h" +#include "softrvv.h" + +namespace softrvv_vwsubu_test { +namespace { + +uint16_t src1[] = {3, 4, 6, 8, 10}; +uint16_t src2[] = {1, 2, 3, 4, 5}; +uint16_t rs1 = 3; +const uint32_t AVL_CONST = sizeof(src1)/sizeof(src1[0]); +uint32_t dest[AVL_CONST]; + +uint32_t ref_vv[] = {2, 2, 3, 4, 5}; +uint32_t ref_vx[] = {0, 1, 3, 5, 7}; + +class SoftRvvVwsubuTest : public ::testing::Test { + protected: + void SetUp() override { memset(dest, 0, sizeof(dest)); } +}; + +TEST_F(SoftRvvVwsubuTest, VV) { + softrvv::vwsub_vv<uint32_t, uint16_t>(dest, src1, src2, AVL_CONST); + ASSERT_EQ(memcmp(dest, ref_vv, sizeof(dest)), 0); +} + +TEST_F(SoftRvvVwsubuTest, VX) { + softrvv::vwsub_vx<uint32_t, uint16_t>(dest, src1, &rs1, AVL_CONST); + ASSERT_EQ(memcmp(dest, ref_vx, sizeof(dest)), 0); +} + +} // namespace +} // namespace softrvv_vwsubu_test
diff --git a/tests/templates/base.tpl.cpp b/tests/templates/base.tpl.cpp new file mode 100644 index 0000000..f6047a1 --- /dev/null +++ b/tests/templates/base.tpl.cpp
@@ -0,0 +1,43 @@ +<%! + +def is_widening(op_code): + return op_code[1] == 'w' + +def is_unsigned(op_code): + return op_code[-1] == 'u' + +def get_sews(op_code): + return [8, 16] if is_widening(op_code) else [8, 16, 32] + +def get_lmuls(op_code): + return [1, 2, 4] if is_widening(op_code) else [1, 2, 4, 8] + +def get_dest_type(op_code, sew): + type_fmt = "%sint%d_t" + sign_type = "u" if is_unsigned(op_code) else "" + dest_sew = sew * 2 if is_widening(op_code) else sew + return type_fmt % (sign_type, dest_sew) + +def get_src_type(op_code, sew): + type_fmt = "%sint%d_t" + sign_type = "u" if is_unsigned(op_code) else "" + return type_fmt % (sign_type, sew) + +def get_ref_opcode(op_code): + return op_code[:-1] if is_unsigned(op_code) else op_code + +%> +/* Automatically generated file */ +#include <limits.h> +#include <riscv_vector.h> +#include <softrvv.h> +#include <springbok.h> +#include <stdio.h> +#include <stdlib.h> + +#include <bit> +#include <tuple> + +#include "pw_unit_test/framework.h" +#include "test_v_helpers.h" +${self.body()}
diff --git a/tests/templates/opivi_test.tpl.cpp b/tests/templates/opivi_test.tpl.cpp index 40a5d26..a831c1e 100644 --- a/tests/templates/opivi_test.tpl.cpp +++ b/tests/templates/opivi_test.tpl.cpp
@@ -1,16 +1,4 @@ -/* Automatically generated file */ -#include <limits.h> -#include <riscv_vector.h> -#include <softrvv.h> -#include <springbok.h> -#include <stdio.h> -#include <stdlib.h> - -#include <bit> -#include <tuple> - -#include "pw_unit_test/framework.h" -#include "test_v_helpers.h" +<%inherit file="base.tpl.cpp"/>\ namespace ${op_code}_vi_test { namespace {
diff --git a/tests/templates/opivv_test.tpl.cpp b/tests/templates/opivv_test.tpl.cpp index 1df0448..2075de2 100644 --- a/tests/templates/opivv_test.tpl.cpp +++ b/tests/templates/opivv_test.tpl.cpp
@@ -1,16 +1,4 @@ -/* Automatically generated file */ -#include <limits.h> -#include <riscv_vector.h> -#include <softrvv.h> -#include <springbok.h> -#include <stdio.h> -#include <stdlib.h> - -#include <bit> -#include <tuple> - -#include "pw_unit_test/framework.h" -#include "test_v_helpers.h" +<%inherit file="base.tpl.cpp"/>\ namespace ${op_code}_vv_test { namespace { @@ -27,10 +15,17 @@ void SetUp() override { zero_vector_registers(); } void TearDown() override { zero_vector_registers(); } }; -% for sew in [8, 16, 32]: -% for lmul in [1, 2, 4, 8]: <% -var_type = "int%d_t" % sew +widening = parent.module.is_widening(op_code) +sews = parent.module.get_sews(op_code) +lmuls = parent.module.get_lmuls(op_code) +ref_opcode = parent.module.get_ref_opcode(op_code) +%>\ +% for sew in sews: +% for lmul in lmuls: +<% +dest_type = parent.module.get_dest_type(op_code, sew) +src_type = parent.module.get_src_type(op_code, sew) %>\ TEST_F(${op_code.capitalize()}Test, ${op_code.lower()}_vv${sew}m${lmul}) { @@ -38,26 +33,29 @@ int32_t avl = AVLS[i]; int vlmax; int vl; - std::tie(vlmax, vl) = vector_test_setup<${var_type}>( + std::tie(vlmax, vl) = vector_test_setup<${src_type}>( VLMUL::LMUL_M${lmul}, avl, {src_vector_1, src_vector_2, dest_vector, ref_dest_vector}); if (avl > vlmax) { continue; } - ${var_type} *ptr_vec_1 = reinterpret_cast<${var_type} *>(src_vector_1); - ${var_type} *ptr_vec_2 = reinterpret_cast<${var_type} *>(src_vector_2); - ${var_type} *ptr_dest_vec = reinterpret_cast<${var_type} *>(dest_vector); - ${var_type} *ptr_ref_dest_vec = reinterpret_cast<${var_type} *>(ref_dest_vector); + ${src_type} *ptr_vec_1 = reinterpret_cast<${src_type} *>(src_vector_1); + ${src_type} *ptr_vec_2 = reinterpret_cast<${src_type} *>(src_vector_2); + ${dest_type} *ptr_dest_vec = reinterpret_cast<${dest_type} *>(dest_vector); + ${dest_type} *ptr_ref_dest_vec = reinterpret_cast<${dest_type} *>(ref_dest_vector); // set up values to test up to index of the AVL - fill_random_vector<${var_type}>(ptr_vec_1, avl); - fill_random_vector<${var_type}>(ptr_vec_2, avl); + fill_random_vector<${src_type}>(ptr_vec_1, avl); + fill_random_vector<${src_type}>(ptr_vec_2, avl); memset(dest_vector, 0, MAXVL_BYTES); memset(ref_dest_vector, 0, MAXVL_BYTES); // Generate reference vector - softrvv::${op_code}_vv<${var_type}>(ptr_ref_dest_vec, ptr_vec_2, ptr_vec_1, avl); - +% if widening: + softrvv::${ref_opcode}_vv<${dest_type}, ${src_type}>(ptr_ref_dest_vec, ptr_vec_2, ptr_vec_1, avl); +%else: + softrvv::${ref_opcode}_vv<${dest_type}>(ptr_ref_dest_vec, ptr_vec_2, ptr_vec_1, avl); +% endif // Load vector registers __asm__ volatile("vle${sew}.v v8, (%0)" : : "r"(ptr_vec_1)); __asm__ volatile("vle${sew}.v v16, (%0)" : : "r"(ptr_vec_2)); @@ -66,10 +64,13 @@ __asm__ volatile("${op_code}.vv v24, v16, v8"); // Store result vector register +% if widening: + __asm__ volatile("vse${sew*2}.v v24, (%0)" : : "r"(ptr_dest_vec)); +% else: __asm__ volatile("vse${sew}.v v24, (%0)" : : "r"(ptr_dest_vec)); - +% endif // Check vector elements - assert_vec_elem_eq<${var_type}>(vlmax, dest_vector, ref_dest_vector); + assert_vec_elem_eq<${dest_type}>(vlmax, dest_vector, ref_dest_vector); } } %endfor
diff --git a/tests/templates/opivx_test.tpl.cpp b/tests/templates/opivx_test.tpl.cpp index 2476708..c10f9c7 100644 --- a/tests/templates/opivx_test.tpl.cpp +++ b/tests/templates/opivx_test.tpl.cpp
@@ -1,16 +1,4 @@ -/* Automatically generated file */ -#include <limits.h> -#include <riscv_vector.h> -#include <softrvv.h> -#include <springbok.h> -#include <stdio.h> -#include <stdlib.h> - -#include <bit> -#include <tuple> - -#include "pw_unit_test/framework.h" -#include "test_v_helpers.h" +<%inherit file="base.tpl.cpp"/>\ namespace ${op_code}_vx_test { namespace { @@ -26,10 +14,17 @@ void SetUp() override { zero_vector_registers(); } void TearDown() override { zero_vector_registers(); } }; -% for sew in [8, 16, 32]: -% for lmul in [1, 2, 4, 8]: <% -var_type = "int%d_t" % sew +widening = parent.module.is_widening(op_code) +sews = parent.module.get_sews(op_code) +lmuls = parent.module.get_lmuls(op_code) +%>\ +% for sew in sews: +% for lmul in lmuls: +<% +dest_type = parent.module.get_dest_type(op_code, sew) +src_type = parent.module.get_src_type(op_code, sew) +ref_opcode = parent.module.get_ref_opcode(op_code) %>\ TEST_F(${op_code.capitalize()}Test, ${op_code.lower()}_vx${sew}m${lmul}) { @@ -37,24 +32,27 @@ int32_t avl = AVLS[i]; int vlmax; int vl; - std::tie(vlmax, vl) = vector_test_setup<${var_type}>( + std::tie(vlmax, vl) = vector_test_setup<${src_type}>( VLMUL::LMUL_M${lmul}, avl, {src_vector_1, dest_vector, ref_dest_vector}); if (avl > vlmax) { continue; } - ${var_type} *ptr_vec_1 = reinterpret_cast<${var_type} *>(src_vector_1); - ${var_type} *ptr_dest_vec = reinterpret_cast<${var_type} *>(dest_vector); - ${var_type} *ptr_ref_dest_vec = reinterpret_cast<${var_type} *>(ref_dest_vector); - ${var_type} test_val = static_cast<${var_type}>(rand()); + ${src_type} *ptr_vec_1 = reinterpret_cast<${src_type} *>(src_vector_1); + ${src_type} test_val = static_cast<${src_type}>(rand()); + ${dest_type} *ptr_dest_vec = reinterpret_cast<${dest_type} *>(dest_vector); + ${dest_type} *ptr_ref_dest_vec = reinterpret_cast<${dest_type} *>(ref_dest_vector); // set up values to test up to index of the AVL - fill_random_vector<${var_type}>(ptr_vec_1, avl); + fill_random_vector<${src_type}>(ptr_vec_1, avl); memset(dest_vector, 0, MAXVL_BYTES); memset(ref_dest_vector, 0, MAXVL_BYTES); // Generate reference vector - softrvv::${op_code}_vx<${var_type}>(ptr_ref_dest_vec, ptr_vec_1, &test_val, avl); - +% if widening: + softrvv::${ref_opcode}_vx<${dest_type}, ${src_type}>(ptr_ref_dest_vec, ptr_vec_1, &test_val, avl); +%else: + softrvv::${ref_opcode}_vx<${dest_type}>(ptr_ref_dest_vec, ptr_vec_1, &test_val, avl); +% endif // Load vector registers __asm__ volatile("vle${sew}.v v8, (%0)" : : "r"(ptr_vec_1)); @@ -62,10 +60,13 @@ __asm__ volatile("${op_code}.vx v24, v8, %[RS1]" ::[RS1] "r"(test_val)); // Store result vector register +% if widening: + __asm__ volatile("vse${sew*2}.v v24, (%0)" : : "r"(ptr_dest_vec)); +% else: __asm__ volatile("vse${sew}.v v24, (%0)" : : "r"(ptr_dest_vec)); - +% endif // Check vector elements - assert_vec_elem_eq<${var_type}>(vlmax, dest_vector, ref_dest_vector); + assert_vec_elem_eq<${dest_type}>(vlmax, dest_vector, ref_dest_vector); } } %endfor