13 #include "sw/device/lib/testing/test_framework/check.h"
27 void (*setup_buf1)(uint8_t *, size_t);
28 void (*setup_buf2)(uint8_t *, size_t);
33 void (*func)(uint8_t *buf1, uint8_t *buf2,
size_t num_runs);
36 size_t expected_max_num_cycles;
40 static inline uint64_t perf_test_run(
const perf_test_t *
test, uint8_t *buf1,
41 uint8_t *buf2,
size_t num_runs) {
42 CHECK(
test->setup_buf1 != NULL);
43 CHECK(
test->setup_buf2 != NULL);
44 CHECK(
test->func != NULL);
46 uint64_t total_clock_cycles = 0;
47 for (
size_t i = 0; i < num_runs; ++i) {
48 test->setup_buf1(buf1, kBufLen);
49 test->setup_buf2(buf2, kBufLen);
52 test->func(buf1, buf2, kBufLen);
61 const uint64_t num_cycles = end_cycles - start_cycles;
63 CHECK(total_clock_cycles < UINT64_MAX - num_cycles);
64 total_clock_cycles += num_cycles;
67 return total_clock_cycles;
71 static inline void fill_buf_deterministic_values(uint8_t *buf,
size_t len) {
73 for (
size_t i = 0; i < len; ++i) {
74 state = state * 17 + i;
75 buf[i] = (uint8_t)state;
80 static inline void fill_buf_zeroes(uint8_t *buf,
size_t len) {
85 static inline void fill_buf_zeroes_then_one(uint8_t *buf,
size_t len) {
86 fill_buf_zeroes(buf, len);
91 static inline void fill_buf_one_then_zeroes(uint8_t *buf,
size_t len) {
92 fill_buf_zeroes(buf, len);
96 OT_NOINLINE void test_memcpy(uint8_t *buf1, uint8_t *buf2,
size_t len) {
100 OT_NOINLINE void test_memset(uint8_t *buf1, uint8_t *buf2,
size_t len) {
101 const int value = buf2[0];
105 OT_NOINLINE void test_memcmp(uint8_t *buf1, uint8_t *buf2,
size_t len) {
109 OT_NOINLINE void test_memrcmp(uint8_t *buf1, uint8_t *buf2,
size_t len) {
113 OT_NOINLINE void test_memchr(uint8_t *buf1, uint8_t *buf2,
size_t len) {
114 const uint8_t value = buf1[len - 1];
118 OT_NOINLINE void test_memrchr(uint8_t *buf1, uint8_t *buf2,
size_t len) {
119 const uint8_t value = buf1[0];
123 OTTF_DEFINE_TEST_CONFIG();
148 .setup_buf1 = &fill_buf_deterministic_values,
149 .setup_buf2 = &fill_buf_deterministic_values,
150 .func = &test_memcpy,
151 .expected_max_num_cycles = 33270,
154 .label =
"memcpy_zeroes",
155 .setup_buf1 = &fill_buf_deterministic_values,
156 .setup_buf2 = &fill_buf_zeroes,
157 .func = &test_memcpy,
158 .expected_max_num_cycles = 33270,
162 .setup_buf1 = &fill_buf_zeroes,
163 .setup_buf2 = &fill_buf_deterministic_values,
164 .func = &test_memset,
165 .expected_max_num_cycles = 23200,
168 .label =
"memset_zeroes",
169 .setup_buf1 = &fill_buf_zeroes,
170 .setup_buf2 = &fill_buf_zeroes,
171 .func = &test_memset,
172 .expected_max_num_cycles = 23200,
175 .label =
"memcmp_pathological",
176 .setup_buf1 = &fill_buf_zeroes_then_one,
177 .setup_buf2 = &fill_buf_zeroes,
178 .func = &test_memcmp,
179 .expected_max_num_cycles = 110740,
182 .label =
"memcmp_zeroes",
183 .setup_buf1 = &fill_buf_zeroes,
184 .setup_buf2 = &fill_buf_zeroes,
185 .func = &test_memcmp,
186 .expected_max_num_cycles = 110740,
189 .label =
"memrcmp_pathological",
190 .setup_buf1 = &fill_buf_zeroes,
191 .setup_buf2 = &fill_buf_one_then_zeroes,
192 .func = &test_memrcmp,
193 .expected_max_num_cycles = 50740,
196 .label =
"memrcmp_zeroes",
197 .setup_buf1 = &fill_buf_zeroes,
198 .setup_buf2 = &fill_buf_zeroes,
199 .func = &test_memrcmp,
200 .expected_max_num_cycles = 50850,
203 .label =
"memchr_pathological",
204 .setup_buf1 = &fill_buf_deterministic_values,
205 .setup_buf2 = &fill_buf_zeroes,
206 .func = &test_memchr,
207 .expected_max_num_cycles = 7250,
210 .label =
"memrchr_pathological",
211 .setup_buf1 = &fill_buf_deterministic_values,
212 .setup_buf2 = &fill_buf_deterministic_values,
213 .func = &test_memrchr,
214 .expected_max_num_cycles = 23850,
218 static uint8_t buf1[kBufLen];
219 static uint8_t buf2[kBufLen];
222 bool all_expectations_match =
true;
223 for (
size_t i = 0; i <
ARRAYSIZE(kPerfTests); ++i) {
226 const uint64_t num_cycles = perf_test_run(
test, buf1, buf2, kNumRuns);
227 if (num_cycles >
test->expected_max_num_cycles) {
228 all_expectations_match =
false;
231 CHECK(
test->expected_max_num_cycles < UINT32_MAX);
232 CHECK(num_cycles < UINT32_MAX);
233 const uint32_t expected_max_num_cycles_u32 =
234 (uint32_t)
test->expected_max_num_cycles;
235 const uint32_t num_cycles_u32 = (uint32_t)num_cycles;
237 CHECK(num_cycles < UINT32_MAX / 100);
238 const uint32_t percent_change =
239 (100 * num_cycles_u32) / expected_max_num_cycles_u32;
243 " Expected: %10d cycles\n"
244 " Actual: %10d cycles\n"
245 " Actual/Expected: %10d%%\n",
246 test->label, expected_max_num_cycles_u32, num_cycles_u32,
250 return all_expectations_match;