From 268d1c8d1708647dd63d9eddc8001715d7748c81 Mon Sep 17 00:00:00 2001 From: Thomas Schlichter Date: Thu, 7 Feb 2019 11:14:16 +0100 Subject: [PATCH] Fix order of DLSCH deinterleaving and rate matching On the gNB side tha data are first rate-matched and then interleaved. So on the UE side, the received LLRs have to be deinterleaved first before rate-matching. This significantly improved the performance, especially for MCS values > 3. --- openair1/PHY/CODING/coding_defs.h | 33 +-- openair1/PHY/CODING/nr_rate_matching.c | 104 +++----- openair1/PHY/NR_TRANSPORT/nr_dlsch.h | 2 + openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c | 23 +- openair1/PHY/NR_TRANSPORT/nr_tbs_tools.c | 15 ++ .../PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c | 246 +++++++++--------- 6 files changed, 198 insertions(+), 225 deletions(-) diff --git a/openair1/PHY/CODING/coding_defs.h b/openair1/PHY/CODING/coding_defs.h index 2040faf4a2..0f316e7869 100644 --- a/openair1/PHY/CODING/coding_defs.h +++ b/openair1/PHY/CODING/coding_defs.h @@ -467,33 +467,26 @@ 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); -uint32_t nr_rate_matching_ldpc(uint8_t Ilbrm, - uint32_t Tbslbrm, - uint8_t BG, - uint16_t Z, - uint32_t G, - uint8_t *w, - uint8_t *e, - uint8_t C, - uint8_t rvidx, - uint8_t Qm, - uint8_t Nl, - uint8_t r); +int nr_rate_matching_ldpc(uint8_t Ilbrm, + uint32_t Tbslbrm, + uint8_t BG, + uint16_t Z, + uint8_t *w, + uint8_t *e, + uint8_t C, + uint8_t rvidx, + uint32_t E); int nr_rate_matching_ldpc_rx(uint8_t Ilbrm, - uint32_t Tbslbrm, - uint8_t BG, - uint16_t Z, - uint32_t G, + 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, - uint8_t Qm, - uint8_t Nl, - uint8_t r, - uint32_t *E_out); + uint32_t E); decoder_if_t phy_threegpplte_turbo_decoder; decoder_if_t phy_threegpplte_turbo_decoder8; diff --git a/openair1/PHY/CODING/nr_rate_matching.c b/openair1/PHY/CODING/nr_rate_matching.c index 01390f1f2f..0bce31630f 100644 --- a/openair1/PHY/CODING/nr_rate_matching.c +++ b/openair1/PHY/CODING/nr_rate_matching.c @@ -63,55 +63,39 @@ void nr_deinterleaving_ldpc(uint32_t E, uint8_t Qm, int16_t *e,int16_t *f) } -uint32_t nr_rate_matching_ldpc(uint8_t Ilbrm, - uint32_t Tbslbrm, - uint8_t BG, - uint16_t Z, - uint32_t G, - uint8_t *w, - uint8_t *e, - uint8_t C, - uint8_t rvidx, - uint8_t Qm, - uint8_t Nl, - uint8_t r) +int nr_rate_matching_ldpc(uint8_t Ilbrm, + uint32_t Tbslbrm, + uint8_t BG, + uint16_t Z, + uint8_t *w, + uint8_t *e, + uint8_t C, + uint8_t rvidx, + uint32_t E) { - uint8_t Cprime; - uint32_t Ncb,E,ind,k,Nref,N; - //uint8_t *e2; + uint32_t Ncb,ind,k,Nref,N; - AssertFatal(Nl>0,"Nl is 0\n"); - AssertFatal(Qm>0,"Qm is 0\n"); + if (C==0) { + printf("nr_rate_matching: invalid parameters (C %d\n",C); + return -1; + } //Bit selection N = (BG==1)?(66*Z):(50*Z); if (Ilbrm == 0) - Ncb = N; + Ncb = N; else { Nref = 3*Tbslbrm/(2*C); //R_LBRM = 2/3 Ncb = min(N, Nref); } -#ifdef RM_DEBUG - printf("nr_rate_matching: Ncb %d, rvidx %d, G %d, Qm %d, Nl%d, r %d\n",Ncb,rvidx, G, Qm,Nl,r); -#endif - - Cprime = C; //assume CBGTI not present - - if (r <= Cprime - ((G/(Nl*Qm))%Cprime) - 1) - E = Nl*Qm*(G/(Nl*Qm*Cprime)); - else - E = Nl*Qm*((G/(Nl*Qm*Cprime))+1); - ind = (index_k0[BG-1][rvidx]*Ncb/N)*Z; #ifdef RM_DEBUG - printf("nr_rate_matching: E %d, k0 %d Cprime %d modcprime %d\n",E,ind, Cprime,((G/(Nl*Qm))%Cprime)); + printf("nr_rate_matching_ldpc: E %d, k0 %d, Ncb %d, rvidx %d\n", E, ind, Ncb, rvidx); #endif - //e2 = e; - k=0; for (; (ind0,"Nl is 0\n"); - AssertFatal(Qm>0,"Qm is 0\n"); - //Bit selection N = (BG==1)?(66*Z):(50*Z); if (Ilbrm == 0) - Ncb = N; + Ncb = N; else { Nref = (3*Tbslbrm/(2*C)); //R_LBRM = 2/3 Ncb = min(N, Nref); } - Cprime = C; //assume CBGTI not present - - if (r <= Cprime - ((G/(Nl*Qm))%Cprime) - 1) - E = Nl*Qm*(G/(Nl*Qm*Cprime)); - else - E = Nl*Qm*((G/(Nl*Qm*Cprime))+1); - ind = (index_k0[BG-1][rvidx]*Ncb/N)*Z; #ifdef RM_DEBUG - printf("nr_rate_matching_ldpc_rx: Clear %d, E %d, Ncb %d,rvidx %d, G %d, Qm %d, Nl%d, r %d\n",clear,E,Ncb,rvidx, G, Qm,Nl,r); + printf("nr_rate_matching_ldpc_rx: Clear %d, E %d, k0 %d, Ncb %d, rvidx %d\n", clear, E, ind, Ncb, rvidx); #endif if (clear==1) memset(w,0,Ncb*sizeof(int16_t)); - soft_input2 = soft_input; k=0; for (; (indharq_processes[harq_pid]->d[r], - dlsch->harq_processes[harq_pid]->e+r_offset, - dlsch->harq_processes[harq_pid]->C, - rel15.redundancy_version, - mod_order, - rel15.nb_layers, - r); + E = nr_get_E(G, dlsch->harq_processes[harq_pid]->C, mod_order, rel15.nb_layers, r); + + nr_rate_matching_ldpc(Ilbrm, + Tbslbrm, + BG, + *pz, + dlsch->harq_processes[harq_pid]->d[r], + dlsch->harq_processes[harq_pid]->e+r_offset, + dlsch->harq_processes[harq_pid]->C, + rel15.redundancy_version, + E); #ifdef DEBUG_DLSCH_CODING for (int i =0; i<16; i++) diff --git a/openair1/PHY/NR_TRANSPORT/nr_tbs_tools.c b/openair1/PHY/NR_TRANSPORT/nr_tbs_tools.c index 0b8ab56329..f8b7454067 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_tbs_tools.c +++ b/openair1/PHY/NR_TRANSPORT/nr_tbs_tools.c @@ -176,3 +176,18 @@ uint32_t nr_get_G(uint16_t nb_rb, uint16_t nb_symb_sch,uint8_t nb_re_dmrs,uint16 G = ((NR_NB_SC_PER_RB*nb_symb_sch)-(nb_re_dmrs*length_dmrs))*nb_rb*Qm*Nl; 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 + + 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)); + else + E = Nl*Qm*((G/(Nl*Qm*Cprime))+1); + + return E; +} diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c index 610b8305df..2888a59606 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c @@ -376,6 +376,22 @@ uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue, for (r=0; rC; r++) { //printf("start rx segment %d\n",r); + E = nr_get_E(G, harq_process->C, harq_process->Qm, harq_process->Nl, r); + +#if UE_TIMING_TRACE + start_meas(dlsch_deinterleaving_stats); +#endif + nr_deinterleaving_ldpc(E, + harq_process->Qm, + harq_process->w[r], + dlsch_llr+r_offset); + + //for (int i =0; i<16; i++) + // printf("rx output deinterleaving w[%d]= %d r_offset %d\n", i,harq_process->w[r][i], r_offset); + +#if UE_TIMING_TRACE + stop_meas(dlsch_deinterleaving_stats); +#endif #if UE_TIMING_TRACE start_meas(dlsch_rate_unmatching_stats); @@ -394,20 +410,15 @@ uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue, #endif if (nr_rate_matching_ldpc_rx(Ilbrm, - Tbslbrm, - p_decParams->BG, - p_decParams->Z, - G, - harq_process->w[r], - dlsch_llr+r_offset, - harq_process->C, - harq_process->rvidx, - (harq_process->round==0)?1:0, - harq_process->Qm, - harq_process->Nl, - r, - &E)==-1) { - + Tbslbrm, + p_decParams->BG, + p_decParams->Z, + harq_process->d[r], + harq_process->w[r], + harq_process->C, + harq_process->rvidx, + (harq_process->round==0)?1:0, + E)==-1) { #if UE_TIMING_TRACE stop_meas(dlsch_rate_unmatching_stats); #endif @@ -419,27 +430,13 @@ uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue, stop_meas(dlsch_rate_unmatching_stats); #endif } + + //for (int i =0; i<16; i++) + // printf("rx output ratematching d[%d]= %d r_offset %d\n", i,harq_process->d[r][i], r_offset); + r_offset += E; - //for (int i =0; i<16; i++) - // printf("rx output ratematching w[%d]= %d r_offset %d\n", i,harq_process->w[r][i], r_offset); - -#if UE_TIMING_TRACE - start_meas(dlsch_deinterleaving_stats); -#endif - nr_deinterleaving_ldpc(E, - harq_process->Qm, - harq_process->d[r], - harq_process->w[r]); - - //for (int i =0; i<16; i++) - // printf("rx output interleaving d[%d]= %d r_offset %d\n", i,harq_process->d[r][i], r_offset); - -#if UE_TIMING_TRACE - stop_meas(dlsch_deinterleaving_stats); -#endif #ifdef DEBUG_DLSCH_DECODING - if (r==0) { write_output("decoder_llr.m","decllr",dlsch_llr,G,1,0); write_output("decoder_in.m","dec",&harq_process->d[0][0],(3*8*Kr_bytes)+12,1,0); @@ -979,6 +976,30 @@ if (harq_process->C>1) { // wakeup worker if more than 1 segment Tbslbrm = nr_compute_tbs(28,nb_rb,frame_parms->symbols_per_slot,0,0, harq_process->Nl); + E = nr_get_E(G, harq_process->C, harq_process->Qm, harq_process->Nl, r); + + /* + printf("Subblock deinterleaving, dlsch_llr %p, w %p\n", + dlsch_llr+r_offset, + &harq_process->w[r]); + */ +#if UE_TIMING_TRACE + start_meas(dlsch_deinterleaving_stats); +#endif + nr_deinterleaving_ldpc(E, + harq_process->Qm, + harq_process->w[r], + dlsch_llr+r_offset); + +#ifdef DEBUG_DLSCH_DECODING + for (int i =0; i<16; i++) + printf("rx output deinterleaving w[%d]= %d r_offset %d\n", i,harq_process->w[r][i], r_offset); +#endif + +#if UE_TIMING_TRACE + stop_meas(dlsch_deinterleaving_stats); +#endif + #if UE_TIMING_TRACE start_meas(dlsch_rate_unmatching_stats); #endif @@ -995,23 +1016,16 @@ if (harq_process->C>1) { // wakeup worker if more than 1 segment harq_process->round); #endif -#ifdef DEBUG_DLSCH_DECODING - printf(" in decoding dlsch->harq_processes[harq_pid]->rvidx = %d\n", dlsch->harq_processes[harq_pid]->rvidx); -#endif if (nr_rate_matching_ldpc_rx(Ilbrm, - Tbslbrm, - p_decParams->BG, - p_decParams->Z, - G, - harq_process->w[r], - dlsch_llr+r_offset, - harq_process->C, - harq_process->rvidx, - (harq_process->round==0)?1:0, - harq_process->Qm, - harq_process->Nl, - r, - &E)==-1) { + Tbslbrm, + p_decParams->BG, + p_decParams->Z, + harq_process->d[r], + harq_process->w[r], + harq_process->C, + harq_process->rvidx, + (harq_process->round==0)?1:0, + E)==-1) { #if UE_TIMING_TRACE stop_meas(dlsch_rate_unmatching_stats); #endif @@ -1023,34 +1037,18 @@ if (harq_process->C>1) { // wakeup worker if more than 1 segment stop_meas(dlsch_rate_unmatching_stats); #endif } + + //for (int i =0; i<16; i++) + // printf("rx output ratematching d[%d]= %d r_offset %d\n", i,harq_process->d[r][i], r_offset); + //r_offset += E; //printf("main thread r_offset %d\n",r_offset); #ifdef DEBUG_DLSCH_DECODING for (int i =0; i<16; i++) - printf("rx output ratematching w[%d]= %d r_offset %d\n", i,harq_process->w[r][i], r_offset); + printf("rx output ratematching d[%d]= %d r_offset %d\n", i,harq_process->d[r][i], r_offset); #endif - /* - printf("Subblock deinterleaving, d %p w %p\n", - harq_process->d[r], - harq_process->w); - */ -#if UE_TIMING_TRACE - start_meas(dlsch_deinterleaving_stats); -#endif - nr_deinterleaving_ldpc(E, - harq_process->Qm, - harq_process->d[r], - harq_process->w[r]); -#ifdef DEBUG_DLSCH_DECODING - for (int i =0; i<16; i++) - printf("rx output interleaving d[%d]= %d r_offset %d\n", i,harq_process->d[r][i], r_offset); -#endif - -#if UE_TIMING_TRACE - stop_meas(dlsch_deinterleaving_stats); -#endif #ifdef DEBUG_DLSCH_DECODING if (r==0) { @@ -1526,6 +1524,23 @@ void *nr_dlsch_decoding_2thread0(void *arg) Tbslbrm = nr_compute_tbs(28,nb_rb,frame_parms->symbols_per_slot,0,0, harq_process->Nl); + E = nr_get_E(G, harq_process->C, harq_process->Qm, harq_process->Nl, r); + +#if UE_TIMING_TRACE + start_meas(dlsch_deinterleaving_stats); +#endif + nr_deinterleaving_ldpc(E, + harq_process->Qm, + harq_process->w[r], + dlsch_llr+r_offset); + + //for (int i =0; i<16; i++) + // printf("rx output deinterleaving w[%d]= %d r_offset %d\n", i,harq_process->w[r][i], r_offset); + +#if UE_TIMING_TRACE + stop_meas(dlsch_deinterleaving_stats); +#endif + #if UE_TIMING_TRACE start_meas(dlsch_rate_unmatching_stats); #endif @@ -1542,23 +1557,16 @@ void *nr_dlsch_decoding_2thread0(void *arg) harq_process->round); #endif -#ifdef DEBUG_DLSCH_DECODING - printf(" in decoding dlsch->harq_processes[harq_pid]->rvidx = %d\n", dlsch->harq_processes[harq_pid]->rvidx); -#endif if (nr_rate_matching_ldpc_rx(Ilbrm, - Tbslbrm, - p_decParams->BG, - p_decParams->Z, - G, - harq_process->w[r], - dlsch_llr+r_offset, - harq_process->C, - harq_process->rvidx, - (harq_process->round==0)?1:0, - harq_process->Qm, - harq_process->Nl, - r, - &E)==-1) { + Tbslbrm, + p_decParams->BG, + p_decParams->Z, + harq_process->d[r], + harq_process->w[r], + harq_process->C, + harq_process->rvidx, + (harq_process->round==0)?1:0, + E)==-1) { #if UE_TIMING_TRACE stop_meas(dlsch_rate_unmatching_stats); #endif @@ -1570,23 +1578,13 @@ void *nr_dlsch_decoding_2thread0(void *arg) stop_meas(dlsch_rate_unmatching_stats); #endif } - //r_offset += E; //for (int i =0; i<16; i++) - // printf("rx output ratematching w[%d]= %d r_offset %d\n", i,harq_process->w[r][i], r_offset); + // printf("rx output ratematching d[%d]= %d r_offset %d\n", i,harq_process->d[r][i], r_offset); + + //r_offset += E; -#if UE_TIMING_TRACE - start_meas(dlsch_deinterleaving_stats); -#endif - nr_deinterleaving_ldpc(E, - harq_process->Qm, - harq_process->d[r], - harq_process->w[r]); -#if UE_TIMING_TRACE - stop_meas(dlsch_deinterleaving_stats); -#endif #ifdef DEBUG_DLSCH_DECODING - if (r==0) { write_output("decoder_llr.m","decllr",dlsch_llr,G,1,0); write_output("decoder_in.m","dec",&harq_process->d[0][0],(3*8*Kr_bytes)+12,1,0); @@ -2043,6 +2041,28 @@ void *nr_dlsch_decoding_2thread1(void *arg) Tbslbrm = nr_compute_tbs(28,nb_rb,frame_parms->symbols_per_slot,0,0, harq_process->Nl); + E = nr_get_E(G, harq_process->C, harq_process->Qm, harq_process->Nl, r); + + /* + printf("Subblock deinterleaving, d %p w %p\n", + harq_process->d[r], + harq_process->w); + */ +#if UE_TIMING_TRACE + start_meas(dlsch_deinterleaving_stats); +#endif + nr_deinterleaving_ldpc(E, + harq_process->Qm, + harq_process->w[r], + dlsch_llr+r_offset); + + //for (int i =0; i<16; i++) + // printf("rx output deinterleaving w[%d]= %d r_offset %d\n", i,harq_process->w[r][i], r_offset); + +#if UE_TIMING_TRACE + stop_meas(dlsch_deinterleaving_stats); +#endif + #if UE_TIMING_TRACE start_meas(dlsch_rate_unmatching_stats); #endif @@ -2059,23 +2079,16 @@ void *nr_dlsch_decoding_2thread1(void *arg) harq_process->round); #endif -#ifdef DEBUG_DLSCH_DECODING - printf(" in decoding dlsch->harq_processes[harq_pid]->rvidx = %d\n", dlsch->harq_processes[harq_pid]->rvidx); -#endif if (nr_rate_matching_ldpc_rx(Ilbrm, Tbslbrm, p_decParams->BG, p_decParams->Z, - G, + harq_process->d[r], harq_process->w[r], - dlsch_llr+r_offset, harq_process->C, harq_process->rvidx, (harq_process->round==0)?1:0, - harq_process->Qm, - harq_process->Nl, - r, - &E)==-1) { + E)==-1) { #if UE_TIMING_TRACE stop_meas(dlsch_rate_unmatching_stats); #endif @@ -2087,23 +2100,12 @@ void *nr_dlsch_decoding_2thread1(void *arg) stop_meas(dlsch_rate_unmatching_stats); #endif } + + //for (int i =0; i<16; i++) + // printf("rx output ratematching d[%d]= %d r_offset %d\n", i,harq_process->d[r][i], r_offset); + //r_offset += E; - /* - printf("Subblock deinterleaving, d %p w %p\n", - harq_process->d[r], - harq_process->w); - */ -#if UE_TIMING_TRACE - start_meas(dlsch_deinterleaving_stats); -#endif - nr_deinterleaving_ldpc(E, - harq_process->Qm, - harq_process->d[r], - harq_process->w[r]); -#if UE_TIMING_TRACE - stop_meas(dlsch_deinterleaving_stats); -#endif #ifdef DEBUG_DLSCH_DECODING if (r==0) { write_output("decoder_llr.m","decllr",dlsch_llr,G,1,0);