eal: add functions for previous power of 2 alignment
Add 32b and 64b API's to align the given integer to the previous power of 2. Update common auto test to include test for previous power of 2 for both 32 and 64bit integers. Signed-off-by: Pavan Nikhilesh <pbhagavatula@caviumnetworks.com>
This commit is contained in:
parent
5120203d75
commit
08f683174e
@ -239,6 +239,51 @@ extern int RTE_BUILD_BUG_ON_detected_error;
|
||||
} while(0)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Combines 32b inputs most significant set bits into the least
|
||||
* significant bits to construct a value with the same MSBs as x
|
||||
* but all 1's under it.
|
||||
*
|
||||
* @param x
|
||||
* The integer whose MSBs need to be combined with its LSBs
|
||||
* @return
|
||||
* The combined value.
|
||||
*/
|
||||
static inline uint32_t
|
||||
rte_combine32ms1b(register uint32_t x)
|
||||
{
|
||||
x |= x >> 1;
|
||||
x |= x >> 2;
|
||||
x |= x >> 4;
|
||||
x |= x >> 8;
|
||||
x |= x >> 16;
|
||||
|
||||
return x;
|
||||
}
|
||||
|
||||
/**
|
||||
* Combines 64b inputs most significant set bits into the least
|
||||
* significant bits to construct a value with the same MSBs as x
|
||||
* but all 1's under it.
|
||||
*
|
||||
* @param v
|
||||
* The integer whose MSBs need to be combined with its LSBs
|
||||
* @return
|
||||
* The combined value.
|
||||
*/
|
||||
static inline uint64_t
|
||||
rte_combine64ms1b(register uint64_t v)
|
||||
{
|
||||
v |= v >> 1;
|
||||
v |= v >> 2;
|
||||
v |= v >> 4;
|
||||
v |= v >> 8;
|
||||
v |= v >> 16;
|
||||
v |= v >> 32;
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
/*********** Macros to work with powers of 2 ********/
|
||||
|
||||
/**
|
||||
@ -266,15 +311,28 @@ static inline uint32_t
|
||||
rte_align32pow2(uint32_t x)
|
||||
{
|
||||
x--;
|
||||
x |= x >> 1;
|
||||
x |= x >> 2;
|
||||
x |= x >> 4;
|
||||
x |= x >> 8;
|
||||
x |= x >> 16;
|
||||
x = rte_combine32ms1b(x);
|
||||
|
||||
return x + 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Aligns input parameter to the previous power of 2
|
||||
*
|
||||
* @param x
|
||||
* The integer value to algin
|
||||
*
|
||||
* @return
|
||||
* Input parameter aligned to the previous power of 2
|
||||
*/
|
||||
static inline uint32_t
|
||||
rte_align32prevpow2(uint32_t x)
|
||||
{
|
||||
x = rte_combine32ms1b(x);
|
||||
|
||||
return x - (x >> 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Aligns 64b input parameter to the next power of 2
|
||||
*
|
||||
@ -288,16 +346,28 @@ static inline uint64_t
|
||||
rte_align64pow2(uint64_t v)
|
||||
{
|
||||
v--;
|
||||
v |= v >> 1;
|
||||
v |= v >> 2;
|
||||
v |= v >> 4;
|
||||
v |= v >> 8;
|
||||
v |= v >> 16;
|
||||
v |= v >> 32;
|
||||
v = rte_combine64ms1b(v);
|
||||
|
||||
return v + 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Aligns 64b input parameter to the previous power of 2
|
||||
*
|
||||
* @param v
|
||||
* The 64b value to align
|
||||
*
|
||||
* @return
|
||||
* Input parameter aligned to the previous power of 2
|
||||
*/
|
||||
static inline uint64_t
|
||||
rte_align64prevpow2(uint64_t v)
|
||||
{
|
||||
v = rte_combine64ms1b(v);
|
||||
|
||||
return v - (v >> 1);
|
||||
}
|
||||
|
||||
/*********** Macros for calculating min and max **********/
|
||||
|
||||
/**
|
||||
|
@ -3,6 +3,7 @@
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <inttypes.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
#include <rte_common.h>
|
||||
@ -70,6 +71,9 @@ test_align(void)
|
||||
#define FAIL_ALIGN(x, i, p)\
|
||||
{printf(x "() test failed: %u %u\n", i, p);\
|
||||
return -1;}
|
||||
#define FAIL_ALIGN64(x, j, q)\
|
||||
{printf(x "() test failed: %"PRIu64" %"PRIu64"\n", j, q);\
|
||||
return -1; }
|
||||
#define ERROR_FLOOR(res, i, pow) \
|
||||
(res % pow) || /* check if not aligned */ \
|
||||
((res / pow) != (i / pow)) /* check if correct alignment */
|
||||
@ -80,6 +84,7 @@ test_align(void)
|
||||
val / pow != (i / pow) + 1) /* if not aligned, hence +1 */
|
||||
|
||||
uint32_t i, p, val;
|
||||
uint64_t j, q;
|
||||
|
||||
for (i = 1, p = 1; i <= MAX_NUM; i ++) {
|
||||
if (rte_align32pow2(i) != p)
|
||||
@ -88,6 +93,27 @@ test_align(void)
|
||||
p <<= 1;
|
||||
}
|
||||
|
||||
for (i = 1, p = 1; i <= MAX_NUM; i++) {
|
||||
if (rte_align32prevpow2(i) != p)
|
||||
FAIL_ALIGN("rte_align32prevpow2", i, p);
|
||||
if (rte_is_power_of_2(i + 1))
|
||||
p = i + 1;
|
||||
}
|
||||
|
||||
for (j = 1, q = 1; j <= MAX_NUM ; j++) {
|
||||
if (rte_align64pow2(j) != q)
|
||||
FAIL_ALIGN64("rte_align64pow2", j, q);
|
||||
if (j == q)
|
||||
q <<= 1;
|
||||
}
|
||||
|
||||
for (j = 1, q = 1; j <= MAX_NUM ; j++) {
|
||||
if (rte_align64prevpow2(j) != q)
|
||||
FAIL_ALIGN64("rte_align64prevpow2", j, q);
|
||||
if (rte_is_power_of_2(j + 1))
|
||||
q = j + 1;
|
||||
}
|
||||
|
||||
for (p = 2; p <= MAX_NUM; p <<= 1) {
|
||||
|
||||
if (!rte_is_power_of_2(p))
|
||||
|
Loading…
Reference in New Issue
Block a user