From 0c2f96d3891d454e471798b3932c990bc9bf4951 Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Wed, 4 Nov 2020 12:33:51 +0100 Subject: [PATCH] Fix 5G NR FEC memcheck --- .../srslte/phy/fec/ldpc/ldpc_encoder.h | 21 ++- lib/src/phy/fec/ldpc/CMakeLists.txt | 19 +- lib/src/phy/fec/ldpc/ldpc_dec_c_avx2.c | 4 +- lib/src/phy/fec/ldpc/ldpc_dec_c_avx2_flood.c | 4 +- lib/src/phy/fec/ldpc/ldpc_encoder.c | 15 +- lib/src/phy/fec/ldpc/test/CMakeLists.txt | 2 +- lib/src/phy/fec/ldpc/test/ldpc_chain_test.c | 129 ++++++++------ .../phy/fec/ldpc/test/ldpc_enc_avx2_test.c | 23 ++- lib/src/phy/fec/ldpc/test/ldpc_enc_test.c | 31 ++-- .../phy/fec/ldpc/test/ldpc_rm_chain_test.c | 168 +++++++++--------- lib/src/phy/fec/ldpc/test/ldpc_rm_test.c | 28 ++- lib/src/phy/fec/polar/CMakeLists.txt | 33 +++- .../phy/fec/polar/polar_decoder_ssc_c_avx2.c | 9 +- lib/src/phy/fec/polar/test/CMakeLists.txt | 20 ++- lib/src/phy/fec/polar/test/polar_chain_test.c | 3 + 15 files changed, 301 insertions(+), 208 deletions(-) diff --git a/lib/include/srslte/phy/fec/ldpc/ldpc_encoder.h b/lib/include/srslte/phy/fec/ldpc/ldpc_encoder.h index 3e19e536d..55e1a361c 100644 --- a/lib/include/srslte/phy/fec/ldpc/ldpc_encoder.h +++ b/lib/include/srslte/phy/fec/ldpc/ldpc_encoder.h @@ -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 diff --git a/lib/src/phy/fec/ldpc/CMakeLists.txt b/lib/src/phy/fec/ldpc/CMakeLists.txt index 69713ce4b..b818ee1e8 100644 --- a/lib/src/phy/fec/ldpc/CMakeLists.txt +++ b/lib/src/phy/fec/ldpc/CMakeLists.txt @@ -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) diff --git a/lib/src/phy/fec/ldpc/ldpc_dec_c_avx2.c b/lib/src/phy/fec/ldpc/ldpc_dec_c_avx2.c index 1eb3da2da..4a433ea4e 100644 --- a/lib/src/phy/fec/ldpc/ldpc_dec_c_avx2.c +++ b/lib/src/phy/fec/ldpc/ldpc_dec_c_avx2.c @@ -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]; diff --git a/lib/src/phy/fec/ldpc/ldpc_dec_c_avx2_flood.c b/lib/src/phy/fec/ldpc/ldpc_dec_c_avx2_flood.c index 06f6afdbe..7282d8517 100644 --- a/lib/src/phy/fec/ldpc/ldpc_dec_c_avx2_flood.c +++ b/lib/src/phy/fec/ldpc/ldpc_dec_c_avx2_flood.c @@ -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]; diff --git a/lib/src/phy/fec/ldpc/ldpc_encoder.c b/lib/src/phy/fec/ldpc/ldpc_encoder.c index 04ae14741..6bfbccc75 100644 --- a/lib/src/phy/fec/ldpc/ldpc_encoder.c +++ b/lib/src/phy/fec/ldpc/ldpc_encoder.c @@ -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); } diff --git a/lib/src/phy/fec/ldpc/test/CMakeLists.txt b/lib/src/phy/fec/ldpc/test/CMakeLists.txt index 630ff51e4..11d151ea9 100644 --- a/lib/src/phy/fec/ldpc/test/CMakeLists.txt +++ b/lib/src/phy/fec/ldpc/test/CMakeLists.txt @@ -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) \ No newline at end of file +add_test(NAME LDPC-RM-chain COMMAND ldpc_rm_chain_test -E 1 -B 1) \ No newline at end of file diff --git a/lib/src/phy/fec/ldpc/test/ldpc_chain_test.c b/lib/src/phy/fec/ldpc/test/ldpc_chain_test.c index 3d1746dbf..579f71005 100644 --- a/lib/src/phy/fec/ldpc/test/ldpc_chain_test.c +++ b/lib/src/phy/fec/ldpc/test/ldpc_chain_test.c @@ -44,6 +44,9 @@ * - **-l \** Lifting Size (according to 5GNR standard. Default 2). * - **-e \** Codeword length after rate matching (set to 0 [default] for full rate). * - **-s \** SNR in dB (Default 3 dB). + * - **-B \** Number of codewords in a batch.(Default 100). + * - **-N \** Max number of simulated batches.(Default 10000). + * - **-E \** Minimum number of errors for a significant simulation.(Default 100). */ #include @@ -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); } diff --git a/lib/src/phy/fec/ldpc/test/ldpc_enc_avx2_test.c b/lib/src/phy/fec/ldpc/test/ldpc_enc_avx2_test.c index e407ad688..72eb5ec65 100644 --- a/lib/src/phy/fec/ldpc/test/ldpc_enc_avx2_test.c +++ b/lib/src/phy/fec/ldpc/test/ldpc_enc_avx2_test.c @@ -32,6 +32,7 @@ * Options: * - **-b \** Base Graph (1 or 2. Default 1). * - **-l \** Lifting Size (according to 5GNR standard. Default 2). + * - **-R \** Number of times tests are repeated (for computing throughput). */ #include @@ -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"); diff --git a/lib/src/phy/fec/ldpc/test/ldpc_enc_test.c b/lib/src/phy/fec/ldpc/test/ldpc_enc_test.c index a10f7ad11..0bd7803cb 100644 --- a/lib/src/phy/fec/ldpc/test/ldpc_enc_test.c +++ b/lib/src/phy/fec/ldpc/test/ldpc_enc_test.c @@ -32,6 +32,7 @@ * Options: * - **-b \** Base Graph (1 or 2. Default 1). * - **-l \** Lifting Size (according to 5GNR standard. Default 2). + * - **-R \** Number of times tests are repeated (for computing throughput). */ #include @@ -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"); diff --git a/lib/src/phy/fec/ldpc/test/ldpc_rm_chain_test.c b/lib/src/phy/fec/ldpc/test/ldpc_rm_chain_test.c index 7aa65ec04..b2fea5bd4 100644 --- a/lib/src/phy/fec/ldpc/test/ldpc_rm_chain_test.c +++ b/lib/src/phy/fec/ldpc/test/ldpc_rm_chain_test.c @@ -41,9 +41,11 @@ * - **-m \** Modulation type BPSK = 0, QPSK =1, QAM16 = 2, QAM64 = 3, QAM256 = 4. * - **-M \** Limited buffer size. * - **-s \** SNR in dB(Default 3 dB). + * - **-B \** Number of codewords in a batch.(Default 100). + * - **-N \** Max number of simulated batches.(Default 10000). + * - **-E \** Minimum number of errors for a significant simulation.(Default 100). */ -#include #include #include #include @@ -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)); - - 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)); + 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)); 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); } diff --git a/lib/src/phy/fec/ldpc/test/ldpc_rm_test.c b/lib/src/phy/fec/ldpc/test/ldpc_rm_test.c index b441764a2..4cf734d47 100644 --- a/lib/src/phy/fec/ldpc/test/ldpc_rm_test.c +++ b/lib/src/phy/fec/ldpc/test/ldpc_rm_test.c @@ -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); } diff --git a/lib/src/phy/fec/polar/CMakeLists.txt b/lib/src/phy/fec/polar/CMakeLists.txt index 68461fa23..01171d5dd 100644 --- a/lib/src/phy/fec/polar/CMakeLists.txt +++ b/lib/src/phy/fec/polar/CMakeLists.txt @@ -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/. +# + +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} +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) diff --git a/lib/src/phy/fec/polar/polar_decoder_ssc_c_avx2.c b/lib/src/phy/fec/polar/polar_decoder_ssc_c_avx2.c index 7f6bba2cc..b760f661d 100644 --- a/lib/src/phy/fec/polar/polar_decoder_ssc_c_avx2.c +++ b/lib/src/phy/fec/polar/polar_decoder_ssc_c_avx2.c @@ -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]) { diff --git a/lib/src/phy/fec/polar/test/CMakeLists.txt b/lib/src/phy/fec/polar/test/CMakeLists.txt index dd10b2688..6cf213a54 100644 --- a/lib/src/phy/fec/polar/test/CMakeLists.txt +++ b/lib/src/phy/fec/polar/test/CMakeLists.txt @@ -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) diff --git a/lib/src/phy/fec/polar/test/polar_chain_test.c b/lib/src/phy/fec/polar/test/polar_chain_test.c index 5b5a2f990..655c9e67b 100644 --- a/lib/src/phy/fec/polar/test/polar_chain_test.c +++ b/lib/src/phy/fec/polar/test/polar_chain_test.c @@ -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