diff --git a/openair1/PHY/LTE_TRANSPORT/dci_tools.c b/openair1/PHY/LTE_TRANSPORT/dci_tools.c index 990c3a1c262c2d381f294539152f631f051188a9..0d933dfd7456f85cb16a2b2350cd8760cd2e477d 100644 --- a/openair1/PHY/LTE_TRANSPORT/dci_tools.c +++ b/openair1/PHY/LTE_TRANSPORT/dci_tools.c @@ -5138,10 +5138,70 @@ int check_dci_format2_2a_coherency(DCI_format_t dci_format, return(1); } +void compute_llr_offset(LTE_DL_FRAME_PARMS *frame_parms, + LTE_UE_PDCCH *pdcch_vars, + LTE_UE_PDSCH *pdsch_vars, + LTE_DL_UE_HARQ_t *dlsch0_harq, + uint8_t nb_rb_alloc, + uint8_t subframe) +{ + uint32_t pbch_pss_sss_re; + uint32_t crs_re; + uint32_t granted_re; + uint32_t data_re; + uint32_t llr_offset; + uint8_t symbol; + uint8_t symbol_mod; + + pdsch_vars->llr_offset[pdcch_vars->num_pdcch_symbols] = 0; + + LOG_I(PHY,"compute_llr_offset: nb RB %d - Qm %d \n", nb_rb_alloc, dlsch0_harq->Qm); + + //dlsch0_harq->rb_alloc_even; + //dlsch0_harq->rb_alloc_odd; + + for(symbol=pdcch_vars->num_pdcch_symbols; symbol<frame_parms->symbols_per_tti; symbol++) + { + symbol_mod = (symbol >= (7-frame_parms->Ncp))? (symbol-(7-frame_parms->Ncp)) : symbol; + if((symbol_mod == 0) || symbol_mod == (4-frame_parms->Ncp)) + { + if (frame_parms->mode1_flag==0) + crs_re = 4; + else + crs_re = 2; + } + else + { + crs_re = 0; + } + + granted_re = nb_rb_alloc * (12-crs_re); + pbch_pss_sss_re = adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,dlsch0_harq->Qm,subframe,symbol); + pbch_pss_sss_re = (double)pbch_pss_sss_re * ((double)(12-crs_re)/12); + data_re = granted_re - pbch_pss_sss_re; + llr_offset = data_re * dlsch0_harq->Qm * 2; + + pdsch_vars->llr_length[symbol] = data_re; + if(symbol < (frame_parms->symbols_per_tti-1)) + pdsch_vars->llr_offset[symbol+1] = pdsch_vars->llr_offset[symbol] + llr_offset; + + //LOG_I(PHY,"Granted Re subframe %d / symbol %d => %d (%d RBs)\n", subframe, symbol_mod, granted_re,dlsch0_harq->nb_rb); + //LOG_I(PHY,"Pbch/PSS/SSS Re subframe %d / symbol %d => %d \n", subframe, symbol_mod, pbch_pss_sss_re); + //LOG_I(PHY,"CRS Re Per PRB subframe %d / symbol %d => %d \n", subframe, symbol_mod, crs_re); + //LOG_I(PHY,"Data Re subframe %d / symbol %d => %d \n", subframe, symbol_mod, data_re); + + + + //LOG_I(PHY,"Data Re subframe %d-symbol %d => llr length %d, llr offset %d \n", subframe, symbol, + // pdsch_vars->llr_length[symbol], pdsch_vars->llr_offset[symbol]); + } +} void prepare_dl_decoding_format1_1A(DCI_format_t dci_format, uint8_t N_RB_DL, DCI_INFO_EXTRACTED_t *pdci_info_extarcted, LTE_DL_FRAME_PARMS *frame_parms, + LTE_UE_PDCCH *pdcch_vars, + LTE_UE_PDSCH *pdsch_vars, uint8_t subframe, uint16_t rnti, uint16_t tc_rnti, @@ -5163,12 +5223,27 @@ void prepare_dl_decoding_format1_1A(DCI_format_t dci_format, uint8_t dai = pdci_info_extarcted->dai; uint8_t NPRB = 0; + uint8_t nb_rb_alloc = 0; if(dci_format == format1A) { if ((rnti==si_rnti) || (rnti==p_rnti) || (rnti==ra_rnti)) { NPRB = (TPC&1) + 2; + switch (N_RB_DL) { + case 6: + nb_rb_alloc = RIV2nb_rb_LUT6[rballoc];//NPRB; + break; + case 25: + nb_rb_alloc = RIV2nb_rb_LUT25[rballoc];//NPRB; + break; + case 50: + nb_rb_alloc = RIV2nb_rb_LUT50[rballoc];//NPRB; + break; + case 100: + nb_rb_alloc = RIV2nb_rb_LUT100[rballoc];//NPRB; + break; + } } else { @@ -5186,6 +5261,7 @@ void prepare_dl_decoding_format1_1A(DCI_format_t dci_format, NPRB = RIV2nb_rb_LUT100[rballoc];//NPRB; break; } + nb_rb_alloc = NPRB; } } else // format1 @@ -5345,7 +5421,6 @@ void prepare_dl_decoding_format1_1A(DCI_format_t dci_format, pdlsch0_harq->rb_alloc_odd[2]= pdlsch0_harq->rb_alloc_even[2]; pdlsch0_harq->rb_alloc_odd[3]= pdlsch0_harq->rb_alloc_even[3]; } - if ((rnti==si_rnti) || (rnti==p_rnti) || (rnti==ra_rnti)) { pdlsch0_harq->TBS = TBStable[mcs1][NPRB-1]; @@ -5359,11 +5434,20 @@ void prepare_dl_decoding_format1_1A(DCI_format_t dci_format, pdlsch0_harq->Qm = get_Qm(mcs1); } } + + compute_llr_offset(frame_parms, + pdcch_vars, + pdsch_vars, + pdlsch0_harq, + nb_rb_alloc, + subframe); } void prepare_dl_decoding_format1C(uint8_t N_RB_DL, DCI_INFO_EXTRACTED_t *pdci_info_extarcted, LTE_DL_FRAME_PARMS *frame_parms, + LTE_UE_PDCCH *pdcch_vars, + LTE_UE_PDSCH *pdsch_vars, uint32_t rnti, uint32_t si_rnti, uint32_t ra_rnti, @@ -5466,6 +5550,14 @@ void prepare_dl_decoding_format1C(uint8_t N_RB_DL, AssertFatal(0,"Format 1C: Unknown N_RB_DL %d\n",frame_parms->N_RB_DL); break; } + + compute_llr_offset(frame_parms, + pdcch_vars, + pdsch_vars, + pdlsch0_harq, + pdlsch0_harq->nb_rb, + subframe); + } void compute_precoding_info_2cw(uint8_t tpmi, uint8_t tbswap, uint16_t pmi_alloc, LTE_DL_FRAME_PARMS *frame_parms, LTE_DL_UE_HARQ_t *dlsch0_harq, LTE_DL_UE_HARQ_t *dlsch1_harq) @@ -5639,6 +5731,8 @@ void compute_precoding_info_format2A(uint8_t tpmi, void prepare_dl_decoding_format2_2A(DCI_format_t dci_format, DCI_INFO_EXTRACTED_t *pdci_info_extarcted, LTE_DL_FRAME_PARMS *frame_parms, + LTE_UE_PDCCH *pdcch_vars, + LTE_UE_PDSCH *pdsch_vars, uint16_t rnti, uint8_t subframe, LTE_DL_UE_HARQ_t *dlsch0_harq, @@ -5890,9 +5984,16 @@ void prepare_dl_decoding_format2_2A(DCI_format_t dci_format, dlsch1_harq->Qm = (mcs2-28)<<1; } -//#ifdef DEBUG_HARQ + + compute_llr_offset(frame_parms, + pdcch_vars, + pdsch_vars, + dlsch0_harq, + dlsch0_harq->nb_rb, + subframe); +#ifdef DEBUG_HARQ printf("[DCI UE]: dlsch0_harq status %d , dlsch1_harq status %d\n", dlsch0_harq->status, dlsch1_harq->status); -//#endif +#endif #ifdef DEBUG_HARQ if (dlsch0 != NULL && dlsch1 != NULL) @@ -5909,6 +6010,8 @@ int generate_ue_dlsch_params_from_dci(int frame, void *dci_pdu, uint16_t rnti, DCI_format_t dci_format, + LTE_UE_PDCCH *pdcch_vars, + LTE_UE_PDSCH *pdsch_vars, LTE_UE_DLSCH_t **dlsch, LTE_DL_FRAME_PARMS *frame_parms, PDSCH_CONFIG_DEDICATED *pdsch_config_dedicated, @@ -5998,6 +6101,8 @@ int generate_ue_dlsch_params_from_dci(int frame, frame_parms->N_RB_DL, &dci_info_extarcted, frame_parms, + pdcch_vars, + pdsch_vars, subframe, rnti, tc_rnti, @@ -6048,6 +6153,8 @@ int generate_ue_dlsch_params_from_dci(int frame, prepare_dl_decoding_format1C(frame_parms->N_RB_DL, &dci_info_extarcted, frame_parms, + pdcch_vars, + pdsch_vars, rnti, si_rnti, ra_rnti, @@ -6099,6 +6206,8 @@ int generate_ue_dlsch_params_from_dci(int frame, frame_parms->N_RB_DL, &dci_info_extarcted, frame_parms, + pdcch_vars, + pdsch_vars, subframe, rnti, tc_rnti, @@ -6153,6 +6262,8 @@ int generate_ue_dlsch_params_from_dci(int frame, prepare_dl_decoding_format2_2A(format2, &dci_info_extarcted, frame_parms, + pdcch_vars, + pdsch_vars, rnti, subframe, dlsch0_harq, @@ -6207,6 +6318,8 @@ int generate_ue_dlsch_params_from_dci(int frame, prepare_dl_decoding_format2_2A(format2A, &dci_info_extarcted, frame_parms, + pdcch_vars, + pdsch_vars, rnti, subframe, dlsch0_harq, diff --git a/openair1/PHY/LTE_TRANSPORT/dlsch_demodulation.c b/openair1/PHY/LTE_TRANSPORT/dlsch_demodulation.c index 6761f6e335d12f6f7fd44a004e931e25d507cbcf..f2a743898431f2ccdc397e20ad1d35e6914bbf25 100644 --- a/openair1/PHY/LTE_TRANSPORT/dlsch_demodulation.c +++ b/openair1/PHY/LTE_TRANSPORT/dlsch_demodulation.c @@ -91,6 +91,7 @@ extern void print_shorts(char *s,int16_t *x); int rx_pdsch(PHY_VARS_UE *ue, + UE_rxtx_proc_t *proc, PDSCH_t type, unsigned char eNB_id, unsigned char eNB_id_i, //if this == ue->n_connected_eNB, we assume MU interference @@ -747,18 +748,35 @@ int rx_pdsch(PHY_VARS_UE *ue, } //printf("LLR dlsch0_harq->Qm %d rx_type %d cw0 %d cw1 %d symbol %d \n",dlsch0_harq->Qm,rx_type,codeword_TB0,codeword_TB1,symbol); + // compute LLRs + // -> // compute @pointer where llrs should filled for this ofdm-symbol + int8_t *pllr_symbol_cw0; + int8_t *pllr_symbol_cw1; + uint32_t llr_offset_symbol; + llr_offset_symbol = pdsch_vars[eNB_id]->llr_offset[symbol]; + pllr_symbol_cw0 = (int8_t*)pdsch_vars[eNB_id]->llr[0]; + pllr_symbol_cw1 = (int8_t*)pdsch_vars[eNB_id]->llr[1]; + pllr_symbol_cw0 += llr_offset_symbol; + pllr_symbol_cw1 += llr_offset_symbol; + + /*LOG_I(PHY,"compute LLRs [AbsSubframe %d.%d-%d] NbRB %d Qm %d LLRs-Length %d LLR-Offset %d @LLR Buff %x @LLR Buff(symb) %x\n", + proc->frame_rx, proc->subframe_rx,symbol, + nb_rb,dlsch0_harq->Qm, + pdsch_vars[eNB_id]->llr_length[symbol], + pdsch_vars[eNB_id]->llr_offset[symbol], + (int16_t*)pdsch_vars[eNB_id]->llr[0], + pllr_symbol);*/ switch (dlsch0_harq->Qm) { case 2 : if ((rx_type==rx_standard) || (codeword_TB0 == -1) || (codeword_TB1 == -1)) { dlsch_qpsk_llr(frame_parms, pdsch_vars[eNB_id]->rxdataF_comp0, - pdsch_vars[eNB_id]->llr[0], + (int16_t*)pllr_symbol_cw0, symbol, first_symbol_flag, nb_rb, adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,2,subframe,symbol), - pdsch_vars[eNB_id]->llr128, beamforming_mode); } else if (rx_type >= rx_IC_single_stream) { @@ -918,12 +936,12 @@ int rx_pdsch(PHY_VARS_UE *ue, if ((rx_type==rx_standard) || (codeword_TB0 == -1) || (codeword_TB1 == -1)) { dlsch_64qam_llr(frame_parms, pdsch_vars[eNB_id]->rxdataF_comp0, - pdsch_vars[eNB_id]->llr[0], + (int16_t*)pllr_symbol_cw0, pdsch_vars[eNB_id]->dl_ch_mag0, pdsch_vars[eNB_id]->dl_ch_magb0, symbol,first_symbol_flag,nb_rb, adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,6,subframe,symbol), - pdsch_vars[eNB_id]->llr128, + pdsch_vars[eNB_id]->llr_offset[symbol], beamforming_mode); } else if (rx_type >= rx_IC_single_stream) { @@ -980,10 +998,10 @@ int rx_pdsch(PHY_VARS_UE *ue, pdsch_vars[eNB_id]->dl_ch_mag0, dl_ch_mag_ptr,//i pdsch_vars[eNB_id]->dl_ch_rho2_ext, - pdsch_vars[eNB_id]->llr[0], + (int16_t*)pllr_symbol_cw0, symbol,first_symbol_flag,nb_rb, adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,6,subframe,symbol), - pdsch_vars[eNB_id]->llr128); + pdsch_vars[eNB_id]->llr_offset[symbol]); if (rx_type==rx_IC_dual_stream) { dlsch_64qam_64qam_llr(frame_parms, rxdataF_comp_ptr, @@ -991,10 +1009,10 @@ int rx_pdsch(PHY_VARS_UE *ue, dl_ch_mag_ptr, pdsch_vars[eNB_id]->dl_ch_mag0,//i pdsch_vars[eNB_id]->dl_ch_rho_ext[harq_pid][round], - pdsch_vars[eNB_id]->llr[1], + (int16_t*)pllr_symbol_cw1, symbol,first_symbol_flag,nb_rb, adjust_G2(frame_parms,dlsch1_harq->rb_alloc_even,6,subframe,symbol), - pdsch_vars[eNB_id]->llr128_2ndstream); + pdsch_vars[eNB_id]->llr_offset[symbol]); } } } @@ -1010,10 +1028,9 @@ int rx_pdsch(PHY_VARS_UE *ue, if (rx_type==rx_standard) { dlsch_qpsk_llr(frame_parms, pdsch_vars[eNB_id]->rxdataF_comp0, - pdsch_vars[eNB_id]->llr[0], + (int16_t*)pllr_symbol_cw0, symbol,first_symbol_flag,nb_rb, adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,2,subframe,symbol), - pdsch_vars[eNB_id]->llr128, beamforming_mode); } break; @@ -1033,12 +1050,12 @@ int rx_pdsch(PHY_VARS_UE *ue, if (rx_type==rx_standard) { dlsch_64qam_llr(frame_parms, pdsch_vars[eNB_id]->rxdataF_comp0, - pdsch_vars[eNB_id]->llr[0], + (int16_t*)pllr_symbol_cw0, pdsch_vars[eNB_id]->dl_ch_mag0, pdsch_vars[eNB_id]->dl_ch_magb0, symbol,first_symbol_flag,nb_rb, adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,6,subframe,symbol), - pdsch_vars[eNB_id]->llr128, + pdsch_vars[eNB_id]->llr_offset[symbol], beamforming_mode); } break; @@ -1096,6 +1113,9 @@ int rx_pdsch(PHY_VARS_UE *ue, 2 * /* ulsch[UE_id]->harq_processes[harq_pid]->nb_rb */ frame_parms->N_RB_UL *12*frame_parms->symbols_per_tti*2)); #endif + if(symbol == (ue->frame_parms.symbols_per_tti>>1)) //(first_symbol_flag) + proc->first_symbol_available = 1; + return(0); } @@ -4604,7 +4624,7 @@ unsigned short dlsch_extract_rbs_dual(int **rxdataF, unsigned char subframe, uint32_t high_speed_flag, LTE_DL_FRAME_PARMS *frame_parms, - MIMO_mode_t mimo_mode) { + MIMO_mode_t mimo_mode) { int prb,nb_rb=0; int prb_off,prb_off2; diff --git a/openair1/PHY/LTE_TRANSPORT/dlsch_llr_computation.c b/openair1/PHY/LTE_TRANSPORT/dlsch_llr_computation.c index e2de78f9caf4b903bb30051095fc83d9774b8b1d..9e102a1c65f4f45ec152650c6118bb1ba79479c2 100644 --- a/openair1/PHY/LTE_TRANSPORT/dlsch_llr_computation.c +++ b/openair1/PHY/LTE_TRANSPORT/dlsch_llr_computation.c @@ -636,7 +636,6 @@ int dlsch_qpsk_llr(LTE_DL_FRAME_PARMS *frame_parms, uint8_t first_symbol_flag, uint16_t nb_rb, uint16_t pbch_pss_sss_adjust, - int16_t **llr32p, uint8_t beamforming_mode) { @@ -645,12 +644,14 @@ int dlsch_qpsk_llr(LTE_DL_FRAME_PARMS *frame_parms, int i,len; uint8_t symbol_mod = (symbol >= (7-frame_parms->Ncp))? (symbol-(7-frame_parms->Ncp)) : symbol; + /* if (first_symbol_flag==1) { llr32 = (uint32_t*)dlsch_llr; } else { llr32 = (uint32_t*)(*llr32p); - } + }*/ + llr32 = (uint32_t*)dlsch_llr; if (!llr32) { msg("dlsch_qpsk_llr: llr is null, symbol %d, llr32=%p\n",symbol, llr32); return(-1); @@ -672,6 +673,13 @@ int dlsch_qpsk_llr(LTE_DL_FRAME_PARMS *frame_parms, //printf("dlsch_qpsk_llr: symbol %d,nb_rb %d, len %d,pbch_pss_sss_adjust %d\n",symbol,nb_rb,len,pbch_pss_sss_adjust); + /*LOG_I(PHY,"dlsch_qpsk_llr: [symb %d / FirstSym %d / Length %d]: @LLR Buff %x, @LLR Buff(symb) %x \n", + symbol, + first_symbol_flag, + len, + dlsch_llr, + llr32);*/ + //printf("ll32p=%p , dlsch_llr=%p, symbol=%d, flag=%d \n", llr32, dlsch_llr, symbol, first_symbol_flag); for (i=0; i<len; i++) { *llr32 = *rxF; @@ -680,7 +688,7 @@ int dlsch_qpsk_llr(LTE_DL_FRAME_PARMS *frame_parms, llr32++; } - *llr32p = (int16_t *)llr32; + //*llr32p = (int16_t *)llr32; return(0); } @@ -1043,7 +1051,8 @@ void dlsch_64qam_llr(LTE_DL_FRAME_PARMS *frame_parms, uint8_t first_symbol_flag, uint16_t nb_rb, uint16_t pbch_pss_sss_adjust, - int16_t **llr_save, + //int16_t **llr_save, + uint32_t llr_offset, uint8_t beamforming_mode) { #if defined(__x86_64__) || defined(__i386__) @@ -1057,11 +1066,18 @@ void dlsch_64qam_llr(LTE_DL_FRAME_PARMS *frame_parms, unsigned char symbol_mod,len_mod4; short *llr; int16_t *llr2; + int8_t *pllr_symbol; + /* if (first_symbol_flag==1) llr = dlsch_llr; else llr = *llr_save; + */ + llr = dlsch_llr; + + pllr_symbol = (int8_t*)dlsch_llr; + pllr_symbol += llr_offset; symbol_mod = (symbol>=(7-frame_parms->Ncp)) ? symbol-(7-frame_parms->Ncp) : symbol; @@ -1085,6 +1101,15 @@ void dlsch_64qam_llr(LTE_DL_FRAME_PARMS *frame_parms, len = (nb_rb*12) - pbch_pss_sss_adjust; } +// printf("dlsch_64qam_llr: symbol %d,nb_rb %d, len %d,pbch_pss_sss_adjust %d\n",symbol,nb_rb,len,pbch_pss_sss_adjust); + +/* LOG_I(PHY,"dlsch_64qam_llr [symb %d / FirstSym %d / Length %d]: @LLR Buff %x \n", + symbol, + first_symbol_flag, + len, + dlsch_llr, + pllr_symbol);*/ + llr2 = llr; llr += (len*6); @@ -1179,7 +1204,6 @@ void dlsch_64qam_llr(LTE_DL_FRAME_PARMS *frame_parms, } - *llr_save = llr; #if defined(__x86_64__) || defined(__i386__) _mm_empty(); _m_empty(); @@ -8794,7 +8818,8 @@ int dlsch_64qam_64qam_llr(LTE_DL_FRAME_PARMS *frame_parms, uint8_t first_symbol_flag, uint16_t nb_rb, uint16_t pbch_pss_sss_adjust, - int16_t **llr16p) + //int16_t **llr16p, + uint32_t llr_offset) { int16_t *rxF = (int16_t*)&rxdataF_comp[0][(symbol*frame_parms->N_RB_DL*12)]; @@ -8803,16 +8828,18 @@ int dlsch_64qam_64qam_llr(LTE_DL_FRAME_PARMS *frame_parms, int16_t *ch_mag_i = (int16_t*)&dl_ch_mag_i[0][(symbol*frame_parms->N_RB_DL*12)]; int16_t *rho = (int16_t*)&rho_i[0][(symbol*frame_parms->N_RB_DL*12)]; int16_t *llr16; + int8_t *pllr_symbol; // pointer where llrs should filled for this ofdm symbol int len; uint8_t symbol_mod = (symbol >= (7-frame_parms->Ncp))? (symbol-(7-frame_parms->Ncp)) : symbol; //first symbol has different structure due to more pilots - if (first_symbol_flag == 1) { + /*if (first_symbol_flag == 1) { llr16 = (int16_t*)dlsch_llr; } else { llr16 = (int16_t*)(*llr16p); - } + }*/ + llr16 = (int16_t*)dlsch_llr; if (!llr16) { msg("dlsch_64qam_64qam_llr: llr is null, symbol %d\n",symbol); return(-1); @@ -8831,6 +8858,18 @@ int dlsch_64qam_64qam_llr(LTE_DL_FRAME_PARMS *frame_parms, len = (nb_rb*12) - pbch_pss_sss_adjust; } + pllr_symbol = (int8_t*)dlsch_llr; + pllr_symbol += llr_offset; + //printf("dlsch_64qam_64qam_llr: symbol %d,nb_rb %d, len %d,pbch_pss_sss_adjust %d\n",symbol,nb_rb,len,pbch_pss_sss_adjust); + /*LOG_I(PHY,"dlsch_64qam_64qam_llr [symb %d / FirstSym %d / Length %d / LLR Offset %d]: @LLR Buff %x, @LLR Buff(symb) %x, , @Compute LLR Buff(symb) %x \n", + symbol, + first_symbol_flag, + len, + llr_offset, + (int16_t*)dlsch_llr, + llr16, + pllr_symbol);*/ + #ifdef __AVX2__ // Round length up to multiple of 16 words @@ -8864,6 +8903,7 @@ int dlsch_64qam_64qam_llr(LTE_DL_FRAME_PARMS *frame_parms, (int32_t *) rho_256i, len); #endif + free16(rxF_256i, sizeof(rxF_256i)); free16(rxF_i_256i, sizeof(rxF_i_256i)); free16(ch_mag_256i, sizeof(ch_mag_256i)); @@ -8881,6 +8921,7 @@ int dlsch_64qam_64qam_llr(LTE_DL_FRAME_PARMS *frame_parms, #endif llr16 += (6*len); - *llr16p = (short *)llr16; + //*llr16p = (short *)llr16; + return(0); } diff --git a/openair1/PHY/LTE_TRANSPORT/proto.h b/openair1/PHY/LTE_TRANSPORT/proto.h index 2100f07805e58cf2a8542837060aa4431bcc0ae5..c4df9f79bebdc39672f01fa4f3c682fd8930029f 100644 --- a/openair1/PHY/LTE_TRANSPORT/proto.h +++ b/openair1/PHY/LTE_TRANSPORT/proto.h @@ -802,7 +802,8 @@ int dlsch_64qam_64qam_llr(LTE_DL_FRAME_PARMS *frame_parms, unsigned char first_symbol_flag, unsigned short nb_rb, uint16_t pbch_pss_sss_adjust, - short **llr16p); + //short **llr16p, + uint32_t llr_offset); /** \brief This function generates log-likelihood ratios (decoder input) for single-stream QPSK received waveforms. @@ -823,7 +824,7 @@ int32_t dlsch_qpsk_llr(LTE_DL_FRAME_PARMS *frame_parms, uint8_t first_symbol_flag, uint16_t nb_rb, uint16_t pbch_pss_sss_adj, - int16_t **llr128p, + //int16_t **llr128p, uint8_t beamforming_mode); /** @@ -912,7 +913,8 @@ void dlsch_64qam_llr(LTE_DL_FRAME_PARMS *frame_parms, uint8_t first_symbol_flag, uint16_t nb_rb, uint16_t pbch_pss_sss_adjust, - int16_t **llr_save, + //int16_t **llr_save, + uint32_t llr_offset, uint8_t beamforming_mode); @@ -1297,6 +1299,7 @@ uint32_t dlsch_decoding_emul(PHY_VARS_UE *phy_vars_ue, @param i_mod Modulation order of the interfering stream */ int32_t rx_pdsch(PHY_VARS_UE *phy_vars_ue, + UE_rxtx_proc_t *proc, PDSCH_t type, uint8_t eNB_id, uint8_t eNB_id_i, @@ -1646,6 +1649,8 @@ int generate_ue_dlsch_params_from_dci(int frame, void *dci_pdu, rnti_t rnti, DCI_format_t dci_format, + LTE_UE_PDCCH *pdcch_vars, + LTE_UE_PDSCH *pdsch_vars, LTE_UE_DLSCH_t **dlsch, LTE_DL_FRAME_PARMS *frame_parms, PDSCH_CONFIG_DEDICATED *pdsch_config_dedicated, diff --git a/openair1/PHY/MODULATION/defs.h b/openair1/PHY/MODULATION/defs.h index da599114a91919c05cb66631bc751c2dc1ce3ab4..d68c157445405521458b38c09b2e466cee9451a3 100644 --- a/openair1/PHY/MODULATION/defs.h +++ b/openair1/PHY/MODULATION/defs.h @@ -78,6 +78,17 @@ int slot_fep_ul(LTE_DL_FRAME_PARMS *frame_parms, unsigned char eNb_id, int no_prefix); +int front_end_fft(PHY_VARS_UE *ue, + unsigned char l, + unsigned char Ns, + int sample_offset, + int no_prefix); + +int front_end_chanEst(PHY_VARS_UE *ue, + unsigned char l, + unsigned char Ns, + int reset_freq_est); + void normal_prefix_mod(int32_t *txdataF,int32_t *txdata,uint8_t nsymb,LTE_DL_FRAME_PARMS *frame_parms); void do_OFDM_mod(int32_t **txdataF, int32_t **txdata, uint32_t frame,uint16_t next_slot, LTE_DL_FRAME_PARMS *frame_parms); diff --git a/openair1/PHY/MODULATION/slot_fep.c b/openair1/PHY/MODULATION/slot_fep.c index 4fc17348410c45fe2454ae238ef885df4406ef8a..6a9bbb354a746fcf291bbcd45e50d3da1371d8cb 100644 --- a/openair1/PHY/MODULATION/slot_fep.c +++ b/openair1/PHY/MODULATION/slot_fep.c @@ -240,3 +240,215 @@ int slot_fep(PHY_VARS_UE *ue, #endif return(0); } + +int front_end_fft(PHY_VARS_UE *ue, + unsigned char l, + unsigned char Ns, + int sample_offset, + int no_prefix) +{ + LTE_DL_FRAME_PARMS *frame_parms = &ue->frame_parms; + LTE_UE_COMMON *common_vars = &ue->common_vars; + unsigned char aa; + unsigned char symbol = l+((7-frame_parms->Ncp)*(Ns&1)); ///symbol within sub-frame + unsigned int nb_prefix_samples = (no_prefix ? 0 : frame_parms->nb_prefix_samples); + unsigned int nb_prefix_samples0 = (no_prefix ? 0 : frame_parms->nb_prefix_samples0); + unsigned int subframe_offset;//,subframe_offset_F; + unsigned int slot_offset; + unsigned int frame_length_samples = frame_parms->samples_per_tti * 10; + unsigned int rx_offset; + + /*LTE_UE_DLSCH_t **dlsch_ue = phy_vars_ue->dlsch_ue[eNB_id]; + unsigned char harq_pid = dlsch_ue[0]->current_harq_pid; + LTE_DL_UE_HARQ_t *dlsch0_harq = dlsch_ue[0]->harq_processes[harq_pid]; + int uespec_pilot[9][1200];*/ + + void (*dft)(int16_t *,int16_t *, int); + int tmp_dft_in[2048] __attribute__ ((aligned (32))); // This is for misalignment issues for 6 and 15 PRBs + + switch (frame_parms->ofdm_symbol_size) { + case 128: + dft = dft128; + break; + + case 256: + dft = dft256; + break; + + case 512: + dft = dft512; + break; + + case 1024: + dft = dft1024; + break; + + case 1536: + dft = dft1536; + break; + + case 2048: + dft = dft2048; + break; + + default: + dft = dft512; + break; + } + + if (no_prefix) { + subframe_offset = frame_parms->ofdm_symbol_size * frame_parms->symbols_per_tti * (Ns>>1); + slot_offset = frame_parms->ofdm_symbol_size * (frame_parms->symbols_per_tti>>1) * (Ns%2); + } else { + subframe_offset = frame_parms->samples_per_tti * (Ns>>1); + slot_offset = (frame_parms->samples_per_tti>>1) * (Ns%2); + } + + // subframe_offset_F = frame_parms->ofdm_symbol_size * frame_parms->symbols_per_tti * (Ns>>1); + + + if (l<0 || l>=7-frame_parms->Ncp) { + printf("slot_fep: l must be between 0 and %d\n",7-frame_parms->Ncp); + return(-1); + } + + if (Ns<0 || Ns>=20) { + printf("slot_fep: Ns must be between 0 and 19\n"); + return(-1); + } + + + + for (aa=0; aa<frame_parms->nb_antennas_rx; aa++) { + memset(&common_vars->common_vars_rx_data_per_thread[(Ns>>1)&0x1].rxdataF[aa][frame_parms->ofdm_symbol_size*symbol],0,frame_parms->ofdm_symbol_size*sizeof(int)); + + rx_offset = sample_offset + slot_offset + nb_prefix_samples0 + subframe_offset - SOFFSET; + // Align with 256 bit + // rx_offset = rx_offset&0xfffffff8; + + if (l==0) { + + if (rx_offset > (frame_length_samples - frame_parms->ofdm_symbol_size)) + memcpy((short *)&common_vars->rxdata[aa][frame_length_samples], + (short *)&common_vars->rxdata[aa][0], + frame_parms->ofdm_symbol_size*sizeof(int)); + + if ((rx_offset&7)!=0) { // if input to dft is not 256-bit aligned, issue for size 6,15 and 25 PRBs + memcpy((void *)tmp_dft_in, + (void *)&common_vars->rxdata[aa][rx_offset % frame_length_samples], + frame_parms->ofdm_symbol_size*sizeof(int)); + dft((int16_t *)tmp_dft_in, + (int16_t *)&common_vars->common_vars_rx_data_per_thread[(Ns>>1)&0x1].rxdataF[aa][frame_parms->ofdm_symbol_size*symbol],1); + } else { // use dft input from RX buffer directly + start_meas(&ue->rx_dft_stats); + + dft((int16_t *)&common_vars->rxdata[aa][(rx_offset) % frame_length_samples], + (int16_t *)&common_vars->common_vars_rx_data_per_thread[(Ns>>1)&0x1].rxdataF[aa][frame_parms->ofdm_symbol_size*symbol],1); + stop_meas(&ue->rx_dft_stats); + + } + } else { + rx_offset += (frame_parms->ofdm_symbol_size+nb_prefix_samples)*l;// + + // (frame_parms->ofdm_symbol_size+nb_prefix_samples)*(l-1); + +#ifdef DEBUG_FEP + // if (ue->frame <100) + LOG_I(PHY,"slot_fep: frame %d: slot %d, symbol %d, nb_prefix_samples %d, nb_prefix_samples0 %d, slot_offset %d, subframe_offset %d, sample_offset %d,rx_offset %d, frame_length_samples %d\n", ue->proc.proc_rxtx[(Ns>>1)&1].frame_rx,Ns, symbol, + nb_prefix_samples,nb_prefix_samples0,slot_offset,subframe_offset,sample_offset,rx_offset,frame_length_samples); +#endif + + if (rx_offset > (frame_length_samples - frame_parms->ofdm_symbol_size)) + memcpy((void *)&common_vars->rxdata[aa][frame_length_samples], + (void *)&common_vars->rxdata[aa][0], + frame_parms->ofdm_symbol_size*sizeof(int)); + + start_meas(&ue->rx_dft_stats); + + if ((rx_offset&7)!=0) { // if input to dft is not 128-bit aligned, issue for size 6 and 15 PRBs + memcpy((void *)tmp_dft_in, + (void *)&common_vars->rxdata[aa][(rx_offset) % frame_length_samples], + frame_parms->ofdm_symbol_size*sizeof(int)); + dft((int16_t *)tmp_dft_in, + (int16_t *)&common_vars->common_vars_rx_data_per_thread[(Ns>>1)&0x1].rxdataF[aa][frame_parms->ofdm_symbol_size*symbol],1); + } else { // use dft input from RX buffer directly + + dft((int16_t *)&common_vars->rxdata[aa][(rx_offset) % frame_length_samples], + (int16_t *)&common_vars->common_vars_rx_data_per_thread[(Ns>>1)&0x1].rxdataF[aa][frame_parms->ofdm_symbol_size*symbol],1); + } + + stop_meas(&ue->rx_dft_stats); + + + } + + #ifdef DEBUG_FEP + // if (ue->frame <100) + printf("slot_fep: frame %d: symbol %d rx_offset %d\n", ue->proc.proc_rxtx[(Ns>>1)&1].frame_rx, symbol,rx_offset); + #endif + } + return(0); +} + +int front_end_chanEst(PHY_VARS_UE *ue, + unsigned char l, + unsigned char Ns, + int reset_freq_est) +{ + LTE_DL_FRAME_PARMS *frame_parms = &ue->frame_parms; + LTE_UE_COMMON *common_vars = &ue->common_vars; + uint8_t eNB_id = 0;//ue_common_vars->eNb_id; + unsigned char aa; + unsigned char symbol = l+((7-frame_parms->Ncp)*(Ns&1)); ///symbol within sub-frame + int i; + + /*LTE_UE_DLSCH_t **dlsch_ue = phy_vars_ue->dlsch_ue[eNB_id]; + unsigned char harq_pid = dlsch_ue[0]->current_harq_pid; + LTE_DL_UE_HARQ_t *dlsch0_harq = dlsch_ue[0]->harq_processes[harq_pid]; + int uespec_pilot[9][1200];*/ + + if (ue->perfect_ce == 0) { + if ((l==0) || (l==(4-frame_parms->Ncp))) { + for (aa=0; aa<frame_parms->nb_antenna_ports_eNB; aa++) { + +#ifdef DEBUG_FEP + printf("Channel estimation eNB %d, aatx %d, slot %d, symbol %d\n",eNB_id,aa,Ns,l); +#endif + start_meas(&ue->dlsch_channel_estimation_stats); + lte_dl_channel_estimation(ue,eNB_id,0, + Ns, + aa, + l, + symbol); + stop_meas(&ue->dlsch_channel_estimation_stats); + + for (i=0; i<ue->measurements.n_adj_cells; i++) { + lte_dl_channel_estimation(ue,eNB_id,i+1, + Ns, + aa, + l, + symbol); + } + } + + + // do frequency offset estimation here! + // use channel estimates from current symbol (=ch_t) and last symbol (ch_{t-1}) +#ifdef DEBUG_FEP + printf("Frequency offset estimation\n"); +#endif + + if (l==(4-frame_parms->Ncp)) { + start_meas(&ue->dlsch_freq_offset_estimation_stats); + lte_est_freq_offset(common_vars->common_vars_rx_data_per_thread[(Ns>>1)&0x1].dl_ch_estimates[0], + frame_parms, + l, + &common_vars->freq_offset, + reset_freq_est); + stop_meas(&ue->dlsch_freq_offset_estimation_stats); + + } + } + + } + return(0); +} diff --git a/openair1/PHY/defs.h b/openair1/PHY/defs.h index 272051000664a4dc4917c5917e9f90b286df2389..55a14923d3ddb9730a5b52f76dfd01d76b07e07b 100644 --- a/openair1/PHY/defs.h +++ b/openair1/PHY/defs.h @@ -392,6 +392,25 @@ typedef struct { pthread_mutex_t mutex_rxtx; /// scheduling parameters for RXn-TXnp4 thread struct sched_param sched_param_rxtx; + + /// internal This variable is protected by ref mutex_fep_slot1. + int instance_cnt_fep_slot1; + /// pthread descriptor fep_slot1 thread + pthread_t pthread_fep_slot1; + /// pthread attributes for fep_slot1 processing thread + pthread_attr_t attr_fep_slot1; + /// condition variable for UE fep_slot1 thread; + pthread_cond_t cond_fep_slot1; + /// mutex for UE synch thread + pthread_mutex_t mutex_fep_slot1; + // + uint8_t chan_est_pilot0_slot1_available; + uint8_t llr_slot1_available; + uint8_t dci_slot0_available; + uint8_t first_symbol_available; + /// scheduling parameters for fep_slot1 thread + struct sched_param sched_param_fep_slot1; + int sub_frame_start; int sub_frame_step; unsigned long long gotIQs; @@ -931,6 +950,14 @@ typedef struct { } PHY_VARS_UE; +/* this structure is used to pass both UE phy vars and + * proc to the function UE_thread_rxn_txnp4 + */ +struct rx_tx_thread_data { + PHY_VARS_UE *UE; + UE_rxtx_proc_t *proc; +}; + void exit_fun(const char* s); static inline int wait_on_condition(pthread_mutex_t *mutex,pthread_cond_t *cond,int *instance_cnt,char *name) { diff --git a/openair1/PHY/impl_defs_lte.h b/openair1/PHY/impl_defs_lte.h index 5707aedd27ccdff32b079a7ce142d77522dddd5e..f40e8ae3e4a6c4e2febb35297e0f212431aaadc1 100644 --- a/openair1/PHY/impl_defs_lte.h +++ b/openair1/PHY/impl_defs_lte.h @@ -925,6 +925,10 @@ typedef struct { //uint32_t *rb_alloc; //uint8_t Qm[2]; //MIMO_mode_t mimo_mode; + // llr offset per ofdm symbol + uint32_t llr_offset[14]; + // llr length per ofdm symbol + uint32_t llr_length[14]; } LTE_UE_PDSCH; typedef struct { diff --git a/openair1/SCHED/defs.h b/openair1/SCHED/defs.h index 10d9d69c5219287de740513132754ca1d77cf10d..bb71e0deb9a1a534f2128cce67b5f34b0a0b8417 100644 --- a/openair1/SCHED/defs.h +++ b/openair1/SCHED/defs.h @@ -140,6 +140,8 @@ void phy_procedures_UE_TX(PHY_VARS_UE *phy_vars_ue,UE_rxtx_proc_t *proc,uint8_t */ int phy_procedures_UE_RX(PHY_VARS_UE *phy_vars_ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,uint8_t abstraction_flag,runmode_t mode,relaying_type_t r_type,PHY_VARS_RN *phy_vars_rn); +void *UE_thread_fep_slot1(void *arg); + /*! \brief Scheduling for UE TX procedures in TDD S-subframes. @param phy_vars_ue Pointer to UE variables on which to act @param eNB_id Local id of eNB on which to act diff --git a/openair1/SCHED/phy_procedures_lte_ue.c b/openair1/SCHED/phy_procedures_lte_ue.c index 389eb5a6943b7fa96a3d4e9f04c40ea43ab2e106..ef1db033e4ca700b4534f1cea62f13ac4ab86133 100644 --- a/openair1/SCHED/phy_procedures_lte_ue.c +++ b/openair1/SCHED/phy_procedures_lte_ue.c @@ -3166,6 +3166,8 @@ int ue_pdcch_procedures(uint8_t eNB_id,PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint (void *)&dci_alloc_rx[i].dci_pdu, ue->pdcch_vars[subframe_rx & 0x1][eNB_id]->crnti, dci_alloc_rx[i].format, + ue->pdcch_vars[subframe_rx & 0x1][eNB_id], + ue->pdsch_vars[subframe_rx & 0x1][eNB_id], ue->dlsch[subframe_rx&0x1][eNB_id], &ue->frame_parms, ue->pdsch_config_dedicated, @@ -3222,6 +3224,8 @@ int ue_pdcch_procedures(uint8_t eNB_id,PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint (void *)&dci_alloc_rx[i].dci_pdu, SI_RNTI, dci_alloc_rx[i].format, + ue->pdcch_vars[subframe_rx & 0x1][eNB_id], + ue->pdsch_vars_SI[eNB_id], &ue->dlsch_SI[eNB_id], &ue->frame_parms, ue->pdsch_config_dedicated, @@ -3253,6 +3257,8 @@ int ue_pdcch_procedures(uint8_t eNB_id,PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint (void *)&dci_alloc_rx[i].dci_pdu, P_RNTI, dci_alloc_rx[i].format, + ue->pdcch_vars[subframe_rx & 0x1][eNB_id], + ue->pdsch_vars_p[eNB_id], &ue->dlsch_SI[eNB_id], &ue->frame_parms, ue->pdsch_config_dedicated, @@ -3289,6 +3295,8 @@ int ue_pdcch_procedures(uint8_t eNB_id,PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint (DCI1A_5MHz_TDD_1_6_t *)&dci_alloc_rx[i].dci_pdu, ue->prach_resources[eNB_id]->ra_RNTI, format1A, + ue->pdcch_vars[subframe_rx & 0x1][eNB_id], + ue->pdsch_vars_ra[eNB_id], &ue->dlsch_ra[eNB_id], &ue->frame_parms, ue->pdsch_config_dedicated, @@ -3647,6 +3655,7 @@ void ue_pdsch_procedures(PHY_VARS_UE *ue, UE_rxtx_proc_t *proc, int eNB_id, PDSC #endif // process DLSCH received in first slot rx_pdsch(ue, + proc, pdsch, eNB_id, eNB_id_i, @@ -4136,19 +4145,72 @@ void ue_dlsch_procedures(PHY_VARS_UE *ue, } -int phy_procedures_UE_RX(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,uint8_t abstraction_flag,runmode_t mode, - relaying_type_t r_type,PHY_VARS_RN *phy_vars_rn) { - - int l,l2; - int pilot1; - int pmch_flag=0; - int frame_rx = proc->frame_rx; - int subframe_rx = proc->subframe_rx; - +#if 0 +/*! + * \brief This is the UE synchronize thread. + * It performs band scanning and synchonization. + * \param arg is a pointer to a \ref PHY_VARS_UE structure. + * \returns a pointer to an int. The storage is not on the heap and must not be freed. + */ +#define FIFO_PRIORITY 40 +void *UE_thread_fep_slot1(void *arg) { + + static __thread int UE_thread_rxtx_retval; + struct rx_tx_thread_data *rtd = arg; + UE_rxtx_proc_t *proc = rtd->proc; + PHY_VARS_UE *ue = rtd->UE; + + char threadname[256]; + proc->subframe_rx=proc->sub_frame_start; + sprintf(threadname,"UE_SLOT1_PROC_%d", proc->sub_frame_start); + cpu_set_t cpuset; + CPU_ZERO(&cpuset); + if ( (proc->sub_frame_start+1)%2 == 0 ) + CPU_SET(0, &cpuset); + if ( (proc->sub_frame_start+1)%2 == 1 ) + CPU_SET(4, &cpuset); + init_thread(900000,1000000 , FIFO_PRIORITY-1, &cpuset, + threadname); + + + uint8_t l; + uint8_t compute_llrs_slot1; + + proc->instance_cnt_fep_slot1=-1; + + while (!oai_exit) { + if (pthread_mutex_lock(&proc->mutex_fep_slot1) != 0) { + LOG_E( PHY, "[SCHED][UE] error locking mutex for UE FEP Slo1\n" ); + exit_fun("nothing to add"); + } + while (proc->instance_cnt_fep_slot1 < 0) { + // most of the time, the thread is waiting here + pthread_cond_wait( &proc->cond_fep_slot1, &proc->mutex_fep_slot1 ); + } + if (pthread_mutex_unlock(&proc->mutex_fep_slot1) != 0) { + LOG_E( PHY, "[SCHED][UE] error unlocking mutex for UE FEP Slo1\n" ); + exit_fun("nothing to add"); + } - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_RX, VCD_FUNCTION_IN); + // Start Thread Processing + LOG_I(PHY," [Th-Slave] ==> execute fep slot1 thread for AbsSubframe %d.%d \n", proc->frame_rx, proc->subframe_rx); +#if 1 + int frame_rx = proc->frame_rx; + int subframe_rx = proc->subframe_rx; + uint8_t pilot0; + uint8_t pilot1; + uint8_t slot1; + + slot1 = (subframe_rx<<1) + 1; + pilot0 = 0; + if (ue->frame_parms.Ncp == 0) { // normal prefix + pilot1 = 4; + } else { // extended prefix + pilot1 = 3; + } +<<<<<<< Updated upstream #if T_TRACER T(T_UE_PHY_DL_TICK, T_INT(ue->Mod_id), T_INT(frame_rx%1024), T_INT(subframe_rx)); @@ -4166,37 +4228,254 @@ int phy_procedures_UE_RX(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,uin start_meas(&ue->phy_proc_rx[subframe_rx&0x1]); start_meas(&ue->generic_stat); #endif +======= + // do first symbol of next downlink subframe for channel estimation + int next_subframe_rx = (1+subframe_rx)%10; + uint8_t next_subframe_slot0 = next_subframe_rx<<1; + // 1- perform FFT for pilot ofdm symbols first (ofdmSym0 next subframe ofdmSym11) + if (subframe_select(&ue->frame_parms,next_subframe_rx) != SF_UL) + { + //LOG_I(PHY,"[Th-Slave] FFT symbol %d slot %d \n", pilot0, next_subframe_slot0); + front_end_fft(ue, + pilot0, + next_subframe_slot0, + 0, + 0); + } + //LOG_I(PHY,"[Th-Slave]FFT symbol %d slot %d \n",pilot1,slot1); + front_end_fft(ue, + pilot1, + slot1, + 0, + 0); + // 2- perform FFT for other ofdm symbols other than pilots + for (l=1; l<ue->frame_parms.symbols_per_tti>>1; l++) + { + if( (l != pilot0) && (l != pilot1)) + { + //LOG_I(PHY,"[Th-Slave]FFT symbol %d slot %d\n",l,slot1); + start_meas(&ue->ofdm_demod_stats); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SLOT_FEP, VCD_FUNCTION_IN); + front_end_fft(ue, + l, + slot1, + 0, + 0); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SLOT_FEP, VCD_FUNCTION_OUT); + stop_meas(&ue->ofdm_demod_stats); + } + } // for l=1..l2 - pmch_flag = is_pmch_subframe(frame_rx,subframe_rx,&ue->frame_parms) ? 1 : 0; + // 3- perform Channel Estimation for slot1 + for (l=1; l<ue->frame_parms.symbols_per_tti>>1; l++) + { + uint32_t wait=0; + if(l==pilot1) + { + LOG_I(PHY,"[Th-Slave] ==> wait pilot0 slot1 channel estimation is ready \n"); + while(proc->chan_est_pilot0_slot1_available==0) + { + //wait until channel estimation for pilot0/slot1 is available + usleep(1); + wait++; + } + } + front_end_chanEst(ue, + l, + slot1, + 0); + //LOG_I(PHY,"[Th-Slave]ChanEst symbol %d slot %d wait%d\n",l,slot1,wait); + ue_measurement_procedures(l-1,ue,proc,0,1+(subframe_rx<<1),0,ue->mode); + } + //LOG_I(PHY,"[Th-Slave]ChanEst symbol %d slot %d\n",0,next_subframe_slot0); + front_end_chanEst(ue, + 0, + next_subframe_slot0, + 0); - // deactivate reception until we scan pdcch - if (ue->dlsch[subframe_rx&0x1][eNB_id][0]) - ue->dlsch[subframe_rx&0x1][eNB_id][0]->active = 0; - if (ue->dlsch[subframe_rx&0x1][eNB_id][1]) - ue->dlsch[subframe_rx&0x1][eNB_id][1]->active = 0; + if ( (subframe_rx == 0) && (ue->decode_MIB == 1)) + { + ue_pbch_procedures(0,ue,proc,0); + } +#endif + LOG_I(PHY," [Th-Slave] ==> FFT/CHanEst Done for AbsSubframe %d.%d \n", proc->frame_rx, proc->subframe_rx); + + LOG_I(PHY," [Th-Slave] ==> Start LLR Comuptation slot1 for AbsSubframe %d.%d \n", proc->frame_rx, proc->subframe_rx); + +#if 1 + // wait until dci info are available + uint32_t wait=0; + while(proc->dci_slot0_available==0) // (proc->dci_slot0_available==0) + { + //wait until channel estimation for pilot0/slot1 is available + usleep(1); + wait++; + } + // check if a dl grant was received on a DCI + compute_llrs_slot1 = 0; + if(ue->dlsch[subframe_rx&0x1][0][0]->active || + ((ue->dlsch_SI[0]) && (ue->dlsch_SI[0]->active == 1)) || + ((ue->dlsch_p[0]) && (ue->dlsch_p[0]->active == 1)) || + ((ue->dlsch_ra[0]) && (ue->dlsch_ra[0]->active == 1)) + ) + { + compute_llrs_slot1 = 1; + } + else + { + proc->llr_slot1_available = 1; + } + LOG_I(PHY,"[Th-Slave] compute llrs slot-1 %d AbsSubframe %d.%d \n",compute_llrs_slot1,frame_rx%1024,subframe_rx); + + if(compute_llrs_slot1) + { + // wait until computation of first ofdm symbol is done + uint32_t wait=0; + while(proc->first_symbol_available==0) + { + //wait until channel estimation for pilot0/slot1 is available + usleep(1); + wait++; + } + + // start slave thread for Pdsch Procedure (slot1) + // do procedures for C-RNTI + //LOG_I(PHY,"[Th-Slave] AbsSubframe %d.%d Pdsch Procedure (slot1) wait %d \n",frame_rx%1024,subframe_rx,wait); + //LOG_I(PHY,"[Th-Slave] AbsSubframe %d.%d Pdsch Procedure PDSCH Active %d \n",frame_rx%1024,subframe_rx, ue->dlsch[subframe_rx&0x1][0][0]->active); + if (ue->dlsch[subframe_rx&0x1][0][0]->active == 1) { + //LOG_I(PHY,"[Th-Slave] AbsSubframe %d.%d Pdsch Procedure PDSCH \n",frame_rx%1024,subframe_rx); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDSCH_PROC, VCD_FUNCTION_IN); + start_meas(&ue->pdsch_procedures_stat); + ue_pdsch_procedures(ue, + proc, + 0, + PDSCH, + ue->dlsch[subframe_rx&0x1][0][0], + NULL, + 1+(ue->frame_parms.symbols_per_tti>>1), + ue->frame_parms.symbols_per_tti-1, + 0); + stop_meas(&ue->pdsch_procedures_stat); + } + + // do procedures for SI-RNTI + if ((ue->dlsch_SI[0]) && (ue->dlsch_SI[0]->active == 1)) { + //LOG_I(PHY,"[Th-Slave] AbsSubframe %d.%d Pdsch Procedure SI-PDSCH \n",frame_rx%1024,subframe_rx); + ue_pdsch_procedures(ue, + proc, + 0, + SI_PDSCH, + ue->dlsch_SI[0], + NULL, + 1+(ue->frame_parms.symbols_per_tti>>1), + ue->frame_parms.symbols_per_tti-1, + 0); + } + + // do procedures for P-RNTI + if ((ue->dlsch_p[0]) && (ue->dlsch_p[0]->active == 1)) { + //LOG_I(PHY,"[Th-Slave] AbsSubframe %d.%d Pdsch Procedure P-PDSCH \n",frame_rx%1024,subframe_rx); + ue_pdsch_procedures(ue, + proc, + 0, + P_PDSCH, + ue->dlsch_p[0], + NULL, + 1+(ue->frame_parms.symbols_per_tti>>1), + ue->frame_parms.symbols_per_tti-1, + 0); + } + // do procedures for RA-RNTI + if ((ue->dlsch_ra[0]) && (ue->dlsch_ra[0]->active == 1)) { + //LOG_I(PHY,"[Th-Slave] AbsSubframe %d.%d Pdsch Procedure RA-PDSCH \n",frame_rx%1024,subframe_rx); + ue_pdsch_procedures(ue, + proc, + 0, + RA_PDSCH, + ue->dlsch_ra[0], + NULL, + 1+(ue->frame_parms.symbols_per_tti>>1), + ue->frame_parms.symbols_per_tti-1, + 0); + } + + //LOG_I(PHY,"Set available llrs slot1 to 1 AbsSubframe %d.%d \n",frame_rx%1024,subframe_rx); + proc->llr_slot1_available = 1; + } +#endif + + LOG_I(PHY," [Th-Slave] ==> End slot1 Thread for AbsSubframe %d.%d \n", proc->frame_rx, proc->subframe_rx); + + // End Thread Processing +>>>>>>> Stashed changes + + if (pthread_mutex_lock(&proc->mutex_fep_slot1) != 0) { + LOG_E( PHY, "[SCHED][UE] error locking mutex for UE RXTX\n" ); + exit_fun("noting to add"); + } + proc->instance_cnt_fep_slot1--; + if (pthread_mutex_unlock(&proc->mutex_fep_slot1) != 0) { + LOG_E( PHY, "[SCHED][UE] error unlocking mutex for UE FEP Slo1\n" ); + exit_fun("noting to add"); + } + } - if (ue->dlsch_SI[eNB_id]) - ue->dlsch_SI[eNB_id]->active = 0; - if (ue->dlsch_p[eNB_id]) - ue->dlsch_p[eNB_id]->active = 0; - if (ue->dlsch_ra[eNB_id]) - ue->dlsch_ra[eNB_id]->active = 0; - -#ifdef DEBUG_PHY_PROC - LOG_D(PHY,"[%s %d] Frame %d subframe %d: Doing phy_procedures_UE_RX\n", - (r_type == multicast_relay) ? "RN/UE" : "UE", - ue->Mod_id,frame_rx, subframe_rx); + // thread finished + free(arg); + return &UE_thread_rxtx_retval; + + +} #endif - if (ue->frame_parms.Ncp == 0) { // normal prefix - pilot1 = 4; - } else { // extended prefix - pilot1 = 3; - } - - +int phy_procedures_UE_RX(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,uint8_t abstraction_flag,runmode_t mode, + relaying_type_t r_type,PHY_VARS_RN *phy_vars_rn) { + + + int l,l2; + int pmch_flag=0; + int frame_rx = proc->frame_rx; + int subframe_rx = proc->subframe_rx; + uint8_t pilot0; + uint8_t pilot1; + uint8_t slot0; + uint8_t slot1; + uint8_t first_ofdm_sym; + + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_RX, VCD_FUNCTION_IN); + + #if T_TRACER + T(T_UE_PHY_DL_TICK, T_INT(ue->Mod_id), T_INT(frame_rx%1024), T_INT(subframe_rx)); + #endif + + + T(T_UE_PHY_INPUT_SIGNAL, T_INT(ue->Mod_id), T_INT(frame_rx%1024), T_INT(subframe_rx), T_INT(0), + T_BUFFER(&ue->common_vars.rxdata[0][subframe_rx*ue->frame_parms.samples_per_tti], + ue->frame_parms.samples_per_tti * 4)); + + // start timers + LOG_I(PHY," ****** start RX-Chain for AbsSubframe %d.%d ****** \n", frame_rx%1024, subframe_rx); + start_meas(&ue->phy_proc_rx[subframe_rx&0x1]); + start_meas(&ue->generic_stat); + + pmch_flag = is_pmch_subframe(frame_rx,subframe_rx,&ue->frame_parms) ? 1 : 0; + + + // deactivate reception until we scan pdcch + if (ue->dlsch[subframe_rx&0x1][eNB_id][0]) + ue->dlsch[subframe_rx&0x1][eNB_id][0]->active = 0; + if (ue->dlsch[subframe_rx&0x1][eNB_id][1]) + ue->dlsch[subframe_rx&0x1][eNB_id][1]->active = 0; + + if (ue->dlsch_SI[eNB_id]) + ue->dlsch_SI[eNB_id]->active = 0; + if (ue->dlsch_p[eNB_id]) + ue->dlsch_p[eNB_id]->active = 0; + if (ue->dlsch_ra[eNB_id]) + ue->dlsch_ra[eNB_id]->active = 0; + if (subframe_select(&ue->frame_parms,subframe_rx) == SF_S) { // S-subframe, do first 5 symbols only l2 = 5; } else if (pmch_flag == 1) { // do first 2 symbols only @@ -4204,399 +4483,453 @@ int phy_procedures_UE_RX(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,uin } else { // normal subframe, last symbol to be processed is the first of the second slot l2 = (ue->frame_parms.symbols_per_tti/2)-1; } - - int prev_subframe_rx = (subframe_rx - 1)<0? 9: (subframe_rx - 1); - if (subframe_select(&ue->frame_parms,prev_subframe_rx) != SF_DL) { - //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - // RX processing of symbols l=0...l2 - //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - l=0; - } else { - //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - // RX processing of symbols l=1...l2 (l=0 is done in last scheduling epoch) - //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - l=1; - } - - LOG_D(PHY," ------ slot 0 Processing: AbsSubframe %d.%d ------ \n", frame_rx%1024, subframe_rx); - LOG_D(PHY," ------ --> FFT/ChannelEst/PDCCH slot 0: AbsSubframe %d.%d ------ \n", frame_rx%1024, subframe_rx); - for (; l<=l2; l++) { - if (abstraction_flag == 0) { -#if UE_TIMING_TRACE - start_meas(&ue->ofdm_demod_stats); -#endif - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SLOT_FEP, VCD_FUNCTION_IN); - slot_fep(ue, - l, - (subframe_rx<<1), - 0, - 0, - 0); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SLOT_FEP, VCD_FUNCTION_OUT); -#if UE_TIMING_TRACE - stop_meas(&ue->ofdm_demod_stats); -#endif - } - ue_measurement_procedures(l-1,ue,proc,eNB_id,(subframe_rx<<1),abstraction_flag,mode); - if ((l==pilot1) || - ((pmch_flag==1)&(l==l2))) { - LOG_D(PHY,"[UE %d] Frame %d: Calling pdcch procedures (eNB %d)\n",ue->Mod_id,frame_rx,eNB_id); - - if (ue_pdcch_procedures(eNB_id,ue,proc,abstraction_flag) == -1) { - LOG_E(PHY,"[UE %d] Frame %d, subframe %d: Error in pdcch procedures\n",ue->Mod_id,frame_rx,subframe_rx); - return(-1); - } - LOG_D(PHY,"num_pdcch_symbols %d\n",ue->pdcch_vars[subframe_rx & 0x1][eNB_id]->num_pdcch_symbols); + int prev_subframe_rx = (subframe_rx - 1)<0? 9: (subframe_rx - 1); + if (subframe_select(&ue->frame_parms,prev_subframe_rx) != SF_DL) { + //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + // RX processing of symbols l=0...l2 + //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + first_ofdm_sym = 0; + } else { + //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + // RX processing of symbols l=1...l2 (l=0 is done in last scheduling epoch) + //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + first_ofdm_sym = 1; + } + slot0 = (subframe_rx<<1); + slot1 = (subframe_rx<<1) + 1; + pilot0 = 0; + if (ue->frame_parms.Ncp == 0) { // normal prefix + pilot1 = 4; + } else { // extended prefix + pilot1 = 3; } - - } // for l=1..l2 - ue_measurement_procedures(l-1,ue,proc,eNB_id,(subframe_rx<<1),abstraction_flag,mode); - - LOG_D(PHY," ------ end FFT/ChannelEst/PDCCH slot 0: AbsSubframe %d.%d ------ \n", frame_rx%1024, subframe_rx); - // If this is PMCH, call procedures and return - if (pmch_flag == 1) { - ue_pmch_procedures(ue,proc,eNB_id,abstraction_flag); - return 0; - } - - slot_fep(ue, - 0, - 1+(subframe_rx<<1), - 0, - 0, - 0); - // first slot has been processed (FFTs + Channel Estimation, PCFICH/PHICH/PDCCH) -#if UE_TIMING_TRACE - stop_meas(&ue->generic_stat); -#if DISABLE_LOG_X - printf("[SFN %d] Slot0: FFT + Channel Estimate + PCFICH/PHICH/PDCCH %5.2f \n",subframe_rx,ue->generic_stat.p_time/(cpuf*1000.0)); -#else - LOG_D(PHY, "[SFN %d] Slot0: FFT + Channel Estimate + PCFICH/PHICH/PDCCH %5.2f \n",subframe_rx,ue->generic_stat.p_time/(cpuf*1000.0)); -#endif + //LOG_I(PHY,"Set available channelEst to 0 AbsSubframe %d.%d \n",frame_rx,subframe_rx); + //LOG_I(PHY,"Set available llrs slot1 to 0 AbsSubframe %d.%d \n",frame_rx,subframe_rx); + //LOG_I(PHY,"Set available dci info slot0 to 0 AbsSubframe %d.%d \n",frame_rx,subframe_rx); + proc->chan_est_pilot0_slot1_available=0; + proc->llr_slot1_available=0; + proc->dci_slot0_available=0; + proc->first_symbol_available=0; + + + //LOG_I(PHY,"fep slot1 thread : instance_cnt %d \n", + // proc->instance_cnt_fep_slot1); + proc->instance_cnt_fep_slot1++; + if (proc->instance_cnt_fep_slot1 == 0) { + LOG_I(PHY,"unblock fep slot1 thread blocked on cond_fep_slot1 : instance_cnt_fep_slot1 %d \n", proc->instance_cnt_fep_slot1 ); + if (pthread_cond_signal(&proc->cond_fep_slot1) != 0) { + LOG_E( PHY, "[SCHED][UE %d] ERROR pthread_cond_signal for UE FEP slot1 thread\n", ue->Mod_id); + exit_fun("nothing to add"); + } + } else { + LOG_E( PHY, "[SCHED][UE %d] UE RX thread busy (IC %d)!!\n", ue->Mod_id, proc->instance_cnt_fep_slot1); + if (proc->instance_cnt_fep_slot1 > 2) + exit_fun("instance_cnt_fep_slot1 > 2"); + } + AssertFatal(pthread_cond_signal(&proc->cond_fep_slot1) ==0 ,""); + AssertFatal(pthread_mutex_unlock(&proc->mutex_fep_slot1) ==0,""); + + /**** FFT Slot0 + Slot1 ****/ + // I- start main thread for FFT/ChanEst symbol: 0/1 --> 7 + + // 1- perform FFT for pilot ofdm symbols first (ofdmSym7 ofdmSym4 or (ofdmSym6 ofdmSym3)) + //LOG_I(PHY,"FFT symbol %d slot %d \n",pilot0,slot1); + front_end_fft(ue, + pilot0, + slot1, + 0, + 0); + //LOG_I(PHY,"FFT symbol %d slot %d \n",pilot1,slot0); + front_end_fft(ue, + pilot1, + slot0, + 0, + 0); + //LOG_I(PHY,"ChanEst symbol %d slot %d\n",pilot1,slot0); + front_end_chanEst(ue, + pilot1, + slot0, + 0); + //LOG_I(PHY,"ChanEst symbol %d slot %d\n",pilot0,slot1); + front_end_chanEst(ue, + pilot0, + slot1, + 0); + proc->chan_est_pilot0_slot1_available = 1; + //LOG_I(PHY,"Set available channelEst to 1 AbsSubframe %d.%d \n",frame_rx,subframe_rx); + // 2- perform FFT for other ofdm symbols other than pilots + for (l=first_ofdm_sym; l<=l2; l++) + { + if( (l != pilot0) && (l != pilot1)) + { + //LOG_I(PHY,"FFT symbol %d slot %d \n", l, slot0); + start_meas(&ue->ofdm_demod_stats); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SLOT_FEP, VCD_FUNCTION_IN); + front_end_fft(ue, + l, + slot0, + 0, + 0); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SLOT_FEP, VCD_FUNCTION_OUT); + stop_meas(&ue->ofdm_demod_stats); + } + } // for l=1..l2 -#endif + // 3- perform Channel Estimation for slot0 + for (l=first_ofdm_sym; l<=l2; l++) + { + if( (l != pilot0) && (l != pilot1)) + { + //LOG_I(PHY,"ChanEst symbol %d slot %d\n",l,slot0); + front_end_chanEst(ue, + l, + slot0, + 0); + } + ue_measurement_procedures(l-1,ue,proc,eNB_id,(subframe_rx<<1),abstraction_flag,mode); + } - LOG_D(PHY," ------ --> PDSCH ChannelComp/LLR slot 0: AbsSubframe %d.%d ------ \n", frame_rx%1024, subframe_rx); -#if UE_TIMING_TRACE - start_meas(&ue->generic_stat); -#endif - // do procedures for C-RNTI - if (ue->dlsch[subframe_rx&0x1][eNB_id][0]->active == 1) { - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDSCH_PROC, VCD_FUNCTION_IN); - ue_pdsch_procedures(ue, - proc, - eNB_id, - PDSCH, - ue->dlsch[subframe_rx&0x1][eNB_id][0], - NULL, - ue->pdcch_vars[subframe_rx & 0x1][eNB_id]->num_pdcch_symbols, - ue->frame_parms.symbols_per_tti>>1, - abstraction_flag); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDSCH_PROC, VCD_FUNCTION_OUT); - } + // PDCCH decoding + if (ue_pdcch_procedures(eNB_id,ue,proc,abstraction_flag) == -1) { + LOG_E(PHY,"[UE %d] Frame %d, subframe %d: Error in pdcch procedures\n",ue->Mod_id,frame_rx,subframe_rx); + return(-1); + } - LOG_D(PHY," ------ end PDSCH ChannelComp/LLR slot 0: AbsSubframe %d.%d ------ \n", frame_rx%1024, subframe_rx); - // do procedures for SI-RNTI - if ((ue->dlsch_SI[eNB_id]) && (ue->dlsch_SI[eNB_id]->active == 1)) { - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDSCH_PROC_SI, VCD_FUNCTION_IN); - ue_pdsch_procedures(ue, - proc, - eNB_id, - SI_PDSCH, - ue->dlsch_SI[eNB_id], - NULL, - ue->pdcch_vars[subframe_rx & 0x1][eNB_id]->num_pdcch_symbols, - ue->frame_parms.symbols_per_tti>>1, - abstraction_flag); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDSCH_PROC_SI, VCD_FUNCTION_OUT); - } + //LOG_I(PHY,"num_pdcch_symbols %d\n",ue->pdcch_vars[subframe_rx & 0x1][eNB_id]->num_pdcch_symbols); + LOG_I(PHY,"Set available dci slot0 to 1 AbsSubframe %d.%d \n",frame_rx%1024,subframe_rx); + proc->dci_slot0_available=1; - // do procedures for SI-RNTI - if ((ue->dlsch_p[eNB_id]) && (ue->dlsch_p[eNB_id]->active == 1)) { - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDSCH_PROC_P, VCD_FUNCTION_IN); - ue_pdsch_procedures(ue, - proc, - eNB_id, - P_PDSCH, - ue->dlsch_p[eNB_id], - NULL, - ue->pdcch_vars[subframe_rx & 0x1][eNB_id]->num_pdcch_symbols, - ue->frame_parms.symbols_per_tti>>1, - abstraction_flag); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDSCH_PROC_P, VCD_FUNCTION_OUT); - } - // do procedures for RA-RNTI - if ((ue->dlsch_ra[eNB_id]) && (ue->dlsch_ra[eNB_id]->active == 1)) { - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDSCH_PROC_RA, VCD_FUNCTION_IN); - ue_pdsch_procedures(ue, - proc, - eNB_id, - RA_PDSCH, - ue->dlsch_ra[eNB_id], - NULL, - ue->pdcch_vars[subframe_rx & 0x1][eNB_id]->num_pdcch_symbols, - ue->frame_parms.symbols_per_tti>>1, - abstraction_flag); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDSCH_PROC_RA, VCD_FUNCTION_OUT); - } - - LOG_D(PHY," ------ slot 1 Processing: AbsSubframe %d.%d ------ \n", frame_rx%1024, subframe_rx); - LOG_D(PHY," ------ --> FFT/ChannelEst/PDCCH slot 1: AbsSubframe %d.%d ------ \n", frame_rx%1024, subframe_rx); - - if (subframe_select(&ue->frame_parms,subframe_rx) != SF_S) { // do front-end processing for second slot, and first symbol of next subframe - for (l=1; l<ue->frame_parms.symbols_per_tti>>1; l++) { - if (abstraction_flag == 0) { -#if UE_TIMING_TRACE - start_meas(&ue->ofdm_demod_stats); -#endif - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SLOT_FEP, VCD_FUNCTION_IN); - slot_fep(ue, - l, - 1+(subframe_rx<<1), - 0, - 0, - 0); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SLOT_FEP, VCD_FUNCTION_OUT); -#if UE_TIMING_TRACE - stop_meas(&ue->ofdm_demod_stats); -#endif - } - - ue_measurement_procedures(l-1,ue,proc,eNB_id,1+(subframe_rx<<1),abstraction_flag,mode); - - } // for l=1..l2 + // If this is PMCH, call procedures and return + if (pmch_flag == 1) { + ue_pmch_procedures(ue,proc,eNB_id,abstraction_flag); + return 0; + } +#if 1 + // II- start slave thread for FFT/ChanEst // do first symbol of next downlink subframe for channel estimation int next_subframe_rx = (1+subframe_rx)%10; + uint8_t next_subframe_slot0 = next_subframe_rx<<1; + // 1- perform FFT for pilot ofdm symbols first (ofdmSym0 next subframe ofdmSym11) if (subframe_select(&ue->frame_parms,next_subframe_rx) != SF_UL) { - slot_fep(ue, - 0, - (next_subframe_rx<<1), - 0, - 0, - 0); + LOG_I(PHY,"FFT symbol %d slot %d \n", pilot0, next_subframe_slot0); + front_end_fft(ue, + pilot0, + next_subframe_slot0, + 0, + 0); } - } // not an S-subframe -#if UE_TIMING_TRACE - stop_meas(&ue->generic_stat); -#if DISABLE_LOG_X - printf("[SFN %d] Slot1: FFT + Channel Estimate + Pdsch Proc Slot0 %5.2f \n",subframe_rx,ue->generic_stat.p_time/(cpuf*1000.0)); -#else - LOG_D(PHY, "[SFN %d] Slot1: FFT + Channel Estimate + Pdsch Proc Slot0 %5.2f \n",subframe_rx,ue->generic_stat.p_time/(cpuf*1000.0)); -#endif - -#endif - - LOG_D(PHY," ------ end FFT/ChannelEst/PDCCH slot 1: AbsSubframe %d.%d ------ \n", frame_rx%1024, subframe_rx); - if ( (subframe_rx == 0) && (ue->decode_MIB == 1)) - { - ue_pbch_procedures(eNB_id,ue,proc,abstraction_flag); - } - - // do procedures for C-RNTI - LOG_D(PHY," ------ --> PDSCH ChannelComp/LLR slot 0: AbsSubframe %d.%d ------ \n", frame_rx%1024, subframe_rx); - if (ue->dlsch[subframe_rx&0x1][eNB_id][0]->active == 1) { - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDSCH_PROC, VCD_FUNCTION_IN); -#if UE_TIMING_TRACE - start_meas(&ue->pdsch_procedures_stat); -#endif - ue_pdsch_procedures(ue, - proc, - eNB_id, - PDSCH, - ue->dlsch[subframe_rx&0x1][eNB_id][0], - NULL, - 1+(ue->frame_parms.symbols_per_tti>>1), - ue->frame_parms.symbols_per_tti-1, - abstraction_flag); - - LOG_D(PHY," ------ end PDSCH ChannelComp/LLR slot 0: AbsSubframe %d.%d ------ \n", frame_rx%1024, subframe_rx); - LOG_D(PHY," ------ --> PDSCH Turbo Decoder slot 0/1: AbsSubframe %d.%d ------ \n", frame_rx%1024, subframe_rx); -#if UE_TIMING_TRACE - stop_meas(&ue->pdsch_procedures_stat); - start_meas(&ue->dlsch_procedures_stat); -#endif - ue_dlsch_procedures(ue, - proc, - eNB_id, - PDSCH, - ue->dlsch[subframe_rx&0x1][eNB_id][0], - ue->dlsch[subframe_rx&0x1][eNB_id][1], - &ue->dlsch_errors[eNB_id], - mode, - abstraction_flag); -#if UE_TIMING_TRACE - stop_meas(&ue->dlsch_procedures_stat); -#if DISABLE_LOG_X - printf("[SFN %d] Slot1: Pdsch Proc %5.2f\n",subframe_rx,ue->pdsch_procedures_stat.p_time/(cpuf*1000.0)); - printf("[SFN %d] Slot0 Slot1: Dlsch Proc %5.2f\n",subframe_rx,ue->dlsch_procedures_stat.p_time/(cpuf*1000.0)); -#else - LOG_D(PHY, "[SFN %d] Slot1: Pdsch Proc %5.2f\n",subframe_rx,ue->pdsch_procedures_stat.p_time/(cpuf*1000.0)); - LOG_D(PHY, "[SFN %d] Slot0 Slot1: Dlsch Proc %5.2f\n",subframe_rx,ue->dlsch_procedures_stat.p_time/(cpuf*1000.0)); -#endif + LOG_I(PHY,"FFT symbol %d slot %d \n",pilot1,slot1); + front_end_fft(ue, + pilot1, + slot1, + 0, + 0); -#endif + // 2- perform FFT for other ofdm symbols other than pilots + for (l=1; l<ue->frame_parms.symbols_per_tti>>1; l++) + { + if( (l != pilot0) && (l != pilot1)) + { + LOG_I(PHY,"FFT symbol %d slot %d\n",l,slot1); + start_meas(&ue->ofdm_demod_stats); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SLOT_FEP, VCD_FUNCTION_IN); + front_end_fft(ue, + l, + slot1, + 0, + 0); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SLOT_FEP, VCD_FUNCTION_OUT); + stop_meas(&ue->ofdm_demod_stats); + } + } // for l=1..l2 - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDSCH_PROC, VCD_FUNCTION_OUT); + // 3- perform Channel Estimation for slot1 + for (l=1; l<ue->frame_parms.symbols_per_tti>>1; l++) + { + if(l == pilot0) + { + //wait until channel estimation for pilot0/slot1 is available + uint32_t wait = 0; + while(proc->chan_est_pilot0_slot1_available == 0) + { + wait++; + } + } + LOG_I(PHY,"ChanEst symbol %d slot %d\n",l,slot1); + front_end_chanEst(ue, + l, + slot1, + 0); + ue_measurement_procedures(l-1,ue,proc,eNB_id,1+(subframe_rx<<1),abstraction_flag,mode); + } + LOG_I(PHY,"ChanEst symbol %d slot %d\n",0,next_subframe_slot0); + front_end_chanEst(ue, + pilot0, + next_subframe_slot0, + 0); - } -#if UE_TIMING_TRACE - start_meas(&ue->generic_stat); + if ( (subframe_rx == 0) && (ue->decode_MIB == 1)) + { + ue_pbch_procedures(eNB_id,ue,proc,abstraction_flag); + } #endif -#if 0 - if(subframe_rx==5 && ue->dlsch[subframe_rx&0x1][eNB_id][0]->harq_processes[ue->dlsch[subframe_rx&0x1][eNB_id][0]->current_harq_pid]->nb_rb > 20){ - //write_output("decoder_llr.m","decllr",dlsch_llr,G,1,0); - //write_output("llr.m","llr", &ue->pdsch_vars[eNB_id]->llr[0][0],(14*nb_rb*12*dlsch1_harq->Qm) - 4*(nb_rb*4*dlsch1_harq->Qm),1,0); + stop_meas(&ue->generic_stat); + printf("------Front-End PROC [SFN %d]: %5.2f ------\n",subframe_rx,ue->generic_stat.p_time/(cpuf*1000.0)); + /**** End Subframe FFT-ChannelEst ****/ + + + /**** Pdsch Procedure Slot0 + Slot1 ****/ + // start main thread for Pdsch Procedure (slot0) + // do procedures for C-RNTI + //LOG_I(PHY,"AbsSubframe %d.%d Pdsch Procedure (slot0)\n",frame_rx%1024,subframe_rx); + //LOG_I(PHY,"AbsSubframe %d.%d Pdsch Procedure PDSCH Active %d \n",frame_rx%1024,subframe_rx, ue->dlsch[subframe_rx&0x1][0][0]->active); + + start_meas(&ue->generic_stat); + if (ue->dlsch[subframe_rx&0x1][eNB_id][0]->active == 1) { + LOG_I(PHY,"AbsSubframe %d.%d Pdsch Procedure PDSCH \n",frame_rx%1024,subframe_rx); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDSCH_PROC, VCD_FUNCTION_IN); + ue_pdsch_procedures(ue, + proc, + eNB_id, + PDSCH, + ue->dlsch[subframe_rx&0x1][eNB_id][0], + NULL, + ue->pdcch_vars[subframe_rx & 0x1][eNB_id]->num_pdcch_symbols, + ue->frame_parms.symbols_per_tti>>1, + abstraction_flag); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDSCH_PROC, VCD_FUNCTION_OUT); + } + + // do procedures for SI-RNTI + if ((ue->dlsch_SI[eNB_id]) && (ue->dlsch_SI[eNB_id]->active == 1)) { + LOG_I(PHY,"AbsSubframe %d.%d Pdsch Procedure SI-PDSCH \n",frame_rx%1024,subframe_rx); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDSCH_PROC_SI, VCD_FUNCTION_IN); + ue_pdsch_procedures(ue, + proc, + eNB_id, + SI_PDSCH, + ue->dlsch_SI[eNB_id], + NULL, + ue->pdcch_vars[subframe_rx & 0x1][eNB_id]->num_pdcch_symbols, + ue->frame_parms.symbols_per_tti>>1, + abstraction_flag); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDSCH_PROC_SI, VCD_FUNCTION_OUT); + } + + // do procedures for SI-RNTI + if ((ue->dlsch_p[eNB_id]) && (ue->dlsch_p[eNB_id]->active == 1)) { + LOG_I(PHY,"AbsSubframe %d.%d Pdsch Procedure P-PDSCH \n",frame_rx%1024,subframe_rx); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDSCH_PROC_P, VCD_FUNCTION_IN); + ue_pdsch_procedures(ue, + proc, + eNB_id, + P_PDSCH, + ue->dlsch_p[eNB_id], + NULL, + ue->pdcch_vars[subframe_rx & 0x1][eNB_id]->num_pdcch_symbols, + ue->frame_parms.symbols_per_tti>>1, + abstraction_flag); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDSCH_PROC_P, VCD_FUNCTION_OUT); + } - write_output("rxdataF0_current.m" , "rxdataF0", &ue->common_vars.common_vars_rx_data_per_thread[subframe_rx&0x1].rxdataF[0][0],14*ue->frame_parms.ofdm_symbol_size,1,1); - //write_output("rxdataF0_previous.m" , "rxdataF0_prev_sss", &ue->common_vars.common_vars_rx_data_per_thread[(subframe_rx+1)&0x1].rxdataF[0][0],14*ue->frame_parms.ofdm_symbol_size,1,1); + // do procedures for RA-RNTI + if ((ue->dlsch_ra[eNB_id]) && (ue->dlsch_ra[eNB_id]->active == 1)) { + LOG_I(PHY,"AbsSubframe %d.%d Pdsch Procedure RA-PDSCH \n",frame_rx%1024,subframe_rx); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDSCH_PROC_RA, VCD_FUNCTION_IN); + ue_pdsch_procedures(ue, + proc, + eNB_id, + RA_PDSCH, + ue->dlsch_ra[eNB_id], + NULL, + ue->pdcch_vars[subframe_rx & 0x1][eNB_id]->num_pdcch_symbols, + ue->frame_parms.symbols_per_tti>>1, + abstraction_flag); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDSCH_PROC_RA, VCD_FUNCTION_OUT); + } - //write_output("rxdataF0_previous.m" , "rxdataF0_prev", &ue->common_vars.common_vars_rx_data_per_thread[(subframe+1)&0x1].rxdataF[0][0],14*ue->frame_parms.ofdm_symbol_size,1,1); + stop_meas(&ue->generic_stat); + printf("------LLR-Slot0 [SFN %d]: %5.2f ------\n",subframe_rx,ue->generic_stat.p_time/(cpuf*1000.0)); + +#if 1 + // start slave thread for Pdsch Procedure (slot1) + // do procedures for C-RNTI + + if (ue->dlsch[subframe_rx&0x1][eNB_id][0]->active == 1) { + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDSCH_PROC, VCD_FUNCTION_IN); + start_meas(&ue->pdsch_procedures_stat); + ue_pdsch_procedures(ue, + proc, + eNB_id, + PDSCH, + ue->dlsch[subframe_rx&0x1][eNB_id][0], + NULL, + 1+(ue->frame_parms.symbols_per_tti>>1), + ue->frame_parms.symbols_per_tti-1, + abstraction_flag); + stop_meas(&ue->pdsch_procedures_stat); + } - write_output("dl_ch_estimates.m", "dl_ch_estimates_sfn5", &ue->common_vars.common_vars_rx_data_per_thread[subframe_rx&0x1].dl_ch_estimates[0][0][0],14*ue->frame_parms.ofdm_symbol_size,1,1); - write_output("dl_ch_estimates_ext.m", "dl_ch_estimatesExt_sfn5", &ue->pdsch_vars[subframe_rx&0x1][0]->dl_ch_estimates_ext[0][0],14*ue->frame_parms.N_RB_DL*12,1,1); - write_output("rxdataF_comp00.m","rxdataF_comp00", &ue->pdsch_vars[subframe_rx&0x1][0]->rxdataF_comp0[0][0],14*ue->frame_parms.N_RB_DL*12,1,1); - //write_output("magDLFirst.m", "magDLFirst", &phy_vars_ue->pdsch_vars[subframe&0x1][0]->dl_ch_mag0[0][0],14*frame_parms->N_RB_DL*12,1,1); - //write_output("magDLSecond.m", "magDLSecond", &phy_vars_ue->pdsch_vars[subframe&0x1][0]->dl_ch_magb0[0][0],14*frame_parms->N_RB_DL*12,1,1); + // do procedures for SI-RNTI + if ((ue->dlsch_SI[eNB_id]) && (ue->dlsch_SI[eNB_id]->active == 1)) { + ue_pdsch_procedures(ue, + proc, + eNB_id, + SI_PDSCH, + ue->dlsch_SI[eNB_id], + NULL, + 1+(ue->frame_parms.symbols_per_tti>>1), + ue->frame_parms.symbols_per_tti-1, + abstraction_flag); + } - AssertFatal (0,""); - } + // do procedures for P-RNTI + if ((ue->dlsch_p[eNB_id]) && (ue->dlsch_p[eNB_id]->active == 1)) { + ue_pdsch_procedures(ue, + proc, + eNB_id, + P_PDSCH, + ue->dlsch_p[eNB_id], + NULL, + 1+(ue->frame_parms.symbols_per_tti>>1), + ue->frame_parms.symbols_per_tti-1, + abstraction_flag); + } + // do procedures for RA-RNTI + if ((ue->dlsch_ra[eNB_id]) && (ue->dlsch_ra[eNB_id]->active == 1)) { + ue_pdsch_procedures(ue, + proc, + eNB_id, + RA_PDSCH, + ue->dlsch_ra[eNB_id], + NULL, + 1+(ue->frame_parms.symbols_per_tti>>1), + ue->frame_parms.symbols_per_tti-1, + abstraction_flag); + } + proc->llr_slot1_available=1; #endif - // do procedures for SI-RNTI - if ((ue->dlsch_SI[eNB_id]) && (ue->dlsch_SI[eNB_id]->active == 1)) { - ue_pdsch_procedures(ue, - proc, - eNB_id, - SI_PDSCH, - ue->dlsch_SI[eNB_id], - NULL, - 1+(ue->frame_parms.symbols_per_tti>>1), - ue->frame_parms.symbols_per_tti-1, - abstraction_flag); - - ue_dlsch_procedures(ue, - proc, - eNB_id, - SI_PDSCH, - ue->dlsch_SI[eNB_id], - NULL, - &ue->dlsch_SI_errors[eNB_id], - mode, - abstraction_flag); - ue->dlsch_SI[eNB_id]->active = 0; - } - - // do procedures for P-RNTI - if ((ue->dlsch_p[eNB_id]) && (ue->dlsch_p[eNB_id]->active == 1)) { - ue_pdsch_procedures(ue, - proc, - eNB_id, - P_PDSCH, - ue->dlsch_p[eNB_id], - NULL, - 1+(ue->frame_parms.symbols_per_tti>>1), - ue->frame_parms.symbols_per_tti-1, - abstraction_flag); - - ue_dlsch_procedures(ue, - proc, - eNB_id, - P_PDSCH, - ue->dlsch_p[eNB_id], - NULL, - &ue->dlsch_p_errors[eNB_id], - mode, - abstraction_flag); - ue->dlsch_p[eNB_id]->active = 0; - } - // do procedures for RA-RNTI - if ((ue->dlsch_ra[eNB_id]) && (ue->dlsch_ra[eNB_id]->active == 1)) { - ue_pdsch_procedures(ue, - proc, - eNB_id, - RA_PDSCH, - ue->dlsch_ra[eNB_id], - NULL, - 1+(ue->frame_parms.symbols_per_tti>>1), - ue->frame_parms.symbols_per_tti-1, - abstraction_flag); - ue_dlsch_procedures(ue, - proc, - eNB_id, - RA_PDSCH, - ue->dlsch_ra[eNB_id], - NULL, - &ue->dlsch_ra_errors[eNB_id], - mode, - abstraction_flag); - ue->dlsch_ra[eNB_id]->active = 0; - } - - // duplicate harq structure - - uint8_t current_harq_pid = ue->dlsch[subframe_rx&0x1][eNB_id][0]->current_harq_pid; - LTE_DL_UE_HARQ_t *current_harq_processes = ue->dlsch[subframe_rx&0x1][eNB_id][0]->harq_processes[current_harq_pid]; - LTE_DL_UE_HARQ_t *harq_processes_dest = ue->dlsch[(subframe_rx+1)&0x1][eNB_id][0]->harq_processes[current_harq_pid]; + start_meas(&ue->generic_stat); + // wait until llr on slot1 are available + uint32_t wait=0; + while(proc->llr_slot1_available==0) + { + //wait until channel estimation for pilot0/slot1 is available + usleep(1); + wait++; + } + stop_meas(&ue->generic_stat); + printf("------ Waiting for LLR-Slot1 [SFN %d]: %5.2f ------\n",subframe_rx,ue->generic_stat.p_time/(cpuf*1000.0)); + + LOG_I(PHY,"==> Start Turbo Decoder wait %d\n", wait); + // Start Turbo decoder + if (ue->dlsch[subframe_rx&0x1][eNB_id][0]->active == 1) { + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDSCH_PROC, VCD_FUNCTION_IN); + start_meas(&ue->dlsch_procedures_stat); + ue_dlsch_procedures(ue, + proc, + eNB_id, + PDSCH, + ue->dlsch[subframe_rx&0x1][eNB_id][0], + ue->dlsch[subframe_rx&0x1][eNB_id][1], + &ue->dlsch_errors[eNB_id], + mode, + abstraction_flag); + stop_meas(&ue->dlsch_procedures_stat); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDSCH_PROC, VCD_FUNCTION_OUT); + } + + // do procedures for SI-RNTI + if ((ue->dlsch_SI[eNB_id]) && (ue->dlsch_SI[eNB_id]->active == 1)) { + ue_dlsch_procedures(ue, + proc, + eNB_id, + SI_PDSCH, + ue->dlsch_SI[eNB_id], + NULL, + &ue->dlsch_SI_errors[eNB_id], + mode, + abstraction_flag); + ue->dlsch_SI[eNB_id]->active = 0; + } + + // do procedures for P-RNTI + if ((ue->dlsch_p[eNB_id]) && (ue->dlsch_p[eNB_id]->active == 1)) { + ue_dlsch_procedures(ue, + proc, + eNB_id, + P_PDSCH, + ue->dlsch_p[eNB_id], + NULL, + &ue->dlsch_p_errors[eNB_id], + mode, + abstraction_flag); + ue->dlsch_p[eNB_id]->active = 0; + } + // do procedures for RA-RNTI + if ((ue->dlsch_ra[eNB_id]) && (ue->dlsch_ra[eNB_id]->active == 1)) { + ue_dlsch_procedures(ue, + proc, + eNB_id, + RA_PDSCH, + ue->dlsch_ra[eNB_id], + NULL, + &ue->dlsch_ra_errors[eNB_id], + mode, + abstraction_flag); + ue->dlsch_ra[eNB_id]->active = 0; + } + printf("------ Turbo Decoding [SFN %d]: %5.2f ------\n",subframe_rx,ue->dlsch_procedures_stat.p_time/(cpuf*1000.0)); + + /**** End Pdsch processing for this subframe ****/ + + if (subframe_rx==9) { + if (frame_rx % 10 == 0) { + if ((ue->dlsch_received[eNB_id] - ue->dlsch_received_last[eNB_id]) != 0) + ue->dlsch_fer[eNB_id] = (100*(ue->dlsch_errors[eNB_id] - ue->dlsch_errors_last[eNB_id]))/(ue->dlsch_received[eNB_id] - ue->dlsch_received_last[eNB_id]); + + ue->dlsch_errors_last[eNB_id] = ue->dlsch_errors[eNB_id]; + ue->dlsch_received_last[eNB_id] = ue->dlsch_received[eNB_id]; + } - harq_status_t *current_harq_ack = &ue->dlsch[subframe_rx&0x1][eNB_id][0]->harq_ack[subframe_rx]; - harq_status_t *harq_ack_dest = &ue->dlsch[(subframe_rx+1)&0x1][eNB_id][0]->harq_ack[subframe_rx]; - copy_harq_proc_struct(harq_processes_dest, current_harq_processes); - copy_ack_struct(harq_ack_dest, current_harq_ack); + ue->bitrate[eNB_id] = (ue->total_TBS[eNB_id] - ue->total_TBS_last[eNB_id])*100; + ue->total_TBS_last[eNB_id] = ue->total_TBS[eNB_id]; + LOG_D(PHY,"[UE %d] Calculating bitrate Frame %d: total_TBS = %d, total_TBS_last = %d, bitrate %f kbits\n", + ue->Mod_id,frame_rx,ue->total_TBS[eNB_id], + ue->total_TBS_last[eNB_id],(float) ue->bitrate[eNB_id]/1000.0); - if (subframe_rx==9) { - if (frame_rx % 10 == 0) { - if ((ue->dlsch_received[eNB_id] - ue->dlsch_received_last[eNB_id]) != 0) - ue->dlsch_fer[eNB_id] = (100*(ue->dlsch_errors[eNB_id] - ue->dlsch_errors_last[eNB_id]))/(ue->dlsch_received[eNB_id] - ue->dlsch_received_last[eNB_id]); + #if UE_AUTOTEST_TRACE + if ((frame_rx % 100 == 0)) { + LOG_I(PHY,"[UE %d] AUTOTEST Metric : UE_DLSCH_BITRATE = %5.2f kbps (frame = %d) \n", ue->Mod_id, (float) ue->bitrate[eNB_id]/1000.0, frame_rx); + } + #endif - ue->dlsch_errors_last[eNB_id] = ue->dlsch_errors[eNB_id]; - ue->dlsch_received_last[eNB_id] = ue->dlsch_received[eNB_id]; } + //printf("after tubo until end of Rx %5.2f \n",ue->generic_stat.p_time/(cpuf*1000.0)); - ue->bitrate[eNB_id] = (ue->total_TBS[eNB_id] - ue->total_TBS_last[eNB_id])*100; - ue->total_TBS_last[eNB_id] = ue->total_TBS[eNB_id]; - LOG_D(PHY,"[UE %d] Calculating bitrate Frame %d: total_TBS = %d, total_TBS_last = %d, bitrate %f kbits\n", - ue->Mod_id,frame_rx,ue->total_TBS[eNB_id], - ue->total_TBS_last[eNB_id],(float) ue->bitrate[eNB_id]/1000.0); - - #if UE_AUTOTEST_TRACE - if ((frame_rx % 100 == 0)) { - LOG_I(PHY,"[UE %d] AUTOTEST Metric : UE_DLSCH_BITRATE = %5.2f kbps (frame = %d) \n", ue->Mod_id, (float) ue->bitrate[eNB_id]/1000.0, frame_rx); - } + #ifdef EMOS + phy_procedures_emos_UE_RX(ue,slot,eNB_id); #endif - } + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_RX, VCD_FUNCTION_OUT); + stop_meas(&ue->phy_proc_rx[subframe_rx&0x1]); -#if UE_TIMING_TRACE - stop_meas(&ue->generic_stat); - printf("after tubo until end of Rx %5.2f \n",ue->generic_stat.p_time/(cpuf*1000.0)); -#endif -#ifdef EMOS - phy_procedures_emos_UE_RX(ue,slot,eNB_id); -#endif + printf("------FULL RX PROC [SFN %d]: %5.2f ------\n",subframe_rx,ue->phy_proc_rx[subframe_rx&0x1].p_time/(cpuf*1000.0)); + LOG_I(PHY," ****** end RX-Chain for AbsSubframe %d.%d ****** \n", frame_rx%1024, subframe_rx); - - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_RX, VCD_FUNCTION_OUT); -#if UE_TIMING_TRACE - stop_meas(&ue->phy_proc_rx[subframe_rx&0x1]); -#if DISABLE_LOG_X - printf("------FULL RX PROC [SFN %d]: %5.2f ------\n",subframe_rx,ue->phy_proc_rx[subframe_rx&0x1].p_time/(cpuf*1000.0)); -#else - LOG_D(PHY, "------FULL RX PROC [SFN %d]: %5.2f ------\n",subframe_rx,ue->phy_proc_rx[subframe_rx&0x1].p_time/(cpuf*1000.0)); -#endif -#endif - LOG_D(PHY," ****** end RX-Chain for AbsSubframe %d.%d ****** \n", frame_rx%1024, subframe_rx); - return (0); -} + return (0); + } #if defined(Rel10) || defined(Rel14) int phy_procedures_RN_UE_RX(uint8_t slot_rx, uint8_t next_slot, relaying_type_t r_type) diff --git a/targets/RT/USER/lte-ue.c b/targets/RT/USER/lte-ue.c index 1ab22b6104a57dfd73b172e2ccb4d1aa594fd82a..aab70aebaa8f621899648863d3a3dc49aa750c89 100644 --- a/targets/RT/USER/lte-ue.c +++ b/targets/RT/USER/lte-ue.c @@ -476,15 +476,6 @@ static void *UE_thread_synch(void *arg) { return &UE_thread_synch_retval; } - -/* this structure is used to pass both UE phy vars and - * proc to the function UE_thread_rxn_txnp4 - */ -struct rx_tx_thread_data { - PHY_VARS_UE *UE; - UE_rxtx_proc_t *proc; -}; - /*! * \brief This is the UE thread for RX subframe n and TX subframe n+4. * This thread performs the phy_procedures_UE_RX() on every received slot. @@ -508,9 +499,9 @@ static void *UE_thread_rxn_txnp4(void *arg) { cpu_set_t cpuset; CPU_ZERO(&cpuset); if ( (proc->sub_frame_start+1)%2 == 0 && threads.even != -1 ) - CPU_SET(threads.even, &cpuset); + CPU_SET(1, &cpuset); if ( (proc->sub_frame_start+1)%2 == 1 && threads.odd != -1 ) - CPU_SET(threads.odd, &cpuset); + CPU_SET(2, &cpuset); init_thread(900000,1000000 , FIFO_PRIORITY-1, &cpuset, threadname); @@ -852,16 +843,273 @@ void *UE_thread(void *arg) { return NULL; } +void *UE_thread_fep_slot1(void *arg) { + + static __thread int UE_thread_rxtx_retval; + struct rx_tx_thread_data *rtd = arg; + UE_rxtx_proc_t *proc = rtd->proc; + PHY_VARS_UE *ue = rtd->UE; + + char threadname[256]; + proc->subframe_rx=proc->sub_frame_start; + sprintf(threadname,"UE_SLOT1_PROC_%d", proc->sub_frame_start); + cpu_set_t cpuset; + CPU_ZERO(&cpuset); + if ( (proc->sub_frame_start+1)%2 == 0 ) + CPU_SET(0, &cpuset); + if ( (proc->sub_frame_start+1)%2 == 1 ) + CPU_SET(4, &cpuset); + init_thread(900000,1000000 , FIFO_PRIORITY-1, &cpuset, + threadname); + + + uint8_t l; + uint8_t compute_llrs_slot1; + + proc->instance_cnt_fep_slot1=-1; + + while (!oai_exit) { + if (pthread_mutex_lock(&proc->mutex_fep_slot1) != 0) { + LOG_E( PHY, "[SCHED][UE] error locking mutex for UE FEP Slo1\n" ); + exit_fun("nothing to add"); + } + while (proc->instance_cnt_fep_slot1 < 0) { + // most of the time, the thread is waiting here + pthread_cond_wait( &proc->cond_fep_slot1, &proc->mutex_fep_slot1 ); + } + if (pthread_mutex_unlock(&proc->mutex_fep_slot1) != 0) { + LOG_E( PHY, "[SCHED][UE] error unlocking mutex for UE FEP Slo1\n" ); + exit_fun("nothing to add"); + } + + // Start Thread Processing + LOG_I(PHY," [Th-Slave] ==> execute fep slot1 thread for AbsSubframe %d.%d \n", proc->frame_rx, proc->subframe_rx); +#if 1 + int frame_rx = proc->frame_rx; + int subframe_rx = proc->subframe_rx; + uint8_t pilot0; + uint8_t pilot1; + uint8_t slot1; + + slot1 = (subframe_rx<<1) + 1; + pilot0 = 0; + if (ue->frame_parms.Ncp == 0) { // normal prefix + pilot1 = 4; + } else { // extended prefix + pilot1 = 3; + } + + // do first symbol of next downlink subframe for channel estimation + int next_subframe_rx = (1+subframe_rx)%10; + uint8_t next_subframe_slot0 = next_subframe_rx<<1; + // 1- perform FFT for pilot ofdm symbols first (ofdmSym0 next subframe ofdmSym11) + if (subframe_select(&ue->frame_parms,next_subframe_rx) != SF_UL) + { + //LOG_I(PHY,"[Th-Slave] FFT symbol %d slot %d \n", pilot0, next_subframe_slot0); + front_end_fft(ue, + pilot0, + next_subframe_slot0, + 0, + 0); + } + //LOG_I(PHY,"[Th-Slave]FFT symbol %d slot %d \n",pilot1,slot1); + front_end_fft(ue, + pilot1, + slot1, + 0, + 0); + // 2- perform FFT for other ofdm symbols other than pilots + for (l=1; l<ue->frame_parms.symbols_per_tti>>1; l++) + { + if( (l != pilot0) && (l != pilot1)) + { + //LOG_I(PHY,"[Th-Slave]FFT symbol %d slot %d\n",l,slot1); + start_meas(&ue->ofdm_demod_stats); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SLOT_FEP, VCD_FUNCTION_IN); + front_end_fft(ue, + l, + slot1, + 0, + 0); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SLOT_FEP, VCD_FUNCTION_OUT); + stop_meas(&ue->ofdm_demod_stats); + } + } // for l=1..l2 + + // 3- perform Channel Estimation for slot1 + for (l=1; l<ue->frame_parms.symbols_per_tti>>1; l++) + { + uint32_t wait=0; + if(l==pilot1) + { + LOG_I(PHY,"[Th-Slave] ==> wait pilot0 slot1 channel estimation is ready \n"); + while(proc->chan_est_pilot0_slot1_available==0) + { + //wait until channel estimation for pilot0/slot1 is available + usleep(1); + wait++; + } + } + front_end_chanEst(ue, + l, + slot1, + 0); + + //LOG_I(PHY,"[Th-Slave]ChanEst symbol %d slot %d wait%d\n",l,slot1,wait); + ue_measurement_procedures(l-1,ue,proc,0,1+(subframe_rx<<1),0,ue->mode); + } + //LOG_I(PHY,"[Th-Slave]ChanEst symbol %d slot %d\n",0,next_subframe_slot0); + front_end_chanEst(ue, + 0, + next_subframe_slot0, + 0); + + if ( (subframe_rx == 0) && (ue->decode_MIB == 1)) + { + ue_pbch_procedures(0,ue,proc,0); + } +#endif + LOG_I(PHY," [Th-Slave] ==> FFT/CHanEst Done for AbsSubframe %d.%d \n", proc->frame_rx, proc->subframe_rx); + + LOG_I(PHY," [Th-Slave] ==> Start LLR Comuptation slot1 for AbsSubframe %d.%d \n", proc->frame_rx, proc->subframe_rx); + +#if 1 + // wait until dci info are available + uint32_t wait=0; + while(proc->dci_slot0_available==0) // (proc->dci_slot0_available==0) + { + //wait until channel estimation for pilot0/slot1 is available + usleep(1); + wait++; + } + // check if a dl grant was received on a DCI + compute_llrs_slot1 = 0; + if(ue->dlsch[subframe_rx&0x1][0][0]->active || + ((ue->dlsch_SI[0]) && (ue->dlsch_SI[0]->active == 1)) || + ((ue->dlsch_p[0]) && (ue->dlsch_p[0]->active == 1)) || + ((ue->dlsch_ra[0]) && (ue->dlsch_ra[0]->active == 1)) + ) + { + compute_llrs_slot1 = 1; + } + else + { + proc->llr_slot1_available = 1; + } + LOG_I(PHY,"[Th-Slave] compute llrs slot-1 %d AbsSubframe %d.%d \n",compute_llrs_slot1,frame_rx%1024,subframe_rx); + + if(compute_llrs_slot1) + { + // wait until computation of first ofdm symbol is done + uint32_t wait=0; + while(proc->first_symbol_available==0) + { + //wait until channel estimation for pilot0/slot1 is available + usleep(1); + wait++; + } + + // start slave thread for Pdsch Procedure (slot1) + // do procedures for C-RNTI + //LOG_I(PHY,"[Th-Slave] AbsSubframe %d.%d Pdsch Procedure (slot1) wait %d \n",frame_rx%1024,subframe_rx,wait); + //LOG_I(PHY,"[Th-Slave] AbsSubframe %d.%d Pdsch Procedure PDSCH Active %d \n",frame_rx%1024,subframe_rx, ue->dlsch[subframe_rx&0x1][0][0]->active); + if (ue->dlsch[subframe_rx&0x1][0][0]->active == 1) { + //LOG_I(PHY,"[Th-Slave] AbsSubframe %d.%d Pdsch Procedure PDSCH \n",frame_rx%1024,subframe_rx); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDSCH_PROC, VCD_FUNCTION_IN); + start_meas(&ue->pdsch_procedures_stat); + ue_pdsch_procedures(ue, + proc, + 0, + PDSCH, + ue->dlsch[subframe_rx&0x1][0][0], + NULL, + 1+(ue->frame_parms.symbols_per_tti>>1), + ue->frame_parms.symbols_per_tti-1, + 0); + stop_meas(&ue->pdsch_procedures_stat); + } + + // do procedures for SI-RNTI + if ((ue->dlsch_SI[0]) && (ue->dlsch_SI[0]->active == 1)) { + //LOG_I(PHY,"[Th-Slave] AbsSubframe %d.%d Pdsch Procedure SI-PDSCH \n",frame_rx%1024,subframe_rx); + ue_pdsch_procedures(ue, + proc, + 0, + SI_PDSCH, + ue->dlsch_SI[0], + NULL, + 1+(ue->frame_parms.symbols_per_tti>>1), + ue->frame_parms.symbols_per_tti-1, + 0); + } + + // do procedures for P-RNTI + if ((ue->dlsch_p[0]) && (ue->dlsch_p[0]->active == 1)) { + //LOG_I(PHY,"[Th-Slave] AbsSubframe %d.%d Pdsch Procedure P-PDSCH \n",frame_rx%1024,subframe_rx); + ue_pdsch_procedures(ue, + proc, + 0, + P_PDSCH, + ue->dlsch_p[0], + NULL, + 1+(ue->frame_parms.symbols_per_tti>>1), + ue->frame_parms.symbols_per_tti-1, + 0); + } + // do procedures for RA-RNTI + if ((ue->dlsch_ra[0]) && (ue->dlsch_ra[0]->active == 1)) { + //LOG_I(PHY,"[Th-Slave] AbsSubframe %d.%d Pdsch Procedure RA-PDSCH \n",frame_rx%1024,subframe_rx); + ue_pdsch_procedures(ue, + proc, + 0, + RA_PDSCH, + ue->dlsch_ra[0], + NULL, + 1+(ue->frame_parms.symbols_per_tti>>1), + ue->frame_parms.symbols_per_tti-1, + 0); + } + + //LOG_I(PHY,"Set available llrs slot1 to 1 AbsSubframe %d.%d \n",frame_rx%1024,subframe_rx); + proc->llr_slot1_available = 1; + } +#endif + + LOG_I(PHY," [Th-Slave] ==> End slot1 Thread for AbsSubframe %d.%d \n", proc->frame_rx, proc->subframe_rx); + + // End Thread Processing + + if (pthread_mutex_lock(&proc->mutex_fep_slot1) != 0) { + LOG_E( PHY, "[SCHED][UE] error locking mutex for UE RXTX\n" ); + exit_fun("noting to add"); + } + proc->instance_cnt_fep_slot1--; + if (pthread_mutex_unlock(&proc->mutex_fep_slot1) != 0) { + LOG_E( PHY, "[SCHED][UE] error unlocking mutex for UE FEP Slo1\n" ); + exit_fun("noting to add"); + } + } + + + // thread finished + free(arg); + return &UE_thread_rxtx_retval; +} /*! * \brief Initialize the UE theads. * Creates the UE threads: * - UE_thread_rxtx0 * - UE_thread_rxtx1 * - UE_thread_synch + * - UE_thread_fep_slot0 + * - UE_thread_fep_slot1 + * - UE_thread_dlsch_proc_slot0 + * - UE_thread_dlsch_proc_slot1 * and the locking between them. */ void init_UE_threads(PHY_VARS_UE *UE) { struct rx_tx_thread_data *rtd; + struct fep_slot1_thread_data *fep_slot1_data; pthread_attr_init (&UE->proc.attr_ue); pthread_attr_setstacksize(&UE->proc.attr_ue,8192);//5*PTHREAD_STACK_MIN); @@ -881,9 +1129,12 @@ void init_UE_threads(PHY_VARS_UE *UE) { UE->proc.proc_rxtx[i].sub_frame_start=i; UE->proc.proc_rxtx[i].sub_frame_step=nb_threads; pthread_create(&UE->proc.proc_rxtx[i].pthread_rxtx, NULL, UE_thread_rxn_txnp4, rtd); + + pthread_mutex_init(&UE->proc.proc_rxtx[i].mutex_fep_slot1,NULL); + pthread_cond_init(&UE->proc.proc_rxtx[i].cond_fep_slot1,NULL); + pthread_create(&UE->proc.proc_rxtx[i].pthread_fep_slot1,NULL,UE_thread_fep_slot1, rtd); } pthread_create(&UE->proc.pthread_synch,NULL,UE_thread_synch,(void*)UE); - }