Merge "Move generator script to top-level directory."
diff --git a/softrvv/include/softrvv.h b/softrvv/include/softrvv.h
index df7f591..0edbf3c 100644
--- a/softrvv/include/softrvv.h
+++ b/softrvv/include/softrvv.h
@@ -5,6 +5,7 @@
#include "encoding.h"
#include "softrvv_vadd.h"
+#include "softrvv_vmin.h"
#include "softrvv_vsub.h"
#include "softrvv_vwadd.h"
#include "softrvv_vwsub.h"
diff --git a/softrvv/include/softrvv_vmin.h b/softrvv/include/softrvv_vmin.h
new file mode 100644
index 0000000..d853455
--- /dev/null
+++ b/softrvv/include/softrvv_vmin.h
@@ -0,0 +1,25 @@
+#ifndef SOFTRVV_VMIN_H
+#define SOFTRVV_VMIN_H
+
+#include <stddef.h>
+#include <stdint.h>
+
+namespace softrvv {
+
+template <typename T>
+void vmin_vx(T *dest, T *src1, const T *src2, int32_t avl) {
+ for (int32_t idx = 0; idx < avl; idx++) {
+ dest[idx] = (src1[idx] < *src2) ? src1[idx] : *src2;
+ }
+}
+
+template <typename T>
+void vmin_vv(T *dest, T *src1, T *src2, int32_t avl) {
+ for (int32_t idx = 0; idx < avl; idx++) {
+ dest[idx] = (src1[idx] < src2[idx]) ? src1[idx] : src2[idx];
+ }
+}
+
+} // namespace softrvv
+
+#endif // SOFTRVV_VMIN_H
diff --git a/softrvv/tests/CMakeLists.txt b/softrvv/tests/CMakeLists.txt
index 9156040..edb6575 100644
--- a/softrvv/tests/CMakeLists.txt
+++ b/softrvv/tests/CMakeLists.txt
@@ -97,3 +97,14 @@
LINKOPTS
-Xlinker --defsym=__itcm_length__=128K
)
+
+vec_cc_test(
+ NAME
+ softrvv_vmin
+ SRCS
+ softrvv_vmin_test.cpp
+ DEPS
+ softrvv
+ LINKOPTS
+ -Xlinker --defsym=__itcm_length__=128K
+)
diff --git a/softrvv/tests/softrvv_vmin_test.cpp b/softrvv/tests/softrvv_vmin_test.cpp
new file mode 100644
index 0000000..c3852f7
--- /dev/null
+++ b/softrvv/tests/softrvv_vmin_test.cpp
@@ -0,0 +1,48 @@
+#include <riscv_vector.h>
+#include <springbok.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "pw_unit_test/framework.h"
+#include "softrvv.h"
+
+namespace softrvv_vmin_test {
+namespace {
+
+// common to all tests
+int32_t src1[] = {-1, 2, 3, 4, 5};
+
+// vector test
+int32_t src2[] = {5, 4, 3, 2, 1};
+
+// scalar register tests
+int32_t rs1[] = {1, 3, 5};
+
+}; // namespace
+const int32_t kAVL = sizeof(src1) / sizeof(src1[0]);
+int32_t dest[kAVL];
+
+int32_t ref_vv[] = {-1, 2, 3, 2, 1};
+
+int32_t ref_vx[3][kAVL] = {{-1, 1, 1, 1, 1}, {-1, 2, 3, 3, 3}, {-1, 2, 3, 4, 5}};
+
+class SoftRvvVminTest : public ::testing::Test {
+ protected:
+ void SetUp() override { memset(dest, 0, sizeof(dest)); }
+};
+
+TEST_F(SoftRvvVminTest, VV) {
+ softrvv::vmin_vv<int32_t>(dest, src1, src2, kAVL);
+ ASSERT_EQ(memcmp(dest, ref_vv, sizeof(dest)), 0);
+}
+
+TEST_F(SoftRvvVminTest, VX) {
+ const int32_t num_vx_tests = sizeof(ref_vx) / sizeof(ref_vx[0]);
+ for (int32_t i = 0; i < num_vx_tests; i++) {
+ softrvv::vmin_vx<int32_t>(dest, src1, &rs1[i], kAVL);
+ ASSERT_EQ(memcmp(dest, &ref_vx[i], sizeof(dest)), 0);
+ }
+}
+
+} // namespace softrvv_vmin_test
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index b2d178e..1ec4a36 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -44,6 +44,26 @@
vec_cc_generated_test(
NAME
+ vmin
+ OPFMT
+ OPIVV
+ OPIVX
+ LINKOPTS
+ -Xlinker --defsym=__itcm_length__=128K
+)
+
+vec_cc_generated_test(
+ NAME
+ vminu
+ OPFMT
+ OPIVV
+ OPIVX
+ LINKOPTS
+ -Xlinker --defsym=__itcm_length__=128K
+)
+
+vec_cc_generated_test(
+ NAME
vwadd
OPFMT
OPIVV
diff --git a/tests/vsetvl_test.cpp b/tests/vsetvl_test.cpp
index 6ea9b73..0aedb0a 100644
--- a/tests/vsetvl_test.cpp
+++ b/tests/vsetvl_test.cpp
@@ -90,6 +90,31 @@
test_vsetvl(VSEW::SEW_E32, VLMUL::LMUL_M8, 32, 8.0);
}
+TEST(VsetvlTest, vsetvl_e8mf2) {
+ test_vsetvl(VSEW::SEW_E8, VLMUL::LMUL_MF2, 8, 0.5);
+}
+
+TEST(VsetvlTest, vsetvl_e8mf4) {
+ test_vsetvl(VSEW::SEW_E8, VLMUL::LMUL_MF4, 8, 0.25);
+}
+
+TEST(VsetvlTest, vsetvl_e16mf2) {
+ test_vsetvl(VSEW::SEW_E16, VLMUL::LMUL_MF2, 16, 0.5);
+}
+
+// The tests pass on Renode but fail on Qemu.
+TEST(VsetvlTest, DISABLED_vsetvl_e8mf8) {
+ test_vsetvl(VSEW::SEW_E8, VLMUL::LMUL_MF8, 8, 0.125);
+}
+
+TEST(VsetvlTest, DISABLED_vsetvl_e16m4) {
+ test_vsetvl(VSEW::SEW_E16, VLMUL::LMUL_MF4, 16, 0.25);
+}
+
+TEST(VsetvlTest, DISABLED_vsetvl_e32mf2) {
+ test_vsetvl(VSEW::SEW_E32, VLMUL::LMUL_MF2, 32, 0.5);
+}
+
TEST(VsetvlTest, vsetvlmax_e8m1) {
test_vsetvlmax(VSEW::SEW_E8, VLMUL::LMUL_M1, 8, 1.0);
}
@@ -138,5 +163,30 @@
test_vsetvlmax(VSEW::SEW_E32, VLMUL::LMUL_M8, 32, 8.0);
}
+TEST(VsetvlTest, vsetvlmax_e8mf2) {
+ test_vsetvlmax(VSEW::SEW_E8, VLMUL::LMUL_MF2, 8, 0.5);
+}
+
+TEST(VsetvlTest, vsetvlmax_e8mf4) {
+ test_vsetvlmax(VSEW::SEW_E8, VLMUL::LMUL_MF4, 8, 0.25);
+}
+
+TEST(VsetvlTest, vsetvlmax_e16mf2) {
+ test_vsetvlmax(VSEW::SEW_E16, VLMUL::LMUL_MF2, 16, 0.5);
+}
+
+// The tests pass on Renode but fail on Qemu.
+TEST(VsetvlTest, DISABLED_vsetvlmax_e8mf8) {
+ test_vsetvlmax(VSEW::SEW_E8, VLMUL::LMUL_MF8, 8, 0.125);
+}
+
+TEST(VsetvlTest, DISABLED_vsetvlmax_e16m4) {
+ test_vsetvlmax(VSEW::SEW_E16, VLMUL::LMUL_MF4, 16, 0.25);
+}
+
+TEST(VsetvlTest, DISABLED_vsetvlmax_e32mf2) {
+ test_vsetvlmax(VSEW::SEW_E32, VLMUL::LMUL_MF2, 32, 0.5);
+}
+
} // namespace
} // namespace vsetvl_test