blob: 804baffab7b4eca6674a5f1f190295979ac80fb3 [file] [log] [blame]
#include <riscv_vector.h>
#include <springbok.h>
#include <stdio.h>
#include <stdlib.h>
#include <bit>
#include <tuple>
#include "pw_unit_test/framework.h"
#include "test_v_helpers.h"
namespace vmv_test {
namespace {
const int VLEN = 512u;
const int MAXVL_BYTES = VLEN / sizeof(uint8_t);
using namespace test_v_helpers;
uint8_t test_vector_1[MAXVL_BYTES];
uint8_t test_vector_2[MAXVL_BYTES];
static void zero_vector_registers() {
// Clear all vector registers
int vlmax = get_vsetvlmax_intrinsic(VSEW::SEW_E32, VLMUL::LMUL_M8);
set_vsetvl_intrinsic(VSEW::SEW_E32, VLMUL::LMUL_M8, vlmax);
__asm__ volatile("vmv.v.i v0, 0");
__asm__ volatile("vmv.v.i v8, 0");
__asm__ volatile("vmv.v.i v16, 0");
__asm__ volatile("vmv.v.i v24, 0");
}
template <typename T>
static std::tuple<int, int> vmv_v_v_i_test_setup(VLMUL lmul, uint32_t avl) {
// Clear all vector registers
zero_vector_registers();
// Initialize test_vector1 and determine vl, vlmax
uint32_t bw = std::__bit_width(sizeof(T));
VSEW sew = static_cast<VSEW>(bw - 1);
int vlmax = get_vsetvlmax_intrinsic(sew, lmul);
if (avl > vlmax) {
avl = vlmax;
}
T *ptr_vec_1 = reinterpret_cast<T *>(test_vector_1);
memset(test_vector_1, 0, MAXVL_BYTES);
memset(test_vector_2, 0, MAXVL_BYTES);
int vl = set_vsetvl_intrinsic(sew, lmul, avl);
EXPECT_EQ(avl, vl);
for (int idx = 0; idx < vl; idx++) {
ptr_vec_1[idx] = idx;
}
return std::make_tuple(vlmax, vl);
}
template <typename T>
static void vmv_check(int avl) {
T *ptr_vec_1 = reinterpret_cast<T *>(test_vector_1);
T *ptr_vec_2 = reinterpret_cast<T *>(test_vector_2);
for (int idx = 0; idx < avl; idx++) {
ASSERT_EQ(ptr_vec_1[idx], ptr_vec_2[idx]);
}
}
TEST(VmvTest, vmv_demo) {
for (int i = 0; i < AVL_COUNT; i++) {
uint32_t avl = AVLS[i];
int vlmax;
int vl;
std::tie(vlmax, vl) = vmv_v_v_i_test_setup<uint8_t>(VLMUL::LMUL_M1, avl);
if (avl > vlmax) {
continue;
}
__asm__ volatile("vle8.v v0, (%0)" : : "r"(test_vector_1));
__asm__ volatile("vmv.v.v v1, v0");
__asm__ volatile("vse8.v v1, (%0)" : : "r"(test_vector_2));
vmv_check<uint8_t>(vlmax);
}
}
// TODO(henryherman): clang vle intrinsic uses vs1r.v (unsupported in renode)
TEST(VmvTest, DISABLED_intrinsic_vmv_demo) {
for (int i = 0; i < AVL_COUNT; i++) {
uint32_t avl = AVLS[i];
int vlmax;
int vl;
std::tie(vlmax, vl) = vmv_v_v_i_test_setup<uint8_t>(VLMUL::LMUL_M1, avl);
if (avl > vlmax) {
continue;
}
vint8m1_t vec1 = vle8_v_i8m1(test_vector_1, vl);
vint8m1_t vec2 = vmv_v_v_i8m1(vec1, vl);
uint8_t *ptr_vec_2 = reinterpret_cast<uint8_t *>(test_vector_2);
vse8_v_i8m1(ptr_vec_2, vec2, vl);
vmv_check<uint8_t>(vlmax);
}
}
#define DEFINE_TEST_VMV_V_V_I_INTRINSIC(_SEW_, _LMUL_) \
TEST(DISABLED_VmvTest, intrinsic_vmv_v_v_i##_SEW_##m##_LMUL_) { \
for (int i = 0; i < AVL_COUNT; i++) { \
uint32_t avl = AVLS[i]; \
int vlmax; \
int vl; \
std::tie(vlmax, vl) = \
vmv_v_v_i_test_setup<uint##_SEW_##_t>(VLMUL::LMUL_M##_LMUL_, avl); \
if (avl > vlmax) { \
continue; \
} \
vint##_SEW_##m##_LMUL_##_t vec1 = \
vle##_SEW_##_v_i##_SEW_##m##_LMUL_(test_vector_1, vl); \
vint##_SEW_##m##_LMUL_##_t vec2 = vmv_v_v_i##_SEW_##m##_LMUL_(vec1, vl); \
uint##_SEW_##_t *ptr_vec_2 = \
reinterpret_cast<uint##_SEW_##_t *>(test_vector_2); \
vse##_SEW_##_v_i##_SEW_##m##_LMUL_(ptr_vec_2, vec2, vl); \
vmv_check<uint##_SEW_##_t>(vlmax); \
} \
}
DEFINE_TEST_VMV_V_V_I_INTRINSIC(8, 1)
DEFINE_TEST_VMV_V_V_I_INTRINSIC(8, 2)
DEFINE_TEST_VMV_V_V_I_INTRINSIC(8, 4)
DEFINE_TEST_VMV_V_V_I_INTRINSIC(8, 8)
DEFINE_TEST_VMV_V_V_I_INTRINSIC(16, 1)
DEFINE_TEST_VMV_V_V_I_INTRINSIC(16, 2)
DEFINE_TEST_VMV_V_V_I_INTRINSIC(16, 4)
DEFINE_TEST_VMV_V_V_I_INTRINSIC(16, 8)
DEFINE_TEST_VMV_V_V_I_INTRINSIC(32, 1)
DEFINE_TEST_VMV_V_V_I_INTRINSIC(32, 2)
DEFINE_TEST_VMV_V_V_I_INTRINSIC(32, 4)
DEFINE_TEST_VMV_V_V_I_INTRINSIC(32, 8)
#define DEFINE_TEST_VMV_V_V_I(_SEW_, _LMUL_) \
TEST(VmvTest, vmv_v_v_i##_SEW_##m##_LMUL_) { \
for (int i = 0; i < AVL_COUNT; i++) { \
uint32_t avl = AVLS[i]; \
int vlmax; \
int vl; \
std::tie(vlmax, vl) = \
vmv_v_v_i_test_setup<uint##_SEW_##_t>(VLMUL::LMUL_M##_LMUL_, avl); \
if (avl > vlmax) { \
continue; \
} \
uint##_SEW_##_t *ptr_vec_1 = \
reinterpret_cast<uint##_SEW_##_t *>(test_vector_1); \
uint##_SEW_##_t *ptr_vec_2 = \
reinterpret_cast<uint##_SEW_##_t *>(test_vector_2); \
__asm__ volatile("vle" #_SEW_ ".v v0, (%0)" : : "r"(ptr_vec_1)); \
__asm__ volatile("vmv.v.v v8, v0"); \
__asm__ volatile("vse" #_SEW_ ".v v8, (%0)" : : "r"(ptr_vec_2)); \
vmv_check<uint##_SEW_##_t>(vlmax); \
} \
}
DEFINE_TEST_VMV_V_V_I(8, 1)
DEFINE_TEST_VMV_V_V_I(8, 2)
DEFINE_TEST_VMV_V_V_I(8, 4)
DEFINE_TEST_VMV_V_V_I(8, 8)
DEFINE_TEST_VMV_V_V_I(16, 1)
DEFINE_TEST_VMV_V_V_I(16, 2)
DEFINE_TEST_VMV_V_V_I(16, 4)
DEFINE_TEST_VMV_V_V_I(16, 8)
DEFINE_TEST_VMV_V_V_I(32, 1)
DEFINE_TEST_VMV_V_V_I(32, 2)
DEFINE_TEST_VMV_V_V_I(32, 4)
DEFINE_TEST_VMV_V_V_I(32, 8)
} // namespace
} // namespace vmv_test