Commit 244355a3 authored by Romain Beurdouche's avatar Romain Beurdouche

fix(nrLDPC_coding_segment): move rate matching, interleaving and their...

fix(nrLDPC_coding_segment): move rate matching, interleaving and their counterparts to segment coding implementation
parent f9bff3d6
......@@ -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);
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);
unsigned char **output_buffers,
unsigned int B,
unsigned int *C,
unsigned int *K,
unsigned int *Zout,
unsigned int *F,
uint8_t BG);
/**
* \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})
......
......@@ -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"
......
......@@ -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"
......
......@@ -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);
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;
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 *)(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 *)(d + ind), E);
k = E;
} else {
memcpy((void *)(e), (void *)(d + ind), Ncb - ind);
k = Ncb - 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;
}
}
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;
}
/*
* 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;
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment