fix(nrLDPC_coding_segment): move rate matching, interleaving and their counterparts to segment coding implementation
This commit is contained in:
+2
-4
@@ -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/
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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})
|
||||
|
||||
|
||||
+1
@@ -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"
|
||||
|
||||
+1
@@ -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"
|
||||
|
||||
+217
-250
@@ -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<end ){
|
||||
*e++ = *f++;
|
||||
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 < end) {
|
||||
*e++ = *f++;
|
||||
*e1++ = *f++;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
{
|
||||
AssertFatal(E%4==0,"");
|
||||
int16_t *e1=e+(E/4);
|
||||
int16_t *e2=e1+(E/4);
|
||||
int16_t *e3=e2+(E/4);
|
||||
int16_t *end=f+E-3;
|
||||
while( f<end ){
|
||||
*e++ = *f++;
|
||||
} break;
|
||||
case 4: {
|
||||
AssertFatal(E % 4 == 0, "");
|
||||
int16_t *e1 = e + (E / 4);
|
||||
int16_t *e2 = e1 + (E / 4);
|
||||
int16_t *e3 = e2 + (E / 4);
|
||||
int16_t *end = f + E - 3;
|
||||
while (f < end) {
|
||||
*e++ = *f++;
|
||||
*e1++ = *f++;
|
||||
*e2++ = *f++;
|
||||
*e3++ = *f++;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 6:
|
||||
{
|
||||
AssertFatal(E%6==0,"");
|
||||
int16_t *e1=e+(E/6);
|
||||
int16_t *e2=e1+(E/6);
|
||||
int16_t *e3=e2+(E/6);
|
||||
int16_t *e4=e3+(E/6);
|
||||
int16_t *e5=e4+(E/6);
|
||||
int16_t *end=f+E-5;
|
||||
while( f<end ){
|
||||
*e++ = *f++;
|
||||
} break;
|
||||
case 6: {
|
||||
AssertFatal(E % 6 == 0, "");
|
||||
int16_t *e1 = e + (E / 6);
|
||||
int16_t *e2 = e1 + (E / 6);
|
||||
int16_t *e3 = e2 + (E / 6);
|
||||
int16_t *e4 = e3 + (E / 6);
|
||||
int16_t *e5 = e4 + (E / 6);
|
||||
int16_t *end = f + E - 5;
|
||||
while (f < end) {
|
||||
*e++ = *f++;
|
||||
*e1++ = *f++;
|
||||
*e2++ = *f++;
|
||||
*e3++ = *f++;
|
||||
*e4++ = *f++;
|
||||
*e5++ = *f++;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 8:
|
||||
{
|
||||
AssertFatal(E%8==0,"");
|
||||
int16_t *e1=e+(E/8);
|
||||
int16_t *e2=e1+(E/8);
|
||||
int16_t *e3=e2+(E/8);
|
||||
int16_t *e4=e3+(E/8);
|
||||
int16_t *e5=e4+(E/8);
|
||||
int16_t *e6=e5+(E/8);
|
||||
int16_t *e7=e6+(E/8);
|
||||
int16_t *end=f+E-7;
|
||||
while( f<end ){
|
||||
*e++ = *f++;
|
||||
} break;
|
||||
case 8: {
|
||||
AssertFatal(E % 8 == 0, "");
|
||||
int16_t *e1 = e + (E / 8);
|
||||
int16_t *e2 = e1 + (E / 8);
|
||||
int16_t *e3 = e2 + (E / 8);
|
||||
int16_t *e4 = e3 + (E / 8);
|
||||
int16_t *e5 = e4 + (E / 8);
|
||||
int16_t *e6 = e5 + (E / 8);
|
||||
int16_t *e7 = e6 + (E / 8);
|
||||
int16_t *end = f + E - 7;
|
||||
while (f < end) {
|
||||
*e++ = *f++;
|
||||
*e1++ = *f++;
|
||||
*e2++ = *f++;
|
||||
*e3++ = *f++;
|
||||
@@ -378,136 +362,112 @@ void nr_deinterleaving_ldpc(uint32_t E, uint8_t Qm, int16_t *e,int16_t *f)
|
||||
*e6++ = *f++;
|
||||
*e7++ = *f++;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
AssertFatal(1==0,"Should not get here : Qm %d\n",Qm);
|
||||
break;
|
||||
} break;
|
||||
default:
|
||||
AssertFatal(1 == 0, "Should not get here : Qm %d\n", Qm);
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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) { // case where we do repetitions (low mcs)
|
||||
for (ind=0; (ind<Ncb)&&(k<E); ind++) {
|
||||
|
||||
while (k < E) { // case where we do repetitions (low mcs)
|
||||
for (ind = 0; (ind < Ncb) && (k < E); ind++) {
|
||||
#ifdef RM_DEBUG
|
||||
printf("RM_TX k%u Ind: %u (%d)\n",k,ind,w[ind]);
|
||||
printf("RM_TX k%u Ind: %u (%d)\n", k, ind, d[ind]);
|
||||
#endif
|
||||
|
||||
if (w[ind] != NR_NULL) e[k++]=w[ind];
|
||||
if (d[ind] != NR_NULL)
|
||||
e[k++] = d[ind];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int nr_rate_matching_ldpc_rx(uint32_t Tbslbrm,
|
||||
uint8_t BG,
|
||||
uint16_t Z,
|
||||
int16_t *w,
|
||||
int16_t *d,
|
||||
int16_t *soft_input,
|
||||
uint8_t C,
|
||||
uint8_t rvidx,
|
||||
@@ -516,89 +476,96 @@ int nr_rate_matching_ldpc_rx(uint32_t Tbslbrm,
|
||||
uint32_t F,
|
||||
uint32_t Foffset)
|
||||
{
|
||||
uint32_t Ncb,ind,k,Nref,N;
|
||||
uint32_t Ncb, ind, k, Nref, N;
|
||||
|
||||
#ifdef RM_DEBUG
|
||||
int nulled=0;
|
||||
int nulled = 0;
|
||||
#endif
|
||||
|
||||
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;
|
||||
else {
|
||||
Nref = (3*Tbslbrm/(2*C)); //R_LBRM = 2/3
|
||||
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;
|
||||
if (Foffset > 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<Foffset)&&(k<E); ind++) {
|
||||
for (; (ind < Foffset) && (k < E); ind++) {
|
||||
#ifdef RM_DEBUG
|
||||
printf("RM_RX k%u Ind %u(before filler): %d (%d)=>",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<Ncb)&&(k<E); ind++) {
|
||||
for (; (ind < Ncb) && (k < E); ind++) {
|
||||
#ifdef RM_DEBUG
|
||||
printf("RM_RX k%u Ind %u(after filler) %d (%d)=>",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<E) {
|
||||
for (ind=0; (ind<Foffset)&&(k<E); ind++) {
|
||||
while (k < E) {
|
||||
for (ind = 0; (ind < Foffset) && (k < E); ind++) {
|
||||
#ifdef RM_DEBUG
|
||||
printf("RM_RX k%u Ind %u(before filler) %d(%d)=>",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<Ncb)&&(k<E); ind++) {
|
||||
for (ind = Foffset + F; (ind < Ncb) && (k < E); ind++) {
|
||||
#ifdef RM_DEBUG
|
||||
printf("RM_RX (after filler) k%u Ind: %u (%d)(soft in %d)=>",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;
|
||||
}
|
||||
|
||||
@@ -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 <stdint.h>
|
||||
|
||||
#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
|
||||
@@ -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)
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
// [from gNB coding]
|
||||
#include <syscall.h>
|
||||
|
||||
#include <nr_rate_matching.h>
|
||||
#include "PHY/CODING/coding_defs.h"
|
||||
#include "PHY/CODING/coding_extern.h"
|
||||
#include "PHY/CODING/lte_interleaver_inline.h"
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
* \note
|
||||
* \warning
|
||||
*/
|
||||
#define _GNU_SOURCE
|
||||
#define _GNU_SOURCE
|
||||
#include <sys/types.h>
|
||||
#include <stdlib.h>
|
||||
#include <malloc.h>
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user