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>