Fix 5G NR FEC memcheck

This commit is contained in:
Xavier Arteaga 2020-11-04 12:33:51 +01:00 committed by Xavier Arteaga
parent 2835e87ff0
commit 0c2f96d389
15 changed files with 300 additions and 207 deletions

View File

@ -86,6 +86,17 @@ srslte_ldpc_encoder_init(srslte_ldpc_encoder_t* q, srslte_ldpc_encoder_type_t ty
*/
SRSLTE_API void srslte_ldpc_encoder_free(srslte_ldpc_encoder_t* q);
/*!
* Encodes a message into a codeword with the specified encoder.
* \param[in] q A pointer to the desired encoder.
* \param[in] input The message to encode.
* \param[out] output The resulting codeword.
* \param[in] input_length The number of uncoded bits in the input message.
* \return An integer: 0 if the function executes correctly, -1 otherwise.
*/
SRSLTE_API int
srslte_ldpc_encoder_encode(srslte_ldpc_encoder_t* q, const uint8_t* input, uint8_t* output, uint32_t input_length);
/*!
* Encodes a message into a codeword with the specified encoder.
* \param[in] q A pointer to the desired encoder.
@ -95,10 +106,10 @@ SRSLTE_API void srslte_ldpc_encoder_free(srslte_ldpc_encoder_t* q);
* \param[in] cdwd_rm_length The codeword length after rate matching.
* \return An integer: 0 if the function executes correctly, -1 otherwise.
*/
SRSLTE_API int srslte_ldpc_encoder_encode(srslte_ldpc_encoder_t* q,
const uint8_t* input,
uint8_t* output,
uint32_t input_length,
uint32_t cdwd_rm_length);
SRSLTE_API int srslte_ldpc_encoder_encode_rm(srslte_ldpc_encoder_t* q,
const uint8_t* input,
uint8_t* output,
uint32_t input_length,
uint32_t cdwd_rm_length);
#endif // SRSLTE_LDPCENCODER_H

View File

@ -18,20 +18,25 @@
# and at http://www.gnu.org/licenses/.
#
set(FEC_SOURCES ${FEC_SOURCES}
if (HAVE_AVX2)
set(AVX2_SOURCES
ldpc/ldpc_dec_c_avx2.c
ldpc/ldpc_dec_c_avx2long.c
ldpc/ldpc_dec_c_avx2_flood.c
ldpc/ldpc_dec_c_avx2long_flood.c
ldpc/ldpc_enc_avx2.c
ldpc/ldpc_enc_avx2long.c
)
endif (HAVE_AVX2)
set(FEC_SOURCES ${FEC_SOURCES} ${AVX2_SOURCES}
ldpc/base_graph.c
ldpc/ldpc_dec_f.c
ldpc/ldpc_dec_s.c
ldpc/ldpc_dec_c.c
ldpc/ldpc_dec_c_flood.c
ldpc/ldpc_dec_c_avx2.c
ldpc/ldpc_dec_c_avx2long.c
ldpc/ldpc_dec_c_avx2_flood.c
ldpc/ldpc_dec_c_avx2long_flood.c
ldpc/ldpc_decoder.c
ldpc/ldpc_enc_c.c
ldpc/ldpc_enc_avx2.c
ldpc/ldpc_enc_avx2long.c
ldpc/ldpc_encoder.c
ldpc/ldpc_rm.c
PARENT_SCOPE)

View File

@ -278,11 +278,11 @@ int update_ldpc_check_to_var_c_avx2(void* p,
__m256i this_abs_v2c_epi8;
__m256i minp_v2c_epi8 = _mm256_set1_epi8(INT8_MAX);
__m256i mins_v2c_epi8 = _mm256_set1_epi8(INT8_MAX);
__m256i prod_v2c_epi8 = _mm256_set1_epi8(0);
__m256i prod_v2c_epi8 = _mm256_setzero_si256();
__m256i mask_sign_epi8;
__m256i mask_min_epi8;
__m256i help_min_epi8;
__m256i min_ix_epi8;
__m256i min_ix_epi8 = _mm256_setzero_si256();
__m256i current_ix_epi8;
int8_t current_var_index = (*these_var_indices)[0];

View File

@ -293,11 +293,11 @@ int update_ldpc_check_to_var_c_avx2_flood(void* p,
__m256i this_abs_v2c_epi8;
__m256i minp_v2c_epi8 = _mm256_set1_epi8(INT8_MAX);
__m256i mins_v2c_epi8 = _mm256_set1_epi8(INT8_MAX);
__m256i prod_v2c_epi8 = _mm256_set1_epi8(0);
__m256i prod_v2c_epi8 = _mm256_setzero_si256();
__m256i mask_sign_epi8;
__m256i mask_min_epi8;
__m256i help_min_epi8;
__m256i min_ix_epi8;
__m256i min_ix_epi8 = _mm256_setzero_si256();
__m256i current_ix_epi8;
int8_t current_var_index = (*these_var_indices)[0];

View File

@ -380,11 +380,16 @@ void srslte_ldpc_encoder_free(srslte_ldpc_encoder_t* q)
bzero(q, sizeof(srslte_ldpc_encoder_t));
}
int srslte_ldpc_encoder_encode(srslte_ldpc_encoder_t* q,
const uint8_t* input,
uint8_t* output,
uint32_t input_length,
uint32_t cdwd_rm_length)
int srslte_ldpc_encoder_encode(srslte_ldpc_encoder_t* q, const uint8_t* input, uint8_t* output, uint32_t input_length)
{
return q->encode(q, input, output, input_length, q->liftN - 2 * q->ls);
}
int srslte_ldpc_encoder_encode_rm(srslte_ldpc_encoder_t* q,
const uint8_t* input,
uint8_t* output,
uint32_t input_length,
uint32_t cdwd_rm_length)
{
return q->encode(q, input, output, input_length, cdwd_rm_length);
}

View File

@ -190,4 +190,4 @@ set(test_name LDPC-RM-BG1)
set(test_command ldpc_rm_test)
ldpc_rm_unit_tests(${lifting_sizes})
add_test(NAME LDPC-RM-chain COMMAND ldpc_rm_chain_test)
add_test(NAME LDPC-RM-chain COMMAND ldpc_rm_chain_test -E 1 -B 1)

View File

@ -44,6 +44,9 @@
* - **-l \<number\>** Lifting Size (according to 5GNR standard. Default 2).
* - **-e \<number\>** Codeword length after rate matching (set to 0 [default] for full rate).
* - **-s \<number\>** SNR in dB (Default 3 dB).
* - **-B \<number\>** Number of codewords in a batch.(Default 100).
* - **-N \<number\>** Max number of simulated batches.(Default 10000).
* - **-E \<number\>** Minimum number of errors for a significant simulation.(Default 100).
*/
#include <math.h>
@ -60,29 +63,31 @@
#include "srslte/phy/utils/random.h"
#include "srslte/phy/utils/vector.h"
srslte_basegraph_t base_graph = BG1; /*!< \brief Base Graph (BG1 or BG2). */
int lift_size = 2; /*!< \brief Lifting Size. */
int rm_length = 0; /*!< \brief Codeword length after rate matching. */
int finalK; /*!< \brief Number of uncoded bits (message length). */
int finalN; /*!< \brief Number of coded bits (codeword length). */
float snr = 0; /*!< \brief Signal-to-Noise Ratio [dB]. */
static srslte_basegraph_t base_graph = BG1; /*!< \brief Base Graph (BG1 or BG2). */
static int lift_size = 2; /*!< \brief Lifting Size. */
static int rm_length = 0; /*!< \brief Codeword length after rate matching. */
static int finalK; /*!< \brief Number of uncoded bits (message length). */
static int finalN; /*!< \brief Number of coded bits (codeword length). */
static float snr = 0; /*!< \brief Signal-to-Noise Ratio [dB]. */
#define BATCH_SIZE 100 /*!< \brief Number of codewords in a batch. */
#define MAX_N_BATCH 10000 /*!< \brief Max number of simulated batches. */
#define REQ_ERRORS 100 /*!< \brief Minimum number of errors for a significant simulation. */
#define MS_SF 0.75f /*!< \brief Scaling factor for the normalized min-sum decoding algorithm. */
static int batch_size = 100; /*!< \brief Number of codewords in a batch. */
static int max_n_batch = 10000; /*!< \brief Max number of simulated batches. */
static int req_errors = 100; /*!< \brief Minimum number of errors for a significant simulation. */
#define MS_SF 0.75f /*!< \brief Scaling factor for the normalized min-sum decoding algorithm. */
/*!
* \brief Prints test help when wrong parameter is passed as input.
*/
void usage(char* prog)
{
printf("Usage: %s [-bX] [-lX] [-eX] [-sX]\n", prog);
printf("Usage: %s [-bX] [-lX] [-eX] [-sX] [-BX]\n", prog);
printf("\t-b Base Graph [(1 or 2) Default %d]\n", base_graph + 1);
printf("\t-l Lifting Size [Default %d]\n", lift_size);
printf("\t-e Word length after rate matching [Default %d (no rate matching, only filler-bits are extracted)]\n",
rm_length);
printf("\t-s SNR [dB, Default %.1f dB]\n", snr);
printf("\t-B Number of codewords in a batch. [Default %d]\n", batch_size);
printf("\t-N Max number of simulated batches. [Default %d]\n", max_n_batch);
printf("\t-E Minimum number of errors for a significant simulation. [Default %d]\n", req_errors);
}
/*!
@ -91,7 +96,7 @@ void usage(char* prog)
void parse_args(int argc, char** argv)
{
int opt = 0;
while ((opt = getopt(argc, argv, "b:l:e:s:")) != -1) {
while ((opt = getopt(argc, argv, "b:l:e:s:B:N:E:")) != -1) {
switch (opt) {
case 'b':
base_graph = (int)strtol(optarg, NULL, 10) - 1;
@ -103,7 +108,16 @@ void parse_args(int argc, char** argv)
rm_length = (int)strtol(optarg, NULL, 10);
break;
case 's':
snr = strtod(optarg, NULL);
snr = (float)strtod(optarg, NULL);
break;
case 'B':
batch_size = (int)strtol(optarg, NULL, 10);
break;
case 'N':
max_n_batch = (int)strtol(optarg, NULL, 10);
break;
case 'E':
req_errors = (int)strtol(optarg, NULL, 10);
break;
default:
usage(argv[0]);
@ -224,18 +238,18 @@ int main(int argc, char** argv)
finalK = encoder.liftK;
finalN = encoder.liftN - 2 * lift_size;
messages_true = malloc(finalK * BATCH_SIZE * sizeof(uint8_t));
messages_sim_f = malloc(finalK * BATCH_SIZE * sizeof(uint8_t));
messages_sim_s = malloc(finalK * BATCH_SIZE * sizeof(uint8_t));
messages_sim_c = malloc(finalK * BATCH_SIZE * sizeof(uint8_t));
messages_sim_c_flood = malloc(finalK * BATCH_SIZE * sizeof(uint8_t));
messages_sim_avx = malloc(finalK * BATCH_SIZE * sizeof(uint8_t));
messages_sim_avx_flood = malloc(finalK * BATCH_SIZE * sizeof(uint8_t));
codewords = malloc(finalN * BATCH_SIZE * sizeof(uint8_t));
symbols_rm = malloc((rm_length + F) * BATCH_SIZE * sizeof(float));
symbols = malloc(finalN * BATCH_SIZE * sizeof(float));
symbols_s = malloc(finalN * BATCH_SIZE * sizeof(int16_t));
symbols_c = malloc(finalN * BATCH_SIZE * sizeof(int8_t));
messages_true = malloc(finalK * batch_size * sizeof(uint8_t));
messages_sim_f = malloc(finalK * batch_size * sizeof(uint8_t));
messages_sim_s = malloc(finalK * batch_size * sizeof(uint8_t));
messages_sim_c = malloc(finalK * batch_size * sizeof(uint8_t));
messages_sim_c_flood = malloc(finalK * batch_size * sizeof(uint8_t));
messages_sim_avx = malloc(finalK * batch_size * sizeof(uint8_t));
messages_sim_avx_flood = malloc(finalK * batch_size * sizeof(uint8_t));
codewords = malloc(finalN * batch_size * sizeof(uint8_t));
symbols_rm = malloc((rm_length + F) * batch_size * sizeof(float));
symbols = malloc(finalN * batch_size * sizeof(float));
symbols_s = malloc(finalN * batch_size * sizeof(int16_t));
symbols_c = malloc(finalN * batch_size * sizeof(int8_t));
if (!messages_true || !messages_sim_f || !messages_sim_s || !messages_sim_c || //
!messages_sim_avx || !messages_sim_c_flood || !messages_sim_avx_flood || //
!codewords || !symbols || !symbols_s || !symbols_c) {
@ -273,8 +287,8 @@ int main(int argc, char** argv)
printf("\nBatch:\n ");
while (((n_error_words_f < REQ_ERRORS) || (n_error_words_s < REQ_ERRORS) || (n_error_words_c < REQ_ERRORS)) &&
(i_batch < MAX_N_BATCH)) {
while (((n_error_words_f < req_errors) || (n_error_words_s < req_errors) || (n_error_words_c < req_errors)) &&
(i_batch < max_n_batch)) {
i_batch++;
if (!(i_batch % 10)) {
@ -286,7 +300,7 @@ int main(int argc, char** argv)
/* generate data_tx */
for (i = 0; i < BATCH_SIZE; i++) {
for (i = 0; i < batch_size; i++) {
for (j = 0; j < finalK - F; j++) {
messages_true[i * finalK + j] = srslte_random_uniform_int_dist(random_gen, 0, 1);
}
@ -305,8 +319,8 @@ int main(int argc, char** argv)
// Encode messages
gettimeofday(&t[1], NULL);
for (j = 0; j < BATCH_SIZE; j++) {
srslte_ldpc_encoder_encode(
for (j = 0; j < batch_size; j++) {
srslte_ldpc_encoder_encode_rm(
&encoder, messages_true + j * finalK, codewords + j * finalN, finalK, n_useful_symbols);
}
gettimeofday(&t[2], NULL);
@ -314,7 +328,7 @@ int main(int argc, char** argv)
elapsed_time_enc += t[0].tv_sec + 1e-6 * t[0].tv_usec;
// Modulate codewords and match rate (puncturing)
for (i = 0; i < BATCH_SIZE; i++) {
for (i = 0; i < batch_size; i++) {
for (j = 0; j < rm_length + F; j++) {
symbols_rm[i * (rm_length + F) + j] =
(codewords[i * finalN + j] == FILLER_BIT) ? INFINITY : 1 - 2 * codewords[i * finalN + j];
@ -322,11 +336,11 @@ int main(int argc, char** argv)
}
// Apply AWGN
srslte_ch_awgn_f(symbols_rm, symbols_rm, noise_std_dev, BATCH_SIZE * (rm_length + F));
srslte_ch_awgn_f(symbols_rm, symbols_rm, noise_std_dev, batch_size * (rm_length + F));
// Convert symbols into LLRs
for (i = 0; i < BATCH_SIZE; i++) {
for (j = 0; j < rm_length + F; j++) { //+F becouse we have alredy considered fillerbits when modulating.
for (i = 0; i < batch_size; i++) {
for (j = 0; j < rm_length + F; j++) { //+F because we have already considered fillerbits when modulating.
symbols[i * finalN + j] = symbols_rm[i * (rm_length + F) + j] * 2 / (noise_std_dev * noise_std_dev);
}
// the rest of symbols are undetermined, set LLR to 0
@ -338,14 +352,14 @@ int main(int argc, char** argv)
//////// Floating point
// Recover messages
gettimeofday(&t[1], NULL);
for (j = 0; j < BATCH_SIZE; j++) {
for (j = 0; j < batch_size; j++) {
srslte_ldpc_decoder_decode_f(&decoder_f, symbols + j * finalN, messages_sim_f + j * finalK, n_useful_symbols);
}
gettimeofday(&t[2], NULL);
get_time_interval(t);
elapsed_time_dec_f += t[0].tv_sec + 1e-6 * t[0].tv_usec;
for (i = 0; i < BATCH_SIZE; i++) {
for (i = 0; i < batch_size; i++) {
for (j = 0; j < finalK; j++) {
i_bit = i * finalK + j;
if (messages_sim_f[i_bit] != (1U & messages_true[i_bit])) {
@ -357,18 +371,18 @@ int main(int argc, char** argv)
//////// Fixed point - 16 bit
// Quantize LLRs with 16 bits
srslte_vec_quant_fs(symbols, symbols_s, gain_s, 0, inf15, BATCH_SIZE * finalN);
srslte_vec_quant_fs(symbols, symbols_s, gain_s, 0, inf15, batch_size * finalN);
// Recover messages
gettimeofday(&t[1], NULL);
for (j = 0; j < BATCH_SIZE; j++) {
for (j = 0; j < batch_size; j++) {
srslte_ldpc_decoder_decode_s(&decoder_s, symbols_s + j * finalN, messages_sim_s + j * finalK, n_useful_symbols);
}
gettimeofday(&t[2], NULL);
get_time_interval(t);
elapsed_time_dec_s += t[0].tv_sec + 1e-6 * t[0].tv_usec;
for (i = 0; i < BATCH_SIZE; i++) {
for (i = 0; i < batch_size; i++) {
for (j = 0; j < finalK; j++) {
i_bit = i * finalK + j;
if (messages_sim_s[i_bit] != (1U & messages_true[i_bit])) {
@ -380,18 +394,18 @@ int main(int argc, char** argv)
//////// Fixed point - 8 bit
// Quantize LLRs with 8 bits
srslte_vec_quant_fc(symbols, symbols_c, gain_c, 0, inf7, BATCH_SIZE * finalN);
srslte_vec_quant_fc(symbols, symbols_c, gain_c, 0, inf7, batch_size * finalN);
// Recover messages
gettimeofday(&t[1], NULL);
for (j = 0; j < BATCH_SIZE; j++) {
for (j = 0; j < batch_size; j++) {
srslte_ldpc_decoder_decode_c(&decoder_c, symbols_c + j * finalN, messages_sim_c + j * finalK, n_useful_symbols);
}
gettimeofday(&t[2], NULL);
get_time_interval(t);
elapsed_time_dec_c += t[0].tv_sec + 1e-6 * t[0].tv_usec;
for (i = 0; i < BATCH_SIZE; i++) {
for (i = 0; i < batch_size; i++) {
for (j = 0; j < finalK; j++) {
i_bit = i * finalK + j;
if (messages_sim_c[i_bit] != (1U & messages_true[i_bit])) {
@ -405,7 +419,7 @@ int main(int argc, char** argv)
// Recover messages
gettimeofday(&t[1], NULL);
for (j = 0; j < BATCH_SIZE; j++) {
for (j = 0; j < batch_size; j++) {
srslte_ldpc_decoder_decode_c(
&decoder_c_flood, symbols_c + j * finalN, messages_sim_c_flood + j * finalK, n_useful_symbols);
}
@ -413,7 +427,7 @@ int main(int argc, char** argv)
get_time_interval(t);
elapsed_time_dec_c_flood += t[0].tv_sec + 1e-6 * t[0].tv_usec;
for (i = 0; i < BATCH_SIZE; i++) {
for (i = 0; i < batch_size; i++) {
for (j = 0; j < finalK; j++) {
i_bit = i * finalK + j;
if (messages_sim_c_flood[i_bit] != (1U & messages_true[i_bit])) {
@ -428,7 +442,7 @@ int main(int argc, char** argv)
// Recover messages
gettimeofday(&t[1], NULL);
for (j = 0; j < BATCH_SIZE; j++) {
for (j = 0; j < batch_size; j++) {
srslte_ldpc_decoder_decode_c(
&decoder_avx, symbols_c + j * finalN, messages_sim_avx + j * finalK, n_useful_symbols);
}
@ -436,7 +450,7 @@ int main(int argc, char** argv)
get_time_interval(t);
elapsed_time_dec_avx += t[0].tv_sec + 1e-6 * t[0].tv_usec;
for (i = 0; i < BATCH_SIZE; i++) {
for (i = 0; i < batch_size; i++) {
for (j = 0; j < finalK; j++) {
i_bit = i * finalK + j;
if (messages_sim_avx[i_bit] != (1U & messages_true[i_bit])) {
@ -450,7 +464,7 @@ int main(int argc, char** argv)
// Recover messages
gettimeofday(&t[1], NULL);
for (j = 0; j < BATCH_SIZE; j++) {
for (j = 0; j < batch_size; j++) {
srslte_ldpc_decoder_decode_c(
&decoder_avx_flood, symbols_c + j * finalN, messages_sim_avx_flood + j * finalK, n_useful_symbols);
}
@ -458,7 +472,7 @@ int main(int argc, char** argv)
get_time_interval(t);
elapsed_time_dec_avx_flood += t[0].tv_sec + 1e-6 * t[0].tv_usec;
for (i = 0; i < BATCH_SIZE; i++) {
for (i = 0; i < batch_size; i++) {
for (j = 0; j < finalK; j++) {
i_bit = i * finalK + j;
if (messages_sim_avx_flood[i_bit] != (1U & messages_true[i_bit])) {
@ -471,9 +485,9 @@ int main(int argc, char** argv)
}
printf("\nEstimated throughput encoder:\n %e word/s\n %e bit/s (information)\n %e bit/s (encoded)\n",
i_batch * BATCH_SIZE / elapsed_time_enc,
i_batch * BATCH_SIZE * finalK / elapsed_time_enc,
i_batch * BATCH_SIZE * finalN / elapsed_time_enc);
i_batch * batch_size / elapsed_time_enc,
i_batch * batch_size * finalK / elapsed_time_enc,
i_batch * batch_size * finalN / elapsed_time_enc);
print_decoder("FLOATING POINT", i_batch, n_error_words_f, elapsed_time_dec_f);
print_decoder("FIXED POINT (16 bits)", i_batch, n_error_words_s, elapsed_time_dec_s);
@ -500,7 +514,9 @@ int main(int argc, char** argv)
free(symbols_s);
free(symbols);
free(codewords);
free(symbols_rm);
free(messages_sim_avx);
free(messages_sim_avx_flood);
free(messages_sim_c_flood);
free(messages_sim_c);
free(messages_sim_s);
@ -509,6 +525,7 @@ int main(int argc, char** argv)
srslte_random_free(random_gen);
#ifdef LV_HAVE_AVX2
srslte_ldpc_decoder_free(&decoder_avx);
srslte_ldpc_decoder_free(&decoder_avx_flood);
#endif // LV_HAVE_AVX2
srslte_ldpc_decoder_free(&decoder_c_flood);
srslte_ldpc_decoder_free(&decoder_c);
@ -520,10 +537,10 @@ int main(int argc, char** argv)
void print_decoder(char* title, int n_batches, int n_errors, double elapsed_time)
{
printf("\n**** %s ****", title);
printf("\nEstimated word error rate:\n %e (%d errors)\n", (double)n_errors / n_batches / BATCH_SIZE, n_errors);
printf("\nEstimated word error rate:\n %e (%d errors)\n", (double)n_errors / n_batches / batch_size, n_errors);
printf("Estimated throughput decoder:\n %e word/s\n %e bit/s (information)\n %e bit/s (encoded)\n",
n_batches * BATCH_SIZE / elapsed_time,
n_batches * BATCH_SIZE * finalK / elapsed_time,
n_batches * BATCH_SIZE * finalN / elapsed_time);
n_batches * batch_size / elapsed_time,
n_batches * batch_size * finalK / elapsed_time,
n_batches * batch_size * finalN / elapsed_time);
}

View File

@ -32,6 +32,7 @@
* Options:
* - **-b \<number\>** Base Graph (1 or 2. Default 1).
* - **-l \<number\>** Lifting Size (according to 5GNR standard. Default 2).
* - **-R \<number\>** Number of times tests are repeated (for computing throughput).
*/
#include <stdio.h>
@ -48,8 +49,8 @@ int lift_size = 2; /*!< \brief Lifting Size. */
int finalK; /*!< \brief Number of uncoded bits (message length). */
int finalN; /*!< \brief Number of coded bits (codeword length). */
#define NOF_MESSAGES 10 /*!< \brief Number of codewords in the test. */
#define NOF_REPS 1000 /*!< \brief Number of times tests are repeated (for computing throughput). */
#define NOF_MESSAGES 10 /*!< \brief Number of codewords in the test. */
static int nof_reps = 1; /*!< \brief Number of times tests are repeated (for computing throughput). */
/*!
* \brief Prints test help when a wrong parameter is passed as input.
@ -59,6 +60,7 @@ void usage(char* prog)
printf("Usage: %s [-bX] [-lX]\n", prog);
printf("\t-b Base Graph [(1 or 2) Default %d]\n", base_graph + 1);
printf("\t-l Lifting Size [Default %d]\n", lift_size);
printf("\t-R Number of times tests are repeated (for computing throughput). [Default %d]\n", lift_size);
}
/*!
@ -67,7 +69,7 @@ void usage(char* prog)
void parse_args(int argc, char** argv)
{
int opt = 0;
while ((opt = getopt(argc, argv, "b:l:")) != -1) {
while ((opt = getopt(argc, argv, "b:l:R:")) != -1) {
switch (opt) {
case 'b':
base_graph = (int)strtol(optarg, NULL, 10) - 1;
@ -75,6 +77,9 @@ void parse_args(int argc, char** argv)
case 'l':
lift_size = (int)strtol(optarg, NULL, 10);
break;
case 'R':
nof_reps = (int)strtol(optarg, NULL, 10);
break;
default:
usage(argv[0]);
exit(-1);
@ -195,14 +200,14 @@ int main(int argc, char** argv)
for (j = 0; j < NOF_MESSAGES; j++) {
printf(" codeword %d\n", j);
gettimeofday(&t[1], NULL);
for (l = 0; l < NOF_REPS; l++) {
srslte_ldpc_encoder_encode(&encoder, messages + j * finalK, codewords_sim + j * finalN, finalK, finalN);
for (l = 0; l < nof_reps; l++) {
srslte_ldpc_encoder_encode_rm(&encoder, messages + j * finalK, codewords_sim + j * finalN, finalK, finalN);
}
gettimeofday(&t[2], NULL);
get_time_interval(t);
elapsed_time += t[0].tv_sec + 1e-6 * t[0].tv_usec;
}
printf("Elapsed time: %e s\n", elapsed_time / NOF_REPS);
printf("Elapsed time: %e s\n", elapsed_time / nof_reps);
printf("\nVerifing results...\n");
for (i = 0; i < NOF_MESSAGES * finalN; i++) {
@ -213,9 +218,9 @@ int main(int argc, char** argv)
}
printf("Estimated throughput:\n %e word/s\n %e bit/s (information)\n %e bit/s (encoded)\n",
NOF_MESSAGES / (elapsed_time / NOF_REPS),
NOF_MESSAGES * finalK / (elapsed_time / NOF_REPS),
NOF_MESSAGES * finalN / (elapsed_time / NOF_REPS));
NOF_MESSAGES / (elapsed_time / nof_reps),
NOF_MESSAGES * finalK / (elapsed_time / nof_reps),
NOF_MESSAGES * finalN / (elapsed_time / nof_reps));
printf("\nTest completed successfully!\n\n");

View File

@ -32,6 +32,7 @@
* Options:
* - **-b \<number\>** Base Graph (1 or 2. Default 1).
* - **-l \<number\>** Lifting Size (according to 5GNR standard. Default 2).
* - **-R \<number\>** Number of times tests are repeated (for computing throughput).
*/
#include <stdio.h>
@ -43,13 +44,13 @@
#include "srslte/phy/fec/ldpc/ldpc_encoder.h"
#include "srslte/phy/utils/debug.h"
srslte_basegraph_t base_graph = BG1; /*!< \brief Base Graph (BG1 or BG2). */
int lift_size = 2; /*!< \brief Lifting Size. */
int finalK; /*!< \brief Number of uncoded bits (message length). */
int finalN; /*!< \brief Number of coded bits (codeword length). */
static srslte_basegraph_t base_graph = BG1; /*!< \brief Base Graph (BG1 or BG2). */
static int lift_size = 2; /*!< \brief Lifting Size. */
static int finalK; /*!< \brief Number of uncoded bits (message length). */
static int finalN; /*!< \brief Number of coded bits (codeword length). */
#define NOF_MESSAGES 10 /*!< \brief Number of codewords in the test. */
#define NOF_REPS 1000 /*!< \brief Number of times tests are repeated (for computing throughput). */
#define NOF_MESSAGES 10 /*!< \brief Number of codewords in the test. */
static int nof_reps = 1; /*!< \brief Number of times tests are repeated (for computing throughput). */
/*!
* \brief Prints test help when a wrong parameter is passed as input.
@ -59,6 +60,7 @@ void usage(char* prog)
printf("Usage: %s [-bX] [-lX]\n", prog);
printf("\t-b Base Graph [(1 or 2) Default %d]\n", base_graph + 1);
printf("\t-l Lifting Size [Default %d]\n", lift_size);
printf("\t-R Number of times tests are repeated (for computing throughput). [Default %d]\n", lift_size);
}
/*!
@ -67,7 +69,7 @@ void usage(char* prog)
void parse_args(int argc, char** argv)
{
int opt = 0;
while ((opt = getopt(argc, argv, "b:l:")) != -1) {
while ((opt = getopt(argc, argv, "b:l:R:")) != -1) {
switch (opt) {
case 'b':
base_graph = (int)strtol(optarg, NULL, 10) - 1;
@ -75,6 +77,9 @@ void parse_args(int argc, char** argv)
case 'l':
lift_size = (int)strtol(optarg, NULL, 10);
break;
case 'R':
nof_reps = (int)strtol(optarg, NULL, 10);
break;
default:
usage(argv[0]);
exit(-1);
@ -195,14 +200,14 @@ int main(int argc, char** argv)
for (j = 0; j < NOF_MESSAGES; j++) {
printf(" codeword %d\n", j);
gettimeofday(&t[1], NULL);
for (l = 0; l < NOF_REPS; l++) {
srslte_ldpc_encoder_encode(&encoder, messages + j * finalK, codewords_sim + j * finalN, finalK, finalN);
for (l = 0; l < nof_reps; l++) {
srslte_ldpc_encoder_encode_rm(&encoder, messages + j * finalK, codewords_sim + j * finalN, finalK, finalN);
}
gettimeofday(&t[2], NULL);
get_time_interval(t);
elapsed_time += t[0].tv_sec + 1e-6 * t[0].tv_usec;
}
printf("Elapsed time: %e s\n", elapsed_time / NOF_REPS);
printf("Elapsed time: %e s\n", elapsed_time / nof_reps);
printf("\nVerifing results...\n");
for (i = 0; i < NOF_MESSAGES * finalN; i++) {
@ -213,9 +218,9 @@ int main(int argc, char** argv)
}
printf("Estimated throughput:\n %e word/s\n %e bit/s (information)\n %e bit/s (encoded)\n",
NOF_MESSAGES / (elapsed_time / NOF_REPS),
NOF_MESSAGES * finalK / (elapsed_time / NOF_REPS),
NOF_MESSAGES * finalN / (elapsed_time / NOF_REPS));
NOF_MESSAGES / (elapsed_time / nof_reps),
NOF_MESSAGES * finalK / (elapsed_time / nof_reps),
NOF_MESSAGES * finalN / (elapsed_time / nof_reps));
printf("\nTest completed successfully!\n\n");

View File

@ -41,9 +41,11 @@
* - **-m \<number\>** Modulation type BPSK = 0, QPSK =1, QAM16 = 2, QAM64 = 3, QAM256 = 4.
* - **-M \<number\>** Limited buffer size.
* - **-s \<number\>** SNR in dB(Default 3 dB).
* - **-B \<number\>** Number of codewords in a batch.(Default 100).
* - **-N \<number\>** Max number of simulated batches.(Default 10000).
* - **-E \<number\>** Minimum number of errors for a significant simulation.(Default 100).
*/
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@ -58,23 +60,22 @@
#include "srslte/phy/utils/random.h"
#include "srslte/phy/utils/vector.h"
srslte_basegraph_t base_graph = BG1; /*!< \brief Base Graph (BG1 or BG2). */
uint32_t lift_size = 2; /*!< \brief Lifting Size. */
uint32_t rm_length = 0; /*!< \brief Codeword length after rate matching. */
uint32_t F = 22 - 5; /*!< \brief Number of filler bits in each CBS. */
uint32_t E = 14000; /*!< \brief Rate-matched Codeword size. */
uint8_t rv = 0; /*!< \brief Redundancy version {0-3}. */
mod_type_t mod_type = BPSK; /*!< \brief Modulation type: BPSK, QPSK, QAM16, QAM64, QAM256 = 4 */
uint32_t Nref = 0; /*!< \brief Limited buffer size. */
float snr = 0; /*!< \brief Signal-to-Noise Ratio [dB]. */
static srslte_basegraph_t base_graph = BG1; /*!< \brief Base Graph (BG1 or BG2). */
static uint32_t lift_size = 2; /*!< \brief Lifting Size. */
static uint32_t rm_length = 0; /*!< \brief Codeword length after rate matching. */
static uint32_t F = 22 - 5; /*!< \brief Number of filler bits in each CBS. */
static uint8_t rv = 0; /*!< \brief Redundancy version {0-3}. */
static mod_type_t mod_type = BPSK; /*!< \brief Modulation type: BPSK, QPSK, QAM16, QAM64, QAM256 = 4 */
static uint32_t Nref = 0; /*!< \brief Limited buffer size. */
static float snr = 0; /*!< \brief Signal-to-Noise Ratio [dB]. */
int finalK = 0; /*!< \brief Number of uncoded bits (message length, including punctured and filler bits). */
int finalN = 0; /*!< \brief Number of coded bits (codeword length). */
static int finalK = 0; /*!< \brief Number of uncoded bits (message length, including punctured and filler bits). */
static int finalN = 0; /*!< \brief Number of coded bits (codeword length). */
#define BATCH_SIZE 100 /*!< \brief Number of codewords in a batch. */
#define MAX_N_BATCH 10000 /*!< \brief Max number of simulated batches. */
#define REQ_ERRORS 100 /*!< \brief Minimum number of errors for a significant simulation. */
#define MS_SF 0.75f /*!< \brief Scaling factor for the normalized min-sum decoding algorithm. */
static int batch_size = 100; /*!< \brief Number of codewords in a batch. */
static int max_n_batch = 10000; /*!< \brief Max number of simulated batches. */
static int req_errors = 100; /*!< \brief Minimum number of errors for a significant simulation. */
#define MS_SF 0.75f /*!< \brief Scaling factor for the normalized min-sum decoding algorithm. */
/*!
* \brief Prints test help when wrong parameter is passed as input.
@ -91,6 +92,9 @@ void usage(char* prog)
printf("\t-m Modulation_type BPSK=0, QPSK=1, 16QAM=2, 64QAM=3, 256QAM = 4 [Default %d]\n", mod_type);
printf("\t-M Limited buffer size (Nref) [Default = %d (normal buffer Nref = N)]\n", Nref);
printf("\t-s SNR [dB, Default %.1f dB]\n", snr);
printf("\t-B Number of codewords in a batch. [Default %d]\n", batch_size);
printf("\t-N Max number of simulated batches. [Default %d]\n", max_n_batch);
printf("\t-E Minimum number of errors for a significant simulation. [Default %d]\n", req_errors);
}
/*!
@ -99,7 +103,7 @@ void usage(char* prog)
void parse_args(int argc, char** argv)
{
int opt = 0;
while ((opt = getopt(argc, argv, "b:l:e:f:r:m:M:s:")) != -1) {
while ((opt = getopt(argc, argv, "b:l:e:f:r:m:M:s:B:N:E:")) != -1) {
switch (opt) {
case 'b':
base_graph = (int)strtol(optarg, NULL, 10) - 1;
@ -123,7 +127,16 @@ void parse_args(int argc, char** argv)
Nref = (uint32_t)strtol(optarg, NULL, 10);
break;
case 's':
snr = strtod(optarg, NULL);
snr = (float)strtod(optarg, NULL);
break;
case 'B':
batch_size = (int)strtol(optarg, NULL, 10);
break;
case 'N':
max_n_batch = (int)strtol(optarg, NULL, 10);
break;
case 'E':
req_errors = (int)strtol(optarg, NULL, 10);
break;
default:
usage(argv[0]);
@ -282,22 +295,22 @@ int main(int argc, char** argv)
1.0 * (encoder.liftK - F) / rm_length);
printf("\n Signal-to-Noise Ratio -> %.2f dB\n", snr);
messages_true = malloc(finalK * BATCH_SIZE * sizeof(uint8_t));
messages_sim_f = malloc(finalK * BATCH_SIZE * sizeof(uint8_t));
messages_sim_s = malloc(finalK * BATCH_SIZE * sizeof(uint8_t));
messages_sim_c = malloc(finalK * BATCH_SIZE * sizeof(uint8_t));
messages_sim_c_flood = malloc(finalK * BATCH_SIZE * sizeof(uint8_t));
messages_sim_avx = malloc(finalK * BATCH_SIZE * sizeof(uint8_t));
messages_sim_avx_flood = malloc(finalK * BATCH_SIZE * sizeof(uint8_t));
codewords = malloc(finalN * BATCH_SIZE * sizeof(uint8_t));
rm_codewords = malloc(rm_length * BATCH_SIZE * sizeof(uint8_t));
rm_symbols = malloc(rm_length * BATCH_SIZE * sizeof(float));
rm_symbols_s = malloc(rm_length * BATCH_SIZE * sizeof(uint16_t));
rm_symbols_c = malloc(rm_length * BATCH_SIZE * sizeof(uint8_t));
messages_true = malloc(finalK * batch_size * sizeof(uint8_t));
messages_sim_f = malloc(finalK * batch_size * sizeof(uint8_t));
messages_sim_s = malloc(finalK * batch_size * sizeof(uint8_t));
messages_sim_c = malloc(finalK * batch_size * sizeof(uint8_t));
messages_sim_c_flood = malloc(finalK * batch_size * sizeof(uint8_t));
messages_sim_avx = malloc(finalK * batch_size * sizeof(uint8_t));
messages_sim_avx_flood = malloc(finalK * batch_size * sizeof(uint8_t));
codewords = malloc(finalN * batch_size * sizeof(uint8_t));
rm_codewords = malloc(rm_length * batch_size * sizeof(uint8_t));
rm_symbols = malloc(rm_length * batch_size * sizeof(float));
rm_symbols_s = malloc(rm_length * batch_size * sizeof(uint16_t));
rm_symbols_c = malloc(rm_length * batch_size * sizeof(uint8_t));
symbols = malloc(finalN * BATCH_SIZE * sizeof(float));
symbols_s = malloc(finalN * BATCH_SIZE * sizeof(int16_t));
symbols_c = malloc(finalN * BATCH_SIZE * sizeof(int8_t));
symbols = malloc(finalN * batch_size * sizeof(float));
symbols_s = malloc(finalN * batch_size * sizeof(int16_t));
symbols_c = malloc(finalN * batch_size * sizeof(int8_t));
if (!messages_true || !messages_sim_f || !messages_sim_s || !messages_sim_c || //
!messages_sim_avx || !messages_sim_c_flood || !messages_sim_avx_flood || //
!codewords || !rm_codewords || !rm_symbols || !rm_symbols_s || !rm_symbols_c || !symbols || !symbols_s ||
@ -336,8 +349,8 @@ int main(int argc, char** argv)
printf("\nBatch:\n ");
while (((n_error_words_f < REQ_ERRORS) || (n_error_words_s < REQ_ERRORS) || (n_error_words_c < REQ_ERRORS)) &&
(i_batch < MAX_N_BATCH)) {
while (((n_error_words_f < req_errors) || (n_error_words_s < req_errors) || (n_error_words_c < req_errors)) &&
(i_batch < max_n_batch)) {
i_batch++;
if (!(i_batch % 10)) {
@ -348,7 +361,7 @@ int main(int argc, char** argv)
}
/* generate data_tx */
for (i = 0; i < BATCH_SIZE; i++) {
for (i = 0; i < batch_size; i++) {
for (j = 0; j < finalK - F; j++) {
messages_true[i * finalK + j] = srslte_random_uniform_int_dist(random_gen, 0, 1);
}
@ -357,21 +370,16 @@ int main(int argc, char** argv)
}
}
// lDPC Encoding
// compute the number of symbols that we need to encode/decode: at least (E + F) if E+F < N,
unsigned int n_useful_symbols = (E + F);
gettimeofday(&t[1], NULL);
for (j = 0; j < BATCH_SIZE; j++) {
srslte_ldpc_encoder_encode(
&encoder, messages_true + j * finalK, codewords + j * finalN, finalK, n_useful_symbols);
for (j = 0; j < batch_size; j++) {
srslte_ldpc_encoder_encode(&encoder, messages_true + j * finalK, codewords + j * finalN, finalK);
}
gettimeofday(&t[2], NULL);
get_time_interval(t);
elapsed_time_enc += t[0].tv_sec + 1e-6 * t[0].tv_usec;
// rate matching
for (j = 0; j < BATCH_SIZE; j++) {
for (j = 0; j < batch_size; j++) {
srslte_ldpc_rm_tx(&rm_tx,
codewords + j * finalN,
rm_codewords + j * rm_length,
@ -383,23 +391,23 @@ int main(int argc, char** argv)
Nref);
}
for (i = 0; i < BATCH_SIZE; i++) {
for (i = 0; i < batch_size; i++) {
for (j = 0; j < rm_length; j++) {
rm_symbols[i * rm_length + j] = 1 - 2 * rm_codewords[i * rm_length + j];
}
}
// Apply AWGN
srslte_ch_awgn_f(rm_symbols, rm_symbols, noise_std_dev, BATCH_SIZE * rm_length);
srslte_ch_awgn_f(rm_symbols, rm_symbols, noise_std_dev, batch_size * rm_length);
// Convert symbols into LLRs
for (i = 0; i < BATCH_SIZE; i++) {
for (i = 0; i < batch_size; i++) {
for (j = 0; j < rm_length; j++) {
rm_symbols[i * rm_length + j] = rm_symbols[i * rm_length + j] * 2 / (noise_std_dev * noise_std_dev);
}
}
for (i = 0; i < BATCH_SIZE; i++) {
for (i = 0; i < batch_size; i++) {
if (srslte_ldpc_rm_rx_f(&rm_rx,
rm_symbols + i * rm_length,
symbols + i * finalN,
@ -417,14 +425,14 @@ int main(int argc, char** argv)
//////// Floating point
// Recover messages
gettimeofday(&t[1], NULL);
for (j = 0; j < BATCH_SIZE; j++) {
srslte_ldpc_decoder_decode_f(&decoder_f, symbols + j * finalN, messages_sim_f + j * finalK, n_useful_symbols);
for (j = 0; j < batch_size; j++) {
srslte_ldpc_decoder_decode_f(&decoder_f, symbols + j * finalN, messages_sim_f + j * finalK, finalN);
}
gettimeofday(&t[2], NULL);
get_time_interval(t);
elapsed_time_dec_f += t[0].tv_sec + 1e-6 * t[0].tv_usec;
for (i = 0; i < BATCH_SIZE; i++) {
for (i = 0; i < batch_size; i++) {
for (j = 0; j < finalK; j++) {
i_bit = i * finalK + j;
if (messages_sim_f[i_bit] != (1U & messages_true[i_bit])) {
@ -437,10 +445,10 @@ int main(int argc, char** argv)
//////// Fixed point - 16 bit
// Quantize LLRs with 16 bits
srslte_vec_quant_fs(rm_symbols, rm_symbols_s, gain_s, 0, inf15, BATCH_SIZE * rm_length);
srslte_vec_quant_fs(rm_symbols, rm_symbols_s, gain_s, 0, inf15, batch_size * rm_length);
// Rate dematcher
for (i = 0; i < BATCH_SIZE; i++) {
for (i = 0; i < batch_size; i++) {
if (srslte_ldpc_rm_rx_s(&rm_rx_s,
rm_symbols_s + i * rm_length,
symbols_s + i * finalN,
@ -457,14 +465,14 @@ int main(int argc, char** argv)
// Recover messages
gettimeofday(&t[1], NULL);
for (j = 0; j < BATCH_SIZE; j++) {
srslte_ldpc_decoder_decode_s(&decoder_s, symbols_s + j * finalN, messages_sim_s + j * finalK, n_useful_symbols);
for (j = 0; j < batch_size; j++) {
srslte_ldpc_decoder_decode_s(&decoder_s, symbols_s + j * finalN, messages_sim_s + j * finalK, finalN);
}
gettimeofday(&t[2], NULL);
get_time_interval(t);
elapsed_time_dec_s += t[0].tv_sec + 1e-6 * t[0].tv_usec;
for (i = 0; i < BATCH_SIZE; i++) {
for (i = 0; i < batch_size; i++) {
for (j = 0; j < finalK; j++) {
i_bit = i * finalK + j;
if (messages_sim_s[i_bit] != (1U & messages_true[i_bit])) {
@ -476,10 +484,10 @@ int main(int argc, char** argv)
//////// Fixed point - 8 bit
// Quantize LLRs with 8 bits
srslte_vec_quant_fc(rm_symbols, rm_symbols_c, gain_c, 0, inf7, BATCH_SIZE * rm_length);
srslte_vec_quant_fc(rm_symbols, rm_symbols_c, gain_c, 0, inf7, batch_size * rm_length);
// Rate dematcher
for (i = 0; i < BATCH_SIZE; i++) {
for (i = 0; i < batch_size; i++) {
if (srslte_ldpc_rm_rx_c(&rm_rx_c,
rm_symbols_c + i * rm_length,
symbols_c + i * finalN,
@ -496,14 +504,14 @@ int main(int argc, char** argv)
// Recover messages
gettimeofday(&t[1], NULL);
for (j = 0; j < BATCH_SIZE; j++) {
srslte_ldpc_decoder_decode_c(&decoder_c, symbols_c + j * finalN, messages_sim_c + j * finalK, n_useful_symbols);
for (j = 0; j < batch_size; j++) {
srslte_ldpc_decoder_decode_c(&decoder_c, symbols_c + j * finalN, messages_sim_c + j * finalK, finalN);
}
gettimeofday(&t[2], NULL);
get_time_interval(t);
elapsed_time_dec_c += t[0].tv_sec + 1e-6 * t[0].tv_usec;
for (i = 0; i < BATCH_SIZE; i++) {
for (i = 0; i < batch_size; i++) {
for (j = 0; j < finalK; j++) {
i_bit = i * finalK + j;
if (messages_sim_c[i_bit] != (1U & messages_true[i_bit])) {
@ -517,15 +525,14 @@ int main(int argc, char** argv)
// Recover messages
gettimeofday(&t[1], NULL);
for (j = 0; j < BATCH_SIZE; j++) {
srslte_ldpc_decoder_decode_c(
&decoder_c_flood, symbols_c + j * finalN, messages_sim_c_flood + j * finalK, n_useful_symbols);
for (j = 0; j < batch_size; j++) {
srslte_ldpc_decoder_decode_c(&decoder_c_flood, symbols_c + j * finalN, messages_sim_c_flood + j * finalK, finalN);
}
gettimeofday(&t[2], NULL);
get_time_interval(t);
elapsed_time_dec_c_flood += t[0].tv_sec + 1e-6 * t[0].tv_usec;
for (i = 0; i < BATCH_SIZE; i++) {
for (i = 0; i < batch_size; i++) {
for (j = 0; j < finalK; j++) {
i_bit = i * finalK + j;
if (messages_sim_c_flood[i_bit] != (1U & messages_true[i_bit])) {
@ -540,15 +547,14 @@ int main(int argc, char** argv)
// Recover messages
gettimeofday(&t[1], NULL);
for (j = 0; j < BATCH_SIZE; j++) {
srslte_ldpc_decoder_decode_c(
&decoder_avx, symbols_c + j * finalN, messages_sim_avx + j * finalK, n_useful_symbols);
for (j = 0; j < batch_size; j++) {
srslte_ldpc_decoder_decode_c(&decoder_avx, symbols_c + j * finalN, messages_sim_avx + j * finalK, finalN);
}
gettimeofday(&t[2], NULL);
get_time_interval(t);
elapsed_time_dec_avx += t[0].tv_sec + 1e-6 * t[0].tv_usec;
for (i = 0; i < BATCH_SIZE; i++) {
for (i = 0; i < batch_size; i++) {
for (j = 0; j < finalK; j++) {
i_bit = i * finalK + j;
if (messages_sim_avx[i_bit] != (1U & messages_true[i_bit])) {
@ -562,15 +568,15 @@ int main(int argc, char** argv)
// Recover messages
gettimeofday(&t[1], NULL);
for (j = 0; j < BATCH_SIZE; j++) {
for (j = 0; j < batch_size; j++) {
srslte_ldpc_decoder_decode_c(
&decoder_avx_flood, symbols_c + j * finalN, messages_sim_avx_flood + j * finalK, n_useful_symbols);
&decoder_avx_flood, symbols_c + j * finalN, messages_sim_avx_flood + j * finalK, finalN);
}
gettimeofday(&t[2], NULL);
get_time_interval(t);
elapsed_time_dec_avx_flood += t[0].tv_sec + 1e-6 * t[0].tv_usec;
for (i = 0; i < BATCH_SIZE; i++) {
for (i = 0; i < batch_size; i++) {
for (j = 0; j < finalK; j++) {
i_bit = i * finalK + j;
if (messages_sim_avx_flood[i_bit] != (1U & messages_true[i_bit])) {
@ -583,9 +589,9 @@ int main(int argc, char** argv)
}
printf("\nEstimated throughput encoder:\n %e word/s\n %e bit/s (information)\n %e bit/s (encoded)\n",
i_batch * BATCH_SIZE / elapsed_time_enc,
i_batch * BATCH_SIZE * finalK / elapsed_time_enc,
i_batch * BATCH_SIZE * finalN / elapsed_time_enc);
i_batch * batch_size / elapsed_time_enc,
i_batch * batch_size * finalK / elapsed_time_enc,
i_batch * batch_size * finalN / elapsed_time_enc);
print_decoder("FLOATING POINT", i_batch, n_error_words_f, elapsed_time_dec_f);
print_decoder("FIXED POINT (16 bits)", i_batch, n_error_words_s, elapsed_time_dec_s);
@ -617,6 +623,7 @@ int main(int argc, char** argv)
free(rm_codewords);
free(codewords);
free(messages_sim_avx);
free(messages_sim_avx_flood);
free(messages_sim_c_flood);
free(messages_sim_c);
free(messages_sim_s);
@ -625,6 +632,7 @@ int main(int argc, char** argv)
srslte_random_free(random_gen);
#ifdef LV_HAVE_AVX2
srslte_ldpc_decoder_free(&decoder_avx);
srslte_ldpc_decoder_free(&decoder_avx_flood);
#endif // LV_HAVE_AVX2
srslte_ldpc_decoder_free(&decoder_c_flood);
srslte_ldpc_decoder_free(&decoder_c);
@ -640,10 +648,10 @@ int main(int argc, char** argv)
void print_decoder(char* title, int n_batches, int n_errors, double elapsed_time)
{
printf("\n**** %s ****", title);
printf("\nEstimated word error rate:\n %e (%d errors)\n", (double)n_errors / n_batches / BATCH_SIZE, n_errors);
printf("\nEstimated word error rate:\n %e (%d errors)\n", (double)n_errors / n_batches / batch_size, n_errors);
printf("Estimated throughput decoder:\n %e word/s\n %e bit/s (information)\n %e bit/s (encoded)\n",
n_batches * BATCH_SIZE / elapsed_time,
n_batches * BATCH_SIZE * finalK / elapsed_time,
n_batches * BATCH_SIZE * finalN / elapsed_time);
n_batches * batch_size / elapsed_time,
n_batches * batch_size * finalK / elapsed_time,
n_batches * batch_size * finalN / elapsed_time);
}

View File

@ -51,18 +51,19 @@
#include "srslte/phy/fec/ldpc/ldpc_rm.h"
#include "srslte/phy/utils/debug.h"
#include "srslte/phy/utils/random.h"
#include "srslte/phy/utils/vector.h"
srslte_basegraph_t base_graph = BG2; /*!< \brief Base Graph (BG1 or BG2). */
uint32_t lift_size = 208; /*!< \brief Lifting Size. */
uint32_t C = 2; /*!< \brief Number of code block segments (CBS). */
uint32_t F = 10; /*!< \brief Number of filler bits in each CBS. */
uint32_t E = 0; /*!< \brief Rate-matched codeword size (E = 0, no rate matching). */
uint8_t rv = 0; /*!< \brief Redundancy version {0-3}. */
mod_type_t mod_type = QPSK; /*!< \brief Modulation type: BPSK, QPSK, QAM16, QAM64, QAM256. */
uint32_t Nref = 0; /*!< \brief Limited buffer size.*/
static srslte_basegraph_t base_graph = BG2; /*!< \brief Base Graph (BG1 or BG2). */
static uint32_t lift_size = 208; /*!< \brief Lifting Size. */
static uint32_t C = 2; /*!< \brief Number of code block segments (CBS). */
static uint32_t F = 10; /*!< \brief Number of filler bits in each CBS. */
static uint32_t E = 0; /*!< \brief Rate-matched codeword size (E = 0, no rate matching). */
static uint8_t rv = 0; /*!< \brief Redundancy version {0-3}. */
static mod_type_t mod_type = QPSK; /*!< \brief Modulation type: BPSK, QPSK, QAM16, QAM64, QAM256. */
static uint32_t Nref = 0; /*!< \brief Limited buffer size.*/
uint32_t N = 0; /*!< \brief Codeblock size (including punctured and filler bits). */
uint32_t K = 0; /*!< \brief Codeword size. */
static uint32_t N = 0; /*!< \brief Codeblock size (including punctured and filler bits). */
static uint32_t K = 0; /*!< \brief Codeword size. */
/*!
* \brief Prints test help when a wrong parameter is passed as input.
@ -218,7 +219,6 @@ int main(int argc, char** argv)
// Generate random bits
for (r = 0; r < C; r++) {
for (i = 0; i < K - F; i++) {
// codeblock_seg[i] = rand() % 2;
codeblocks[r * K + i] = srslte_random_uniform_int_dist(random_gen, 0, 1);
}
for (; i < K; i++) { // add filler bits
@ -226,14 +226,10 @@ int main(int argc, char** argv)
}
}
// lDPC Encoding
// compute the number of symbols that we need to encode/decode: at least (E + F) if E+F < N,
unsigned int n_useful_symbols = (E + F);
// Encode messages
// gettimeofday(&t[1], NULL);
for (r = 0; r < C; r++) {
if (srslte_ldpc_encoder_encode(&encoder, codeblocks + r * K, codewords + r * N, K, n_useful_symbols)) {
if (srslte_ldpc_encoder_encode(&encoder, codeblocks + r * K, codewords + r * N, K)) {
exit(-1);
}

View File

@ -1,21 +1,40 @@
#
# Project: 5GCoding-SRS
# Author: Jesus Gomez (CTTC)
# Copyright: Software Radio Systems Limited
# Copyright 2013-2020 Software Radio Systems Limited
#
# This file is part of srsLTE
#
# srsLTE is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of
# the License, or (at your option) any later version.
#
# srsLTE is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# A copy of the GNU Affero General Public License can be found in
# the LICENSE file in the top-level directory of this distribution
# and at http://www.gnu.org/licenses/.
#
set(FEC_SOURCES ${FEC_SOURCES}
if (HAVE_AVX2)
set(AVX2_SOURCES
polar/polar_encoder_avx2.c
polar/polar_decoder_ssc_c_avx2.c
polar/polar_decoder_vector_avx2.c
)
endif (HAVE_AVX2)
set(FEC_SOURCES ${FEC_SOURCES} ${AVX2_SOURCES}
polar/polar_encoder.c
polar/polar_encoder_pipelined.c
polar/polar_encoder_avx2.c
polar/polar_decoder.c
polar/polar_decoder_ssc_all.c
polar/polar_decoder_ssc_f.c
polar/polar_decoder_ssc_s.c
polar/polar_decoder_ssc_c.c
polar/polar_decoder_ssc_c_avx2.c
polar/polar_decoder_vector.c
polar/polar_decoder_vector_avx2.c
PARENT_SCOPE)
add_subdirectory(test)

View File

@ -35,6 +35,7 @@
#include "../utils_avx2.h"
#include "polar_decoder_vector_avx2.h"
#include "srslte/phy/fec/polar/polar_encoder.h"
#include "srslte/phy/utils/vector.h"
#ifdef LV_HAVE_AVX2
@ -148,7 +149,8 @@ void* create_polar_decoder_ssc_c_avx2(uint16_t* frozen_set, const uint8_t code_s
return NULL;
}
if ((pp->param->code_stage_size = malloc((code_size_log + 1) * sizeof(uint16_t))) == NULL) {
printf("-- code_stage_size=%d;\n", code_size_log + 1);
if ((pp->param->code_stage_size = srslte_vec_u16_malloc(code_size_log + 1)) == NULL) {
free(pp->param);
free(pp->enc);
free(pp);
@ -315,7 +317,10 @@ static void simplified_node(struct pSSC_c_avx2* p)
uint8_t* estbits1 = NULL;
uint16_t stage_size = pp->param->code_stage_size[stage];
uint16_t stage_half_size = pp->param->code_stage_size[stage - 1];
uint16_t stage_half_size = 0;
if (stage > 0) {
stage_half_size = pp->param->code_stage_size[stage - 1];
}
switch (pp->param->node_type[stage][bit_pos]) {

View File

@ -1,7 +1,21 @@
#
# Project: 5GCoding-SRS
# Author: Jesus Gomez (CTTC)
# Copyright: Software Radio Systems Limited
# Copyright 2013-2020 Software Radio Systems Limited
#
# This file is part of srsLTE
#
# srsLTE is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of
# the License, or (at your option) any later version.
#
# srsLTE is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# A copy of the GNU Affero General Public License can be found in
# the LICENSE file in the top-level directory of this distribution
# and at http://www.gnu.org/licenses/.
#
add_library(polar_test_utils polar_sets.c subchannel_allocation.c)

View File

@ -714,6 +714,7 @@ int main(int argc, char** argv)
free(data_rx);
free(data_rx_s);
free(data_rx_c);
free(data_rx_c_avx2);
free(input_enc);
free(output_enc);
@ -722,10 +723,12 @@ int main(int argc, char** argv)
free(llr);
free(llr_s);
free(llr_c);
free(llr_c_avx2);
free(output_dec);
free(output_dec_s);
free(output_dec_c);
free(output_dec_c_avx2);
#ifdef DATA_ALL_ONES
#else