blob: b3f6db0cfc6325b232ab98d5646b7aacf239c823 [file] [log] [blame]
/*
* Copyright 2023 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "vector_vset_tests/include/vector_vset_tests.h"
#include <springbok.h>
#include <string.h>
// TODO(b/194689843): Re-enable e64 and mf[2|4|8] tests.
uint8_t lmul_string_to_vlmul(const char *);
uint32_t construct_vtype(const char *, uint8_t, bool, bool);
void subtest_vsetvl(const char *, const char *, uint32_t, bool, bool, uint32_t,
uint32_t);
bool test_vector(void) {
uint32_t vlenb;
__asm__ volatile("csrr %0, vlenb" : "=r"(vlenb));
assert(vlenb == _TEST_VLENB);
test_vector_vsetvl();
test_vector_vsetvli();
test_vector_vsetivli();
return true;
}
uint8_t lmul_string_to_vlmul(const char *lmul) {
uint8_t vlmul = 0;
if (strequal(lmul, "1/8")) {
vlmul = 5;
} else if (strequal(lmul, "1/4")) {
vlmul = 6;
} else if (strequal(lmul, "1/2")) {
vlmul = 7;
} else if (strequal(lmul, "1")) {
vlmul = 0;
} else if (strequal(lmul, "2")) {
vlmul = 1;
} else if (strequal(lmul, "4")) {
vlmul = 2;
} else if (strequal(lmul, "8")) {
vlmul = 3;
} else {
assert(false); // unhandled lmul
}
return vlmul;
}
uint32_t construct_vtype(const char *vtypei, uint8_t vlmul, bool tail_agnostic,
bool mask_agnostic) {
uint32_t vtype = 0;
if (strequal(vtypei, "e8")) {
vtype = get_vtype_e8(vlmul, tail_agnostic, mask_agnostic);
} else if (strequal(vtypei, "e16")) {
vtype = get_vtype_e16(vlmul, tail_agnostic, mask_agnostic);
} else if (strequal(vtypei, "e32")) {
vtype = get_vtype_e32(vlmul, tail_agnostic, mask_agnostic);
} else if (strequal(vtypei, "e64")) {
vtype = get_vtype_e64(vlmul, tail_agnostic, mask_agnostic);
} else {
assert(false); // unhandled vtypei
}
return vtype;
}
void subtest_vsetvl(const char *vtypei, const char *lmul, uint32_t avl,
bool tail_agnostic, bool mask_agnostic,
uint32_t expected_vl, uint32_t line) {
uint32_t observed_vl = 0;
uint8_t vlmul = lmul_string_to_vlmul(lmul);
uint32_t vtype = construct_vtype(vtypei, vlmul, tail_agnostic, mask_agnostic);
volatile uint32_t avl_vol = avl;
// vsetvl rd, rs1, rs2 # rd = new vl, rs1 = AVL, rs2 = new vtype value
__asm__ volatile(
"vsetvl t0, %[AVL], %[VTYPE]" ::[AVL] "r"(avl_vol), [VTYPE] "r"(vtype));
COPY_SCALAR_REG(observed_vl);
if (observed_vl != expected_vl) {
LOG_INFO("observed_vl = %u, expected_vl = %u, test_line = %u ", observed_vl,
expected_vl, line);
}
assert(observed_vl == expected_vl);
}
void test_vector_vsetvl(void) {
LOG_INFO("%s", __FUNCTION__);
struct subtest_s {
const char *vtypei; // e8, e16, e32, e64
const char *lmul; // 1/8, 1/4, 1/2, 1, 2, 4, 8
uint32_t avl;
uint32_t expected_vl; // blindly copy expected_vl from qemu simulation
uint32_t line;
};
struct subtest_s subtests[] = {
{.vtypei = "e8",
.lmul = "1/4",
.avl = 0,
.expected_vl = 0,
.line = __LINE__},
{.vtypei = "e8",
.lmul = "1/4",
.avl = 1,
.expected_vl = 1,
.line = __LINE__},
{.vtypei = "e8",
.lmul = "1/4",
.avl = (_TEST_VLENB >> 2) - 1,
.expected_vl = (_TEST_VLENB >> 2) - 1,
.line = __LINE__},
{.vtypei = "e8",
.lmul = "1/4",
.avl = (_TEST_VLENB >> 2),
.expected_vl = (_TEST_VLENB >> 2),
.line = __LINE__},
{.vtypei = "e8",
.lmul = "1/4",
.avl = (_TEST_VLENB >> 2) + 1,
.expected_vl = (_TEST_VLENB >> 2),
.line = __LINE__},
{.vtypei = "e8",
.lmul = "1/2",
.avl = 0,
.expected_vl = 0,
.line = __LINE__},
{.vtypei = "e16",
.lmul = "1/2",
.avl = 0,
.expected_vl = 0,
.line = __LINE__},
{.vtypei = "e8",
.lmul = "1/2",
.avl = 1,
.expected_vl = 1,
.line = __LINE__},
{.vtypei = "e16",
.lmul = "1/2",
.avl = 1,
.expected_vl = 1,
.line = __LINE__},
{.vtypei = "e8",
.lmul = "1/2",
.avl = (_TEST_VLENB >> 1) - 1,
.expected_vl = (_TEST_VLENB >> 1) - 1,
.line = __LINE__},
{.vtypei = "e16",
.lmul = "1/2",
.avl = (_TEST_VLENB >> 2) - 1,
.expected_vl = (_TEST_VLENB >> 2) - 1,
.line = __LINE__},
{.vtypei = "e8",
.lmul = "1/2",
.avl = (_TEST_VLENB >> 1),
.expected_vl = (_TEST_VLENB >> 1),
.line = __LINE__},
{.vtypei = "e16",
.lmul = "1/2",
.avl = (_TEST_VLENB >> 2),
.expected_vl = (_TEST_VLENB >> 2),
.line = __LINE__},
{.vtypei = "e8",
.lmul = "1/2",
.avl = (_TEST_VLENB >> 1) + 1,
.expected_vl = (_TEST_VLENB >> 1),
.line = __LINE__},
{.vtypei = "e16",
.lmul = "1/2",
.avl = (_TEST_VLENB >> 2) + 1,
.expected_vl = (_TEST_VLENB >> 2),
.line = __LINE__},
{.vtypei = "e8",
.lmul = "1",
.avl = 0,
.expected_vl = 0,
.line = __LINE__},
{.vtypei = "e16",
.lmul = "1",
.avl = 0,
.expected_vl = 0,
.line = __LINE__},
{.vtypei = "e32",
.lmul = "1",
.avl = 0,
.expected_vl = 0,
.line = __LINE__},
{.vtypei = "e8",
.lmul = "1",
.avl = 1,
.expected_vl = 1,
.line = __LINE__},
{.vtypei = "e16",
.lmul = "1",
.avl = 1,
.expected_vl = 1,
.line = __LINE__},
{.vtypei = "e32",
.lmul = "1",
.avl = 1,
.expected_vl = 1,
.line = __LINE__},
{.vtypei = "e8",
.lmul = "1",
.avl = (_TEST_VLENB >> 0) - 1,
.expected_vl = (_TEST_VLENB >> 0) - 1,
.line = __LINE__},
{.vtypei = "e16",
.lmul = "1",
.avl = (_TEST_VLENB >> 1) - 1,
.expected_vl = (_TEST_VLENB >> 1) - 1,
.line = __LINE__},
{.vtypei = "e32",
.lmul = "1",
.avl = (_TEST_VLENB >> 2) - 1,
.expected_vl = (_TEST_VLENB >> 2) - 1,
.line = __LINE__},
{.vtypei = "e8",
.lmul = "1",
.avl = (_TEST_VLENB >> 0),
.expected_vl = (_TEST_VLENB >> 0),
.line = __LINE__},
{.vtypei = "e16",
.lmul = "1",
.avl = (_TEST_VLENB >> 1),
.expected_vl = (_TEST_VLENB >> 1),
.line = __LINE__},
{.vtypei = "e32",
.lmul = "1",
.avl = (_TEST_VLENB >> 2),
.expected_vl = (_TEST_VLENB >> 2),
.line = __LINE__},
{.vtypei = "e8",
.lmul = "1",
.avl = (_TEST_VLENB >> 0) + 1,
.expected_vl = (_TEST_VLENB >> 0),
.line = __LINE__},
{.vtypei = "e16",
.lmul = "1",
.avl = (_TEST_VLENB >> 1) + 1,
.expected_vl = (_TEST_VLENB >> 1),
.line = __LINE__},
{.vtypei = "e32",
.lmul = "1",
.avl = (_TEST_VLENB >> 2) + 1,
.expected_vl = (_TEST_VLENB >> 2),
.line = __LINE__},
{.vtypei = "e8",
.lmul = "2",
.avl = 0,
.expected_vl = 0,
.line = __LINE__},
{.vtypei = "e16",
.lmul = "2",
.avl = 0,
.expected_vl = 0,
.line = __LINE__},
{.vtypei = "e32",
.lmul = "2",
.avl = 0,
.expected_vl = 0,
.line = __LINE__},
{.vtypei = "e8",
.lmul = "2",
.avl = 1,
.expected_vl = 1,
.line = __LINE__},
{.vtypei = "e16",
.lmul = "2",
.avl = 1,
.expected_vl = 1,
.line = __LINE__},
{.vtypei = "e32",
.lmul = "2",
.avl = 1,
.expected_vl = 1,
.line = __LINE__},
{.vtypei = "e8",
.lmul = "2",
.avl = (_TEST_VLENB << 1) - 1,
.expected_vl = (_TEST_VLENB << 1) - 1,
.line = __LINE__},
{.vtypei = "e16",
.lmul = "2",
.avl = (_TEST_VLENB >> 0) - 1,
.expected_vl = (_TEST_VLENB >> 0) - 1,
.line = __LINE__},
{.vtypei = "e32",
.lmul = "2",
.avl = (_TEST_VLENB >> 1) - 1,
.expected_vl = (_TEST_VLENB >> 1) - 1,
.line = __LINE__},
{.vtypei = "e8",
.lmul = "2",
.avl = (_TEST_VLENB << 1),
.expected_vl = (_TEST_VLENB << 1),
.line = __LINE__},
{.vtypei = "e16",
.lmul = "2",
.avl = (_TEST_VLENB >> 0),
.expected_vl = (_TEST_VLENB >> 0),
.line = __LINE__},
{.vtypei = "e32",
.lmul = "2",
.avl = (_TEST_VLENB >> 1),
.expected_vl = (_TEST_VLENB >> 1),
.line = __LINE__},
{.vtypei = "e8",
.lmul = "2",
.avl = (_TEST_VLENB << 1) + 1,
.expected_vl = (_TEST_VLENB << 1),
.line = __LINE__},
{.vtypei = "e16",
.lmul = "2",
.avl = (_TEST_VLENB >> 0) + 1,
.expected_vl = (_TEST_VLENB >> 0),
.line = __LINE__},
{.vtypei = "e32",
.lmul = "2",
.avl = (_TEST_VLENB >> 1) + 1,
.expected_vl = (_TEST_VLENB >> 1),
.line = __LINE__},
{.vtypei = "e8",
.lmul = "4",
.avl = 0,
.expected_vl = 0,
.line = __LINE__},
{.vtypei = "e16",
.lmul = "4",
.avl = 0,
.expected_vl = 0,
.line = __LINE__},
{.vtypei = "e32",
.lmul = "4",
.avl = 0,
.expected_vl = 0,
.line = __LINE__},
{.vtypei = "e8",
.lmul = "4",
.avl = 1,
.expected_vl = 1,
.line = __LINE__},
{.vtypei = "e16",
.lmul = "4",
.avl = 1,
.expected_vl = 1,
.line = __LINE__},
{.vtypei = "e32",
.lmul = "4",
.avl = 1,
.expected_vl = 1,
.line = __LINE__},
{.vtypei = "e8",
.lmul = "4",
.avl = (_TEST_VLENB << 2) - 1,
.expected_vl = (_TEST_VLENB << 2) - 1,
.line = __LINE__},
{.vtypei = "e16",
.lmul = "4",
.avl = (_TEST_VLENB << 1) - 1,
.expected_vl = (_TEST_VLENB << 1) - 1,
.line = __LINE__},
{.vtypei = "e32",
.lmul = "4",
.avl = (_TEST_VLENB >> 0) - 1,
.expected_vl = (_TEST_VLENB >> 0) - 1,
.line = __LINE__},
{.vtypei = "e8",
.lmul = "4",
.avl = (_TEST_VLENB << 2),
.expected_vl = (_TEST_VLENB << 2),
.line = __LINE__},
{.vtypei = "e16",
.lmul = "4",
.avl = (_TEST_VLENB << 1),
.expected_vl = (_TEST_VLENB << 1),
.line = __LINE__},
{.vtypei = "e32",
.lmul = "4",
.avl = (_TEST_VLENB >> 0),
.expected_vl = (_TEST_VLENB >> 0),
.line = __LINE__},
{.vtypei = "e8",
.lmul = "4",
.avl = (_TEST_VLENB << 2) + 1,
.expected_vl = (_TEST_VLENB << 2),
.line = __LINE__},
{.vtypei = "e16",
.lmul = "4",
.avl = (_TEST_VLENB << 1) + 1,
.expected_vl = (_TEST_VLENB << 1),
.line = __LINE__},
{.vtypei = "e32",
.lmul = "4",
.avl = (_TEST_VLENB >> 0) + 1,
.expected_vl = (_TEST_VLENB >> 0),
.line = __LINE__},
{.vtypei = "e8",
.lmul = "8",
.avl = 0,
.expected_vl = 0,
.line = __LINE__},
{.vtypei = "e16",
.lmul = "8",
.avl = 0,
.expected_vl = 0,
.line = __LINE__},
{.vtypei = "e32",
.lmul = "8",
.avl = 0,
.expected_vl = 0,
.line = __LINE__},
{.vtypei = "e8",
.lmul = "8",
.avl = 1,
.expected_vl = 1,
.line = __LINE__},
{.vtypei = "e16",
.lmul = "8",
.avl = 1,
.expected_vl = 1,
.line = __LINE__},
{.vtypei = "e32",
.lmul = "8",
.avl = 1,
.expected_vl = 1,
.line = __LINE__},
{.vtypei = "e8",
.lmul = "8",
.avl = (_TEST_VLENB << 3) - 1,
.expected_vl = (_TEST_VLENB << 3) - 1,
.line = __LINE__},
{.vtypei = "e16",
.lmul = "8",
.avl = (_TEST_VLENB << 2) - 1,
.expected_vl = (_TEST_VLENB << 2) - 1,
.line = __LINE__},
{.vtypei = "e32",
.lmul = "8",
.avl = (_TEST_VLENB << 1) - 1,
.expected_vl = (_TEST_VLENB << 1) - 1,
.line = __LINE__},
{.vtypei = "e8",
.lmul = "8",
.avl = (_TEST_VLENB << 3),
.expected_vl = (_TEST_VLENB << 3),
.line = __LINE__},
{.vtypei = "e16",
.lmul = "8",
.avl = (_TEST_VLENB << 2),
.expected_vl = (_TEST_VLENB << 2),
.line = __LINE__},
{.vtypei = "e32",
.lmul = "8",
.avl = (_TEST_VLENB << 1),
.expected_vl = (_TEST_VLENB << 1),
.line = __LINE__},
{.vtypei = "e8",
.lmul = "8",
.avl = (_TEST_VLENB << 3) + 1,
.expected_vl = (_TEST_VLENB << 3),
.line = __LINE__},
{.vtypei = "e16",
.lmul = "8",
.avl = (_TEST_VLENB << 2) + 1,
.expected_vl = (_TEST_VLENB << 2),
.line = __LINE__},
{.vtypei = "e32",
.lmul = "8",
.avl = (_TEST_VLENB << 1) + 1,
.expected_vl = (_TEST_VLENB << 1),
.line = __LINE__},
};
uint32_t len = sizeof(subtests) / sizeof(struct subtest_s);
for (uint32_t i = 0; i < len; i++) {
LOG_INFO("Subtest %u", i);
struct subtest_s subtest = subtests[i];
uint8_t lmul = lmul_string_to_vlmul(subtest.lmul);
if (lmul <= 4) { // non-fractional LMUL, vtu is supported.
subtest_vsetvl(subtest.vtypei, subtest.lmul, subtest.avl, false, false,
subtest.expected_vl, subtest.line);
subtest_vsetvl(subtest.vtypei, subtest.lmul, subtest.avl, false, true,
subtest.expected_vl, subtest.line);
}
subtest_vsetvl(subtest.vtypei, subtest.lmul, subtest.avl, true, false,
subtest.expected_vl, subtest.line);
subtest_vsetvl(subtest.vtypei, subtest.lmul, subtest.avl, true, true,
subtest.expected_vl, subtest.line);
}
}
// vsetvli rd, rs1, vtypei # rd = new vl, rs1 = AVL, vtypei = new vtype
// setting
#define VSETVLI_TEST_HELPER(VTYPEI_VAR, VTYPEI_SYMBOL, AVL_VAR) \
if (strequal(VTYPEI_VAR, VTYPEI_SYMBOL)) { \
__asm__ volatile( \
"vsetvli t0, %[AVL], " VTYPEI_SYMBOL::[AVL] "r"(AVL_VAR)); \
}
void subtest_vsetvli(const char *vtypei, uint32_t avl, uint32_t expected_vl) {
uint32_t observed_vl = 0;
VSETVLI_TEST_HELPER(vtypei, "e8,m1,tu,mu", avl);
VSETVLI_TEST_HELPER(vtypei, "e8,m1,tu,ma", avl);
VSETVLI_TEST_HELPER(vtypei, "e8,m1,ta,mu", avl);
VSETVLI_TEST_HELPER(vtypei, "e8,m1,ta,ma", avl);
VSETVLI_TEST_HELPER(vtypei, "e16,m1,tu,mu", avl);
VSETVLI_TEST_HELPER(vtypei, "e16,m1,tu,ma", avl);
VSETVLI_TEST_HELPER(vtypei, "e16,m1,ta,mu", avl);
VSETVLI_TEST_HELPER(vtypei, "e16,m1,ta,ma", avl);
VSETVLI_TEST_HELPER(vtypei, "e32,m1,tu,mu", avl);
VSETVLI_TEST_HELPER(vtypei, "e32,m1,tu,ma", avl);
VSETVLI_TEST_HELPER(vtypei, "e32,m1,ta,mu", avl);
VSETVLI_TEST_HELPER(vtypei, "e32,m1,ta,ma", avl);
VSETVLI_TEST_HELPER(vtypei, "e8,mf4,ta,mu", avl);
VSETVLI_TEST_HELPER(vtypei, "e8,mf4,ta,ma", avl);
VSETVLI_TEST_HELPER(vtypei, "e8,mf2,ta,mu", avl);
VSETVLI_TEST_HELPER(vtypei, "e8,mf2,ta,ma", avl);
VSETVLI_TEST_HELPER(vtypei, "e16,mf2,ta,mu", avl);
VSETVLI_TEST_HELPER(vtypei, "e16,mf2,ta,ma", avl);
VSETVLI_TEST_HELPER(vtypei, "e8,m1,tu,mu", avl);
VSETVLI_TEST_HELPER(vtypei, "e8,m1,tu,ma", avl);
VSETVLI_TEST_HELPER(vtypei, "e8,m1,ta,mu", avl);
VSETVLI_TEST_HELPER(vtypei, "e8,m1,ta,ma", avl);
VSETVLI_TEST_HELPER(vtypei, "e16,m1,tu,mu", avl);
VSETVLI_TEST_HELPER(vtypei, "e16,m1,tu,ma", avl);
VSETVLI_TEST_HELPER(vtypei, "e16,m1,ta,mu", avl);
VSETVLI_TEST_HELPER(vtypei, "e16,m1,ta,ma", avl);
VSETVLI_TEST_HELPER(vtypei, "e32,m1,tu,mu", avl);
VSETVLI_TEST_HELPER(vtypei, "e32,m1,tu,ma", avl);
VSETVLI_TEST_HELPER(vtypei, "e32,m1,ta,mu", avl);
VSETVLI_TEST_HELPER(vtypei, "e32,m1,ta,ma", avl);
VSETVLI_TEST_HELPER(vtypei, "e8,m2,tu,mu", avl);
VSETVLI_TEST_HELPER(vtypei, "e8,m2,tu,ma", avl);
VSETVLI_TEST_HELPER(vtypei, "e8,m2,ta,mu", avl);
VSETVLI_TEST_HELPER(vtypei, "e8,m2,ta,ma", avl);
VSETVLI_TEST_HELPER(vtypei, "e16,m2,tu,mu", avl);
VSETVLI_TEST_HELPER(vtypei, "e16,m2,tu,ma", avl);
VSETVLI_TEST_HELPER(vtypei, "e16,m2,ta,mu", avl);
VSETVLI_TEST_HELPER(vtypei, "e16,m2,ta,ma", avl);
VSETVLI_TEST_HELPER(vtypei, "e32,m2,tu,mu", avl);
VSETVLI_TEST_HELPER(vtypei, "e32,m2,tu,ma", avl);
VSETVLI_TEST_HELPER(vtypei, "e32,m2,ta,mu", avl);
VSETVLI_TEST_HELPER(vtypei, "e32,m2,ta,ma", avl);
VSETVLI_TEST_HELPER(vtypei, "e8,m4,tu,mu", avl);
VSETVLI_TEST_HELPER(vtypei, "e8,m4,tu,ma", avl);
VSETVLI_TEST_HELPER(vtypei, "e8,m4,ta,mu", avl);
VSETVLI_TEST_HELPER(vtypei, "e8,m4,ta,ma", avl);
VSETVLI_TEST_HELPER(vtypei, "e16,m4,tu,mu", avl);
VSETVLI_TEST_HELPER(vtypei, "e16,m4,tu,ma", avl);
VSETVLI_TEST_HELPER(vtypei, "e16,m4,ta,mu", avl);
VSETVLI_TEST_HELPER(vtypei, "e16,m4,ta,ma", avl);
VSETVLI_TEST_HELPER(vtypei, "e32,m4,tu,mu", avl);
VSETVLI_TEST_HELPER(vtypei, "e32,m4,tu,ma", avl);
VSETVLI_TEST_HELPER(vtypei, "e32,m4,ta,mu", avl);
VSETVLI_TEST_HELPER(vtypei, "e32,m4,ta,ma", avl);
VSETVLI_TEST_HELPER(vtypei, "e8,m8,tu,mu", avl);
VSETVLI_TEST_HELPER(vtypei, "e8,m8,tu,ma", avl);
VSETVLI_TEST_HELPER(vtypei, "e8,m8,ta,mu", avl);
VSETVLI_TEST_HELPER(vtypei, "e8,m8,ta,ma", avl);
VSETVLI_TEST_HELPER(vtypei, "e16,m8,tu,mu", avl);
VSETVLI_TEST_HELPER(vtypei, "e16,m8,tu,ma", avl);
VSETVLI_TEST_HELPER(vtypei, "e16,m8,ta,mu", avl);
VSETVLI_TEST_HELPER(vtypei, "e16,m8,ta,ma", avl);
VSETVLI_TEST_HELPER(vtypei, "e32,m8,tu,mu", avl);
VSETVLI_TEST_HELPER(vtypei, "e32,m8,tu,ma", avl);
VSETVLI_TEST_HELPER(vtypei, "e32,m8,ta,mu", avl);
VSETVLI_TEST_HELPER(vtypei, "e32,m8,ta,ma", avl);
COPY_SCALAR_REG(observed_vl);
if (observed_vl != expected_vl) {
LOG_INFO("Subtest failed, observed_vl = %u, expected_vl = %u", observed_vl,
expected_vl);
}
assert(observed_vl == expected_vl);
}
void test_vector_vsetvli(void) {
LOG_INFO("%s", __FUNCTION__);
struct subtest_s {
const char *vtypei;
uint32_t avl;
uint32_t expected_vl; // blindly copy expected_vl from qemu simulation
};
struct subtest_s subtests[] = {
{.vtypei = "e8,mf4", .avl = 0, .expected_vl = 0},
{.vtypei = "e8,mf4", .avl = 1, .expected_vl = 1},
{.vtypei = "e8,mf4",
.avl = (_TEST_VLENB >> 2) - 1,
.expected_vl = (_TEST_VLENB >> 2) - 1},
{.vtypei = "e8,mf4",
.avl = (_TEST_VLENB >> 2),
.expected_vl = (_TEST_VLENB >> 2)},
{.vtypei = "e8,mf4",
.avl = (_TEST_VLENB >> 2) + 1,
.expected_vl = (_TEST_VLENB >> 2)},
{.vtypei = "e8,mf2", .avl = 0, .expected_vl = 0},
{.vtypei = "e16,mf2", .avl = 0, .expected_vl = 0},
{.vtypei = "e8,mf2", .avl = 1, .expected_vl = 1},
{.vtypei = "e16,mf2", .avl = 1, .expected_vl = 1},
{.vtypei = "e8,mf2",
.avl = (_TEST_VLENB >> 1) - 1,
.expected_vl = (_TEST_VLENB >> 1) - 1},
{.vtypei = "e16,mf2",
.avl = (_TEST_VLENB >> 2) - 1,
.expected_vl = (_TEST_VLENB >> 2) - 1},
{.vtypei = "e8,mf2",
.avl = (_TEST_VLENB >> 1),
.expected_vl = (_TEST_VLENB >> 1)},
{.vtypei = "e16,mf2",
.avl = (_TEST_VLENB >> 2),
.expected_vl = (_TEST_VLENB >> 2)},
{.vtypei = "e8,mf2",
.avl = (_TEST_VLENB >> 1) + 1,
.expected_vl = (_TEST_VLENB >> 1)},
{.vtypei = "e16,mf2",
.avl = (_TEST_VLENB >> 2) + 1,
.expected_vl = (_TEST_VLENB >> 2)},
{.vtypei = "e8,m1", .avl = 0, .expected_vl = 0},
{.vtypei = "e16,m1", .avl = 0, .expected_vl = 0},
{.vtypei = "e32,m1", .avl = 0, .expected_vl = 0},
{.vtypei = "e8,m1", .avl = 1, .expected_vl = 1},
{.vtypei = "e16,m1", .avl = 1, .expected_vl = 1},
{.vtypei = "e32,m1", .avl = 1, .expected_vl = 1},
{.vtypei = "e8,m1",
.avl = (_TEST_VLENB >> 0) - 1,
.expected_vl = (_TEST_VLENB >> 0) - 1},
{.vtypei = "e16,m1",
.avl = (_TEST_VLENB >> 1) - 1,
.expected_vl = (_TEST_VLENB >> 1) - 1},
{.vtypei = "e32,m1",
.avl = (_TEST_VLENB >> 2) - 1,
.expected_vl = (_TEST_VLENB >> 2) - 1},
{.vtypei = "e8,m1",
.avl = (_TEST_VLENB >> 0),
.expected_vl = (_TEST_VLENB >> 0)},
{.vtypei = "e16,m1",
.avl = (_TEST_VLENB >> 1),
.expected_vl = (_TEST_VLENB >> 1)},
{.vtypei = "e32,m1",
.avl = (_TEST_VLENB >> 2),
.expected_vl = (_TEST_VLENB >> 2)},
{.vtypei = "e8,m1",
.avl = (_TEST_VLENB >> 0) + 1,
.expected_vl = (_TEST_VLENB >> 0)},
{.vtypei = "e16,m1",
.avl = (_TEST_VLENB >> 1) + 1,
.expected_vl = (_TEST_VLENB >> 1)},
{.vtypei = "e32,m1",
.avl = (_TEST_VLENB >> 2) + 1,
.expected_vl = (_TEST_VLENB >> 2)},
{.vtypei = "e8,m2", .avl = 0, .expected_vl = 0},
{.vtypei = "e16,m2", .avl = 0, .expected_vl = 0},
{.vtypei = "e32,m2", .avl = 0, .expected_vl = 0},
{.vtypei = "e8,m2", .avl = 1, .expected_vl = 1},
{.vtypei = "e16,m2", .avl = 1, .expected_vl = 1},
{.vtypei = "e32,m2", .avl = 1, .expected_vl = 1},
{.vtypei = "e8,m2",
.avl = (_TEST_VLENB << 1) - 1,
.expected_vl = (_TEST_VLENB << 1) - 1},
{.vtypei = "e16,m2",
.avl = (_TEST_VLENB >> 0) - 1,
.expected_vl = (_TEST_VLENB >> 0) - 1},
{.vtypei = "e32,m2",
.avl = (_TEST_VLENB >> 1) - 1,
.expected_vl = (_TEST_VLENB >> 1) - 1},
{.vtypei = "e8,m2",
.avl = (_TEST_VLENB << 1),
.expected_vl = (_TEST_VLENB << 1)},
{.vtypei = "e16,m2",
.avl = (_TEST_VLENB >> 0),
.expected_vl = (_TEST_VLENB >> 0)},
{.vtypei = "e32,m2",
.avl = (_TEST_VLENB >> 1),
.expected_vl = (_TEST_VLENB >> 1)},
{.vtypei = "e8,m2",
.avl = (_TEST_VLENB << 1) + 1,
.expected_vl = (_TEST_VLENB << 1)},
{.vtypei = "e16,m2",
.avl = (_TEST_VLENB >> 0) + 1,
.expected_vl = (_TEST_VLENB >> 0)},
{.vtypei = "e32,m2",
.avl = (_TEST_VLENB >> 1) + 1,
.expected_vl = (_TEST_VLENB >> 1)},
{.vtypei = "e8,m4", .avl = 0, .expected_vl = 0},
{.vtypei = "e16,m4", .avl = 0, .expected_vl = 0},
{.vtypei = "e32,m4", .avl = 0, .expected_vl = 0},
{.vtypei = "e8,m4", .avl = 1, .expected_vl = 1},
{.vtypei = "e16,m4", .avl = 1, .expected_vl = 1},
{.vtypei = "e32,m4", .avl = 1, .expected_vl = 1},
{.vtypei = "e8,m4",
.avl = (_TEST_VLENB << 2) - 1,
.expected_vl = (_TEST_VLENB << 2) - 1},
{.vtypei = "e16,m4",
.avl = (_TEST_VLENB << 1) - 1,
.expected_vl = (_TEST_VLENB << 1) - 1},
{.vtypei = "e32,m4",
.avl = (_TEST_VLENB >> 0) - 1,
.expected_vl = (_TEST_VLENB >> 0) - 1},
{.vtypei = "e8,m4",
.avl = (_TEST_VLENB << 2),
.expected_vl = (_TEST_VLENB << 2)},
{.vtypei = "e16,m4",
.avl = (_TEST_VLENB << 1),
.expected_vl = (_TEST_VLENB << 1)},
{.vtypei = "e32,m4",
.avl = (_TEST_VLENB >> 0),
.expected_vl = (_TEST_VLENB >> 0)},
{.vtypei = "e8,m4",
.avl = (_TEST_VLENB << 2) + 1,
.expected_vl = (_TEST_VLENB << 2)},
{.vtypei = "e16,m4",
.avl = (_TEST_VLENB << 1) + 1,
.expected_vl = (_TEST_VLENB << 1)},
{.vtypei = "e32,m4",
.avl = (_TEST_VLENB >> 0) + 1,
.expected_vl = (_TEST_VLENB >> 0)},
{.vtypei = "e8,m8", .avl = 0, .expected_vl = 0},
{.vtypei = "e16,m8", .avl = 0, .expected_vl = 0},
{.vtypei = "e32,m8", .avl = 0, .expected_vl = 0},
{.vtypei = "e8,m8", .avl = 1, .expected_vl = 1},
{.vtypei = "e16,m8", .avl = 1, .expected_vl = 1},
{.vtypei = "e32,m8", .avl = 1, .expected_vl = 1},
{.vtypei = "e8,m8",
.avl = (_TEST_VLENB << 3) - 1,
.expected_vl = (_TEST_VLENB << 3) - 1},
{.vtypei = "e16,m8",
.avl = (_TEST_VLENB << 2) - 1,
.expected_vl = (_TEST_VLENB << 2) - 1},
{.vtypei = "e32,m8",
.avl = (_TEST_VLENB << 1) - 1,
.expected_vl = (_TEST_VLENB << 1) - 1},
{.vtypei = "e8,m8",
.avl = (_TEST_VLENB << 3),
.expected_vl = (_TEST_VLENB << 3)},
{.vtypei = "e16,m8",
.avl = (_TEST_VLENB << 2),
.expected_vl = (_TEST_VLENB << 2)},
{.vtypei = "e32,m8",
.avl = (_TEST_VLENB << 1),
.expected_vl = (_TEST_VLENB << 1)},
{.vtypei = "e8,m8",
.avl = (_TEST_VLENB << 3) + 1,
.expected_vl = (_TEST_VLENB << 3)},
{.vtypei = "e16,m8",
.avl = (_TEST_VLENB << 2) + 1,
.expected_vl = (_TEST_VLENB << 2)},
{.vtypei = "e32,m8",
.avl = (_TEST_VLENB << 1) + 1,
.expected_vl = (_TEST_VLENB << 1)},
};
uint32_t len = sizeof(subtests) / sizeof(struct subtest_s);
for (uint32_t i = 0; i < len; i++) {
LOG_INFO("Subtest %u", i);
struct subtest_s subtest = subtests[i];
char new_vtypei[32];
uint32_t vtypei_len = strlength(subtest.vtypei);
memcpy(new_vtypei, subtest.vtypei, vtypei_len);
if (strstr(subtest.vtypei, "mf") == NULL) { // non-fractional LMUL.
memcpy(new_vtypei + vtypei_len, ",tu,mu\0", (size_t)7);
subtest_vsetvli(new_vtypei, subtest.avl, subtest.expected_vl);
memcpy(new_vtypei + vtypei_len, ",tu,ma\0", (size_t)7);
subtest_vsetvli(new_vtypei, subtest.avl, subtest.expected_vl);
}
memcpy(new_vtypei + vtypei_len, ",ta,mu\0", (size_t)7);
subtest_vsetvli(new_vtypei, subtest.avl, subtest.expected_vl);
memcpy(new_vtypei + vtypei_len, ",ta,ma\0", (size_t)7);
subtest_vsetvli(new_vtypei, subtest.avl, subtest.expected_vl);
}
}
#define _STRING_LITERAL(x) #x
#define STRING_LITERAL(x) _STRING_LITERAL(x)
// vsetivli rd, uimm, vtypei # rd = new vl, uimm = AVL, vtypei = new vtype
// setting
#define VSETIVLI_SUBTEST(AVL, VTYPEI, EXPECTED_VL) \
do { \
LOG_INFO("Subtest %u", subtest_count++); \
uint32_t observed_vl = 0; \
if (strstr(VTYPEI, "mf") == NULL) { \
__asm__ volatile("vsetivli t0, " STRING_LITERAL(AVL) ", " VTYPEI \
", tu, mu"); \
COPY_SCALAR_REG(observed_vl); \
if (observed_vl != EXPECTED_VL) { \
LOG_INFO("Subtest observed_vl = %u, expected_vl = %d", observed_vl, \
EXPECTED_VL); \
} \
assert(observed_vl == EXPECTED_VL); \
__asm__ volatile("vsetivli t0, " STRING_LITERAL(AVL) ", " VTYPEI \
", tu, ma"); \
COPY_SCALAR_REG(observed_vl); \
if (observed_vl != EXPECTED_VL) { \
LOG_INFO("Subtest observed_vl = %u, expected_vl = %d", observed_vl, \
EXPECTED_VL); \
} \
assert(observed_vl == EXPECTED_VL); \
} \
__asm__ volatile("vsetivli t0, " STRING_LITERAL(AVL) ", " VTYPEI \
", ta, mu"); \
COPY_SCALAR_REG(observed_vl); \
if (observed_vl != EXPECTED_VL) { \
LOG_INFO("Subtest observed_vl = %u, expected_vl = %d", observed_vl, \
EXPECTED_VL); \
} \
assert(observed_vl == EXPECTED_VL); \
__asm__ volatile("vsetivli t0, " STRING_LITERAL(AVL) ", " VTYPEI \
", ta, ma"); \
COPY_SCALAR_REG(observed_vl); \
if (observed_vl != EXPECTED_VL) { \
LOG_INFO("Subtest observed_vl = %u, expected_vl = %d", observed_vl, \
EXPECTED_VL); \
} \
assert(observed_vl == EXPECTED_VL); \
} while (0)
#if _TEST_VLEN == 256
#define VLENB_DIV8_SUB1 3
#define VLENB_DIV8 4
#define VLENB_DIV8_ADD1 5
#define VLENB_DIV4_SUB1 7
#define VLENB_DIV4 8
#define VLENB_DIV4_ADD1 9
#define VLENB_DIV2_SUB1 15
#define VLENB_DIV2 16
#define VLENB_DIV2_ADD1 17
#define VLENB_SUB1 31
#define VLENB 32
#define VLENB_ADD1 33
#define VLENB_MUL2_SUB1 63
#define VLENB_MUL2 64
#define VLENB_MUL2_ADD1 65
#define VLENB_MUL4_SUB1 127
#define VLENB_MUL4 128
#define VLENB_MUL4_ADD1 129
#define VLENB_MUL8_SUB1 255
#define VLENB_MUL8 256
#define VLENB_MUL8_ADD1 257
#elif _TEST_VLEN == 512
#define VLENB_DIV8_SUB1 7
#define VLENB_DIV8 8
#define VLENB_DIV8_ADD1 9
#define VLENB_DIV4_SUB1 15
#define VLENB_DIV4 16
#define VLENB_DIV4_ADD1 17
#define VLENB_DIV2_SUB1 31
#define VLENB_DIV2 32
#define VLENB_DIV2_ADD1 33
#define VLENB_SUB1 63
#define VLENB 64
#define VLENB_ADD1 65
#define VLENB_MUL2_SUB1 127
#define VLENB_MUL2 128
#define VLENB_MUL2_ADD1 129
#define VLENB_MUL4_SUB1 255
#define VLENB_MUL4 256
#define VLENB_MUL4_ADD1 257
#define VLENB_MUL8_SUB1 511
#define VLENB_MUL8 512
#define VLENB_MUL8_ADD1 513
#endif
void test_vector_vsetivli(void) {
LOG_INFO("%s", __FUNCTION__);
// AVL immediate is 5 bits -> 31 is the max
uint32_t subtest_count = 0;
VSETIVLI_SUBTEST(0, "e8,mf4", 0);
VSETIVLI_SUBTEST(1, "e8,mf4", 1);
VSETIVLI_SUBTEST(0, "e8,mf2", 0);
VSETIVLI_SUBTEST(0, "e16,mf2", 0);
VSETIVLI_SUBTEST(1, "e8,mf2", 1);
VSETIVLI_SUBTEST(1, "e16,mf2", 1);
VSETIVLI_SUBTEST(0, "e8,m1", 0);
VSETIVLI_SUBTEST(0, "e16,m1", 0);
VSETIVLI_SUBTEST(0, "e32,m1", 0);
VSETIVLI_SUBTEST(1, "e8,m1", 1);
VSETIVLI_SUBTEST(1, "e16,m1", 1);
VSETIVLI_SUBTEST(1, "e32,m1", 1);
VSETIVLI_SUBTEST(0, "e8,m2", 0);
VSETIVLI_SUBTEST(0, "e16,m2", 0);
VSETIVLI_SUBTEST(0, "e32,m2", 0);
VSETIVLI_SUBTEST(1, "e8,m2", 1);
VSETIVLI_SUBTEST(1, "e16,m2", 1);
VSETIVLI_SUBTEST(1, "e32,m2", 1);
VSETIVLI_SUBTEST(0, "e8,m4", 0);
VSETIVLI_SUBTEST(0, "e16,m4", 0);
VSETIVLI_SUBTEST(0, "e32,m4", 0);
VSETIVLI_SUBTEST(1, "e8,m4", 1);
VSETIVLI_SUBTEST(1, "e16,m4", 1);
VSETIVLI_SUBTEST(1, "e32,m4", 1);
VSETIVLI_SUBTEST(0, "e8,m8", 0);
VSETIVLI_SUBTEST(0, "e16,m8", 0);
VSETIVLI_SUBTEST(0, "e32,m8", 0);
VSETIVLI_SUBTEST(1, "e8,m8", 1);
VSETIVLI_SUBTEST(1, "e16,m8", 1);
VSETIVLI_SUBTEST(1, "e32,m8", 1);
#if VLENB_DIV4_SUB1 < 32
VSETIVLI_SUBTEST(VLENB_DIV4_SUB1, "e8,mf4", VLENB_DIV4_SUB1);
VSETIVLI_SUBTEST(VLENB_DIV4_SUB1, "e16,mf2", VLENB_DIV4_SUB1);
VSETIVLI_SUBTEST(VLENB_DIV4_SUB1, "e32,m1", VLENB_DIV4_SUB1);
#endif
#if VLENB_DIV4 < 32
VSETIVLI_SUBTEST(VLENB_DIV4, "e8,mf4", VLENB_DIV4);
VSETIVLI_SUBTEST(VLENB_DIV4, "e16,mf2", VLENB_DIV4);
VSETIVLI_SUBTEST(VLENB_DIV4, "e32,m1", VLENB_DIV4);
#endif
#if VLENB_DIV4_ADD1 < 32
VSETIVLI_SUBTEST(VLENB_DIV4_ADD1, "e8,mf4", VLENB_DIV4);
VSETIVLI_SUBTEST(VLENB_DIV4_ADD1, "e16,mf2", VLENB_DIV4);
VSETIVLI_SUBTEST(VLENB_DIV4_ADD1, "e32,m1", VLENB_DIV4);
#endif
#if VLENB_DIV2_SUB1 < 32
VSETIVLI_SUBTEST(VLENB_DIV2_SUB1, "e8,mf2", VLENB_DIV2_SUB1);
VSETIVLI_SUBTEST(VLENB_DIV2_SUB1, "e16,m1", VLENB_DIV2_SUB1);
VSETIVLI_SUBTEST(VLENB_DIV2_SUB1, "e32,m2", VLENB_DIV2_SUB1);
#endif
#if VLENB_DIV2 < 32
VSETIVLI_SUBTEST(VLENB_DIV2, "e8,mf2", VLENB_DIV2);
VSETIVLI_SUBTEST(VLENB_DIV2, "e16,m1", VLENB_DIV2);
VSETIVLI_SUBTEST(VLENB_DIV2, "e32,m2", VLENB_DIV2);
#endif
#if VLENB_DIV2_ADD1 < 32
VSETIVLI_SUBTEST(VLENB_DIV2_ADD1, "e8,mf2", VLENB_DIV2);
VSETIVLI_SUBTEST(VLENB_DIV2_ADD1, "e16,m1", VLENB_DIV2);
VSETIVLI_SUBTEST(VLENB_DIV2_ADD1, "e32,m2", VLENB_DIV2);
#endif
#if VLENB_SUB1 < 32
VSETIVLI_SUBTEST(VLENB_SUB1, "e8,m1", VLENB_SUB1);
VSETIVLI_SUBTEST(VLENB_SUB1, "e16,m2", VLENB_SUB1);
VSETIVLI_SUBTEST(VLENB_SUB1, "e32,m4", VLENB_SUB1);
#endif
#if VLENB < 32
VSETIVLI_SUBTEST(VLENB, "e8,m1", VLENB);
VSETIVLI_SUBTEST(VLENB, "e16,m2", VLENB);
VSETIVLI_SUBTEST(VLENB, "e32,m4", VLENB);
#endif
#if VLENB_ADD1 < 32
VSETIVLI_SUBTEST(VLENB_ADD1, "e8,m1", VLENB);
VSETIVLI_SUBTEST(VLENB_ADD1, "e16,m2", VLENB);
VSETIVLI_SUBTEST(VLENB_ADD1, "e32,m4", VLENB);
#endif
#if VLENB_MUL2_SUB1 < 32
VSETIVLI_SUBTEST(VLENB_MUL2_SUB1, "e8,m2", VLENB_MUL2_SUB1);
VSETIVLI_SUBTEST(VLENB_MUL2_SUB1, "e16,m4", VLENB_MUL2_SUB1);
VSETIVLI_SUBTEST(VLENB_MUL2_SUB1, "e32,m8", VLENB_MUL2_SUB1);
#endif
#if VLENB_MUL2 < 32
VSETIVLI_SUBTEST(VLENB_MUL2, "e8,m2", VLENB_MUL2);
VSETIVLI_SUBTEST(VLENB_MUL2, "e16,m4", VLENB_MUL2);
VSETIVLI_SUBTEST(VLENB_MUL2, "e32,m8", VLENB_MUL2);
#endif
#if VLENB_MUL2_ADD1 < 32
VSETIVLI_SUBTEST(VLENB_MUL2_ADD1, "e8,m2", VLENB_MUL2);
VSETIVLI_SUBTEST(VLENB_MUL2_ADD1, "e16,m4", VLENB_MUL2);
VSETIVLI_SUBTEST(VLENB_MUL2_ADD1, "e32,m8", VLENB_MUL2);
#endif
#if VLENB_MUL4_SUB1 < 32
VSETIVLI_SUBTEST(VLENB_MUL4_SUB1, "e8,m4", VLENB_MUL4_SUB1);
VSETIVLI_SUBTEST(VLENB_MUL4_SUB1, "e16,m8", VLENB_MUL4_SUB1);
#endif
#if VLENB_MUL4 < 32
VSETIVLI_SUBTEST(VLENB_MUL4, "e8,m4", VLENB_MUL4);
VSETIVLI_SUBTEST(VLENB_MUL4, "e16,m8", VLENB_MUL4);
#endif
#if VLENB_MUL4_ADD1 < 32
VSETIVLI_SUBTEST(VLENB_MUL4_ADD1, "e8,m4", VLENB_MUL4);
VSETIVLI_SUBTEST(VLENB_MUL4_ADD1, "e16,m8", VLENB_MUL4);
#endif
#if VLENB_MUL8_SUB1 < 32
VSETIVLI_SUBTEST(VLENB_MUL8_SUB1, "e8,m8", VLENB_MUL8_SUB1);
#endif
#if VLENB_MUL8 < 32
VSETIVLI_SUBTEST(VLENB_MUL8, "e8,m8", VLENB_MUL8);
#endif
#if VLENB_MUL8_ADD1 < 32
VSETIVLI_SUBTEST(VLENB_MUL8_ADD1, "e8,m8", VLENB_MUL8);
#endif
}