From 5aa7f9dd8b907fe9297776aa956f0edc3c82d4a3 Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Wed, 14 Apr 2021 13:47:18 +0200 Subject: [PATCH] Condensed LDPC Decoder config arguments into an structure and unified common decoder code --- .../srsran/phy/fec/ldpc/ldpc_decoder.h | 55 +- lib/include/srsran/phy/phch/sch_nr.h | 7 +- lib/src/phy/fec/ldpc/ldpc_decoder.c | 651 ++++-------------- lib/src/phy/fec/ldpc/test/ldpc_chain_test.c | 34 +- .../phy/fec/ldpc/test/ldpc_dec_avx2_test.c | 9 +- .../phy/fec/ldpc/test/ldpc_dec_avx512_test.c | 9 +- lib/src/phy/fec/ldpc/test/ldpc_dec_c_test.c | 9 +- lib/src/phy/fec/ldpc/test/ldpc_dec_s_test.c | 9 +- lib/src/phy/fec/ldpc/test/ldpc_dec_test.c | 9 +- .../phy/fec/ldpc/test/ldpc_rm_chain_test.c | 34 +- lib/src/phy/phch/sch_nr.c | 19 +- 11 files changed, 264 insertions(+), 581 deletions(-) diff --git a/lib/include/srsran/phy/fec/ldpc/ldpc_decoder.h b/lib/include/srsran/phy/fec/ldpc/ldpc_decoder.h index 0539168bc..3ae49164a 100644 --- a/lib/include/srsran/phy/fec/ldpc/ldpc_decoder.h +++ b/lib/include/srsran/phy/fec/ldpc/ldpc_decoder.h @@ -23,13 +23,14 @@ #ifndef SRSRAN_LDPCDECODER_H #define SRSRAN_LDPCDECODER_H +#include "srsran/phy/fec/crc.h" #include "srsran/phy/fec/ldpc/base_graph.h" /*! * \brief Types of LDPC decoder. */ typedef enum { - SRSRAN_LDPC_DECODER_F, /*!< \brief %Decoder working with real-valued LLRs. */ + SRSRAN_LDPC_DECODER_F = 0, /*!< \brief %Decoder working with real-valued LLRs. */ SRSRAN_LDPC_DECODER_S, /*!< \brief %Decoder working with 16-bit integer-valued LLRs. */ SRSRAN_LDPC_DECODER_C, /*!< \brief %Decoder working with 8-bit integer-valued LLRs. */ SRSRAN_LDPC_DECODER_C_FLOOD, /*!< \brief %Decoder working with 8-bit integer-valued LLRs, flooded scheduling. */ @@ -41,20 +42,32 @@ typedef enum { (AVX512 version). */ } srsran_ldpc_decoder_type_t; +/*! + * \brief Describes the LDPC decoder configuration arguments. + */ +typedef struct { + srsran_ldpc_decoder_type_t type; /*!< \brief Type of LDPC decoder. */ + srsran_basegraph_t bg; /*!< \brief The desired base graph (BG1 or BG2). */ + uint16_t ls; /*!< \brief The desired lifting size. */ + float scaling_fctr; /*!< \brief Scaling factor of the normalized min-sum algorithm.*/ + uint32_t max_nof_iter; /*!< \brief Maximum number of iterations, set to 0 for default value. */ +} srsran_ldpc_decoder_args_t; + /*! * \brief Describes an LDPC decoder. */ typedef struct SRSRAN_API { - void* ptr; /*!< \brief Registers used by the decoder. */ - srsran_basegraph_t bg; /*!< \brief Current base graph. */ - uint16_t ls; /*!< \brief Current lifting size. */ - uint8_t bgN; /*!< \brief Number of variable nodes in the BG. */ - uint16_t liftN; /*!< \brief Number of variable nodes in the lifted graph. */ - uint8_t bgM; /*!< \brief Number of check nodes in the BG. */ - uint16_t liftM; /*!< \brief Number of check nodes in the lifted graph. */ - uint8_t bgK; /*!< \brief Number of "uncoded bits" in the BG. */ - uint16_t liftK; /*!< \brief Number of uncoded bits in the lifted graph. */ - uint16_t* pcm; /*!< \brief Pointer to the parity check matrix (compact form). */ + void* ptr; /*!< \brief Registers used by the decoder. */ + srsran_basegraph_t bg; /*!< \brief Current base graph. */ + uint16_t ls; /*!< \brief Current lifting size. */ + uint32_t max_nof_iter; /*!< \brief Maximum number of iterations. */ + uint8_t bgN; /*!< \brief Number of variable nodes in the BG. */ + uint16_t liftN; /*!< \brief Number of variable nodes in the lifted graph. */ + uint8_t bgM; /*!< \brief Number of check nodes in the BG. */ + uint16_t liftM; /*!< \brief Number of check nodes in the lifted graph. */ + uint8_t bgK; /*!< \brief Number of "uncoded bits" in the BG. */ + uint16_t liftK; /*!< \brief Number of uncoded bits in the lifted graph. */ + uint16_t* pcm; /*!< \brief Pointer to the parity check matrix (compact form). */ int8_t (*var_indices)[MAX_CNCT]; /*!< \brief Pointer to lists of variable indices connected to a given check node. */ @@ -65,32 +78,28 @@ typedef struct SRSRAN_API { int (*decode_f)(void*, const float*, uint8_t*, - uint32_t); /*!< \brief Pointer to the decoding function (float version). */ + uint32_t, + srsran_crc_t*); /*!< \brief Pointer to the decoding function (float version). */ int (*decode_s)(void*, const int16_t*, uint8_t*, - uint32_t); /*!< \brief Pointer to the decoding function (16-bit version). */ + uint32_t, + srsran_crc_t*); /*!< \brief Pointer to the decoding function (16-bit version). */ int (*decode_c)(void*, const int8_t*, uint8_t*, - uint32_t); /*!< \brief Pointer to the decoding function (16-bit version). */ + uint32_t, + srsran_crc_t*); /*!< \brief Pointer to the decoding function (16-bit version). */ } srsran_ldpc_decoder_t; /*! * Initializes all the LDPC decoder variables according to the given base graph * and lifting size. * \param[out] q A pointer to a srsran_ldpc_decoder_t structure. - * \param[in] type Type of LDPC decoder. - * \param[in] bg The desired base graph (BG1 or BG2). - * \param[in] ls The desired lifting size. - * \param[in] scaling_fctr Scaling factor of the normalized min-sum algorithm. + * \param[in] args LDPC configuration arguments. * \return An integer: 0 if the function executes correctly, -1 otherwise. */ -SRSRAN_API int srsran_ldpc_decoder_init(srsran_ldpc_decoder_t* q, - srsran_ldpc_decoder_type_t type, - srsran_basegraph_t bg, - uint16_t ls, - float scaling_fctr); +SRSRAN_API int srsran_ldpc_decoder_init(srsran_ldpc_decoder_t* q, const srsran_ldpc_decoder_args_t* args); /*! * The LDPC decoder "destructor": it frees all the resources allocated to the decoder. diff --git a/lib/include/srsran/phy/phch/sch_nr.h b/lib/include/srsran/phy/phch/sch_nr.h index 3a730c10c..d3eaa4bf9 100644 --- a/lib/include/srsran/phy/phch/sch_nr.h +++ b/lib/include/srsran/phy/phch/sch_nr.h @@ -60,9 +60,10 @@ typedef struct SRSRAN_API { * @brief SCH encoder and decoder initialization arguments */ typedef struct SRSRAN_API { - bool disable_simd; - bool decoder_use_flooded; - float decoder_scaling_factor; + bool disable_simd; + bool decoder_use_flooded; + float decoder_scaling_factor; + uint32_t max_nof_iter; ///< Maximum number of LDPC iterations } srsran_sch_nr_args_t; /** diff --git a/lib/src/phy/fec/ldpc/ldpc_decoder.c b/lib/src/phy/fec/ldpc/ldpc_decoder.c index e71601652..11a52dbc1 100644 --- a/lib/src/phy/fec/ldpc/ldpc_decoder.c +++ b/lib/src/phy/fec/ldpc/ldpc_decoder.c @@ -30,7 +30,106 @@ #include "srsran/phy/utils/debug.h" #include "srsran/phy/utils/vector.h" -#define MAX_ITERATIONS 10 /*!< \brief Iterations of the BP algorithm. */ +#define LDPC_DECODER_DEFAULT_MAX_NOF_ITER 10 /*!< \brief Default maximum number of iterations of the BP algorithm. */ + +#define LDPC_DECODER_TEMPLATE(LLR_TYPE, SUFFIX) \ + static int decode_##SUFFIX( \ + void* o, const LLR_TYPE* llrs, uint8_t* message, uint32_t cdwd_rm_length, srsran_crc_t* crc) \ + { \ + srsran_ldpc_decoder_t* q = o; \ + \ + /* it must be smaller than the codeword size */ \ + if (cdwd_rm_length > q->liftN - 2 * q->ls) { \ + cdwd_rm_length = q->liftN - 2 * q->ls; \ + } \ + /* We need at least q->bgK + 4 variable nodes to cover the high-rate region. However,*/ \ + /* 2 variable nodes are systematically punctured by the encoder. */ \ + if (cdwd_rm_length < (q->bgK + 2) * q->ls) { \ + /* ERROR("The rate-matched codeword should have a length at least equal to the high-rate region.");*/ \ + cdwd_rm_length = (q->bgK + 2) * q->ls; \ + /* return -1;*/ \ + } \ + if (cdwd_rm_length % q->ls) { \ + cdwd_rm_length = (cdwd_rm_length / q->ls + 1) * q->ls; \ + /* ERROR("The rate-matched codeword length should be a multiple of the lifting size."); */ \ + /* return -1;*/ \ + } \ + init_ldpc_dec_##SUFFIX(q->ptr, llrs, q->ls); \ + \ + uint16_t* this_pcm = NULL; \ + int8_t(*these_var_indices)[MAX_CNCT] = NULL; \ + \ + /* When computing the number of layers, we need to recall that the standard always removes */ \ + /* the first two variable nodes from the final codeword.*/ \ + uint8_t n_layers = cdwd_rm_length / q->ls - q->bgK + 2; \ + \ + for (int i_iteration = 0; i_iteration < q->max_nof_iter; i_iteration++) { \ + for (int i_layer = 0; i_layer < n_layers; i_layer++) { \ + update_ldpc_var_to_check_##SUFFIX(q->ptr, i_layer); \ + \ + this_pcm = q->pcm + i_layer * q->bgN; \ + these_var_indices = q->var_indices + i_layer; \ + \ + update_ldpc_check_to_var_##SUFFIX(q->ptr, i_layer, this_pcm, these_var_indices); \ + \ + update_ldpc_soft_bits_##SUFFIX(q->ptr, i_layer, these_var_indices); \ + } \ + } \ + \ + extract_ldpc_message_##SUFFIX(q->ptr, message, q->liftK); \ + \ + return q->max_nof_iter; \ + } +#define LDPC_DECODER_TEMPLATE_FLOOD(LLR_TYPE, SUFFIX) \ + static int decode_##SUFFIX( \ + void* o, const LLR_TYPE* llrs, uint8_t* message, uint32_t cdwd_rm_length, srsran_crc_t* crc) \ + { \ + srsran_ldpc_decoder_t* q = o; \ + \ + /* it must be smaller than the codeword size */ \ + if (cdwd_rm_length > q->liftN - 2 * q->ls) { \ + cdwd_rm_length = q->liftN - 2 * q->ls; \ + } \ + /* We need at least q->bgK + 4 variable nodes to cover the high-rate region. However,*/ \ + /* 2 variable nodes are systematically punctured by the encoder. */ \ + if (cdwd_rm_length < (q->bgK + 2) * q->ls) { \ + /* ERROR("The rate-matched codeword should have a length at least equal to the high-rate region.");*/ \ + cdwd_rm_length = (q->bgK + 2) * q->ls; \ + /* return -1;*/ \ + } \ + if (cdwd_rm_length % q->ls) { \ + cdwd_rm_length = (cdwd_rm_length / q->ls + 1) * q->ls; \ + /* ERROR("The rate-matched codeword length should be a multiple of the lifting size."); */ \ + /* return -1;*/ \ + } \ + init_ldpc_dec_##SUFFIX(q->ptr, llrs, q->ls); \ + \ + uint16_t* this_pcm = NULL; \ + int8_t(*these_var_indices)[MAX_CNCT] = NULL; \ + \ + /* When computing the number of layers, we need to recall that the standard always removes */ \ + /* the first two variable nodes from the final codeword.*/ \ + uint8_t n_layers = cdwd_rm_length / q->ls - q->bgK + 2; \ + \ + for (int i_iteration = 0; i_iteration < 2 * q->max_nof_iter; i_iteration++) { \ + for (int i_layer = 0; i_layer < n_layers; i_layer++) { \ + update_ldpc_var_to_check_##SUFFIX(q->ptr, i_layer); \ + } \ + \ + for (int i_layer = 0; i_layer < n_layers; i_layer++) { \ + this_pcm = q->pcm + i_layer * q->bgN; \ + these_var_indices = q->var_indices + i_layer; \ + \ + update_ldpc_check_to_var_##SUFFIX(q->ptr, i_layer, this_pcm, these_var_indices); \ + } \ + \ + update_ldpc_soft_bits_##SUFFIX(q->ptr, q->var_indices); \ + } \ + \ + extract_ldpc_message_##SUFFIX(q->ptr, message, q->liftK); \ + \ + return q->max_nof_iter; \ + } /*! Carries out the actual destruction of the memory allocated to the decoder, float-LLR case. */ static void free_dec_f(void* o) @@ -46,52 +145,7 @@ static void free_dec_f(void* o) } /*! Carries out the decoding with real-valued LLRs. */ -static int decode_f(void* o, const float* llrs, uint8_t* message, uint32_t cdwd_rm_length) -{ - srsran_ldpc_decoder_t* q = o; - - if (cdwd_rm_length > q->liftN - 2 * q->ls) { - cdwd_rm_length = q->liftN - 2 * q->ls; - } - // We need at least q->bgK + 4 variable nodes to cover the high-rate region. However, - // 2 variable nodes are systematically punctured by the encoder. - if (cdwd_rm_length < (q->bgK + 2) * q->ls) { - // ERROR("The rate-matched codeword should have a length at least equal to the high-rate region."); - cdwd_rm_length = (q->bgK + 2) * q->ls; - // return -1; - } - if (cdwd_rm_length % q->ls) { - cdwd_rm_length = (cdwd_rm_length / q->ls + 1) * q->ls; - // ERROR("The rate-matched codeword length should be a multiple of the lifting size."); - // return -1; - } - - init_ldpc_dec_f(q->ptr, llrs, q->ls); - - uint16_t* this_pcm = NULL; - int8_t(*these_var_indices)[MAX_CNCT] = NULL; - - // When computing the number of layers, we need to recall that the standard always removes - // the first two variable nodes from the final codeword. - uint8_t n_layers = cdwd_rm_length / q->ls - q->bgK + 2; - - for (int i_iteration = 0; i_iteration < MAX_ITERATIONS; i_iteration++) { - for (int i_layer = 0; i_layer < n_layers; i_layer++) { - update_ldpc_var_to_check_f(q->ptr, i_layer); - - this_pcm = q->pcm + i_layer * q->bgN; - these_var_indices = q->var_indices + i_layer; - - update_ldpc_check_to_var_f(q->ptr, i_layer, this_pcm, these_var_indices); - - update_ldpc_soft_bits_f(q->ptr, i_layer, these_var_indices); - } - } - - extract_ldpc_message_f(q->ptr, message, q->liftK); - - return 0; -} +LDPC_DECODER_TEMPLATE(float, f) /*! Initializes the decoder to work with real valued LLRs. */ static int init_f(srsran_ldpc_decoder_t* q) @@ -123,53 +177,7 @@ static void free_dec_s(void* o) } /*! Carries out the decoding with 16-bit integer-valued LLRs. */ -static int decode_s(void* o, const int16_t* llrs, uint8_t* message, uint32_t cdwd_rm_length) -{ - srsran_ldpc_decoder_t* q = o; - - // it must be smaller than the codeword size - if (cdwd_rm_length > q->liftN - 2 * q->ls) { - cdwd_rm_length = q->liftN - 2 * q->ls; - } - // We need at least q->bgK + 4 variable nodes to cover the high-rate region. However, - // 2 variable nodes are systematically punctured by the encoder. - if (cdwd_rm_length < (q->bgK + 2) * q->ls) { - // ERROR("The rate-matched codeword should have a length at least equal to the high-rate region."); - cdwd_rm_length = (q->bgK + 2) * q->ls; - // return -1; - } - if (cdwd_rm_length % q->ls) { - cdwd_rm_length = (cdwd_rm_length / q->ls + 1) * q->ls; - // ERROR("The rate-matched codeword length should be a multiple of the lifting size."); - // return -1; - } - - init_ldpc_dec_s(q->ptr, llrs, q->ls); - - uint16_t* this_pcm = NULL; - int8_t(*these_var_indices)[MAX_CNCT] = NULL; - - // When computing the number of layers, we need to recall that the standard always removes - // the first two variable nodes from the final codeword. - uint8_t n_layers = cdwd_rm_length / q->ls - q->bgK + 2; - - for (int i_iteration = 0; i_iteration < MAX_ITERATIONS; i_iteration++) { - for (int i_layer = 0; i_layer < n_layers; i_layer++) { - update_ldpc_var_to_check_s(q->ptr, i_layer); - - this_pcm = q->pcm + i_layer * q->bgN; - these_var_indices = q->var_indices + i_layer; - - update_ldpc_check_to_var_s(q->ptr, i_layer, this_pcm, these_var_indices); - - update_ldpc_soft_bits_s(q->ptr, i_layer, these_var_indices); - } - } - - extract_ldpc_message_s(q->ptr, message, q->liftK); - - return 0; -} +LDPC_DECODER_TEMPLATE(int16_t, s) /*! Initializes the decoder to work with 16-bit integer-valued LLRs. */ static int init_s(srsran_ldpc_decoder_t* q) @@ -201,53 +209,7 @@ static void free_dec_c(void* o) } /*! Carries out the decoding with 8-bit integer-valued LLRs. */ -static int decode_c(void* o, const int8_t* llrs, uint8_t* message, uint32_t cdwd_rm_length) -{ - srsran_ldpc_decoder_t* q = o; - - // it must be smaller than the codeword size - if (cdwd_rm_length > q->liftN - 2 * q->ls) { - cdwd_rm_length = q->liftN - 2 * q->ls; - } - // We need at least q->bgK + 4 variable nodes to cover the high-rate region. However, - // 2 variable nodes are systematically punctured by the encoder. - if (cdwd_rm_length < (q->bgK + 2) * q->ls) { - // ERROR("The rate-matched codeword should have a length at least equal to the high-rate region."); - cdwd_rm_length = (q->bgK + 2) * q->ls; - // return -1; - } - if (cdwd_rm_length % q->ls) { - cdwd_rm_length = (cdwd_rm_length / q->ls + 1) * q->ls; - // ERROR("The rate-matched codeword length should be a multiple of the lifting size."); - // return -1; - } - - init_ldpc_dec_c(q->ptr, llrs, q->ls); - - uint16_t* this_pcm = NULL; - int8_t(*these_var_indices)[MAX_CNCT] = NULL; - - // When computing the number of layers, we need to recall that the standard always removes - // the first two variable nodes from the final codeword. - uint8_t n_layers = cdwd_rm_length / q->ls - q->bgK + 2; - - for (int i_iteration = 0; i_iteration < MAX_ITERATIONS; i_iteration++) { - for (int i_layer = 0; i_layer < n_layers; i_layer++) { - update_ldpc_var_to_check_c(q->ptr, i_layer); - - this_pcm = q->pcm + i_layer * q->bgN; - these_var_indices = q->var_indices + i_layer; - - update_ldpc_check_to_var_c(q->ptr, i_layer, this_pcm, these_var_indices); - - update_ldpc_soft_bits_c(q->ptr, i_layer, these_var_indices); - } - } - - extract_ldpc_message_c(q->ptr, message, q->liftK); - - return 0; -} +LDPC_DECODER_TEMPLATE(int8_t, c) /*! Initializes the decoder to work with 8-bit integer-valued LLRs. */ static int init_c(srsran_ldpc_decoder_t* q) @@ -279,53 +241,7 @@ static void free_dec_c_flood(void* o) } /*! Carries out the decoding with 8-bit integer-valued LLRs, flooded scheduling. */ -static int decode_c_flood(void* o, const int8_t* llrs, uint8_t* message, uint32_t cdwd_rm_length) -{ - srsran_ldpc_decoder_t* q = o; - - // it must be smaller than the codeword size - if (cdwd_rm_length > q->liftN - 2 * q->ls) { - cdwd_rm_length = q->liftN - 2 * q->ls; - } - // We need at least q->bgK + 4 variable nodes to cover the high-rate region. However, - // 2 variable nodes are systematically punctured by the encoder. - if (cdwd_rm_length < (q->bgK + 2) * q->ls) { - // ERROR("The rate-matched codeword should have a length at least equal to the high-rate region."); - cdwd_rm_length = (q->bgK + 2) * q->ls; - // return -1; - } - if (cdwd_rm_length % q->ls) { - cdwd_rm_length = (cdwd_rm_length / q->ls + 1) * q->ls; - // ERROR("The rate-matched codeword length should be a multiple of the lifting size."); - // return -1; - } - init_ldpc_dec_c_flood(q->ptr, llrs, q->ls); - - uint16_t* this_pcm = NULL; - int8_t(*these_var_indices)[MAX_CNCT] = NULL; - - // When computing the number of layers, we need to recall that the standard always removes - // the first two variable nodes from the final codeword. - uint8_t n_layers = cdwd_rm_length / q->ls - q->bgK + 2; - - for (int i_iteration = 0; i_iteration < 2 * MAX_ITERATIONS; i_iteration++) { - for (int i_layer = 0; i_layer < n_layers; i_layer++) { - update_ldpc_var_to_check_c_flood(q->ptr, i_layer); - } - - for (int i_layer = 0; i_layer < n_layers; i_layer++) { - this_pcm = q->pcm + i_layer * q->bgN; - these_var_indices = q->var_indices + i_layer; - - update_ldpc_check_to_var_c_flood(q->ptr, i_layer, this_pcm, these_var_indices); - } - update_ldpc_soft_bits_c_flood(q->ptr, q->var_indices); - } - - extract_ldpc_message_c_flood(q->ptr, message, q->liftK); - - return 0; -} +LDPC_DECODER_TEMPLATE_FLOOD(int8_t, c_flood); /*! Initializes the decoder to work with 8-bit integer-valued LLRs. */ static int init_c_flood(srsran_ldpc_decoder_t* q) @@ -358,52 +274,7 @@ static void free_dec_c_avx2(void* o) } /*! Carries out the decoding with 8-bit integer-valued LLRs (AVX2 implementation). */ -static int decode_c_avx2(void* o, const int8_t* llrs, uint8_t* message, uint32_t cdwd_rm_length) -{ - srsran_ldpc_decoder_t* q = o; - - // it must be smaller than the codeword size - if (cdwd_rm_length > q->liftN - 2 * q->ls) { - cdwd_rm_length = q->liftN - 2 * q->ls; - } - // We need at least q->bgK + 4 variable nodes to cover the high-rate region. However, - // 2 variable nodes are systematically punctured by the encoder. - if (cdwd_rm_length < (q->bgK + 2) * q->ls) { - // ERROR("The rate-matched codeword should have a length at least equal to the high-rate region."); - cdwd_rm_length = (q->bgK + 2) * q->ls; - // return -1; - } - if (cdwd_rm_length % q->ls) { - cdwd_rm_length = (cdwd_rm_length / q->ls + 1) * q->ls; - // ERROR("The rate-matched codeword length should be a multiple of the lifting size."); - // return -1; - } - init_ldpc_dec_c_avx2(q->ptr, llrs, q->ls); - - uint16_t* this_pcm = NULL; - int8_t(*these_var_indices)[MAX_CNCT] = NULL; - - // When computing the number of layers, we need to recall that the standard always removes - // the first two variable nodes from the final codeword. - uint8_t n_layers = cdwd_rm_length / q->ls - q->bgK + 2; - - for (int i_iteration = 0; i_iteration < MAX_ITERATIONS; i_iteration++) { - for (int i_layer = 0; i_layer < n_layers; i_layer++) { - update_ldpc_var_to_check_c_avx2(q->ptr, i_layer); - - this_pcm = q->pcm + i_layer * q->bgN; - these_var_indices = q->var_indices + i_layer; - - update_ldpc_check_to_var_c_avx2(q->ptr, i_layer, this_pcm, these_var_indices); - - update_ldpc_soft_bits_c_avx2(q->ptr, i_layer, these_var_indices); - } - } - - extract_ldpc_message_c_avx2(q->ptr, message, q->liftK); - - return 0; -} +LDPC_DECODER_TEMPLATE(int8_t, c_avx2); /*! Initializes the decoder to work with 8-bit integer-valued LLRs (AVX2 implementation). */ static int init_c_avx2(srsran_ldpc_decoder_t* q) @@ -436,52 +307,7 @@ static void free_dec_c_avx2long(void* o) } /*! Carries out the decoding with 8-bit integer-valued LLRs (AVX2 implementation, large lifting size). */ -static int decode_c_avx2long(void* o, const int8_t* llrs, uint8_t* message, uint32_t cdwd_rm_length) -{ - srsran_ldpc_decoder_t* q = o; - - // it must be smaller than the codeword size - if (cdwd_rm_length > q->liftN - 2 * q->ls) { - cdwd_rm_length = q->liftN - 2 * q->ls; - } - // We need at least q->bgK + 4 variable nodes to cover the high-rate region. However, - // 2 variable nodes are systematically punctured by the encoder. - if (cdwd_rm_length < (q->bgK + 2) * q->ls) { - // ERROR("The rate-matched codeword should have a length at least equal to the high-rate region."); - cdwd_rm_length = (q->bgK + 2) * q->ls; - // return -1; - } - if (cdwd_rm_length % q->ls) { - cdwd_rm_length = (cdwd_rm_length / q->ls + 1) * q->ls; - // ERROR("The rate-matched codeword length should be a multiple of the lifting size."); - // return -1; - } - init_ldpc_dec_c_avx2long(q->ptr, llrs, q->ls); - - uint16_t* this_pcm = NULL; - int8_t(*these_var_indices)[MAX_CNCT] = NULL; - - // When computing the number of layers, we need to recall that the standard always removes - // the first two variable nodes from the final codeword. - uint8_t n_layers = cdwd_rm_length / q->ls - q->bgK + 2; - - for (int i_iteration = 0; i_iteration < MAX_ITERATIONS; i_iteration++) { - for (int i_layer = 0; i_layer < n_layers; i_layer++) { - update_ldpc_var_to_check_c_avx2long(q->ptr, i_layer); - - this_pcm = q->pcm + i_layer * q->bgN; - these_var_indices = q->var_indices + i_layer; - - update_ldpc_check_to_var_c_avx2long(q->ptr, i_layer, this_pcm, these_var_indices); - - update_ldpc_soft_bits_c_avx2long(q->ptr, i_layer, these_var_indices); - } - } - - extract_ldpc_message_c_avx2long(q->ptr, message, q->liftK); - - return 0; -} +LDPC_DECODER_TEMPLATE(int8_t, c_avx2long); /*! Initializes the decoder to work with 8-bit integer-valued LLRs (AVX2 implementation, large lifting size). */ static int init_c_avx2long(srsran_ldpc_decoder_t* q) @@ -514,53 +340,7 @@ static void free_dec_c_avx2_flood(void* o) } /*! Carries out the decoding with 8-bit integer-valued LLRs (AVX2 implementation, flooded scheduling). */ -static int decode_c_avx2_flood(void* o, const int8_t* llrs, uint8_t* message, uint32_t cdwd_rm_length) -{ - srsran_ldpc_decoder_t* q = o; - - // it must be smaller than the codeword size - if (cdwd_rm_length > q->liftN - 2 * q->ls) { - cdwd_rm_length = q->liftN - 2 * q->ls; - } - // We need at least q->bgK + 4 variable nodes to cover the high-rate region. However, - // 2 variable nodes are systematically punctured by the encoder. - if (cdwd_rm_length < (q->bgK + 2) * q->ls) { - // ERROR("The rate-matched codeword should have a length at least equal to the high-rate region."); - cdwd_rm_length = (q->bgK + 2) * q->ls; - // return -1; - } - if (cdwd_rm_length % q->ls) { - cdwd_rm_length = (cdwd_rm_length / q->ls + 1) * q->ls; - // ERROR("The rate-matched codeword length should be a multiple of the lifting size."); - // return -1; - } - init_ldpc_dec_c_avx2_flood(q->ptr, llrs, q->ls); - - uint16_t* this_pcm = NULL; - int8_t(*these_var_indices)[MAX_CNCT] = NULL; - - // When computing the number of layers, we need to recall that the standard always removes - // the first two variable nodes from the final codeword. - uint8_t n_layers = cdwd_rm_length / q->ls - q->bgK + 2; - - for (int i_iteration = 0; i_iteration < 2 * MAX_ITERATIONS; i_iteration++) { - for (int i_layer = 0; i_layer < n_layers; i_layer++) { - update_ldpc_var_to_check_c_avx2_flood(q->ptr, i_layer); - } - - for (int i_layer = 0; i_layer < n_layers; i_layer++) { - this_pcm = q->pcm + i_layer * q->bgN; - these_var_indices = q->var_indices + i_layer; - - update_ldpc_check_to_var_c_avx2_flood(q->ptr, i_layer, this_pcm, these_var_indices); - } - update_ldpc_soft_bits_c_avx2_flood(q->ptr, q->var_indices); - } - - extract_ldpc_message_c_avx2_flood(q->ptr, message, q->liftK); - - return 0; -} +LDPC_DECODER_TEMPLATE_FLOOD(int8_t, c_avx2_flood); /*! Initializes the decoder to work with 8-bit integer-valued LLRs (AVX2 implementation, flooded scheduling). */ static int init_c_avx2_flood(srsran_ldpc_decoder_t* q) @@ -594,54 +374,7 @@ static void free_dec_c_avx2long_flood(void* o) /*! Carries out the decoding with 8-bit integer-valued LLRs (flooded scheduling, AVX2 implementation, large lifting * size). */ -static int decode_c_avx2long_flood(void* o, const int8_t* llrs, uint8_t* message, uint32_t cdwd_rm_length) -{ - srsran_ldpc_decoder_t* q = o; - - // it must be smaller than the codeword size - if (cdwd_rm_length > q->liftN - 2 * q->ls) { - cdwd_rm_length = q->liftN - 2 * q->ls; - } - // We need at least q->bgK + 4 variable nodes to cover the high-rate region. However, - // 2 variable nodes are systematically punctured by the encoder. - if (cdwd_rm_length < (q->bgK + 2) * q->ls) { - // ERROR("The rate-matched codeword should have a length at least equal to the high-rate region."); - cdwd_rm_length = (q->bgK + 2) * q->ls; - // return -1; - } - if (cdwd_rm_length % q->ls) { - cdwd_rm_length = (cdwd_rm_length / q->ls + 1) * q->ls; - // ERROR("The rate-matched codeword length should be a multiple of the lifting size."); - // return -1; - } - init_ldpc_dec_c_avx2long_flood(q->ptr, llrs, q->ls); - - uint16_t* this_pcm = NULL; - int8_t(*these_var_indices)[MAX_CNCT] = NULL; - - // When computing the number of layers, we need to recall that the standard always removes - // the first two variable nodes from the final codeword. - uint8_t n_layers = cdwd_rm_length / q->ls - q->bgK + 2; - - for (int i_iteration = 0; i_iteration < 2 * MAX_ITERATIONS; i_iteration++) { - for (int i_layer = 0; i_layer < n_layers; i_layer++) { - update_ldpc_var_to_check_c_avx2long_flood(q->ptr, i_layer); - } - - for (int i_layer = 0; i_layer < n_layers; i_layer++) { - this_pcm = q->pcm + i_layer * q->bgN; - these_var_indices = q->var_indices + i_layer; - - update_ldpc_check_to_var_c_avx2long_flood(q->ptr, i_layer, this_pcm, these_var_indices); - } - - update_ldpc_soft_bits_c_avx2long_flood(q->ptr, q->var_indices); - } - - extract_ldpc_message_c_avx2long_flood(q->ptr, message, q->liftK); - - return 0; -} +LDPC_DECODER_TEMPLATE_FLOOD(int8_t, c_avx2long_flood) /*! Initializes the decoder to work with 8-bit integer-valued LLRs * (flooded scheduling, AVX2 implementation, large lifting size). */ @@ -680,52 +413,7 @@ static void free_dec_c_avx512(void* o) } /*! Carries out the decoding with 8-bit integer-valued LLRs (AVX512 implementation). */ -static int decode_c_avx512(void* o, const int8_t* llrs, uint8_t* message, uint32_t cdwd_rm_length) -{ - srsran_ldpc_decoder_t* q = o; - - // it must be smaller than the codeword size - if (cdwd_rm_length > q->liftN - 2 * q->ls) { - cdwd_rm_length = q->liftN - 2 * q->ls; - } - // We need at least q->bgK + 4 variable nodes to cover the high-rate region. However, - // 2 variable nodes are systematically punctured by the encoder. - if (cdwd_rm_length < (q->bgK + 2) * q->ls) { - // ERROR("The rate-matched codeword should have a length at least equal to the high-rate region."); - cdwd_rm_length = (q->bgK + 2) * q->ls; - // return -1; - } - if (cdwd_rm_length % q->ls) { - cdwd_rm_length = (cdwd_rm_length / q->ls + 1) * q->ls; - // ERROR("The rate-matched codeword length should be a multiple of the lifting size."); - // return -1; - } - init_ldpc_dec_c_avx512(q->ptr, llrs, q->ls); - - uint16_t* this_pcm = NULL; - int8_t(*these_var_indices)[MAX_CNCT] = NULL; - - // When computing the number of layers, we need to recall that the standard always removes - // the first two variable nodes from the final codeword. - uint8_t n_layers = cdwd_rm_length / q->ls - q->bgK + 2; - - for (int i_iteration = 0; i_iteration < MAX_ITERATIONS; i_iteration++) { - for (int i_layer = 0; i_layer < n_layers; i_layer++) { - update_ldpc_var_to_check_c_avx512(q->ptr, i_layer); - - this_pcm = q->pcm + i_layer * q->bgN; - these_var_indices = q->var_indices + i_layer; - - update_ldpc_check_to_var_c_avx512(q->ptr, i_layer, this_pcm, these_var_indices); - - update_ldpc_soft_bits_c_avx512(q->ptr, i_layer, these_var_indices); - } - } - - extract_ldpc_message_c_avx512(q->ptr, message, q->liftK); - - return 0; -} +LDPC_DECODER_TEMPLATE(int8_t, c_avx512) /*! Initializes the decoder to work with 8-bit integer-valued LLRs (AVX512 implementation). */ static int init_c_avx512(srsran_ldpc_decoder_t* q) @@ -758,52 +446,7 @@ static void free_dec_c_avx512long(void* o) } /*! Carries out the decoding with 8-bit integer-valued LLRs (AVX512 implementation, large lifting size). */ -static int decode_c_avx512long(void* o, const int8_t* llrs, uint8_t* message, uint32_t cdwd_rm_length) -{ - srsran_ldpc_decoder_t* q = o; - - // it must be smaller than the codeword size - if (cdwd_rm_length > q->liftN - 2 * q->ls) { - cdwd_rm_length = q->liftN - 2 * q->ls; - } - // We need at least q->bgK + 4 variable nodes to cover the high-rate region. However, - // 2 variable nodes are systematically punctured by the encoder. - if (cdwd_rm_length < (q->bgK + 2) * q->ls) { - // ERROR("The rate-matched codeword should have a length at least equal to the high-rate region."); - cdwd_rm_length = (q->bgK + 2) * q->ls; - // return -1; - } - if (cdwd_rm_length % q->ls) { - cdwd_rm_length = (cdwd_rm_length / q->ls + 1) * q->ls; - // ERROR("The rate-matched codeword length should be a multiple of the lifting size."); - // return -1; - } - - init_ldpc_dec_c_avx512long(q->ptr, llrs, q->ls); - - uint16_t* this_pcm = NULL; - int8_t(*these_var_indices)[MAX_CNCT] = NULL; - - // When computing the number of layers, we need to recall that the standard always removes - // the first two variable nodes from the final codeword. - uint8_t n_layers = cdwd_rm_length / q->ls - q->bgK + 2; - - for (int i_iteration = 0; i_iteration < MAX_ITERATIONS; i_iteration++) { - for (int i_layer = 0; i_layer < n_layers; i_layer++) { - update_ldpc_var_to_check_c_avx512long(q->ptr, i_layer); - - this_pcm = q->pcm + i_layer * q->bgN; - these_var_indices = q->var_indices + i_layer; - - update_ldpc_check_to_var_c_avx512long(q->ptr, i_layer, this_pcm, these_var_indices); - - update_ldpc_soft_bits_c_avx512long(q->ptr, i_layer, these_var_indices); - } - } - extract_ldpc_message_c_avx512long(q->ptr, message, q->liftK); - - return 0; -} +LDPC_DECODER_TEMPLATE(int8_t, c_avx512long) /*! Initializes the decoder to work with 8-bit integer-valued LLRs (AVX512 implementation, large lifting size). */ static int init_c_avx512long(srsran_ldpc_decoder_t* q) @@ -837,54 +480,7 @@ static void free_dec_c_avx512long_flood(void* o) /*! Carries out the decoding with 8-bit integer-valued LLRs (flooded scheduling, AVX512 implementation, large lifting * size). */ -static int decode_c_avx512long_flood(void* o, const int8_t* llrs, uint8_t* message, uint32_t cdwd_rm_length) -{ - srsran_ldpc_decoder_t* q = o; - - // it must be smaller than the codeword size - if (cdwd_rm_length > q->liftN - 2 * q->ls) { - cdwd_rm_length = q->liftN - 2 * q->ls; - } - // We need at least q->bgK + 4 variable nodes to cover the high-rate region. However, - // 2 variable nodes are systematically punctured by the encoder. - if (cdwd_rm_length < (q->bgK + 2) * q->ls) { - // ERROR("The rate-matched codeword should have a length at least equal to the high-rate region."); - cdwd_rm_length = (q->bgK + 2) * q->ls; - // return -1; - } - if (cdwd_rm_length % q->ls) { - cdwd_rm_length = (cdwd_rm_length / q->ls + 1) * q->ls; - // ERROR("The rate-matched codeword length should be a multiple of the lifting size."); - // return -1; - } - init_ldpc_dec_c_avx512long_flood(q->ptr, llrs, q->ls); - - uint16_t* this_pcm = NULL; - int8_t(*these_var_indices)[MAX_CNCT] = NULL; - - // When computing the number of layers, we need to recall that the standard always removes - // the first two variable nodes from the final codeword. - uint8_t n_layers = cdwd_rm_length / q->ls - q->bgK + 2; - - for (int i_iteration = 0; i_iteration < 2 * MAX_ITERATIONS; i_iteration++) { - for (int i_layer = 0; i_layer < n_layers; i_layer++) { - update_ldpc_var_to_check_c_avx512long_flood(q->ptr, i_layer); - } - - for (int i_layer = 0; i_layer < n_layers; i_layer++) { - this_pcm = q->pcm + i_layer * q->bgN; - these_var_indices = q->var_indices + i_layer; - - update_ldpc_check_to_var_c_avx512long_flood(q->ptr, i_layer, this_pcm, these_var_indices); - } - - update_ldpc_soft_bits_c_avx512long_flood(q->ptr, q->var_indices); - } - - extract_ldpc_message_c_avx512long_flood(q->ptr, message, q->liftK); - - return 0; -} +LDPC_DECODER_TEMPLATE_FLOOD(int8_t, c_avx512long_flood) /*! Initializes the decoder to work with 8-bit integer-valued LLRs * (flooded scheduling, AVX512 implementation, large lifting size). */ @@ -905,14 +501,19 @@ static int init_c_avx512long_flood(srsran_ldpc_decoder_t* q) #endif // LV_HAVE_AVX512 -int srsran_ldpc_decoder_init(srsran_ldpc_decoder_t* q, - srsran_ldpc_decoder_type_t type, - srsran_basegraph_t bg, - uint16_t ls, - float scaling_fctr) +int srsran_ldpc_decoder_init(srsran_ldpc_decoder_t* q, const srsran_ldpc_decoder_args_t* args) { - int ls_index = get_ls_index(ls); + if (q == NULL || args == NULL) { + return -1; + } + // Extract configuration arguments + uint16_t ls = args->ls; + srsran_basegraph_t bg = args->bg; + float scaling_fctr = args->scaling_fctr; + srsran_ldpc_decoder_type_t type = args->type; + + int ls_index = get_ls_index(ls); if (ls_index == VOID_LIFTSIZE) { ERROR("Invalid lifting size %d", ls); return -1; @@ -939,6 +540,8 @@ int srsran_ldpc_decoder_init(srsran_ldpc_decoder_t* q, q->liftM = ls * q->bgM; q->liftN = ls * q->bgN; + q->max_nof_iter = (args->max_nof_iter == 0) ? LDPC_DECODER_DEFAULT_MAX_NOF_ITER : args->max_nof_iter; + q->pcm = srsran_vec_u16_malloc(q->bgM * q->bgN); if (!q->pcm) { perror("malloc"); @@ -1017,7 +620,7 @@ void srsran_ldpc_decoder_free(srsran_ldpc_decoder_t* q) int srsran_ldpc_decoder_decode_f(srsran_ldpc_decoder_t* q, const float* llrs, uint8_t* message, uint32_t cdwd_rm_length) { - return q->decode_f(q, llrs, message, cdwd_rm_length); + return q->decode_f(q, llrs, message, cdwd_rm_length, NULL); } int srsran_ldpc_decoder_decode_s(srsran_ldpc_decoder_t* q, @@ -1025,7 +628,7 @@ int srsran_ldpc_decoder_decode_s(srsran_ldpc_decoder_t* q, uint8_t* message, uint32_t cdwd_rm_length) { - return q->decode_s(q, llrs, message, cdwd_rm_length); + return q->decode_s(q, llrs, message, cdwd_rm_length, NULL); } int srsran_ldpc_decoder_decode_c(srsran_ldpc_decoder_t* q, @@ -1033,5 +636,5 @@ int srsran_ldpc_decoder_decode_c(srsran_ldpc_decoder_t* q, uint8_t* message, uint32_t cdwd_rm_length) { - return q->decode_c(q, llrs, message, cdwd_rm_length); + return q->decode_c(q, llrs, message, cdwd_rm_length, NULL); } 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 2670fb6a2..4cdff475b 100644 --- a/lib/src/phy/fec/ldpc/test/ldpc_chain_test.c +++ b/lib/src/phy/fec/ldpc/test/ldpc_chain_test.c @@ -160,7 +160,7 @@ int main(int argc, char** argv) perror("encoder init"); exit(-1); } -#else // no AVX2 +#else // no AVX2 if (srsran_ldpc_encoder_init(&encoder, SRSRAN_LDPC_ENCODER_C, base_graph, lift_size) != 0) { perror("encoder init"); exit(-1); @@ -168,42 +168,53 @@ int main(int argc, char** argv) #endif // LV_HAVE_AVX2 #endif // LV_HAVE_AVX512 + // Create LDPC configuration arguments + srsran_ldpc_decoder_args_t decoder_args = {}; + decoder_args.bg = base_graph; + decoder_args.ls = lift_size; + decoder_args.scaling_fctr = MS_SF; + // create an LDPC decoder (float) srsran_ldpc_decoder_t decoder_f; - if (srsran_ldpc_decoder_init(&decoder_f, SRSRAN_LDPC_DECODER_F, base_graph, lift_size, MS_SF) != 0) { + decoder_args.type = SRSRAN_LDPC_DECODER_F; + if (srsran_ldpc_decoder_init(&decoder_f, &decoder_args) != 0) { perror("decoder init"); exit(-1); } // create an LDPC decoder (16 bit) srsran_ldpc_decoder_t decoder_s; - if (srsran_ldpc_decoder_init(&decoder_s, SRSRAN_LDPC_DECODER_S, base_graph, lift_size, MS_SF) != 0) { + decoder_args.type = SRSRAN_LDPC_DECODER_S; + if (srsran_ldpc_decoder_init(&decoder_s, &decoder_args) != 0) { perror("decoder init"); exit(-1); } // create an LDPC decoder (8 bit) srsran_ldpc_decoder_t decoder_c; - if (srsran_ldpc_decoder_init(&decoder_c, SRSRAN_LDPC_DECODER_C, base_graph, lift_size, MS_SF) != 0) { + decoder_args.type = SRSRAN_LDPC_DECODER_C; + if (srsran_ldpc_decoder_init(&decoder_c, &decoder_args) != 0) { perror("decoder init"); exit(-1); } // create an LDPC decoder (8 bit, flooded) srsran_ldpc_decoder_t decoder_c_flood; - if (srsran_ldpc_decoder_init(&decoder_c_flood, SRSRAN_LDPC_DECODER_C_FLOOD, base_graph, lift_size, MS_SF) != 0) { + decoder_args.type = SRSRAN_LDPC_DECODER_C_FLOOD; + if (srsran_ldpc_decoder_init(&decoder_c_flood, &decoder_args) != 0) { perror("decoder init"); exit(-1); } #ifdef LV_HAVE_AVX2 // create an LDPC decoder (8 bit, AVX2 version) srsran_ldpc_decoder_t decoder_avx; - if (srsran_ldpc_decoder_init(&decoder_avx, SRSRAN_LDPC_DECODER_C_AVX2, base_graph, lift_size, MS_SF) != 0) { + decoder_args.type = SRSRAN_LDPC_DECODER_C_AVX2; + if (srsran_ldpc_decoder_init(&decoder_avx, &decoder_args) != 0) { perror("decoder init"); exit(-1); } // create an LDPC decoder (8 bit, flooded scheduling, AVX2 version) srsran_ldpc_decoder_t decoder_avx_flood; - if (srsran_ldpc_decoder_init(&decoder_avx_flood, SRSRAN_LDPC_DECODER_C_AVX2_FLOOD, base_graph, lift_size, MS_SF) != - 0) { + decoder_args.type = SRSRAN_LDPC_DECODER_C_AVX2_FLOOD; + if (srsran_ldpc_decoder_init(&decoder_avx_flood, &decoder_args) != 0) { perror("decoder init"); exit(-1); } @@ -212,15 +223,16 @@ int main(int argc, char** argv) #ifdef LV_HAVE_AVX512 // create an LDPC decoder (8 bit, AVX512 version) srsran_ldpc_decoder_t decoder_avx512; - if (srsran_ldpc_decoder_init(&decoder_avx512, SRSRAN_LDPC_DECODER_C_AVX512, base_graph, lift_size, MS_SF) != 0) { + decoder_args.type = SRSRAN_LDPC_DECODER_C_AVX512; + if (srsran_ldpc_decoder_init(&decoder_avx512, &decoder_args) != 0) { perror("decoder init"); exit(-1); } // create an LDPC decoder (8 bit, flooded scheduling, AVX512 version) srsran_ldpc_decoder_t decoder_avx512_flood; - if (srsran_ldpc_decoder_init( - &decoder_avx512_flood, SRSRAN_LDPC_DECODER_C_AVX512_FLOOD, base_graph, lift_size, MS_SF) != 0) { + decoder_args.type = SRSRAN_LDPC_DECODER_C_AVX512_FLOOD; + if (srsran_ldpc_decoder_init(&decoder_avx512_flood, &decoder_args) != 0) { perror("decoder init"); exit(-1); } diff --git a/lib/src/phy/fec/ldpc/test/ldpc_dec_avx2_test.c b/lib/src/phy/fec/ldpc/test/ldpc_dec_avx2_test.c index 306848143..cddd9b7e4 100644 --- a/lib/src/phy/fec/ldpc/test/ldpc_dec_avx2_test.c +++ b/lib/src/phy/fec/ldpc/test/ldpc_dec_avx2_test.c @@ -153,9 +153,16 @@ int main(int argc, char** argv) srsran_ldpc_decoder_type_t dectype = (scheduling == 0) ? SRSRAN_LDPC_DECODER_C_AVX2 : SRSRAN_LDPC_DECODER_C_AVX2_FLOOD; + // Create LDPC configuration arguments + srsran_ldpc_decoder_args_t decoder_args = {}; + decoder_args.type = dectype; + decoder_args.bg = base_graph; + decoder_args.ls = lift_size; + decoder_args.scaling_fctr = 1.0f; + // create an LDPC decoder srsran_ldpc_decoder_t decoder; - if (srsran_ldpc_decoder_init(&decoder, dectype, base_graph, lift_size, 1) != 0) { + if (srsran_ldpc_decoder_init(&decoder, &decoder_args) != 0) { perror("decoder init"); exit(-1); } diff --git a/lib/src/phy/fec/ldpc/test/ldpc_dec_avx512_test.c b/lib/src/phy/fec/ldpc/test/ldpc_dec_avx512_test.c index a3391ce65..4efc302d5 100644 --- a/lib/src/phy/fec/ldpc/test/ldpc_dec_avx512_test.c +++ b/lib/src/phy/fec/ldpc/test/ldpc_dec_avx512_test.c @@ -152,9 +152,16 @@ int main(int argc, char** argv) srsran_ldpc_decoder_type_t dectype = (scheduling == 0) ? SRSRAN_LDPC_DECODER_C_AVX512 : SRSRAN_LDPC_DECODER_C_AVX512_FLOOD; + // Create LDPC configuration arguments + srsran_ldpc_decoder_args_t decoder_args = {}; + decoder_args.type = dectype; + decoder_args.bg = base_graph; + decoder_args.ls = lift_size; + decoder_args.scaling_fctr = 1.0f; + // create an LDPC decoder srsran_ldpc_decoder_t decoder; - if (srsran_ldpc_decoder_init(&decoder, dectype, base_graph, lift_size, 1) != 0) { + if (srsran_ldpc_decoder_init(&decoder, &decoder_args) != 0) { perror("decoder init"); exit(-1); } diff --git a/lib/src/phy/fec/ldpc/test/ldpc_dec_c_test.c b/lib/src/phy/fec/ldpc/test/ldpc_dec_c_test.c index a698c22a6..ec34c5374 100644 --- a/lib/src/phy/fec/ldpc/test/ldpc_dec_c_test.c +++ b/lib/src/phy/fec/ldpc/test/ldpc_dec_c_test.c @@ -146,9 +146,16 @@ int main(int argc, char** argv) srsran_ldpc_decoder_type_t dectype = (scheduling == 0) ? SRSRAN_LDPC_DECODER_C : SRSRAN_LDPC_DECODER_C_FLOOD; + // Create LDPC configuration arguments + srsran_ldpc_decoder_args_t decoder_args = {}; + decoder_args.type = dectype; + decoder_args.bg = base_graph; + decoder_args.ls = lift_size; + decoder_args.scaling_fctr = 1.0f; + // create an LDPC decoder srsran_ldpc_decoder_t decoder; - if (srsran_ldpc_decoder_init(&decoder, dectype, base_graph, lift_size, 1) != 0) { + if (srsran_ldpc_decoder_init(&decoder, &decoder_args) != 0) { perror("decoder init"); exit(-1); } diff --git a/lib/src/phy/fec/ldpc/test/ldpc_dec_s_test.c b/lib/src/phy/fec/ldpc/test/ldpc_dec_s_test.c index 01b730537..8e03679bb 100644 --- a/lib/src/phy/fec/ldpc/test/ldpc_dec_s_test.c +++ b/lib/src/phy/fec/ldpc/test/ldpc_dec_s_test.c @@ -139,9 +139,16 @@ int main(int argc, char** argv) parse_args(argc, argv); + // Create LDPC configuration arguments + srsran_ldpc_decoder_args_t decoder_args = {}; + decoder_args.type = SRSRAN_LDPC_DECODER_S; + decoder_args.bg = base_graph; + decoder_args.ls = lift_size; + decoder_args.scaling_fctr = 1.0f; + // create an LDPC decoder srsran_ldpc_decoder_t decoder; - if (srsran_ldpc_decoder_init(&decoder, SRSRAN_LDPC_DECODER_S, base_graph, lift_size, 1) != 0) { + if (srsran_ldpc_decoder_init(&decoder, &decoder_args) != 0) { perror("decoder init"); exit(-1); } diff --git a/lib/src/phy/fec/ldpc/test/ldpc_dec_test.c b/lib/src/phy/fec/ldpc/test/ldpc_dec_test.c index 34aa5f504..62bb23431 100644 --- a/lib/src/phy/fec/ldpc/test/ldpc_dec_test.c +++ b/lib/src/phy/fec/ldpc/test/ldpc_dec_test.c @@ -139,9 +139,16 @@ int main(int argc, char** argv) parse_args(argc, argv); + // Create LDPC configuration arguments + srsran_ldpc_decoder_args_t decoder_args = {}; + decoder_args.type = SRSRAN_LDPC_DECODER_F; + decoder_args.bg = base_graph; + decoder_args.ls = lift_size; + decoder_args.scaling_fctr = 1.0f; + // create an LDPC decoder srsran_ldpc_decoder_t decoder; - if (srsran_ldpc_decoder_init(&decoder, SRSRAN_LDPC_DECODER_F, base_graph, lift_size, 1) != 0) { + if (srsran_ldpc_decoder_init(&decoder, &decoder_args) != 0) { perror("decoder init"); exit(-1); } 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 f94c5239c..caabbb059 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 @@ -188,7 +188,7 @@ int main(int argc, char** argv) perror("encoder init"); exit(-1); } -#else // no AVX2 +#else // no AVX2 if (srsran_ldpc_encoder_init(&encoder, SRSRAN_LDPC_ENCODER_C, base_graph, lift_size) != 0) { perror("encoder init"); exit(-1); @@ -234,42 +234,53 @@ int main(int argc, char** argv) exit(-1); } + // Create LDPC configuration arguments + srsran_ldpc_decoder_args_t decoder_args = {}; + decoder_args.bg = base_graph; + decoder_args.ls = lift_size; + decoder_args.scaling_fctr = MS_SF; + // create an LDPC decoder (float) srsran_ldpc_decoder_t decoder_f; - if (srsran_ldpc_decoder_init(&decoder_f, SRSRAN_LDPC_DECODER_F, base_graph, lift_size, MS_SF) != 0) { + decoder_args.type = SRSRAN_LDPC_DECODER_F; + if (srsran_ldpc_decoder_init(&decoder_f, &decoder_args) != 0) { perror("decoder init"); exit(-1); } // create an LDPC decoder (16 bit) srsran_ldpc_decoder_t decoder_s; - if (srsran_ldpc_decoder_init(&decoder_s, SRSRAN_LDPC_DECODER_S, base_graph, lift_size, MS_SF) != 0) { + decoder_args.type = SRSRAN_LDPC_DECODER_S; + if (srsran_ldpc_decoder_init(&decoder_s, &decoder_args) != 0) { perror("decoder init (int16_t)"); exit(-1); } // create an LDPC decoder (8 bit) srsran_ldpc_decoder_t decoder_c; - if (srsran_ldpc_decoder_init(&decoder_c, SRSRAN_LDPC_DECODER_C, base_graph, lift_size, MS_SF) != 0) { + decoder_args.type = SRSRAN_LDPC_DECODER_C; + if (srsran_ldpc_decoder_init(&decoder_c, &decoder_args) != 0) { perror("decoder init (int8_t)"); exit(-1); } // create an LDPC decoder (8 bit, flooded) srsran_ldpc_decoder_t decoder_c_flood; - if (srsran_ldpc_decoder_init(&decoder_c_flood, SRSRAN_LDPC_DECODER_C_FLOOD, base_graph, lift_size, MS_SF) != 0) { + decoder_args.type = SRSRAN_LDPC_DECODER_C_FLOOD; + if (srsran_ldpc_decoder_init(&decoder_c_flood, &decoder_args) != 0) { perror("decoder init"); exit(-1); } #ifdef LV_HAVE_AVX2 // create an LDPC decoder (8 bit, AVX2 version) srsran_ldpc_decoder_t decoder_avx; - if (srsran_ldpc_decoder_init(&decoder_avx, SRSRAN_LDPC_DECODER_C_AVX2, base_graph, lift_size, MS_SF) != 0) { + decoder_args.type = SRSRAN_LDPC_DECODER_C_AVX2; + if (srsran_ldpc_decoder_init(&decoder_avx, &decoder_args) != 0) { perror("decoder init"); exit(-1); } // create an LDPC decoder (8 bit, flooded scheduling, AVX2 version) srsran_ldpc_decoder_t decoder_avx_flood; - if (srsran_ldpc_decoder_init(&decoder_avx_flood, SRSRAN_LDPC_DECODER_C_AVX2_FLOOD, base_graph, lift_size, MS_SF) != - 0) { + decoder_args.type = SRSRAN_LDPC_DECODER_C_AVX2_FLOOD; + if (srsran_ldpc_decoder_init(&decoder_avx_flood, &decoder_args) != 0) { perror("decoder init"); exit(-1); } @@ -278,15 +289,16 @@ int main(int argc, char** argv) #ifdef LV_HAVE_AVX512 // create an LDPC decoder (8 bit, AVX2 version) srsran_ldpc_decoder_t decoder_avx512; - if (srsran_ldpc_decoder_init(&decoder_avx512, SRSRAN_LDPC_DECODER_C_AVX512, base_graph, lift_size, MS_SF) != 0) { + decoder_args.type = SRSRAN_LDPC_DECODER_C_AVX512; + if (srsran_ldpc_decoder_init(&decoder_avx512, &decoder_args) != 0) { perror("decoder init"); exit(-1); } // create an LDPC decoder (8 bit, flooded scheduling, AVX512 version) srsran_ldpc_decoder_t decoder_avx512_flood; - if (srsran_ldpc_decoder_init( - &decoder_avx512_flood, SRSRAN_LDPC_DECODER_C_AVX512_FLOOD, base_graph, lift_size, MS_SF) != 0) { + decoder_args.type = SRSRAN_LDPC_DECODER_C_AVX512_FLOOD; + if (srsran_ldpc_decoder_init(&decoder_avx512_flood, &decoder_args) != 0) { perror("decoder init"); exit(-1); } diff --git a/lib/src/phy/phch/sch_nr.c b/lib/src/phy/phch/sch_nr.c index 66cbb37c2..523fd4202 100644 --- a/lib/src/phy/phch/sch_nr.c +++ b/lib/src/phy/phch/sch_nr.c @@ -275,24 +275,35 @@ int srsran_sch_nr_init_rx(srsran_sch_nr_t* q, const srsran_sch_nr_args_t* args) continue; } - q->decoder_bg1[ls] = calloc(1, sizeof(srsran_ldpc_decoder_t)); + // Initialise LDPC configuration arguments + srsran_ldpc_decoder_args_t decoder_args = {}; + decoder_args.type = decoder_type; + decoder_args.ls = ls; + decoder_args.scaling_fctr = scaling_factor; + decoder_args.max_nof_iter = args->max_nof_iter; + + q->decoder_bg1[ls] = SRSRAN_MEM_ALLOC(srsran_ldpc_decoder_t, 1); if (!q->decoder_bg1[ls]) { ERROR("Error: calloc"); return SRSRAN_ERROR; } + SRSRAN_MEM_ZERO(q->decoder_bg1[ls], srsran_ldpc_decoder_t, 1); - if (srsran_ldpc_decoder_init(q->decoder_bg1[ls], decoder_type, BG1, ls, scaling_factor) < SRSRAN_SUCCESS) { + decoder_args.bg = BG1; + if (srsran_ldpc_decoder_init(q->decoder_bg1[ls], &decoder_args) < SRSRAN_SUCCESS) { ERROR("Error: initialising BG1 LDPC decoder for ls=%d", ls); return SRSRAN_ERROR; } - q->decoder_bg2[ls] = calloc(1, sizeof(srsran_ldpc_decoder_t)); + q->decoder_bg2[ls] = SRSRAN_MEM_ALLOC(srsran_ldpc_decoder_t, 1); if (!q->decoder_bg2[ls]) { ERROR("Error: calloc"); return SRSRAN_ERROR; } + SRSRAN_MEM_ZERO(q->decoder_bg2[ls], srsran_ldpc_decoder_t, 1); - if (srsran_ldpc_decoder_init(q->decoder_bg2[ls], decoder_type, BG2, ls, scaling_factor) < SRSRAN_SUCCESS) { + decoder_args.bg = BG2; + if (srsran_ldpc_decoder_init(q->decoder_bg2[ls], &decoder_args) < SRSRAN_SUCCESS) { ERROR("Error: initialising BG2 LDPC decoder for ls=%d", ls); return SRSRAN_ERROR; }