1a9de470cSBruce Richardson /* SPDX-License-Identifier: BSD-3-Clause 2a9de470cSBruce Richardson * Copyright(c) 2010-2014 Intel Corporation 3a9de470cSBruce Richardson */ 4a9de470cSBruce Richardson 5a9de470cSBruce Richardson #include <stdio.h> 6a9de470cSBruce Richardson #include <inttypes.h> 7a9de470cSBruce Richardson #include <string.h> 8a9de470cSBruce Richardson #include <math.h> 9a9de470cSBruce Richardson #include <rte_common.h> 10a9de470cSBruce Richardson #include <rte_hexdump.h> 11a9de470cSBruce Richardson #include <rte_pause.h> 12a9de470cSBruce Richardson 13a9de470cSBruce Richardson #include "test.h" 14a9de470cSBruce Richardson 15a9de470cSBruce Richardson #define MAX_NUM 1 << 20 16a9de470cSBruce Richardson 17a9de470cSBruce Richardson #define FAIL(x)\ 18a9de470cSBruce Richardson {printf(x "() test failed!\n");\ 19a9de470cSBruce Richardson return -1;} 20a9de470cSBruce Richardson 21a9de470cSBruce Richardson /* this is really a sanity check */ 22a9de470cSBruce Richardson static int 23a9de470cSBruce Richardson test_macros(int __rte_unused unused_parm) 24a9de470cSBruce Richardson { 25a9de470cSBruce Richardson #define SMALLER 0x1000U 26a9de470cSBruce Richardson #define BIGGER 0x2000U 27a9de470cSBruce Richardson #define PTR_DIFF BIGGER - SMALLER 28a9de470cSBruce Richardson #define FAIL_MACRO(x)\ 29a9de470cSBruce Richardson {printf(#x "() test failed!\n");\ 30a9de470cSBruce Richardson return -1;} 31a9de470cSBruce Richardson 32a9de470cSBruce Richardson uintptr_t unused = 0; 33a9de470cSBruce Richardson 34a9de470cSBruce Richardson RTE_SET_USED(unused); 35a9de470cSBruce Richardson 36a9de470cSBruce Richardson if ((uintptr_t)RTE_PTR_ADD(SMALLER, PTR_DIFF) != BIGGER) 37a9de470cSBruce Richardson FAIL_MACRO(RTE_PTR_ADD); 38a9de470cSBruce Richardson if ((uintptr_t)RTE_PTR_SUB(BIGGER, PTR_DIFF) != SMALLER) 39a9de470cSBruce Richardson FAIL_MACRO(RTE_PTR_SUB); 40a9de470cSBruce Richardson if (RTE_PTR_DIFF(BIGGER, SMALLER) != PTR_DIFF) 41a9de470cSBruce Richardson FAIL_MACRO(RTE_PTR_DIFF); 42a9de470cSBruce Richardson if (RTE_MAX(SMALLER, BIGGER) != BIGGER) 43a9de470cSBruce Richardson FAIL_MACRO(RTE_MAX); 44a9de470cSBruce Richardson if (RTE_MIN(SMALLER, BIGGER) != SMALLER) 45a9de470cSBruce Richardson FAIL_MACRO(RTE_MIN); 46a9de470cSBruce Richardson 47a9de470cSBruce Richardson if (strncmp(RTE_STR(test), "test", sizeof("test"))) 48a9de470cSBruce Richardson FAIL_MACRO(RTE_STR); 49a9de470cSBruce Richardson 50a9de470cSBruce Richardson return 0; 51a9de470cSBruce Richardson } 52a9de470cSBruce Richardson 53a9de470cSBruce Richardson static int 54a9de470cSBruce Richardson test_bsf(void) 55a9de470cSBruce Richardson { 56a9de470cSBruce Richardson uint32_t shift, pos; 57a9de470cSBruce Richardson 58a9de470cSBruce Richardson /* safe versions should be able to handle 0 */ 59a9de470cSBruce Richardson if (rte_bsf32_safe(0, &pos) != 0) 60a9de470cSBruce Richardson FAIL("rte_bsf32_safe"); 61a9de470cSBruce Richardson if (rte_bsf64_safe(0, &pos) != 0) 62a9de470cSBruce Richardson FAIL("rte_bsf64_safe"); 63a9de470cSBruce Richardson 64a9de470cSBruce Richardson for (shift = 0; shift < 63; shift++) { 65a9de470cSBruce Richardson uint32_t val32; 66a9de470cSBruce Richardson uint64_t val64; 67a9de470cSBruce Richardson 68a9de470cSBruce Richardson val64 = 1ULL << shift; 69a9de470cSBruce Richardson if ((uint32_t)rte_bsf64(val64) != shift) 70a9de470cSBruce Richardson FAIL("rte_bsf64"); 71a9de470cSBruce Richardson if (rte_bsf64_safe(val64, &pos) != 1) 72a9de470cSBruce Richardson FAIL("rte_bsf64_safe"); 73a9de470cSBruce Richardson if (pos != shift) 74a9de470cSBruce Richardson FAIL("rte_bsf64_safe"); 75a9de470cSBruce Richardson 76a9de470cSBruce Richardson if (shift > 31) 77a9de470cSBruce Richardson continue; 78a9de470cSBruce Richardson 79a9de470cSBruce Richardson val32 = 1U << shift; 80a9de470cSBruce Richardson if ((uint32_t)rte_bsf32(val32) != shift) 81a9de470cSBruce Richardson FAIL("rte_bsf32"); 82a9de470cSBruce Richardson if (rte_bsf32_safe(val32, &pos) != 1) 83a9de470cSBruce Richardson FAIL("rte_bsf32_safe"); 84a9de470cSBruce Richardson if (pos != shift) 85a9de470cSBruce Richardson FAIL("rte_bsf32_safe"); 86a9de470cSBruce Richardson } 87a9de470cSBruce Richardson 88a9de470cSBruce Richardson return 0; 89a9de470cSBruce Richardson } 90a9de470cSBruce Richardson 91a9de470cSBruce Richardson static int 92a9de470cSBruce Richardson test_misc(void) 93a9de470cSBruce Richardson { 94a9de470cSBruce Richardson char memdump[] = "memdump_test"; 95a9de470cSBruce Richardson 96a9de470cSBruce Richardson rte_memdump(stdout, "test", memdump, sizeof(memdump)); 97a9de470cSBruce Richardson rte_hexdump(stdout, "test", memdump, sizeof(memdump)); 98a9de470cSBruce Richardson 99a9de470cSBruce Richardson rte_pause(); 100a9de470cSBruce Richardson 101a9de470cSBruce Richardson return 0; 102a9de470cSBruce Richardson } 103a9de470cSBruce Richardson 104a9de470cSBruce Richardson static int 105a9de470cSBruce Richardson test_align(void) 106a9de470cSBruce Richardson { 107a9de470cSBruce Richardson #define FAIL_ALIGN(x, i, p)\ 108a9de470cSBruce Richardson {printf(x "() test failed: %u %u\n", i, p);\ 109a9de470cSBruce Richardson return -1;} 110a9de470cSBruce Richardson #define FAIL_ALIGN64(x, j, q)\ 111a9de470cSBruce Richardson {printf(x "() test failed: %"PRIu64" %"PRIu64"\n", j, q);\ 112a9de470cSBruce Richardson return -1; } 113a9de470cSBruce Richardson #define ERROR_FLOOR(res, i, pow) \ 114a9de470cSBruce Richardson (res % pow) || /* check if not aligned */ \ 115a9de470cSBruce Richardson ((res / pow) != (i / pow)) /* check if correct alignment */ 116a9de470cSBruce Richardson #define ERROR_CEIL(res, i, pow) \ 117a9de470cSBruce Richardson (res % pow) || /* check if not aligned */ \ 118a9de470cSBruce Richardson ((i % pow) == 0 ? /* check if ceiling is invoked */ \ 119a9de470cSBruce Richardson val / pow != i / pow : /* if aligned */ \ 120a9de470cSBruce Richardson val / pow != (i / pow) + 1) /* if not aligned, hence +1 */ 121a9de470cSBruce Richardson 122a9de470cSBruce Richardson uint32_t i, p, val; 123a9de470cSBruce Richardson uint64_t j, q; 124a9de470cSBruce Richardson 125a9de470cSBruce Richardson for (i = 1, p = 1; i <= MAX_NUM; i ++) { 126a9de470cSBruce Richardson if (rte_align32pow2(i) != p) 127a9de470cSBruce Richardson FAIL_ALIGN("rte_align32pow2", i, p); 128a9de470cSBruce Richardson if (i == p) 129a9de470cSBruce Richardson p <<= 1; 130a9de470cSBruce Richardson } 131a9de470cSBruce Richardson 132a9de470cSBruce Richardson for (i = 1, p = 1; i <= MAX_NUM; i++) { 133a9de470cSBruce Richardson if (rte_align32prevpow2(i) != p) 134a9de470cSBruce Richardson FAIL_ALIGN("rte_align32prevpow2", i, p); 135a9de470cSBruce Richardson if (rte_is_power_of_2(i + 1)) 136a9de470cSBruce Richardson p = i + 1; 137a9de470cSBruce Richardson } 138a9de470cSBruce Richardson 139a9de470cSBruce Richardson for (j = 1, q = 1; j <= MAX_NUM ; j++) { 140a9de470cSBruce Richardson if (rte_align64pow2(j) != q) 141a9de470cSBruce Richardson FAIL_ALIGN64("rte_align64pow2", j, q); 142a9de470cSBruce Richardson if (j == q) 143a9de470cSBruce Richardson q <<= 1; 144a9de470cSBruce Richardson } 145a9de470cSBruce Richardson 146a9de470cSBruce Richardson for (j = 1, q = 1; j <= MAX_NUM ; j++) { 147a9de470cSBruce Richardson if (rte_align64prevpow2(j) != q) 148a9de470cSBruce Richardson FAIL_ALIGN64("rte_align64prevpow2", j, q); 149a9de470cSBruce Richardson if (rte_is_power_of_2(j + 1)) 150a9de470cSBruce Richardson q = j + 1; 151a9de470cSBruce Richardson } 152a9de470cSBruce Richardson 153a9de470cSBruce Richardson for (p = 2; p <= MAX_NUM; p <<= 1) { 154a9de470cSBruce Richardson 155a9de470cSBruce Richardson if (!rte_is_power_of_2(p)) 156a9de470cSBruce Richardson FAIL("rte_is_power_of_2"); 157a9de470cSBruce Richardson 158a9de470cSBruce Richardson for (i = 1; i <= MAX_NUM; i++) { 159a9de470cSBruce Richardson /* align floor */ 160a9de470cSBruce Richardson if (RTE_ALIGN_FLOOR((uintptr_t)i, p) % p) 161a9de470cSBruce Richardson FAIL_ALIGN("RTE_ALIGN_FLOOR", i, p); 162a9de470cSBruce Richardson 163a9de470cSBruce Richardson val = RTE_PTR_ALIGN_FLOOR((uintptr_t) i, p); 164a9de470cSBruce Richardson if (ERROR_FLOOR(val, i, p)) 165a9de470cSBruce Richardson FAIL_ALIGN("RTE_PTR_ALIGN_FLOOR", i, p); 166a9de470cSBruce Richardson 167a9de470cSBruce Richardson val = RTE_ALIGN_FLOOR(i, p); 168a9de470cSBruce Richardson if (ERROR_FLOOR(val, i, p)) 169a9de470cSBruce Richardson FAIL_ALIGN("RTE_ALIGN_FLOOR", i, p); 170a9de470cSBruce Richardson 171a9de470cSBruce Richardson /* align ceiling */ 172a9de470cSBruce Richardson val = RTE_PTR_ALIGN((uintptr_t) i, p); 173a9de470cSBruce Richardson if (ERROR_CEIL(val, i, p)) 174a9de470cSBruce Richardson FAIL_ALIGN("RTE_PTR_ALIGN", i, p); 175a9de470cSBruce Richardson 176a9de470cSBruce Richardson val = RTE_ALIGN(i, p); 177a9de470cSBruce Richardson if (ERROR_CEIL(val, i, p)) 178a9de470cSBruce Richardson FAIL_ALIGN("RTE_ALIGN", i, p); 179a9de470cSBruce Richardson 180a9de470cSBruce Richardson val = RTE_ALIGN_CEIL(i, p); 181a9de470cSBruce Richardson if (ERROR_CEIL(val, i, p)) 182a9de470cSBruce Richardson FAIL_ALIGN("RTE_ALIGN_CEIL", i, p); 183a9de470cSBruce Richardson 184a9de470cSBruce Richardson val = RTE_PTR_ALIGN_CEIL((uintptr_t)i, p); 185a9de470cSBruce Richardson if (ERROR_CEIL(val, i, p)) 186a9de470cSBruce Richardson FAIL_ALIGN("RTE_PTR_ALIGN_CEIL", i, p); 187a9de470cSBruce Richardson 188a9de470cSBruce Richardson /* by this point we know that val is aligned to p */ 189a9de470cSBruce Richardson if (!rte_is_aligned((void*)(uintptr_t) val, p)) 190a9de470cSBruce Richardson FAIL("rte_is_aligned"); 191a9de470cSBruce Richardson } 192a9de470cSBruce Richardson } 193a9de470cSBruce Richardson 194a9de470cSBruce Richardson for (p = 1; p <= MAX_NUM / 2; p++) { 195a9de470cSBruce Richardson for (i = 1; i <= MAX_NUM / 2; i++) { 196a9de470cSBruce Richardson val = RTE_ALIGN_MUL_CEIL(i, p); 197a9de470cSBruce Richardson if (val % p != 0 || val < i) 198a9de470cSBruce Richardson FAIL_ALIGN("RTE_ALIGN_MUL_CEIL", i, p); 199a9de470cSBruce Richardson val = RTE_ALIGN_MUL_FLOOR(i, p); 200a9de470cSBruce Richardson if (val % p != 0 || val > i) 201a9de470cSBruce Richardson FAIL_ALIGN("RTE_ALIGN_MUL_FLOOR", i, p); 202f56e5514SPavan Nikhilesh val = RTE_ALIGN_MUL_NEAR(i, p); 203f56e5514SPavan Nikhilesh if (val % p != 0 || ((val != RTE_ALIGN_MUL_CEIL(i, p)) 204f56e5514SPavan Nikhilesh & (val != RTE_ALIGN_MUL_FLOOR(i, p)))) 205f56e5514SPavan Nikhilesh FAIL_ALIGN("RTE_ALIGN_MUL_NEAR", i, p); 206a9de470cSBruce Richardson } 207a9de470cSBruce Richardson } 208a9de470cSBruce Richardson 209a9de470cSBruce Richardson return 0; 210a9de470cSBruce Richardson } 211a9de470cSBruce Richardson 212a9de470cSBruce Richardson static int 213a9de470cSBruce Richardson test_log2(void) 214a9de470cSBruce Richardson { 215a9de470cSBruce Richardson uint32_t i, base, compare; 216a9de470cSBruce Richardson const uint32_t max = 0x10000; 217a9de470cSBruce Richardson const uint32_t step = 1; 218a9de470cSBruce Richardson 219*30a0df64SDavid Marchand compare = rte_log2_u32(0); 220*30a0df64SDavid Marchand if (compare != 0) { 221*30a0df64SDavid Marchand printf("Wrong rte_log2_u32(0) val %x, expected 0\n", compare); 222*30a0df64SDavid Marchand return TEST_FAILED; 223*30a0df64SDavid Marchand } 224*30a0df64SDavid Marchand 225*30a0df64SDavid Marchand compare = rte_log2_u64(0); 226*30a0df64SDavid Marchand if (compare != 0) { 227*30a0df64SDavid Marchand printf("Wrong rte_log2_u64(0) val %x, expected 0\n", compare); 228*30a0df64SDavid Marchand return TEST_FAILED; 229*30a0df64SDavid Marchand } 230*30a0df64SDavid Marchand 231*30a0df64SDavid Marchand for (i = 1; i < max; i = i + step) { 232a9de470cSBruce Richardson uint64_t i64; 233a9de470cSBruce Richardson 234a9de470cSBruce Richardson /* extend range for 64-bit */ 235a9de470cSBruce Richardson i64 = (uint64_t)i << 32; 236a9de470cSBruce Richardson base = (uint32_t)ceilf(log2(i64)); 237a9de470cSBruce Richardson compare = rte_log2_u64(i64); 238a9de470cSBruce Richardson if (base != compare) { 239a9de470cSBruce Richardson printf("Wrong rte_log2_u64(%" PRIx64 ") val %x, expected %x\n", 240a9de470cSBruce Richardson i64, compare, base); 241a9de470cSBruce Richardson return TEST_FAILED; 242a9de470cSBruce Richardson } 243a9de470cSBruce Richardson 244a9de470cSBruce Richardson base = (uint32_t)ceilf(log2((uint32_t)i)); 245a9de470cSBruce Richardson compare = rte_log2_u32((uint32_t)i); 246a9de470cSBruce Richardson if (base != compare) { 247a9de470cSBruce Richardson printf("Wrong rte_log2_u32(%x) val %x, expected %x\n", 248a9de470cSBruce Richardson i, compare, base); 249a9de470cSBruce Richardson return TEST_FAILED; 250a9de470cSBruce Richardson } 251a9de470cSBruce Richardson compare = rte_log2_u64((uint64_t)i); 252a9de470cSBruce Richardson if (base != compare) { 253a9de470cSBruce Richardson printf("Wrong rte_log2_u64(%x) val %x, expected %x\n", 254a9de470cSBruce Richardson i, compare, base); 255a9de470cSBruce Richardson return TEST_FAILED; 256a9de470cSBruce Richardson } 257a9de470cSBruce Richardson } 258a9de470cSBruce Richardson return 0; 259a9de470cSBruce Richardson } 260a9de470cSBruce Richardson 261a9de470cSBruce Richardson static int 262a9de470cSBruce Richardson test_fls(void) 263a9de470cSBruce Richardson { 264a9de470cSBruce Richardson struct fls_test_vector { 265a9de470cSBruce Richardson uint32_t arg; 266a9de470cSBruce Richardson int rc; 267a9de470cSBruce Richardson }; 268a9de470cSBruce Richardson int expected, rc; 269a9de470cSBruce Richardson uint32_t i, arg; 270a9de470cSBruce Richardson 271a9de470cSBruce Richardson const struct fls_test_vector test[] = { 272a9de470cSBruce Richardson {0x0, 0}, 273a9de470cSBruce Richardson {0x1, 1}, 274a9de470cSBruce Richardson {0x4000, 15}, 275a9de470cSBruce Richardson {0x80000000, 32}, 276a9de470cSBruce Richardson }; 277a9de470cSBruce Richardson 278a9de470cSBruce Richardson for (i = 0; i < RTE_DIM(test); i++) { 279a9de470cSBruce Richardson uint64_t arg64; 280a9de470cSBruce Richardson 281a9de470cSBruce Richardson arg = test[i].arg; 282a9de470cSBruce Richardson rc = rte_fls_u32(arg); 283a9de470cSBruce Richardson expected = test[i].rc; 284a9de470cSBruce Richardson if (rc != expected) { 285a9de470cSBruce Richardson printf("Wrong rte_fls_u32(0x%x) rc=%d, expected=%d\n", 286a9de470cSBruce Richardson arg, rc, expected); 287a9de470cSBruce Richardson return TEST_FAILED; 288a9de470cSBruce Richardson } 289a9de470cSBruce Richardson /* 64-bit version */ 290a9de470cSBruce Richardson arg = test[i].arg; 291a9de470cSBruce Richardson rc = rte_fls_u64(arg); 292a9de470cSBruce Richardson expected = test[i].rc; 293a9de470cSBruce Richardson if (rc != expected) { 294a9de470cSBruce Richardson printf("Wrong rte_fls_u64(0x%x) rc=%d, expected=%d\n", 295a9de470cSBruce Richardson arg, rc, expected); 296a9de470cSBruce Richardson return TEST_FAILED; 297a9de470cSBruce Richardson } 298a9de470cSBruce Richardson /* 64-bit version shifted by 32 bits */ 299a9de470cSBruce Richardson arg64 = (uint64_t)test[i].arg << 32; 300a9de470cSBruce Richardson rc = rte_fls_u64(arg64); 301a9de470cSBruce Richardson /* don't shift zero */ 302a9de470cSBruce Richardson expected = test[i].rc == 0 ? 0 : test[i].rc + 32; 303a9de470cSBruce Richardson if (rc != expected) { 304a9de470cSBruce Richardson printf("Wrong rte_fls_u64(0x%" PRIx64 ") rc=%d, expected=%d\n", 305a9de470cSBruce Richardson arg64, rc, expected); 306a9de470cSBruce Richardson return TEST_FAILED; 307a9de470cSBruce Richardson } 308a9de470cSBruce Richardson } 309a9de470cSBruce Richardson 310a9de470cSBruce Richardson return 0; 311a9de470cSBruce Richardson } 312a9de470cSBruce Richardson 313a9de470cSBruce Richardson static int 314a9de470cSBruce Richardson test_common(void) 315a9de470cSBruce Richardson { 316a9de470cSBruce Richardson int ret = 0; 317a9de470cSBruce Richardson ret |= test_align(); 318a9de470cSBruce Richardson ret |= test_macros(0); 319a9de470cSBruce Richardson ret |= test_misc(); 320a9de470cSBruce Richardson ret |= test_bsf(); 321a9de470cSBruce Richardson ret |= test_log2(); 322a9de470cSBruce Richardson ret |= test_fls(); 323a9de470cSBruce Richardson 324a9de470cSBruce Richardson return ret; 325a9de470cSBruce Richardson } 326a9de470cSBruce Richardson 327a9de470cSBruce Richardson REGISTER_TEST_COMMAND(common_autotest, test_common); 328