Add vsll instruction and test.

* Add softrvv implementation.
* Add sorfrvv test.
* Add v-ext test.

Change-Id: I14e6522c6fc65367d824a2be6bd49aa69df46f35
diff --git a/scripts/vec_test_helpers/__init__.py b/scripts/vec_test_helpers/__init__.py
index 77cb7ff..58bf125 100644
--- a/scripts/vec_test_helpers/__init__.py
+++ b/scripts/vec_test_helpers/__init__.py
@@ -2,6 +2,7 @@
 
 This module is for reusable helper functions used by the templates.
 """
+import numpy as np
 
 def is_widening(op_code):
     """Check if a particular op_code is a widening type."""
@@ -35,3 +36,13 @@
 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
+
+def get_imms(op_code):
+    """Return a list of valid immediate values for a op code."""
+    if op_code in ['vsll', 'vsrl']:
+        # Left and right shift immediates must be [0,31]
+        return np.linspace(0, 31, 8, dtype=np.int32)
+    else:
+        # Immediate values must be [-16, 15]
+        return np.linspace(-16, 15, 7, dtype=np.int32)
+
diff --git a/softrvv/include/softrvv.h b/softrvv/include/softrvv.h
index e532f94..7d952bc 100644
--- a/softrvv/include/softrvv.h
+++ b/softrvv/include/softrvv.h
@@ -13,6 +13,7 @@
 #include "softrvv_vor.h"
 #include "softrvv_vrem.h"
 #include "softrvv_vsext_vzext.h"
+#include "softrvv_vsll.h"
 #include "softrvv_vsub.h"
 #include "softrvv_vwadd.h"
 #include "softrvv_vwsub.h"
diff --git a/softrvv/include/softrvv_vsll.h b/softrvv/include/softrvv_vsll.h
new file mode 100644
index 0000000..a4809a9
--- /dev/null
+++ b/softrvv/include/softrvv_vsll.h
@@ -0,0 +1,34 @@
+#ifndef SOFTRVV_VSLL_H
+#define SOFTRVV_VSLL_H
+
+#include <stddef.h>
+
+#include <type_traits>
+
+namespace softrvv {
+
+template <typename T>
+void vsll_vx(T *dest, T *src1, const T *src2, int32_t avl) {
+  // Only low lg2(SEW) bits are used for shift
+  const T low_bits_mask = sizeof(T) * 8 - 1;
+  const T shift = *src2 & low_bits_mask;
+  for (int32_t idx = 0; idx < avl; idx++) {
+    dest[idx] = static_cast<T>(
+        static_cast<typename std::make_unsigned<T>::type>(src1[idx]) << shift);
+  }
+}
+
+template <typename T>
+void vsll_vv(T *dest, T *src1, T *src2, int32_t avl) {
+  // Only low lg2(SEW) bits are used for shift
+  const T low_bits_mask = sizeof(T) * 8 - 1;
+  for (int32_t idx = 0; idx < avl; idx++) {
+    dest[idx] = static_cast<T>(
+        static_cast<typename std::make_unsigned<T>::type>(src1[idx])
+        << (src2[idx] & low_bits_mask));
+  }
+}
+
+}  // namespace softrvv
+
+#endif  // SOFTRVV_VSLL_H
diff --git a/softrvv/tests/CMakeLists.txt b/softrvv/tests/CMakeLists.txt
index 3807827..b893673 100644
--- a/softrvv/tests/CMakeLists.txt
+++ b/softrvv/tests/CMakeLists.txt
@@ -161,6 +161,15 @@
    -Xlinker --defsym=__itcm_length__=128K
 )
 
+softrvv_vec_cc_generated_test(
+  NAME
+    vsll
+  TEMPLATE
+    softrvv_vsll_test.tpl.cpp
+  LINKOPTS
+   -Xlinker --defsym=__itcm_length__=128K
+)
+
 vec_cc_test(
   NAME
     softrvv_vmax
diff --git a/softrvv/tests/templates/softrvv_vsll_test.tpl.cpp b/softrvv/tests/templates/softrvv_vsll_test.tpl.cpp
new file mode 100644
index 0000000..5c6b102
--- /dev/null
+++ b/softrvv/tests/templates/softrvv_vsll_test.tpl.cpp
@@ -0,0 +1,11 @@
+<%inherit file="base.tpl.cpp"/>\
+<%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)
+tmp_rs1 = rs1 & (np.int32(0).itemsize * 8 - 1)
+ref_vx = np.left_shift(src1, tmp_rs1)
+%>\
+${tests.test_opivv_opivx("int32_t", op, src1, src2, rs1, ref_vv, ref_vx)}
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index 02a410c..b2d3d40 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -219,6 +219,15 @@
    -Xlinker --defsym=__itcm_length__=128K
 )
 
+vec_cc_generated_test(
+  NAME
+    vsll
+  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 39343cb..a3df734 100644
--- a/tests/templates/base_opivi_test.tpl.cpp
+++ b/tests/templates/base_opivi_test.tpl.cpp
@@ -13,9 +13,15 @@
   void SetUp() override { zero_vector_registers(); }
   void TearDown() override { zero_vector_registers(); }
 };
-% for test_val in [-16, -15, -4, 1, 5, 12, 15]:
-% for sew in [8, 16, 32]:
-% for lmul in [1, 2, 4, 8]:
+<%
+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)
+%>\
+% for test_val in imms:
+% for sew in sews:
+% for lmul in lmuls:
 <%
 var_type = "int%d_t" % sew
 %>\