| /* |
| * 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. |
| */ |
| |
| #ifndef TEST_V_HELPERS_H |
| #define TEST_V_HELPERS_H |
| |
| #include <stdint.h> |
| |
| #include <bit> |
| #include <tuple> |
| |
| #include "pw_unit_test/framework.h" |
| |
| namespace test_v_helpers { |
| |
| const int LMUL_MAX = 8; |
| const int VLEN = 512; |
| const int MAXVL_BYTES = VLEN * LMUL_MAX; |
| |
| #ifdef FOR_TBM |
| const int32_t AVLS[] = {17}; |
| #else |
| const int32_t AVLS[] = {1, 4, 3, 2, 16, 8, 5, 17, |
| 32, 36, 64, 55, 100, 321, 256, 128, |
| 512, 623, 1024, 1100, 1543, 2048, 3052, 4096, |
| 5555, 8192, 10241, 16384, 24325, 32768}; |
| #endif |
| |
| const int32_t AVL_COUNT = sizeof(AVLS) / sizeof(AVLS[0]); |
| |
| enum VSEW { |
| SEW_E8 = 0, |
| SEW_E16 = 1, |
| SEW_E32 = 2, |
| /* // SEW limited to E32 |
| SEW_E64 = 3, |
| SEW_E128 = 4, |
| SEW_E256 = 5, |
| SEW_E512 = 6, |
| SEW_E1024 = 7, |
| */ |
| }; |
| |
| enum VLMUL { |
| LMUL_MF8 = 5, |
| LMUL_MF4 = 6, |
| LMUL_MF2 = 7, |
| |
| LMUL_M1 = 0, |
| LMUL_M2 = 1, |
| LMUL_M4 = 2, |
| LMUL_M8 = 3, |
| }; |
| |
| uint32_t get_vtype(VSEW sew, VLMUL lmul, bool tail_agnostic, |
| bool mask_agnostic); |
| |
| // vsetvl rd, rs1, rs2 # rd = new vl, rs1 = AVL, rs2 = new vtype value |
| uint32_t set_vsetvl(VSEW sew, VLMUL lmul, uint32_t avl, bool tail_agnostic, |
| bool mask_agnostic); |
| |
| int set_vsetvl_intrinsic(VSEW sew, VLMUL lmul, uint32_t avl); |
| |
| int get_vsetvlmax_intrinsic(VSEW sew, VLMUL lmul); |
| |
| int set_vsetvli(VSEW sew, VLMUL lmul, uint32_t avl); |
| |
| void zero_vector_registers(); |
| // Set AVL = constant 17 for now. |
| const uint32_t AVL_CONST = 17; |
| uint32_t set_vsetivli(VSEW sew, VLMUL lmul); |
| |
| template <typename T> |
| void assert_vec_elem_eq(int avl, void *test_vector_1, void *test_vector_2) { |
| 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]); |
| } |
| } |
| |
| template <typename T> |
| void assert_vec_mask_eq(int avl, void *test_vector_1, void *test_vector_2) { |
| const unsigned int bw_required = std::__bit_width(sizeof(T)* 8); |
| const unsigned int shift = bw_required - 1; |
| 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++) { |
| unsigned int element_idx = idx >> shift; // Eqivalent to idx / (sizeof(T) * 8) |
| unsigned int element_pos = idx & ~(element_idx << shift); // Equivalent to idx % (sizeof(T) * 8) |
| T *e1 = ptr_vec_1 + element_idx; |
| T *e2 = ptr_vec_2 + element_idx; |
| ASSERT_EQ(*e1 & (1 << element_pos), *e2 & (1 << element_pos)); |
| } |
| } |
| |
| template <typename T> |
| static std::tuple<int, int> vector_test_setup( |
| VLMUL lmul, int32_t avl, const std::initializer_list<void *> &vec_list) { |
| // Clear all vector registers |
| zero_vector_registers(); |
| // Initialize test_vector_1 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; |
| } |
| for (auto vec : vec_list) { |
| memset(vec, 0, MAXVL_BYTES); |
| } |
| int vl = set_vsetvl_intrinsic(sew, lmul, avl); |
| |
| EXPECT_EQ(avl, vl); |
| |
| return std::make_tuple(vlmax, vl); |
| } |
| |
| template <typename T> |
| void fill_random_vector(T *vec, int32_t avl) { |
| for (int32_t i = 0; i < avl; i++) { |
| vec[i] = static_cast<T>(rand()); |
| } |
| } |
| |
| template <typename T> |
| void fill_vector_with_index(T *vec, int32_t avl) { |
| for (int32_t i = 0; i < avl; i++) { |
| vec[i] = static_cast<T>(i); |
| } |
| } |
| |
| } // namespace test_v_helpers |
| |
| #endif |