/******************************************************************************* Eurecom OpenAirInterface Copyright(c) 1999 - 2011 Eurecom This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, version 2, as published by the Free Software Foundation. This program is distributed in the hope it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. The full GNU General Public License is included in this distribution in the file called "COPYING". Contact Information Openair Admin: openair_admin@eurecom.fr Openair Tech : openair_tech@eurecom.fr Forums : http://forums.eurecom.fsr/openairinterface Address : Eurecom, 2229, route des crĂȘtes, 06560 Valbonne Sophia Antipolis, France *******************************************************************************/ /*! \file PHY/LTE_TRANSPORT/ulsch_decoding.c * \brief Top-level routines for decoding the ULSCH transport channel from 36.212 V8.6 2009-03 * \author R. Knopp * \date 2011 * \version 0.1 * \company Eurecom * \email: knopp@eurecom.fr * \note * \warning */ //#include "defs.h" #include "PHY/defs.h" #include "PHY/extern.h" #include "PHY/CODING/extern.h" #include "extern.h" #include "MAC_INTERFACE/defs.h" #include "MAC_INTERFACE/extern.h" #include "SCHED/extern.h" #ifdef OPENAIR2 #include "LAYER2/MAC/defs.h" #include "LAYER2/MAC/extern.h" #include "RRC/LITE/extern.h" #include "PHY_INTERFACE/extern.h" #endif #ifdef OMP #include #endif #ifdef PHY_ABSTRACTION #include "UTIL/OCG/OCG.h" #include "UTIL/OCG/OCG_extern.h" #endif #include "UTIL/LOG/vcd_signal_dumper.h" //#define DEBUG_ULSCH_DECODING void free_eNB_ulsch(LTE_eNB_ULSCH_t *ulsch) { int i,r; if (ulsch) { for (i=0;iMdlharq;i++) { if (ulsch->harq_processes[i]) { if (ulsch->harq_processes[i]->b) { free16(ulsch->harq_processes[i]->b,MAX_ULSCH_PAYLOAD_BYTES); ulsch->harq_processes[i]->b = NULL; } if (ulsch->harq_processes[i]->c) { for (r=0;rharq_processes[i]->c[r],((r==0)?8:0) + 768); ulsch->harq_processes[i]->c[r] = NULL; } } for (r=0;rharq_processes[i]->d[r]) { free16(ulsch->harq_processes[i]->d[r],((3*8*6144)+12+96)*sizeof(short)); ulsch->harq_processes[i]->d[r] = NULL; } free16(ulsch->harq_processes[i],sizeof(LTE_UL_eNB_HARQ_t)); ulsch->harq_processes[i] = NULL; } } free16(ulsch,sizeof(LTE_eNB_ULSCH_t)); ulsch = NULL; } } LTE_eNB_ULSCH_t *new_eNB_ulsch(uint8_t Mdlharq,uint8_t max_turbo_iterations,uint8_t N_RB_UL, uint8_t abstraction_flag) { LTE_eNB_ULSCH_t *ulsch; uint8_t exit_flag = 0,i,r; unsigned char bw_scaling =1; switch (N_RB_UL){ case 6: bw_scaling =16; break; case 25: bw_scaling =4; break; case 50: bw_scaling =2; break; default: bw_scaling =1; break; } ulsch = (LTE_eNB_ULSCH_t *)malloc16(sizeof(LTE_eNB_ULSCH_t)); if (ulsch) { memset(ulsch,0,sizeof(LTE_eNB_ULSCH_t)); ulsch->Mdlharq = Mdlharq; ulsch->max_turbo_iterations = max_turbo_iterations; for (i=0;iharq_processes[i] = (LTE_UL_eNB_HARQ_t *)malloc16(sizeof(LTE_UL_eNB_HARQ_t)); if (ulsch->harq_processes[i]) { memset(ulsch->harq_processes[i],0,sizeof(LTE_UL_eNB_HARQ_t)); ulsch->harq_processes[i]->b = (uint8_t*)malloc16(MAX_ULSCH_PAYLOAD_BYTES/bw_scaling); if (ulsch->harq_processes[i]->b) memset(ulsch->harq_processes[i]->b,0,MAX_ULSCH_PAYLOAD_BYTES/bw_scaling); else exit_flag=3; if (abstraction_flag==0) { for (r=0;rharq_processes[i]->c[r] = (uint8_t*)malloc16(((r==0)?8:0) + 3+768); if (ulsch->harq_processes[i]->c[r]) memset(ulsch->harq_processes[i]->c[r],0,((r==0)?8:0) + 3+768); else exit_flag=2; ulsch->harq_processes[i]->d[r] = (short*)malloc16(((3*8*6144)+12+96)*sizeof(short)); if (ulsch->harq_processes[i]->d[r]) memset(ulsch->harq_processes[i]->d[r],0,((3*8*6144)+12+96)*sizeof(short)); else exit_flag=2; } ulsch->harq_processes[i]->subframe_scheduling_flag = 0; } } else { exit_flag=1; } } if (exit_flag==0) return(ulsch); } LOG_E(PHY,"new_ue_ulsch: exit_flag = %d\n",exit_flag); free_eNB_ulsch(ulsch); return(NULL); } void clean_eNb_ulsch(LTE_eNB_ULSCH_t *ulsch, uint8_t abstraction_flag) { unsigned char Mdlharq; unsigned char i; //ulsch = (LTE_eNB_ULSCH_t *)malloc16(sizeof(LTE_eNB_ULSCH_t)); if (ulsch) { Mdlharq = ulsch->Mdlharq; ulsch->rnti = 0; for (i=0;iharq_processes[i]) { // ulsch->harq_processes[i]->Ndi = 0; ulsch->harq_processes[i]->status = 0; ulsch->harq_processes[i]->subframe_scheduling_flag = 0; //ulsch->harq_processes[i]->phich_active = 0; //this will be done later after transmission of PHICH ulsch->harq_processes[i]->phich_ACK = 0; ulsch->harq_processes[i]->round = 0; } } } } uint8_t extract_cqi_crc(uint8_t *cqi,uint8_t CQI_LENGTH) { uint8_t crc; crc = cqi[CQI_LENGTH>>3]; // msg("crc1: %x, shift %d\n",crc,CQI_LENGTH&0x7); crc = (crc<<(CQI_LENGTH&0x7)); // clear crc bits // ((char *)cqi)[CQI_LENGTH>>3] &= 0xff>>(8-(CQI_LENGTH&0x7)); // msg("crc2: %x, cqi0 %x\n",crc,cqi[1+(CQI_LENGTH>>3)]); crc |= (cqi[1+(CQI_LENGTH>>3)])>>(8-(CQI_LENGTH&0x7)); // clear crc bits //(((char *)cqi)[1+(CQI_LENGTH>>3)]) = 0; // printf("crc : %x\n",crc); return(crc); } unsigned int ulsch_decoding(PHY_VARS_eNB *phy_vars_eNB, uint8_t UE_id, uint8_t subframe, uint8_t control_only_flag, uint8_t Nbundled, uint8_t llr8_flag) { int16_t *ulsch_llr = phy_vars_eNB->lte_eNB_pusch_vars[UE_id]->llr; LTE_DL_FRAME_PARMS *frame_parms = &phy_vars_eNB->lte_frame_parms; LTE_eNB_ULSCH_t *ulsch = phy_vars_eNB->ulsch_eNB[UE_id]; uint8_t harq_pid; unsigned short nb_rb; unsigned int A,E; uint8_t Q_m; unsigned int i,i2,q,j,j2; int iprime; unsigned int ret=0,offset; unsigned short iind; // uint8_t dummy_channel_output[(3*8*block_length)+12]; unsigned int r,r_offset=0,Kr,Kr_bytes; uint8_t crc_type; uint8_t *columnset; unsigned int sumKr=0; unsigned int Qprime,L,G,Q_CQI,Q_RI,H,Hprime,Hpp,Cmux,Rmux_prime,O_RCC; unsigned int Qprime_ACK,Qprime_CQI,Qprime_RI,len_ACK=0,len_RI=0; uint8_t q_ACK[MAX_ACK_PAYLOAD],q_RI[MAX_RI_PAYLOAD]; int metric,metric_new; uint8_t o_flip[8]; uint32_t x1, x2, s=0; int16_t ys,c; uint32_t wACK_idx; int16_t dummy_w[MAX_NUM_ULSCH_SEGMENTS][3*(6144+64)]; uint8_t dummy_w_cc[3*(MAX_CQI_BITS+8+32)]; int16_t y[6*14*1200]; uint8_t ytag[14*1200]; // uint8_t ytag2[6*14*1200],*ytag2_ptr; int16_t cseq[6*14*1200]; int off; int status[20]; uint8_t (*tc)(int16_t *y, uint8_t *, uint16_t, uint16_t, uint16_t, uint8_t, uint8_t, uint8_t, time_stats_t *, time_stats_t *, time_stats_t *, time_stats_t *, time_stats_t *, time_stats_t *, time_stats_t *); vcd_signal_dumper_dump_function_by_name(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_ULSCH_DECODING,1); // x1 is set in lte_gold_generic x2 = ((uint32_t)ulsch->rnti<<14) + ((uint32_t)subframe<<9) + frame_parms->Nid_cell; //this is c_init in 36.211 Sec 6.3.1 // harq_pid = (ulsch->RRCConnRequest_flag == 0) ? subframe2harq_pid_tdd(frame_parms->tdd_config,subframe) : 0; harq_pid = subframe2harq_pid(frame_parms,(((subframe)>=8)?-1:0)+phy_vars_eNB->frame,subframe); if (harq_pid==255) { LOG_E(PHY, "ulsch_decoding.c: FATAL ERROR: illegal harq_pid, returning\n"); return(-1); } if (llr8_flag == 0) tc = phy_threegpplte_turbo_decoder16; else tc = phy_threegpplte_turbo_decoder8; nb_rb = ulsch->harq_processes[harq_pid]->nb_rb; A = ulsch->harq_processes[harq_pid]->TBS; Q_m = get_Qm_ul(ulsch->harq_processes[harq_pid]->mcs); G = nb_rb * (12 * Q_m) * ulsch->Nsymb_pusch; #ifdef DEBUG_ULSCH_DECODING LOG_D(PHY,"ulsch_decoding (Nid_cell %d, rnti %x, x2 %x): round %d, RV %d, mcs %d, O_RI %d, O_ACK %d, G %d, subframe %d\n", frame_parms->Nid_cell,ulsch->rnti,x2, ulsch->harq_processes[harq_pid]->round, ulsch->harq_processes[harq_pid]->rvidx, ulsch->harq_processes[harq_pid]->mcs, ulsch->O_RI, ulsch->harq_processes[harq_pid]->O_ACK, G, subframe); #endif if (ulsch->harq_processes[harq_pid]->round == 0) { // This is a new packet, so compute quantities regarding segmentation ulsch->harq_processes[harq_pid]->B = A+24; lte_segmentation(NULL, NULL, ulsch->harq_processes[harq_pid]->B, &ulsch->harq_processes[harq_pid]->C, &ulsch->harq_processes[harq_pid]->Cplus, &ulsch->harq_processes[harq_pid]->Cminus, &ulsch->harq_processes[harq_pid]->Kplus, &ulsch->harq_processes[harq_pid]->Kminus, &ulsch->harq_processes[harq_pid]->F); // CLEAR LLR's HERE for first packet in process } sumKr = 0; for (r=0;rharq_processes[harq_pid]->C;r++) { if (rharq_processes[harq_pid]->Cminus) Kr = ulsch->harq_processes[harq_pid]->Kminus; else Kr = ulsch->harq_processes[harq_pid]->Kplus; sumKr += Kr; } if (sumKr==0) { LOG_N(PHY,"[eNB %d] ulsch_decoding.c: FATAL sumKr is 0!\n",phy_vars_eNB->Mod_id); LOG_D(PHY,"ulsch_decoding (Nid_cell %d, rnti %x, x2 %x): harq_pid %d round %d, RV %d, mcs %d, O_RI %d, O_ACK %d, G %d, subframe %d\n", frame_parms->Nid_cell,ulsch->rnti,x2, harq_pid, ulsch->harq_processes[harq_pid]->round, ulsch->harq_processes[harq_pid]->rvidx, ulsch->harq_processes[harq_pid]->mcs, ulsch->O_RI, ulsch->harq_processes[harq_pid]->O_ACK, G, subframe); mac_xface->macphy_exit(""); return(-1); } // Compute Q_ri Qprime = ulsch->O_RI*ulsch->harq_processes[harq_pid]->Msc_initial*ulsch->harq_processes[harq_pid]->Nsymb_initial * ulsch->beta_offset_ri_times8; if (Qprime > 0 ) { if ((Qprime % (8*sumKr)) > 0) Qprime = 1+(Qprime/(8*sumKr)); else Qprime = Qprime/(8*sumKr); if (Qprime > 4*nb_rb * 12) Qprime = 4*nb_rb * 12; } Q_RI = Q_m*Qprime; Qprime_RI = Qprime; // Compute Q_ack Qprime = ulsch->harq_processes[harq_pid]->O_ACK*ulsch->harq_processes[harq_pid]->Msc_initial*ulsch->harq_processes[harq_pid]->Nsymb_initial * ulsch->beta_offset_harqack_times8; if (Qprime > 0) { if ((Qprime % (8*sumKr)) > 0) Qprime = 1+(Qprime/(8*sumKr)); else Qprime = Qprime/(8*sumKr); if (Qprime > (4*nb_rb * 12)) Qprime = 4*nb_rb * 12; } // Q_ACK = Qprime * Q_m; Qprime_ACK = Qprime; #ifdef DEBUG_ULSCH_DECODING LOG_D(PHY,"ulsch_decoding.c: Qprime_ACK %d, Msc_initial %d, Nsymb_initial %d, sumKr %d\n", Qprime_ACK,ulsch->harq_processes[harq_pid]->Msc_initial,ulsch->harq_processes[harq_pid]->Nsymb_initial,sumKr); #endif // Compute Q_cqi if (ulsch->Or1 < 12) L=0; else L=8; if (ulsch->Or1 > 0) Qprime = (ulsch->Or1 + L) * ulsch->harq_processes[harq_pid]->Msc_initial*ulsch->harq_processes[harq_pid]->Nsymb_initial * ulsch->beta_offset_cqi_times8; else Qprime=0; if (Qprime > 0) { if ((Qprime % (8*sumKr)) > 0) Qprime = 1+(Qprime/(8*sumKr)); else Qprime = Qprime/(8*sumKr); } G = nb_rb * (12 * Q_m) * (ulsch->Nsymb_pusch); if (Qprime > (G - ulsch->O_RI)) Qprime = G - ulsch->O_RI; Q_CQI = Q_m * Qprime; #ifdef DEBUG_ULSCH_DECODING printf("ulsch_decoding.c: G %d, Q_RI %d, Q_CQI %d (L %d, Or1 %d) O_ACK %d\n",G,Q_RI,Q_CQI,L,ulsch->Or1,ulsch->harq_processes[harq_pid]->O_ACK); #endif Qprime_CQI = Qprime; G = G - Q_RI - Q_CQI; if ((int)G < 0) { LOG_E(PHY,"FATAL: ulsch_decoding.c G < 0 (%d) : Q_RI %d, Q_CQI %d\n",G,Q_RI,Q_CQI); return(-1); } H = G + Q_CQI; Hprime = H/Q_m; // Demultiplexing/Deinterleaving of PUSCH/ACK/RI/CQI Hpp = Hprime + Qprime_RI; Cmux = ulsch->Nsymb_pusch; // Rmux = Hpp*Q_m/Cmux; Rmux_prime = Hpp/Cmux; #ifdef DEBUG_ULSCH_DECODING LOG_D(PHY,"ulsch_decoding.c: G raw %d (%d symb), Hpp %d, Cmux %d, Rmux_prime %d\n",G,ulsch->Nsymb_pusch,Hpp,Cmux,Rmux_prime); #endif // Clear "tag" interleaving matrix to allow for CQI/DATA identification memset(ytag,0,Cmux*Rmux_prime); start_meas(&phy_vars_eNB->ulsch_demultiplexing_stats); i=0; // Do RI coding if (ulsch->O_RI == 1) { switch (Q_m) { case 2: q_RI[0] = 0; q_RI[1] = PUSCH_y; len_RI=2; break; case 4: q_RI[0] = 0; q_RI[1] = PUSCH_y;//1; q_RI[2] = PUSCH_x;//o_RI[0]; q_RI[3] = PUSCH_x;//1; len_RI=4; break; case 6: q_RI[0] = 0; q_RI[1] = PUSCH_y;//1; q_RI[2] = PUSCH_x;//1; q_RI[3] = PUSCH_x;//ulsch->o_RI[0]; q_RI[4] = PUSCH_x;//1; q_RI[5] = PUSCH_x;//1; len_RI=6; break; } } else if (ulsch->O_RI > 1){ LOG_E(PHY,"ulsch_decoding: FATAL, RI cannot be more than 1 bit yet\n"); return(-1); } // 1-bit ACK/NAK if (ulsch->harq_processes[harq_pid]->O_ACK == 1) { switch (Q_m) { case 2: q_ACK[0] = 0; q_ACK[1] = (ulsch->bundling==0)? PUSCH_y : 0; len_ACK = 2; break; case 4: q_ACK[0] = 0; q_ACK[1] = (ulsch->bundling==0)? PUSCH_y : 0; q_ACK[2] = PUSCH_x; q_ACK[3] = PUSCH_x; len_ACK = 4; break; case 6: q_ACK[0] = 0; q_ACK[1] = (ulsch->bundling==0)? PUSCH_y : 0; q_ACK[2] = PUSCH_x; q_ACK[3] = PUSCH_x; q_ACK[4] = PUSCH_x; q_ACK[6] = PUSCH_x; len_ACK = 6; break; } } // two-bit ACK/NAK if (ulsch->harq_processes[harq_pid]->O_ACK == 2) { switch (Q_m) { case 2: q_ACK[0] = 0; q_ACK[1] = 0; q_ACK[2] = 0; q_ACK[3] = 0; q_ACK[4] = 0; q_ACK[5] = 0; len_ACK = 6; break; case 4: q_ACK[0] = 0; q_ACK[1] = 0; q_ACK[2] = PUSCH_x; q_ACK[3] = PUSCH_x;//1; q_ACK[4] = 0; q_ACK[5] = 0; q_ACK[6] = PUSCH_x; q_ACK[7] = PUSCH_x;//1; q_ACK[8] = 0; q_ACK[9] = 0; q_ACK[10] = PUSCH_x; q_ACK[11] = PUSCH_x;//1; len_ACK = 12; break; case 6: q_ACK[0] = 0; q_ACK[1] = 0; q_ACK[2] = PUSCH_x; q_ACK[3] = PUSCH_x; q_ACK[4] = PUSCH_x; q_ACK[5] = PUSCH_x; q_ACK[6] = 0; q_ACK[7] = 0; q_ACK[8] = PUSCH_x; q_ACK[9] = PUSCH_x; q_ACK[10] = PUSCH_x; q_ACK[11] = PUSCH_x; q_ACK[12] = 0; q_ACK[13] = 0; q_ACK[14] = PUSCH_x; q_ACK[15] = PUSCH_x; q_ACK[16] = PUSCH_x; q_ACK[17] = PUSCH_x; len_ACK = 18; break; } } if (ulsch->harq_processes[harq_pid]->O_ACK > 2) { LOG_E(PHY,"ulsch_decoding: FATAL, ACK cannot be more than 2 bits yet\n"); return(-1); } // RI BITS memset(y,LTE_NULL,Q_m*Hpp); // memset(ytag2,0,Q_m*Hpp); // read in buffer and unscramble llrs for everything but placeholder bits // llrs stored per symbol correspond to columns of interleaving matrix s = lte_gold_generic(&x1, &x2, 1); i2=0; for (i=0;i<((Hpp*Q_m)>>5);i++) { for (j=0;j<32;j++) { cseq[i2++] = (int16_t)((((s>>j)&1)<<1)-1); } s = lte_gold_generic(&x1, &x2, 0); } if (frame_parms->Ncp == 0) columnset = cs_ri_normal; else columnset = cs_ri_extended; j=0; for (i=0;i>2); /* for (q=0;qNcp == 0) columnset = cs_ack_normal; else columnset = cs_ack_extended; j=0; for (i=0;i>2); /* for (q=0;qharq_processes[harq_pid]->O_ACK == 1) { if (ulsch->bundling==0) cseq[off+1] = cseq[off]; // PUSCH_y for (q=2;qharq_processes[harq_pid]->O_ACK == 2) { for (q=2;q>(i&0x1f))&1); // if bits are tagged as placeholders (RI,ACK) if (ytag2[q+(Q_m*((r*Cmux)+j))] == PUSCH_y) { c=c_prev; } else if (ytag2[q+(Q_m*((r*Cmux)+j))] == PUSCH_x) { c = 0; #ifdef DEBUG_ULSCH_DECODING // msg("ulsch_decoding.c: PUSCH_x in row %d, col %d: llr %d\n",r,j,ulsch_llr[i]); #endif } c_prev = c; #ifdef DEBUG_ULSCH_DECODING // msg("llr[%d] = %d (c %d, ytag2 %d) ==> ",i,ulsch_llr[i],c,ytag2[q+(Q_m*((r*Cmux)+j))]); #endif // note flipped here for reverse polarity in 3GPP bit mapping y[q+(Q_m*((r*Cmux)+j))] = (c==0) ? -ulsch_llr[i] : ulsch_llr[i]; i++; #ifdef DEBUG_ULSCH_DECODING // msg("%d\n",y[q+(Q_m*((r*Cmux)+j))]); #endif */ stop_meas(&phy_vars_eNB->ulsch_demultiplexing_stats); if (i!=(H+Q_RI)) LOG_D(PHY,"ulsch_decoding.c: Error in input buffer length (j %d, H+Q_RI %d)\n",i,H+Q_RI); // HARQ-ACK Bits (LLRs are nulled in overwritten bits after copying HARQ-ACK LLR) if (frame_parms->Ncp == 0) columnset = cs_ack_normal; else columnset = cs_ack_extended; j=0; if (ulsch->harq_processes[harq_pid]->O_ACK == 1) { switch (Q_m) { case 2: len_ACK = 2; break; case 4: len_ACK = 4; break; case 6: len_ACK = 6; break; } } if (ulsch->harq_processes[harq_pid]->O_ACK == 2) { switch (Q_m) { case 2: len_ACK = 6; break; case 4: len_ACK = 12; break; case 6: len_ACK = 18; break; } } if (ulsch->harq_processes[harq_pid]->O_ACK > 2) { LOG_E(PHY,"ulsch_decoding: FATAL, ACK cannot be more than 2 bits yet\n"); return(-1); } for (i=0;iq_ACK[i] = 0; for (i=0;i>2); for (q=0;qq_ACK[(q+(Q_m*i))%len_ACK] += y[q+(Q_m*((r*Cmux) + columnset[j]))]; #ifdef DEBUG_ULSCH_DECODING // LOG_D(PHY,"ACK %d => %d (%d,%d,%d)\n",(q+(Q_m*i))%len_ACK,ulsch->q_ACK[(q+(Q_m*i))%len_ACK],q+(Q_m*((r*Cmux) + columnset[j])),r,columnset[j]); printf("ACK %d => %d (%d,%d,%d)\n",(q+(Q_m*i))%len_ACK,ulsch->q_ACK[(q+(Q_m*i))%len_ACK],q+(Q_m*((r*Cmux) + columnset[j])),r,columnset[j]); #endif y[q+(Q_m*((r*Cmux) + columnset[j]))]=0; // NULL LLRs in ACK positions } j=(j+3)&3; } // RI BITS if (ulsch->O_RI == 1) { switch (Q_m) { case 2: len_RI=2; break; case 4: len_RI=4; break; case 6: len_RI=6; break; } } if (ulsch->O_RI > 1) { LOG_E(PHY,"ulsch_decoding: FATAL, RI cannot be more than 1 bit yet\n"); return(-1); } for (i=0;iq_RI[i] = 0; if (frame_parms->Ncp == 0) columnset = cs_ri_normal; else columnset = cs_ri_extended; j=0; for (i=0;i>2); for (q=0;qq_RI[(q+(Q_m*i))%len_RI] += y[q+(Q_m*((r*Cmux) + columnset[j]))]; ytag[(r*Cmux) + columnset[j]] = LTE_NULL; j=(j+3)&3; } // CQI and Data bits j=0;j2=0; // r=0; for (i=0;i127) ulsch->q[q+(Q_m*i)] = 127; else if (ys<-128) ulsch->q[q+(Q_m*i)] = -128; else ulsch->q[q+(Q_m*i)] = ys; #ifdef DEBUG_ULSCH_DECODING msg("ulsch_decoding.c: CQI %d, r %d, j %d, y[%d] %d\n",q+(Q_m*i),r,j, q+(Q_m*((r*Cmux) + j)),ys); #endif } */ while (ytag[j]==LTE_NULL){j++;j2+=Q_m;} for (q=0;q127) ulsch->q[q+(Q_m*i)] = 127; else if (ys<-128) ulsch->q[q+(Q_m*i)] = -128; else ulsch->q[q+(Q_m*i)] = ys; #ifdef DEBUG_ULSCH_DECODING LOG_D(PHY,"ulsch_decoding.c: CQI %d, q %d, y[%d] %d\n",q+(Q_m*i),q,j2, q+j2,ys); #endif } j2+=Q_m; } // j2=j*Q_m; switch (Q_m) { case 2: for (iprime=0;iprime<(Hprime-Qprime_CQI)<<1;) { while (ytag[j]==LTE_NULL) { j++;j2+=2; } ulsch->e[iprime++] = y[j2++]; ulsch->e[iprime++] = y[j2++]; #ifdef DEBUG_ULSCH_DECODING // msg("ulsch_decoding.c: e %d, r %d, j %d, y[%d] %d\n",g,r,j,q+(Q_m*((r*Cmux) + j)),y[q+(Q_m*((r*Cmux)+j))]); #endif } // write_output("/tmp/ulsch_e.m","ulsch_e",ulsch->e,iprime,1,0); break; case 4: for (iprime=0;iprime<(Hprime-Qprime_CQI)<<2;) { while (ytag[j]==LTE_NULL) { j++;j2+=4; } ulsch->e[iprime++] = y[j2++]; ulsch->e[iprime++] = y[j2++]; ulsch->e[iprime++] = y[j2++]; ulsch->e[iprime++] = y[j2++]; #ifdef DEBUG_ULSCH_DECODING // msg("ulsch_decoding.c: e %d, r %d, j %d, y[%d] %d\n",g,r,j,q+(Q_m*((r*Cmux) + j)),y[q+(Q_m*((r*Cmux)+j))]); #endif } break; case 6: for (iprime=0;iprime<(Hprime-Qprime_CQI)*6;) { while (ytag[j]==LTE_NULL) { j++;j2+=6; } ulsch->e[iprime++] = y[j2++]; ulsch->e[iprime++] = y[j2++]; ulsch->e[iprime++] = y[j2++]; ulsch->e[iprime++] = y[j2++]; ulsch->e[iprime++] = y[j2++]; ulsch->e[iprime++] = y[j2++]; #ifdef DEBUG_ULSCH_DECODING // msg("ulsch_decoding.c: e %d, r %d, j %d, y[%d] %d\n",g,r,j,q+(Q_m*((r*Cmux) + j)),y[q+(Q_m*((r*Cmux)+j))]); #endif } break; } /* for (i=0,iprime=-Qprime_CQI;i127) ulsch->q[q+(Q_m*i)] = 127; else if (ys<-128) ulsch->q[q+(Q_m*i)] = -128; else ulsch->q[q+(Q_m*i)] = ys; #ifdef DEBUG_ULSCH_DECODING msg("ulsch_decoding.c: CQI %d, r %d, j %d, y[%d] %d\n",q+(Q_m*i),r,j, q+(Q_m*((r*Cmux) + j)),ys); #endif } } else { for (q=0;qe[g] = y[q+(Q_m*((r*Cmux)+j))]; #ifdef DEBUG_ULSCH_DECODING // msg("ulsch_decoding.c: e %d, r %d, j %d, y[%d] %d\n",g,r,j,q+(Q_m*((r*Cmux) + j)),y[q+(Q_m*((r*Cmux)+j))]); #endif } } j++; if (j==Cmux) { j=0; r++; } } */ // Do CQI/RI/HARQ-ACK Decoding first and pass to MAC // HARQ-ACK wACK_idx = (ulsch->bundling==0) ? 4 : ((Nbundled-1)&3); #ifdef DEBUG_ULSCH_DECODING LOG_D(PHY,"ulsch_decoding.c: Bundling %d, Nbundled %d, wACK_idx %d\n", ulsch->bundling,Nbundled,wACK_idx); #endif if (ulsch->harq_processes[harq_pid]->O_ACK == 1) { ulsch->q_ACK[0] *= wACK_RX[wACK_idx][0]; ulsch->q_ACK[0] += (ulsch->bundling==0) ? ulsch->q_ACK[1]*wACK_RX[wACK_idx][0] : ulsch->q_ACK[1]*wACK_RX[wACK_idx][1]; if (ulsch->q_ACK[0] < 0) ulsch->o_ACK[0] = 0; else ulsch->o_ACK[0] = 1; #ifdef DEBUG_ULSCH_DECODING LOG_D(PHY,"ulsch_decoding.c: ulsch_q_ACK[0] %d (%d,%d)\n",ulsch->q_ACK[0],wACK_RX[wACK_idx][0],wACK_RX[wACK_idx][1]); #endif } if (ulsch->harq_processes[harq_pid]->O_ACK == 2) { switch (Q_m) { case 2: ulsch->q_ACK[0] = ulsch->q_ACK[0]*wACK_RX[wACK_idx][0] + ulsch->q_ACK[3]*wACK_RX[wACK_idx][1]; ulsch->q_ACK[1] = ulsch->q_ACK[1]*wACK_RX[wACK_idx][0] + ulsch->q_ACK[4]*wACK_RX[wACK_idx][1]; ulsch->q_ACK[2] = ulsch->q_ACK[2]*wACK_RX[wACK_idx][0] + ulsch->q_ACK[5]*wACK_RX[wACK_idx][1]; break; case 4: ulsch->q_ACK[0] = ulsch->q_ACK[0]*wACK_RX[wACK_idx][0] + ulsch->q_ACK[5]*wACK_RX[wACK_idx][1]; ulsch->q_ACK[1] = ulsch->q_ACK[1]*wACK_RX[wACK_idx][0] + ulsch->q_ACK[8]*wACK_RX[wACK_idx][1]; ulsch->q_ACK[2] = ulsch->q_ACK[4]*wACK_RX[wACK_idx][0] + ulsch->q_ACK[9]*wACK_RX[wACK_idx][1]; break; case 6: ulsch->q_ACK[0] = ulsch->q_ACK[0]*wACK_RX[wACK_idx][0] + ulsch->q_ACK[7]*wACK_RX[wACK_idx][1]; ulsch->q_ACK[1] = ulsch->q_ACK[1]*wACK_RX[wACK_idx][0] + ulsch->q_ACK[12]*wACK_RX[wACK_idx][1]; ulsch->q_ACK[2] = ulsch->q_ACK[6]*wACK_RX[wACK_idx][0] + ulsch->q_ACK[13]*wACK_RX[wACK_idx][1]; break; } ulsch->o_ACK[0] = 1; ulsch->o_ACK[1] = 1; metric = ulsch->q_ACK[0]+ulsch->q_ACK[1]-ulsch->q_ACK[2]; metric_new = -ulsch->q_ACK[0]+ulsch->q_ACK[1]+ulsch->q_ACK[2]; if (metric_new > metric) { ulsch->o_ACK[0]=0; ulsch->o_ACK[1]=1; metric = metric_new; } metric_new = ulsch->q_ACK[0]-ulsch->q_ACK[1]+ulsch->q_ACK[2]; if (metric_new > metric) { ulsch->o_ACK[0] = 1; ulsch->o_ACK[1] = 0; metric = metric_new; } metric_new = -ulsch->q_ACK[0]-ulsch->q_ACK[1]-ulsch->q_ACK[2]; if (metric_new > metric) { ulsch->o_ACK[0] = 0; ulsch->o_ACK[1] = 0; metric = metric_new; } } #ifdef DEBUG_ULSCH_DECODING for (i=0;iharq_processes[harq_pid]->O_ACK;i++) LOG_D(PHY,"ulsch_decoding: O_ACK[%d] %d, q_ACK => (%d,%d,%d)\n",i,ulsch->o_ACK[i],ulsch->q_ACK[0],ulsch->q_ACK[1],ulsch->q_ACK[2]); #endif // RI if ((ulsch->O_RI == 1) && (Qprime_RI > 0)) { ulsch->o_RI[0] = ((ulsch->q_RI[0] + ulsch->q_RI[Q_m/2]) > 0) ? 0 : 1; } #ifdef DEBUG_ULSCH_DECODING if (Qprime_RI > 0) { for (i=0;i<2*ulsch->O_RI;i++) LOG_D(PHY,"ulsch_decoding: q_RI[%d] %d\n",i,ulsch->q_RI[i]); } if (Qprime_CQI > 0) { for (i=0;iO_RI;i++) LOG_D(PHY,"ulsch_decoding: O_RI[%d] %d\n",i,ulsch->o_RI[i]); } #endif // CQI if (Qprime_CQI>0) { memset((void *)&dummy_w_cc[0],0,3*(ulsch->Or1+8+32)); O_RCC = generate_dummy_w_cc(ulsch->Or1+8, &dummy_w_cc[0]); lte_rate_matching_cc_rx(O_RCC, Q_CQI, ulsch->o_w, dummy_w_cc, ulsch->q); sub_block_deinterleaving_cc((unsigned int)(ulsch->Or1+8), &ulsch->o_d[96], &ulsch->o_w[0]); memset(o_flip,0,1+((8+ulsch->Or1)/8)); phy_viterbi_lte_sse2(ulsch->o_d+96,o_flip,8+ulsch->Or1); if (extract_cqi_crc(o_flip,ulsch->Or1) == (crc8(o_flip,ulsch->Or1)>>24)) ulsch->cqi_crc_status = 1; else ulsch->cqi_crc_status = 0; //printf("crc(cqi) rx: %x\n",(crc8(o_flip,ulsch->Or1)>>24)); if (ulsch->Or1<=32) { ulsch->o[3] = o_flip[0] ; ulsch->o[2] = o_flip[1] ; ulsch->o[1] = o_flip[2] ; ulsch->o[0] = o_flip[3] ; } else { ulsch->o[7] = o_flip[0] ; ulsch->o[6] = o_flip[1] ; ulsch->o[5] = o_flip[2] ; ulsch->o[4] = o_flip[3] ; ulsch->o[3] = o_flip[4] ; ulsch->o[2] = o_flip[5] ; ulsch->o[1] = o_flip[6] ; ulsch->o[0] = o_flip[7] ; } #ifdef DEBUG_ULSCH_DECODING LOG_D(PHY,"ulsch_decoding: Or1=%d\n",ulsch->Or1); for (i=0;i<1+((8+ulsch->Or1)/8);i++) msg("ulsch_decoding: O[%d] %d\n",i,ulsch->o[i]); if (ulsch->cqi_crc_status == 1) msg("RX CQI CRC OK (%x)\n",extract_cqi_crc(o_flip,ulsch->Or1)); else msg("RX CQI CRC NOT OK (%x)\n",extract_cqi_crc(o_flip,ulsch->Or1)); #endif } // return(0); // Do PUSCH Decoding // stop_meas(&phy_vars_eNB->ulsch_demultiplexing_stats); r_offset = 0; for (r=0;rharq_processes[harq_pid]->C;r++) { // Get Turbo interleaver parameters if (rharq_processes[harq_pid]->Cminus) Kr = ulsch->harq_processes[harq_pid]->Kminus; else Kr = ulsch->harq_processes[harq_pid]->Kplus; Kr_bytes = Kr>>3; if (Kr_bytes<=64) iind = (Kr_bytes-5); else if (Kr_bytes <=128) iind = 59 + ((Kr_bytes-64)>>1); else if (Kr_bytes <= 256) iind = 91 + ((Kr_bytes-128)>>2); else if (Kr_bytes <= 768) iind = 123 + ((Kr_bytes-256)>>3); else { LOG_E(PHY,"ulsch_decoding: Illegal codeword size %d!!!\n",Kr_bytes); return(-1); } #ifdef DEBUG_ULSCH_DECODING msg("f1 %d, f2 %d, F %d\n",f1f2mat_old[2*iind],f1f2mat_old[1+(2*iind)],(r==0) ? ulsch->harq_processes[harq_pid]->F : 0); #endif memset(&dummy_w[r][0],0,3*(6144+64)*sizeof(short)); ulsch->harq_processes[harq_pid]->RTC[r] = generate_dummy_w(4+(Kr_bytes*8), (uint8_t*)&dummy_w[r][0], (r==0) ? ulsch->harq_processes[harq_pid]->F : 0); #ifdef DEBUG_ULSCH_DECODING msg("Rate Matching Segment %d (coded bits (G) %d,unpunctured/repeated bits %d, Q_m %d, nb_rb %d, Nl %d)...\n", r, G, Kr*3, Q_m, nb_rb, ulsch->harq_processes[harq_pid]->Nl); #endif start_meas(&phy_vars_eNB->ulsch_rate_unmatching_stats); if (lte_rate_matching_turbo_rx(ulsch->harq_processes[harq_pid]->RTC[r], G, ulsch->harq_processes[harq_pid]->w[r], (uint8_t*) &dummy_w[r][0], ulsch->e, ulsch->harq_processes[harq_pid]->C, NSOFT, ulsch->Mdlharq, 1, ulsch->harq_processes[harq_pid]->rvidx, (ulsch->harq_processes[harq_pid]->round==0)?1:0, // clear get_Qm_ul(ulsch->harq_processes[harq_pid]->mcs), 1, r, &E)==-1) { LOG_E(PHY,"ulsch_decoding.c: Problem in rate matching\n"); return(-1); } stop_meas(&phy_vars_eNB->ulsch_rate_unmatching_stats); r_offset += E; /* msg("Subblock deinterleaving, d %p w %p\n", ulsch->harq_processes[harq_pid]->d[r], ulsch->harq_processes[harq_pid]->w); */ start_meas(&phy_vars_eNB->ulsch_deinterleaving_stats); sub_block_deinterleaving_turbo(4+Kr, &ulsch->harq_processes[harq_pid]->d[r][96], ulsch->harq_processes[harq_pid]->w[r]); stop_meas(&phy_vars_eNB->ulsch_deinterleaving_stats); /*#ifdef DEBUG_ULSCH_DECODING msg("decoder input(segment %d) :",r); for (i=0;i<(3*8*Kr_bytes)+12;i++) msg("%d : %d\n",i,ulsch->harq_processes[harq_pid]->d[r][96+i]); msg("\n"); #endif*/ } #ifdef OMP #pragma omp parallel private(r,ret) shared(ulsch,harq_pid,crc_type,Kr,f1f2mat_old,phy_vars_eNB,status,iind,) { #pragma omp for nowait #endif for (r=0;rharq_processes[harq_pid]->C;r++) { // msg("Clearing c, %p\n",ulsch->harq_processes[harq_pid]->c[r]); // memset(ulsch->harq_processes[harq_pid]->c[r],0,16);//block_length); // msg("done\n"); if (ulsch->harq_processes[harq_pid]->C == 1) crc_type = CRC24_A; else crc_type = CRC24_B; /* msg("decoder input(segment %d)\n",r); for (i=0;i<(3*8*Kr_bytes)+12;i++) if ((ulsch->harq_processes[harq_pid]->d[r][96+i]>7) || (ulsch->harq_processes[harq_pid]->d[r][96+i] < -8)) msg("%d : %d\n",i,ulsch->harq_processes[harq_pid]->d[r][96+i]); msg("\n"); */ start_meas(&phy_vars_eNB->ulsch_turbo_decoding_stats); ret = tc(&ulsch->harq_processes[harq_pid]->d[r][96], ulsch->harq_processes[harq_pid]->c[r], Kr, f1f2mat_old[iind*2], f1f2mat_old[(iind*2)+1], ulsch->max_turbo_iterations,//MAX_TURBO_ITERATIONS, crc_type, (r==0) ? ulsch->harq_processes[harq_pid]->F : 0, &phy_vars_eNB->ulsch_tc_init_stats, &phy_vars_eNB->ulsch_tc_alpha_stats, &phy_vars_eNB->ulsch_tc_beta_stats, &phy_vars_eNB->ulsch_tc_gamma_stats, &phy_vars_eNB->ulsch_tc_ext_stats, &phy_vars_eNB->ulsch_tc_intl1_stats, &phy_vars_eNB->ulsch_tc_intl2_stats); stop_meas(&phy_vars_eNB->ulsch_turbo_decoding_stats); status[r] = ret; if (ret==(1+ulsch->max_turbo_iterations)) {// a Code segment is in error so break; #ifdef DEBUG_ULSCH_DECODING msg("ULSCH harq_pid %d CRC failed\n",harq_pid); #endif /* for (i=0;i %d\n",r,i,ulsch->harq_processes[harq_pid]->c[r][i]); return(ret); */ } #ifdef DEBUG_ULSCH_DECODING else msg("ULSCH harq_pid %d CRC OK : %d iterations\n",harq_pid, ret); #endif } #ifdef OMP } #endif // Reassembly of Transport block here offset = 0; // msg("F %d, Fbytes %d\n",ulsch->harq_processes[harq_pid]->F,ulsch->harq_processes[harq_pid]->F>>3); ret = 1; for (r=0;rharq_processes[harq_pid]->C;r++) { if (status[r] != (1+ulsch->max_turbo_iterations)) { if (rharq_processes[harq_pid]->Cminus) Kr = ulsch->harq_processes[harq_pid]->Kminus; else Kr = ulsch->harq_processes[harq_pid]->Kplus; Kr_bytes = Kr>>3; if (r==0) { memcpy(ulsch->harq_processes[harq_pid]->b, &ulsch->harq_processes[harq_pid]->c[0][(ulsch->harq_processes[harq_pid]->F>>3)], Kr_bytes - (ulsch->harq_processes[harq_pid]->F>>3) - ((ulsch->harq_processes[harq_pid]->C>1)?3:0)); offset = Kr_bytes - (ulsch->harq_processes[harq_pid]->F>>3) - ((ulsch->harq_processes[harq_pid]->C>1)?3:0); // msg("copied %d bytes to b sequence\n", // Kr_bytes - (ulsch->harq_processes[harq_pid]->F>>3)); } else { memcpy(ulsch->harq_processes[harq_pid]->b+offset, ulsch->harq_processes[harq_pid]->c[r], Kr_bytes - ((ulsch->harq_processes[harq_pid]->C>1)?3:0)); offset += (Kr_bytes- ((ulsch->harq_processes[harq_pid]->C>1)?3:0)); } if (ret != (1+ulsch->max_turbo_iterations)) ret = status[r]; } else { ret = 1+ulsch->max_turbo_iterations; } } vcd_signal_dumper_dump_function_by_name(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_ULSCH_DECODING,0); return(ret); } #ifdef PHY_ABSTRACTION #ifdef PHY_ABSTRACTION_UL int ulsch_abstraction(double* sinr_dB, uint8_t TM, uint8_t mcs,uint16_t nrb, uint16_t frb) { int index,ii; double sinr_eff = 0; int rb_count = 0; int offset; double bler = 0; TM = TM-1; sinr_eff = sinr_dB[frb]; //the single sinr_eff value we calculated with MMSE FDE formula in init_snr_up function sinr_eff *= 10; sinr_eff = floor(sinr_eff); sinr_eff /= 10; LOG_D(PHY,"[ABSTRACTION] sinr_eff after rounding = %f\n",sinr_eff); for (index = 0; index < 16; index++) { if(index == 0) { if (sinr_eff < sinr_bler_map_up[mcs][0][index]) { bler = 1; break; } } if (sinr_eff == sinr_bler_map_up[mcs][0][index]) { bler = sinr_bler_map_up[mcs][1][index]; } } #ifdef USER_MODE // need to be adapted for the emulation in the kernel space if (uniformrandom() < bler) { LOG_I(OCM,"abstraction_decoding failed (mcs=%d, sinr_eff=%f, bler=%f)\n",mcs,sinr_eff,bler); return(0); } else { LOG_I(OCM,"abstraction_decoding successful (mcs=%d, sinr_eff=%f, bler=%f)\n",mcs,sinr_eff,bler); return(1); } #endif } int ulsch_abstraction_MIESM(double* sinr_dB,uint8_t TM, uint8_t mcs,uint16_t nrb, uint16_t frb) { int index; double sinr_eff = 0; double sinr_db1 = 0; double sinr_db2 = 0; double SI=0; double RBIR=0; int rb_count = 0; int offset, M=0; double bler = 0; int start,middle,end; TM = TM-1; for (offset = frb; offset <= (frb + nrb -1); offset++) { rb_count++; //we need to do the table lookups here for the mutual information corresponding to the certain sinr_dB. sinr_db1 = sinr_dB[offset*2]; sinr_db2 = sinr_dB[offset*2+1]; msg("sinr_db1=%f\n,sinr_db2=%f\n",sinr_db1,sinr_db2); //rounding up for the table lookup sinr_db1 *= 10; sinr_db2 *= 10; sinr_db1 = floor(sinr_db1); sinr_db2 = floor(sinr_db2); if ((int)sinr_db1%2) { sinr_db1 += 1; } if ((int)sinr_db2%2) { sinr_db2 += 1; } sinr_db1 /= 10; sinr_db2 /= 10; if(mcs<10){ //for sinr_db1 for (index = 0; index < 162; index++) { if (sinr_db1 < MI_map_4qam[0][0]) { SI += (MI_map_4qam[1][0]/beta1_dlsch_MI[TM][mcs]); M +=2; break; } if (sinr_db1 > MI_map_4qam[0][161]) { SI += (MI_map_4qam[1][161]/beta1_dlsch_MI[TM][mcs]); M +=2; break; } if (sinr_db1 == MI_map_4qam[0][index]) { SI += (MI_map_4qam[1][index]/beta1_dlsch_MI[TM][mcs]); M +=2; break; } } //for sinr_db2 for (index = 0; index < 162; index++) { if (sinr_db2 < MI_map_4qam[0][0]) { SI += (MI_map_4qam[1][0]/beta1_dlsch_MI[TM][mcs]); M +=2; break; } if (sinr_db2 > MI_map_4qam[0][161]) { SI += (MI_map_4qam[1][161]/beta1_dlsch_MI[TM][mcs]); M +=2; break; } if (sinr_db2 == MI_map_4qam[0][index]) { SI += (MI_map_4qam[1][index]/beta1_dlsch_MI[TM][mcs]); M +=2; break; } } } else if(mcs>9 && mcs<17) { //for sinr_db1 for (index = 0; index < 197; index++) { if (sinr_db1 < MI_map_16qam[0][0]) { SI += (MI_map_16qam[1][0]/beta1_dlsch_MI[TM][mcs]); M +=4; break; } if (sinr_db1 > MI_map_16qam[0][196]) { SI += (MI_map_16qam[1][196]/beta1_dlsch_MI[TM][mcs]); M +=4; break; } if (sinr_db1 == MI_map_16qam[0][index]) { SI += (MI_map_16qam[1][index]/beta1_dlsch_MI[TM][mcs]); M +=4; break; } } //for sinr_db2 for (index = 0; index < 197; index++) { if (sinr_db2 < MI_map_16qam[0][0]) { SI += (MI_map_16qam[1][0]/beta1_dlsch_MI[TM][mcs]); M +=4; break; } if (sinr_db2 > MI_map_16qam[0][196]) { SI += (MI_map_16qam[1][196]/beta1_dlsch_MI[TM][mcs]); M +=4; break; } if (sinr_db2 == MI_map_16qam[0][index]) { SI += (MI_map_16qam[1][index]/beta1_dlsch_MI[TM][mcs]); M +=4; break; } } } else if(mcs>16 && mcs<22) { //for sinr_db1 for (index = 0; index < 227; index++) { if (sinr_db1 < MI_map_64qam[0][0]) { SI += (MI_map_64qam[1][0]/beta1_dlsch_MI[TM][mcs]); M +=6; break; } if (sinr_db1 > MI_map_64qam[0][226]) { SI += (MI_map_64qam[1][226]/beta1_dlsch_MI[TM][mcs]); M +=6; break; } if (sinr_db1 == MI_map_64qam[0][index]) { SI += (MI_map_64qam[1][index]/beta1_dlsch_MI[TM][mcs]); M +=6; break; } } //for sinr_db2 for (index = 0; index < 227; index++) { if (sinr_db2 < MI_map_64qam[0][0]) { SI += (MI_map_64qam[1][0]/beta1_dlsch_MI[TM][mcs]); M +=6; break; } if (sinr_db2 > MI_map_64qam[0][226]) { SI += (MI_map_64qam[1][226]/beta1_dlsch_MI[TM][mcs]); M +=6; break; } if (sinr_db2 == MI_map_64qam[0][index]) { SI += (MI_map_64qam[1][index]/beta1_dlsch_MI[TM][mcs]); M +=6; break; } } } } // } RBIR = SI/M; //Now RBIR->SINR_effective Mapping //binary search method is performed here if(mcs<10){ start = 0; end = 161; middle = end/2; if (RBIR <= MI_map_4qam[2][start]) { sinr_eff = MI_map_4qam[0][start]; } else { if (RBIR >= MI_map_4qam[2][end]) sinr_eff = MI_map_4qam[0][end]; else {//while((end-start > 1) && (RBIR >= MI_map_4qam[2])) if (RBIR < MI_map_4qam[2][middle]){ end = middle; middle = end/2; } else{ start = middle; middle = (end-middle)/2; } } for (; end>start; end--){ if ((RBIR < MI_map_4qam[2][end]) && (RBIR > MI_map_4qam[2][end-2])){ sinr_eff = MI_map_4qam[0][end-1]; break; } } } sinr_eff = sinr_eff * beta2_dlsch_MI[TM][mcs]; } else if (mcs>9 && mcs<17) { start = 0; end = 196; middle = end/2; if (RBIR <= MI_map_16qam[2][start]) { sinr_eff = MI_map_16qam[0][start]; } else { if (RBIR >= MI_map_16qam[2][end]) sinr_eff = MI_map_16qam[0][end]; else { //while((end-start > 1) && (RBIR >= MI_map_4qam[2])) if (RBIR < MI_map_16qam[2][middle]){ end = middle; middle = end/2; } else{ start = middle; middle = (end-middle)/2; } } for (; end>start; end--){ if ((RBIR < MI_map_16qam[2][end]) && (RBIR > MI_map_16qam[2][end-2])){ sinr_eff = MI_map_16qam[0][end-1]; break; } } } sinr_eff = sinr_eff * beta2_dlsch_MI[TM][mcs]; } else if (mcs>16) { start = 0; end = 226; middle = end/2; if (RBIR <= MI_map_64qam[2][start]) { sinr_eff = MI_map_64qam[0][start]; } else { if (RBIR >= MI_map_64qam[2][end]) sinr_eff = MI_map_64qam[0][end]; else { //while((end-start > 1) && (RBIR >= MI_map_4qam[2])) if (RBIR < MI_map_64qam[2][middle]){ end = middle; middle = end/2; } else{ start = middle; middle = (end-middle)/2; } } for (; end>start; end--){ if ((RBIR < MI_map_64qam[2][end]) && (RBIR > MI_map_64qam[2][end-2])){ sinr_eff = MI_map_64qam[0][end-1]; break; } } } sinr_eff = sinr_eff * beta2_dlsch_MI[TM][mcs]; } printf("SINR_Eff = %e\n",sinr_eff); sinr_eff *= 10; sinr_eff = floor(sinr_eff); // if ((int)sinr_eff%2) { // sinr_eff += 1; // } sinr_eff /= 10; msg("sinr_eff after rounding = %f\n",sinr_eff); for (index = 0; index < 16; index++) { if(index == 0) { if (sinr_eff < sinr_bler_map_up[mcs][0][index]) { bler = 1; break; } } if (sinr_eff == sinr_bler_map_up[mcs][0][index]) { bler = sinr_bler_map_up[mcs][1][index]; } } #ifdef USER_MODE // need to be adapted for the emulation in the kernel space if (uniformrandom() < bler) { msg("abstraction_decoding failed (mcs=%d, sinr_eff=%f, bler=%f)\n",mcs,sinr_eff,bler); return(0); } else { msg("abstraction_decoding successful (mcs=%d, sinr_eff=%f, bler=%f)\n",mcs,sinr_eff,bler); return(1); } #endif } #endif uint32_t ulsch_decoding_emul(PHY_VARS_eNB *phy_vars_eNB, uint8_t subframe, uint8_t UE_index, uint16_t *crnti) { uint8_t UE_id; uint16_t rnti; uint8_t harq_pid = subframe2harq_pid(&phy_vars_eNB->lte_frame_parms,((subframe>=8)?-1:0)+phy_vars_eNB->frame,subframe); rnti = phy_vars_eNB->ulsch_eNB[UE_index]->rnti; #ifdef DEBUG_PHY LOG_D(PHY,"[eNB %d] ulsch_decoding_emul : subframe %d UE_index %d harq_pid %d rnti %x\n",phy_vars_eNB->Mod_id,subframe,UE_index,harq_pid,rnti); #endif for (UE_id=0;UE_idlte_ue_pdcch_vars[0]->crnti) break; /* msg("[PHY] EMUL eNB %d ulsch_decoding_emul : subframe ue id %d crnti %x nb ue %d\n", phy_vars_eNB->Mod_id, UE_id, PHY_vars_UE_g[UE_id]->lte_ue_pdcch_vars[0]->crnti, NB_UE_INST); */ } if (UE_id==NB_UE_INST) { LOG_W(PHY,"[eNB %d] ulsch_decoding_emul: FATAL, didn't find UE with rnti %x (UE index %d)\n", phy_vars_eNB->Mod_id, rnti, UE_index); return(1+phy_vars_eNB->ulsch_eNB[UE_id]->max_turbo_iterations); } else { LOG_D(PHY,"[eNB %d] Found UE with rnti %x => UE_id %d\n",phy_vars_eNB->Mod_id, rnti, UE_id); } if (PHY_vars_UE_g[UE_id]->ulsch_ue[0]->harq_processes[harq_pid]->status == CBA_ACTIVE){ *crnti = rnti; PHY_vars_UE_g[UE_id]->ulsch_ue[0]->harq_processes[harq_pid]->status=IDLE; } else *crnti = 0x0; // Do abstraction here to determine if packet it in error /* if (ulsch_abstraction_MIESM(phy_vars_eNB->sinr_dB_eNB,1, phy_vars_eNB->ulsch_eNB[UE_id]->harq_processes[harq_pid]->mcs,phy_vars_eNB->ulsch_eNB[UE_id]->harq_processes[harq_pid]->nb_rb, phy_vars_eNB->ulsch_eNB[UE_id]->harq_processes[harq_pid]->first_rb) == 1) flag = 1; else flag = 0;*/ /* //SINRdbPost = phy_vars_eNB->sinr_dB_eNB; mcsPost = phy_vars_eNB->ulsch_eNB[UE_id]->harq_processes[harq_pid]->mcs, nrbPost = phy_vars_eNB->ulsch_eNB[UE_id]->harq_processes[harq_pid]->nb_rb; frbPost = phy_vars_eNB->ulsch_eNB[UE_id]->harq_processes[harq_pid]->first_rb; if(nrbPost > 0) { SINRdbPost = phy_vars_eNB->sinr_dB_eNB; ULflag1 = 1; } else { SINRdbPost = NULL ; ULflag1 = 0 ; }*/ // // write_output("postprocSINR.m","SINReNB",phy_vars_eNB->sinr_dB,301,1,7); //Yazdir buraya her frame icin 300 eNb // fprintf(SINRrx,"%e,%e,%e,%e;\n",SINRdbPost); //fprintf(SINRrx,"%e\n",SINRdbPost); // fprintf(csv_fd,"%e+i*(%e),",channelx,channely); // if (ulsch_abstraction(phy_vars_eNB->sinr_dB,1, phy_vars_eNB->ulsch_eNB[UE_id]->harq_processes[harq_pid]->mcs,phy_vars_eNB->ulsch_eNB[UE_id]->harq_processes[harq_pid]->nb_rb, phy_vars_eNB->ulsch_eNB[UE_id]->harq_processes[harq_pid]->first_rb) == 1) { if (1) { LOG_D(PHY,"ulsch_decoding_emul abstraction successful\n"); memcpy(phy_vars_eNB->ulsch_eNB[UE_index]->harq_processes[harq_pid]->b, PHY_vars_UE_g[UE_id]->ulsch_ue[0]->harq_processes[harq_pid]->b, phy_vars_eNB->ulsch_eNB[UE_index]->harq_processes[harq_pid]->TBS>>3); // get local ue's ack if ((UE_index >= oai_emulation.info.first_ue_local) ||(UE_index <(oai_emulation.info.first_ue_local+oai_emulation.info.nb_ue_local))){ get_ack(&phy_vars_eNB->lte_frame_parms, PHY_vars_UE_g[UE_id]->dlsch_ue[0][0]->harq_ack, subframe, phy_vars_eNB->ulsch_eNB[UE_index]->o_ACK); }else { // get remote UEs' ack phy_vars_eNB->ulsch_eNB[UE_index]->o_ACK[0] = PHY_vars_UE_g[UE_id]->ulsch_ue[0]->o_ACK[0]; phy_vars_eNB->ulsch_eNB[UE_index]->o_ACK[1] = PHY_vars_UE_g[UE_id]->ulsch_ue[0]->o_ACK[1]; } // Do abstraction of PUSCH feedback #ifdef DEBUG_PHY LOG_D(PHY,"[eNB %d][EMUL] ue index %d UE_id %d: subframe %d : o_ACK (%d %d), cqi (val %d, len %d)\n", phy_vars_eNB->Mod_id,UE_index, UE_id, subframe,phy_vars_eNB->ulsch_eNB[UE_index]->o_ACK[0], phy_vars_eNB->ulsch_eNB[UE_index]->o_ACK[1], ((HLC_subband_cqi_rank1_2A_5MHz *)PHY_vars_UE_g[UE_id]->ulsch_ue[0]->o)->cqi1, PHY_vars_UE_g[UE_id]->ulsch_ue[0]->O); #endif phy_vars_eNB->ulsch_eNB[UE_index]->Or1 = PHY_vars_UE_g[UE_id]->ulsch_ue[0]->O; phy_vars_eNB->ulsch_eNB[UE_index]->Or2 = PHY_vars_UE_g[UE_id]->ulsch_ue[0]->O; phy_vars_eNB->ulsch_eNB[UE_index]->uci_format = PHY_vars_UE_g[UE_id]->ulsch_ue[0]->uci_format; memcpy(phy_vars_eNB->ulsch_eNB[UE_index]->o,PHY_vars_UE_g[UE_id]->ulsch_ue[0]->o,MAX_CQI_BYTES); memcpy(phy_vars_eNB->ulsch_eNB[UE_index]->o_RI,PHY_vars_UE_g[UE_id]->ulsch_ue[0]->o_RI,2); phy_vars_eNB->ulsch_eNB[UE_index]->cqi_crc_status = 1; return(1); } else { LOG_W(PHY,"[eNB %d] ulsch_decoding_emul abstraction failed for UE %d\n",phy_vars_eNB->Mod_id,UE_index); phy_vars_eNB->ulsch_eNB[UE_index]->cqi_crc_status = 0; // retransmission return(1+phy_vars_eNB->ulsch_eNB[UE_index]->max_turbo_iterations); } } #endif