diff options
Diffstat (limited to 'test/unaligned_access.cc')
-rw-r--r-- | test/unaligned_access.cc | 157 |
1 files changed, 157 insertions, 0 deletions
diff --git a/test/unaligned_access.cc b/test/unaligned_access.cc new file mode 100644 index 0000000000..f3dc99d432 --- /dev/null +++ b/test/unaligned_access.cc @@ -0,0 +1,157 @@ +/* Copyright 2023 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/** + * Test if unaligned access works properly + */ + +#include "common.h" +#include "console.h" +#include "test_util.h" + +extern "C" { +#include "shared_mem.h" +#include "timer.h" +} + +#include <array> +#include <cstdio> +#include <cstring> + +test_static int test_unaligned_access() +{ + /* This is equivalent to {0xff, 0x09, 0x04, 0x06, 0x04, 0x06, 0x07, + * 0xed, 0x0a, 0x0b, 0x0d, 0x38, 0xbd, 0x57, 0x59} */ + alignas(int32_t) constexpr std::array<int8_t, 15> test_array = { + -1, 9, 4, 6, 4, 6, 7, -19, 10, 11, 13, 56, -67, 87, 89 + }; + + constexpr std::array<int32_t, 12> expected_results = { + 0x060409ff, + 0x04060409, + 0x06040604, + 0x07060406, + static_cast<int32_t>(0xed070604), + 0x0aed0706, + 0x0b0aed07, + 0x0d0b0aed, + 0x380d0b0a, + static_cast<int32_t>(0xbd380d0b), + 0x57bd380d, + 0x5957bd38 + }; + + /* If i % 4 = 0, we have an aligned access. Otherwise, it is + unaligned access. */ + for (int i = 0; i < expected_results.size(); ++i) { + const int32_t *test_array_ptr = + reinterpret_cast<const int32_t *>(test_array.data() + + i); + + TEST_EQ(*test_array_ptr, expected_results[i], "0x%08x"); + } + + return EC_SUCCESS; +} + +test_static int benchmark_unaligned_access_memcpy() +{ + int i; + timestamp_t t0, t1, t2, t3; + char *buf; + const int buf_size = 1000; + const int len = 400; + const int dest_offset = 500; + const int iteration = 1000; + + TEST_ASSERT(shared_mem_acquire(buf_size, &buf) == EC_SUCCESS); + + for (i = 0; i < len; ++i) + buf[i] = i & 0x7f; + for (i = len; i < buf_size; ++i) + buf[i] = 0; + + t0 = get_time(); + for (i = 0; i < iteration; ++i) { + memcpy(buf + dest_offset + 1, buf, len); /* unaligned */ + } + t1 = get_time(); + TEST_ASSERT_ARRAY_EQ(buf + dest_offset + 1, buf, len); + ccprintf(" (speed gain: %" PRId64 " ->", t1.val - t0.val); + + t2 = get_time(); + for (i = 0; i < iteration; ++i) { + memcpy(buf + dest_offset, buf, len); /* aligned */ + } + t3 = get_time(); + ccprintf(" %" PRId64 " us) ", t3.val - t2.val); + TEST_ASSERT_ARRAY_EQ(buf + dest_offset, buf, len); + return EC_SUCCESS; +} + +test_static int benchmark_unaligned_access_array() +{ + timestamp_t t0, t1, t2, t3; + const int iteration = 1000; + + alignas(int32_t) std::array<int8_t, 100> test_array_1; + std::array<int32_t, 20> test_array_2; + constexpr std::array<int32_t, 20> test_array_3 = { + 67305985, 134678021, 202050057, 269422093, 336794129, + 404166165, 471538201, 538910237, 606282273, 673654309, + 741026345, 808398381, 875770417, 943142453, 1010514489, + 1077886525, 1145258561, 1212630597, 1280002633, 1347374669 + }; + constexpr std::array<int32_t, 20> test_array_4 = { + 50462976, 117835012, 185207048, 252579084, 319951120, + 387323156, 454695192, 522067228, 589439264, 656811300, + 724183336, 791555372, 858927408, 926299444, 993671480, + 1061043516, 1128415552, 1195787588, 1263159624, 1330531660 + }; + + for (int i = 0; i < test_array_1.size(); ++i) { + test_array_1[i] = static_cast<int8_t>(i); + } + + t0 = get_time(); + for (int t = 0; t < iteration; ++t) { + const int32_t *test_array_1_ptr = + reinterpret_cast<const int32_t *>(test_array_1.data() + + 1); + + for (int i = 0; i < test_array_2.size(); ++i) { + test_array_2[i] = (*test_array_1_ptr++); /* unaligned */ + } + TEST_ASSERT_ARRAY_EQ(test_array_2.data(), test_array_3.data(), + test_array_2.size()); + } + t1 = get_time(); + ccprintf(" (speed gain: %" PRId64 " ->", t1.val - t0.val); + + t2 = get_time(); + for (int t = 0; t < iteration; ++t) { + const int32_t *test_array_1_ptr = + reinterpret_cast<const int32_t *>(test_array_1.data()); + + for (int i = 0; i < test_array_2.size(); ++i) { + test_array_2[i] = (*test_array_1_ptr++); /* aligned */ + } + TEST_ASSERT_ARRAY_EQ(test_array_2.data(), test_array_4.data(), + test_array_2.size()); + } + t3 = get_time(); + ccprintf(" %" PRId64 " us) ", t3.val - t2.val); + + return EC_SUCCESS; +} + +extern "C" void run_test(int, const char **) +{ + test_reset(); + RUN_TEST(test_unaligned_access); + RUN_TEST(benchmark_unaligned_access_memcpy); + RUN_TEST(benchmark_unaligned_access_array); + test_print_result(); +} |