Merge "gloss: _write takes a buffer of arbitrary length, not a C string"
diff --git a/scripts/vec_test_helpers/__init__.py b/scripts/vec_test_helpers/__init__.py index 10511f8..87f457e 100644 --- a/scripts/vec_test_helpers/__init__.py +++ b/scripts/vec_test_helpers/__init__.py
@@ -2,47 +2,235 @@ 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_destination_mask_register(self): + """Check if a particular op_code has a mask output.""" + int_comparison_ops = ('vmseq', 'vmsne', 'vmsltu', 'vmsleu', 'vmsle', 'vmsgtu', 'vmsgt') + return self.op_code in int_comparison_ops + + 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 pack_dest_mask(self, values): + """Pack values into a single destination register.""" + dest_type = self.get_np_dest_type() + return np.packbits(dest_type(values), bitorder='little') + +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..5595634 100644 --- a/softrvv/include/softrvv.h +++ b/softrvv/include/softrvv.h
@@ -4,12 +4,21 @@ #include <stddef.h> #include "encoding.h" +#include "softrvv_internal.h" #include "softrvv_vadd.h" #include "softrvv_vand.h" #include "softrvv_vdiv.h" #include "softrvv_vmax.h" #include "softrvv_vmin.h" #include "softrvv_vmul_vmulh.h" +#include "softrvv_vmseq.h" +#include "softrvv_vmsgt.h" +#include "softrvv_vmsge.h" +#include "softrvv_vmsle.h" +#include "softrvv_vmslt.h" +#include "softrvv_vmsne.h" +#include "softrvv_vnsra.h" +#include "softrvv_vnsrl.h" #include "softrvv_vor.h" #include "softrvv_vrem.h" #include "softrvv_vsext_vzext.h"
diff --git a/softrvv/include/softrvv_internal.h b/softrvv/include/softrvv_internal.h new file mode 100644 index 0000000..e4475a5 --- /dev/null +++ b/softrvv/include/softrvv_internal.h
@@ -0,0 +1,40 @@ +#ifndef SOFTRVV_INTERNAL_H +#define SOFTRVV_INTERNAL_H + +#include <bit> +#include <tuple> + +namespace softrvv { + +template <typename T> +inline std::tuple<int, int>get_element_and_pos(unsigned int index) { + // bw_required is the number of bits required to store the value + const unsigned int bw_required = std::__bit_width(sizeof(T)* 8); + const unsigned int shift = bw_required - 1; + // shift is the number of bits required to store the value minus 1 + // Example for T is int32_t: + // 32 requires 6 bits to store, the shift required to divide by 32 is 5 (6 - 1) + // Shift of the index is equivalent to a divide + unsigned int element_idx = index >> shift; + // Masked lowers bits are equivalent to remainder + unsigned int element_pos = index & ~(element_idx << shift); + return std::make_tuple(element_idx, element_pos); +} + +template <typename T> +inline void set_bit_in_dest_mask(unsigned int index, T *dest, bool set_bit) { + unsigned int element_idx; + unsigned int element_pos; + std::tie(element_idx, element_pos) = get_element_and_pos<T>(index); + T *dest_eptr = dest + element_idx; + if (set_bit) { + // Set the target bit + *dest_eptr |= (1 << element_pos); + } else { + // Clear the target bit + *dest_eptr &= ~(1 << element_pos); + } +} + +} // namespace softrvv +#endif // SOFTRVV_INTERNAL_H
diff --git a/softrvv/include/softrvv_vmseq.h b/softrvv/include/softrvv_vmseq.h new file mode 100644 index 0000000..05bf2f3 --- /dev/null +++ b/softrvv/include/softrvv_vmseq.h
@@ -0,0 +1,25 @@ +#ifndef SOFTRVV_VMSEQ_H +#define SOFTRVV_VMSEQ_H + +#include <stddef.h> +#include <stdint.h> + +namespace softrvv { + +template <typename T> +void vmseq_vx(T *dest, T *src2, const T *src1, int32_t avl) { + for (int32_t idx = 0; idx < avl; idx++) { + set_bit_in_dest_mask<T>(idx, dest, src2[idx] == *src1); + } +} + +template <typename T> +void vmseq_vv(T *dest, T *src2, T *src1, int32_t avl) { + for (int32_t idx = 0; idx < avl; idx++) { + set_bit_in_dest_mask<T>(idx, dest, src2[idx] == src1[idx]); + } +} + +} // namespace softrvv + +#endif // SOFTRVV_VMSEQ_H
diff --git a/softrvv/include/softrvv_vmsge.h b/softrvv/include/softrvv_vmsge.h new file mode 100644 index 0000000..90738ee --- /dev/null +++ b/softrvv/include/softrvv_vmsge.h
@@ -0,0 +1,25 @@ +#ifndef SOFTRVV_VMSGE_H +#define SOFTRVV_VMSGE_H + +#include <stddef.h> +#include <stdint.h> + +namespace softrvv { + +template <typename T> +void vmsge_vx(T *dest, T *src2, const T *src1, int32_t avl) { + for (int32_t idx = 0; idx < avl; idx++) { + set_bit_in_dest_mask<T>(idx, dest, src2[idx] >= *src1); + } +} + +template <typename T> +void vmsge_vv(T *dest, T *src2, T *src1, int32_t avl) { + for (int32_t idx = 0; idx < avl; idx++) { + set_bit_in_dest_mask<T>(idx, dest, src2[idx] >= src1[idx]); + } +} + +} // namespace softrvv + +#endif // SOFTRVV_VMSGE_H
diff --git a/softrvv/include/softrvv_vmsgt.h b/softrvv/include/softrvv_vmsgt.h new file mode 100644 index 0000000..a3e7afe --- /dev/null +++ b/softrvv/include/softrvv_vmsgt.h
@@ -0,0 +1,25 @@ +#ifndef SOFTRVV_VMSGT_H +#define SOFTRVV_VMSGT_H + +#include <stddef.h> +#include <stdint.h> + +namespace softrvv { + +template <typename T> +void vmsgt_vx(T *dest, T *src2, const T *src1, int32_t avl) { + for (int32_t idx = 0; idx < avl; idx++) { + set_bit_in_dest_mask<T>(idx, dest, src2[idx] > *src1); + } +} + +template <typename T> +void vmsgt_vv(T *dest, T *src2, T *src1, int32_t avl) { + for (int32_t idx = 0; idx < avl; idx++) { + set_bit_in_dest_mask<T>(idx, dest, src2[idx] > src1[idx]); + } +} + +} // namespace softrvv + +#endif // SOFTRVV_VMSGT_H
diff --git a/softrvv/include/softrvv_vmsle.h b/softrvv/include/softrvv_vmsle.h new file mode 100644 index 0000000..a53c8d0 --- /dev/null +++ b/softrvv/include/softrvv_vmsle.h
@@ -0,0 +1,25 @@ +#ifndef SOFTRVV_VMSLE_H +#define SOFTRVV_VMSLE_H + +#include <stddef.h> +#include <stdint.h> + +namespace softrvv { + +template <typename T> +void vmsle_vx(T *dest, T *src2, const T *src1, int32_t avl) { + for (int32_t idx = 0; idx < avl; idx++) { + set_bit_in_dest_mask<T>(idx, dest, src2[idx] <= *src1); + } +} + +template <typename T> +void vmsle_vv(T *dest, T *src2, T *src1, int32_t avl) { + for (int32_t idx = 0; idx < avl; idx++) { + set_bit_in_dest_mask<T>(idx, dest, src2[idx] <= src1[idx]); + } +} + +} // namespace softrvv + +#endif // SOFTRVV_VMSLE_H
diff --git a/softrvv/include/softrvv_vmslt.h b/softrvv/include/softrvv_vmslt.h new file mode 100644 index 0000000..070c66a --- /dev/null +++ b/softrvv/include/softrvv_vmslt.h
@@ -0,0 +1,25 @@ +#ifndef SOFTRVV_VMSLT_H +#define SOFTRVV_VMSLT_H + +#include <stddef.h> +#include <stdint.h> + +namespace softrvv { + +template <typename T> +void vmslt_vx(T *dest, T *src2, const T *src1, int32_t avl) { + for (int32_t idx = 0; idx < avl; idx++) { + set_bit_in_dest_mask<T>(idx, dest, src2[idx] < *src1); + } +} + +template <typename T> +void vmslt_vv(T *dest, T *src2, T *src1, int32_t avl) { + for (int32_t idx = 0; idx < avl; idx++) { + set_bit_in_dest_mask<T>(idx, dest, src2[idx] < src1[idx]); + } +} + +} // namespace softrvv + +#endif // SOFTRVV_VMSLT_H
diff --git a/softrvv/include/softrvv_vmsne.h b/softrvv/include/softrvv_vmsne.h new file mode 100644 index 0000000..68b8378 --- /dev/null +++ b/softrvv/include/softrvv_vmsne.h
@@ -0,0 +1,25 @@ +#ifndef SOFTRVV_VMSNE_H +#define SOFTRVV_VMSNE_H + +#include <stddef.h> +#include <stdint.h> + +namespace softrvv { + +template <typename T> +void vmsne_vx(T *dest, T *src2, const T *src1, int32_t avl) { + for (int32_t idx = 0; idx < avl; idx++) { + set_bit_in_dest_mask<T>(idx, dest, src2[idx] != *src1); + } +} + +template <typename T> +void vmsne_vv(T *dest, T *src2, T *src1, int32_t avl) { + for (int32_t idx = 0; idx < avl; idx++) { + set_bit_in_dest_mask<T>(idx, dest, src2[idx] != src1[idx]); + } +} + +} // namespace softrvv + +#endif // SOFTRVV_VMSNE_H
diff --git a/softrvv/include/softrvv_vnsra.h b/softrvv/include/softrvv_vnsra.h new file mode 100644 index 0000000..7c81a14 --- /dev/null +++ b/softrvv/include/softrvv_vnsra.h
@@ -0,0 +1,31 @@ +#ifndef SOFTRVV_VNSRA_H +#define SOFTRVV_VNSRA_H + +#include <stddef.h> + +namespace softrvv { + +template <typename T1, typename T2> +void vnsra_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>(src1[idx] >> shift); + } +} + +template <typename T1, typename T2> +void vnsra_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>(src1[idx] >> (src2[idx] & low_bits_mask)); + } +} + +} // namespace softrvv + +#endif // SOFTRVV_VNSRA_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..fd87980 100644 --- a/softrvv/tests/CMakeLists.txt +++ b/softrvv/tests/CMakeLists.txt
@@ -188,6 +188,78 @@ -Xlinker --defsym=__itcm_length__=128K ) +softrvv_vec_cc_generated_test( + NAME + vnsrl + TEMPLATE + softrvv_vnsrl_test.tpl.cpp + LINKOPTS + -Xlinker --defsym=__itcm_length__=128K +) + +softrvv_vec_cc_generated_test( + NAME + vnsra + TEMPLATE + softrvv_vnsra_test.tpl.cpp + LINKOPTS + -Xlinker --defsym=__itcm_length__=128K +) + +softrvv_vec_cc_generated_test( + NAME + vmseq + TEMPLATE + softrvv_vmseq_test.tpl.cpp + LINKOPTS + -Xlinker --defsym=__itcm_length__=128K +) + +softrvv_vec_cc_generated_test( + NAME + vmsne + TEMPLATE + softrvv_vmsne_test.tpl.cpp + LINKOPTS + -Xlinker --defsym=__itcm_length__=128K +) + +softrvv_vec_cc_generated_test( + NAME + vmslt + TEMPLATE + softrvv_vmslt_test.tpl.cpp + LINKOPTS + -Xlinker --defsym=__itcm_length__=128K +) + +softrvv_vec_cc_generated_test( + NAME + vmsle + TEMPLATE + softrvv_vmsle_test.tpl.cpp + LINKOPTS + -Xlinker --defsym=__itcm_length__=128K +) + +softrvv_vec_cc_generated_test( + NAME + vmsgt + TEMPLATE + softrvv_vmsgt_test.tpl.cpp + LINKOPTS + -Xlinker --defsym=__itcm_length__=128K +) + +softrvv_vec_cc_generated_test( + NAME + vmsge + TEMPLATE + softrvv_vmsge_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..1586eb6 100644 --- a/softrvv/tests/templates/opivv_opivx_test.tpl.cpp +++ b/softrvv/tests/templates/opivv_opivx_test.tpl.cpp
@@ -1,26 +1,16 @@ -<%def name="test_opivv_opivx(dtype, op, src1, src2, rs1, ref_vv, ref_vx)"> +<%! +import vec_test_helpers +%>\ +<%def name="test_opivv_opivx(template_helper, src2, src1, 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) -%> -namespace softrvv_${op}_test { +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) { T *ptr_vec_1 = reinterpret_cast<T *>(test_vector_1); @@ -30,21 +20,63 @@ } } -class SoftRvv${op.capitalize()}Test : public ::testing::Test { +template <typename T> +void assert_vec_mask_eq(int avl, void *test_vector_1, void *test_vector_2) { + uint32_t *ptr_vec_1 = reinterpret_cast<uint32_t *>(test_vector_1); + uint32_t *ptr_vec_2 = reinterpret_cast<uint32_t *>(test_vector_2); + for (int idx = 0; idx < avl; idx++) { + const int bits_in_element = sizeof(uint32_t) * 8; + int eidx = idx / bits_in_element; + int epos = idx % bits_in_element; + uint32_t *e1 = ptr_vec_1 + eidx; + uint32_t *e2 = ptr_vec_2 + eidx; + ASSERT_EQ(*e1 & (1 << epos), *e2 & (1 << epos)); + } +} + +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> +} // 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[kAVL] = {${ref_vv}}; +${var_types.dest_type} ref_vx[kAVL] = {${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);\ +${insert_check(template_helper, var_types.dest_type, "ref_vv")}\ +} + +TEST_F(SoftRvv${template_helper.op_code.capitalize()}Test, VX) { + softrvv::${template_helper.op_code}_vx<${datatypes}>(dest, src2, &rs1, kAVL);\ +${insert_check(template_helper, var_types.dest_type, "ref_vx")}\ +} +</%def>\ + +<%def name="insert_check(template_helper, dest_type, ref_var)"> +% if template_helper.is_destination_mask_register(): + assert_vec_mask_eq<${dest_type}>(kAVL, dest, ${ref_var}); +% else: + assert_vec_elem_eq<${dest_type}>(kAVL, dest, ${ref_var}); +% endif +</%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_vmseq_test.tpl.cpp b/softrvv/tests/templates/softrvv_vmseq_test.tpl.cpp new file mode 100644 index 0000000..744d971 --- /dev/null +++ b/softrvv/tests/templates/softrvv_vmseq_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 +N = 8 +M = 3 +template_helper = vec_test_helpers.VecTemplateHelper(op, 32) +src2, src1, rs1 = template_helper.get_test_inputs(n=N) +indices = np.random.choice(src2.shape[0], M, replace=False) +src1[indices] = rs1 +src2[indices] = rs1 +ref_vv = template_helper.pack_dest_mask(src2 == src1) +ref_vx = template_helper.pack_dest_mask(src2 == rs1) +%>\ +${tests.test_opivv_opivx(template_helper, src2, src1, rs1, ref_vv, ref_vx)}
diff --git a/softrvv/tests/templates/softrvv_vmsge_test.tpl.cpp b/softrvv/tests/templates/softrvv_vmsge_test.tpl.cpp new file mode 100644 index 0000000..82bbe77 --- /dev/null +++ b/softrvv/tests/templates/softrvv_vmsge_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 +N = 8 +M = 3 +template_helper = vec_test_helpers.VecTemplateHelper(op, 32) +src2, src1, rs1 = template_helper.get_test_inputs(n=N) +indices = np.random.choice(src2.shape[0], M, replace=False) +src1[indices] = rs1 +src2[indices] = rs1 +ref_vv = template_helper.pack_dest_mask(src2 >= src1) +ref_vx = template_helper.pack_dest_mask(src2 >= rs1) +%>\ +${tests.test_opivv_opivx(template_helper, src2, src1, rs1, ref_vv, ref_vx)}
diff --git a/softrvv/tests/templates/softrvv_vmsgt_test.tpl.cpp b/softrvv/tests/templates/softrvv_vmsgt_test.tpl.cpp new file mode 100644 index 0000000..5deb454 --- /dev/null +++ b/softrvv/tests/templates/softrvv_vmsgt_test.tpl.cpp
@@ -0,0 +1,12 @@ +<%inherit file="base.tpl.cpp"/>\ +<%namespace name="tests" file="opivv_opivx_test.tpl.cpp"/> +<% +import numpy as np +import vec_test_helpers +N = 8 +template_helper = vec_test_helpers.VecTemplateHelper(op, 32) +src2, src1, rs1 = template_helper.get_test_inputs(n=N) +ref_vv = template_helper.pack_dest_mask(src2 > src1) +ref_vx = template_helper.pack_dest_mask(src2 > rs1) +%>\ +${tests.test_opivv_opivx(template_helper, src2, src1, rs1, ref_vv, ref_vx)}
diff --git a/softrvv/tests/templates/softrvv_vmsle_test.tpl.cpp b/softrvv/tests/templates/softrvv_vmsle_test.tpl.cpp new file mode 100644 index 0000000..07a1ab1 --- /dev/null +++ b/softrvv/tests/templates/softrvv_vmsle_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 +N = 8 +M = 2 +template_helper = vec_test_helpers.VecTemplateHelper(op, 32) +src2, src1, rs1 = template_helper.get_test_inputs(n=N) +indices = np.random.choice(src2.shape[0], M, replace=False) +src1[indices] = rs1 +src2[indices] = rs1 +ref_vv = template_helper.pack_dest_mask(src2 <= src1) +ref_vx = template_helper.pack_dest_mask(src2 <= rs1) +%>\ +${tests.test_opivv_opivx(template_helper, src2, src1, rs1, ref_vv, ref_vx)}
diff --git a/softrvv/tests/templates/softrvv_vmslt_test.tpl.cpp b/softrvv/tests/templates/softrvv_vmslt_test.tpl.cpp new file mode 100644 index 0000000..2b30b84 --- /dev/null +++ b/softrvv/tests/templates/softrvv_vmslt_test.tpl.cpp
@@ -0,0 +1,13 @@ +<%inherit file="base.tpl.cpp"/>\ +<%namespace name="tests" file="opivv_opivx_test.tpl.cpp"/> +<% +import numpy as np +import vec_test_helpers +N = 8 +M = 3 +template_helper = vec_test_helpers.VecTemplateHelper(op, 32) +src2, src1, rs1 = template_helper.get_test_inputs(n=N) +ref_vv = template_helper.pack_dest_mask(src2 < src1) +ref_vx = template_helper.pack_dest_mask(src2 < rs1) +%>\ +${tests.test_opivv_opivx(template_helper, src2, src1, rs1, ref_vv, ref_vx)}
diff --git a/softrvv/tests/templates/softrvv_vmsne_test.tpl.cpp b/softrvv/tests/templates/softrvv_vmsne_test.tpl.cpp new file mode 100644 index 0000000..5d560ac --- /dev/null +++ b/softrvv/tests/templates/softrvv_vmsne_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 +N = 8 +M = 3 +template_helper = vec_test_helpers.VecTemplateHelper(op, 32) +src2, src1, rs1 = template_helper.get_test_inputs(n=N) +indices = np.random.choice(src2.shape[0], M, replace=False) +src1[indices] = rs1 +src2[indices] = rs1 +ref_vv = template_helper.pack_dest_mask(src2 != src1) +ref_vx = template_helper.pack_dest_mask(src2 != rs1) +%>\ +${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_vnsra_test.tpl.cpp b/softrvv/tests/templates/softrvv_vnsra_test.tpl.cpp new file mode 100644 index 0000000..fcd6e67 --- /dev/null +++ b/softrvv/tests/templates/softrvv_vnsra_test.tpl.cpp
@@ -0,0 +1,15 @@ +<%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) +ref_vv = np.right_shift(src2, tmp_src1).astype(np.int16) +tmp_rs1 = rs1 & (src2_type(0).itemsize * 8 - 1) +ref_vx = np.right_shift(src2, tmp_rs1).astype(np.int16) +%>\ +${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..58a22df 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt
@@ -246,6 +246,114 @@ -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_generated_test( + NAME + vnsra + TEMPLATE + opivv_opivx_opivi_test.tpl.cpp + LINKOPTS + -Xlinker --defsym=__itcm_length__=192K +) + +vec_cc_generated_test( + NAME + vmseq + TEMPLATE + opivv_opivx_opivi_test.tpl.cpp + LINKOPTS + -Xlinker --defsym=__itcm_length__=192K +) + +vec_cc_generated_test( + NAME + vmsne + TEMPLATE + opivv_opivx_opivi_test.tpl.cpp + LINKOPTS + -Xlinker --defsym=__itcm_length__=192K +) + +vec_cc_generated_test( + NAME + vmsltu + TEMPLATE + opivv_opivx_test.tpl.cpp + LINKOPTS + -Xlinker --defsym=__itcm_length__=192K +) + +vec_cc_generated_test( + NAME + vmslt + TEMPLATE + opivv_opivx_test.tpl.cpp + LINKOPTS + -Xlinker --defsym=__itcm_length__=192K +) + +vec_cc_generated_test( + NAME + vmsleu + TEMPLATE + opivv_opivx_opivi_test.tpl.cpp + LINKOPTS + -Xlinker --defsym=__itcm_length__=192K +) + +vec_cc_generated_test( + NAME + vmsle + TEMPLATE + opivv_opivx_opivi_test.tpl.cpp + LINKOPTS + -Xlinker --defsym=__itcm_length__=192K +) + +vec_cc_generated_test( + NAME + vmsgtu + TEMPLATE + opivx_opivi_test.tpl.cpp + LINKOPTS + -Xlinker --defsym=__itcm_length__=192K +) + +vec_cc_generated_test( + NAME + vmsgt + TEMPLATE + opivx_opivi_test.tpl.cpp + LINKOPTS + -Xlinker --defsym=__itcm_length__=192K +) + +vec_cc_generated_test( + NAME + vmsgeu + TEMPLATE + opivx_test.tpl.cpp + LINKOPTS + -Xlinker --defsym=__itcm_length__=192K +) + +vec_cc_generated_test( + NAME + vmsge + TEMPLATE + opivx_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..c1dcc32 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::${ref_opcode}_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>
diff --git a/tests/templates/opivx_test.tpl.cpp b/tests/templates/opivx_test.tpl.cpp new file mode 100644 index 0000000..a63d525 --- /dev/null +++ b/tests/templates/opivx_test.tpl.cpp
@@ -0,0 +1,4 @@ +<%inherit file="base.tpl.cpp"/>\ +<%namespace name="tests_vx" file="base_opivx_test.tpl.cpp"/>\ +<%namespace name="tests_vi" file="base_opivi_test.tpl.cpp"/>\ +${tests_vx.test_opivx(op)}