Condensed LDPC Decoder config arguments into an structure and unified common decoder code

master
Xavier Arteaga 4 years ago committed by Xavier Arteaga
parent 1f1233782f
commit 5aa7f9dd8b

@ -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.

@ -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;
/**

@ -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);
}

@ -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);
}

@ -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);
}

@ -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);
}

@ -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);
}

@ -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);
}

@ -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);
}

@ -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);
}

@ -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;
}

Loading…
Cancel
Save