From 244355a3d22b9079b7e2e6e5b89b6456946a6bf2 Mon Sep 17 00:00:00 2001 From: Romain Beurdouche Date: Wed, 18 Dec 2024 14:27:46 +0000 Subject: [PATCH] fix(nrLDPC_coding_segment): move rate matching, interleaving and their counterparts to segment coding implementation --- CMakeLists.txt | 6 +- openair1/PHY/CODING/coding_defs.h | 186 +++---- .../nrLDPC_coding_segment/CMakeLists.txt | 1 + .../nrLDPC_coding_segment_decoder.c | 1 + .../nrLDPC_coding_segment_encoder.c | 1 + .../nrLDPC_coding_segment}/nr_rate_matching.c | 467 ++++++++---------- .../nrLDPC_coding_segment/nr_rate_matching.h | 97 ++++ .../nrLDPC_coding_xdma/CMakeLists.txt | 2 + .../nrLDPC_coding_xdma/nrLDPC_coding_xdma.c | 1 + openair1/PHY/CODING/nrLDPC_load.c | 4 +- openair1/PHY/NR_TRANSPORT/nr_tbs_tools.c | 71 ++- 11 files changed, 444 insertions(+), 393 deletions(-) rename openair1/PHY/CODING/{ => nrLDPC_coding/nrLDPC_coding_segment}/nr_rate_matching.c (69%) create mode 100644 openair1/PHY/CODING/nrLDPC_coding/nrLDPC_coding_segment/nr_rate_matching.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 9907b9ff42..3a3bca4ab7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -807,8 +807,6 @@ set(PHY_SRC_COMMON ${OPENAIR1_DIR}/PHY/LTE_REFSIG/lte_dl_mbsfn.c ${OPENAIR1_DIR}/PHY/LTE_REFSIG/lte_ul_ref.c ${OPENAIR1_DIR}/PHY/CODING/lte_segmentation.c - ${OPENAIR1_DIR}/PHY/CODING/nr_segmentation.c - ${OPENAIR1_DIR}/PHY/CODING/nr_rate_matching.c ${OPENAIR1_DIR}/PHY/CODING/ccoding_byte.c ${OPENAIR1_DIR}/PHY/CODING/ccoding_byte_lte.c ${OPENAIR1_DIR}/PHY/CODING/3gpplte_sse.c @@ -919,6 +917,8 @@ set(PHY_SRC_UE ) set(PHY_NR_SRC_COMMON + ${OPENAIR1_DIR}/PHY/CODING/nr_segmentation.c + ${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_tbs_tools.c ${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_prach_common.c ${OPENAIR1_DIR}/PHY/nr_phy_common/src/nr_phy_common_csirs.c ${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_scrambling.c @@ -942,7 +942,6 @@ set(PHY_SRC_UE ${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_dlsch_coding.c ${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_ulsch_decoding.c ${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_ulsch.c - ${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_tbs_tools.c ${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_sch_dmrs.c ${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_prach.c ${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_ulsch_llr_computation.c @@ -990,7 +989,6 @@ set(PHY_SRC_UE ${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c ${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/nr_ulsch_coding.c ${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c - ${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_tbs_tools.c ${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_prach_common.c ${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_sch_dmrs.c ${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/ diff --git a/openair1/PHY/CODING/coding_defs.h b/openair1/PHY/CODING/coding_defs.h index efc81620af..7da151fea9 100644 --- a/openair1/PHY/CODING/coding_defs.h +++ b/openair1/PHY/CODING/coding_defs.h @@ -41,7 +41,6 @@ #define MAX_LDPC_ITERATIONS_MBSFN 4 #define LTE_NULL 2 -#define NR_NULL 2 typedef struct { unsigned short nb_bits; unsigned short f1; @@ -60,10 +59,9 @@ typedef struct interleaver_codebook { extern t_interleaver_codebook *f1f2mat; extern short *il_tb; - /** @addtogroup _PHY_CODING_BLOCKS_ * @{ -*/ + */ /** \fn lte_segmentation(uint8_t *input_buffer, uint8_t **output_buffers, @@ -95,8 +93,6 @@ int32_t lte_segmentation(uint8_t *input_buffer, uint32_t *Kminus, uint32_t *F); - - /** \fn uint32_t sub_block_interleaving_turbo(uint32_t D, uint8_t *d,uint8_t *w) \brief This is the subblock interleaving algorithm from 36-212 (Release 8, 8.6 2009-03), pages 15-16. This function takes the d-sequence and generates the w-sequence. The nu-sequence from 36-212 is implicit. @@ -105,18 +101,17 @@ This function takes the d-sequence and generates the w-sequence. The nu-sequenc \param w Pointer to output (w-sequence, interleaver output) \returns Interleaving matrix cardinality (\f$K_{\pi}\f$ from 36-212) */ -uint32_t sub_block_interleaving_turbo(uint32_t D, uint8_t *d,uint8_t *w); +uint32_t sub_block_interleaving_turbo(uint32_t D, uint8_t *d, uint8_t *w); /** \fn uint32_t sub_block_interleaving_cc(uint32_t D, uint8_t *d,uint8_t *w) -\brief This is the subblock interleaving algorithm for convolutionally coded blocks from 36-212 (Release 8, 8.6 2009-03), pages 15-16. -This function takes the d-sequence and generates the w-sequence. The nu-sequence from 36-212 is implicit. +\brief This is the subblock interleaving algorithm for convolutionally coded blocks from 36-212 (Release 8, 8.6 2009-03), +pages 15-16. This function takes the d-sequence and generates the w-sequence. The nu-sequence from 36-212 is implicit. \param D Number of input bits \param d Pointer to input (d-sequence, convolutional code output) \param w Pointer to output (w-sequence, interleaver output) \returns Interleaving matrix cardinality (\f$K_{\pi}\f$ from 36-212) */ -uint32_t sub_block_interleaving_cc(uint32_t D, uint8_t *d,uint8_t *w); - +uint32_t sub_block_interleaving_cc(uint32_t D, uint8_t *d, uint8_t *w); /** \fn void sub_block_deinterleaving_turbo(uint32_t D, int16_t *d,int16_t *w) \brief This is the subblock deinterleaving algorithm from 36-212 (Release 8, 8.6 2009-03), pages 15-16. @@ -125,16 +120,16 @@ This function takes the w-sequence and generates the d-sequence. The nu-sequenc \param d Pointer to output (d-sequence, turbo code output) \param w Pointer to input (w-sequence, interleaver output) */ -void sub_block_deinterleaving_turbo(uint32_t D, int16_t *d,int16_t *w); +void sub_block_deinterleaving_turbo(uint32_t D, int16_t *d, int16_t *w); /** \fn void sub_block_deinterleaving_cc(uint32_t D, int8_t *d,int8_t *w) -\brief This is the subblock deinterleaving algorithm for convolutionally-coded data from 36-212 (Release 8, 8.6 2009-03), pages 15-16. -This function takes the w-sequence and generates the d-sequence. The nu-sequence from 36-212 is implicit. +\brief This is the subblock deinterleaving algorithm for convolutionally-coded data from 36-212 (Release 8, 8.6 2009-03), +pages 15-16. This function takes the w-sequence and generates the d-sequence. The nu-sequence from 36-212 is implicit. \param D Number of input bits \param d Pointer to output (d-sequence, turbo code output) \param w Pointer to input (w-sequence, interleaver output) */ -void sub_block_deinterleaving_cc(uint32_t D,int8_t *d,int8_t *w); +void sub_block_deinterleaving_cc(uint32_t D, int8_t *d, int8_t *w); /** \fn generate_dummy_w(uint32_t D, uint8_t *w,uint8_t F) \brief This function generates a dummy interleaved sequence (first row) for receiver, in order to identify @@ -148,7 +143,8 @@ the NULL positions used to make the matrix complete. uint32_t generate_dummy_w(uint32_t D, uint8_t *w, uint8_t F); /** \fn generate_dummy_w_cc(uint32_t D, uint8_t *w) -\brief This function generates a dummy interleaved sequence (first row) for receiver (convolutionally-coded data), in order to identify the NULL positions used to make the matrix complete. +\brief This function generates a dummy interleaved sequence (first row) for receiver (convolutionally-coded data), +in order to identify the NULL positions used to make the matrix complete. \param D Number of systematic bits plus 4 (plus 4 for termination) \param w This is the dummy sequence (first row), it will contain zeros and at most 31 "LTE_NULL" values \returns Interleaving matrix cardinality (\f$K_{\pi}\f$ from 36-212) @@ -168,7 +164,8 @@ uint32_t generate_dummy_w_cc(uint32_t D, uint8_t *w); uint8_t Nl, uint8_t r) -\brief This is the LTE rate matching algorithm for Turbo-coded channels (e.g. DLSCH,ULSCH). It is taken directly from 36-212 (Rel 8 8.6, 2009-03), pages 16-18 ) +\brief This is the LTE rate matching algorithm for Turbo-coded channels (e.g. DLSCH,ULSCH). +It is taken directly from 36-212 (Rel 8 8.6, 2009-03), pages 16-18 ) \param RTC R^TC_subblock from subblock interleaver (number of rows in interleaving matrix) for up to 8 segments \param G This the number of coded transport bits allocated in sub-frame \param w This is a pointer to the w-sequence (second interleaver output) @@ -184,7 +181,6 @@ uint32_t generate_dummy_w_cc(uint32_t D, uint8_t *w); \param nb_rb Number of PRBs \returns \f$E\f$, the number of coded bits per segment */ - uint32_t lte_rate_matching_turbo(uint32_t RTC, uint32_t G, uint8_t *w, @@ -200,20 +196,19 @@ uint32_t lte_rate_matching_turbo(uint32_t RTC, uint8_t nb_rb); /** -\brief This is the LTE rate matching algorithm for Convolutionally-coded channels (e.g. BCH,DCI,UCI). It is taken directly from 36-212 (Rel 8 8.6, 2009-03), pages 16-18 ) +\brief This is the LTE rate matching algorithm for Convolutionally-coded channels (e.g. BCH,DCI,UCI). +It is taken directly from 36-212 (Rel 8 8.6, 2009-03), pages 16-18 ) \param RCC R^CC_subblock from subblock interleaver (number of rows in interleaving matrix) for up to 8 segments \param E Number of coded channel bits \param w This is a pointer to the w-sequence (second interleaver output) \param e This is a pointer to the e-sequence (rate matching output, channel input/output bits) \returns \f$E\f$, the number of coded bits per segment */ -uint32_t lte_rate_matching_cc(uint32_t RCC, - uint16_t E, - uint8_t *w, - uint8_t *e); +uint32_t lte_rate_matching_cc(uint32_t RCC, uint16_t E, uint8_t *w, uint8_t *e); /** -\brief This is the LTE rate matching algorithm for Turbo-coded channels (e.g. DLSCH,ULSCH). It is taken directly from 36-212 (Rel 8 8.6, 2009-03), pages 16-18 ) +\brief This is the LTE rate matching algorithm for Turbo-coded channels (e.g. DLSCH,ULSCH). +It is taken directly from 36-212 (Rel 8 8.6, 2009-03), pages 16-18 ) \param RTC R^TC_subblock from subblock interleaver (number of rows in interleaving matrix) \param G This the number of coded transport bits allocated in sub-frame \param w This is a pointer to the soft w-sequence (second interleaver output) with soft-combined outputs from successive HARQ rounds @@ -265,7 +260,8 @@ uint32_t lte_rate_matching_turbo_rx_abs(uint32_t RTC, uint32_t *E_out); /** -\brief This is the LTE rate matching algorithm for Convolutionally-coded channels (e.g. BCH,DCI,UCI). It is taken directly from 36-212 (Rel 8 8.6, 2009-03), pages 16-18 ) +\brief This is the LTE rate matching algorithm for Convolutionally-coded channels (e.g. BCH,DCI,UCI). +It is taken directly from 36-212 (Rel 8 8.6, 2009-03), pages 16-18 ) \param RCC R^CC_subblock from subblock interleaver (number of rows in interleaving matrix) \param E This the number of coded bits allocated for channel \param w This is a pointer to the soft w-sequence (second interleaver output) with soft-combined outputs from successive HARQ rounds @@ -273,11 +269,7 @@ uint32_t lte_rate_matching_turbo_rx_abs(uint32_t RTC, \param soft_input This is a pointer to the soft channel output \returns \f$E\f$, the number of coded bits per segment */ -void lte_rate_matching_cc_rx(uint32_t RCC, - uint16_t E, - int8_t *w, - uint8_t *dummy_w, - int8_t *soft_input); +void lte_rate_matching_cc_rx(uint32_t RCC, uint16_t E, int8_t *w, uint8_t *dummy_w, int8_t *soft_input); /** \fn void ccodedot11_encode(uint32_t numbytes,uint8_t *inPtr,uint8_t *outPtr,uint8_t puncturing) \brief This function implements a rate 1/2 constraint length 7 convolutional code. @@ -286,10 +278,7 @@ void lte_rate_matching_cc_rx(uint32_t RCC, @param outPtr Pointer to output buffer @param puncturing Puncturing pattern (Not used at present, to be removed) */ -void ccodedot11_encode (uint32_t numbytes, - uint8_t *inPtr, - uint8_t *outPtr, - uint8_t puncturing); +void ccodedot11_encode(uint32_t numbytes, uint8_t *inPtr, uint8_t *outPtr, uint8_t puncturing); /*!\fn void ccodedot11_init(void) \brief This function initializes the generator polynomials for an 802.11 convolutional code.*/ @@ -299,11 +288,6 @@ void ccodedot11_init(void); \brief This function initializes the trellis structure for decoding an 802.11 convolutional code.*/ void ccodedot11_init_inv(void); - - - - - /** \fn void ccodelte_encode(int32_t numbits,uint8_t add_crc, uint8_t *inPtr,uint8_t *outPtr,uint16_t rnti) \brief This function implements the LTE convolutional code of rate 1/3 with a constraint length of 7 bits. The inputs are bit packed in octets @@ -314,12 +298,7 @@ void ccodedot11_init_inv(void); @param outPtr Pointer to output buffer @param rnti RNTI for CRC scrambling */ -void -ccodelte_encode (int32_t numbits, - uint8_t add_crc, - uint8_t *inPtr, - uint8_t *outPtr, - uint16_t rnti); +void ccodelte_encode(int32_t numbits, uint8_t add_crc, uint8_t *inPtr, uint8_t *outPtr, uint16_t rnti); /*!\fn void ccodelte_init(void) \brief This function initializes the generator polynomials for an LTE convolutional code.*/ @@ -337,13 +316,9 @@ void ccodedab_init(void); \brief This function initializes the trellis structure for decoding an DAB convolutional code (first 3 bits).*/ void ccodedab_init_inv(void); - - /*!\fn void crcTableInit(void) \brief This function initializes the different crc tables.*/ -void crcTableInit (void); - - +void crcTableInit(void); /*!\fn uint32_t crc24a(uint8_t *inPtr, int32_t bitlen) \brief This computes a 24-bit crc ('a' variant for overall transport block) @@ -351,7 +326,7 @@ based on 3GPP UMTS/LTE specifications. @param inPtr Pointer to input byte stream @param bitlen length of inputs in bits */ -unsigned int crc24a (unsigned char * inptr, int bitlen); +unsigned int crc24a(unsigned char *inptr, int bitlen); /*!\fn uint32_t crc24b(uint8_t *inPtr, int32_t bitlen) \brief This computes a 24-bit crc ('b' variant for transport-block segments) @@ -359,7 +334,7 @@ based on 3GPP UMTS/LTE specifications. @param inPtr Pointer to input byte stream @param bitlen length of inputs in bits */ -uint32_t crc24b (uint8_t *inPtr, int32_t bitlen); +uint32_t crc24b(uint8_t *inPtr, int32_t bitlen); /*!\fn uint32_t crc24c(uint8_t *inPtr, int32_t bitlen) \brief This computes a 24-bit crc ('c' variant for transport-block segments) @@ -367,68 +342,67 @@ based on 3GPP Rel 15 specifications. @param inPtr Pointer to input byte stream @param bitlen length of inputs in bits */ -uint32_t crc24c (uint8_t *inPtr, int32_t bitlen); +uint32_t crc24c(uint8_t *inPtr, int32_t bitlen); /*!\fn uint32_t crc16(uint8_t *inPtr, int32_t bitlen) \brief This computes a 16-bit crc based on 3GPP UMTS specifications. @param inPtr Pointer to input byte stream @param bitlen length of inputs in bits*/ -unsigned int crc16 (unsigned char * inptr, int bitlen); +unsigned int crc16(unsigned char *inptr, int bitlen); /*!\fn uint32_t crc12(uint8_t *inPtr, int32_t bitlen) \brief This computes a 12-bit crc based on 3GPP UMTS specifications. @param inPtr Pointer to input byte stream @param bitlen length of inputs in bits*/ -unsigned int crc12 (unsigned char * inptr, int bitlen); +unsigned int crc12(unsigned char *inptr, int bitlen); /*!\fn uint32_t crc12(uint8_t *inPtr, int32_t bitlen) \brief This computes an 11-bit crc based on 3GPP NR specifications. @param inPtr Pointer to input byte stream @param bitlen length of inputs in bits*/ -unsigned int crc11 (unsigned char * inptr, int bitlen); +unsigned int crc11(unsigned char *inptr, int bitlen); /*!\fn uint32_t crc8(uint8_t *inPtr, int32_t bitlen) \brief This computes a 8-bit crc based on 3GPP UMTS specifications. @param inPtr Pointer to input byte stream @param bitlen length of inputs in bits*/ -unsigned int crc8 (unsigned char * inptr, int bitlen); +unsigned int crc8(unsigned char *inptr, int bitlen); /*!\fn uint32_t crc8(uint8_t *inPtr, int32_t bitlen) \brief This computes a 6-bit crc based on 3GPP NR specifications. @param inPtr Pointer to input byte stream @param bitlen length of inputs in bits*/ -unsigned int crc6 (unsigned char * inptr, int bitlen); +unsigned int crc6(unsigned char *inptr, int bitlen); int check_crc(uint8_t *decoded_bytes, uint32_t n, uint8_t crc_type); /*!\fn void phy_viterbi_dot11_sse2(int8_t *y, uint8_t *decoded_bytes, uint16_t n,int offset,int traceback) -\brief This routine performs a SIMD optmized Viterbi decoder for the 802.11 64-state convolutional code. It can be -run in segments with final trace back after last segment. +\brief This routine performs a SIMD optmized Viterbi decoder for the 802.11 64-state convolutional code. +It can be run in segments with final trace back after last segment. @param y Pointer to soft input (coded on 8-bits but should be limited to 4-bit precision to avoid overflow) @param decoded_bytes Pointer to decoded output @param n Length of input/trellis depth in bits for this run @param offset offset in receive buffer for segment on which to operate @param traceback flag to indicate that traceback should be performed*/ -void phy_viterbi_dot11_sse2(int8_t *y,uint8_t *decoded_bytes,uint16_t n); +void phy_viterbi_dot11_sse2(int8_t *y, uint8_t *decoded_bytes, uint16_t n); /*!\fn void phy_viterbi_lte_sse2(int8_t *y, uint8_t *decoded_bytes, uint16_t n) \brief This routine performs a SIMD optmized Viterbi decoder for the LTE 64-state tail-biting convolutional code. @param y Pointer to soft input (coded on 8-bits but should be limited to 4-bit precision to avoid overflow) @param decoded_bytes Pointer to decoded output @param n Length of input/trellis depth in bits*/ -//void phy_viterbi_lte_sse2(int8_t *y,uint8_t *decoded_bytes,uint16_t n); -void phy_viterbi_lte_sse2(int8_t *y,uint8_t *decoded_bytes,uint16_t n); +// void phy_viterbi_lte_sse2(int8_t *y,uint8_t *decoded_bytes,uint16_t n); +void phy_viterbi_lte_sse2(int8_t *y, uint8_t *decoded_bytes, uint16_t n); /*!\fn void phy_generate_viterbi_tables(void) \brief This routine initializes metric tables for the optimized Viterbi decoder. */ -void phy_generate_viterbi_tables( void ); +void phy_generate_viterbi_tables(void); /*!\fn void phy_generate_viterbi_tables_lte(void) \brief This routine initializes metric tables for the optimized LTE Viterbi decoder. */ -void phy_generate_viterbi_tables_lte( void ); - +void phy_generate_viterbi_tables_lte(void); /*!\fn int32_t rate_matching(uint32_t N_coded, uint32_t N_input, @@ -443,63 +417,43 @@ void phy_generate_viterbi_tables_lte( void ); @param off Offset for seed */ -int32_t rate_matching(uint32_t N_coded, - uint32_t N_input, - uint8_t *inPtr, - uint8_t N_bps, - uint32_t off); +int32_t rate_matching(uint32_t N_coded, uint32_t N_input, uint8_t *inPtr, uint8_t N_bps, uint32_t off); -int32_t rate_matching_lte(uint32_t N_coded, - uint32_t N_input, - uint8_t *inPtr, - uint32_t off); +int32_t rate_matching_lte(uint32_t N_coded, uint32_t N_input, uint8_t *inPtr, uint32_t off); -unsigned int crcbit (unsigned char * inputptr, int octetlen, unsigned int poly); +unsigned int crcbit(unsigned char *inputptr, int octetlen, unsigned int poly); -void phy_viterbi_dot11(int8_t *,uint8_t *,uint16_t); +void phy_viterbi_dot11(int8_t *, uint8_t *, uint16_t); +/** + * \brief perform segmentation of a Transport Block (TB) into segments + * \param input_buffer buffer containing the TB data to be segmented, can be NULL + * \param output_buffer buffer containing the TB data after segmentation, can be NULL + * \param B size of the TB in bits + * \param C pointer to write the number of segments + * \param K pointer to write the payload size per segment + * \param Zout pointer to write the lifting size per segment + * \param F pointer to write the number of filler bits per segment + */ int32_t nr_segmentation(unsigned char *input_buffer, - unsigned char **output_buffers, - unsigned int B, - unsigned int *C, - unsigned int *K, - unsigned int *Zout, - unsigned int *F, - uint8_t BG); + unsigned char **output_buffers, + unsigned int B, + unsigned int *C, + unsigned int *K, + unsigned int *Zout, + unsigned int *F, + uint8_t BG); -void nr_interleaving_ldpc(uint32_t E, uint8_t Qm, uint8_t *e,uint8_t *f); - -void nr_deinterleaving_ldpc(uint32_t E, uint8_t Qm, int16_t *e,int16_t *f); - -int nr_get_R_ldpc_decoder(int rvidx, - int E, - int BG, - int Z, - int *llrLen, - int round); - -int nr_rate_matching_ldpc(uint32_t Tbslbrm, - uint8_t BG, - uint16_t Z, - uint8_t *w, - uint8_t *e, - uint8_t C, - uint32_t F, - uint32_t Foffset, - uint8_t rvidx, - uint32_t E); - -int nr_rate_matching_ldpc_rx(uint32_t Tbslbrm, - uint8_t BG, - uint16_t Z, - int16_t *w, - int16_t *soft_input, - uint8_t C, - uint8_t rvidx, - uint8_t clear, - uint32_t E, - uint32_t F, - uint32_t Foffset); +/** + * \brief compute parameter R for NR LDPC decoder + * \param rvidx redundancy version index + * \param E size of the code segment in bits + * \param BG LDPC base graph number + * \param Z lifting size + * \param llrlen pointer to the size in bits of input llrs + * \round HARQ round index + */ +int nr_get_R_ldpc_decoder(int rvidx, int E, int BG, int Z, int *llrLen, int round); decoder_if_t phy_threegpplte_turbo_decoder; decoder_if_t phy_threegpplte_turbo_decoder8; diff --git a/openair1/PHY/CODING/nrLDPC_coding/nrLDPC_coding_segment/CMakeLists.txt b/openair1/PHY/CODING/nrLDPC_coding/nrLDPC_coding_segment/CMakeLists.txt index ca8ff03700..52de22b05f 100644 --- a/openair1/PHY/CODING/nrLDPC_coding/nrLDPC_coding_segment/CMakeLists.txt +++ b/openair1/PHY/CODING/nrLDPC_coding/nrLDPC_coding_segment/CMakeLists.txt @@ -2,6 +2,7 @@ add_library(ldpc MODULE nrLDPC_coding_segment_decoder.c nrLDPC_coding_segment_encoder.c ${PHY_NR_CODINGIF} + nr_rate_matching.c ) set_target_properties(ldpc PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}) diff --git a/openair1/PHY/CODING/nrLDPC_coding/nrLDPC_coding_segment/nrLDPC_coding_segment_decoder.c b/openair1/PHY/CODING/nrLDPC_coding/nrLDPC_coding_segment/nrLDPC_coding_segment_decoder.c index e1fec76e23..77a726511d 100644 --- a/openair1/PHY/CODING/nrLDPC_coding/nrLDPC_coding_segment/nrLDPC_coding_segment_decoder.c +++ b/openair1/PHY/CODING/nrLDPC_coding/nrLDPC_coding_segment/nrLDPC_coding_segment_decoder.c @@ -25,6 +25,7 @@ // [from gNB coding] +#include "nr_rate_matching.h" #include "PHY/defs_gNB.h" #include "PHY/CODING/coding_extern.h" #include "PHY/CODING/coding_defs.h" diff --git a/openair1/PHY/CODING/nrLDPC_coding/nrLDPC_coding_segment/nrLDPC_coding_segment_encoder.c b/openair1/PHY/CODING/nrLDPC_coding/nrLDPC_coding_segment/nrLDPC_coding_segment_encoder.c index 6c66edeb82..5b51fa1f00 100644 --- a/openair1/PHY/CODING/nrLDPC_coding/nrLDPC_coding_segment/nrLDPC_coding_segment_encoder.c +++ b/openair1/PHY/CODING/nrLDPC_coding/nrLDPC_coding_segment/nrLDPC_coding_segment_encoder.c @@ -23,6 +23,7 @@ * \brief Top-level routines for implementing LDPC encoding of transport channels */ +#include "nr_rate_matching.h" #include "PHY/defs_gNB.h" #include "PHY/CODING/coding_extern.h" #include "PHY/CODING/coding_defs.h" diff --git a/openair1/PHY/CODING/nr_rate_matching.c b/openair1/PHY/CODING/nrLDPC_coding/nrLDPC_coding_segment/nr_rate_matching.c similarity index 69% rename from openair1/PHY/CODING/nr_rate_matching.c rename to openair1/PHY/CODING/nrLDPC_coding/nrLDPC_coding_segment/nr_rate_matching.c index 1ed520cf12..a25b6d4b57 100644 --- a/openair1/PHY/CODING/nr_rate_matching.c +++ b/openair1/PHY/CODING/nrLDPC_coding/nrLDPC_coding_segment/nr_rate_matching.c @@ -19,29 +19,24 @@ * contact@openairinterface.org */ -/* file: nr_rate_matching.c - purpose: Procedures for rate matching/interleaving for NR LDPC - author: hongzhi.wang@tcl.com -*/ - -#include "PHY/defs_gNB.h" -#include "PHY/defs_nr_UE.h" -#include "PHY/CODING/coding_defs.h" +#include "PHY/defs_common.h" #include "PHY/sse_intrin.h" -//#define RM_DEBUG 1 +#include "nr_rate_matching.h" + +// #define RM_DEBUG 1 static const uint8_t index_k0[2][4] = {{0, 17, 33, 56}, {0, 13, 25, 43}}; -void nr_interleaving_ldpc(uint32_t E, uint8_t Qm, uint8_t *e,uint8_t *f) +void nr_interleaving_ldpc(uint32_t E, uint8_t Qm, uint8_t *e, uint8_t *f) { uint32_t EQm; - EQm = E/Qm; - memset(f,0,E*sizeof(uint8_t)); - uint8_t *e0,*e1,*e2,*e3,*e4,*e5,*e6,*e7; + EQm = E / Qm; + memset(f, 0, E * sizeof(uint8_t)); + uint8_t *e0, *e1, *e2, *e3, *e4, *e5, *e6, *e7; uint8_t *fp; -#if 0 //def __WASAVX2__ +#if 0 // def __WASAVX2__ simde__m256i tmp0,tmp1,tmp2,tmp0b,tmp1b,tmp3,tmp4,tmp5; simde__m256i *e0_256,*e1_256,*e2_256,*e3_256,*e4_256,*e5_256,*e6_256,*e7_256; @@ -228,148 +223,137 @@ void nr_interleaving_ldpc(uint32_t E, uint8_t Qm, uint8_t *e,uint8_t *f) } #else - //original unoptimized loops - /* - for (int j = 0; j< EQm; j++,j2+=2){ - for (int i = 0; i< Qm; i++){ - f[(i+j*Qm)] = e[(i*EQm + j)]; - } - } - */ + // original unoptimized loops + /* + for (int j = 0; j< EQm; j++,j2+=2){ + for (int i = 0; i< Qm; i++){ + f[(i+j*Qm)] = e[(i*EQm + j)]; + } + } + */ - fp=f; + fp = f; switch (Qm) { - case 2: - e0=e; - e1=e0+EQm; - for (int j = 0, j2 = 0; j< EQm; j++,j2+=2){ - fp=&f[j2]; - fp[0] = e0[j]; - fp[1] = e1[j]; - } - break; - case 4: - e0=e; - e1=e0+EQm; - e2=e1+EQm; - e3=e2+EQm; - for (int j = 0, j2 = 0; j< EQm; j++,j2+=4){ - fp=&f[j2]; - fp[0] = e0[j]; - fp[1] = e1[j]; - fp[2] = e2[j]; - fp[3] = e3[j]; - } - break; - case 6: - e0=e; - e1=e0+EQm; - e2=e1+EQm; - e3=e2+EQm; - e4=e3+EQm; - e5=e4+EQm; - fp = f; - for (int j = 0; j< EQm; j++){ - *fp++ = e0[j]; - *fp++ = e1[j]; - *fp++ = e2[j]; - *fp++ = e3[j]; - *fp++ = e4[j]; - *fp++ = e5[j]; - } - break; - case 8: - e0=e; - e1=e0+EQm; - e2=e1+EQm; - e3=e2+EQm; - e4=e3+EQm; - e5=e4+EQm; - e6=e5+EQm; - e7=e6+EQm; - for (int j = 0, j2 = 0; j< EQm; j++,j2+=8){ - fp=&f[j2]; - fp[0] = e0[j]; - fp[1] = e1[j]; - fp[2] = e2[j]; - fp[3] = e3[j]; - fp[4] = e4[j]; - fp[5] = e5[j]; - fp[6] = e6[j]; - fp[7] = e7[j]; - } - break; - default: AssertFatal(1==0,"Should never be here!\n"); + case 2: + e0 = e; + e1 = e0 + EQm; + for (int j = 0, j2 = 0; j < EQm; j++, j2 += 2) { + fp = &f[j2]; + fp[0] = e0[j]; + fp[1] = e1[j]; + } + break; + case 4: + e0 = e; + e1 = e0 + EQm; + e2 = e1 + EQm; + e3 = e2 + EQm; + for (int j = 0, j2 = 0; j < EQm; j++, j2 += 4) { + fp = &f[j2]; + fp[0] = e0[j]; + fp[1] = e1[j]; + fp[2] = e2[j]; + fp[3] = e3[j]; + } + break; + case 6: + e0 = e; + e1 = e0 + EQm; + e2 = e1 + EQm; + e3 = e2 + EQm; + e4 = e3 + EQm; + e5 = e4 + EQm; + fp = f; + for (int j = 0; j < EQm; j++) { + *fp++ = e0[j]; + *fp++ = e1[j]; + *fp++ = e2[j]; + *fp++ = e3[j]; + *fp++ = e4[j]; + *fp++ = e5[j]; + } + break; + case 8: + e0 = e; + e1 = e0 + EQm; + e2 = e1 + EQm; + e3 = e2 + EQm; + e4 = e3 + EQm; + e5 = e4 + EQm; + e6 = e5 + EQm; + e7 = e6 + EQm; + for (int j = 0, j2 = 0; j < EQm; j++, j2 += 8) { + fp = &f[j2]; + fp[0] = e0[j]; + fp[1] = e1[j]; + fp[2] = e2[j]; + fp[3] = e3[j]; + fp[4] = e4[j]; + fp[5] = e5[j]; + fp[6] = e6[j]; + fp[7] = e7[j]; + } + break; + default: + AssertFatal(1 == 0, "Should never be here!\n"); } #endif } - - - -void nr_deinterleaving_ldpc(uint32_t E, uint8_t Qm, int16_t *e,int16_t *f) -{ - - - switch(Qm) { - case 2: - { - AssertFatal(E%2==0,""); - int16_t *e1=e+(E/2); - int16_t *end=f+E-1; - while( f Ncb) infoBits = Ncb; - if (infoBits > *llrLen) *llrLen = infoBits; - - int sysBits = (BG==1)?(22*Z):(10*Z); - float decoderR = (float)sysBits/(infoBits + 2*Z); - - if (BG == 2) - if (decoderR < 0.3333) - return 15; - else if (decoderR < 0.6667) - return 13; - else - return 23; - else - if (decoderR < 0.6667) - return 13; - else if (decoderR < 0.8889) - return 23; - else - return 89; } int nr_rate_matching_ldpc(uint32_t Tbslbrm, uint8_t BG, uint16_t Z, - uint8_t *w, + uint8_t *d, uint8_t *e, uint8_t C, - uint32_t F, - uint32_t Foffset, + uint32_t F, + uint32_t Foffset, uint8_t rvidx, uint32_t E) { - uint32_t Ncb,ind,k=0,Nref,N; + uint32_t Ncb, ind, k = 0, Nref, N; - if (C==0) { - LOG_E(PHY,"nr_rate_matching: invalid parameters (C %d\n",C); + if (C == 0) { + LOG_E(PHY, "nr_rate_matching: invalid parameters (C %d\n", C); return -1; } - //Bit selection - N = (BG==1)?(66*Z):(50*Z); + // Bit selection + N = (BG == 1) ? (66 * Z) : (50 * Z); if (Tbslbrm == 0) - Ncb = N; + Ncb = N; else { - Nref = 3*Tbslbrm/(2*C); //R_LBRM = 2/3 - Ncb = min(N, Nref); + Nref = 3 * Tbslbrm / (2 * C); // R_LBRM = 2/3 + Ncb = min(N, Nref); } - ind = (index_k0[BG-1][rvidx]*Ncb/N)*Z; + ind = (index_k0[BG - 1][rvidx] * Ncb / N) * Z; #ifdef RM_DEBUG - printf("nr_rate_matching_ldpc: E %u, F %u, Foffset %u, k0 %u, Ncb %u, rvidx %d, Tbslbrm %u\n", E, F, Foffset, ind, Ncb, rvidx, Tbslbrm); + printf("nr_rate_matching_ldpc: E %u, F %u, Foffset %u, k0 %u, Ncb %u, rvidx %d, Tbslbrm %u\n", + E, + F, + Foffset, + ind, + Ncb, + rvidx, + Tbslbrm); #endif if (Foffset > E) { - LOG_E(PHY,"nr_rate_matching: invalid parameters (Foffset %d > E %d) F %d, k0 %d, Ncb %d, rvidx %d, Tbslbrm %d\n",Foffset,E,F, ind, Ncb, rvidx, Tbslbrm); + LOG_E(PHY, + "nr_rate_matching: invalid parameters (Foffset %d > E %d) F %d, k0 %d, Ncb %d, rvidx %d, Tbslbrm %d\n", + Foffset, + E, + F, + ind, + Ncb, + rvidx, + Tbslbrm); return -1; } if (Foffset > Ncb) { - LOG_E(PHY,"nr_rate_matching: invalid parameters (Foffset %d > Ncb %d)\n",Foffset,Ncb); + LOG_E(PHY, "nr_rate_matching: invalid parameters (Foffset %d > Ncb %d)\n", Foffset, Ncb); return -1; } - if (ind >= Foffset && ind < (F+Foffset)) ind = F+Foffset; + if (ind >= Foffset && ind < (F + Foffset)) + ind = F + Foffset; if (ind < Foffset) { // case where we have some bits before the filler and the rest after - memcpy((void*)e,(void*)(w+ind),Foffset-ind); + memcpy((void *)e, (void *)(d + ind), Foffset - ind); - if (E + F <= Ncb-ind) { // E+F doesn't contain all coded bits - memcpy((void*)(e+Foffset-ind),(void*)(w+Foffset+F),E-Foffset+ind); - k=E; + if (E + F <= Ncb - ind) { // E+F doesn't contain all coded bits + memcpy((void *)(e + Foffset - ind), (void *)(d + Foffset + F), E - Foffset + ind); + k = E; + } else { + memcpy((void *)(e + Foffset - ind), (void *)(d + Foffset + F), Ncb - Foffset - F); + k = Ncb - F - ind; } - else { - memcpy((void*)(e+Foffset-ind),(void*)(w+Foffset+F),Ncb-Foffset-F); - k=Ncb-F-ind; - } - } - else { - if (E <= Ncb-ind) { //E+F doesn't contain all coded bits - memcpy((void*)(e),(void*)(w+ind),E); - k=E; - } - else { - memcpy((void*)(e),(void*)(w+ind),Ncb-ind); - k=Ncb-ind; + } else { + if (E <= Ncb - ind) { // E+F doesn't contain all coded bits + memcpy((void *)(e), (void *)(d + ind), E); + k = E; + } else { + memcpy((void *)(e), (void *)(d + ind), Ncb - ind); + k = Ncb - ind; } } - while(k E) { - LOG_E(PHY,"nr_rate_matching: invalid parameters (Foffset %d > E %d)\n",Foffset,E); + LOG_E(PHY, "nr_rate_matching: invalid parameters (Foffset %d > E %d)\n", Foffset, E); return -1; } if (Foffset > Ncb) { - LOG_E(PHY,"nr_rate_matching: invalid parameters (Foffset %d > Ncb %d)\n",Foffset,Ncb); + LOG_E(PHY, "nr_rate_matching: invalid parameters (Foffset %d > Ncb %d)\n", Foffset, Ncb); return -1; } #ifdef RM_DEBUG - printf("nr_rate_matching_ldpc_rx: Clear %d, E %u, Foffset %u, k0 %u, Ncb %u, rvidx %d, Tbslbrm %u\n", clear, E, Foffset, ind, Ncb, rvidx, Tbslbrm); + printf("nr_rate_matching_ldpc_rx: Clear %d, E %u, Foffset %u, k0 %u, Ncb %u, rvidx %d, Tbslbrm %u\n", + clear, + E, + Foffset, + ind, + Ncb, + rvidx, + Tbslbrm); #endif if (clear == 1) - memset(w, 0, Ncb * sizeof(int16_t)); + memset(d, 0, Ncb * sizeof(int16_t)); - k=0; + k = 0; if (ind < Foffset) - for (; (ind",k,ind,w[ind],soft_input[k]); + printf("RM_RX k%u Ind %u(before filler): %d (%d)=>", k, ind, d[ind], soft_input[k]); #endif - w[ind]+=soft_input[k++]; + d[ind] += soft_input[k++]; #ifdef RM_DEBUG - printf("%d\n",w[ind]); + printf("%d\n", d[ind]); #endif } - if (ind >= Foffset && ind < Foffset+F) ind=Foffset+F; + if (ind >= Foffset && ind < Foffset + F) + ind = Foffset + F; - for (; (ind",k,ind,w[ind],soft_input[k]); + printf("RM_RX k%u Ind %u(after filler) %d (%d)=>", k, ind, d[ind], soft_input[k]); #endif - w[ind] += soft_input[k++]; + d[ind] += soft_input[k++]; #ifdef RM_DEBUG - printf("%d\n",w[ind]); + printf("%d\n", d[ind]); #endif } - while(k",k,ind,w[ind],soft_input[k]); + printf("RM_RX k%u Ind %u(before filler) %d(%d)=>", k, ind, d[ind], soft_input[k]); #endif - w[ind]+=soft_input[k++]; + d[ind] += soft_input[k++]; #ifdef RM_DEBUG - printf("%d\n",w[ind]); + printf("%d\n", d[ind]); #endif } - for (ind=Foffset+F; (ind",k,ind,w[ind],soft_input[k]); + printf("RM_RX (after filler) k%u Ind: %u (%d)(soft in %d)=>", k, ind, d[ind], soft_input[k]); #endif - w[ind] += soft_input[k++]; + d[ind] += soft_input[k++]; #ifdef RM_DEBUG - printf("%d\n",w[ind]); + printf("%d\n", d[ind]); #endif } } return 0; } - diff --git a/openair1/PHY/CODING/nrLDPC_coding/nrLDPC_coding_segment/nr_rate_matching.h b/openair1/PHY/CODING/nrLDPC_coding/nrLDPC_coding_segment/nr_rate_matching.h new file mode 100644 index 0000000000..ac6a496801 --- /dev/null +++ b/openair1/PHY/CODING/nrLDPC_coding/nrLDPC_coding_segment/nr_rate_matching.h @@ -0,0 +1,97 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +#ifndef __NR_RATE_MATCHING__H__ +#define __NR_RATE_MATCHING__H__ + +#include + +#define NR_NULL 2 + +/** + * \brief interleave a code segment after encoding and rate matching + * \param E size of the code segment in bits + * \param Qm modulation order + * \param e input rate matched segment + * \param f output interleaved segment + */ +void nr_interleaving_ldpc(uint32_t E, uint8_t Qm, uint8_t *e, uint8_t *f); + +/** + * \brief deinterleave a code segment before RX rate matching and decoding + * \param E size of the code segment in bits + * \param Qm modulation order + * \param e output deinterleaved segment + * \param f input llr segment + */ +void nr_deinterleaving_ldpc(uint32_t E, uint8_t Qm, int16_t *e, int16_t *f); + +/** + * \brief rate match a code segment after encoding + * \Tbslbrm Transport Block size LBRM + * \param BG LDPC base graph number + * \param Z segment lifting size + * \param d input encoded segment + * \param e output rate matched segment + * \param C number of segments in the Transport Block + * \param F number of filler bits in the segment + * \param Foffset offset of the filler bits in the segment + * \param rvidx redundancy version index + * \param E size of the code segment in bits + */ +int nr_rate_matching_ldpc(uint32_t Tbslbrm, + uint8_t BG, + uint16_t Z, + uint8_t *d, + uint8_t *e, + uint8_t C, + uint32_t F, + uint32_t Foffset, + uint8_t rvidx, + uint32_t E); + +/** + * \brief rate match a code segment before decoding + * \Tbslbrm Transport Block size LBRM + * \param BG LDPC base graph number + * \param Z segment lifting size + * \param d output rate matched segment + * \param soft_input input deinterleaved segment + * \param C number of segments in the Transport Block + * \param rvidx redundancy version index + * \param clear flag to clear d on the first round of a new HARQ process + * \param E size of the code segment in bits + * \param F number of filler bits in the segment + * \param Foffset offset of the filler bits in the segment + */ +int nr_rate_matching_ldpc_rx(uint32_t Tbslbrm, + uint8_t BG, + uint16_t Z, + int16_t *d, + int16_t *soft_input, + uint8_t C, + uint8_t rvidx, + uint8_t clear, + uint32_t E, + uint32_t F, + uint32_t Foffset); + +#endif diff --git a/openair1/PHY/CODING/nrLDPC_coding/nrLDPC_coding_xdma/CMakeLists.txt b/openair1/PHY/CODING/nrLDPC_coding/nrLDPC_coding_xdma/CMakeLists.txt index 4e7d79f6d7..8c357c75d4 100644 --- a/openair1/PHY/CODING/nrLDPC_coding/nrLDPC_coding_xdma/CMakeLists.txt +++ b/openair1/PHY/CODING/nrLDPC_coding/nrLDPC_coding_xdma/CMakeLists.txt @@ -12,7 +12,9 @@ if (ENABLE_LDPC_XDMA) nrLDPC_coding_xdma.c ../nrLDPC_coding_segment/nrLDPC_coding_segment_encoder.c ../../nrLDPC_load.c + ../nrLDPC_coding_segment/nr_rate_matching.c ) + target_include_directories(ldpc_xdma PRIVATE ../nrLDPC_coding_segment) set_target_properties(ldpc_xdma PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}) add_dependencies(nr-softmodem ldpc_xdma) diff --git a/openair1/PHY/CODING/nrLDPC_coding/nrLDPC_coding_xdma/nrLDPC_coding_xdma.c b/openair1/PHY/CODING/nrLDPC_coding/nrLDPC_coding_xdma/nrLDPC_coding_xdma.c index 057fb58f6a..6422eaba0c 100644 --- a/openair1/PHY/CODING/nrLDPC_coding/nrLDPC_coding_xdma/nrLDPC_coding_xdma.c +++ b/openair1/PHY/CODING/nrLDPC_coding/nrLDPC_coding_xdma/nrLDPC_coding_xdma.c @@ -27,6 +27,7 @@ // [from gNB coding] #include +#include #include "PHY/CODING/coding_defs.h" #include "PHY/CODING/coding_extern.h" #include "PHY/CODING/lte_interleaver_inline.h" diff --git a/openair1/PHY/CODING/nrLDPC_load.c b/openair1/PHY/CODING/nrLDPC_load.c index b80887c327..0316ebadc5 100644 --- a/openair1/PHY/CODING/nrLDPC_load.c +++ b/openair1/PHY/CODING/nrLDPC_load.c @@ -29,7 +29,7 @@ * \note * \warning */ -#define _GNU_SOURCE +#define _GNU_SOURCE #include #include #include @@ -41,7 +41,7 @@ /* arguments used when called from phy simulators exec's which do not use the config module */ /* arg is used to initialize the config module so that the loader works as expected */ -char *arg[64]={"ldpctest",NULL}; +char *arg[64] = {"ldpctest", NULL}; int load_LDPClib(char *version, ldpc_interface_t *itf) { diff --git a/openair1/PHY/NR_TRANSPORT/nr_tbs_tools.c b/openair1/PHY/NR_TRANSPORT/nr_tbs_tools.c index b882828cd6..378dca796c 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_tbs_tools.c +++ b/openair1/PHY/NR_TRANSPORT/nr_tbs_tools.c @@ -20,45 +20,74 @@ */ /*! \file PHY/NR_TRANSPORT/nr_tbs_tools.c -* \brief Top-level routines for implementing LDPC-coded (DLSCH) transport channels from 38-212, 15.2 -* \author H.Wang -* \date 2018 -* \version 0.1 -* \company Eurecom -* \email: -* \note -* \warning -*/ + * \brief Top-level routines for implementing LDPC-coded (DLSCH) transport channels from 38-212, 15.2 + * \author H.Wang + * \date 2018 + * \version 0.1 + * \company Eurecom + * \email: + * \note + * \warning + */ #include "nr_transport_common_proto.h" #include "PHY/CODING/coding_defs.h" #include "PHY/defs_nr_common.h" -uint32_t nr_get_G(uint16_t nb_rb, - uint16_t nb_symb_sch, - uint8_t nb_re_dmrs, - uint16_t length_dmrs, - uint32_t unav_res, - uint8_t Qm, - uint8_t Nl) +uint32_t +nr_get_G(uint16_t nb_rb, uint16_t nb_symb_sch, uint8_t nb_re_dmrs, uint16_t length_dmrs, uint32_t unav_res, uint8_t Qm, uint8_t Nl) { uint32_t G = ((NR_NB_SC_PER_RB * nb_symb_sch) - (nb_re_dmrs * length_dmrs)) * nb_rb * Qm * Nl; G -= unav_res * Qm * Nl; - return(G); + return (G); } uint32_t nr_get_E(uint32_t G, uint8_t C, uint8_t Qm, uint8_t Nl, uint8_t r) { uint32_t E; - uint8_t Cprime = C; //assume CBGTI not present + uint8_t Cprime = C; // assume CBGTI not present AssertFatal(Nl > 0, "Nl is 0\n"); AssertFatal(Qm > 0, "Qm is 0\n"); if (r <= Cprime - ((G / (Nl * Qm)) % Cprime) - 1) - E = Nl * Qm * (G / (Nl * Qm * Cprime)); + E = Nl * Qm * (G / (Nl * Qm * Cprime)); else - E = Nl * Qm * ((G / (Nl * Qm * Cprime)) + 1); + E = Nl * Qm * ((G / (Nl * Qm * Cprime)) + 1); - LOG_D(PHY,"nr_get_E : (G %d, C %d, Qm %d, Nl %d, r %d), E %d\n",G, C, Qm, Nl, r, E); + LOG_D(PHY, "nr_get_E : (G %d, C %d, Qm %d, Nl %d, r %d), E %d\n", G, C, Qm, Nl, r, E); return E; } + +static const uint8_t index_k0[2][4] = {{0, 17, 33, 56}, {0, 13, 25, 43}}; + +int nr_get_R_ldpc_decoder(int rvidx, int E, int BG, int Z, int *llrLen, int round) +{ + AssertFatal(BG == 1 || BG == 2, "Unknown BG %d\n", BG); + + int Ncb = (BG == 1) ? (66 * Z) : (50 * Z); + int infoBits = (index_k0[BG - 1][rvidx] * Z + E); + + if (round == 0) + *llrLen = infoBits; + if (infoBits > Ncb) + infoBits = Ncb; + if (infoBits > *llrLen) + *llrLen = infoBits; + + int sysBits = (BG == 1) ? (22 * Z) : (10 * Z); + float decoderR = (float)sysBits / (infoBits + 2 * Z); + + if (BG == 2) + if (decoderR < 0.3333) + return 15; + else if (decoderR < 0.6667) + return 13; + else + return 23; + else if (decoderR < 0.6667) + return 13; + else if (decoderR < 0.8889) + return 23; + else + return 89; +}