mirror of https://github.com/PentHertz/srsLTE.git
Implement on the fly sequence generation
This commit is contained in:
parent
6c15feeff3
commit
7291a5db91
|
@ -52,6 +52,12 @@ SRSLTE_API int srslte_sequence_LTE_pr(srslte_sequence_t* q, uint32_t len, uint32
|
||||||
|
|
||||||
SRSLTE_API int srslte_sequence_set_LTE_pr(srslte_sequence_t* q, uint32_t len, uint32_t seed);
|
SRSLTE_API int srslte_sequence_set_LTE_pr(srslte_sequence_t* q, uint32_t len, uint32_t seed);
|
||||||
|
|
||||||
|
SRSLTE_API void srslte_sequence_apply_f(const float* in, float* out, uint32_t length, uint32_t seed);
|
||||||
|
|
||||||
|
SRSLTE_API void srslte_sequence_apply_s(const int16_t* in, int16_t* out, uint32_t length, uint32_t seed);
|
||||||
|
|
||||||
|
SRSLTE_API void srslte_sequence_apply_c(const int8_t* in, int8_t* out, uint32_t length, uint32_t seed);
|
||||||
|
|
||||||
SRSLTE_API int srslte_sequence_pbch(srslte_sequence_t* seq, srslte_cp_t cp, uint32_t cell_id);
|
SRSLTE_API int srslte_sequence_pbch(srslte_sequence_t* seq, srslte_cp_t cp, uint32_t cell_id);
|
||||||
|
|
||||||
SRSLTE_API int srslte_sequence_pcfich(srslte_sequence_t* seq, uint32_t nslot, uint32_t cell_id);
|
SRSLTE_API int srslte_sequence_pcfich(srslte_sequence_t* seq, uint32_t nslot, uint32_t cell_id);
|
||||||
|
|
|
@ -168,19 +168,25 @@ __attribute__((constructor)) __attribute__((unused)) static void srslte_lte_pr_p
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void sequence_gen_LTE_pr(uint8_t* pr, uint32_t len, uint32_t seed)
|
static uint32_t sequence_get_x2_init(uint32_t seed)
|
||||||
{
|
{
|
||||||
int n = 0;
|
|
||||||
uint32_t x1 = sequence_x1_init; // X1 initial state is fix
|
|
||||||
uint32_t x2 = 0;
|
uint32_t x2 = 0;
|
||||||
|
|
||||||
// Load X2 state
|
|
||||||
for (uint32_t i = 0; i < SEQUENCE_SEED_LEN; i++) {
|
for (uint32_t i = 0; i < SEQUENCE_SEED_LEN; i++) {
|
||||||
if ((seed >> i) & 1U) {
|
if ((seed >> i) & 1U) {
|
||||||
x2 ^= sequence_x2_init[i];
|
x2 ^= sequence_x2_init[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return x2;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void sequence_gen_LTE_pr(uint8_t* pr, uint32_t len, uint32_t seed)
|
||||||
|
{
|
||||||
|
int n = 0;
|
||||||
|
uint32_t x1 = sequence_x1_init; // X1 initial state is fix
|
||||||
|
uint32_t x2 = sequence_get_x2_init(seed); // loads x2 initial state
|
||||||
|
|
||||||
// Parallel stage
|
// Parallel stage
|
||||||
if (len >= SEQUENCE_PAR_BITS) {
|
if (len >= SEQUENCE_PAR_BITS) {
|
||||||
for (; n < len - (SEQUENCE_PAR_BITS - 1); n += SEQUENCE_PAR_BITS) {
|
for (; n < len - (SEQUENCE_PAR_BITS - 1); n += SEQUENCE_PAR_BITS) {
|
||||||
|
@ -355,3 +361,173 @@ void srslte_sequence_free(srslte_sequence_t* q)
|
||||||
}
|
}
|
||||||
bzero(q, sizeof(srslte_sequence_t));
|
bzero(q, sizeof(srslte_sequence_t));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void srslte_sequence_apply_f(const float* in, float* out, uint32_t length, uint32_t seed)
|
||||||
|
{
|
||||||
|
uint32_t x1 = sequence_x1_init; // X1 initial state is fix
|
||||||
|
uint32_t x2 = sequence_get_x2_init(seed); // loads x2 initial state
|
||||||
|
|
||||||
|
uint32_t i = 0;
|
||||||
|
|
||||||
|
if (length >= SEQUENCE_PAR_BITS) {
|
||||||
|
for (; i < length - (SEQUENCE_PAR_BITS - 1); i += SEQUENCE_PAR_BITS) {
|
||||||
|
uint32_t c = (uint32_t)(x1 ^ x2);
|
||||||
|
|
||||||
|
uint32_t j = 0;
|
||||||
|
#ifdef LV_HAVE_SSE
|
||||||
|
for (; j < SEQUENCE_PAR_BITS - 3; j += 4) {
|
||||||
|
// Preloads bits of interest in the 4 LSB
|
||||||
|
__m128i mask = _mm_set1_epi32(c >> j);
|
||||||
|
|
||||||
|
// Masks each bit
|
||||||
|
mask = _mm_and_si128(mask, _mm_setr_epi32(1, 2, 4, 8));
|
||||||
|
|
||||||
|
// Get non zero mask
|
||||||
|
mask = _mm_cmpgt_epi32(mask, _mm_set1_epi32(0));
|
||||||
|
|
||||||
|
// And with MSB
|
||||||
|
mask = _mm_and_si128(mask, (__m128i)_mm_set1_ps(-0.0F));
|
||||||
|
|
||||||
|
// Load input
|
||||||
|
__m128 v = _mm_loadu_ps(in + i + j);
|
||||||
|
|
||||||
|
// Loads input and perform sign XOR
|
||||||
|
v = _mm_xor_ps((__m128)mask, v);
|
||||||
|
|
||||||
|
_mm_storeu_ps(out + i + j, v);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
for (; j < SEQUENCE_PAR_BITS; j++) {
|
||||||
|
((uint32_t*)out)[i + j] = ((uint32_t*)in)[i] ^ (((c >> j) & 1U) << 31U);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Step sequences
|
||||||
|
x1 = sequence_gen_LTE_pr_memless_step_par_x1(x1);
|
||||||
|
x2 = sequence_gen_LTE_pr_memless_step_par_x2(x2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (; i < length; i++) {
|
||||||
|
|
||||||
|
((uint32_t*)out)[i] = ((uint32_t*)in)[i] ^ (((x1 ^ x2) & 1U) << 31U);
|
||||||
|
|
||||||
|
// Step sequences
|
||||||
|
x1 = sequence_gen_LTE_pr_memless_step_x1(x1);
|
||||||
|
x2 = sequence_gen_LTE_pr_memless_step_x2(x2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void srslte_sequence_apply_s(const int16_t* in, int16_t* out, uint32_t length, uint32_t seed)
|
||||||
|
{
|
||||||
|
uint32_t x1 = sequence_x1_init; // X1 initial state is fix
|
||||||
|
uint32_t x2 = sequence_get_x2_init(seed); // loads x2 initial state
|
||||||
|
|
||||||
|
uint32_t i = 0;
|
||||||
|
|
||||||
|
if (length >= SEQUENCE_PAR_BITS) {
|
||||||
|
for (; i < length - (SEQUENCE_PAR_BITS - 1); i += SEQUENCE_PAR_BITS) {
|
||||||
|
uint32_t c = (uint32_t)(x1 ^ x2);
|
||||||
|
|
||||||
|
uint32_t j = 0;
|
||||||
|
#ifdef LV_HAVE_SSE
|
||||||
|
for (; j < SEQUENCE_PAR_BITS - 7; j += 8) {
|
||||||
|
// Preloads bits of interest in the 8 LSB
|
||||||
|
__m128i mask = _mm_set1_epi16((c >> j) & 0xff);
|
||||||
|
|
||||||
|
// Masks each bit
|
||||||
|
mask = _mm_and_si128(mask, _mm_setr_epi16(0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80));
|
||||||
|
|
||||||
|
// Get non zero mask
|
||||||
|
mask = _mm_cmpgt_epi16(mask, _mm_set1_epi16(0));
|
||||||
|
|
||||||
|
// Load input
|
||||||
|
__m128i v = _mm_loadu_si128((__m128i*)(in + i + j));
|
||||||
|
|
||||||
|
// Negate
|
||||||
|
v = _mm_xor_si128(v, mask);
|
||||||
|
|
||||||
|
// Add one
|
||||||
|
mask = _mm_and_si128(mask, _mm_set1_epi16(1));
|
||||||
|
v = _mm_add_epi16(v, mask);
|
||||||
|
|
||||||
|
_mm_storeu_si128((__m128i*)(out + i + j), v);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
for (; j < SEQUENCE_PAR_BITS; j++) {
|
||||||
|
out[i + j] = in[i + j] * (((c >> j) & 1U) ? -1 : +1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Step sequences
|
||||||
|
x1 = sequence_gen_LTE_pr_memless_step_par_x1(x1);
|
||||||
|
x2 = sequence_gen_LTE_pr_memless_step_par_x2(x2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (; i < length; i++) {
|
||||||
|
out[i] = in[i] * (((x1 ^ x2) & 1U) ? -1 : +1);
|
||||||
|
|
||||||
|
// Step sequences
|
||||||
|
x1 = sequence_gen_LTE_pr_memless_step_x1(x1);
|
||||||
|
x2 = sequence_gen_LTE_pr_memless_step_x2(x2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void srslte_sequence_apply_c(const int8_t* in, int8_t* out, uint32_t length, uint32_t seed)
|
||||||
|
{
|
||||||
|
uint32_t x1 = sequence_x1_init; // X1 initial state is fix
|
||||||
|
uint32_t x2 = sequence_get_x2_init(seed); // loads x2 initial state
|
||||||
|
|
||||||
|
uint32_t i = 0;
|
||||||
|
|
||||||
|
if (length >= SEQUENCE_PAR_BITS) {
|
||||||
|
for (; i < length - (SEQUENCE_PAR_BITS - 1); i += SEQUENCE_PAR_BITS) {
|
||||||
|
uint32_t c = (uint32_t)(x1 ^ x2);
|
||||||
|
|
||||||
|
uint32_t j = 0;
|
||||||
|
#ifdef LV_HAVE_SSE
|
||||||
|
if (SEQUENCE_PAR_BITS >= 16) {
|
||||||
|
// Preloads bits of interest in the 16 LSB
|
||||||
|
__m128i mask = _mm_set1_epi32(c);
|
||||||
|
mask = _mm_shuffle_epi8(mask, _mm_setr_epi8(0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1));
|
||||||
|
|
||||||
|
// Masks each bit
|
||||||
|
// mask = _mm_and_si128( mask, _mm_set_epi64x(0x0102040810204080, 0x0102040810204080));
|
||||||
|
mask = _mm_and_si128(mask, _mm_set_epi64x(0x8040201008040201, 0x8040201008040201));
|
||||||
|
|
||||||
|
// Get non zero mask
|
||||||
|
mask = _mm_cmpeq_epi8(mask, _mm_set_epi64x(0x8040201008040201, 0x8040201008040201));
|
||||||
|
|
||||||
|
// Load input
|
||||||
|
__m128i v = _mm_loadu_si128((__m128i*)(in + i + j));
|
||||||
|
|
||||||
|
// Negate
|
||||||
|
v = _mm_xor_si128(mask, v);
|
||||||
|
|
||||||
|
// Add one
|
||||||
|
mask = _mm_and_si128(mask, _mm_set1_epi8(1));
|
||||||
|
v = _mm_add_epi8(v, mask);
|
||||||
|
|
||||||
|
_mm_storeu_si128((__m128i*)(out + i + j), v);
|
||||||
|
|
||||||
|
// Increment bit counter `j`
|
||||||
|
j += 16;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
for (; j < SEQUENCE_PAR_BITS; j++) {
|
||||||
|
out[i + j] = in[i + j] * (((c >> j) & 1U) ? -1 : +1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Step sequences
|
||||||
|
x1 = sequence_gen_LTE_pr_memless_step_par_x1(x1);
|
||||||
|
x2 = sequence_gen_LTE_pr_memless_step_par_x2(x2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (; i < length; i++) {
|
||||||
|
out[i] = in[i] * (((x1 ^ x2) & 1U) ? -1 : +1);
|
||||||
|
|
||||||
|
// Step sequences
|
||||||
|
x1 = sequence_gen_LTE_pr_memless_step_x1(x1);
|
||||||
|
x2 = sequence_gen_LTE_pr_memless_step_x2(x2);
|
||||||
|
}
|
||||||
|
}
|
|
@ -35,10 +35,20 @@ static int16_t c_short[Nc + MAX_SEQ_LEN + 31];
|
||||||
static int8_t c_char[Nc + MAX_SEQ_LEN + 31];
|
static int8_t c_char[Nc + MAX_SEQ_LEN + 31];
|
||||||
static uint8_t c_packed[MAX_SEQ_LEN / 8];
|
static uint8_t c_packed[MAX_SEQ_LEN / 8];
|
||||||
|
|
||||||
|
static float ones_float[Nc + MAX_SEQ_LEN + 31];
|
||||||
|
static int16_t ones_short[Nc + MAX_SEQ_LEN + 31];
|
||||||
|
static int8_t ones_char[Nc + MAX_SEQ_LEN + 31];
|
||||||
|
static uint8_t ones_packed[MAX_SEQ_LEN / 8];
|
||||||
|
|
||||||
static int test_sequence(srslte_sequence_t* sequence, uint32_t seed, uint32_t length, uint32_t repetitions)
|
static int test_sequence(srslte_sequence_t* sequence, uint32_t seed, uint32_t length, uint32_t repetitions)
|
||||||
{
|
{
|
||||||
int ret = SRSLTE_SUCCESS;
|
int ret = SRSLTE_SUCCESS;
|
||||||
struct timeval t[3] = {};
|
struct timeval t[3] = {};
|
||||||
|
uint64_t interval_gen_us = 0;
|
||||||
|
uint64_t interval_xor_float_us = 0;
|
||||||
|
uint64_t interval_xor_short_us = 0;
|
||||||
|
uint64_t interval_xor_char_us = 0;
|
||||||
|
|
||||||
gettimeofday(&t[1], NULL);
|
gettimeofday(&t[1], NULL);
|
||||||
|
|
||||||
// Generate sequence
|
// Generate sequence
|
||||||
|
@ -48,6 +58,7 @@ static int test_sequence(srslte_sequence_t* sequence, uint32_t seed, uint32_t le
|
||||||
|
|
||||||
gettimeofday(&t[2], NULL);
|
gettimeofday(&t[2], NULL);
|
||||||
get_time_interval(t);
|
get_time_interval(t);
|
||||||
|
interval_gen_us = t->tv_sec * 1000000UL + t->tv_usec;
|
||||||
|
|
||||||
// Generate gold sequence
|
// Generate gold sequence
|
||||||
for (uint32_t n = 0; n < 31; n++) {
|
for (uint32_t n = 0; n < 31; n++) {
|
||||||
|
@ -70,35 +81,77 @@ static int test_sequence(srslte_sequence_t* sequence, uint32_t seed, uint32_t le
|
||||||
srslte_bit_pack_vector(c, c_packed, length);
|
srslte_bit_pack_vector(c, c_packed, length);
|
||||||
|
|
||||||
if (memcmp(c, sequence->c, length) != 0) {
|
if (memcmp(c, sequence->c, length) != 0) {
|
||||||
ERROR("Unmatched c\n");
|
ERROR("Unmatched c");
|
||||||
ret = SRSLTE_ERROR;
|
ret = SRSLTE_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check Float sequence
|
||||||
if (memcmp(c_float, sequence->c_float, length * sizeof(float)) != 0) {
|
if (memcmp(c_float, sequence->c_float, length * sizeof(float)) != 0) {
|
||||||
ERROR("Unmatched c_float\n");
|
ERROR("Unmatched c_float");
|
||||||
ret = SRSLTE_ERROR;
|
ret = SRSLTE_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Test in-place Float XOR
|
||||||
|
gettimeofday(&t[1], NULL);
|
||||||
|
for (uint32_t r = 0; r < repetitions; r++) {
|
||||||
|
srslte_sequence_apply_f(ones_float, sequence->c_float, length, seed);
|
||||||
|
}
|
||||||
|
gettimeofday(&t[2], NULL);
|
||||||
|
get_time_interval(t);
|
||||||
|
interval_xor_float_us = t->tv_sec * 1000000UL + t->tv_usec;
|
||||||
|
|
||||||
|
// Check Short Sequence
|
||||||
|
if (memcmp(c_short, sequence->c_short, length * sizeof(int16_t)) != 0) {
|
||||||
|
ERROR("Unmatched XOR c_short");
|
||||||
|
ret = SRSLTE_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test in-place Short XOR
|
||||||
|
gettimeofday(&t[1], NULL);
|
||||||
|
for (uint32_t r = 0; r < repetitions; r++) {
|
||||||
|
srslte_sequence_apply_s(ones_short, sequence->c_short, length, seed);
|
||||||
|
}
|
||||||
|
gettimeofday(&t[2], NULL);
|
||||||
|
get_time_interval(t);
|
||||||
|
interval_xor_short_us = t->tv_sec * 1000000UL + t->tv_usec;
|
||||||
|
|
||||||
if (memcmp(c_short, sequence->c_short, length * sizeof(int16_t)) != 0) {
|
if (memcmp(c_short, sequence->c_short, length * sizeof(int16_t)) != 0) {
|
||||||
ERROR("Unmatched c_short\n");
|
ERROR("Unmatched XOR c_short");
|
||||||
ret = SRSLTE_ERROR;
|
ret = SRSLTE_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check Char Sequence
|
||||||
if (memcmp(c_char, sequence->c_char, length * sizeof(int8_t)) != 0) {
|
if (memcmp(c_char, sequence->c_char, length * sizeof(int8_t)) != 0) {
|
||||||
ERROR("Unmatched c_char\n");
|
ERROR("Unmatched c_char");
|
||||||
|
ret = SRSLTE_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test in-place Char XOR
|
||||||
|
gettimeofday(&t[1], NULL);
|
||||||
|
for (uint32_t r = 0; r < repetitions; r++) {
|
||||||
|
srslte_sequence_apply_c(ones_char, sequence->c_char, length, seed);
|
||||||
|
}
|
||||||
|
gettimeofday(&t[2], NULL);
|
||||||
|
get_time_interval(t);
|
||||||
|
interval_xor_char_us = t->tv_sec * 1000000UL + t->tv_usec;
|
||||||
|
|
||||||
|
if (memcmp(c_char, sequence->c_char, length * sizeof(int8_t)) != 0) {
|
||||||
|
ERROR("Unmatched XOR c_char");
|
||||||
ret = SRSLTE_ERROR;
|
ret = SRSLTE_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (memcmp(c_packed, sequence->c_bytes, length / 8) != 0) {
|
if (memcmp(c_packed, sequence->c_bytes, length / 8) != 0) {
|
||||||
ERROR("Unmatched c_packed\n");
|
ERROR("Unmatched c_packed");
|
||||||
ret = SRSLTE_ERROR;
|
ret = SRSLTE_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t elapsed_us = t->tv_usec + t->tv_sec * 1000000UL;
|
printf("%08x; %8d; %8.1f; %8.1f; %8.1f; %8.1f; %8c\n",
|
||||||
printf("%08x; %8d; %8.1f; %8c\n",
|
|
||||||
seed,
|
seed,
|
||||||
length,
|
length,
|
||||||
(double)(length * repetitions) / (double)elapsed_us,
|
(double)(length * repetitions) / (double)interval_gen_us,
|
||||||
|
(double)(length * repetitions) / (double)interval_xor_float_us,
|
||||||
|
(double)(length * repetitions) / (double)interval_xor_short_us,
|
||||||
|
(double)(length * repetitions) / (double)interval_xor_char_us,
|
||||||
ret == SRSLTE_SUCCESS ? 'y' : 'n');
|
ret == SRSLTE_SUCCESS ? 'y' : 'n');
|
||||||
|
|
||||||
return SRSLTE_SUCCESS;
|
return SRSLTE_SUCCESS;
|
||||||
|
@ -113,10 +166,20 @@ int main(int argc, char** argv)
|
||||||
srslte_sequence_t sequence = {};
|
srslte_sequence_t sequence = {};
|
||||||
srslte_random_t random_gen = srslte_random_init(0);
|
srslte_random_t random_gen = srslte_random_init(0);
|
||||||
|
|
||||||
|
// Initialise vectors with ones
|
||||||
|
for (uint32_t i = 0; i < MAX_SEQ_LEN; i++) {
|
||||||
|
ones_float[i] = 1.0F;
|
||||||
|
ones_short[i] = 1;
|
||||||
|
ones_char[i] = 1;
|
||||||
|
if (i < MAX_SEQ_LEN / 8) {
|
||||||
|
ones_packed[i] = UINT8_MAX;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Initialise sequence object
|
// Initialise sequence object
|
||||||
srslte_sequence_init(&sequence, max_length);
|
srslte_sequence_init(&sequence, max_length);
|
||||||
|
|
||||||
printf("%8s; %8s; %8s; %8s\n", "seed", "length", "Rate M/s", "Passed");
|
printf("%8s; %8s; %8s; %8s; %8s; %8s; %8s\n", "seed", "length", "GEN", "XOR PS", "XOR 16", "XOR 8", "Passed");
|
||||||
|
|
||||||
for (uint32_t length = min_length; length <= max_length; length = (length * 5) / 4) {
|
for (uint32_t length = min_length; length <= max_length; length = (length * 5) / 4) {
|
||||||
test_sequence(&sequence, (uint32_t)srslte_random_uniform_int_dist(random_gen, 1, INT32_MAX), length, repetitions);
|
test_sequence(&sequence, (uint32_t)srslte_random_uniform_int_dist(random_gen, 1, INT32_MAX), length, repetitions);
|
||||||
|
|
Loading…
Reference in New Issue