blob: 9fa49584820aaab360ceb927d5bad506827fc619 [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 <stdlib.h>
#include "pw_unit_test/framework.h"
#include "test_v_helpers.h"
// Test for vmerge.vim and vmerge.vvm instructions.
namespace vmerge_test {
namespace {
using namespace test_v_helpers;
uint8_t src_vector_1[MAXVL_BYTES];
uint8_t src_vector_2[MAXVL_BYTES];
uint8_t src_mask_vector[MAXVL_BYTES];
uint8_t dest_vector[MAXVL_BYTES];
class VmergeTest : public ::testing::Test {
protected:
void SetUp() override { zero_vector_registers(); }
void TearDown() override { zero_vector_registers(); }
};
TEST_F(VmergeTest, vmerge_vim) {
for (int i = 0; i < AVL_COUNT; i++) {
int32_t avl = AVLS[i];
int vlmax;
int vl;
/* For non narrowing instructions all vectors have same type*/
std::tie(vlmax, vl) = vector_test_setup<uint8_t>(
VLMUL::LMUL_M1, avl, {dest_vector, src_vector_2, src_mask_vector});
if (avl > vlmax) {
continue;
}
fill_random_vector<uint8_t>(src_vector_2, vl);
fill_random_vector<uint8_t>(src_mask_vector, vl);
const int8_t test_val = 12;
// Load vector registers
__asm__ volatile("vle8.v v16, (%0)" : : "r"(src_vector_2));
__asm__ volatile("vle8.v v0, (%0)" : : "r"(src_mask_vector));
// Run target instruction
__asm__ volatile("vmerge.vim v24, v16, %[IMM], v0" ::[IMM] "n"(test_val));
// Store result vector register
__asm__ volatile("vse8.v v24, (%0)" : : "r"(dest_vector));
// Check vector elements
constexpr uint32_t kShift = 3; // shift for uint8_t
for (int idx = 0; idx < vl; idx++) {
uint32_t mask_idx = idx >> kShift;
uint32_t mask_pos = idx & ~(mask_idx << kShift);
if (src_mask_vector[mask_idx] & (1 << mask_pos)) {
ASSERT_EQ(dest_vector[idx], test_val);
} else {
ASSERT_EQ(dest_vector[idx], src_vector_2[idx]);
}
}
}
}
TEST_F(VmergeTest, vmerge_vvm) {
for (int i = 0; i < AVL_COUNT; i++) {
int32_t avl = AVLS[i];
int vlmax;
int vl;
/* For non narrowing instructions all vectors have same type*/
std::tie(vlmax, vl) = vector_test_setup<uint8_t>(
VLMUL::LMUL_M1, avl,
{dest_vector, src_vector_1, src_vector_2, src_mask_vector});
if (avl > vlmax) {
continue;
}
fill_random_vector<uint8_t>(src_vector_1, vl);
fill_random_vector<uint8_t>(src_vector_2, vl);
fill_random_vector<uint8_t>(src_mask_vector, vl);
// Load vector registers
__asm__ volatile("vle8.v v8, (%0)" : : "r"(src_vector_1));
__asm__ volatile("vle8.v v16, (%0)" : : "r"(src_vector_2));
__asm__ volatile("vle8.v v0, (%0)" : : "r"(src_mask_vector));
// Run target instruction
__asm__ volatile("vmerge.vvm v24, v16, v8, v0");
// Store result vector register
__asm__ volatile("vse8.v v24, (%0)" : : "r"(dest_vector));
// Check vector elements
constexpr uint32_t kShift = 3; // shift for uint8_t
for (int idx = 0; idx < vl; idx++) {
uint32_t mask_idx = idx >> kShift;
uint32_t mask_pos = idx & ~(mask_idx << kShift);
if (src_mask_vector[mask_idx] & (1 << mask_pos)) {
ASSERT_EQ(dest_vector[idx], src_vector_1[idx]);
} else {
ASSERT_EQ(dest_vector[idx], src_vector_2[idx]);
}
}
}
}
} // namespace
} // namespace vmerge_test