| #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 |