| // 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 <riscv_vector.h> |
| #include <springbok.h> |
| #include <stdio.h> |
| #include <stdlib.h> |
| |
| #include "pw_unit_test/framework.h" |
| #include "test_v_helpers/include/test_v_helpers.h" |
| |
| namespace vsetvl_test { |
| namespace { |
| |
| using namespace test_v_helpers; |
| |
| const uint64_t VLEN = 512u; |
| const uint32_t VILL = 0x80000000; |
| |
| #define MIN(X, Y) ((X) < (Y) ? (X) : (Y)) |
| |
| static inline uint32_t read_vtype() { |
| uint32_t vtype; |
| __asm__ volatile("csrr %[VTYPE], vtype" : [VTYPE] "=r"(vtype) :); |
| return vtype; |
| } |
| |
| static inline bool is_illegal_vtype() { |
| uint32_t vtype = read_vtype(); |
| if (vtype & VILL) { |
| return true; |
| } |
| return false; |
| } |
| |
| static uint32_t calculate_vl(uint32_t sew, uint32_t avl, float lmul) { |
| uint32_t vlmax = (uint32_t)(VLEN * lmul / sew); |
| return MIN(avl, vlmax); |
| } |
| |
| static void test_vsetvl(VSEW sew, VLMUL vlmul, uint32_t width, float lmul, |
| bool expect_illegal = false) { |
| size_t vl = 0; |
| for (int i = 0; i < AVL_COUNT; i++) { |
| vl = set_vsetvl_intrinsic(sew, vlmul, AVLS[i]); |
| if (!expect_illegal) { |
| EXPECT_EQ(vl, calculate_vl(width, AVLS[i], lmul)); |
| } else { |
| EXPECT_TRUE(is_illegal_vtype()); |
| } |
| } |
| for (int i = 0; i < AVL_COUNT; i++) { |
| vl = set_vsetvl(sew, vlmul, AVLS[i], false, false); |
| if (!expect_illegal) { |
| EXPECT_EQ(vl, calculate_vl(width, AVLS[i], lmul)); |
| } else { |
| EXPECT_TRUE(is_illegal_vtype()); |
| } |
| } |
| for (int i = 0; i < AVL_COUNT; i++) { |
| vl = set_vsetvli(sew, vlmul, AVLS[i]); |
| if (!expect_illegal) { |
| EXPECT_EQ(vl, calculate_vl(width, AVLS[i], lmul)); |
| } else { |
| EXPECT_TRUE(is_illegal_vtype()); |
| } |
| } |
| vl = set_vsetivli(sew, vlmul); |
| if (!expect_illegal) { |
| EXPECT_EQ(vl, calculate_vl(width, AVL_CONST, lmul)); |
| } else { |
| EXPECT_TRUE(is_illegal_vtype()); |
| } |
| } |
| |
| static void test_vsetvlmax(VSEW sew, VLMUL vlmul, uint32_t width, float lmul, |
| bool expect_illegal = false) { |
| if (!expect_illegal) { |
| EXPECT_EQ(get_vsetvlmax_intrinsic(sew, vlmul), (int)VLEN / width * lmul); |
| } else { |
| EXPECT_EQ(get_vsetvlmax_intrinsic(sew, vlmul), 0); |
| } |
| } |
| |
| TEST(VsetvlTest, vsetvl_e8m1) { |
| test_vsetvl(VSEW::SEW_E8, VLMUL::LMUL_M1, 8, 1.0); |
| } |
| |
| TEST(VsetvlTest, vsetvl_e16m1) { |
| test_vsetvl(VSEW::SEW_E16, VLMUL::LMUL_M1, 16, 1.0); |
| } |
| |
| TEST(VsetvlTest, vsetvl_e32m1) { |
| test_vsetvl(VSEW::SEW_E32, VLMUL::LMUL_M1, 32, 1.0); |
| } |
| |
| TEST(VsetvlTest, vsetvl_e8m2) { |
| test_vsetvl(VSEW::SEW_E8, VLMUL::LMUL_M2, 8, 2.0); |
| } |
| |
| TEST(VsetvlTest, vsetvl_e16m2) { |
| test_vsetvl(VSEW::SEW_E16, VLMUL::LMUL_M2, 16, 2.0); |
| } |
| |
| TEST(VsetvlTest, vsetvl_e32m2) { |
| test_vsetvl(VSEW::SEW_E32, VLMUL::LMUL_M2, 32, 2.0); |
| } |
| |
| TEST(VsetvlTest, vsetvl_e8m4) { |
| test_vsetvl(VSEW::SEW_E8, VLMUL::LMUL_M4, 8, 4.0); |
| } |
| |
| TEST(VsetvlTest, vsetvl_e16m4) { |
| test_vsetvl(VSEW::SEW_E16, VLMUL::LMUL_M4, 16, 4.0); |
| } |
| |
| TEST(VsetvlTest, vsetvl_e32m4) { |
| test_vsetvl(VSEW::SEW_E32, VLMUL::LMUL_M4, 32, 4.0); |
| } |
| |
| TEST(VsetvlTest, vsetvl_e8m8) { |
| test_vsetvl(VSEW::SEW_E8, VLMUL::LMUL_M8, 8, 8.0); |
| } |
| |
| TEST(VsetvlTest, vsetvl_e16m8) { |
| test_vsetvl(VSEW::SEW_E16, VLMUL::LMUL_M8, 16, 8); |
| } |
| |
| TEST(VsetvlTest, vsetvl_e32m8) { |
| test_vsetvl(VSEW::SEW_E32, VLMUL::LMUL_M8, 32, 8.0); |
| } |
| |
| TEST(VsetvlTest, vsetvl_e8mf2) { |
| test_vsetvl(VSEW::SEW_E8, VLMUL::LMUL_MF2, 8, 0.5); |
| } |
| |
| TEST(VsetvlTest, vsetvl_e8mf4) { |
| test_vsetvl(VSEW::SEW_E8, VLMUL::LMUL_MF4, 8, 0.25); |
| } |
| |
| TEST(VsetvlTest, vsetvl_e16mf2) { |
| test_vsetvl(VSEW::SEW_E16, VLMUL::LMUL_MF2, 16, 0.5); |
| } |
| |
| TEST(VsetvlTest, vsetvl_e8mf8_vill) { |
| test_vsetvl(VSEW::SEW_E8, VLMUL::LMUL_MF8, 8, 0.125, true); |
| } |
| |
| TEST(VsetvlTest, vsetvl_e16mf4_vill) { |
| test_vsetvl(VSEW::SEW_E16, VLMUL::LMUL_MF4, 16, 0.25, true); |
| } |
| |
| TEST(VsetvlTest, vsetvl_e32mf2_vill) { |
| test_vsetvl(VSEW::SEW_E32, VLMUL::LMUL_MF2, 32, 0.5, true); |
| } |
| |
| TEST(VsetvlTest, vsetvlmax_e8m1) { |
| test_vsetvlmax(VSEW::SEW_E8, VLMUL::LMUL_M1, 8, 1.0); |
| } |
| |
| TEST(VsetvlTest, vsetvlmax_e8m2) { |
| test_vsetvlmax(VSEW::SEW_E8, VLMUL::LMUL_M2, 8, 2.0); |
| } |
| |
| TEST(VsetvlTest, vsetvlmax_e8m4) { |
| test_vsetvlmax(VSEW::SEW_E8, VLMUL::LMUL_M4, 8, 4.0); |
| } |
| |
| TEST(VsetvlTest, vsetvlmax_e8m8) { |
| test_vsetvlmax(VSEW::SEW_E8, VLMUL::LMUL_M8, 8, 8.0); |
| } |
| |
| TEST(VsetvlTest, vsetvlmax_e16m1) { |
| test_vsetvlmax(VSEW::SEW_E16, VLMUL::LMUL_M1, 16, 1.0); |
| } |
| |
| TEST(VsetvlTest, vsetvlmax_e16m2) { |
| test_vsetvlmax(VSEW::SEW_E16, VLMUL::LMUL_M2, 16, 2.0); |
| } |
| |
| TEST(VsetvlTest, vsetvlmax_e16m4) { |
| test_vsetvlmax(VSEW::SEW_E16, VLMUL::LMUL_M4, 16, 4.0); |
| } |
| |
| TEST(VsetvlTest, vsetvlmax_e16m8) { |
| test_vsetvlmax(VSEW::SEW_E16, VLMUL::LMUL_M8, 16, 8.0); |
| } |
| |
| TEST(VsetvlTest, vsetvlmax_e32m1) { |
| test_vsetvlmax(VSEW::SEW_E32, VLMUL::LMUL_M1, 32, 1.0); |
| } |
| |
| TEST(VsetvlTest, vsetvlmax_e32m2) { |
| test_vsetvlmax(VSEW::SEW_E32, VLMUL::LMUL_M2, 32, 2.0); |
| } |
| |
| TEST(VsetvlTest, vsetvlmax_e32m4) { |
| test_vsetvlmax(VSEW::SEW_E32, VLMUL::LMUL_M4, 32, 4.0); |
| } |
| |
| TEST(VsetvlTest, vsetvlmax_e32m8) { |
| test_vsetvlmax(VSEW::SEW_E32, VLMUL::LMUL_M8, 32, 8.0); |
| } |
| |
| TEST(VsetvlTest, vsetvlmax_e8mf2) { |
| test_vsetvlmax(VSEW::SEW_E8, VLMUL::LMUL_MF2, 8, 0.5); |
| } |
| |
| TEST(VsetvlTest, vsetvlmax_e8mf4) { |
| test_vsetvlmax(VSEW::SEW_E8, VLMUL::LMUL_MF4, 8, 0.25); |
| } |
| |
| TEST(VsetvlTest, vsetvlmax_e16mf2) { |
| test_vsetvlmax(VSEW::SEW_E16, VLMUL::LMUL_MF2, 16, 0.5); |
| } |
| |
| TEST(VsetvlTest, vsetvlmax_e8mf8_vill) { |
| test_vsetvlmax(VSEW::SEW_E8, VLMUL::LMUL_MF8, 8, 0.125, true); |
| } |
| |
| TEST(VsetvlTest, vsetvlmax_e16mf4_vill) { |
| test_vsetvlmax(VSEW::SEW_E16, VLMUL::LMUL_MF4, 16, 0.25, true); |
| } |
| |
| TEST(VsetvlTest, vsetvlmax_e32mf2_vill) { |
| test_vsetvlmax(VSEW::SEW_E32, VLMUL::LMUL_MF2, 32, 0.5, true); |
| } |
| |
| } // namespace |
| } // namespace vsetvl_test |