blob: 1d04efc3d019e6f0a9c5b23e7624edd528b9e29b [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 vl{1,2,8}re{8,16,32}.v and vs{1,2,8}r{8,16,32}.v instructions.
namespace vlnr_vsnr_test {
namespace {
using namespace test_v_helpers;
uint8_t test_vector_1[MAXVL_BYTES];
uint8_t reference_vector_1[MAXVL_BYTES];
enum VNF { NF1 = 0, NF2 = 1, NF4 = 2, NF8 = 3 };
class VlnrVsnrTest : public ::testing::Test {
public:
void vsr_test(VSEW sew, VNF nf);
protected:
void SetUp() override { zero_vector_registers(); }
void TearDown() override { zero_vector_registers(); }
};
void VlnrVsnrTest::vsr_test(VSEW sew, VNF nf) {
int avl = get_vsetvlmax_intrinsic(SEW_E8, LMUL_M1);
int vlmax;
int vl;
int nf_val = 1 << nf;
std::tie(vlmax, vl) = vector_test_setup<uint8_t>(
LMUL_M1, avl, {test_vector_1, reference_vector_1});
fill_random_vector<uint8_t>(reinterpret_cast<uint8_t *>(reference_vector_1),
avl * nf_val);
switch (nf) {
case NF1: {
switch (sew) {
case SEW_E8:
__asm__ volatile(
"vl1r.v v25, (%[REG])" ::[REG] "r"(reference_vector_1));
break;
case SEW_E16:
__asm__ volatile(
"vl1re16.v v25, (%[REG])" ::[REG] "r"(reference_vector_1));
break;
case SEW_E32:
__asm__ volatile(
"vl1re32.v v25, (%[REG])" ::[REG] "r"(reference_vector_1));
break;
default:
break;
}
__asm__ volatile("vs1r.v v25, (%[REG])" ::[REG] "r"(test_vector_1));
break;
}
case NF2: {
switch (sew) {
case SEW_E8:
__asm__ volatile(
"vl2r.v v26, (%[REG])" ::[REG] "r"(reference_vector_1));
break;
case SEW_E16:
__asm__ volatile(
"vl2re16.v v26, (%[REG])" ::[REG] "r"(reference_vector_1));
break;
case SEW_E32:
__asm__ volatile(
"vl2re32.v v26, (%[REG])" ::[REG] "r"(reference_vector_1));
break;
default:
break;
}
__asm__ volatile("vs2r.v v26, (%[REG])" ::[REG] "r"(test_vector_1));
break;
}
case NF4: {
switch (sew) {
case SEW_E8:
__asm__ volatile(
"vl4r.v v28, (%[REG])" ::[REG] "r"(reference_vector_1));
break;
case SEW_E16:
__asm__ volatile(
"vl4re16.v v28, (%[REG])" ::[REG] "r"(reference_vector_1));
break;
case SEW_E32:
__asm__ volatile(
"vl4re32.v v28, (%[REG])" ::[REG] "r"(reference_vector_1));
break;
default:
break;
}
__asm__ volatile("vs4r.v v28, (%[REG])" ::[REG] "r"(test_vector_1));
break;
}
case NF8: {
switch (sew) {
case SEW_E8:
__asm__ volatile(
"vl8r.v v0, (%[REG])" ::[REG] "r"(reference_vector_1));
break;
case SEW_E16:
__asm__ volatile(
"vl8re16.v v0, (%[REG])" ::[REG] "r"(reference_vector_1));
break;
case SEW_E32:
__asm__ volatile(
"vl8re32.v v0, (%[REG])" ::[REG] "r"(reference_vector_1));
break;
default:
break;
}
__asm__ volatile("vs8r.v v0, (%[REG])" ::[REG] "r"(test_vector_1));
break;
}
}
assert_vec_elem_eq<uint8_t>(avl * nf_val, test_vector_1, reference_vector_1);
}
TEST_F(VlnrVsnrTest, vl1re8_vs1r) { vsr_test(SEW_E8, NF1); }
TEST_F(VlnrVsnrTest, vl2re8_vs2r) { vsr_test(SEW_E8, NF2); }
TEST_F(VlnrVsnrTest, vl4re8_vs4r) { vsr_test(SEW_E8, NF4); }
TEST_F(VlnrVsnrTest, vl8re8_vs8r) { vsr_test(SEW_E8, NF8); }
TEST_F(VlnrVsnrTest, vl1re16_vs1r) { vsr_test(SEW_E16, NF1); }
TEST_F(VlnrVsnrTest, vl2re16_vs2r) { vsr_test(SEW_E16, NF2); }
TEST_F(VlnrVsnrTest, vl4re16_vs4r) { vsr_test(SEW_E16, NF4); }
TEST_F(VlnrVsnrTest, vl8re16_vs8r) { vsr_test(SEW_E16, NF8); }
TEST_F(VlnrVsnrTest, vl1re32_vs1r) { vsr_test(SEW_E32, NF1); }
TEST_F(VlnrVsnrTest, vl2re32_vs2r) { vsr_test(SEW_E32, NF2); }
TEST_F(VlnrVsnrTest, vl4re32_vs4r) { vsr_test(SEW_E32, NF4); }
TEST_F(VlnrVsnrTest, vl8re32_vs8r) { vsr_test(SEW_E32, NF8); }
} // namespace
} // namespace vlnr_vsnr_test