Add vzext and vsext to softrvv.

Change-Id: If0246bc187fae25615f7c05f6809f09bbe56962f
diff --git a/softrvv/include/softrvv.h b/softrvv/include/softrvv.h
index 299fbb0..df7f591 100644
--- a/softrvv/include/softrvv.h
+++ b/softrvv/include/softrvv.h
@@ -8,6 +8,7 @@
 #include "softrvv_vsub.h"
 #include "softrvv_vwadd.h"
 #include "softrvv_vwsub.h"
+#include "softrvv_vsext_vzext.h"
 
 
 namespace softrvv {
@@ -29,4 +30,4 @@
 
 }  // namespace softrvv
 
-#endif  // SOFTRVV_H
\ No newline at end of file
+#endif  // SOFTRVV_H
diff --git a/softrvv/include/softrvv_vsext_vzext.h b/softrvv/include/softrvv_vsext_vzext.h
new file mode 100644
index 0000000..c58e91c
--- /dev/null
+++ b/softrvv/include/softrvv_vsext_vzext.h
@@ -0,0 +1,28 @@
+#ifndef SOFTRVV_VSEXT_VZEXT_H
+#define SOFTRVV_VSEXT_VZEXT_H
+
+#include <stddef.h>
+
+namespace softrvv {
+
+// Cast a vector from T2 to T1
+// vsext is the vector signed extention instruction
+template <typename T1, typename T2>
+void vsext_v(T1 *dest, const T2 *src1, int32_t avl) {
+  for (int32_t idx = 0; idx < avl; idx++) {
+    dest[idx] = static_cast<T1>(src1[idx]);
+  }
+}
+
+// Cast a vector from T2 to T1
+// vzext is the vector zero extention instruction
+// Function is identical to vsext as compiler
+// does the right thing when T1,T2 are unsigned
+template <typename T1, typename T2>
+void vzext_v(T1 *dest, const T2 *src1, int32_t avl) {
+  vsext_v<T1, T2>(dest, src1, avl);
+}
+
+}  // namespace softrvv
+
+#endif  // SOFTRVV_VSEXT_VZEXT_H
diff --git a/softrvv/tests/CMakeLists.txt b/softrvv/tests/CMakeLists.txt
index 68c5364..9156040 100644
--- a/softrvv/tests/CMakeLists.txt
+++ b/softrvv/tests/CMakeLists.txt
@@ -75,3 +75,25 @@
   LINKOPTS
    -Xlinker --defsym=__itcm_length__=128K
 )
+
+vec_cc_test(
+  NAME
+    softrvv_vsext
+  SRCS
+    softrvv_vsext_test.cpp
+  DEPS
+    softrvv
+  LINKOPTS
+   -Xlinker --defsym=__itcm_length__=128K
+)
+
+vec_cc_test(
+  NAME
+    softrvv_vzext
+  SRCS
+    softrvv_vzext_test.cpp
+  DEPS
+    softrvv
+  LINKOPTS
+   -Xlinker --defsym=__itcm_length__=128K
+)
diff --git a/softrvv/tests/softrvv_vsext_test.cpp b/softrvv/tests/softrvv_vsext_test.cpp
new file mode 100644
index 0000000..27e3c81
--- /dev/null
+++ b/softrvv/tests/softrvv_vsext_test.cpp
@@ -0,0 +1,28 @@
+#include <riscv_vector.h>
+#include <springbok.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "pw_unit_test/framework.h"
+#include "softrvv.h"
+
+namespace softrvv_vsext_test {
+namespace {
+
+int16_t src1[] = {-1, -2, 3, -4, 5};
+const uint32_t AVL_CONST = sizeof(src1)/sizeof(src1[0]);
+int32_t dest[AVL_CONST];
+int32_t ref_dest[] = {-1, -2, 3, -4, 5};
+
+class SoftRvvVsextTest : public ::testing::Test {
+ protected:
+  void SetUp() override { memset(dest, 0, sizeof(dest)); }
+};
+
+TEST_F(SoftRvvVsextTest, VF2) {
+  softrvv::vsext_v<int32_t, int16_t>(dest, src1, AVL_CONST);
+  ASSERT_EQ(memcmp(dest, ref_dest, sizeof(dest)), 0);
+}
+
+}  // namespace
+}  // namespace softrvv_vsext_test
diff --git a/softrvv/tests/softrvv_vzext_test.cpp b/softrvv/tests/softrvv_vzext_test.cpp
new file mode 100644
index 0000000..896a764
--- /dev/null
+++ b/softrvv/tests/softrvv_vzext_test.cpp
@@ -0,0 +1,28 @@
+#include <riscv_vector.h>
+#include <springbok.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "pw_unit_test/framework.h"
+#include "softrvv.h"
+
+namespace softrvv_vzext_test {
+namespace {
+
+uint16_t src1[] = {1, 2, 3, 4, 5};
+const uint32_t AVL_CONST = sizeof(src1)/sizeof(src1[0]);
+uint32_t dest[AVL_CONST];
+uint32_t ref_dest[] = {1, 2, 3, 4, 5};
+
+class SoftRvvVzextTest : public ::testing::Test {
+ protected:
+  void SetUp() override { memset(dest, 0, sizeof(dest)); }
+};
+
+TEST_F(SoftRvvVzextTest, VF2) {
+  softrvv::vzext_v<uint32_t, uint16_t>(dest, src1, AVL_CONST);
+  ASSERT_EQ(memcmp(dest, ref_dest, sizeof(dest)), 0);
+}
+
+}  // namespace
+}  // namespace softrvv_vzext_test