Add support for vnsrl and narrowing ops. * vnsrl is a narrowing op, which required template changes to support varying type widths. * Add/modify vec_test_helpers module to support narrowing ops. * Add softrvv vnsrl implementation and test. * Add a compile time check to softrvv_vnsrl for SEW of dest is 1/2 SEW src2. * Add vnsrl test. * Modify softrvv templates for changes in vec_test_helpers module. Change-Id: I5889200ea36e213dee9a051ae726ed3bf0480d3e
diff --git a/scripts/vec_test_helpers/__init__.py b/scripts/vec_test_helpers/__init__.py index 10511f8..7da121f 100644 --- a/scripts/vec_test_helpers/__init__.py +++ b/scripts/vec_test_helpers/__init__.py
@@ -2,47 +2,225 @@ This module is for reusable helper functions used by the templates. """ +import collections +import enum +import re import numpy as np -def is_widening(op_code): - """Check if a particular op_code is a widening type.""" - return op_code[1] == 'w' +class VecTemplateHelper: + """Given op and sew provide template with necessary parameters.""" + class OperandType(enum.Enum): + """RISC-V V operand type options.""" + VECTOR = enum.auto() + SCALAR = enum.auto() + IMMEDIATE = enum.auto() -def is_unsigned(op_code): - """Check if a particular op_code is a unsigned type.""" - return op_code[-1] == 'u' + class OperandWidth(enum.Enum): + """RISC-V V operand width type option.""" + STANDARD = enum.auto() + WIDENING = enum.auto() + NARROWING = enum.auto() -def get_sews(op_code): - """Given an op_code return a list of valid element widths.""" - return [8, 16] if is_widening(op_code) else [8, 16, 32] + mnemonic_suffix = { + OperandType.VECTOR : { + OperandWidth.STANDARD: "vv", + OperandWidth.WIDENING: "vv", + OperandWidth.NARROWING: "wv", + }, + OperandType.SCALAR : { + OperandWidth.STANDARD: "vx", + OperandWidth.WIDENING: "vx", + OperandWidth.NARROWING: "wx", + }, + OperandType.IMMEDIATE : { + OperandWidth.STANDARD: "vi", + OperandWidth.WIDENING: "vi", + OperandWidth.NARROWING: "wi", + }, + } -def get_lmuls(op_code): - """Given an op_code return an iterable if valid lmuls.""" - return [1, 2, 4] if is_widening(op_code) else [1, 2, 4, 8] + """Helper class for providing params for use in templates""" + def __init__(self, op_code, sew=None): + self._op_code = op_code + self._sew = sew + self.force_unsigned = False + self.signed_np_types = { + 8:np.int8, + 16:np.int16, + 32:np.int32} + self.unsigned_np_types = { + 8:np.uint8, + 16:np.uint16, + 32:np.uint32} -def get_dest_type(op_code, sew): - """Return a destination type for a op_code and element width.""" - 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) + @property + def op_code(self): + """Return the op_code.""" + if self._op_code is None: + raise ValueError("SEW was not set.") + return self._op_code -def get_src_type(op_code, sew): - """Return a source type for an op_code and element width.""" - type_fmt = "%sint%d_t" - sign_type = "u" if is_unsigned(op_code) else "" - return type_fmt % (sign_type, sew) + @op_code.setter + def op_code(self, value): + """Set the op_code""" + self._op_code = value -def get_ref_opcode(op_code): - """Return the name of the reference code in the softrvv library.""" - return op_code[:-1] if is_unsigned(op_code) else op_code + @property + def sew(self): + """Return the selected element width.""" + if self._sew is None: + raise ValueError("SEW was not set.") + return self._sew -def get_imms(op_code): - """Return a list of valid immediate values for a op code.""" - if op_code in ['vsll', 'vsrl', 'vsra']: - # Left and right shift immediates must be [0,31] - return np.linspace(0, 31, 8, dtype=np.int32) - else: + @sew.setter + def sew(self, value): + """Set the selected element width.""" + if not value in (8, 16, 32): + raise ValueError("Invalid SEW") + self._sew = value + + def is_widening(self): + """Check if a particular op_code is a widening type.""" + return self.op_code[1] == 'w' + + def is_narrowing(self): + """Check if a particular op_code is a narrowing type.""" + return self.op_code[1] == 'n' + + def is_unsigned(self): + """Check if a particular op_code is a unsigned type.""" + return self.op_code[-1] == 'u' + + def get_sews(self): + """Given an op_code return a list of valid element widths.""" + if self.is_widening() or self.is_narrowing(): + return [8, 16] + return [8, 16, 32] + + def get_sew_sizes(self): + """Return size of types.""" + dest_sew = self.sew + src2_sew = self.sew + src1_sew = self.sew + imm_sew = self.sew + if self.is_narrowing(): + src2_sew = self.sew * 2 + elif self.is_widening(): + dest_sew = self.sew * 2 + return dest_sew, src2_sew, src1_sew, imm_sew + + def get_var_types(self): + """Return types for an op_code and element width.""" + VarTypes = collections.namedtuple( + "VarTypes", + ('dest_type', 'src2_type', 'src1_type', 'imm_type')) + type_fmt = "%sint%d_t" + sign_type = "u" if self.is_unsigned() or self.force_unsigned else "" + dest_sew, src2_sew, src1_sew, imm_sew = self.get_sew_sizes() + dest_type = type_fmt % (sign_type, dest_sew) + src1_type = type_fmt % (sign_type, src1_sew) + src2_type = type_fmt % (sign_type, src2_sew) + imm_type = type_fmt % (sign_type, imm_sew) + var_types = VarTypes(dest_type, src2_type, src1_type, imm_type) + return var_types + + def get_mnemonic(self, operand_type): + """Generate the correct mnemonic given a opcode and operand type.""" + operand_width = self.OperandWidth.STANDARD + if self.is_narrowing(): + operand_width = self.OperandWidth.NARROWING + elif self.is_widening(): + operand_width = self.OperandWidth.WIDENING + op_suffix = self.mnemonic_suffix[operand_type][operand_width] + return "%s.%s" % (self.op_code, op_suffix) + + def get_lmuls(self): + """Given an op_code return an iterable of valid lmuls.""" + if self.is_widening() or self.is_narrowing(): + return [1, 2, 4] + return [1, 2, 4, 8] + + @staticmethod + def get_sew_from_dtype(dtype): + """Extract the selected element width from a data type.""" + match = re.match(r"[a-z]+(?P<sew>[\d]+)", dtype) + return int(match['sew']) + + def get_softrvv_template_data_type(self): + """Return types """ + var_types = self.get_var_types() + if self.is_narrowing() or self.is_widening(): + return "%s, %s" % (var_types.dest_type, var_types.src2_type) + return var_types.src1_type + + def get_ref_opcode(self): + """Return the name of the reference code in the softrvv library.""" + return self.op_code[:-1] if self.is_unsigned() else self.op_code + + def get_imms(self): + """Return a list of valid immediate values for a op code.""" + if self.op_code in ['vsll', 'vsrl', 'vsra', 'vnsrl', 'vnsra']: + # Left and right shift immediates must be [0,31] + return np.linspace(0, 31, 8, dtype=np.int32) # Immediate values must be [-16, 15] return np.linspace(-16, 15, 7, dtype=np.int32) + def get_np_dest_type(self): + """Return numpy type for destination.""" + if self.force_unsigned: + types = self.unsigned_np_types + else: + types = self.signed_np_types + if self.is_widening(): + return types[self.sew * 2] + return types[self.sew] + + def get_np_src1_type(self): + """Return numpy type for src1.""" + if self.force_unsigned: + types = self.unsigned_np_types + else: + types = self.signed_np_types + return types[self.sew] + + def get_np_src2_type(self): + """Return numpy type for src2.""" + if self.force_unsigned: + types = self.unsigned_np_types + else: + types = self.signed_np_types + if self.is_narrowing(): + return types[self.sew * 2] + return types[self.sew] + + def get_test_inputs(self, n=5, allow_zero=True): # pylint: disable=invalid-name + """Return test inputs.""" + src1_np_type = self.get_np_src1_type() + src2_np_type = self.get_np_src2_type() + type_info = np.iinfo(src1_np_type) + src1_data = np.random.randint( + type_info.min, type_info.max, n).astype(src1_np_type) + rs1 = self.get_np_src1_type()(np.random.randint( + type_info.min, type_info.max)) + src2_np_type = self.get_np_src2_type() + type_info = np.iinfo(src2_np_type) + src2_data = np.random.randint( + type_info.min, type_info.max, n).astype(src2_np_type) + if not allow_zero: + src2_data[src2_data==0] = 1 + rs1 = 1 if rs1 == 0 else rs1 + return src2_data, src1_data, rs1 + +def cast_to_unsigned(arr): + """Cast a signed array to an unsigned array.""" + udtypes = {np.int8:np.uint8, + np.int16:np.uint16, + np.int32:np.uint32, + np.int64:np.uint64} + if not arr.dtype.type in udtypes.keys(): + raise TypeError + return arr.astype(udtypes[arr.dtype.type]) + +def to_carr_str(arr): + """Simple function for turn array into comma separated list.""" + return ", ".join(("%s" % x for x in arr))
diff --git a/softrvv/include/softrvv.h b/softrvv/include/softrvv.h index 189934b..e3a245a 100644 --- a/softrvv/include/softrvv.h +++ b/softrvv/include/softrvv.h
@@ -10,6 +10,7 @@ #include "softrvv_vmax.h" #include "softrvv_vmin.h" #include "softrvv_vmul_vmulh.h" +#include "softrvv_vnsrl.h" #include "softrvv_vor.h" #include "softrvv_vrem.h" #include "softrvv_vsext_vzext.h"
diff --git a/softrvv/include/softrvv_vnsrl.h b/softrvv/include/softrvv_vnsrl.h new file mode 100644 index 0000000..58563cd --- /dev/null +++ b/softrvv/include/softrvv_vnsrl.h
@@ -0,0 +1,36 @@ +#ifndef SOFTRVV_VNSRL_H +#define SOFTRVV_VNSRL_H + +#include <stddef.h> + +#include <type_traits> + +namespace softrvv { + +template <typename T1, typename T2> +void vnsrl_vx(T1 *dest, T2 *src1, const T1 *src2, int32_t avl) { + // Only low lg2(SEW*2) bits are used for shift + static_assert(sizeof(T1) * 2 == sizeof(T2)); + const T1 low_bits_mask = sizeof(T2) * 8 - 1; + const T1 shift = *src2 & low_bits_mask; + for (int32_t idx = 0; idx < avl; idx++) { + dest[idx] = static_cast<T1>( + static_cast<typename std::make_unsigned<T2>::type>(src1[idx]) >> shift); + } +} + +template <typename T1, typename T2> +void vnsrl_vv(T1 *dest, T2 *src1, T1 *src2, int32_t avl) { + // // Only low lg2(SEW*2) bits are used for shift + static_assert(sizeof(T1) * 2 == sizeof(T2)); + const T1 low_bits_mask = sizeof(T2) * 8 - 1; + for (int32_t idx = 0; idx < avl; idx++) { + dest[idx] = static_cast<T1>( + static_cast<typename std::make_unsigned<T2>::type>(src1[idx]) + >> (src2[idx] & low_bits_mask)); + } +} + +} // namespace softrvv + +#endif // SOFTRVV_VNSRL_H
diff --git a/softrvv/tests/CMakeLists.txt b/softrvv/tests/CMakeLists.txt index 6f846d5..ac55038 100644 --- a/softrvv/tests/CMakeLists.txt +++ b/softrvv/tests/CMakeLists.txt
@@ -188,6 +188,15 @@ -Xlinker --defsym=__itcm_length__=128K ) +softrvv_vec_cc_generated_test( + NAME + vnsrl + TEMPLATE + softrvv_vnsrl_test.tpl.cpp + LINKOPTS + -Xlinker --defsym=__itcm_length__=128K +) + vec_cc_test( NAME softrvv_vmax
diff --git a/softrvv/tests/templates/opivv_opivx_test.tpl.cpp b/softrvv/tests/templates/opivv_opivx_test.tpl.cpp index c91eb95..2a21200 100644 --- a/softrvv/tests/templates/opivv_opivx_test.tpl.cpp +++ b/softrvv/tests/templates/opivv_opivx_test.tpl.cpp
@@ -1,25 +1,18 @@ -<%def name="test_opivv_opivx(dtype, op, src1, src2, rs1, ref_vv, ref_vx)"> -<% - -def to_carr_str(arr): - return ", ".join(("%s" % x for x in arr)) - -src1 = to_carr_str(src1) -src2 = to_carr_str(src2) -ref_vv = to_carr_str(ref_vv) -ref_vx = to_carr_str(ref_vx) +<%! +import vec_test_helpers %> -namespace softrvv_${op}_test { + +<%def name="test_opivv_opivx(template_helper, src2, src1, rs1, ref_vv, ref_vx)"> +<% +src1 = vec_test_helpers.to_carr_str(src1) +src2 = vec_test_helpers.to_carr_str(src2) +ref_vv = vec_test_helpers.to_carr_str(ref_vv) +ref_vx = vec_test_helpers.to_carr_str(ref_vx) +%> +namespace softrvv_${template_helper.op_code}_test { namespace { -${dtype} src1[] = {${src1}}; -${dtype} src2[] = {${src2}}; -${dtype} rs1 = ${rs1}; -const ${dtype} kAVL = sizeof(src1)/sizeof(src1[0]); -${dtype} dest[kAVL]; - -${dtype} ref_vv[] = {${ref_vv}}; -${dtype} ref_vx[] = {${ref_vx}}; +${insert_variable_init(template_helper, src2, src1, rs1, ref_vv, ref_vx)} template <typename T> void assert_vec_elem_eq(int avl, void *test_vector_1, void *test_vector_2) { @@ -29,22 +22,43 @@ ASSERT_EQ(ptr_vec_1[idx], ptr_vec_2[idx]); } } - -class SoftRvv${op.capitalize()}Test : public ::testing::Test { +class SoftRvv${template_helper.op_code.capitalize()}Test : public ::testing::Test { protected: void SetUp() override { memset(dest, 0, sizeof(dest)); } }; -TEST_F(SoftRvv${op.capitalize()}Test, VV) { - softrvv::${op}_vv<${dtype}>(dest, src1, src2, kAVL); - assert_vec_elem_eq<${dtype}>(kAVL, dest, ref_vv); -} - -TEST_F(SoftRvv${op.capitalize()}Test, VX) { - softrvv::${op}_vx<${dtype}>(dest, src1, &rs1, kAVL); - assert_vec_elem_eq<${dtype}>(kAVL, dest, ref_vx); -} +${insert_test(template_helper)} } // namespace } // namespace softrvv_${op}_test </%def> + +<%def name="insert_variable_init(template_helper, src2, src1, rs1, ref_vv, ref_vx)"> +<% + var_types = template_helper.get_var_types() +%>\ +${var_types.src1_type} src1[] = {${src1}}; +${var_types.src2_type} src2[] = {${src2}}; +${var_types.imm_type} rs1 = ${rs1}; +const int kAVL = sizeof(src1)/sizeof(src1[0]); +${var_types.dest_type} dest[kAVL]; + +${var_types.dest_type} ref_vv[] = {${ref_vv}}; +${var_types.dest_type} ref_vx[] = {${ref_vx}}; +</%def>\ + +<%def name="insert_test(template_helper)"> +<% +var_types = template_helper.get_var_types() +datatypes = template_helper.get_softrvv_template_data_type() +%>\ +TEST_F(SoftRvv${template_helper.op_code.capitalize()}Test, VV) { + softrvv::${template_helper.op_code}_vv<${datatypes}>(dest, src2, src1, kAVL); + assert_vec_elem_eq<${var_types.dest_type}>(kAVL, dest, ref_vv); +} + +TEST_F(SoftRvv${template_helper.op_code.capitalize()}Test, VX) { + softrvv::${template_helper.op_code}_vx<${datatypes}>(dest, src2, &rs1, kAVL); + assert_vec_elem_eq<${var_types.dest_type}>(kAVL, dest, ref_vx); +} +</%def>\
diff --git a/softrvv/tests/templates/softrvv_vadd_test.tpl.cpp b/softrvv/tests/templates/softrvv_vadd_test.tpl.cpp index a5a6910..12db2ad 100644 --- a/softrvv/tests/templates/softrvv_vadd_test.tpl.cpp +++ b/softrvv/tests/templates/softrvv_vadd_test.tpl.cpp
@@ -2,8 +2,10 @@ <%namespace name="tests" file="opivv_opivx_test.tpl.cpp"/> <% import numpy as np -src1, src2, rs1 = parent.module.get_test_inputs(np.int32, N=5) -ref_vv = src1 + src2 -ref_vx = src1 + rs1 +import vec_test_helpers +template_helper = vec_test_helpers.VecTemplateHelper(op, 32) +src2, src1, rs1 = template_helper.get_test_inputs(n=5) +ref_vv = src2 + src1 +ref_vx = src2 + rs1 %>\ -${tests.test_opivv_opivx("int32_t", op, src1, src2, rs1, ref_vv, ref_vx)} +${tests.test_opivv_opivx(template_helper, src2, src1, rs1, ref_vv, ref_vx)}
diff --git a/softrvv/tests/templates/softrvv_vdiv_test.tpl.cpp b/softrvv/tests/templates/softrvv_vdiv_test.tpl.cpp index 0c2bdd3..3e2ad01 100644 --- a/softrvv/tests/templates/softrvv_vdiv_test.tpl.cpp +++ b/softrvv/tests/templates/softrvv_vdiv_test.tpl.cpp
@@ -2,8 +2,10 @@ <%namespace name="tests" file="opivv_opivx_test.tpl.cpp"/> <% import numpy as np -src1, src2, rs1 = parent.module.get_test_inputs(np.int32, N=5, allow_zero=False) -ref_vv = np.divide(src1, src2).astype(np.int32) -ref_vx = np.divide(src1, rs1).astype(np.int32) +import vec_test_helpers +template_helper = vec_test_helpers.VecTemplateHelper(op, 32) +src2, src1, rs1 = template_helper.get_test_inputs(n=5, allow_zero=False) +ref_vv = np.divide(src2, src1).astype(np.int32) +ref_vx = np.divide(src2, rs1).astype(np.int32) %>\ -${tests.test_opivv_opivx("int32_t", op, src1, src2, rs1, ref_vv, ref_vx)} +${tests.test_opivv_opivx(template_helper, src2, src1, rs1, ref_vv, ref_vx)}
diff --git a/softrvv/tests/templates/softrvv_vmul_test.tpl.cpp b/softrvv/tests/templates/softrvv_vmul_test.tpl.cpp index 8b47598..bd7caf7 100644 --- a/softrvv/tests/templates/softrvv_vmul_test.tpl.cpp +++ b/softrvv/tests/templates/softrvv_vmul_test.tpl.cpp
@@ -2,8 +2,10 @@ <%namespace name="tests" file="opivv_opivx_test.tpl.cpp"/> <% import numpy as np -src1, src2, rs1 = parent.module.get_test_inputs(np.int32, N=5) -ref_vv = src1 * src2 -ref_vx = src1 * rs1 +import vec_test_helpers +template_helper = vec_test_helpers.VecTemplateHelper(op, 32) +src2, src1, rs1 = template_helper.get_test_inputs(n=5) +ref_vv = src2 * src1 +ref_vx = src2 * rs1 %>\ -${tests.test_opivv_opivx("int32_t", op, src1, src2, rs1, ref_vv, ref_vx)} +${tests.test_opivv_opivx(template_helper, src2, src1, rs1, ref_vv, ref_vx)}
diff --git a/softrvv/tests/templates/softrvv_vmulh_test.tpl.cpp b/softrvv/tests/templates/softrvv_vmulh_test.tpl.cpp index 5a77585..60accea 100644 --- a/softrvv/tests/templates/softrvv_vmulh_test.tpl.cpp +++ b/softrvv/tests/templates/softrvv_vmulh_test.tpl.cpp
@@ -2,10 +2,12 @@ <%namespace name="tests" file="opivv_opivx_test.tpl.cpp"/> <% import numpy as np -src1, src2, rs1 = parent.module.get_test_inputs(np.int32, N=5) +import vec_test_helpers +template_helper = vec_test_helpers.VecTemplateHelper(op, 32) +src2, src1, rs1 = template_helper.get_test_inputs(n=5) ref_vv = np.right_shift( - src1.astype(np.int64) * src2.astype(np.int64), 32).astype(np.int32) + src2.astype(np.int64) * src1.astype(np.int64), 32).astype(np.int32) ref_vx = np.right_shift( - src1.astype(np.int64) * rs1, 32).astype(np.int32) + src2.astype(np.int64) * rs1, 32).astype(np.int32) %> -${tests.test_opivv_opivx("int32_t", op, src1, src2, rs1, ref_vv, ref_vx)} +${tests.test_opivv_opivx(template_helper, src2, src1, rs1, ref_vv, ref_vx)}
diff --git a/softrvv/tests/templates/softrvv_vnsrl_test.tpl.cpp b/softrvv/tests/templates/softrvv_vnsrl_test.tpl.cpp new file mode 100644 index 0000000..e7c07fc --- /dev/null +++ b/softrvv/tests/templates/softrvv_vnsrl_test.tpl.cpp
@@ -0,0 +1,16 @@ +<%inherit file="base.tpl.cpp"/>\ +<%namespace name="tests" file="opivv_opivx_test.tpl.cpp"/> +<% +import numpy as np +import vec_test_helpers +template_helper = vec_test_helpers.VecTemplateHelper(op, 16) +N = 5 +src2, src1, rs1 = template_helper.get_test_inputs(n=N) +src2_type = template_helper.get_np_src2_type() +tmp_src1 = src1 & (src2_type(0).itemsize * 8 -1) +dest_type = template_helper.get_np_dest_type() +ref_vv = np.right_shift(vec_test_helpers.cast_to_unsigned(src2), tmp_src1).astype(dest_type) +tmp_rs1 = rs1 & (src2_type(0).itemsize * 8 - 1) +ref_vx = np.right_shift(vec_test_helpers.cast_to_unsigned(src2), tmp_rs1).astype(dest_type) +%>\ +${tests.test_opivv_opivx(template_helper, src2, src1, rs1, ref_vv, ref_vx)}
diff --git a/softrvv/tests/templates/softrvv_vrem_test.tpl.cpp b/softrvv/tests/templates/softrvv_vrem_test.tpl.cpp index 33c42b4..79f6e62 100644 --- a/softrvv/tests/templates/softrvv_vrem_test.tpl.cpp +++ b/softrvv/tests/templates/softrvv_vrem_test.tpl.cpp
@@ -2,8 +2,12 @@ <%namespace name="tests" file="opivv_opivx_test.tpl.cpp"/> <% import numpy as np -src1, src2, rs1 = parent.module.get_test_inputs(np.uint32, N=5, allow_zero=False) -ref_vv = np.mod(src1,src2).astype(np.uint32) -ref_vx = np.mod(src1, rs1).astype(np.uint32) +import vec_test_helpers +template_helper = vec_test_helpers.VecTemplateHelper(op, 32) +template_helper.force_unsigned = True +src2, src1, rs1 = template_helper.get_test_inputs(n=5, allow_zero=False) +dest_type = template_helper.get_np_dest_type() +ref_vv = np.mod(src2,src1).astype(dest_type) +ref_vx = np.mod(src2, rs1).astype(dest_type) %>\ -${tests.test_opivv_opivx("uint32_t", op, src1, src2, rs1, ref_vv, ref_vx)} +${tests.test_opivv_opivx(template_helper, src2, src1, rs1, ref_vv, ref_vx)}
diff --git a/softrvv/tests/templates/softrvv_vsll_test.tpl.cpp b/softrvv/tests/templates/softrvv_vsll_test.tpl.cpp index 5c6b102..262d7b2 100644 --- a/softrvv/tests/templates/softrvv_vsll_test.tpl.cpp +++ b/softrvv/tests/templates/softrvv_vsll_test.tpl.cpp
@@ -2,10 +2,13 @@ <%namespace name="tests" file="opivv_opivx_test.tpl.cpp"/> <% import numpy as np -src1, src2, rs1 = parent.module.get_test_inputs(np.int32, N=5) -tmp_src2 = src2 & (np.int32(0).itemsize * 8 -1) -ref_vv = np.left_shift(src1, tmp_src2) +import vec_test_helpers +template_helper = vec_test_helpers.VecTemplateHelper(op, 32) +template_helper.force_unsigned = True +src2, src1, rs1 = template_helper.get_test_inputs(n=5) +tmp_src1 = src1 & (np.int32(0).itemsize * 8 -1) +ref_vv = np.left_shift(src2, tmp_src1) tmp_rs1 = rs1 & (np.int32(0).itemsize * 8 - 1) -ref_vx = np.left_shift(src1, tmp_rs1) +ref_vx = np.left_shift(src2, tmp_rs1) %>\ -${tests.test_opivv_opivx("int32_t", op, src1, src2, rs1, ref_vv, ref_vx)} +${tests.test_opivv_opivx(template_helper, src2, src1, rs1, ref_vv, ref_vx)}
diff --git a/softrvv/tests/templates/softrvv_vsra_test.tpl.cpp b/softrvv/tests/templates/softrvv_vsra_test.tpl.cpp index 45ef61d..ebcee5f 100644 --- a/softrvv/tests/templates/softrvv_vsra_test.tpl.cpp +++ b/softrvv/tests/templates/softrvv_vsra_test.tpl.cpp
@@ -2,10 +2,14 @@ <%namespace name="tests" file="opivv_opivx_test.tpl.cpp"/> <% import numpy as np -src1, src2, rs1 = parent.module.get_test_inputs(np.int32, N=5) -tmp_src2 = src2 & (np.int32(0).itemsize * 8 -1) -ref_vv = np.right_shift(src1, tmp_src2) -tmp_rs1 = rs1 & (np.int32(0).itemsize * 8 - 1) -ref_vx = np.right_shift(src1, tmp_rs1) +import vec_test_helpers +template_helper = vec_test_helpers.VecTemplateHelper(op, 32) +template_helper.force_unsigned = True +src2, src1, rs1 = template_helper.get_test_inputs(n=5) +src2_type = template_helper.get_np_src2_type() +tmp_src1 = src1 & (src2_type(0).itemsize * 8 -1) +ref_vv = np.right_shift(src2, tmp_src1) +tmp_rs1 = rs1 & (src2_type(0).itemsize * 8 - 1) +ref_vx = np.right_shift(src2, tmp_rs1) %>\ -${tests.test_opivv_opivx("int32_t", op, src1, src2, rs1, ref_vv, ref_vx)} +${tests.test_opivv_opivx(template_helper, src2, src1, rs1, ref_vv, ref_vx)}
diff --git a/softrvv/tests/templates/softrvv_vsrl_test.tpl.cpp b/softrvv/tests/templates/softrvv_vsrl_test.tpl.cpp index 0a3f95f..f858108 100644 --- a/softrvv/tests/templates/softrvv_vsrl_test.tpl.cpp +++ b/softrvv/tests/templates/softrvv_vsrl_test.tpl.cpp
@@ -2,10 +2,14 @@ <%namespace name="tests" file="opivv_opivx_test.tpl.cpp"/> <% import numpy as np -src1, src2, rs1 = parent.module.get_test_inputs(np.int32, N=5) -tmp_src2 = src2 & (np.int32(0).itemsize * 8 -1) -ref_vv = np.right_shift(src1.astype(np.uint32), tmp_src2).astype(np.int32) -tmp_rs1 = rs1 & (np.int32(0).itemsize * 8 - 1) -ref_vx = np.right_shift(src1.astype(np.uint32), tmp_rs1).astype(np.int32) +import vec_test_helpers +template_helper = vec_test_helpers.VecTemplateHelper(op, 32) +src2, src1, rs1 = template_helper.get_test_inputs(n=5) +src1_type = template_helper.get_np_src1_type() +tmp_src1 = src1 & (src1_type(0).itemsize * 8 -1) +dest_type = template_helper.get_np_dest_type() +ref_vv = np.right_shift(vec_test_helpers.cast_to_unsigned(src2), tmp_src1).astype(dest_type) +tmp_rs1 = rs1 & (src1_type(0).itemsize * 8 - 1) +ref_vx = np.right_shift(vec_test_helpers.cast_to_unsigned(src2), tmp_rs1).astype(dest_type) %>\ -${tests.test_opivv_opivx("int32_t", op, src1, src2, rs1, ref_vv, ref_vx)} +${tests.test_opivv_opivx(template_helper, src2, src1, rs1, ref_vv, ref_vx)}
diff --git a/softrvv/tests/templates/softrvv_vsub_test.tpl.cpp b/softrvv/tests/templates/softrvv_vsub_test.tpl.cpp index 9facf2a..0663f4b 100644 --- a/softrvv/tests/templates/softrvv_vsub_test.tpl.cpp +++ b/softrvv/tests/templates/softrvv_vsub_test.tpl.cpp
@@ -2,8 +2,10 @@ <%namespace name="tests" file="opivv_opivx_test.tpl.cpp"/> <% import numpy as np -src1, src2, rs1 = parent.module.get_test_inputs(np.int32, N=5) -ref_vv = src1 - src2 -ref_vx = src1 - rs1 +import vec_test_helpers +template_helper = vec_test_helpers.VecTemplateHelper(op, 32) +src2, src1, rs1 = template_helper.get_test_inputs(n=5) +ref_vv = src2 - src1 +ref_vx = src2 - rs1 %>\ -${tests.test_opivv_opivx("int32_t", op, src1, src2, rs1, ref_vv, ref_vx)} +${tests.test_opivv_opivx(template_helper, src2, src1, rs1, ref_vv, ref_vx)}
diff --git a/softrvv/tests/templates/softrvv_vxor_test.tpl.cpp b/softrvv/tests/templates/softrvv_vxor_test.tpl.cpp index e87343b..7808a44 100644 --- a/softrvv/tests/templates/softrvv_vxor_test.tpl.cpp +++ b/softrvv/tests/templates/softrvv_vxor_test.tpl.cpp
@@ -2,8 +2,10 @@ <%namespace name="tests" file="opivv_opivx_test.tpl.cpp"/> <% import numpy as np -src1, src2, rs1 = parent.module.get_test_inputs(np.int32, N=5) -ref_vv = np.bitwise_xor(src1, src2) -ref_vx = np.bitwise_xor(src1, rs1) +import vec_test_helpers +template_helper = vec_test_helpers.VecTemplateHelper(op, 32) +src2, src1, rs1 = template_helper.get_test_inputs(n=5) +ref_vv = np.bitwise_xor(src2, src1) +ref_vx = np.bitwise_xor(src2, rs1) %>\ -${tests.test_opivv_opivx("int32_t", op, src1, src2, rs1, ref_vv, ref_vx)} +${tests.test_opivv_opivx(template_helper, src2, src1, rs1, ref_vv, ref_vx)}
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 4a8ed75..e1de24d 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt
@@ -246,6 +246,15 @@ -Xlinker --defsym=__itcm_length__=192K ) +vec_cc_generated_test( + NAME + vnsrl + TEMPLATE + opivv_opivx_opivi_test.tpl.cpp + LINKOPTS + -Xlinker --defsym=__itcm_length__=192K +) + vec_cc_test( NAME vsetvl_test
diff --git a/tests/templates/base_opivi_test.tpl.cpp b/tests/templates/base_opivi_test.tpl.cpp index a3df734..64aa5e0 100644 --- a/tests/templates/base_opivi_test.tpl.cpp +++ b/tests/templates/base_opivi_test.tpl.cpp
@@ -1,3 +1,6 @@ +<%! +import vec_test_helpers +%>\ <%def name="test_opivi(op_code)"> namespace ${op_code}_vi_test { namespace { @@ -14,55 +17,18 @@ void TearDown() override { zero_vector_registers(); } }; <% -import vec_test_helpers -sews = vec_test_helpers.get_sews(op_code) -lmuls = vec_test_helpers.get_lmuls(op_code) -imms = vec_test_helpers.get_imms(op_code) +template_helper = vec_test_helpers.VecTemplateHelper(op_code) +sews = template_helper.get_sews() +lmuls = template_helper.get_lmuls() +imms = template_helper.get_imms() %>\ -% for test_val in imms: +% for imm in imms: % for sew in sews: % for lmul in lmuls: <% -var_type = "int%d_t" % sew +template_helper.sew = sew %>\ - -TEST_F(${op_code.capitalize()}Test, ${op_code.lower()}_vi${sew}m${lmul}simm5_${("%s" % test_val).replace('-','n')}) { - for (int i = 0; i < AVL_COUNT; i++) { - int32_t avl = AVLS[i]; - int vlmax; - int vl; - const ${var_type} test_val = ${test_val}; - - std::tie(vlmax, vl) = vector_test_setup<${var_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); - // set up values to test up to index of the AVL - fill_random_vector<${var_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); - - // Load vector registers - __asm__ volatile("vle${sew}.v v8, (%0)" : : "r"(ptr_vec_1)); - - // Run target instruction - __asm__ volatile("${op_code}.vi v24, v8, %[SIMM5]" ::[SIMM5] "n"(test_val)); - - // Store result vector register - __asm__ volatile("vse${sew}.v v24, (%0)" : : "r"(ptr_dest_vec)); - - // Check vector elements - assert_vec_elem_eq<${var_type}>(vlmax, dest_vector, ref_dest_vector); - } -} +${insert_vi_test(template_helper, lmul, imm)} %endfor %endfor %endfor @@ -71,3 +37,72 @@ } // namespace ${op_code}_vi_test </%def> +<%def name="insert_vi_test(template_helper, lmul, imm)"> +<% +# Initialize the variables for a given test config +op_code = template_helper.op_code +sew = template_helper.sew +ref_opcode = template_helper.get_ref_opcode() +dest_sew, src2_sew, _, __ = template_helper.get_sew_sizes() +datatypes = template_helper.get_softrvv_template_data_type() +var_types = template_helper.get_var_types() +mnemonic = template_helper.get_mnemonic( + vec_test_helpers.VecTemplateHelper.OperandType.IMMEDIATE) +is_narrowing = template_helper.is_narrowing() +is_widening = template_helper.is_widening() +%>\ +TEST_F(${op_code.capitalize()}Test, ${mnemonic.lower().replace(".","_")}${sew}m${lmul}simm5_${("%s" % imm).replace('-','n')}) { + for (int i = 0; i < AVL_COUNT; i++) { + int32_t avl = AVLS[i]; + int vlmax; + int vl; + const ${var_types.imm_type} test_val = ${imm}; +% if is_narrowing: + /* When a narrowing instruction is used sew matches dest size */ + vector_test_setup<${var_types.src2_type}>( + VLMUL::LMUL_M${lmul}, avl, + {src_vector_1}); + std::tie(vlmax, vl) = vector_test_setup<${var_types.dest_type}>( + VLMUL::LMUL_M${lmul}, avl, + {dest_vector, ref_dest_vector}); +% elif is_widening: + /* When a widening instruction is used sew matches src2 size */ + vector_test_setup<${var_types.dest_type}>( + VLMUL::LMUL_M${lmul}, avl, + {dest_vector, ref_dest_vector}); + std::tie(vlmax, vl) = vector_test_setup<${var_types.src2_type}>( + VLMUL::LMUL_M${lmul}, avl, + {src_vector_1}); +% else: + /* For non narrowing instructions all vectors have same type*/ + std::tie(vlmax, vl) = vector_test_setup<${var_types.dest_type}>( + VLMUL::LMUL_M${lmul}, avl, + {dest_vector, ref_dest_vector, src_vector_1}); +% endif + if (avl > vlmax) { + continue; + } + ${var_types.src2_type} *ptr_vec_1 = reinterpret_cast<${var_types.src2_type} *>(src_vector_1); + ${var_types.dest_type} *ptr_dest_vec = reinterpret_cast<${var_types.dest_type} *>(dest_vector); + ${var_types.dest_type} *ptr_ref_dest_vec = reinterpret_cast<${var_types.dest_type} *>(ref_dest_vector); + // set up values to test up to index of the AVL + fill_random_vector<${var_types.src2_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<${datatypes}>(ptr_ref_dest_vec, ptr_vec_1, &test_val, avl); + + // Load vector registers + __asm__ volatile("vle${src2_sew}.v v8, (%0)" : : "r"(ptr_vec_1)); + + // Run target instruction + __asm__ volatile("${mnemonic} v24, v8, %[SIMM5]" ::[SIMM5] "n"(test_val)); + + // Store result vector register + __asm__ volatile("vse${dest_sew}.v v24, (%0)" : : "r"(ptr_dest_vec)); + + // Check vector elements + assert_vec_elem_eq<${var_types.dest_type}>(vlmax, dest_vector, ref_dest_vector); + } +} +</%def>
diff --git a/tests/templates/base_opivv_test.tpl.cpp b/tests/templates/base_opivv_test.tpl.cpp index 35b92b8..a7aba2f 100644 --- a/tests/templates/base_opivv_test.tpl.cpp +++ b/tests/templates/base_opivv_test.tpl.cpp
@@ -1,3 +1,6 @@ +<%! +import vec_test_helpers +%>\ <%def name="test_opivv(op_code)"> namespace ${op_code}_vv_test { namespace { @@ -15,63 +18,16 @@ void TearDown() override { zero_vector_registers(); } }; <% -import vec_test_helpers -sews = vec_test_helpers.get_sews(op_code) -lmuls = vec_test_helpers.get_lmuls(op_code) +template_helper = vec_test_helpers.VecTemplateHelper(op_code) +sews = template_helper.get_sews() +lmuls = template_helper.get_lmuls() %>\ % for sew in sews: % for lmul in lmuls: <% -dest_type = vec_test_helpers.get_dest_type(op_code, sew) -src_type = vec_test_helpers.get_src_type(op_code, sew) -ref_opcode = vec_test_helpers.get_ref_opcode(op_code) -widening = vec_test_helpers.is_widening(op_code) +template_helper.sew = sew %>\ -TEST_F(${op_code.capitalize()}Test, ${op_code.lower()}_vv${sew}m${lmul}) { - for (int i = 0; i < AVL_COUNT; i++) { - int32_t avl = AVLS[i]; - int vlmax; - int vl; - 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; - } - ${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<${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 -% 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)); - - // Run target instruction - __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<${dest_type}>(vlmax, dest_vector, ref_dest_vector); - } -} +${insert_vv_test(template_helper, lmul)} %endfor %endfor @@ -79,3 +35,81 @@ } // namespace ${op_code}_vv_test </%def> +<%def name="insert_vv_test(template_helper, lmul)"> +<% +# Initialize the variables for a given test config +op_code = template_helper.op_code +sew = template_helper.sew +ref_opcode = template_helper.get_ref_opcode() +dest_sew, src2_sew, src1_sew, _ = template_helper.get_sew_sizes() +datatypes = template_helper.get_softrvv_template_data_type() +var_types = template_helper.get_var_types() +mnemonic = template_helper.get_mnemonic( + vec_test_helpers.VecTemplateHelper.OperandType.VECTOR) +is_narrowing = template_helper.is_narrowing() +is_widening = template_helper.is_widening() +%>\ +TEST_F(${op_code.capitalize()}Test, ${mnemonic.lower().replace(".","_")}${sew}m${lmul}) { + for (int i = 0; i < AVL_COUNT; i++) { + int32_t avl = AVLS[i]; + int vlmax; + int vl; +% if is_narrowing: + vector_test_setup<${var_types.src2_type}>( + VLMUL::LMUL_M${lmul}, avl, + {src_vector_2}); + vector_test_setup<${var_types.src1_type}>( + VLMUL::LMUL_M${lmul}, avl, + {src_vector_1}); + /* When a narrowing instruction is used sew matches dest size */ + std::tie(vlmax, vl) = vector_test_setup<${var_types.dest_type}>( + VLMUL::LMUL_M${lmul}, avl, + {dest_vector, ref_dest_vector}); +% elif is_widening: + /* When a widening instruction is used sew matches src2 size */ + vector_test_setup<${var_types.dest_type}>( + VLMUL::LMUL_M${lmul}, avl, + {dest_vector, ref_dest_vector}); + vector_test_setup<${var_types.src1_type}>( + VLMUL::LMUL_M${lmul}, avl, + {src_vector_1}); + std::tie(vlmax, vl) = vector_test_setup<${var_types.src2_type}>( + VLMUL::LMUL_M${lmul}, avl, + {src_vector_2}); +% else: + /* For non narrowing instructions all vectors have same type*/ + std::tie(vlmax, vl) = vector_test_setup<${var_types.dest_type}>( + VLMUL::LMUL_M${lmul}, avl, + {dest_vector, ref_dest_vector, src_vector_1}); +% endif + + if (avl > vlmax) { + continue; + } + ${var_types.src1_type} *ptr_vec_1 = reinterpret_cast<${var_types.src1_type} *>(src_vector_1); + ${var_types.src2_type} *ptr_vec_2 = reinterpret_cast<${var_types.src2_type} *>(src_vector_2); + ${var_types.dest_type} *ptr_dest_vec = reinterpret_cast<${var_types.dest_type} *>(dest_vector); + ${var_types.dest_type} *ptr_ref_dest_vec = reinterpret_cast<${var_types.dest_type} *>(ref_dest_vector); + + // set up values to test up to index of the AVL + fill_random_vector<${var_types.src1_type}>(ptr_vec_1, avl); + fill_random_vector<${var_types.src2_type}>(ptr_vec_2, avl); + memset(dest_vector, 0, MAXVL_BYTES); + memset(ref_dest_vector, 0, MAXVL_BYTES); + + // Generate reference vector + softrvv::${ref_opcode}_vv<${datatypes}>(ptr_ref_dest_vec, ptr_vec_2, ptr_vec_1, avl); + // Load vector registers + __asm__ volatile("vle${src1_sew}.v v8, (%0)" : : "r"(ptr_vec_1)); + __asm__ volatile("vle${src2_sew}.v v16, (%0)" : : "r"(ptr_vec_2)); + + // Run target instruction + __asm__ volatile("${mnemonic} v24, v16, v8"); + + // Store result vector register + __asm__ volatile("vse${dest_sew}.v v24, (%0)" : : "r"(ptr_dest_vec)); + // Check vector elements + assert_vec_elem_eq<${var_types.dest_type}>(vlmax, dest_vector, ref_dest_vector); + } +} +</%def>
diff --git a/tests/templates/base_opivx_test.tpl.cpp b/tests/templates/base_opivx_test.tpl.cpp index 8feaeb4..0800a34 100644 --- a/tests/templates/base_opivx_test.tpl.cpp +++ b/tests/templates/base_opivx_test.tpl.cpp
@@ -1,10 +1,13 @@ +<%! +import vec_test_helpers +%>\ <%def name="test_opivx(op_code)"> namespace ${op_code}_vx_test { namespace { using namespace test_v_helpers; -uint8_t src_vector_1[MAXVL_BYTES]; +uint8_t src_vector_2[MAXVL_BYTES]; uint8_t dest_vector[MAXVL_BYTES]; uint8_t ref_dest_vector[MAXVL_BYTES]; @@ -14,60 +17,16 @@ void TearDown() override { zero_vector_registers(); } }; <% -import vec_test_helpers -sews = vec_test_helpers.get_sews(op_code) -lmuls = vec_test_helpers.get_lmuls(op_code) +template_helper = vec_test_helpers.VecTemplateHelper(op_code) +sews = template_helper.get_sews() +lmuls = template_helper.get_lmuls() %>\ % for sew in sews: % for lmul in lmuls: <% -dest_type = vec_test_helpers.get_dest_type(op_code, sew) -src_type = vec_test_helpers.get_src_type(op_code, sew) -ref_opcode = vec_test_helpers.get_ref_opcode(op_code) -widening = vec_test_helpers.is_widening(op_code) +template_helper.sew = sew %>\ -TEST_F(${op_code.capitalize()}Test, ${op_code.lower()}_vx${sew}m${lmul}) { - for (int i = 0; i < AVL_COUNT; i++) { - int32_t avl = AVLS[i]; - int vlmax; - int vl; - 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; - } - ${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<${src_type}>(ptr_vec_1, avl); - memset(dest_vector, 0, MAXVL_BYTES); - memset(ref_dest_vector, 0, MAXVL_BYTES); - - // Generate reference vector -% 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)); - - // Run target instruction - __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<${dest_type}>(vlmax, dest_vector, ref_dest_vector); - } -} +${insert_vx_test(template_helper, lmul)} %endfor %endfor @@ -75,3 +34,72 @@ } // namespace ${op_code}_vx_test </%def> +<%def name="insert_vx_test(template_helper, lmul)"> +<% +# Initialize the variables for a given test config +op_code = template_helper.op_code +sew = template_helper.sew +ref_opcode = template_helper.get_ref_opcode() +dest_sew, src2_sew, _, __ = template_helper.get_sew_sizes() +datatypes = template_helper.get_softrvv_template_data_type() +var_types = template_helper.get_var_types() +mnemonic = template_helper.get_mnemonic( + vec_test_helpers.VecTemplateHelper.OperandType.SCALAR) +is_narrowing = template_helper.is_narrowing() +is_widening = template_helper.is_widening() +%>\ +TEST_F(${op_code.capitalize()}Test, ${mnemonic.lower().replace(".","_")}${sew}m${lmul}) { + for (int i = 0; i < AVL_COUNT; i++) { + int32_t avl = AVLS[i]; + int vlmax; + int vl; +% if is_narrowing: + /* When a narrowing instruction is used sew matches dest size */ + vector_test_setup<${var_types.src2_type}>( + VLMUL::LMUL_M${lmul}, avl, + {src_vector_2}); + /* SEW is set to size of dest type */ + std::tie(vlmax, vl) = vector_test_setup<${var_types.dest_type}>( + VLMUL::LMUL_M${lmul}, avl, + {dest_vector, ref_dest_vector}); +% elif is_widening: + /* When a widening instruction is used sew matches src2 size */ + vector_test_setup<${var_types.dest_type}>( + VLMUL::LMUL_M${lmul}, avl, + {dest_vector, ref_dest_vector}); + std::tie(vlmax, vl) = vector_test_setup<${var_types.src2_type}>( + VLMUL::LMUL_M${lmul}, avl, + {src_vector_2}); +% else: + /* For non narrowing instructions all vectors have same type*/ + std::tie(vlmax, vl) = vector_test_setup<${var_types.dest_type}>( + VLMUL::LMUL_M${lmul}, avl, + {dest_vector, ref_dest_vector, src_vector_2}); +% endif + if (avl > vlmax) { + continue; + } + ${var_types.src2_type} *ptr_vec_2 = reinterpret_cast<${var_types.src2_type} *>(src_vector_2); + ${var_types.imm_type} test_val = static_cast<${var_types.imm_type}>(rand()); + ${var_types.dest_type} *ptr_dest_vec = reinterpret_cast<${var_types.dest_type} *>(dest_vector); + ${var_types.dest_type} *ptr_ref_dest_vec = reinterpret_cast<${var_types.dest_type} *>(ref_dest_vector); + // set up values to test up to index of the AVL + fill_random_vector<${var_types.src2_type}>(ptr_vec_2, avl); + memset(dest_vector, 0, MAXVL_BYTES); + memset(ref_dest_vector, 0, MAXVL_BYTES); + + // Generate reference vector + softrvv::${ref_opcode}_vx<${datatypes}>(ptr_ref_dest_vec, ptr_vec_2, &test_val, avl); + // Load vector registers + __asm__ volatile("vle${src2_sew}.v v8, (%0)" : : "r"(ptr_vec_2)); + + // Run target instruction + __asm__ volatile("${mnemonic} v24, v8, %[RS1]" ::[RS1] "r"(test_val)); + + // Store result vector register + __asm__ volatile("vse${dest_sew}.v v24, (%0)" : : "r"(ptr_dest_vec)); + // Check vector elements + assert_vec_elem_eq<${var_types.dest_type}>(vlmax, dest_vector, ref_dest_vector); + } +} +</%def>