Add softrvv vmin implementation.

* Add support for vector test via generators.

Change-Id: Ibefa169fbbd67821f2df03f63f1d8f0b8ffe4325
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 e3644c5..7dac024 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -45,6 +45,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