/* * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The OpenAirInterface Software Alliance licenses this file to You under * the OAI Public License, Version 1.1 (the "License"); you may not use this file * except in compliance with the License. * You may obtain a copy of the License at * * http://www.openairinterface.org/?page_id=698 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. *------------------------------------------------------------------------------- * For more information about the OpenAirInterface (OAI) Software Alliance: * contact@openairinterface.org */ /*! \file PHY/LTE_TRANSPORT/dci_nr.c * \brief Implements PDCCH physical channel TX/RX procedures (36.211) and DCI encoding/decoding (36.212/36.213). Current LTE compliance V8.6 2009-03. * \author R. Knopp, A. Mico Pereperez * \date 2018 * \version 0.1 * \company Eurecom * \email: knopp@eurecom.fr * \note * \warning */ #ifdef USER_MODE #include <stdio.h> #include <stdlib.h> #include <string.h> #endif //#include "PHY/defs.h" #include "PHY/defs_nr_UE.h" #include "PHY/CODING/nrPolar_tools/nr_polar_dci_defs.h" #include "PHY/phy_extern_nr_ue.h" #include "PHY/CODING/coding_extern.h" //#include "PHY/extern.h" //#include "SCHED/defs.h" //#include "SIMULATION/TOOLS/defs.h" // for taus #include "PHY/sse_intrin.h" #include "assertions.h" #include "T.h" //#define DEBUG_DCI_ENCODING 1 //#define DEBUG_DCI_DECODING 1 //#define DEBUG_PHY //#define NR_LTE_PDCCH_DCI_SWITCH #define NR_PDCCH_DCI_RUN // activates new nr functions #define NR_PDCCH_DCI_DEBUG // activates NR_PDCCH_DCI_DEBUG logs #define NR_NBR_CORESET_ACT_BWP 3 // The number of CoreSets per BWP is limited to 3 (including initial CORESET: ControlResourceId 0) #define NR_NBR_SEARCHSPACE_ACT_BWP 10 // The number of SearSpaces per BWP is limited to 10 (including initial SEARCHSPACE: SearchSpaceId 0) #define PDCCH_TEST_POLAR_TEMP_FIX //#undef ALL_AGGREGATION //extern uint16_t phich_reg[MAX_NUM_PHICH_GROUPS][3]; //extern uint16_t pcfich_reg[4]; /*uint32_t check_phich_reg(NR_DL_FRAME_PARMS *frame_parms,uint32_t kprime,uint8_t lprime,uint8_t mi) { uint16_t i; uint16_t Ngroup_PHICH = (frame_parms->phich_config_common.phich_resource*frame_parms->N_RB_DL)/48; uint16_t mprime; uint16_t *pcfich_reg = frame_parms->pcfich_reg; if ((lprime>0) && (frame_parms->Ncp==0) ) return(0); // printf("check_phich_reg : mi %d\n",mi); // compute REG based on symbol if ((lprime == 0)|| ((lprime==1)&&(frame_parms->nb_antenna_ports_eNB == 4))) mprime = kprime/6; else mprime = kprime>>2; // check if PCFICH uses mprime if ((lprime==0) && ((mprime == pcfich_reg[0]) || (mprime == pcfich_reg[1]) || (mprime == pcfich_reg[2]) || (mprime == pcfich_reg[3]))) { #ifdef DEBUG_DCI_ENCODING printf("[PHY] REG %d allocated to PCFICH\n",mprime); #endif return(1); } // handle Special subframe case for TDD !!! // printf("Checking phich_reg %d\n",mprime); if (mi > 0) { if (((frame_parms->phich_config_common.phich_resource*frame_parms->N_RB_DL)%48) > 0) Ngroup_PHICH++; if (frame_parms->Ncp == 1) { Ngroup_PHICH<<=1; } for (i=0; i<Ngroup_PHICH; i++) { if ((mprime == frame_parms->phich_reg[i][0]) || (mprime == frame_parms->phich_reg[i][1]) || (mprime == frame_parms->phich_reg[i][2])) { #ifdef DEBUG_DCI_ENCODING printf("[PHY] REG %d (lprime %d) allocated to PHICH\n",mprime,lprime); #endif return(1); } } } return(0); }*/ uint16_t extract_crc(uint8_t *dci,uint8_t dci_len) { uint16_t crc16; // uint8_t i; /* uint8_t crc; crc = ((uint16_t *)dci)[DCI_LENGTH>>4]; printf("crc1: %x, shift %d (DCI_LENGTH %d)\n",crc,DCI_LENGTH&0xf,DCI_LENGTH); crc = (crc>>(DCI_LENGTH&0xf)); // clear crc bits ((uint16_t *)dci)[DCI_LENGTH>>4] &= (0xffff>>(16-(DCI_LENGTH&0xf))); printf("crc2: %x, dci0 %x\n",crc,((int16_t *)dci)[DCI_LENGTH>>4]); crc |= (((uint16_t *)dci)[1+(DCI_LENGTH>>4)])<<(16-(DCI_LENGTH&0xf)); // clear crc bits (((uint16_t *)dci)[1+(DCI_LENGTH>>4)]) = 0; printf("extract_crc: crc %x\n",crc); */ #ifdef DEBUG_DCI_DECODING LOG_I(PHY,"dci_crc (%x,%x,%x), dci_len&0x7=%d\n",dci[dci_len>>3],dci[1+(dci_len>>3)],dci[2+(dci_len>>3)], dci_len&0x7); #endif if ((dci_len&0x7) > 0) { ((uint8_t *)&crc16)[0] = dci[1+(dci_len>>3)]<<(dci_len&0x7) | dci[2+(dci_len>>3)]>>(8-(dci_len&0x7)); ((uint8_t *)&crc16)[1] = dci[(dci_len>>3)]<<(dci_len&0x7) | dci[1+(dci_len>>3)]>>(8-(dci_len&0x7)); } else { ((uint8_t *)&crc16)[0] = dci[1+(dci_len>>3)]; ((uint8_t *)&crc16)[1] = dci[(dci_len>>3)]; } #ifdef DEBUG_DCI_DECODING LOG_I(PHY,"dci_crc =>%x\n",crc16); #endif // dci[(dci_len>>3)]&=(0xffff<<(dci_len&0xf)); // dci[(dci_len>>3)+1] = 0; // dci[(dci_len>>3)+2] = 0; return((uint16_t)crc16); } static uint8_t d[3*(MAX_DCI_SIZE_BITS + 16) + 96]; static uint8_t w[3*3*(MAX_DCI_SIZE_BITS+16)]; void dci_encoding(uint8_t *a, uint8_t A, uint16_t E, uint8_t *e, uint16_t rnti) { uint8_t D = (A + 16); uint32_t RCC; #ifdef DEBUG_DCI_ENCODING int32_t i; #endif // encode dci #ifdef DEBUG_DCI_ENCODING printf("Doing DCI encoding for %d bits, e %p, rnti %x\n",A,e,rnti); #endif memset((void *)d,LTE_NULL,96); ccodelte_encode(A,2,a,d+96,rnti); #ifdef DEBUG_DCI_ENCODING for (i=0; i<16+A; i++) printf("%d : (%d,%d,%d)\n",i,*(d+96+(3*i)),*(d+97+(3*i)),*(d+98+(3*i))); #endif #ifdef DEBUG_DCI_ENCODING printf("Doing DCI interleaving for %d coded bits, e %p\n",D*3,e); #endif RCC = sub_block_interleaving_cc(D,d+96,w); #ifdef DEBUG_DCI_ENCODING printf("Doing DCI rate matching for %d channel bits, RCC %d, e %p\n",E,RCC,e); #endif lte_rate_matching_cc(RCC,E,w,e); } uint8_t *generate_dci0(uint8_t *dci, uint8_t *e, uint8_t DCI_LENGTH, uint8_t aggregation_level, uint16_t rnti) { uint16_t coded_bits; uint8_t dci_flip[8]; if (aggregation_level>3) { printf("dci.c: generate_dci FATAL, illegal aggregation_level %d\n",aggregation_level); return NULL; } coded_bits = 72 * (1<<aggregation_level); /* #ifdef DEBUG_DCI_ENCODING for (i=0;i<1+((DCI_LENGTH+16)/8);i++) printf("i %d : %x\n",i,dci[i]); #endif */ if (DCI_LENGTH<=32) { dci_flip[0] = dci[3]; dci_flip[1] = dci[2]; dci_flip[2] = dci[1]; dci_flip[3] = dci[0]; } else { dci_flip[0] = dci[7]; dci_flip[1] = dci[6]; dci_flip[2] = dci[5]; dci_flip[3] = dci[4]; dci_flip[4] = dci[3]; dci_flip[5] = dci[2]; dci_flip[6] = dci[1]; dci_flip[7] = dci[0]; #ifdef DEBUG_DCI_ENCODING printf("DCI => %x,%x,%x,%x,%x,%x,%x,%x\n", dci_flip[0],dci_flip[1],dci_flip[2],dci_flip[3], dci_flip[4],dci_flip[5],dci_flip[6],dci_flip[7]); #endif } dci_encoding(dci_flip,DCI_LENGTH,coded_bits,e,rnti); return(e+coded_bits); } uint32_t Y; #define CCEBITS 72 #define CCEPERSYMBOL 33 // This is for 1200 RE #define CCEPERSYMBOL0 22 // This is for 1200 RE #define DCI_BITS_MAX ((2*CCEPERSYMBOL+CCEPERSYMBOL0)*CCEBITS) #define Msymb (DCI_BITS_MAX/2) //#define Mquad (Msymb/4) static int32_t wtemp[2][Msymb]; void pdcch_interleaving(NR_DL_FRAME_PARMS *frame_parms,int32_t **z, int32_t **wbar,uint8_t n_symbols_pdcch,uint8_t mi) { int32_t *wptr,*wptr2,*zptr; uint32_t Mquad = get_nquad(n_symbols_pdcch,frame_parms,mi); uint32_t RCC = (Mquad>>5), ND; uint32_t row,col,Kpi,index; int32_t i,k,a; #ifdef RM_DEBUG int32_t nulled=0; #endif // printf("[PHY] PDCCH Interleaving Mquad %d (Nsymb %d)\n",Mquad,n_symbols_pdcch); if ((Mquad&0x1f) > 0) RCC++; Kpi = (RCC<<5); ND = Kpi - Mquad; k=0; for (col=0; col<32; col++) { index = bitrev_cc_dci[col]; for (row=0; row<RCC; row++) { //printf("col %d, index %d, row %d\n",col,index,row); if (index>=ND) { for (a=0; a<frame_parms->nb_antenna_ports_eNB; a++) { //printf("a %d k %d\n",a,k); wptr = &wtemp[a][k<<2]; zptr = &z[a][(index-ND)<<2]; //printf("wptr=%p, zptr=%p\n",wptr,zptr); wptr[0] = zptr[0]; wptr[1] = zptr[1]; wptr[2] = zptr[2]; wptr[3] = zptr[3]; } k++; } index+=32; } } // permutation for (i=0; i<Mquad; i++) { for (a=0; a<frame_parms->nb_antenna_ports_eNB; a++) { //wptr = &wtemp[a][i<<2]; //wptr2 = &wbar[a][((i+frame_parms->Nid_cell)%Mquad)<<2]; wptr = &wtemp[a][((i+frame_parms->Nid_cell)%Mquad)<<2]; wptr2 = &wbar[a][i<<2]; wptr2[0] = wptr[0]; wptr2[1] = wptr[1]; wptr2[2] = wptr[2]; wptr2[3] = wptr[3]; } } } #ifdef NR_PDCCH_DCI_RUN void nr_pdcch_demapping_deinterleaving(uint16_t *llr, uint16_t *z, NR_DL_FRAME_PARMS *frame_parms, uint8_t coreset_time_dur, uint32_t coreset_nbr_rb, uint8_t reg_bundle_size_L, uint8_t coreset_interleaver_size_R, uint8_t n_shift){ /* * This function will do demapping and deinterleaving from llr containing demodulated symbols * Demapping will regroup in REG and bundles * Deinterleaving will order the bundles * * In the following example we can see the process. The llr contains the demodulated IQs, but they are not ordered from REG 0,1,2,.. * In e_rx (z) we will order the REG ids and group them into bundles. * Then we will put the bundles in the correct order as indicated in subclause 7.3.2.2 * llr --------------------------> e_rx (z) ----> e_rx (z) | ... | ... | REG 26 symbol 2 | ... | ... | REG 5 | REG 2 | ... | ... | REG 25 symbol 1 | ... | ... | REG 4 | REG 1 | ... | ... ... ... | REG 24 (bundle 7) ... ... symbol 0 | ... bundle 3 bundle 6 | ... bundle 2 bundle 1 | REG 3 bundle 1 bundle 7 | REG 0 (bundle 0) bundle 0 bundle 0 */ int c=0,r=0; uint16_t bundle_j=0, f_bundle_j,f_reg; uint32_t coreset_C; uint16_t index_z, index_llr; int coreset_interleaved = 0; if (reg_bundle_size_L!=0){ // interleaving will be done only if reg_bundle_size_L != 0 coreset_interleaved=1; coreset_C = (uint32_t)((coreset_nbr_rb * coreset_time_dur)/ (coreset_interleaver_size_R*reg_bundle_size_L)); } else { reg_bundle_size_L=6; } for(int reg=0; reg<((coreset_nbr_rb*coreset_time_dur)); reg++){ if ((reg%reg_bundle_size_L) == 0){ if (r == coreset_interleaver_size_R) { r=0; c++; } bundle_j = (c*coreset_interleaver_size_R)+r; f_bundle_j = ((r*coreset_C)+c+n_shift)%((coreset_nbr_rb*coreset_time_dur)/reg_bundle_size_L); if (coreset_interleaved==0) f_bundle_j=bundle_j; #ifndef NR_PDCCH_DCI_DEBUG printf("\n\t\t<-NR_PDCCH_DCI_DEBUG (nr_pdcch_demapping_deinterleaving)-> [r=%d,c=%d] bundle_j(%d) interleaved at f_bundle_j(%d)\n",r,c,bundle_j,f_bundle_j); #endif } f_reg = (f_bundle_j*reg_bundle_size_L)+(reg%reg_bundle_size_L); //index_z = 9*reg; index_z = 9*(uint16_t)floor(reg/coreset_time_dur) + (9*coreset_nbr_rb)*(reg%coreset_time_dur); //index_llr = 9*(((uint16_t)floor(f_reg/reg_bundle_size_L)+(f_reg)%coreset_time_dur))*(coreset_nbr_rb); index_llr = 9*((uint16_t)floor(f_reg/coreset_time_dur)+((f_reg%coreset_time_dur)*(coreset_nbr_rb))); for (int i=0; i<9; i++){ z[index_z + i] = llr[index_llr + i]; #ifndef NR_PDCCH_DCI_DEBUG printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_pdcch_demapping_deinterleaving)-> [reg=%d,bundle_j=%d] z[%d]=(%d,%d) <-> \t[f_reg=%d,fbundle_j=%d] llr[%d]=(%d,%d) \n", reg,bundle_j,(index_z + i),*(char*) &z[index_z + i],*(1 + (char*) &z[index_z + i]), f_reg,f_bundle_j,(index_llr + i),*(char*) &llr[index_llr + i], *(1 + (char*) &llr[index_llr + i])); #endif } if ((reg%reg_bundle_size_L) == 0) r++; } } #if 0 void nr_pdcch_demapping(uint16_t *llr, uint16_t *wbar, NR_DL_FRAME_PARMS *frame_parms, uint8_t coreset_time_dur, uint32_t coreset_nbr_rb) { /* * LLR contains the PDCCH for the coreset_time_dur symbols in the following sequence: * * The REGs have to be numbered in increasing order in a time-first manner, * starting with 0 for the first OFDM symbol and the lowest-numbered resource * block in the control resource set * * | ... | ... | ... | * | REG 3 | REG 4 | REG 5 | * | REG 0 | REG 1 | REG 2 | * | symbol0 | symbol1 | symbol2 | * * ................. * ___________REG 1+2l * ___________REG 1+l * symbol 1___REG 1 * ................. * ___________REG 2l * ___________REG l * symbol 0___REG 0 * * WBAR will contain the PDCCH organized in REGx where x will be consecutive: * REG 0 * REG 1 * REG 2 * ... * REG l * REG 1+l * REG 2+l * ... * */ uint32_t m,i,k,l; uint32_t num_re_pdcch = 12 * coreset_nbr_rb; i=0; m=0; for (k=0; k<num_re_pdcch; k++) { for (l=0; l < coreset_time_dur ; l++) { if ((k%12==1)||(k%12==5)||(k%12==9)){ #ifdef NR_PDCCH_DCI_DEBUG printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_pdcch_demapping)-> k,l=(%d,%d) DM-RS PDCCH signal\n",k,l); #endif } else { if ((m%9)==0 && (m !=0) && (l==0)) { #ifdef NR_PDCCH_DCI_DEBUG printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_pdcch_demapping)-> we have modified m: old_m=%d, new_m=%d\n", m,m+(9*(coreset_time_dur-1))); #endif m=m+(9*(coreset_time_dur-1)); // to avoid overwriting m+1 when a whole REG has been completed } wbar[(l*9)+m] = llr[(l*9*coreset_nbr_rb)+i]; #ifdef NR_PDCCH_DCI_DEBUG printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_pdcch_demapping)-> k,l=(%d,%d) i,m=(%d,%d) REG (%d) > wbar(%d,%d) \t llr[%d]->wbar[%d]\n", k,l,i,m, (m+(l*9)) / 9, *(char*) &wbar[m+(l*9)], *(1 + (char*) &wbar[m+(l*9)]), (l*9*coreset_nbr_rb)+i,m+(l*9)); #endif if (l==coreset_time_dur-1) { i++; m++; } } } } } #endif //0 #endif void pdcch_demapping(uint16_t *llr,uint16_t *wbar,NR_DL_FRAME_PARMS *frame_parms,uint8_t num_pdcch_symbols,uint8_t mi) { uint32_t i, lprime; uint16_t kprime,kprime_mod12,mprime,symbol_offset,tti_offset,tti_offset0; int16_t re_offset,re_offset0; // This is the REG allocation algorithm from 36-211, second part of Section 6.8.5 int Msymb2; switch (frame_parms->N_RB_DL) { case 100: Msymb2 = Msymb; break; case 75: Msymb2 = 3*Msymb/4; break; case 50: Msymb2 = Msymb>>1; break; case 25: Msymb2 = Msymb>>2; break; case 15: Msymb2 = Msymb*15/100; break; case 6: Msymb2 = Msymb*6/100; break; default: Msymb2 = Msymb>>2; break; } mprime=0; re_offset = 0; re_offset0 = 0; // counter for symbol with pilots (extracted outside!) for (kprime=0; kprime<frame_parms->N_RB_DL*12; kprime++) { for (lprime=0; lprime<num_pdcch_symbols; lprime++) { symbol_offset = (uint32_t)frame_parms->N_RB_DL*12*lprime; tti_offset = symbol_offset + re_offset; tti_offset0 = symbol_offset + re_offset0; // if REG is allocated to PHICH, skip it if (check_phich_reg(frame_parms,kprime,lprime,mi) == 1) { // printf("dci_demapping : skipping REG %d (RE %d)\n",(lprime==0)?kprime/6 : kprime>>2,kprime); if ((lprime == 0)&&((kprime%6)==0)) re_offset0+=4; } else { // not allocated to PHICH/PCFICH // printf("dci_demapping: REG %d\n",(lprime==0)?kprime/6 : kprime>>2); if (lprime == 0) { // first symbol, or second symbol+4 TX antennas skip pilots kprime_mod12 = kprime%12; if ((kprime_mod12 == 0) || (kprime_mod12 == 6)) { // kprime represents REG for (i=0; i<4; i++) { wbar[mprime] = llr[tti_offset0+i]; #ifdef DEBUG_DCI_DECODING // LOG_I(PHY,"PDCCH demapping mprime %d.%d <= llr %d (symbol %d re %d) -> (%d,%d)\n",mprime/4,i,tti_offset0+i,symbol_offset,re_offset0,*(char*)&wbar[mprime],*(1+(char*)&wbar[mprime])); #endif mprime++; re_offset0++; } } } else if ((lprime==1)&&(frame_parms->nb_antenna_ports_eNB == 4)) { // LATER!!!! } else { // no pilots in this symbol kprime_mod12 = kprime%12; if ((kprime_mod12 == 0) || (kprime_mod12 == 4) || (kprime_mod12 == 8)) { // kprime represents REG for (i=0; i<4; i++) { wbar[mprime] = llr[tti_offset+i]; #ifdef DEBUG_DCI_DECODING // LOG_I(PHY,"PDCCH demapping mprime %d.%d <= llr %d (symbol %d re %d) -> (%d,%d)\n",mprime/4,i,tti_offset+i,symbol_offset,re_offset+i,*(char*)&wbar[mprime],*(1+(char*)&wbar[mprime])); #endif mprime++; } } // is representative } // no pilots case } // not allocated to PHICH/PCFICH // Stop when all REGs are copied in if (mprime>=Msymb2) break; } //lprime loop re_offset++; } // kprime loop } static uint16_t wtemp_rx[Msymb]; #if 0 #ifdef NR_PDCCH_DCI_RUN void nr_pdcch_deinterleaving(NR_DL_FRAME_PARMS *frame_parms, uint16_t *z, uint16_t *wbar, uint8_t coreset_time_dur, uint8_t reg_bundle_size_L, uint8_t coreset_interleaver_size_R, uint8_t n_shift, uint32_t coreset_nbr_rb) { /* * This function will perform deinterleaving described in 38.211 Section 7.3.2.2 * coreset_freq_dom (bit map 45 bits: each bit indicates 6 RB in CORESET -> 1 bit MSB indicates PRB 0..6 are part of CORESET) * coreset_time_dur (1,2,3) * coreset_CCE_REG_mapping_type (interleaved, non-interleaved) * reg_bundle_size (2,3,6) */ #ifdef NR_PDCCH_DCI_DEBUG printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_pdcch_deinterleaving)-> coreset_nbr_rb=(%lld), reg_bundle_size_L=(%d), coreset_interleaver_size_R=(%d), n_shift=(%d)\n", coreset_nbr_rb,reg_bundle_size_L,coreset_interleaver_size_R,n_shift); #endif /* * First verify that CORESET is interleaved or not interleaved depending on parameter cce-REG-MappingType * if non-interleaved then do nothing: wbar table stays as it is (if REG bundle size is set to 0 by higher layer, then we consider that there is no interleaving) */ int coreset_interleaved = 1; if (reg_bundle_size_L==0) coreset_interleaved=0; /* * if interleaved then do this: wbar table has bundles interleaved. We have to de-interleave then * following procedure described in 38.211 Section 7.3.2.2: */ int c=0 ,r=-1; uint32_t bundle_id, bundle_interleaved, k, l, i=0; uint32_t coreset_C = (uint32_t)(coreset_nbr_rb * coreset_time_dur/ (coreset_interleaver_size_R*reg_bundle_size_L)); //uint16_t *wptr; //wptr = &wtemp_rx[0]; //z = &wtemp_rx[0]; bundle_id=0; for (k=0 ; k<9*coreset_nbr_rb*coreset_time_dur; k++){ #ifdef NR_PDCCH_DCI_DEBUG printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_pdcch_deinterleaving)-> k=%d \t coreset_interleaved=%d reg_bundle_size_L=%d coreset_C=%d coreset_interleaver_R=%d", k,coreset_interleaved,reg_bundle_size_L, coreset_C,coreset_interleaver_size_R); #endif if (k%(9*reg_bundle_size_L)==0) { // calculate offset properly if (r==coreset_interleaver_size_R-1) { //if (bundle_id>=(c+1)*coreset_interleaver_size_R) { c++; r=0; } else { r++; } #ifdef NR_PDCCH_DCI_DEBUG printf("\t --> time to modify bundle_interleaved and bundle_id --> r=%d c=%d\n",r,c); #endif bundle_id=c*coreset_interleaver_size_R+r; bundle_interleaved=(r*coreset_C+c+n_shift)%(coreset_nbr_rb * coreset_time_dur/reg_bundle_size_L); } if (coreset_interleaved == 1){ //wptr[i+(bundle_interleaved-bundle_id)*9*reg_bundle_size_L]=wbar[i]; #ifdef NR_PDCCH_DCI_DEBUG printf("\t\t\t\t\t wptr[%d] = (%d,%d) <-> wbar[%d]",i, *(char*) &wbar[i], *(1 + (char*) &wbar[i]),i+(bundle_interleaved-bundle_id)*9*reg_bundle_size_L); #endif z[i]=wbar[i+(bundle_interleaved-bundle_id)*9*reg_bundle_size_L]; #ifdef NR_PDCCH_DCI_DEBUG printf("\t\t bundle_id = %d \t bundle_interleaved = %d (r=%d, c=%d)\n",bundle_id,bundle_interleaved,r,c); #endif i++; } else { z[i]=wbar[i]; i++; } //bundle_id=c*coreset_interleaver_size_R+r; } } #endif #endif //0 void pdcch_deinterleaving(NR_DL_FRAME_PARMS *frame_parms,uint16_t *z, uint16_t *wbar,uint8_t number_pdcch_symbols,uint8_t mi) { uint16_t *wptr,*zptr,*wptr2; uint16_t Mquad=get_nquad(number_pdcch_symbols,frame_parms,mi); uint32_t RCC = (Mquad>>5), ND; uint32_t row,col,Kpi,index; int32_t i,k; // printf("Mquad %d, RCC %d\n",Mquad,RCC); if (!z) { printf("dci.c: pdcch_deinterleaving: FATAL z is Null\n"); return; } // undo permutation for (i=0; i<Mquad; i++) { wptr = &wtemp_rx[((i+frame_parms->Nid_cell)%Mquad)<<2]; wptr2 = &wbar[i<<2]; wptr[0] = wptr2[0]; wptr[1] = wptr2[1]; wptr[2] = wptr2[2]; wptr[3] = wptr2[3]; /* printf("pdcch_deinterleaving (%p,%p): quad %d (%d) -> (%d,%d %d,%d %d,%d %d,%d)\n",wptr,wptr2,i,(i+frame_parms->Nid_cell)%Mquad, ((char*)wptr2)[0], ((char*)wptr2)[1], ((char*)wptr2)[2], ((char*)wptr2)[3], ((char*)wptr2)[4], ((char*)wptr2)[5], ((char*)wptr2)[6], ((char*)wptr2)[7]); */ } if ((Mquad&0x1f) > 0) RCC++; Kpi = (RCC<<5); ND = Kpi - Mquad; k=0; for (col=0; col<32; col++) { index = bitrev_cc_dci[col]; for (row=0; row<RCC; row++) { // printf("row %d, index %d, Nd %d\n",row,index,ND); if (index>=ND) { wptr = &wtemp_rx[k<<2]; zptr = &z[(index-ND)<<2]; zptr[0] = wptr[0]; zptr[1] = wptr[1]; zptr[2] = wptr[2]; zptr[3] = wptr[3]; /* printf("deinterleaving ; k %d, index-Nd %d => (%d,%d,%d,%d,%d,%d,%d,%d)\n",k,(index-ND), ((int8_t *)wptr)[0], ((int8_t *)wptr)[1], ((int8_t *)wptr)[2], ((int8_t *)wptr)[3], ((int8_t *)wptr)[4], ((int8_t *)wptr)[5], ((int8_t *)wptr)[6], ((int8_t *)wptr)[7]); */ k++; } index+=32; } } for (i=0; i<Mquad; i++) { zptr = &z[i<<2]; /* printf("deinterleaving ; quad %d => (%d,%d,%d,%d,%d,%d,%d,%d)\n",i, ((int8_t *)zptr)[0], ((int8_t *)zptr)[1], ((int8_t *)zptr)[2], ((int8_t *)zptr)[3], ((int8_t *)zptr)[4], ((int8_t *)zptr)[5], ((int8_t *)zptr)[6], ((int8_t *)zptr)[7]); */ } } int32_t pdcch_qpsk_qpsk_llr(NR_DL_FRAME_PARMS *frame_parms, int32_t **rxdataF_comp, int32_t **rxdataF_comp_i, int32_t **rho_i, int16_t *pdcch_llr16, int16_t *pdcch_llr8in, uint8_t symbol) { int16_t *rxF=(int16_t*)&rxdataF_comp[0][(symbol*frame_parms->N_RB_DL*12)]; int16_t *rxF_i=(int16_t*)&rxdataF_comp_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 *llr128; int32_t i; char *pdcch_llr8; int16_t *pdcch_llr; pdcch_llr8 = (char *)&pdcch_llr8in[symbol*frame_parms->N_RB_DL*12]; pdcch_llr = &pdcch_llr16[symbol*frame_parms->N_RB_DL*12]; // printf("dlsch_qpsk_qpsk: symbol %d\n",symbol); llr128 = (int16_t*)pdcch_llr; if (!llr128) { printf("dlsch_qpsk_qpsk_llr: llr is null, symbol %d\n",symbol); return -1; } qpsk_qpsk(rxF, rxF_i, llr128, rho, frame_parms->N_RB_DL*12); //prepare for Viterbi which accepts 8 bit, but prefers 4 bit, soft input. for (i=0; i<(frame_parms->N_RB_DL*24); i++) { if (*pdcch_llr>7) *pdcch_llr8=7; else if (*pdcch_llr<-8) *pdcch_llr8=-8; else *pdcch_llr8 = (char)(*pdcch_llr); pdcch_llr++; pdcch_llr8++; } return(0); } #ifdef NR_PDCCH_DCI_RUN int32_t nr_pdcch_llr(NR_DL_FRAME_PARMS *frame_parms, int32_t **rxdataF_comp, char *pdcch_llr, uint8_t symbol,uint32_t coreset_nbr_rb) { int16_t *rxF = (int16_t*) &rxdataF_comp[0][(symbol * coreset_nbr_rb * 12)]; int32_t i; char *pdcch_llr8; pdcch_llr8 = &pdcch_llr[2 * symbol * coreset_nbr_rb * 9]; if (!pdcch_llr8) { printf("pdcch_qpsk_llr: llr is null, symbol %d\n", symbol); return (-1); } #ifdef NR_PDCCH_DCI_DEBUG printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_pdcch_llr)-> llr logs: pdcch qpsk llr for symbol %d (pos %d), llr offset %d\n",symbol,(symbol*frame_parms->N_RB_DL*12),pdcch_llr8-pdcch_llr); #endif //for (i = 0; i < (frame_parms->N_RB_DL * ((symbol == 0) ? 16 : 24)); i++) { for (i = 0; i < (coreset_nbr_rb * ((symbol == 0) ? 18 : 18)); i++) { if (*rxF > 31) *pdcch_llr8 = 31; else if (*rxF < -32) *pdcch_llr8 = -32; else *pdcch_llr8 = (char) (*rxF); #ifndef NR_PDCCH_DCI_DEBUG printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_pdcch_llr)-> llr logs: rb=%d i=%d *rxF:%d => *pdcch_llr8:%d\n",i/18,i,*rxF,*pdcch_llr8); #endif rxF++; pdcch_llr8++; } return (0); } #endif int32_t pdcch_llr(NR_DL_FRAME_PARMS *frame_parms, int32_t **rxdataF_comp, char *pdcch_llr, uint8_t symbol) { int16_t *rxF= (int16_t*) &rxdataF_comp[0][(symbol*frame_parms->N_RB_DL*12)]; int32_t i; char *pdcch_llr8; pdcch_llr8 = &pdcch_llr[2*symbol*frame_parms->N_RB_DL*12]; if (!pdcch_llr8) { printf("pdcch_qpsk_llr: llr is null, symbol %d\n",symbol); return(-1); } // printf("pdcch qpsk llr for symbol %d (pos %d), llr offset %d\n",symbol,(symbol*frame_parms->N_RB_DL*12),pdcch_llr8-pdcch_llr); for (i=0; i<(frame_parms->N_RB_DL*((symbol==0) ? 16 : 24)); i++) { if (*rxF>31) *pdcch_llr8=31; else if (*rxF<-32) *pdcch_llr8=-32; else *pdcch_llr8 = (char)(*rxF); // printf("%d %d => %d\n",i,*rxF,*pdcch_llr8); rxF++; pdcch_llr8++; } return(0); } //__m128i avg128P; //compute average channel_level on each (TX,RX) antenna pair void pdcch_channel_level(int32_t **dl_ch_estimates_ext, NR_DL_FRAME_PARMS *frame_parms, int32_t *avg, uint8_t nb_rb) { int16_t rb; uint8_t aatx,aarx; #if defined(__x86_64__) || defined(__i386__) __m128i *dl_ch128; __m128i avg128P; #elif defined(__arm__) int16x8_t *dl_ch128; int32x4_t *avg128P; #endif for (aatx=0; aatx<frame_parms->nb_antenna_ports_eNB; aatx++) for (aarx=0; aarx<frame_parms->nb_antennas_rx; aarx++) { //clear average level #if defined(__x86_64__) || defined(__i386__) avg128P = _mm_setzero_si128(); dl_ch128=(__m128i *)&dl_ch_estimates_ext[(aatx<<1)+aarx][0]; #elif defined(__arm__) #endif for (rb=0; rb<nb_rb; rb++) { #if defined(__x86_64__) || defined(__i386__) avg128P = _mm_add_epi32(avg128P,_mm_madd_epi16(dl_ch128[0],dl_ch128[0])); avg128P = _mm_add_epi32(avg128P,_mm_madd_epi16(dl_ch128[1],dl_ch128[1])); avg128P = _mm_add_epi32(avg128P,_mm_madd_epi16(dl_ch128[2],dl_ch128[2])); #elif defined(__arm__) #endif dl_ch128+=3; /* if (rb==0) { print_shorts("dl_ch128",&dl_ch128[0]); print_shorts("dl_ch128",&dl_ch128[1]); print_shorts("dl_ch128",&dl_ch128[2]); } */ } DevAssert( nb_rb ); avg[(aatx<<1)+aarx] = (((int32_t*)&avg128P)[0] + ((int32_t*)&avg128P)[1] + ((int32_t*)&avg128P)[2] + ((int32_t*)&avg128P)[3])/(nb_rb*12); // printf("Channel level : %d\n",avg[(aatx<<1)+aarx]); } #if defined(__x86_64__) || defined(__i386__) _mm_empty(); _m_empty(); #endif } #if defined(__x86_64) || defined(__i386__) __m128i mmtmpPD0,mmtmpPD1,mmtmpPD2,mmtmpPD3; #elif defined(__arm__) #endif /* void pdcch_dual_stream_correlation(NR_DL_FRAME_PARMS *frame_parms, uint8_t symbol, int32_t **dl_ch_estimates_ext, int32_t **dl_ch_estimates_ext_i, int32_t **dl_ch_rho_ext, uint8_t output_shift) { uint16_t rb; #if defined(__x86_64__) || defined(__i386__) __m128i *dl_ch128,*dl_ch128i,*dl_ch_rho128; #elif defined(__arm__) #endif uint8_t aarx; // printf("dlsch_dual_stream_correlation: symbol %d\n",symbol); for (aarx=0; aarx<frame_parms->nb_antennas_rx; aarx++) { #if defined(__x86_64__) || defined(__i386__) dl_ch128 = (__m128i *)&dl_ch_estimates_ext[aarx][symbol*frame_parms->N_RB_DL*12]; dl_ch128i = (__m128i *)&dl_ch_estimates_ext_i[aarx][symbol*frame_parms->N_RB_DL*12]; dl_ch_rho128 = (__m128i *)&dl_ch_rho_ext[aarx][symbol*frame_parms->N_RB_DL*12]; #elif defined(__arm__) #endif for (rb=0; rb<frame_parms->N_RB_DL; rb++) { // multiply by conjugated channel #if defined(__x86_64__) || defined(__i386__) mmtmpPD0 = _mm_madd_epi16(dl_ch128[0],dl_ch128i[0]); // print_ints("re",&mmtmpPD0); // mmtmpD0 contains real part of 4 consecutive outputs (32-bit) mmtmpPD1 = _mm_shufflelo_epi16(dl_ch128[0],_MM_SHUFFLE(2,3,0,1)); mmtmpPD1 = _mm_shufflehi_epi16(mmtmpPD1,_MM_SHUFFLE(2,3,0,1)); mmtmpPD1 = _mm_sign_epi16(mmtmpPD1,*(__m128i*)&conjugate[0]); // print_ints("im",&mmtmpPD1); mmtmpPD1 = _mm_madd_epi16(mmtmpPD1,dl_ch128i[0]); // mmtmpD1 contains imag part of 4 consecutive outputs (32-bit) mmtmpPD0 = _mm_srai_epi32(mmtmpPD0,output_shift); // print_ints("re(shift)",&mmtmpPD0); mmtmpPD1 = _mm_srai_epi32(mmtmpPD1,output_shift); // print_ints("im(shift)",&mmtmpPD1); mmtmpPD2 = _mm_unpacklo_epi32(mmtmpPD0,mmtmpPD1); mmtmpPD3 = _mm_unpackhi_epi32(mmtmpPD0,mmtmpPD1); // print_ints("c0",&mmtmpPD2); // print_ints("c1",&mmtmpPD3); dl_ch_rho128[0] = _mm_packs_epi32(mmtmpPD2,mmtmpPD3); //print_shorts("rx:",dl_ch128_2); //print_shorts("ch:",dl_ch128); //print_shorts("pack:",rho128); // multiply by conjugated channel mmtmpPD0 = _mm_madd_epi16(dl_ch128[1],dl_ch128i[1]); // mmtmpPD0 contains real part of 4 consecutive outputs (32-bit) mmtmpPD1 = _mm_shufflelo_epi16(dl_ch128[1],_MM_SHUFFLE(2,3,0,1)); mmtmpPD1 = _mm_shufflehi_epi16(mmtmpPD1,_MM_SHUFFLE(2,3,0,1)); mmtmpPD1 = _mm_sign_epi16(mmtmpPD1,*(__m128i*)conjugate); mmtmpPD1 = _mm_madd_epi16(mmtmpPD1,dl_ch128i[1]); // mmtmpPD1 contains imag part of 4 consecutive outputs (32-bit) mmtmpPD0 = _mm_srai_epi32(mmtmpPD0,output_shift); mmtmpPD1 = _mm_srai_epi32(mmtmpPD1,output_shift); mmtmpPD2 = _mm_unpacklo_epi32(mmtmpPD0,mmtmpPD1); mmtmpPD3 = _mm_unpackhi_epi32(mmtmpPD0,mmtmpPD1); dl_ch_rho128[1] =_mm_packs_epi32(mmtmpPD2,mmtmpPD3); //print_shorts("rx:",dl_ch128_2+1); //print_shorts("ch:",dl_ch128+1); //print_shorts("pack:",rho128+1); // multiply by conjugated channel mmtmpPD0 = _mm_madd_epi16(dl_ch128[2],dl_ch128i[2]); // mmtmpPD0 contains real part of 4 consecutive outputs (32-bit) mmtmpPD1 = _mm_shufflelo_epi16(dl_ch128[2],_MM_SHUFFLE(2,3,0,1)); mmtmpPD1 = _mm_shufflehi_epi16(mmtmpPD1,_MM_SHUFFLE(2,3,0,1)); mmtmpPD1 = _mm_sign_epi16(mmtmpPD1,*(__m128i*)conjugate); mmtmpPD1 = _mm_madd_epi16(mmtmpPD1,dl_ch128i[2]); // mmtmpPD1 contains imag part of 4 consecutive outputs (32-bit) mmtmpPD0 = _mm_srai_epi32(mmtmpPD0,output_shift); mmtmpPD1 = _mm_srai_epi32(mmtmpPD1,output_shift); mmtmpPD2 = _mm_unpacklo_epi32(mmtmpPD0,mmtmpPD1); mmtmpPD3 = _mm_unpackhi_epi32(mmtmpPD0,mmtmpPD1); dl_ch_rho128[2] = _mm_packs_epi32(mmtmpPD2,mmtmpPD3); //print_shorts("rx:",dl_ch128_2+2); //print_shorts("ch:",dl_ch128+2); //print_shorts("pack:",rho128+2); dl_ch128+=3; dl_ch128i+=3; dl_ch_rho128+=3; #elif defined(__arm__) #endif } } #if defined(__x86_64__) || defined(__i386__) _mm_empty(); _m_empty(); #endif } */ void pdcch_detection_mrc_i(NR_DL_FRAME_PARMS *frame_parms, int32_t **rxdataF_comp, int32_t **rxdataF_comp_i, int32_t **rho, int32_t **rho_i, uint8_t symbol) { uint8_t aatx; #if defined(__x86_64__) || defined(__i386__) __m128i *rxdataF_comp128_0,*rxdataF_comp128_1,*rxdataF_comp128_i0,*rxdataF_comp128_i1,*rho128_0,*rho128_1,*rho128_i0,*rho128_i1; #elif defined(__arm__) int16x8_t *rxdataF_comp128_0,*rxdataF_comp128_1,*rxdataF_comp128_i0,*rxdataF_comp128_i1,*rho128_0,*rho128_1,*rho128_i0,*rho128_i1; #endif int32_t i; if (frame_parms->nb_antennas_rx>1) { for (aatx=0; aatx<frame_parms->nb_antenna_ports_eNB; aatx++) { //if (frame_parms->mode1_flag && (aatx>0)) break; #if defined(__x86_64__) || defined(__i386__) rxdataF_comp128_0 = (__m128i *)&rxdataF_comp[(aatx<<1)][symbol*frame_parms->N_RB_DL*12]; rxdataF_comp128_1 = (__m128i *)&rxdataF_comp[(aatx<<1)+1][symbol*frame_parms->N_RB_DL*12]; #elif defined(__arm__) rxdataF_comp128_0 = (int16x8_t *)&rxdataF_comp[(aatx<<1)][symbol*frame_parms->N_RB_DL*12]; rxdataF_comp128_1 = (int16x8_t *)&rxdataF_comp[(aatx<<1)+1][symbol*frame_parms->N_RB_DL*12]; #endif // MRC on each re of rb on MF output for (i=0; i<frame_parms->N_RB_DL*3; i++) { #if defined(__x86_64__) || defined(__i386__) rxdataF_comp128_0[i] = _mm_adds_epi16(_mm_srai_epi16(rxdataF_comp128_0[i],1),_mm_srai_epi16(rxdataF_comp128_1[i],1)); #elif defined(__arm__) rxdataF_comp128_0[i] = vhaddq_s16(rxdataF_comp128_0[i],rxdataF_comp128_1[i]); #endif } } #if defined(__x86_64__) || defined(__i386__) rho128_0 = (__m128i *) &rho[0][symbol*frame_parms->N_RB_DL*12]; rho128_1 = (__m128i *) &rho[1][symbol*frame_parms->N_RB_DL*12]; #elif defined(__arm__) rho128_0 = (int16x8_t *) &rho[0][symbol*frame_parms->N_RB_DL*12]; rho128_1 = (int16x8_t *) &rho[1][symbol*frame_parms->N_RB_DL*12]; #endif for (i=0; i<frame_parms->N_RB_DL*3; i++) { #if defined(__x86_64__) || defined(__i386__) rho128_0[i] = _mm_adds_epi16(_mm_srai_epi16(rho128_0[i],1),_mm_srai_epi16(rho128_1[i],1)); #elif defined(__arm__) rho128_0[i] = vhaddq_s16(rho128_0[i],rho128_1[i]); #endif } #if defined(__x86_64__) || defined(__i386__) rho128_i0 = (__m128i *) &rho_i[0][symbol*frame_parms->N_RB_DL*12]; rho128_i1 = (__m128i *) &rho_i[1][symbol*frame_parms->N_RB_DL*12]; rxdataF_comp128_i0 = (__m128i *)&rxdataF_comp_i[0][symbol*frame_parms->N_RB_DL*12]; rxdataF_comp128_i1 = (__m128i *)&rxdataF_comp_i[1][symbol*frame_parms->N_RB_DL*12]; #elif defined(__arm__) rho128_i0 = (int16x8_t*) &rho_i[0][symbol*frame_parms->N_RB_DL*12]; rho128_i1 = (int16x8_t*) &rho_i[1][symbol*frame_parms->N_RB_DL*12]; rxdataF_comp128_i0 = (int16x8_t *)&rxdataF_comp_i[0][symbol*frame_parms->N_RB_DL*12]; rxdataF_comp128_i1 = (int16x8_t *)&rxdataF_comp_i[1][symbol*frame_parms->N_RB_DL*12]; #endif // MRC on each re of rb on MF and rho for (i=0; i<frame_parms->N_RB_DL*3; i++) { #if defined(__x86_64__) || defined(__i386__) rxdataF_comp128_i0[i] = _mm_adds_epi16(_mm_srai_epi16(rxdataF_comp128_i0[i],1),_mm_srai_epi16(rxdataF_comp128_i1[i],1)); rho128_i0[i] = _mm_adds_epi16(_mm_srai_epi16(rho128_i0[i],1),_mm_srai_epi16(rho128_i1[i],1)); #elif defined(__arm__) rxdataF_comp128_i0[i] = vhaddq_s16(rxdataF_comp128_i0[i],rxdataF_comp128_i1[i]); rho128_i0[i] = vhaddq_s16(rho128_i0[i],rho128_i1[i]); #endif } } #if defined(__x86_64__) || defined(__i386__) _mm_empty(); _m_empty(); #endif } #ifdef NR_PDCCH_DCI_RUN // This function will extract the mapped DM-RS PDCCH REs as per 38.211 Section 7.4.1.3.2 (Mapping to physical resources) void nr_pdcch_extract_rbs_single(int32_t **rxdataF, int32_t **dl_ch_estimates, int32_t **rxdataF_ext, int32_t **dl_ch_estimates_ext, uint8_t symbol, uint32_t high_speed_flag, NR_DL_FRAME_PARMS *frame_parms, uint64_t coreset_freq_dom, uint32_t coreset_nbr_rb, uint32_t n_BWP_start) { /* * This function is demapping DM-RS PDCCH RE * Implementing 38.211 Section 7.4.1.3.2 Mapping to physical resources * PDCCH DM-RS signals are mapped on RE a_k_l where: * k = 12*n + 4*kprime + 1 * n=0,1,.. * kprime=0,1,2 * According to this equations, DM-RS PDCCH are mapped on k where k%12==1 || k%12==5 || k%12==9 * */ // the bitmap coreset_frq_domain contains 45 bits #define CORESET_FREQ_DOMAIN_BITMAP_SIZE 45 // each bit is associated to 6 RBs #define BIT_TO_NBR_RB_CORESET_FREQ_DOMAIN 6 #define NBR_RE_PER_RB_WITH_DMRS 12 // after removing the 3 DMRS RE, the RB contains 9 RE with PDCCH #define NBR_RE_PER_RB_WITHOUT_DMRS 9 uint16_t c_rb, c_rb_tmp, rb, nb_rb = 0; // this variable will be incremented by 1 each time a bit set to '0' is found in coreset_freq_dom bitmap uint16_t offset_discontiguous=0; uint8_t rb_count_bit,i, j, aarx, bitcnt_coreset_freq_dom=0; int32_t *dl_ch0, *dl_ch0_ext, *rxF, *rxF_ext; int nushiftmod3 = frame_parms->nushift % 3; uint8_t symbol_mod; symbol_mod = (symbol >= (7 - frame_parms->Ncp)) ? symbol - (7 - frame_parms->Ncp) : symbol; c_rb = n_BWP_start; // c_rb is the common resource block: RB within the BWP #ifdef DEBUG_DCI_DECODING LOG_I(PHY, "extract_rbs_single: symbol_mod %d\n",symbol_mod); #endif for (aarx = 0; aarx < frame_parms->nb_antennas_rx; aarx++) { if (high_speed_flag == 1){ dl_ch0 = &dl_ch_estimates[aarx][(symbol * (frame_parms->ofdm_symbol_size))]; #ifdef NR_PDCCH_DCI_DEBUG printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_pdcch_extract_rbs_single)-> dl_ch0 = &dl_ch_estimates[aarx = (%d)][ (symbol * (frame_parms->ofdm_symbol_size (%d))) = (%d)]\n", aarx,frame_parms->ofdm_symbol_size,(symbol * (frame_parms->ofdm_symbol_size))); #endif } else { dl_ch0 = &dl_ch_estimates[aarx][0]; #ifdef NR_PDCCH_DCI_DEBUG printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_pdcch_extract_rbs_single)-> dl_ch0 = &dl_ch_estimates[aarx = (%d)][0]\n",aarx); #endif } dl_ch0_ext = &dl_ch_estimates_ext[aarx][symbol * (coreset_nbr_rb * NBR_RE_PER_RB_WITH_DMRS)]; #ifdef NR_PDCCH_DCI_DEBUG printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_pdcch_extract_rbs_single)-> dl_ch0_ext = &dl_ch_estimates_ext[aarx = (%d)][symbol * (frame_parms->N_RB_DL * 9) = (%d)]\n", aarx,symbol * (coreset_nbr_rb * NBR_RE_PER_RB_WITH_DMRS)); #endif rxF_ext = &rxdataF_ext[aarx][symbol * (coreset_nbr_rb * NBR_RE_PER_RB_WITH_DMRS)]; #ifdef NR_PDCCH_DCI_DEBUG printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_pdcch_extract_rbs_single)-> rxF_ext = &rxdataF_ext[aarx = (%d)][symbol * (frame_parms->N_RB_DL * 9) = (%d)]\n", aarx,symbol * (coreset_nbr_rb * NBR_RE_PER_RB_WITH_DMRS)); printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_pdcch_extract_rbs_single)-> (for symbol=%d, aarx=%d), symbol_mod=%d, nushiftmod3=%d \n",symbol,aarx,symbol_mod,nushiftmod3); #endif /* * The following for loop handles treatment of PDCCH contained in table rxdataF (in frequency domain) * In NR the PDCCH IQ symbols are contained within RBs in the CORESET defined by higher layers which is located within the BWP * Lets consider that the first RB to be considered as part of the CORESET and part of the PDCCH is n_BWP_start * Several cases have to be handled differently as IQ symbols are situated in different parts of rxdataF: * 1. Number of RBs in the system bandwidth is even * 1.1 The RB is < than the N_RB_DL/2 -> IQ symbols are in the second half of the rxdataF (from first_carrier_offset) * 1.2 The RB is >= than the N_RB_DL/2 -> IQ symbols are in the first half of the rxdataF (from element 0) * 2. Number of RBs in the system bandwidth is odd * (particular case when the RB with DC as it is treated differently: it is situated in symbol borders of rxdataF) * 2.1 The RB is <= than the N_RB_DL/2 -> IQ symbols are in the second half of the rxdataF (from first_carrier_offset) * 2.2 The RB is > than the N_RB_DL/2+1 -> IQ symbols are in the first half of the rxdataF (from element 0 + 2nd half RB containing DC) * 2.3 The RB is == N_RB_DL/2+1 -> IQ symbols are in the lower border of the rxdataF for first 6 IQ element and the upper border of the rxdataF for the last 6 IQ elements * If the first RB containing PDCCH within the UE BWP and within the CORESET is higher than half of the system bandwidth (N_RB_DL), * then the IQ symbol is going to be found at the position 0+c_rb-N_RB_DL/2 in rxdataF and * we have to point the pointer at (1+c_rb-N_RB_DL/2) in rxdataF */ #ifdef NR_PDCCH_DCI_DEBUG printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_pdcch_extract_rbs_single)-> n_BWP_start=%d, coreset_nbr_rb=%d\n",n_BWP_start,coreset_nbr_rb); #endif for (c_rb = n_BWP_start; c_rb < (n_BWP_start + coreset_nbr_rb + (BIT_TO_NBR_RB_CORESET_FREQ_DOMAIN * offset_discontiguous)); c_rb++) { //c_rb_tmp = 0; if (((c_rb - n_BWP_start) % BIT_TO_NBR_RB_CORESET_FREQ_DOMAIN)==0) { bitcnt_coreset_freq_dom ++; while ((((coreset_freq_dom & 0x1FFFFFFFFFFF) >> (CORESET_FREQ_DOMAIN_BITMAP_SIZE - bitcnt_coreset_freq_dom)) & 0x1)== 0){ // 46 -> 45 is number of bits in coreset_freq_dom // next 6 RB are not part of the CORESET within the BWP as bit in coreset_freq_dom is set to 0 bitcnt_coreset_freq_dom ++; //c_rb_tmp = c_rb_tmp + 6; c_rb = c_rb + BIT_TO_NBR_RB_CORESET_FREQ_DOMAIN; offset_discontiguous ++; #ifdef NR_PDCCH_DCI_DEBUG printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_pdcch_extract_rbs_single)-> we entered here as coreset_freq_dom=%llx (bit %d) is 0, coreset_freq_domain is discontiguous\n",coreset_freq_dom,(46 - bitcnt_coreset_freq_dom)); #endif } } //c_rb = c_rb + c_rb_tmp; #ifdef NR_PDCCH_DCI_DEBUG printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_pdcch_extract_rbs_single)-> c_rb=%d\n",c_rb); #endif // first we set initial conditions for pointer to rxdataF depending on the situation of the first RB within the CORESET (c_rb = n_BWP_start) if ((c_rb < (frame_parms->N_RB_DL >> 1)) && ((frame_parms->N_RB_DL & 1) == 0)) { //if RB to be treated is lower than middle system bandwidth then rxdataF pointed at (offset + c_br + symbol * ofdm_symbol_size): even case rxF = &rxdataF[aarx][(frame_parms->first_carrier_offset + 12 * c_rb + (symbol * (frame_parms->ofdm_symbol_size)))]; #ifndef NR_PDCCH_DCI_DEBUG printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_pdcch_extract_rbs_single)-> in even case c_rb (%d) is lower than half N_RB_DL -> rxF = &rxdataF[aarx = (%d)][(frame_parms->first_carrier_offset + 12 * c_rb + (symbol * (frame_parms->ofdm_symbol_size))) = (%d)]\n", c_rb,aarx,(frame_parms->first_carrier_offset + 12 * c_rb + (symbol * (frame_parms->ofdm_symbol_size)))); #endif } if ((c_rb >= (frame_parms->N_RB_DL >> 1)) && ((frame_parms->N_RB_DL & 1) == 0)) { // number of RBs is even and c_rb is higher than half system bandwidth (we don't skip DC) // if these conditions are true the pointer has to be situated at the 1st part of the rxdataF rxF = &rxdataF[aarx][(12*(c_rb - (frame_parms->N_RB_DL>>1)) + (symbol * (frame_parms->ofdm_symbol_size)))]; // we point at the 1st part of the rxdataF in symbol #ifndef NR_PDCCH_DCI_DEBUG printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_pdcch_extract_rbs_single)-> in even case c_rb (%d) is higher than half N_RB_DL (not DC) -> rxF = &rxdataF[aarx = (%d)][(12*(c_rb - (frame_parms->N_RB_DL>>1)) + (symbol * (frame_parms->ofdm_symbol_size))) = (%d)]\n", c_rb,aarx,(12*(c_rb - (frame_parms->N_RB_DL>>1)) + (symbol * (frame_parms->ofdm_symbol_size)))); #endif //rxF = &rxdataF[aarx][(1 + 12*(c_rb - (frame_parms->N_RB_DL>>1)) + (symbol * (frame_parms->ofdm_symbol_size)))]; // we point at the 1st part of the rxdataF in symbol //#ifdef NR_PDCCH_DCI_DEBUG // printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_pdcch_extract_rbs_single)-> in even case c_rb (%d) is higher than half N_RB_DL (not DC) -> rxF = &rxdataF[aarx = (%d)][(1 + 12*(c_rb - (frame_parms->N_RB_DL>>1)) + (symbol * (frame_parms->ofdm_symbol_size))) = (%d)]\n", // c_rb,aarx,(1 + 12*(c_rb - (frame_parms->N_RB_DL>>1)) + (symbol * (frame_parms->ofdm_symbol_size)))); //#endif } if ((c_rb < (frame_parms->N_RB_DL >> 1)) && ((frame_parms->N_RB_DL & 1) != 0)){ //if RB to be treated is lower than middle system bandwidth then rxdataF pointed at (offset + c_br + symbol * ofdm_symbol_size): odd case rxF = &rxdataF[aarx][(frame_parms->first_carrier_offset + 12 * c_rb + (symbol * (frame_parms->ofdm_symbol_size)))]; #ifndef NR_PDCCH_DCI_DEBUG printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_pdcch_extract_rbs_single)-> in odd case c_rb (%d) is lower or equal than half N_RB_DL -> rxF = &rxdataF[aarx = (%d)][(frame_parms->first_carrier_offset + 12 * c_rb + (symbol * (frame_parms->ofdm_symbol_size))) = (%d)]\n", c_rb,aarx,(frame_parms->first_carrier_offset + 12 * c_rb + (symbol * (frame_parms->ofdm_symbol_size)))); #endif } if ((c_rb > (frame_parms->N_RB_DL >> 1)) && ((frame_parms->N_RB_DL & 1) != 0)){ // number of RBs is odd and c_rb is higher than half system bandwidth + 1 // if these conditions are true the pointer has to be situated at the 1st part of the rxdataF just after the first IQ symbols of the RB containing DC rxF = &rxdataF[aarx][(12*(c_rb - (frame_parms->N_RB_DL>>1)) - 6 + (symbol * (frame_parms->ofdm_symbol_size)))]; // we point at the 1st part of the rxdataF in symbol #ifndef NR_PDCCH_DCI_DEBUG printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_pdcch_extract_rbs_single)-> in odd case c_rb (%d) is higher than half N_RB_DL (not DC) -> rxF = &rxdataF[aarx = (%d)][(12*(c_rb - frame_parms->N_RB_DL) - 5 + (symbol * (frame_parms->ofdm_symbol_size))) = (%d)]\n", c_rb,aarx,(12*(c_rb - (frame_parms->N_RB_DL>>1)) - 6 + (symbol * (frame_parms->ofdm_symbol_size)))); #endif } if ((c_rb == (frame_parms->N_RB_DL >> 1)) && ((frame_parms->N_RB_DL & 1) != 0)){ // treatment of RB containing the DC // if odd number RBs in system bandwidth and first RB to be treated is higher than middle system bandwidth (around DC) // we have to treat the RB in two parts: first part from i=0 to 5, the data is at the end of rxdataF (pointing at the end of the table) rxF = &rxdataF[aarx][(frame_parms->first_carrier_offset + 12 * c_rb + (symbol * (frame_parms->ofdm_symbol_size)))]; #ifndef NR_PDCCH_DCI_DEBUG printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_pdcch_extract_rbs_single)-> in odd case c_rb (%d) is half N_RB_DL + 1 we treat DC case -> rxF = &rxdataF[aarx = (%d)][(frame_parms->first_carrier_offset + 12 * c_rb + (symbol * (frame_parms->ofdm_symbol_size))) = (%d)]\n", c_rb,aarx,(frame_parms->first_carrier_offset + 12 * c_rb + (symbol * (frame_parms->ofdm_symbol_size)))); #endif /*if (symbol_mod > 300) { // this if is going to be removed as DM-RS signals are present in all symbols of PDCCH for (i = 0; i < 6; i++) { dl_ch0_ext[i] = dl_ch0[i]; rxF_ext[i] = rxF[i]; } rxF = &rxdataF[aarx][(symbol * (frame_parms->ofdm_symbol_size))]; // we point at the 1st part of the rxdataF in symbol #ifdef NR_PDCCH_DCI_DEBUG printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_pdcch_extract_rbs_single)-> in odd case c_rb (%d) is half N_RB_DL +1 we treat DC case -> rxF = &rxdataF[aarx = (%d)][(symbol * (frame_parms->ofdm_symbol_size)) = (%d)]\n", c_rb,aarx,(symbol * (frame_parms->ofdm_symbol_size))); #endif for (; i < 12; i++) { dl_ch0_ext[i] = dl_ch0[i]; rxF_ext[i] = rxF[(1 + i - 6)]; } nb_rb++; dl_ch0_ext += 12; rxF_ext += 12; dl_ch0 += 12; rxF += 7; c_rb++; } else {*/ j = 0; for (i = 0; i < 6; i++) { //treating first part of the RB note that i=5 would correspond to DC. We treat it in NR if ((i != 1) && (i != 5)) { dl_ch0_ext[j] = dl_ch0[i]; rxF_ext[j++] = rxF[i]; // printf("**extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[j-1],*(1+(short*)&rxF_ext[j-1])); } } // then we point at the begining of the symbol part of rxdataF do process second part of RB rxF = &rxdataF[aarx][((symbol * (frame_parms->ofdm_symbol_size)))]; // we point at the 1st part of the rxdataF in symbol #ifndef NR_PDCCH_DCI_DEBUG printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_pdcch_extract_rbs_single)-> in odd case c_rb (%d) is half N_RB_DL +1 we treat DC case -> rxF = &rxdataF[aarx = (%d)][(symbol * (frame_parms->ofdm_symbol_size)) = (%d)]\n", c_rb,aarx,(symbol * (frame_parms->ofdm_symbol_size))); #endif for (; i < 12; i++) { if ((i != 9)) { dl_ch0_ext[j] = dl_ch0[i]; rxF_ext[j++] = rxF[(1 + i - 6)]; // printf("**extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[j-1],*(1+(short*)&rxF_ext[j-1])); } } nb_rb++; dl_ch0_ext += NBR_RE_PER_RB_WITHOUT_DMRS; rxF_ext += NBR_RE_PER_RB_WITHOUT_DMRS; dl_ch0 += 12; //rxF += 7; //c_rb++; //n_BWP_start++; // We have to increment this variable here to be consequent in the for loop afterwards //} } else { // treatment of any RB that does not contain the DC /*if (symbol_mod > 300) { memcpy(dl_ch0_ext, dl_ch0, 12 * sizeof(int32_t)); for (i = 0; i < 12; i++) { rxF_ext[i] = rxF[i]; } nb_rb++; dl_ch0_ext += 12; rxF_ext += 12; dl_ch0 += 12; //rxF += 12; } else {*/ j = 0; for (i = 0; i < 12; i++) { if ((i != 1) && (i != 5) && (i != 9)) { rxF_ext[j] = rxF[i]; #ifndef NR_PDCCH_DCI_DEBUG printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_pdcch_extract_rbs_single)-> RB[c_rb %d] \t RE[re %d] => rxF_ext[%d]=(%d,%d)\t rxF[%d]=(%d,%d)", c_rb, i, j, *(short *) &rxF_ext[j],*(1 + (short*) &rxF_ext[j]), i, *(short *) &rxF[i], *(1 + (short*) &rxF[i])); #endif dl_ch0_ext[j] = dl_ch0[i]; //printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_pdcch_extract_rbs_single)-> ch %d => dl_ch0(%d,%d)\n", i, *(short *) &dl_ch0[i], *(1 + (short*) &dl_ch0[i])); //printf("\t-> dl_ch0[%d] => dl_ch0_ext[%d](%d,%d)\n", i,j, *(short *) &dl_ch0[i], *(1 + (short*) &dl_ch0[i])); j++; } else { #ifndef NR_PDCCH_DCI_DEBUG printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_pdcch_extract_rbs_single)-> RB[c_rb %d] \t RE[re %d] => rxF_ext[%d]=(%d,%d)\t rxF[%d]=(%d,%d) \t\t <==> DM-RS PDCCH, this is a pilot symbol\n", c_rb, i, j, *(short *) &rxF_ext[j], *(1 + (short*) &rxF_ext[j]), i, *(short *) &rxF[i], *(1 + (short*) &rxF[i])); #endif } } nb_rb++; dl_ch0_ext += NBR_RE_PER_RB_WITHOUT_DMRS; rxF_ext += NBR_RE_PER_RB_WITHOUT_DMRS; dl_ch0 += 12; //rxF += 12; //} } } } } #endif #ifdef NR_PDCCH_DCI_RUN_bis // this function is just a second implementation of nr_pdcch_extract_rbs_single // the code modification is minimum but it can be slower in processing time // to be removed void nr_pdcch_extract_rbs_single_bis(int32_t **rxdataF, int32_t **dl_ch_estimates, int32_t **rxdataF_ext, int32_t **dl_ch_estimates_ext, uint8_t symbol, uint32_t high_speed_flag, NR_DL_FRAME_PARMS *frame_parms, uint64_t coreset_freq_dom, uint32_t coreset_nbr_rb, uint32_t n_BWP_start) { uint16_t rb, nb_rb = 0; uint8_t i, j, aarx; int32_t *dl_ch0, *dl_ch0_ext, *rxF, *rxF_ext; int nushiftmod3 = frame_parms->nushift % 3; uint8_t symbol_mod; symbol_mod = (symbol >= (7 - frame_parms->Ncp)) ? symbol - (7 - frame_parms->Ncp) : symbol; #ifdef DEBUG_DCI_DECODING LOG_I(PHY, "extract_rbs_single: symbol_mod %d\n",symbol_mod); #endif for (aarx = 0; aarx < frame_parms->nb_antennas_rx; aarx++) { if (high_speed_flag == 1){ dl_ch0 = &dl_ch_estimates[aarx][5 + (symbol * (frame_parms->ofdm_symbol_size))]; printf("\t\t### in function nr_pdcch_extract_rbs_single(), \t ### dl_ch0 = &dl_ch_estimates[aarx = (%d) ][5 + (symbol * (frame_parms->ofdm_symbol_size)) = (%d)]\n", aarx,5 + (symbol * (frame_parms->ofdm_symbol_size))); } else { dl_ch0 = &dl_ch_estimates[aarx][5]; printf("\t\t### in function nr_pdcch_extract_rbs_single(), \t ### dl_ch0 = &dl_ch_estimates[aarx = (%d)][5]\n",aarx); } dl_ch0_ext = &dl_ch_estimates_ext[aarx][symbol * (frame_parms->N_RB_DL * 12)]; printf("\t\t### in function nr_pdcch_extract_rbs_single(), \t ### dl_ch0_ext = &dl_ch_estimates_ext[aarx = (%d)][symbol * (frame_parms->N_RB_DL * 12) = (%d)]\n", aarx,symbol * (frame_parms->N_RB_DL * 12)); rxF_ext = &rxdataF_ext[aarx][symbol * (frame_parms->N_RB_DL * 12)]; printf("\t\t### in function nr_pdcch_extract_rbs_single(), \t ### rxF_ext = &rxdataF_ext[aarx = (%d)][symbol * (frame_parms->N_RB_DL * 12) = (%d)]\n", aarx,symbol * (frame_parms->N_RB_DL * 12)); rxF = &rxdataF[aarx][(frame_parms->first_carrier_offset + (symbol * (frame_parms->ofdm_symbol_size)))]; printf("\t\t### in function nr_pdcch_extract_rbs_single(), \t ### rxF = &rxdataF[aarx = (%d)][(frame_parms->first_carrier_offset + (symbol * (frame_parms->ofdm_symbol_size))) = (%d)]\n", aarx,(frame_parms->first_carrier_offset + (symbol * (frame_parms->ofdm_symbol_size)))); printf("\t\t ###### in function pdcch_extract_rbs_single(for symbol=%d, aarx=%d), symbol_mod=%d, nushiftmod3=%d \n",symbol,aarx,symbol_mod,nushiftmod3); printf("\t\t ###### rxF_ext = &rxdataF_ext[aarx(%d)][symbol(%d) * (frame_parms->N_RB_DL(%d) * 12)]\n",aarx,symbol,frame_parms->N_RB_DL); printf("\t\t ###### rxF = &rxdataF[aarx(%d)][(frame_parms->first_carrier_offset(%d) + (symbol(%d) * (frame_parms->ofdm_symbol_size(%d))))]\n", aarx,frame_parms->first_carrier_offset,symbol,frame_parms->ofdm_symbol_size); if ((frame_parms->N_RB_DL & 1) == 0) { // even number of RBs for (rb = 0; rb < frame_parms->N_RB_DL; rb++) { printf("\t\t\t ###### rb=%d\n",rb); if (rb == (frame_parms->N_RB_DL >> 1)) { // For second half of RBs skip DC carrier rxF = &rxdataF[aarx][(1 + (symbol * (frame_parms->ofdm_symbol_size)))]; printf("\t\t\t ###### if rb (%d) is half N_RB_DL, skip DC carrier -> rxF = &rxdataF[aarx(%d)][(1 + (symbol(%d) * (frame_parms->ofdm_symbol_size(%d))))\n", rb,aarx,symbol,frame_parms->ofdm_symbol_size); //dl_ch0++; } if (symbol_mod > 0) { memcpy(dl_ch0_ext, dl_ch0, 12 * sizeof(int32_t)); for (i = 0; i < 12; i++) { rxF_ext[i] = rxF[i]; } nb_rb++; dl_ch0_ext += 12; rxF_ext += 12; dl_ch0 += 12; rxF += 12; } else { j = 0; for (i = 0; i < 12; i++) { if ((i != 1) && (i != 5) && (i != 9)) { rxF_ext[j] = rxF[i]; printf("\textract rb %d \t re %d => rxF_ext[%d]=(%d,%d)", rb, i, j, *(short *) &rxF_ext[j], *(1 + (short*) &rxF_ext[j])); dl_ch0_ext[j++] = dl_ch0[i]; printf("\t\tch %d => dl_ch0(%d,%d)\n", i, *(short *) &dl_ch0[i], *(1 + (short*) &dl_ch0[i])); } } nb_rb++; dl_ch0_ext += 9; rxF_ext += 9; dl_ch0 += 12; rxF += 12; } } } else { // Odd number of RBs for (rb = 0; rb < frame_parms->N_RB_DL >> 1; rb++) { printf("\t\t\t ###### rb=%d (Odd number of RBs, rb < half of band)\n",rb); if (symbol_mod > 0) { memcpy(dl_ch0_ext, dl_ch0, 12 * sizeof(int32_t)); for (i = 0; i < 12; i++) rxF_ext[i] = rxF[i]; nb_rb++; dl_ch0_ext += 12; rxF_ext += 12; dl_ch0 += 12; rxF += 12; } else { j = 0; for (i = 0; i < 12; i++) { if ((i != 1) && (i != 5) && (i != 9)) { rxF_ext[j] = rxF[i]; printf("\t\t\t\t ###### extract rb %d, re %d => rxF_ext[%d]=(%d,%d) rxF[%d]=(%d,%d)", rb,i,j,*(short *)&rxF_ext[j],*(1+(short*)&rxF_ext[j]),i,*(short *)&rxF[i],*(1+(short*)&rxF[i])); dl_ch0_ext[j++] = dl_ch0[i]; printf("\t ###### extract rb %d, re %d => dl_ch0 []=(%d,%d)\n",rb,i,*(short *)&dl_ch0[i],*(1+(short*)&dl_ch0[i])); } else { printf("\t\t\t\t ###### THIS IS a pilot rb %d \t re %d => rxF_ext[%d]=(%d,%d)\t rxF[%d]=(%d,%d) \t this is a pilot symbol\n", rb,i,j,*(short *)&rxF_ext[j],*(1+(short*)&rxF_ext[j]),i,*(short *)&rxF[i],*(1+(short*)&rxF[i])); } } nb_rb++; dl_ch0_ext += 9; rxF_ext += 9; dl_ch0 += 12; rxF += 12; } } // Do middle RB (around DC) //printf("dlch_ext %d\n",dl_ch0_ext-&dl_ch_estimates_ext[aarx][0]); if (symbol_mod == 0) { j = 0; for (i = 0; i < 6; i++) { if ((i != 1) && (i != 5)) { dl_ch0_ext[j] = dl_ch0[i]; rxF_ext[j++] = rxF[i]; //printf("**extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[j-1],*(1+(short*)&rxF_ext[j-1])); } } rxF = &rxdataF[aarx][((symbol * (frame_parms->ofdm_symbol_size)))]; for (; i < 12; i++) { if (i != 9) { dl_ch0_ext[j] = dl_ch0[i]; rxF_ext[j++] = rxF[(1 + i - 6)]; //printf("**extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[j-1],*(1+(short*)&rxF_ext[j-1])); } } nb_rb++; dl_ch0_ext += 9; rxF_ext += 9; dl_ch0 += 12; rxF += 7; rb++; } else { for (i = 0; i < 6; i++) { dl_ch0_ext[i] = dl_ch0[i]; rxF_ext[i] = rxF[i]; } rxF = &rxdataF[aarx][((symbol * (frame_parms->ofdm_symbol_size)))]; for (; i < 12; i++) { dl_ch0_ext[i] = dl_ch0[i]; rxF_ext[i] = rxF[(1 + i - 6)]; } nb_rb++; dl_ch0_ext += 12; rxF_ext += 12; dl_ch0 += 12; rxF += 7; rb++; } for (; rb < frame_parms->N_RB_DL; rb++) { printf("\t\t\t ###### rb=%d (Even number of RBs, rb > half of band)\n",rb); if (symbol_mod > 0) { memcpy(dl_ch0_ext, dl_ch0, 12 * sizeof(int32_t)); for (i = 0; i < 12; i++) rxF_ext[i] = rxF[i]; nb_rb++; dl_ch0_ext += 12; rxF_ext += 12; dl_ch0 += 12; rxF += 12; } else { j = 0; for (i = 0; i < 12; i++) { if ((i != 1) && (i != 5) && (i != 9)) { rxF_ext[j] = rxF[i]; printf("\t\t\t\t ###### extract rb %d, re %d => rxF_ext[]=(%d,%d)",rb,i,*(short *)&rxF_ext[j],*(1+(short*)&rxF_ext[j])); //printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[j],*(1+(short*)&rxF_ext[j])); dl_ch0_ext[j++] = dl_ch0[i]; printf("\t ###### extract rb %d, re %d => dl_ch0 []=(%d,%d)\n",rb,i,*(short *)&dl_ch0[i],*(1+(short*)&dl_ch0[i])); } else { printf("\t\t\t\t ###### THIS IS a RS at re %d\n",i); } } nb_rb++; dl_ch0_ext += 9; rxF_ext += 9; dl_ch0 += 12; rxF += 12; } } } } // The function has created table rxdataF_ext with the contents of rxdataF and removing the pilots at positions 1,5,9 in every RB. // Now we need to check the contents of rxdataF_ext and keep only the values which correspond to our CORESET depending on variables: // - coreset_freq_dom (45 bit map) // - n_BWP_start (first RB within the active BWP and the CORESET) j=0; k=0; rxF_ext = &rxdataF_ext[aarx][(symbol * (frame_parms->N_RB_DL * 12))]; printf("\t\t### in function nr_pdcch_extract_rbs_single(), \t ### rxF_ext = &rxdataF_ext[aarx = (%d)][n_BWP_start + (symbol * (frame_parms->N_RB_DL * 12)) = (%d)]\n", aarx,(n_BWP_start + (symbol * (frame_parms->N_RB_DL * 12)))); int bitcnt_coreset_freq_dom = 1; // this variable will allow to check each bit of the 45 bitmap coreset_freq_dom. //Eg: if bitcnt_coreset_freq_dom = 3, (46-3) we verify bit 43 starting from LSB for (rb=0; rb<frame_parms->N_RB_DL;rb++) { if (rb < n_BWP_start) { // while rb is not within CORESET, then remove values for (i=0; i<8; i++) { //rxF_ext[i] = 0; j++; } //rxF_ext = &rxdataF_ext[aarx][(j + (symbol * (frame_parms->N_RB_DL * 12)))]; } else if ((rb >= n_BWP_start) && (rb < (n_BWP_start + 6 * 45))) { // rb is within CORESET, we need to verify now whether bit in coreset_freq_dom is set or not if ((((coreset_freq_dom & 0x1FFFFFFFFFFF) >> (46 - bitcnt_coreset_freq_dom)) & 0x1)== 0){ // if bit is 0, next 6 consecutive RBs do not belong to CORESET bitcnt_coreset_freq_dom ++; rb = rb + 6; for (i=0; i<(9*6); i++) { //rxF_ext[i] = 0; j++; } //rxF_ext = &rxdataF_ext[aarx][(j + (symbol * (frame_parms->N_RB_DL * 12)))]; } else { // if bit is 1, next 6 consecutive RBs belong to CORESET bitcnt_coreset_freq_dom ++; rb = rb + 6; for (i=0; i<(9*6); i++) { rxF_ext[k] = rxF_ext[j]; k++; j++; } //rxF_ext = &rxdataF_ext[aarx][(j + (symbol * (frame_parms->N_RB_DL * 12)))]; } } else { // for the RBs that are in the upper side of the CORESET bitmap for (i=0; i<8; i++) { rxF_ext[k] = 0; k++; j++; } //rxF_ext = &rxdataF_ext[aarx][(j + (symbol * (frame_parms->N_RB_DL * 12)))]; } } } #endif void pdcch_extract_rbs_single(int32_t **rxdataF, int32_t **dl_ch_estimates, int32_t **rxdataF_ext, int32_t **dl_ch_estimates_ext, uint8_t symbol, uint32_t high_speed_flag, NR_DL_FRAME_PARMS *frame_parms) { uint16_t rb,nb_rb=0; uint8_t i,j,aarx; int32_t *dl_ch0,*dl_ch0_ext,*rxF,*rxF_ext; int nushiftmod3 = frame_parms->nushift%3; uint8_t symbol_mod; symbol_mod = (symbol>=(7-frame_parms->Ncp)) ? symbol-(7-frame_parms->Ncp) : symbol; #ifdef DEBUG_DCI_DECODING LOG_I(PHY, "extract_rbs_single: symbol_mod %d\n",symbol_mod); #endif for (aarx=0; aarx<frame_parms->nb_antennas_rx; aarx++) { if (high_speed_flag == 1) dl_ch0 = &dl_ch_estimates[aarx][5+(symbol*(frame_parms->ofdm_symbol_size))]; else dl_ch0 = &dl_ch_estimates[aarx][5]; dl_ch0_ext = &dl_ch_estimates_ext[aarx][symbol*(frame_parms->N_RB_DL*12)]; rxF_ext = &rxdataF_ext[aarx][symbol*(frame_parms->N_RB_DL*12)]; rxF = &rxdataF[aarx][(frame_parms->first_carrier_offset + (symbol*(frame_parms->ofdm_symbol_size)))]; if ((frame_parms->N_RB_DL&1) == 0) { // even number of RBs for (rb=0; rb<frame_parms->N_RB_DL; rb++) { // For second half of RBs skip DC carrier if (rb==(frame_parms->N_RB_DL>>1)) { rxF = &rxdataF[aarx][(1 + (symbol*(frame_parms->ofdm_symbol_size)))]; //dl_ch0++; } if (symbol_mod>0) { memcpy(dl_ch0_ext,dl_ch0,12*sizeof(int32_t)); for (i=0; i<12; i++) { rxF_ext[i]=rxF[i]; } nb_rb++; dl_ch0_ext+=12; rxF_ext+=12; dl_ch0+=12; rxF+=12; } else { j=0; for (i=0; i<12; i++) { if ((i!=nushiftmod3) && (i!=(nushiftmod3+3)) && (i!=(nushiftmod3+6)) && (i!=(nushiftmod3+9))) { rxF_ext[j]=rxF[i]; // printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[j],*(1+(short*)&rxF_ext[j])); dl_ch0_ext[j++]=dl_ch0[i]; // printf("ch %d => (%d,%d)\n",i,*(short *)&dl_ch0[i],*(1+(short*)&dl_ch0[i])); } } nb_rb++; dl_ch0_ext+=8; rxF_ext+=8; dl_ch0+=12; rxF+=12; } } } else { // Odd number of RBs for (rb=0; rb<frame_parms->N_RB_DL>>1; rb++) { if (symbol_mod>0) { memcpy(dl_ch0_ext,dl_ch0,12*sizeof(int32_t)); for (i=0; i<12; i++) rxF_ext[i]=rxF[i]; nb_rb++; dl_ch0_ext+=12; rxF_ext+=12; dl_ch0+=12; rxF+=12; } else { j=0; for (i=0; i<12; i++) { if ((i!=nushiftmod3) && (i!=(nushiftmod3+3)) && (i!=(nushiftmod3+6)) && (i!=(nushiftmod3+9))) { rxF_ext[j]=rxF[i]; // printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[j],*(1+(short*)&rxF_ext[j])); dl_ch0_ext[j++]=dl_ch0[i]; // printf("ch %d => (%d,%d)\n",i,*(short *)&dl_ch0[i],*(1+(short*)&dl_ch0[i])); } } nb_rb++; dl_ch0_ext+=8; rxF_ext+=8; dl_ch0+=12; rxF+=12; } } // Do middle RB (around DC) // printf("dlch_ext %d\n",dl_ch0_ext-&dl_ch_estimates_ext[aarx][0]); if (symbol_mod==0) { j=0; for (i=0; i<6; i++) { if ((i!=nushiftmod3) && (i!=(nushiftmod3+3))) { dl_ch0_ext[j]=dl_ch0[i]; rxF_ext[j++]=rxF[i]; // printf("**extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[j-1],*(1+(short*)&rxF_ext[j-1])); } } rxF = &rxdataF[aarx][((symbol*(frame_parms->ofdm_symbol_size)))]; for (; i<12; i++) { if ((i!=(nushiftmod3+6)) && (i!=(nushiftmod3+9))) { dl_ch0_ext[j]=dl_ch0[i]; rxF_ext[j++]=rxF[(1+i-6)]; // printf("**extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[j-1],*(1+(short*)&rxF_ext[j-1])); } } nb_rb++; dl_ch0_ext+=8; rxF_ext+=8; dl_ch0+=12; rxF+=7; rb++; } else { for (i=0; i<6; i++) { dl_ch0_ext[i]=dl_ch0[i]; rxF_ext[i]=rxF[i]; } rxF = &rxdataF[aarx][((symbol*(frame_parms->ofdm_symbol_size)))]; for (; i<12; i++) { dl_ch0_ext[i]=dl_ch0[i]; rxF_ext[i]=rxF[(1+i-6)]; } nb_rb++; dl_ch0_ext+=12; rxF_ext+=12; dl_ch0+=12; rxF+=7; rb++; } for (; rb<frame_parms->N_RB_DL; rb++) { if (symbol_mod > 0) { memcpy(dl_ch0_ext,dl_ch0,12*sizeof(int32_t)); for (i=0; i<12; i++) rxF_ext[i]=rxF[i]; nb_rb++; dl_ch0_ext+=12; rxF_ext+=12; dl_ch0+=12; rxF+=12; } else { j=0; for (i=0; i<12; i++) { if ((i!=(nushiftmod3)) && (i!=(nushiftmod3+3)) && (i!=(nushiftmod3+6)) && (i!=(nushiftmod3+9))) { rxF_ext[j]=rxF[i]; // printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[j],*(1+(short*)&rxF_ext[j])); dl_ch0_ext[j++]=dl_ch0[i]; } } nb_rb++; dl_ch0_ext+=8; rxF_ext+=8; dl_ch0+=12; rxF+=12; } } } } } void pdcch_extract_rbs_dual(int32_t **rxdataF, int32_t **dl_ch_estimates, int32_t **rxdataF_ext, int32_t **dl_ch_estimates_ext, uint8_t symbol, uint32_t high_speed_flag, NR_DL_FRAME_PARMS *frame_parms) { uint16_t rb,nb_rb=0; uint8_t i,aarx,j; int32_t *dl_ch0,*dl_ch0_ext,*dl_ch1,*dl_ch1_ext,*rxF,*rxF_ext; uint8_t symbol_mod; int nushiftmod3 = frame_parms->nushift%3; symbol_mod = (symbol>=(7-frame_parms->Ncp)) ? symbol-(7-frame_parms->Ncp) : symbol; #ifdef DEBUG_DCI_DECODING LOG_I(PHY, "extract_rbs_dual: symbol_mod %d\n",symbol_mod); #endif for (aarx=0; aarx<frame_parms->nb_antennas_rx; aarx++) { if (high_speed_flag==1) { dl_ch0 = &dl_ch_estimates[aarx][5+(symbol*(frame_parms->ofdm_symbol_size))]; dl_ch1 = &dl_ch_estimates[2+aarx][5+(symbol*(frame_parms->ofdm_symbol_size))]; } else { dl_ch0 = &dl_ch_estimates[aarx][5]; dl_ch1 = &dl_ch_estimates[2+aarx][5]; } dl_ch0_ext = &dl_ch_estimates_ext[aarx][symbol*(frame_parms->N_RB_DL*12)]; dl_ch1_ext = &dl_ch_estimates_ext[2+aarx][symbol*(frame_parms->N_RB_DL*12)]; // printf("pdcch extract_rbs: rxF_ext pos %d\n",symbol*(frame_parms->N_RB_DL*12)); rxF_ext = &rxdataF_ext[aarx][symbol*(frame_parms->N_RB_DL*12)]; rxF = &rxdataF[aarx][(frame_parms->first_carrier_offset + (symbol*(frame_parms->ofdm_symbol_size)))]; if ((frame_parms->N_RB_DL&1) == 0) // even number of RBs for (rb=0; rb<frame_parms->N_RB_DL; rb++) { // For second half of RBs skip DC carrier if (rb==(frame_parms->N_RB_DL>>1)) { rxF = &rxdataF[aarx][(1 + (symbol*(frame_parms->ofdm_symbol_size)))]; // dl_ch0++; //dl_ch1++; } if (symbol_mod>0) { memcpy(dl_ch0_ext,dl_ch0,12*sizeof(int32_t)); memcpy(dl_ch1_ext,dl_ch1,12*sizeof(int32_t)); /* printf("rb %d\n",rb); for (i=0;i<12;i++) printf("(%d %d)",((int16_t *)dl_ch0)[i<<1],((int16_t*)dl_ch0)[1+(i<<1)]); printf("\n"); */ for (i=0; i<12; i++) { rxF_ext[i]=rxF[i]; // printf("%d : (%d,%d)\n",(rxF+(2*i)-&rxdataF[aarx][( (symbol*(frame_parms->ofdm_symbol_size)))*2])/2, // ((int16_t*)&rxF[i<<1])[0],((int16_t*)&rxF[i<<1])[0]); } nb_rb++; dl_ch0_ext+=12; dl_ch1_ext+=12; rxF_ext+=12; } else { j=0; for (i=0; i<12; i++) { if ((i!=nushiftmod3) && (i!=nushiftmod3+3) && (i!=nushiftmod3+6) && (i!=nushiftmod3+9)) { rxF_ext[j]=rxF[i]; // printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[j],*(1+(short*)&rxF_ext[j])); dl_ch0_ext[j] =dl_ch0[i]; dl_ch1_ext[j++]=dl_ch1[i]; } } nb_rb++; dl_ch0_ext+=8; dl_ch1_ext+=8; rxF_ext+=8; } dl_ch0+=12; dl_ch1+=12; rxF+=12; } else { // Odd number of RBs for (rb=0; rb<frame_parms->N_RB_DL>>1; rb++) { // printf("rb %d: %d\n",rb,rxF-&rxdataF[aarx][(symbol*(frame_parms->ofdm_symbol_size))*2]); if (symbol_mod>0) { memcpy(dl_ch0_ext,dl_ch0,12*sizeof(int32_t)); memcpy(dl_ch1_ext,dl_ch1,12*sizeof(int32_t)); for (i=0; i<12; i++) rxF_ext[i]=rxF[i]; nb_rb++; dl_ch0_ext+=12; dl_ch1_ext+=12; rxF_ext+=12; dl_ch0+=12; dl_ch1+=12; rxF+=12; } else { j=0; for (i=0; i<12; i++) { if ((i!=nushiftmod3) && (i!=nushiftmod3+3) && (i!=nushiftmod3+6) && (i!=nushiftmod3+9)) { rxF_ext[j]=rxF[i]; // printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[j],*(1+(short*)&rxF_ext[j])); dl_ch0_ext[j]=dl_ch0[i]; dl_ch1_ext[j++]=dl_ch1[i]; // printf("ch %d => (%d,%d)\n",i,*(short *)&dl_ch0[i],*(1+(short*)&dl_ch0[i])); } } nb_rb++; dl_ch0_ext+=8; dl_ch1_ext+=8; rxF_ext+=8; dl_ch0+=12; dl_ch1+=12; rxF+=12; } } // Do middle RB (around DC) if (symbol_mod > 0) { for (i=0; i<6; i++) { dl_ch0_ext[i]=dl_ch0[i]; dl_ch1_ext[i]=dl_ch1[i]; rxF_ext[i]=rxF[i]; } rxF = &rxdataF[aarx][((symbol*(frame_parms->ofdm_symbol_size)))]; for (; i<12; i++) { dl_ch0_ext[i]=dl_ch0[i]; dl_ch1_ext[i]=dl_ch1[i]; rxF_ext[i]=rxF[(1+i)]; } nb_rb++; dl_ch0_ext+=12; dl_ch1_ext+=12; rxF_ext+=12; dl_ch0+=12; dl_ch1+=12; rxF+=7; rb++; } else { j=0; for (i=0; i<6; i++) { if ((i!=nushiftmod3) && (i!=nushiftmod3+3)) { dl_ch0_ext[j]=dl_ch0[i]; dl_ch1_ext[j]=dl_ch1[i]; rxF_ext[j++]=rxF[i]; // printf("**extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[j-1],*(1+(short*)&rxF_ext[j-1])); } } rxF = &rxdataF[aarx][((symbol*(frame_parms->ofdm_symbol_size)))]; for (; i<12; i++) { if ((i!=nushiftmod3+6) && (i!=nushiftmod3+9)) { dl_ch0_ext[j]=dl_ch0[i]; dl_ch1_ext[j]=dl_ch1[i]; rxF_ext[j++]=rxF[(1+i-6)]; // printf("**extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[j-1],*(1+(short*)&rxF_ext[j-1])); } } nb_rb++; dl_ch0_ext+=8; dl_ch1_ext+=8; rxF_ext+=8; dl_ch0+=12; dl_ch1+=12; rxF+=7; rb++; } for (; rb<frame_parms->N_RB_DL; rb++) { if (symbol_mod>0) { // printf("rb %d: %d\n",rb,rxF-&rxdataF[aarx][(symbol*(frame_parms->ofdm_symbol_size))*2]); memcpy(dl_ch0_ext,dl_ch0,12*sizeof(int32_t)); memcpy(dl_ch1_ext,dl_ch1,12*sizeof(int32_t)); for (i=0; i<12; i++) rxF_ext[i]=rxF[i]; nb_rb++; dl_ch0_ext+=12; dl_ch1_ext+=12; rxF_ext+=12; dl_ch0+=12; dl_ch1+=12; rxF+=12; } else { j=0; for (i=0; i<12; i++) { if ((i!=nushiftmod3) && (i!=nushiftmod3+3) && (i!=nushiftmod3+6) && (i!=nushiftmod3+9)) { rxF_ext[j]=rxF[i]; // printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[j],*(1+(short*)&rxF_ext[j])); dl_ch0_ext[j]=dl_ch0[i]; dl_ch1_ext[j++]=dl_ch1[i]; } } nb_rb++; dl_ch0_ext+=8; dl_ch1_ext+=8; rxF_ext+=8; dl_ch0+=12; dl_ch1+=12; rxF+=12; } } } } } #if defined(__x86_64__) || defined(__i386__) __m128i mmtmpP0,mmtmpP1,mmtmpP2,mmtmpP3; #elif defined(__arm__) int16x8_t mmtmpP0,mmtmpP1,mmtmpP2,mmtmpP3; #endif void nr_pdcch_channel_compensation(int32_t **rxdataF_ext, int32_t **dl_ch_estimates_ext, int32_t **rxdataF_comp, int32_t **rho, NR_DL_FRAME_PARMS *frame_parms, uint8_t symbol, uint8_t output_shift, uint32_t coreset_nbr_rb) { uint16_t rb; //,nb_rb=20; uint8_t aatx,aarx; #if defined(__x86_64__) || defined(__i386__) __m128i *dl_ch128,*rxdataF128,*rxdataF_comp128; #elif defined(__arm__) #endif for (aatx=0; aatx<frame_parms->nb_antenna_ports_eNB;aatx++) for (aarx=0; aarx<frame_parms->nb_antennas_rx; aarx++) { #if defined(__x86_64__) || defined(__i386__) dl_ch128 = (__m128i *)&dl_ch_estimates_ext[(aatx<<1)+aarx][symbol*coreset_nbr_rb*12]; rxdataF128 = (__m128i *)&rxdataF_ext[aarx][symbol*coreset_nbr_rb*12]; rxdataF_comp128 = (__m128i *)&rxdataF_comp[(aatx<<1)+aarx][symbol*coreset_nbr_rb*12]; //printf("ch compensation dl_ch ext addr %p \n", &dl_ch_estimates_ext[(aatx<<1)+aarx][symbol*20*12]); //printf("rxdataf ext addr %p symbol %d\n", &rxdataF_ext[aarx][symbol*20*12], symbol); //printf("rxdataf_comp addr %p\n",&rxdataF_comp[(aatx<<1)+aarx][symbol*20*12]); #elif defined(__arm__) // to be filled in #endif for (rb=0; rb<coreset_nbr_rb; rb++) { //printf("rb %d\n",rb); #if defined(__x86_64__) || defined(__i386__) // multiply by conjugated channel mmtmpP0 = _mm_madd_epi16(dl_ch128[0],rxdataF128[0]); // print_ints("re",&mmtmpP0); // mmtmpP0 contains real part of 4 consecutive outputs (32-bit) mmtmpP1 = _mm_shufflelo_epi16(dl_ch128[0],_MM_SHUFFLE(2,3,0,1)); mmtmpP1 = _mm_shufflehi_epi16(mmtmpP1,_MM_SHUFFLE(2,3,0,1)); mmtmpP1 = _mm_sign_epi16(mmtmpP1,*(__m128i*)&conjugate[0]); // print_ints("im",&mmtmpP1); mmtmpP1 = _mm_madd_epi16(mmtmpP1,rxdataF128[0]); // mmtmpP1 contains imag part of 4 consecutive outputs (32-bit) mmtmpP0 = _mm_srai_epi32(mmtmpP0,output_shift); // print_ints("re(shift)",&mmtmpP0); mmtmpP1 = _mm_srai_epi32(mmtmpP1,output_shift); // print_ints("im(shift)",&mmtmpP1); mmtmpP2 = _mm_unpacklo_epi32(mmtmpP0,mmtmpP1); mmtmpP3 = _mm_unpackhi_epi32(mmtmpP0,mmtmpP1); // print_ints("c0",&mmtmpP2); // print_ints("c1",&mmtmpP3); rxdataF_comp128[0] = _mm_packs_epi32(mmtmpP2,mmtmpP3); //print_shorts("rx:",rxdataF128); //print_shorts("ch:",dl_ch128); //print_shorts("pack:",rxdataF_comp128); // multiply by conjugated channel mmtmpP0 = _mm_madd_epi16(dl_ch128[1],rxdataF128[1]); // mmtmpP0 contains real part of 4 consecutive outputs (32-bit) mmtmpP1 = _mm_shufflelo_epi16(dl_ch128[1],_MM_SHUFFLE(2,3,0,1)); mmtmpP1 = _mm_shufflehi_epi16(mmtmpP1,_MM_SHUFFLE(2,3,0,1)); mmtmpP1 = _mm_sign_epi16(mmtmpP1,*(__m128i*)&conjugate[0]); mmtmpP1 = _mm_madd_epi16(mmtmpP1,rxdataF128[1]); // mmtmpP1 contains imag part of 4 consecutive outputs (32-bit) mmtmpP0 = _mm_srai_epi32(mmtmpP0,output_shift); mmtmpP1 = _mm_srai_epi32(mmtmpP1,output_shift); mmtmpP2 = _mm_unpacklo_epi32(mmtmpP0,mmtmpP1); mmtmpP3 = _mm_unpackhi_epi32(mmtmpP0,mmtmpP1); rxdataF_comp128[1] = _mm_packs_epi32(mmtmpP2,mmtmpP3); //print_shorts("rx:",rxdataF128+1); //print_shorts("ch:",dl_ch128+1); //print_shorts("pack:",rxdataF_comp128+1); // multiply by conjugated channel mmtmpP0 = _mm_madd_epi16(dl_ch128[2],rxdataF128[2]); // mmtmpP0 contains real part of 4 consecutive outputs (32-bit) mmtmpP1 = _mm_shufflelo_epi16(dl_ch128[2],_MM_SHUFFLE(2,3,0,1)); mmtmpP1 = _mm_shufflehi_epi16(mmtmpP1,_MM_SHUFFLE(2,3,0,1)); mmtmpP1 = _mm_sign_epi16(mmtmpP1,*(__m128i*)&conjugate[0]); mmtmpP1 = _mm_madd_epi16(mmtmpP1,rxdataF128[2]); // mmtmpP1 contains imag part of 4 consecutive outputs (32-bit) mmtmpP0 = _mm_srai_epi32(mmtmpP0,output_shift); mmtmpP1 = _mm_srai_epi32(mmtmpP1,output_shift); mmtmpP2 = _mm_unpacklo_epi32(mmtmpP0,mmtmpP1); mmtmpP3 = _mm_unpackhi_epi32(mmtmpP0,mmtmpP1); rxdataF_comp128[2] = _mm_packs_epi32(mmtmpP2,mmtmpP3); /////////////////////////////////////////////////////////////////////////////////////////////// //print_shorts("rx:",rxdataF128+2); //print_shorts("ch:",dl_ch128+2); //print_shorts("pack:",rxdataF_comp128+2); #ifndef NR_PDCCH_DCI_DEBUG for (int i=0; i<20 ; i++) printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_pdcch_channel_compensation)-> rb=%d rxdataF128[%d]=(%d,%d) rxdataF_comp128[%d]=(%d,%d)\n", rb, i, *(short *) &rxdataF128[i],*(1 + (short*) &rxdataF128[i]), i,*(short *) &rxdataF_comp128[i], *(1 + (short*) &rxdataF_comp128[i])); #endif dl_ch128+=3; rxdataF128+=3; rxdataF_comp128+=3; #elif defined(__arm__) // to be filled in #endif } } #if defined(__x86_64__) || defined(__i386__) _mm_empty(); _m_empty(); #endif } /* void pdcch_channel_compensation(int32_t **rxdataF_ext, int32_t **dl_ch_estimates_ext, int32_t **rxdataF_comp, int32_t **rho, NR_DL_FRAME_PARMS *frame_parms, uint8_t symbol, uint8_t output_shift) { uint16_t rb; #if defined(__x86_64__) || defined(__i386__) __m128i *dl_ch128,*rxdataF128,*rxdataF_comp128; __m128i *dl_ch128_2, *rho128; #elif defined(__arm__) #endif uint8_t aatx,aarx,pilots=0; #ifdef DEBUG_DCI_DECODING LOG_I(PHY, "PDCCH comp: symbol %d\n",symbol); #endif if (symbol==0) pilots=1; for (aatx=0; aatx<frame_parms->nb_antenna_ports_eNB; aatx++) { //if (frame_parms->mode1_flag && aatx>0) break; //if mode1_flag is set then there is only one stream to extract, independent of nb_antenna_ports_eNB for (aarx=0; aarx<frame_parms->nb_antennas_rx; aarx++) { #if defined(__x86_64__) || defined(__i386__) dl_ch128 = (__m128i *)&dl_ch_estimates_ext[(aatx<<1)+aarx][symbol*frame_parms->N_RB_DL*12]; rxdataF128 = (__m128i *)&rxdataF_ext[aarx][symbol*frame_parms->N_RB_DL*12]; rxdataF_comp128 = (__m128i *)&rxdataF_comp[(aatx<<1)+aarx][symbol*frame_parms->N_RB_DL*12]; #elif defined(__arm__) #endif for (rb=0; rb<frame_parms->N_RB_DL; rb++) { #if defined(__x86_64__) || defined(__i386__) // multiply by conjugated channel mmtmpPD0 = _mm_madd_epi16(dl_ch128[0],rxdataF128[0]); // print_ints("re",&mmtmpPD0); // mmtmpPD0 contains real part of 4 consecutive outputs (32-bit) mmtmpPD1 = _mm_shufflelo_epi16(dl_ch128[0],_MM_SHUFFLE(2,3,0,1)); mmtmpPD1 = _mm_shufflehi_epi16(mmtmpPD1,_MM_SHUFFLE(2,3,0,1)); mmtmpPD1 = _mm_sign_epi16(mmtmpPD1,*(__m128i*)&conjugate[0]); // print_ints("im",&mmtmpPD1); mmtmpPD1 = _mm_madd_epi16(mmtmpPD1,rxdataF128[0]); // mmtmpPD1 contains imag part of 4 consecutive outputs (32-bit) mmtmpPD0 = _mm_srai_epi32(mmtmpPD0,output_shift); // print_ints("re(shift)",&mmtmpPD0); mmtmpPD1 = _mm_srai_epi32(mmtmpPD1,output_shift); // print_ints("im(shift)",&mmtmpPD1); mmtmpPD2 = _mm_unpacklo_epi32(mmtmpPD0,mmtmpPD1); mmtmpPD3 = _mm_unpackhi_epi32(mmtmpPD0,mmtmpPD1); // print_ints("c0",&mmtmpPD2); // print_ints("c1",&mmtmpPD3); rxdataF_comp128[0] = _mm_packs_epi32(mmtmpPD2,mmtmpPD3); // print_shorts("rx:",rxdataF128); // print_shorts("ch:",dl_ch128); // print_shorts("pack:",rxdataF_comp128); // multiply by conjugated channel mmtmpPD0 = _mm_madd_epi16(dl_ch128[1],rxdataF128[1]); // mmtmpPD0 contains real part of 4 consecutive outputs (32-bit) mmtmpPD1 = _mm_shufflelo_epi16(dl_ch128[1],_MM_SHUFFLE(2,3,0,1)); mmtmpPD1 = _mm_shufflehi_epi16(mmtmpPD1,_MM_SHUFFLE(2,3,0,1)); mmtmpPD1 = _mm_sign_epi16(mmtmpPD1,*(__m128i*)conjugate); mmtmpPD1 = _mm_madd_epi16(mmtmpPD1,rxdataF128[1]); // mmtmpPD1 contains imag part of 4 consecutive outputs (32-bit) mmtmpPD0 = _mm_srai_epi32(mmtmpPD0,output_shift); mmtmpPD1 = _mm_srai_epi32(mmtmpPD1,output_shift); mmtmpPD2 = _mm_unpacklo_epi32(mmtmpPD0,mmtmpPD1); mmtmpPD3 = _mm_unpackhi_epi32(mmtmpPD0,mmtmpPD1); rxdataF_comp128[1] = _mm_packs_epi32(mmtmpPD2,mmtmpPD3); // print_shorts("rx:",rxdataF128+1); // print_shorts("ch:",dl_ch128+1); // print_shorts("pack:",rxdataF_comp128+1); // multiply by conjugated channel if (pilots == 0) { mmtmpPD0 = _mm_madd_epi16(dl_ch128[2],rxdataF128[2]); // mmtmpPD0 contains real part of 4 consecutive outputs (32-bit) mmtmpPD1 = _mm_shufflelo_epi16(dl_ch128[2],_MM_SHUFFLE(2,3,0,1)); mmtmpPD1 = _mm_shufflehi_epi16(mmtmpPD1,_MM_SHUFFLE(2,3,0,1)); mmtmpPD1 = _mm_sign_epi16(mmtmpPD1,*(__m128i*)conjugate); mmtmpPD1 = _mm_madd_epi16(mmtmpPD1,rxdataF128[2]); // mmtmpPD1 contains imag part of 4 consecutive outputs (32-bit) mmtmpPD0 = _mm_srai_epi32(mmtmpPD0,output_shift); mmtmpPD1 = _mm_srai_epi32(mmtmpPD1,output_shift); mmtmpPD2 = _mm_unpacklo_epi32(mmtmpPD0,mmtmpPD1); mmtmpPD3 = _mm_unpackhi_epi32(mmtmpPD0,mmtmpPD1); rxdataF_comp128[2] = _mm_packs_epi32(mmtmpPD2,mmtmpPD3); } // print_shorts("rx:",rxdataF128+2); // print_shorts("ch:",dl_ch128+2); // print_shorts("pack:",rxdataF_comp128+2); if (pilots==0) { dl_ch128+=3; rxdataF128+=3; rxdataF_comp128+=3; } else { dl_ch128+=2; rxdataF128+=2; rxdataF_comp128+=2; } #elif defined(__arm__) #endif } } } if (rho) { for (aarx=0; aarx<frame_parms->nb_antennas_rx; aarx++) { #if defined(__x86_64__) || defined(__i386__) rho128 = (__m128i *)&rho[aarx][symbol*frame_parms->N_RB_DL*12]; dl_ch128 = (__m128i *)&dl_ch_estimates_ext[aarx][symbol*frame_parms->N_RB_DL*12]; dl_ch128_2 = (__m128i *)&dl_ch_estimates_ext[2+aarx][symbol*frame_parms->N_RB_DL*12]; #elif defined(__arm__) #endif for (rb=0; rb<frame_parms->N_RB_DL; rb++) { #if defined(__x86_64__) || defined(__i386__) // multiply by conjugated channel mmtmpPD0 = _mm_madd_epi16(dl_ch128[0],dl_ch128_2[0]); // print_ints("re",&mmtmpD0); // mmtmpD0 contains real part of 4 consecutive outputs (32-bit) mmtmpPD1 = _mm_shufflelo_epi16(dl_ch128[0],_MM_SHUFFLE(2,3,0,1)); mmtmpPD1 = _mm_shufflehi_epi16(mmtmpPD1,_MM_SHUFFLE(2,3,0,1)); mmtmpPD1 = _mm_sign_epi16(mmtmpPD1,*(__m128i*)&conjugate[0]); // print_ints("im",&mmtmpPD1); mmtmpPD1 = _mm_madd_epi16(mmtmpPD1,dl_ch128_2[0]); // mmtmpPD1 contains imag part of 4 consecutive outputs (32-bit) mmtmpPD0 = _mm_srai_epi32(mmtmpPD0,output_shift); // print_ints("re(shift)",&mmtmpD0); mmtmpPD1 = _mm_srai_epi32(mmtmpPD1,output_shift); // print_ints("im(shift)",&mmtmpD1); mmtmpPD2 = _mm_unpacklo_epi32(mmtmpPD0,mmtmpPD1); mmtmpPD3 = _mm_unpackhi_epi32(mmtmpPD0,mmtmpPD1); // print_ints("c0",&mmtmpPD2); // print_ints("c1",&mmtmpPD3); rho128[0] = _mm_packs_epi32(mmtmpPD2,mmtmpPD3); //print_shorts("rx:",dl_ch128_2); //print_shorts("ch:",dl_ch128); //print_shorts("pack:",rho128); // multiply by conjugated channel mmtmpPD0 = _mm_madd_epi16(dl_ch128[1],dl_ch128_2[1]); // mmtmpD0 contains real part of 4 consecutive outputs (32-bit) mmtmpPD1 = _mm_shufflelo_epi16(dl_ch128[1],_MM_SHUFFLE(2,3,0,1)); mmtmpPD1 = _mm_shufflehi_epi16(mmtmpPD1,_MM_SHUFFLE(2,3,0,1)); mmtmpPD1 = _mm_sign_epi16(mmtmpPD1,*(__m128i*)conjugate); mmtmpPD1 = _mm_madd_epi16(mmtmpPD1,dl_ch128_2[1]); // mmtmpD1 contains imag part of 4 consecutive outputs (32-bit) mmtmpPD0 = _mm_srai_epi32(mmtmpPD0,output_shift); mmtmpPD1 = _mm_srai_epi32(mmtmpPD1,output_shift); mmtmpPD2 = _mm_unpacklo_epi32(mmtmpPD0,mmtmpPD1); mmtmpPD3 = _mm_unpackhi_epi32(mmtmpPD0,mmtmpPD1); rho128[1] =_mm_packs_epi32(mmtmpPD2,mmtmpPD3); //print_shorts("rx:",dl_ch128_2+1); //print_shorts("ch:",dl_ch128+1); //print_shorts("pack:",rho128+1); // multiply by conjugated channel mmtmpPD0 = _mm_madd_epi16(dl_ch128[2],dl_ch128_2[2]); // mmtmpPD0 contains real part of 4 consecutive outputs (32-bit) mmtmpPD1 = _mm_shufflelo_epi16(dl_ch128[2],_MM_SHUFFLE(2,3,0,1)); mmtmpPD1 = _mm_shufflehi_epi16(mmtmpPD1,_MM_SHUFFLE(2,3,0,1)); mmtmpPD1 = _mm_sign_epi16(mmtmpPD1,*(__m128i*)conjugate); mmtmpPD1 = _mm_madd_epi16(mmtmpPD1,dl_ch128_2[2]); // mmtmpPD1 contains imag part of 4 consecutive outputs (32-bit) mmtmpPD0 = _mm_srai_epi32(mmtmpPD0,output_shift); mmtmpPD1 = _mm_srai_epi32(mmtmpPD1,output_shift); mmtmpPD2 = _mm_unpacklo_epi32(mmtmpPD0,mmtmpPD1); mmtmpPD3 = _mm_unpackhi_epi32(mmtmpPD0,mmtmpPD1); rho128[2] = _mm_packs_epi32(mmtmpPD2,mmtmpPD3); //print_shorts("rx:",dl_ch128_2+2); //print_shorts("ch:",dl_ch128+2); //print_shorts("pack:",rho128+2); dl_ch128+=3; dl_ch128_2+=3; rho128+=3; #elif defined(__arm_) #endif } } } #if defined(__x86_64__) || defined(__i386__) _mm_empty(); _m_empty(); #endif } */ void pdcch_detection_mrc(NR_DL_FRAME_PARMS *frame_parms, int32_t **rxdataF_comp, uint8_t symbol) { uint8_t aatx; #if defined(__x86_64__) || defined(__i386__) __m128i *rxdataF_comp128_0,*rxdataF_comp128_1; #elif defined(__arm__) int16x8_t *rxdataF_comp128_0,*rxdataF_comp128_1; #endif int32_t i; if (frame_parms->nb_antennas_rx>1) { for (aatx=0; aatx<frame_parms->nb_antenna_ports_eNB; aatx++) { #if defined(__x86_64__) || defined(__i386__) rxdataF_comp128_0 = (__m128i *)&rxdataF_comp[(aatx<<1)][symbol*frame_parms->N_RB_DL*12]; rxdataF_comp128_1 = (__m128i *)&rxdataF_comp[(aatx<<1)+1][symbol*frame_parms->N_RB_DL*12]; #elif defined(__arm__) rxdataF_comp128_0 = (int16x8_t *)&rxdataF_comp[(aatx<<1)][symbol*frame_parms->N_RB_DL*12]; rxdataF_comp128_1 = (int16x8_t *)&rxdataF_comp[(aatx<<1)+1][symbol*frame_parms->N_RB_DL*12]; #endif // MRC on each re of rb for (i=0; i<frame_parms->N_RB_DL*3; i++) { #if defined(__x86_64__) || defined(__i386__) rxdataF_comp128_0[i] = _mm_adds_epi16(_mm_srai_epi16(rxdataF_comp128_0[i],1),_mm_srai_epi16(rxdataF_comp128_1[i],1)); #elif defined(__arm__) rxdataF_comp128_0[i] = vhaddq_s16(rxdataF_comp128_0[i],rxdataF_comp128_1[i]); #endif } } } #if defined(__x86_64__) || defined(__i386__) _mm_empty(); _m_empty(); #endif } void pdcch_siso(NR_DL_FRAME_PARMS *frame_parms, int32_t **rxdataF_comp, uint8_t l) { uint8_t rb,re,jj,ii; jj=0; ii=0; for (rb=0; rb<frame_parms->N_RB_DL; rb++) { for (re=0; re<12; re++) { rxdataF_comp[0][jj++] = rxdataF_comp[0][ii]; ii++; } } } void pdcch_alamouti(NR_DL_FRAME_PARMS *frame_parms, int32_t **rxdataF_comp, uint8_t symbol) { int16_t *rxF0,*rxF1; uint8_t rb,re; int32_t jj=(symbol*frame_parms->N_RB_DL*12); rxF0 = (int16_t*)&rxdataF_comp[0][jj]; //tx antenna 0 h0*y rxF1 = (int16_t*)&rxdataF_comp[2][jj]; //tx antenna 1 h1*y for (rb=0; rb<frame_parms->N_RB_DL; rb++) { for (re=0; re<12; re+=2) { // Alamouti RX combining rxF0[0] = rxF0[0] + rxF1[2]; rxF0[1] = rxF0[1] - rxF1[3]; rxF0[2] = rxF0[2] - rxF1[0]; rxF0[3] = rxF0[3] + rxF1[1]; rxF0+=4; rxF1+=4; } } } int32_t avgP[4]; #ifdef NR_PDCCH_DCI_RUN int32_t nr_rx_pdcch(PHY_VARS_NR_UE *ue, uint32_t frame, uint8_t nr_tti_rx, uint8_t eNB_id, MIMO_mode_t mimo_mode, uint32_t high_speed_flag, uint8_t is_secondary_ue, int nb_coreset_active, uint16_t symbol_mon, NR_SEARCHSPACE_TYPE_t searchSpaceType) { #ifdef MU_RECEIVER uint8_t eNB_id_i=eNB_id+1; //add 1 to eNB_id to separate from wanted signal, chosen as the B/F'd pilots from the SeNB are shifted by 1 #endif NR_UE_COMMON *common_vars = &ue->common_vars; NR_DL_FRAME_PARMS *frame_parms = &ue->frame_parms; NR_UE_PDCCH **pdcch_vars = ue->pdcch_vars[ue->current_thread_id[nr_tti_rx]]; NR_UE_PDCCH *pdcch_vars2 = ue->pdcch_vars[ue->current_thread_id[nr_tti_rx]][eNB_id]; int do_common; if (searchSpaceType == common) do_common=1; if (searchSpaceType == ue_specific) do_common=0; uint8_t log2_maxh, aatx, aarx; int32_t avgs; uint8_t n_pdcch_symbols; // the variable mi can be removed for NR uint8_t mi = get_mi(frame_parms, nr_tti_rx); /* * The following variables have been extracted from higher layer parameters * MIB1 => pdcchConfigSIB1 * ControlResourceSet IE * pdcch-Config * pdcch-ConfigCommon */ #if 0 /* * initialize this values for testing */ pdcch_vars2->coreset[nb_coreset_active].frequencyDomainResources = 0x1FFF2FF00000; //pdcch_vars2->coreset[nb_coreset_active].frequencyDomainResources = 0x1E0000000000; pdcch_vars2->coreset[nb_coreset_active].duration = 2; pdcch_vars2->coreset[nb_coreset_active].cce_reg_mappingType.shiftIndex = 0; pdcch_vars2->coreset[nb_coreset_active].cce_reg_mappingType.reg_bundlesize = bundle_n6; pdcch_vars2->coreset[nb_coreset_active].cce_reg_mappingType.interleaversize = interleave_n2; pdcch_vars2->coreset[nb_coreset_active].pdcchDMRSScramblingID = 1; for (int i=0; i < NR_NBR_SEARCHSPACE_ACT_BWP; i++){ pdcch_vars[eNB_id]->searchSpace[i].nrofCandidates_aggrlevel1 = 7; pdcch_vars[eNB_id]->searchSpace[i].nrofCandidates_aggrlevel2 = 6; pdcch_vars[eNB_id]->searchSpace[i].nrofCandidates_aggrlevel4 = 4; pdcch_vars[eNB_id]->searchSpace[i].nrofCandidates_aggrlevel8 = 3; pdcch_vars[eNB_id]->searchSpace[i].nrofCandidates_aggrlevel16 = 1; pdcch_vars[eNB_id]->searchSpace[i].searchSpaceType.sfi_nrofCandidates_aggrlevel1 = 7; pdcch_vars[eNB_id]->searchSpace[i].searchSpaceType.sfi_nrofCandidates_aggrlevel2 = 6; pdcch_vars[eNB_id]->searchSpace[i].searchSpaceType.sfi_nrofCandidates_aggrlevel4 = 4; pdcch_vars[eNB_id]->searchSpace[i].searchSpaceType.sfi_nrofCandidates_aggrlevel8 = 3; pdcch_vars[eNB_id]->searchSpace[i].searchSpaceType.sfi_nrofCandidates_aggrlevel16 = 1; } /* * to be removed after testing */ #endif //(0) // number of RB (1 symbol) or REG (12 RE) in one CORESET: higher-layer parameter CORESET-freq-dom // (bit map 45 bits: each bit indicates 6 RB in CORESET -> 1 bit MSB indicates PRB 0..6 are part of CORESET) uint64_t coreset_freq_dom = pdcch_vars2->coreset[nb_coreset_active].frequencyDomainResources; // number of symbols in CORESET: higher-layer parameter CORESET-time-dur {1,2,3} int coreset_time_dur = pdcch_vars2->coreset[nb_coreset_active].duration; // depends on higher-layer parameter CORESET-shift-index {0,1,...,274} int n_shift = pdcch_vars2->coreset[nb_coreset_active].cce_reg_mappingType.shiftIndex; // higher-layer parameter CORESET-REG-bundle-size (for non-interleaved L = 6 / for interleaved L {2,6}) NR_UE_CORESET_REG_bundlesize_t reg_bundle_size_L = pdcch_vars2->coreset[nb_coreset_active].cce_reg_mappingType.reg_bundlesize; // higher-layer parameter CORESET-interleaver-size {2,3,6} NR_UE_CORESET_interleaversize_t coreset_interleaver_size_R= pdcch_vars2->coreset[nb_coreset_active].cce_reg_mappingType.interleaversize; NR_UE_CORESET_precoder_granularity_t precoder_granularity = pdcch_vars2->coreset[nb_coreset_active].precoderGranularity; int tci_statesPDCCH = pdcch_vars2->coreset[nb_coreset_active].tciStatesPDCCH; int tci_present = pdcch_vars2->coreset[nb_coreset_active].tciPresentInDCI; uint16_t pdcch_DMRS_scrambling_id = pdcch_vars2->coreset[nb_coreset_active].pdcchDMRSScramblingID; // The UE can be assigned 4 different BWP but only one active at a time. // For each BWP the number of CORESETs is limited to 3 (including initial CORESET Id=0 -> ControlResourceSetId (0..maxNrofControlReourceSets-1) (0..12-1) //uint32_t n_BWP_start = 0; //uint32_t n_rb_offset = 0; uint32_t n_rb_offset = pdcch_vars2->coreset[nb_coreset_active].rb_offset+43; //to be removed 43 // start time position for CORESET // parameter symbol_mon is a 14 bits bitmap indicating monitoring symbols within a slot uint8_t start_symbol = 0; // at the moment we are considering that the PDCCH is always starting at symbol 0 of current slot // the following code to initialize start_symbol must be activated once we implement PDCCH demapping on symbol not equal to 0 (considering symbol_mon) for (int i=0; i < 14; i++) { if ((symbol_mon >> (i+1))&0x1 != 0) { start_symbol = i; i=14; } } #ifdef NR_PDCCH_DCI_DEBUG printf("\t<-NR_PDCCH_DCI_DEBUG (nr_rx_pdcch)-> symbol_mon=(%d) and start_symbol=(%d)\n",symbol_mon,start_symbol); printf("\t<-NR_PDCCH_DCI_DEBUG (nr_rx_pdcch)-> coreset_freq_dom=(%lld) n_rb_offset=(%d) coreset_time_dur=(%d) n_shift=(%d) reg_bundle_size_L=(%d) coreset_interleaver_size_R=(%d) \n", coreset_freq_dom,n_rb_offset,coreset_time_dur,n_shift,reg_bundle_size_L,coreset_interleaver_size_R); #endif // // according to 38.213 v15.1.0: a PDCCH monitoring pattern within a slot, // indicating first symbol(s) of the control resource set within a slot // for PDCCH monitoring, by higher layer parameter monitoringSymbolsWithinSlot // // at the moment we do not implement this and start_symbol is always 0 // note that the bitmap symbol_mon may indicate several monitoring times within a same slot (symbols 0..13) // this may lead to a modification in ue scheduler // indicates the number of active CORESETs for the current BWP to decode PDCCH: max is 3 (this variable is not useful here, to be removed) uint8_t coreset_nbr_act; // indicates the number of REG contained in the PDCCH (number of RBs * number of symbols, in CORESET) uint8_t coreset_nbr_reg; uint32_t coreset_C; uint32_t coreset_nbr_rb = 0; // for (int j=0; j < coreset_nbr_act; j++) { // for each active CORESET (max number of active CORESETs in a BWP is 3), // we calculate the number of RB for each CORESET bitmap #ifdef NR_PDCCH_DCI_DEBUG printf("\t<-NR_PDCCH_DCI_DEBUG (nr_rx_pdcch)-> coreset_freq_dom=(%lld)\n",coreset_freq_dom); #endif int i; //for each bit in the coreset_freq_dom bitmap for (i = 0; i < 45; i++) { // this loop counts each bit of the bit map coreset_freq_dom, and increments nbr_RB_coreset for each bit set to '1' if (((coreset_freq_dom & 0x1FFFFFFFFFFF) >> i) & 0x1) coreset_nbr_rb++; } coreset_nbr_rb = 6 * coreset_nbr_rb; // coreset_nbr_rb has to be multiplied by 6 to indicate the number of PRB or REG(=12 RE) within the CORESET #ifdef NR_PDCCH_DCI_DEBUG printf("\t<-NR_PDCCH_DCI_DEBUG (nr_rx_pdcch)-> coreset_freq_dom=(%lld,%llx), coreset_nbr_rb=%d\n", coreset_freq_dom,coreset_freq_dom,coreset_nbr_rb); #endif coreset_nbr_reg = coreset_time_dur * coreset_nbr_rb; coreset_C = (uint32_t)(coreset_nbr_reg / (reg_bundle_size_L * coreset_interleaver_size_R)); #ifdef NR_PDCCH_DCI_DEBUG printf("\t<-NR_PDCCH_DCI_DEBUG (nr_rx_pdcch)-> coreset_nbr_rb=%d, coreset_nbr_reg=%d, coreset_C=(%d/(%d*%d))=%d\n", coreset_nbr_rb, coreset_nbr_reg, coreset_nbr_reg, reg_bundle_size_L,coreset_interleaver_size_R, coreset_C); #endif for (int s = start_symbol; s < (start_symbol + coreset_time_dur); s++) { printf("\t<-NR_PDCCH_DCI_DEBUG (nr_rx_pdcch)-> we enter process pdcch ofdm symbol s=%d where coreset_time_dur=%d\n",s,coreset_time_dur); /* if (is_secondary_ue == 1) { pdcch_extract_rbs_single(common_vars->common_vars_rx_data_per_thread[ue->current_thread_id[nr_tti_rx]].rxdataF, common_vars->common_vars_rx_data_per_thread[ue->current_thread_id[nr_tti_rx]].dl_ch_estimates[eNB_id+1], //add 1 to eNB_id to compensate for the shifted B/F'd pilots from the SeNB pdcch_vars[eNB_id]->rxdataF_ext, pdcch_vars[eNB_id]->dl_ch_estimates_ext, 0, high_speed_flag, frame_parms); #ifdef MU_RECEIVER pdcch_extract_rbs_single(common_vars->common_vars_rx_data_per_thread[ue->current_thread_id[nr_tti_rx]].rxdataF, common_vars->common_vars_rx_data_per_thread[ue->current_thread_id[nr_tti_rx]].dl_ch_estimates[eNB_id_i - 1], //subtract 1 to eNB_id_i to compensate for the non-shifted pilots from the PeNB pdcch_vars[eNB_id_i]->rxdataF_ext,//shift by two to simulate transmission from a second antenna pdcch_vars[eNB_id_i]->dl_ch_estimates_ext,//shift by two to simulate transmission from a second antenna 0, high_speed_flag, frame_parms); #endif //MU_RECEIVER } else if (frame_parms->nb_antenna_ports_eNB>1) { pdcch_extract_rbs_dual(common_vars->common_vars_rx_data_per_thread[ue->current_thread_id[nr_tti_rx]].rxdataF, common_vars->common_vars_rx_data_per_thread[ue->current_thread_id[nr_tti_rx]].dl_ch_estimates[eNB_id], pdcch_vars[eNB_id]->rxdataF_ext, pdcch_vars[eNB_id]->dl_ch_estimates_ext, 0, high_speed_flag, frame_parms); } else {*/ #ifdef NR_PDCCH_DCI_DEBUG printf("\t<-NR_PDCCH_DCI_DEBUG (nr_rx_pdcch)-> we enter nr_pdcch_extract_rbs_single(is_secondary_ue=%d) to remove DM-RS PDCCH\n", is_secondary_ue); printf("\t<-NR_PDCCH_DCI_DEBUG (nr_rx_pdcch)-> in nr_pdcch_extract_rbs_single(rxdataF -> rxdataF_ext || dl_ch_estimates -> dl_ch_estimates_ext)\n"); #endif nr_pdcch_extract_rbs_single(common_vars->common_vars_rx_data_per_thread[ue->current_thread_id[nr_tti_rx]].rxdataF, common_vars->common_vars_rx_data_per_thread[ue->current_thread_id[nr_tti_rx]].dl_ch_estimates[eNB_id], pdcch_vars[eNB_id]->rxdataF_ext, pdcch_vars[eNB_id]->dl_ch_estimates_ext, s, high_speed_flag, frame_parms, coreset_freq_dom, coreset_nbr_rb, n_rb_offset); /* printf("\t### in nr_rx_pdcch() function we enter pdcch_extract_rbs_single(is_secondary_ue=%d) to remove DM-RS PDCCH\n",is_secondary_ue); pdcch_extract_rbs_single(common_vars->common_vars_rx_data_per_thread[ue->current_thread_id[nr_tti_rx]].rxdataF, common_vars->common_vars_rx_data_per_thread[ue->current_thread_id[nr_tti_rx]].dl_ch_estimates[eNB_id], pdcch_vars[eNB_id]->rxdataF_ext, pdcch_vars[eNB_id]->dl_ch_estimates_ext, 0, high_speed_flag, frame_parms); */ //} #ifdef NR_PDCCH_DCI_DEBUG printf("\t<-NR_PDCCH_DCI_DEBUG (nr_rx_pdcch)-> we enter pdcch_channel_level(avgP=%d) => compute channel level based on ofdm symbol 0, pdcch_vars[eNB_id]->dl_ch_estimates_ext\n",avgP); printf("\t<-NR_PDCCH_DCI_DEBUG (nr_rx_pdcch)-> in pdcch_channel_level(dl_ch_estimates_ext -> dl_ch_estimates_ext)\n"); #endif // compute channel level based on ofdm symbol 0 pdcch_channel_level(pdcch_vars[eNB_id]->dl_ch_estimates_ext, frame_parms, avgP, coreset_nbr_rb); avgs = 0; for (aatx = 0; aatx < frame_parms->nb_antenna_ports_eNB; aatx++) for (aarx = 0; aarx < frame_parms->nb_antennas_rx; aarx++) avgs = cmax(avgs, avgP[(aarx << 1) + aatx]); log2_maxh = (log2_approx(avgs) / 2) + 5; //+frame_parms->nb_antennas_rx; #ifdef UE_DEBUG_TRACE LOG_D(PHY,"nr_tti_rx %d: pdcch log2_maxh = %d (%d,%d)\n",nr_tti_rx,log2_maxh,avgP[0],avgs); #endif #if T_TRACER T(T_UE_PHY_PDCCH_ENERGY, T_INT(eNB_id), T_INT(0), T_INT(frame%1024), T_INT(nr_tti_rx), T_INT(avgP[0]), T_INT(avgP[1]), T_INT(avgP[2]), T_INT(avgP[3])); #endif #ifdef NR_PDCCH_DCI_DEBUG printf("\t<-NR_PDCCH_DCI_DEBUG (nr_rx_pdcch)-> we enter nr_pdcch_channel_compensation(log2_maxh=%d)\n",log2_maxh); printf("\t<-NR_PDCCH_DCI_DEBUG (nr_rx_pdcch)-> in nr_pdcch_channel_compensation(rxdataF_ext x dl_ch_estimates_ext -> rxdataF_comp)\n"); #endif // compute LLRs for ofdm symbol 0 only nr_pdcch_channel_compensation(pdcch_vars[eNB_id]->rxdataF_ext, pdcch_vars[eNB_id]->dl_ch_estimates_ext, pdcch_vars[eNB_id]->rxdataF_comp, (aatx > 1) ? pdcch_vars[eNB_id]->rho : NULL, frame_parms, s, log2_maxh, coreset_nbr_rb); // log2_maxh+I0_shift /* printf("\t### in nr_rx_pdcch() function we enter pdcch_channel_compensation(log2_maxh=%d) => compute LLRs for ofdm symbol 0 only, pdcch_vars[eNB_id]->rxdataF_ext ---> pdcch_vars[eNB_id]->rxdataF_comp\n",log2_maxh); // compute LLRs for ofdm symbol 0 only pdcch_channel_compensation(pdcch_vars[eNB_id]->rxdataF_ext, pdcch_vars[eNB_id]->dl_ch_estimates_ext, pdcch_vars[eNB_id]->rxdataF_comp, (aatx>1) ? pdcch_vars[eNB_id]->rho : NULL, frame_parms, 0, log2_maxh);// log2_maxh+I0_shift */ #ifdef DEBUG_PHY if (nr_tti_rx==5) write_output("rxF_comp_d.m","rxF_c_d",&pdcch_vars[eNB_id]->rxdataF_comp[0][s*frame_parms->N_RB_DL*12],frame_parms->N_RB_DL*12,1,1); #endif #ifdef MU_RECEIVER if (is_secondary_ue) { //get MF output for interfering stream pdcch_channel_compensation(pdcch_vars[eNB_id_i]->rxdataF_ext, pdcch_vars[eNB_id_i]->dl_ch_estimates_ext, pdcch_vars[eNB_id_i]->rxdataF_comp, (aatx>1) ? pdcch_vars[eNB_id_i]->rho : NULL, frame_parms, 0, log2_maxh);// log2_maxh+I0_shift #ifdef DEBUG_PHY write_output("rxF_comp_i.m","rxF_c_i",&pdcch_vars[eNB_id_i]->rxdataF_comp[0][s*frame_parms->N_RB_DL*12],frame_parms->N_RB_DL*12,1,1); #endif pdcch_dual_stream_correlation(frame_parms, 0, pdcch_vars[eNB_id]->dl_ch_estimates_ext, pdcch_vars[eNB_id_i]->dl_ch_estimates_ext, pdcch_vars[eNB_id]->dl_ch_rho_ext, log2_maxh); } #endif //MU_RECEIVER if (frame_parms->nb_antennas_rx > 1) { #ifdef MU_RECEIVER if (is_secondary_ue) { pdcch_detection_mrc_i(frame_parms, pdcch_vars[eNB_id]->rxdataF_comp, pdcch_vars[eNB_id_i]->rxdataF_comp, pdcch_vars[eNB_id]->rho, pdcch_vars[eNB_id]->dl_ch_rho_ext, 0); #ifdef DEBUG_PHY write_output("rxF_comp_d.m","rxF_c_d",&pdcch_vars[eNB_id]->rxdataF_comp[0][s*frame_parms->N_RB_DL*12],frame_parms->N_RB_DL*12,1,1); write_output("rxF_comp_i.m","rxF_c_i",&pdcch_vars[eNB_id_i]->rxdataF_comp[0][s*frame_parms->N_RB_DL*12],frame_parms->N_RB_DL*12,1,1); #endif } else #endif //MU_RECEIVER #ifdef NR_PDCCH_DCI_DEBUG printf("\t<-NR_PDCCH_DCI_DEBUG (nr_rx_pdcch)-> we enter pdcch_detection_mrc(frame_parms->nb_antennas_rx=%d)\n", frame_parms->nb_antennas_rx); #endif pdcch_detection_mrc(frame_parms, pdcch_vars[eNB_id]->rxdataF_comp,s); } if (mimo_mode == SISO) { #ifdef NR_PDCCH_DCI_DEBUG printf("\t<-NR_PDCCH_DCI_DEBUG (nr_rx_pdcch)-> we enter pdcch_siso ---> pdcch_vars[eNB_id]->rxdataF_comp Nothing to do here. TO BE REMOVED!!!\n"); #endif //pdcch_siso(frame_parms, pdcch_vars[eNB_id]->rxdataF_comp,s); } else pdcch_alamouti(frame_parms, pdcch_vars[eNB_id]->rxdataF_comp,s); #ifdef MU_RECEIVER if (is_secondary_ue) { pdcch_qpsk_qpsk_llr(frame_parms, pdcch_vars[eNB_id]->rxdataF_comp, pdcch_vars[eNB_id_i]->rxdataF_comp, pdcch_vars[eNB_id]->dl_ch_rho_ext, pdcch_vars[eNB_id]->llr16, //subsequent function require 16 bit llr, but output must be 8 bit (actually clipped to 4, because of the Viterbi decoder) pdcch_vars[eNB_id]->llr, 0); /* #ifdef DEBUG_PHY if (subframe==5) { write_output("llr8_seq.m","llr8",&pdcch_vars[eNB_id]->llr[s*frame_parms->N_RB_DL*12],frame_parms->N_RB_DL*12,1,4); write_output("llr16_seq.m","llr16",&pdcch_vars[eNB_id]->llr16[s*frame_parms->N_RB_DL*12],frame_parms->N_RB_DL*12,1,4); } #endif*/ } else { #endif //MU_RECEIVER #ifdef NR_PDCCH_DCI_DEBUG printf("\t<-NR_PDCCH_DCI_DEBUG (nr_rx_pdcch)-> we enter nr_pdcch_llr(for symbol %d), pdcch_vars[eNB_id]->rxdataF_comp ---> pdcch_vars[eNB_id]->llr \n",s); printf("\t<-NR_PDCCH_DCI_DEBUG (nr_rx_pdcch)-> in nr_pdcch_llr(rxdataF_comp -> llr)\n"); #endif nr_pdcch_llr(frame_parms, pdcch_vars[eNB_id]->rxdataF_comp, (char *) pdcch_vars[eNB_id]->llr, s, coreset_nbr_rb); /* printf("\t### in nr_rx_pdcch() function we enter pdcch_llr(for symbol 0), pdcch_vars[eNB_id]->rxdataF_comp ---> pdcch_vars[eNB_id]->llr \n"); pdcch_llr(frame_parms, pdcch_vars[eNB_id]->rxdataF_comp,(char *) pdcch_vars[eNB_id]->llr, 0); */ /*#ifdef DEBUG_PHY write_output("llr8_seq.m","llr8",&pdcch_vars[eNB_id]->llr[s*frame_parms->N_RB_DL*12],frame_parms->N_RB_DL*12,1,4); #endif*/ #ifdef MU_RECEIVER } #endif //MU_RECEIVER #if T_TRACER T(T_UE_PHY_PDCCH_IQ, T_INT(frame_parms->N_RB_DL), T_INT(frame_parms->N_RB_DL), T_INT(n_pdcch_symbols), T_BUFFER(pdcch_vars[eNB_id]->rxdataF_comp, frame_parms->N_RB_DL*12*n_pdcch_symbols* 4)); #endif #ifdef DEBUG_DCI_DECODING printf("demapping: nr_tti_rx %d, mi %d, tdd_config %d\n",nr_tti_rx,get_mi(frame_parms,nr_tti_rx),frame_parms->tdd_config); #endif } #ifdef NR_PDCCH_DCI_DEBUG printf("\t<-NR_PDCCH_DCI_DEBUG (nr_rx_pdcch)-> we enter nr_pdcch_demapping_deinterleaving()\n"); #endif nr_pdcch_demapping_deinterleaving(pdcch_vars[eNB_id]->llr, (uint16_t*) pdcch_vars[eNB_id]->e_rx, frame_parms, coreset_time_dur, coreset_nbr_rb, reg_bundle_size_L, coreset_interleaver_size_R, n_shift); #if 0 #ifdef NR_PDCCH_DCI_DEBUG printf("\t<-NR_PDCCH_DCI_DEBUG (nr_rx_pdcch)-> we enter nr_pdcch_demapping()\n"); #endif nr_pdcch_demapping(pdcch_vars[eNB_id]->llr, pdcch_vars[eNB_id]->wbar, frame_parms, coreset_time_dur, coreset_nbr_rb); #ifdef NR_PDCCH_DCI_DEBUG printf("\t<-NR_PDCCH_DCI_DEBUG (nr_rx_pdcch)-> we enter nr_pdcch_deinterleaving()\n"); #endif nr_pdcch_deinterleaving(frame_parms, (uint16_t*) pdcch_vars[eNB_id]->e_rx, pdcch_vars[eNB_id]->wbar, coreset_time_dur, reg_bundle_size_L, coreset_interleaver_size_R, n_shift, coreset_nbr_rb); #ifdef NR_PDCCH_DCI_DEBUG printf("\t<-NR_PDCCH_DCI_DEBUG (nr_rx_pdcch)-> we enter nr_pdcch_unscrambling()\n"); for (int i=0; i<(coreset_time_dur*coreset_nbr_rb*9); i++){ printf("\te_rx[%d]=(%d,%d)",i,*(char*) &pdcch_vars[eNB_id]->e_rx[i],*(1 + (char*) &pdcch_vars[eNB_id]->e_rx[i])); if (i%10 == 0) printf("\n"); } printf("\n"); #endif #endif //#if 0 #ifdef NR_PDCCH_DCI_DEBUG // printf("\t<-NR_PDCCH_DCI_DEBUG (nr_rx_pdcch)-> we end nr_pdcch_unscrambling()\n"); // for (int i=0; i<(coreset_time_dur*coreset_nbr_rb*9); i++){ // printf("\t before unscrambling : e_rx[%d]=(%d,%d)\n",i,*(char*) &pdcch_vars[eNB_id]->e_rx[i],*(1 + (char*) &pdcch_vars[eNB_id]->e_rx[i])); // } // printf("\n"); #endif nr_pdcch_unscrambling(pdcch_vars[eNB_id]->crnti, frame_parms, nr_tti_rx, (uint16_t*) pdcch_vars[eNB_id]->e_rx, coreset_time_dur*coreset_nbr_rb*9*2, // get_nCCE(n_pdcch_symbols, frame_parms, mi) * 72, pdcch_DMRS_scrambling_id, do_common); #ifdef NR_PDCCH_DCI_DEBUG printf("\t<-NR_PDCCH_DCI_DEBUG (nr_rx_pdcch)-> we end nr_pdcch_unscrambling()\n"); // for (int i=0; i<(coreset_time_dur*coreset_nbr_rb*9); i++){ // printf("\t after unscrambling : e_rx[%d]=(%d,%d)\n",i,*(char*) &pdcch_vars[eNB_id]->e_rx[i],*(1 + (char*) &pdcch_vars[eNB_id]->e_rx[i])); // } // printf("\n"); #endif //#endif //0 /* printf("\t### in nr_rx_pdcch() function we enter pdcch_demapping()\n"); pdcch_demapping(pdcch_vars[eNB_id]->llr, pdcch_vars[eNB_id]->wbar, frame_parms, n_pdcch_symbols, get_mi(frame_parms,nr_tti_rx)); printf("\t### in nr_rx_pdcch() function we enter pdcch_deinterleaving()\n"); pdcch_deinterleaving(frame_parms, (uint16_t*)pdcch_vars[eNB_id]->e_rx, pdcch_vars[eNB_id]->wbar, n_pdcch_symbols, mi); printf("\t### in nr_rx_pdcch() function we enter pdcch_unscrambling()\n"); pdcch_unscrambling(frame_parms, nr_tti_rx, pdcch_vars[eNB_id]->e_rx, get_nCCE(n_pdcch_symbols,frame_parms,mi)*72); */ pdcch_vars[eNB_id]->num_pdcch_symbols = n_pdcch_symbols; #ifdef NR_PDCCH_DCI_DEBUG printf("\t<-NR_PDCCH_DCI_DEBUG (nr_rx_pdcch)-> Ending nr_rx_pdcch() function\n"); #endif return (0); } #endif void pdcch_scrambling(NR_DL_FRAME_PARMS *frame_parms, uint8_t nr_tti_rx, uint8_t *e, uint32_t length) { int i; uint8_t reset; uint32_t x1, x2, s=0; reset = 1; // x1 is set in lte_gold_generic x2 = (nr_tti_rx<<9) + frame_parms->Nid_cell; //this is c_init in 36.211 Sec 6.8.2 for (i=0; i<length; i++) { if ((i&0x1f)==0) { s = lte_gold_generic(&x1, &x2, reset); //printf("lte_gold[%d]=%x\n",i,s); reset = 0; } // printf("scrambling %d : e %d, c %d\n",i,e[i],((s>>(i&0x1f))&1)); if (e[i] != 2) // <NIL> element is 2 e[i] = (e[i]&1) ^ ((s>>(i&0x1f))&1); } } #ifdef NR_PDCCH_DCI_RUN void nr_pdcch_unscrambling(uint16_t crnti, NR_DL_FRAME_PARMS *frame_parms, uint8_t nr_tti_rx, uint16_t *z, uint32_t length, uint16_t pdcch_DMRS_scrambling_id, int do_common) { int i; uint8_t reset; uint32_t x1, x2, s = 0; uint16_t n_id; //{0,1,...,65535} uint32_t n_rnti; reset = 1; // x1 is set in first call to lte_gold_generic //do_common=1; if (do_common){ n_id = frame_parms->Nid_cell; n_rnti = 0; } else { n_id = pdcch_DMRS_scrambling_id; n_rnti = (uint32_t)crnti; } //x2 = ((n_rnti * (1 << 16)) + n_id)%(1 << 31); //uint32_t puissance_2_16 = ((1<<16)*n_rnti)+n_id; //uint32_t puissance_2_31= (1<<30)*2; //uint32_t calc_x2=puissance_2_16%puissance_2_31; x2 = (((1<<16)*n_rnti)+n_id)%((1<<30)*2); //this is c_init in 38.211 v15.1.0 Section 7.3.2.3 // x2 = (nr_tti_rx << 9) + frame_parms->Nid_cell; //this is c_init in 36.211 Sec 6.8.2 #ifndef NR_PDCCH_DCI_DEBUG printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_pdcch_unscrambling)-> (c_init=%d, n_id=%d, n_rnti=%d, length=%d)\n",x2,n_id,n_rnti,length); #endif for (i = 0; i < length; i++) { if ((i & 0x1f) == 0) { s = lte_gold_generic(&x1, &x2, reset); //printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_pdcch_unscrambling)-> lte_gold[%d]=%x\n",i,s); reset = 0; } #ifndef NR_PDCCH_DCI_DEBUG if (i%2 == 0) printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_pdcch_unscrambling)-> unscrambling %d : scrambled_z=%d, => ", i,*(char*) &z[(int)floor(i/2)]); if (i%2 == 1) printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_pdcch_unscrambling)-> unscrambling %d : scrambled_z=%d, => ", i,*(1 + (char*) &z[(int)floor(i/2)])); #endif if (((s >> (i % 32)) & 1) == 1){ if (i%2 == 0) *(char*) &z[(int)floor(i/2)] = -(*(char*) &z[(int)floor(i/2)]); if (i%2 == 1) *(1 + (char*) &z[(int)floor(i/2)]) = -(*(1 + (char*) &z[(int)floor(i/2)])); } //llr[i] = -llr[i]; //llr[i] = (-1)*llr[i]; #ifndef NR_PDCCH_DCI_DEBUG if (i%2 == 0) printf("unscrambled_z=%d\n",*(char*) &z[(int)floor(i/2)]); if (i%2 == 1) printf("unscrambled_z=%d\n",*(1 + (char*) &z[(int)floor(i/2)])); #endif } } #if 0 void nr_pdcch_unscrambling_tmp(uint16_t crnti, NR_DL_FRAME_PARMS *frame_parms, uint8_t nr_tti_rx, double llr[], uint32_t length, uint16_t pdcch_DMRS_scrambling_id, int do_common) { int i; uint8_t reset; uint32_t x1, x2, s = 0; uint16_t n_id; //{0,1,...,65535} uint32_t n_rnti; reset = 1; // x1 is set in first call to lte_gold_generic //do_common=1; if (do_common){ n_id = frame_parms->Nid_cell; n_rnti = 0; } else { n_id = pdcch_DMRS_scrambling_id; n_rnti = (uint32_t)crnti; } //x2 = ((n_rnti * (1 << 16)) + n_id)%(1 << 31); //uint32_t puissance_2_16 = ((1<<16)*n_rnti)+n_id; //uint32_t puissance_2_31= (1<<30)*2; //uint32_t calc_x2=puissance_2_16%puissance_2_31; x2 = (((1<<16)*n_rnti)+n_id)%((1<<30)*2); //this is c_init in 38.211 v15.1.0 Section 7.3.2.3 // x2 = (nr_tti_rx << 9) + frame_parms->Nid_cell; //this is c_init in 36.211 Sec 6.8.2 #ifdef NR_PDCCH_DCI_DEBUG printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_pdcch_unscrambling)-> (c_init=%d, n_id=%d, n_rnti=%d, length=%d)\n",x2,n_id,n_rnti,length); #endif for (i = 0; i < length; i++) { if ((i & 0x1f) == 0) { s = lte_gold_generic(&x1, &x2, reset); printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_pdcch_unscrambling)-> lte_gold[%d]=%x\n",i,s); reset = 0; } printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_pdcch_unscrambling)-> unscrambling %d : scrambled_llr=%d, c %d => ",i,llr[i],((s>>(i&0x1f))&1)); if (((s >> (i % 32)) & 1) == 1) llr[i] = -llr[i]; //llr[i] = (-1)*llr[i]; printf("unscrambled_llr=%d\n",llr[i]); } } void nr_pdcch_unscrambling_old(uint16_t crnti, NR_DL_FRAME_PARMS *frame_parms, uint8_t nr_tti_rx, int8_t* llr, uint32_t length, uint16_t pdcch_DMRS_scrambling_id, int do_common) { int i; uint8_t reset; uint32_t x1, x2, s = 0; uint16_t n_id; //{0,1,...,65535} uint32_t n_rnti; reset = 1; // x1 is set in first call to lte_gold_generic //do_common=1; if (do_common){ n_id = frame_parms->Nid_cell; n_rnti = 0; } else { n_id = pdcch_DMRS_scrambling_id; n_rnti = (uint32_t)crnti; } //x2 = ((n_rnti * (1 << 16)) + n_id)%(1 << 31); //uint32_t puissance_2_16 = ((1<<16)*n_rnti)+n_id; //uint32_t puissance_2_31= (1<<30)*2; //uint32_t calc_x2=puissance_2_16%puissance_2_31; x2 = (((1<<16)*n_rnti)+n_id)%((1<<30)*2); //this is c_init in 38.211 v15.1.0 Section 7.3.2.3 // x2 = (nr_tti_rx << 9) + frame_parms->Nid_cell; //this is c_init in 36.211 Sec 6.8.2 #ifdef NR_PDCCH_DCI_DEBUG printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_pdcch_unscrambling)-> (c_init=%d, n_id=%d, n_rnti=%d)\n",x2,n_id,n_rnti); #endif for (i = 0; i < length; i++) { if ((i & 0x1f) == 0) { s = lte_gold_generic(&x1, &x2, reset); // printf("lte_gold[%d]=%x\n",i,s); reset = 0; } // printf("unscrambling %d : e %d, c %d => ",i,llr[i],((s>>(i&0x1f))&1)); if (((s >> (i % 32)) & 1) == 0) llr[i] = -llr[i]; // printf("%d\n",llr[i]); } } #endif // 0 #endif void pdcch_unscrambling(NR_DL_FRAME_PARMS *frame_parms, uint8_t nr_tti_rx, int8_t* llr, uint32_t length) { int i; uint8_t reset; uint32_t x1, x2, s=0; reset = 1; // x1 is set in first call to lte_gold_generic x2 = (nr_tti_rx<<9) + frame_parms->Nid_cell; //this is c_init in 36.211 Sec 6.8.2 for (i=0; i<length; i++) { if ((i&0x1f)==0) { s = lte_gold_generic(&x1, &x2, reset); // printf("lte_gold[%d]=%x\n",i,s); reset = 0; } // printf("unscrambling %d : e %d, c %d => ",i,llr[i],((s>>(i&0x1f))&1)); if (((s>>(i%32))&1)==0) llr[i] = -llr[i]; // printf("%d\n",llr[i]); } } /*uint8_t get_num_pdcch_symbols(uint8_t num_dci, DCI_ALLOC_t *dci_alloc, NR_DL_FRAME_PARMS *frame_parms, uint8_t nr_tti_rx) { uint16_t numCCE = 0; uint8_t i; uint8_t nCCEmin = 0; uint16_t CCE_max_used_index = 0; uint16_t firstCCE_max = dci_alloc[0].firstCCE; uint8_t L = dci_alloc[0].L; // check pdcch duration imposed by PHICH duration (Section 6.9 of 36-211) if (frame_parms->Ncp==1) { // extended prefix if ((frame_parms->frame_type == TDD) && ((frame_parms->tdd_config<3)||(frame_parms->tdd_config==6)) && ((nr_tti_rx==1) || (nr_tti_rx==6))) // subframes 1 and 6 (S-subframes) for 5ms switching periodicity are 2 symbols nCCEmin = 2; else { // 10ms switching periodicity is always 3 symbols, any DL-only subframe is 3 symbols nCCEmin = 3; } } // compute numCCE for (i=0; i<num_dci; i++) { // printf("dci %d => %d\n",i,dci_alloc[i].L); numCCE += (1<<(dci_alloc[i].L)); if(firstCCE_max < dci_alloc[i].firstCCE) { firstCCE_max = dci_alloc[i].firstCCE; L = dci_alloc[i].L; } } CCE_max_used_index = firstCCE_max + (1<<L) - 1; //if ((9*numCCE) <= (frame_parms->N_RB_DL*2)) if (CCE_max_used_index < get_nCCE(1, frame_parms, get_mi(frame_parms, nr_tti_rx))) return(cmax(1,nCCEmin)); //else if ((9*numCCE) <= (frame_parms->N_RB_DL*((frame_parms->nb_antenna_ports_eNB==4) ? 4 : 5))) else if (CCE_max_used_index < get_nCCE(2, frame_parms, get_mi(frame_parms, nr_tti_rx))) return(cmax(2,nCCEmin)); //else if ((9*numCCE) <= (frame_parms->N_RB_DL*((frame_parms->nb_antenna_ports_eNB==4) ? 7 : 8))) else if (CCE_max_used_index < get_nCCE(3, frame_parms, get_mi(frame_parms, nr_tti_rx))) return(cmax(3,nCCEmin)); else if (frame_parms->N_RB_DL<=10) { if (frame_parms->Ncp == 0) { // normal CP printf("numCCE %d, N_RB_DL = %d : should be returning 4 PDCCH symbols (%d,%d,%d)\n",numCCE,frame_parms->N_RB_DL, get_nCCE(1, frame_parms, get_mi(frame_parms, nr_tti_rx)), get_nCCE(2, frame_parms, get_mi(frame_parms, nr_tti_rx)), get_nCCE(3, frame_parms, get_mi(frame_parms, nr_tti_rx))); if ((9*numCCE) <= (frame_parms->N_RB_DL*((frame_parms->nb_antenna_ports_eNB==4) ? 10 : 11))) return(4); } else { // extended CP if ((9*numCCE) <= (frame_parms->N_RB_DL*((frame_parms->nb_antenna_ports_eNB==4) ? 9 : 10))) return(4); } } LOG_D(PHY," dci.c: get_num_pdcch_symbols nr_tti_rx %d FATAL, illegal numCCE %d (num_dci %d)\n",nr_tti_rx,numCCE,num_dci); //for (i=0;i<num_dci;i++) { // printf("dci_alloc[%d].L = %d\n",i,dci_alloc[i].L); //} //exit(-1); return(0); } uint8_t generate_dci_top(int num_dci, DCI_ALLOC_t *dci_alloc, uint32_t n_rnti, int16_t amp, NR_DL_FRAME_PARMS *frame_parms, int32_t **txdataF, uint32_t nr_tti_rx) { uint8_t *e_ptr,num_pdcch_symbols; uint32_t i, lprime; uint32_t gain_lin_QPSK,kprime,kprime_mod12,mprime,nsymb,symbol_offset,tti_offset; int16_t re_offset; uint8_t mi = get_mi(frame_parms,nr_tti_rx); static uint8_t e[DCI_BITS_MAX]; static int32_t yseq0[Msymb],yseq1[Msymb],wbar0[Msymb],wbar1[Msymb]; int32_t *y[2]; int32_t *wbar[2]; int nushiftmod3 = frame_parms->nushift%3; int Msymb2; int split_flag=0; switch (frame_parms->N_RB_DL) { case 100: Msymb2 = Msymb; break; case 75: Msymb2 = 3*Msymb/4; break; case 50: Msymb2 = Msymb>>1; break; case 25: Msymb2 = Msymb>>2; break; case 15: Msymb2 = Msymb*15/100; break; case 6: Msymb2 = Msymb*6/100; break; default: Msymb2 = Msymb>>2; break; } num_pdcch_symbols = get_num_pdcch_symbols(num_dci,dci_alloc,frame_parms,nr_tti_rx); // printf("nr_tti_rx %d in generate_dci_top num_pdcch_symbols = %d, num_dci %d\n", // nr_tti_rx,num_pdcch_symbols,num_dci); generate_pcfich(num_pdcch_symbols, amp, frame_parms, txdataF, nr_tti_rx); wbar[0] = &wbar0[0]; wbar[1] = &wbar1[0]; y[0] = &yseq0[0]; y[1] = &yseq1[0]; // reset all bits to <NIL>, here we set <NIL> elements as 2 // memset(e, 2, DCI_BITS_MAX); // here we interpret NIL as a random QPSK sequence. That makes power estimation easier. for (i=0; i<DCI_BITS_MAX; i++) e[i]=taus()&1; e_ptr = e; // generate DCIs for (i=0; i<num_dci; i++) { #ifdef DEBUG_DCI_ENCODING printf("Generating %s DCI %d/%d (nCCE %d) of length %d, aggregation %d (%x)\n", dci_alloc[i].search_space == DCI_COMMON_SPACE ? "common" : "UE", i,num_dci,dci_alloc[i].firstCCE,dci_alloc[i].dci_length,1<<dci_alloc[i].L, *(unsigned int*)dci_alloc[i].dci_pdu); dump_dci(frame_parms,&dci_alloc[i]); #endif if (dci_alloc[i].firstCCE>=0) { e_ptr = generate_dci0(dci_alloc[i].dci_pdu, e+(72*dci_alloc[i].firstCCE), dci_alloc[i].dci_length, dci_alloc[i].L, dci_alloc[i].rnti); } } // Scrambling // printf("pdcch scrambling\n"); pdcch_scrambling(frame_parms, nr_tti_rx, e, 8*get_nquad(num_pdcch_symbols, frame_parms, mi)); //72*get_nCCE(num_pdcch_symbols,frame_parms,mi)); // Now do modulation if (frame_parms->mode1_flag==1) gain_lin_QPSK = (int16_t)((amp*ONE_OVER_SQRT2_Q15)>>15); else gain_lin_QPSK = amp/2; e_ptr = e; #ifdef DEBUG_DCI_ENCODING printf(" PDCCH Modulation, Msymb %d, Msymb2 %d,gain_lin_QPSK %d\n",Msymb,Msymb2,gain_lin_QPSK); #endif if (frame_parms->mode1_flag) { //SISO for (i=0; i<Msymb2; i++) { //((int16_t*)(&(y[0][i])))[0] = (*e_ptr == 1) ? -gain_lin_QPSK : gain_lin_QPSK; //((int16_t*)(&(y[1][i])))[0] = (*e_ptr == 1) ? -gain_lin_QPSK : gain_lin_QPSK; ((int16_t*)(&(y[0][i])))[0] = (*e_ptr == 2) ? 0 : (*e_ptr == 1) ? -gain_lin_QPSK : gain_lin_QPSK; ((int16_t*)(&(y[1][i])))[0] = (*e_ptr == 2) ? 0 : (*e_ptr == 1) ? -gain_lin_QPSK : gain_lin_QPSK; e_ptr++; //((int16_t*)(&(y[0][i])))[1] = (*e_ptr == 1) ? -gain_lin_QPSK : gain_lin_QPSK; //((int16_t*)(&(y[1][i])))[1] = (*e_ptr == 1) ? -gain_lin_QPSK : gain_lin_QPSK; ((int16_t*)(&(y[0][i])))[1] = (*e_ptr == 2) ? 0 : (*e_ptr == 1) ? -gain_lin_QPSK : gain_lin_QPSK; ((int16_t*)(&(y[1][i])))[1] = (*e_ptr == 2) ? 0 : (*e_ptr == 1) ? -gain_lin_QPSK : gain_lin_QPSK; e_ptr++; } } else { //ALAMOUTI for (i=0; i<Msymb2; i+=2) { #ifdef DEBUG_DCI_ENCODING printf(" PDCCH Modulation (TX diversity): REG %d\n",i>>2); #endif // first antenna position n -> x0 ((int16_t*)&y[0][i])[0] = (*e_ptr==2) ? 0 : (*e_ptr == 1) ? -gain_lin_QPSK : gain_lin_QPSK; e_ptr++; ((int16_t*)&y[0][i])[1] = (*e_ptr==2) ? 0 : (*e_ptr == 1) ? -gain_lin_QPSK : gain_lin_QPSK; e_ptr++; // second antenna position n -> -x1* ((int16_t*)&y[1][i])[0] = (*e_ptr==2) ? 0 : (*e_ptr == 1) ? gain_lin_QPSK : -gain_lin_QPSK; e_ptr++; ((int16_t*)&y[1][i])[1] = (*e_ptr==2) ? 0 : (*e_ptr == 1) ? -gain_lin_QPSK : gain_lin_QPSK; e_ptr++; // fill in the rest of the ALAMOUTI precoding ((int16_t*)&y[0][i+1])[0] = -((int16_t*)&y[1][i])[0]; ((int16_t*)&y[0][i+1])[1] = ((int16_t*)&y[1][i])[1]; ((int16_t*)&y[1][i+1])[0] = ((int16_t*)&y[0][i])[0]; ((int16_t*)&y[1][i+1])[1] = -((int16_t*)&y[0][i])[1]; } } #ifdef DEBUG_DCI_ENCODING printf(" PDCCH Interleaving\n"); #endif // printf("y %p (%p,%p), wbar %p (%p,%p)\n",y,y[0],y[1],wbar,wbar[0],wbar[1]); // This is the interleaving procedure defined in 36-211, first part of Section 6.8.5 pdcch_interleaving(frame_parms,&y[0],&wbar[0],num_pdcch_symbols,mi); mprime=0; nsymb = (frame_parms->Ncp==0) ? 14:12; re_offset = frame_parms->first_carrier_offset; // This is the REG allocation algorithm from 36-211, second part of Section 6.8.5 // printf("DCI (SF %d) : txdataF %p (0 %p)\n",subframe,&txdataF[0][512*14*subframe],&txdataF[0][0]); for (kprime=0; kprime<frame_parms->N_RB_DL*12; kprime++) { for (lprime=0; lprime<num_pdcch_symbols; lprime++) { symbol_offset = (uint32_t)frame_parms->ofdm_symbol_size*(lprime+(nr_tti_rx*nsymb)); tti_offset = symbol_offset + re_offset; (re_offset==(frame_parms->ofdm_symbol_size-2)) ? (split_flag=1) : (split_flag=0); // printf("kprime %d, lprime %d => REG %d (symbol %d)\n",kprime,lprime,(lprime==0)?(kprime/6) : (kprime>>2),symbol_offset); // if REG is allocated to PHICH, skip it if (check_phich_reg(frame_parms,kprime,lprime,mi) == 1) { #ifdef DEBUG_DCI_ENCODING printf("generate_dci: skipping REG %d (kprime %d, lprime %d)\n",(lprime==0)?(kprime/6) : (kprime>>2),kprime,lprime); #endif } else { // Copy REG to TX buffer if ((lprime == 0)|| ((lprime==1)&&(frame_parms->nb_antenna_ports_eNB == 4))) { // first symbol, or second symbol+4 TX antennas skip pilots kprime_mod12 = kprime%12; if ((kprime_mod12 == 0) || (kprime_mod12 == 6)) { // kprime represents REG for (i=0; i<6; i++) { if ((i!=(nushiftmod3))&&(i!=(nushiftmod3+3))) { txdataF[0][tti_offset+i] = wbar[0][mprime]; if (frame_parms->nb_antenna_ports_eNB > 1) txdataF[1][tti_offset+i] = wbar[1][mprime]; #ifdef DEBUG_DCI_ENCODING printf(" PDCCH mapping mprime %d => %d (symbol %d re %d) -> (%d,%d)\n",mprime,tti_offset,symbol_offset,re_offset+i,*(short*)&wbar[0][mprime],*(1+(short*)&wbar[0][mprime])); #endif mprime++; } } } } else { // no pilots in this symbol kprime_mod12 = kprime%12; if ((kprime_mod12 == 0) || (kprime_mod12 == 4) || (kprime_mod12 == 8)) { // kprime represents REG if (split_flag==0) { for (i=0; i<4; i++) { txdataF[0][tti_offset+i] = wbar[0][mprime]; if (frame_parms->nb_antenna_ports_eNB > 1) txdataF[1][tti_offset+i] = wbar[1][mprime]; #ifdef DEBUG_DCI_ENCODING LOG_I(PHY," PDCCH mapping mprime %d => %d (symbol %d re %d) -> (%d,%d)\n",mprime,tti_offset,symbol_offset,re_offset+i,*(short*)&wbar[0][mprime],*(1+(short*)&wbar[0][mprime])); #endif mprime++; } } else { txdataF[0][tti_offset+0] = wbar[0][mprime]; if (frame_parms->nb_antenna_ports_eNB > 1) txdataF[1][tti_offset+0] = wbar[1][mprime]; #ifdef DEBUG_DCI_ENCODING printf(" PDCCH mapping mprime %d => %d (symbol %d re %d) -> (%d,%d)\n",mprime,tti_offset,symbol_offset,re_offset,*(short*)&wbar[0][mprime],*(1+(short*)&wbar[0][mprime])); #endif mprime++; txdataF[0][tti_offset+1] = wbar[0][mprime]; if (frame_parms->nb_antenna_ports_eNB > 1) txdataF[1][tti_offset+1] = wbar[1][mprime]; #ifdef DEBUG_DCI_ENCODING printf("PDCCH mapping mprime %d => %d (symbol %d re %d) -> (%d,%d)\n",mprime,tti_offset,symbol_offset,re_offset+1,*(short*)&wbar[0][mprime],*(1+(short*)&wbar[0][mprime])); #endif mprime++; txdataF[0][tti_offset-frame_parms->ofdm_symbol_size+3] = wbar[0][mprime]; if (frame_parms->nb_antenna_ports_eNB > 1) txdataF[1][tti_offset-frame_parms->ofdm_symbol_size+3] = wbar[1][mprime]; #ifdef DEBUG_DCI_ENCODING printf(" PDCCH mapping mprime %d => %d (symbol %d re %d) -> (%d,%d)\n",mprime,tti_offset,symbol_offset,re_offset-frame_parms->ofdm_symbol_size+3,*(short*)&wbar[0][mprime], *(1+(short*)&wbar[0][mprime])); #endif mprime++; txdataF[0][tti_offset-frame_parms->ofdm_symbol_size+4] = wbar[0][mprime]; if (frame_parms->nb_antenna_ports_eNB > 1) txdataF[1][tti_offset-frame_parms->ofdm_symbol_size+4] = wbar[1][mprime]; #ifdef DEBUG_DCI_ENCODING printf(" PDCCH mapping mprime %d => %d (symbol %d re %d) -> (%d,%d)\n",mprime,tti_offset,symbol_offset,re_offset-frame_parms->ofdm_symbol_size+4,*(short*)&wbar[0][mprime], *(1+(short*)&wbar[0][mprime])); #endif mprime++; } } } if (mprime>=Msymb2) return(num_pdcch_symbols); } // check_phich_reg } //lprime loop re_offset++; if (re_offset == (frame_parms->ofdm_symbol_size)) re_offset = 1; } // kprime loop return(num_pdcch_symbols); } */ #ifdef PHY_ABSTRACTION uint8_t generate_dci_top_emul(PHY_VARS_eNB *phy_vars_eNB, int num_dci, DCI_ALLOC_t *dci_alloc, uint8_t subframe) { int n_dci, n_dci_dl; uint8_t ue_id; LTE_eNB_DLSCH_t *dlsch_eNB; int num_ue_spec_dci; int num_common_dci; int i; uint8_t num_pdcch_symbols = get_num_pdcch_symbols(num_dci, dci_alloc, &phy_vars_eNB->frame_parms, subframe); eNB_transport_info[phy_vars_eNB->Mod_id][phy_vars_eNB->CC_id].cntl.cfi=num_pdcch_symbols; num_ue_spec_dci = 0; num_common_dci = 0; for (i = 0; i < num_dci; i++) { /* TODO: maybe useless test, to remove? */ if (!(dci_alloc[i].firstCCE>=0)) abort(); if (dci_alloc[i].search_space == DCI_COMMON_SPACE) num_common_dci++; else num_ue_spec_dci++; } memcpy(phy_vars_eNB->dci_alloc[subframe&1],dci_alloc,sizeof(DCI_ALLOC_t)*(num_dci)); phy_vars_eNB->num_ue_spec_dci[subframe&1]=num_ue_spec_dci; phy_vars_eNB->num_common_dci[subframe&1]=num_common_dci; eNB_transport_info[phy_vars_eNB->Mod_id][phy_vars_eNB->CC_id].num_ue_spec_dci = num_ue_spec_dci; eNB_transport_info[phy_vars_eNB->Mod_id][phy_vars_eNB->CC_id].num_common_dci = num_common_dci; LOG_D(PHY,"[eNB %d][DCI][EMUL] CC id %d: num spec dci %d num comm dci %d num PMCH %d \n", phy_vars_eNB->Mod_id, phy_vars_eNB->CC_id, num_ue_spec_dci,num_common_dci, eNB_transport_info[phy_vars_eNB->Mod_id][phy_vars_eNB->CC_id].num_pmch); if (eNB_transport_info[phy_vars_eNB->Mod_id][phy_vars_eNB->CC_id].cntl.pmch_flag == 1 ) n_dci_dl = eNB_transport_info[phy_vars_eNB->Mod_id][phy_vars_eNB->CC_id].num_pmch; else n_dci_dl = 0; for (n_dci =0 ; n_dci < (eNB_transport_info[phy_vars_eNB->Mod_id][phy_vars_eNB->CC_id].num_ue_spec_dci+ eNB_transport_info[phy_vars_eNB->Mod_id][phy_vars_eNB->CC_id].num_common_dci); n_dci++) { if (dci_alloc[n_dci].format > 0) { // exclude the uplink dci if (dci_alloc[n_dci].rnti == SI_RNTI) { dlsch_eNB = PHY_vars_eNB_g[phy_vars_eNB->Mod_id][phy_vars_eNB->CC_id]->dlsch_SI; eNB_transport_info[phy_vars_eNB->Mod_id][phy_vars_eNB->CC_id].dlsch_type[n_dci_dl] = 0;//SI; eNB_transport_info[phy_vars_eNB->Mod_id][phy_vars_eNB->CC_id].harq_pid[n_dci_dl] = 0; eNB_transport_info[phy_vars_eNB->Mod_id][phy_vars_eNB->CC_id].tbs[n_dci_dl] = dlsch_eNB->harq_processes[0]->TBS>>3; LOG_D(PHY,"[DCI][EMUL]SI tbs is %d and dci index %d harq pid is %d \n",eNB_transport_info[phy_vars_eNB->Mod_id][phy_vars_eNB->CC_id].tbs[n_dci_dl],n_dci_dl, eNB_transport_info[phy_vars_eNB->Mod_id][phy_vars_eNB->CC_id].harq_pid[n_dci_dl]); } else if (dci_alloc[n_dci_dl].ra_flag == 1) { dlsch_eNB = PHY_vars_eNB_g[phy_vars_eNB->Mod_id][phy_vars_eNB->CC_id]->dlsch_ra; eNB_transport_info[phy_vars_eNB->Mod_id][phy_vars_eNB->CC_id].dlsch_type[n_dci_dl] = 1;//RA; eNB_transport_info[phy_vars_eNB->Mod_id][phy_vars_eNB->CC_id].harq_pid[n_dci_dl] = 0; eNB_transport_info[phy_vars_eNB->Mod_id][phy_vars_eNB->CC_id].tbs[n_dci_dl] = dlsch_eNB->harq_processes[0]->TBS>>3; LOG_D(PHY,"[DCI][EMUL] RA tbs is %d and dci index %d harq pid is %d \n",eNB_transport_info[phy_vars_eNB->Mod_id][phy_vars_eNB->CC_id].tbs[n_dci_dl],n_dci_dl, eNB_transport_info[phy_vars_eNB->Mod_id][phy_vars_eNB->CC_id].harq_pid[n_dci_dl]); } else { ue_id = find_ue(dci_alloc[n_dci_dl].rnti,PHY_vars_eNB_g[phy_vars_eNB->Mod_id][phy_vars_eNB->CC_id]); DevAssert( ue_id != (uint8_t)-1 ); dlsch_eNB = PHY_vars_eNB_g[phy_vars_eNB->Mod_id][phy_vars_eNB->CC_id]->dlsch[ue_id][0]; eNB_transport_info[phy_vars_eNB->Mod_id][phy_vars_eNB->CC_id].dlsch_type[n_dci_dl] = 2;//TB0; eNB_transport_info[phy_vars_eNB->Mod_id][phy_vars_eNB->CC_id].harq_pid[n_dci_dl] = dlsch_eNB->current_harq_pid; eNB_transport_info[phy_vars_eNB->Mod_id][phy_vars_eNB->CC_id].ue_id[n_dci_dl] = ue_id; eNB_transport_info[phy_vars_eNB->Mod_id][phy_vars_eNB->CC_id].tbs[n_dci_dl] = dlsch_eNB->harq_processes[dlsch_eNB->current_harq_pid]->TBS>>3; LOG_D(PHY,"[DCI][EMUL] TB1 tbs is %d and dci index %d harq pid is %d \n",eNB_transport_info[phy_vars_eNB->Mod_id][phy_vars_eNB->CC_id].tbs[n_dci_dl],n_dci_dl, eNB_transport_info[phy_vars_eNB->Mod_id][phy_vars_eNB->CC_id].harq_pid[n_dci_dl]); // check for TB1 later } } n_dci_dl++; } memcpy((void *)&eNB_transport_info[phy_vars_eNB->Mod_id][phy_vars_eNB->CC_id].dci_alloc, (void *)dci_alloc, n_dci*sizeof(DCI_ALLOC_t)); return(num_pdcch_symbols); } #endif static uint8_t dci_decoded_output[RX_NB_TH][(MAX_DCI_SIZE_BITS+64)/8]; /*uint16_t get_nCCE(uint8_t num_pdcch_symbols,NR_DL_FRAME_PARMS *frame_parms,uint8_t mi) { return(get_nquad(num_pdcch_symbols,frame_parms,mi)/9); } uint16_t get_nquad(uint8_t num_pdcch_symbols,NR_DL_FRAME_PARMS *frame_parms,uint8_t mi) { uint16_t Nreg=0; uint8_t Ngroup_PHICH = (frame_parms->phich_config_common.phich_resource*frame_parms->N_RB_DL)/48; if (((frame_parms->phich_config_common.phich_resource*frame_parms->N_RB_DL)%48) > 0) Ngroup_PHICH++; if (frame_parms->Ncp == 1) { Ngroup_PHICH<<=1; } Ngroup_PHICH*=mi; if ((num_pdcch_symbols>0) && (num_pdcch_symbols<4)) switch (frame_parms->N_RB_DL) { case 6: Nreg=12+(num_pdcch_symbols-1)*18; break; case 25: Nreg=50+(num_pdcch_symbols-1)*75; break; case 50: Nreg=100+(num_pdcch_symbols-1)*150; break; case 100: Nreg=200+(num_pdcch_symbols-1)*300; break; default: return(0); } // printf("Nreg %d (%d)\n",Nreg,Nreg - 4 - (3*Ngroup_PHICH)); return(Nreg - 4 - (3*Ngroup_PHICH)); } uint16_t get_nCCE_mac(uint8_t Mod_id,uint8_t CC_id,int num_pdcch_symbols,int nr_tti_rx) { // check for eNB only ! return(get_nCCE(num_pdcch_symbols, &PHY_vars_eNB_g[Mod_id][CC_id]->frame_parms, get_mi(&PHY_vars_eNB_g[Mod_id][CC_id]->frame_parms,nr_tti_rx))); } */ int get_nCCE_offset_l1(int *CCE_table, const unsigned char L, const int nCCE, const int common_dci, const unsigned short rnti, const unsigned char nr_tti_rx) { int search_space_free,m,nb_candidates = 0,l,i; unsigned int Yk; /* printf("CCE Allocation: "); for (i=0;i<nCCE;i++) printf("%d.",CCE_table[i]); printf("\n"); */ if (common_dci == 1) { // check CCE(0 ... L-1) nb_candidates = (L==4) ? 4 : 2; nb_candidates = min(nb_candidates,nCCE/L); // printf("Common DCI nb_candidates %d, L %d\n",nb_candidates,L); for (m = nb_candidates-1 ; m >=0 ; m--) { search_space_free = 1; for (l=0; l<L; l++) { // printf("CCE_table[%d] %d\n",(m*L)+l,CCE_table[(m*L)+l]); if (CCE_table[(m*L) + l] == 1) { search_space_free = 0; break; } } if (search_space_free == 1) { // printf("returning %d\n",m*L); for (l=0; l<L; l++) CCE_table[(m*L)+l]=1; return(m*L); } } return(-1); } else { // Find first available in ue specific search space // according to procedure in Section 9.1.1 of 36.213 (v. 8.6) // compute Yk Yk = (unsigned int)rnti; for (i=0; i<=nr_tti_rx; i++) Yk = (Yk*39827)%65537; Yk = Yk % (nCCE/L); switch (L) { case 1: case 2: nb_candidates = 6; break; case 4: case 8: nb_candidates = 2; break; default: DevParam(L, nCCE, rnti); break; } LOG_D(MAC,"rnti %x, Yk = %d, nCCE %d (nCCE/L %d),nb_cand %d\n",rnti,Yk,nCCE,nCCE/L,nb_candidates); for (m = 0 ; m < nb_candidates ; m++) { search_space_free = 1; for (l=0; l<L; l++) { int cce = (((Yk+m)%(nCCE/L))*L) + l; if (cce >= nCCE || CCE_table[cce] == 1) { search_space_free = 0; break; } } if (search_space_free == 1) { for (l=0; l<L; l++) CCE_table[(((Yk+m)%(nCCE/L))*L)+l]=1; return(((Yk+m)%(nCCE/L))*L); } } return(-1); } } #ifdef NR_PDCCH_DCI_RUN void nr_dci_decoding_procedure0(int s, int p, int coreset_time_dur, uint16_t coreset_nbr_rb, NR_UE_PDCCH **pdcch_vars, int do_common, uint8_t nr_tti_rx, NR_DCI_ALLOC_t *dci_alloc, int16_t eNB_id, uint8_t current_thread_id, NR_DL_FRAME_PARMS *frame_parms, t_nrPolar_paramsPtr *nrPolar_params, uint8_t mi, uint16_t crc_scrambled_values[TOTAL_NBR_SCRAMBLED_VALUES], uint8_t L, NR_UE_SEARCHSPACE_CSS_DCI_FORMAT_t format_css, NR_UE_SEARCHSPACE_USS_DCI_FORMAT_t format_uss, uint8_t sizeof_bits, uint8_t sizeof_bytes, uint8_t *dci_cnt, crc_scrambled_t *crc_scrambled, format_found_t *format_found, uint16_t pdcch_DMRS_scrambling_id, uint32_t *CCEmap0, uint32_t *CCEmap1, uint32_t *CCEmap2) { uint16_t crc, CCEind, nCCE[3]; uint32_t *CCEmap = NULL, CCEmap_mask = 0; uint8_t L2 = (1 << L); unsigned int Yk, nb_candidates = 0, i, m; unsigned int CCEmap_cand; double *polar_input = malloc (sizeof(double) * 108*L2); int8_t decoderState=0; // A[p], p is the current active CORESET uint16_t A[3]={39827,39829,39839}; //Table 10.1-2: Maximum number of PDCCH candidates per slot and per serving cell as a function of the subcarrier spacing value 2^mu*15 KHz, mu {0,1,2,3} uint8_t m_max_slot_pdcch_Table10_1_2 [4] = {44,36,22,20}; //Table 10.1-3: Maximum number of non-overlapped CCEs per slot and per serving cell as a function of the subcarrier spacing value 2^mu*15 KHz, mu {0,1,2,3} uint8_t cce_max_slot_pdcch_Table10_1_3 [4] = {56,56,48,32}; int coreset_nbr_cce_per_symbol=0; #ifdef NR_PDCCH_DCI_DEBUG printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_dci_decoding_procedure0)-> format_found is %d \n", *format_found); #endif //if (mode == NO_DCI) { // #ifdef NR_PDCCH_DCI_DEBUG // printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_dci_decoding_procedure0)-> skip DCI decoding: expect no DCIs at nr_tti_rx %d in current searchSpace\n", nr_tti_rx); // #endif // return; //} #ifdef NR_PDCCH_DCI_DEBUG printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_dci_decoding_procedure0)-> frequencyDomainResources=%llx, duration=%d\n", pdcch_vars[eNB_id]->coreset[p].frequencyDomainResources, pdcch_vars[eNB_id]->coreset[p].duration); #endif // nCCE = get_nCCE(pdcch_vars[eNB_id]->num_pdcch_symbols, frame_parms, mi); for (int i = 0; i < 45; i++) { // this loop counts each bit of the bit map coreset_freq_dom, and increments nbr_RB_coreset for each bit set to '1' if (((pdcch_vars[eNB_id]->coreset[p].frequencyDomainResources & 0x1FFFFFFFFFFF) >> i) & 0x1) coreset_nbr_cce_per_symbol++; } nCCE[p] = pdcch_vars[eNB_id]->coreset[p].duration*coreset_nbr_cce_per_symbol; // 1 CCE = 6 RB // p is the current CORESET we are currently monitoring (among the 3 possible CORESETs in a BWP) // the number of CCE in the current CORESET is: // the number of symbols in the CORESET (pdcch_vars[eNB_id]->coreset[p].duration) // multiplied by the number of bits set to '1' in the frequencyDomainResources bitmap // (1 bit set to '1' corresponds to 6 RB and 1 CCE = 6 RB) #ifdef NR_PDCCH_DCI_DEBUG printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_dci_decoding_procedure0)-> nCCE[%d]=%d\n",p,nCCE[p]); #endif /* if (nCCE > get_nCCE(3, frame_parms, 1)) { LOG_D(PHY, "skip DCI decoding: nCCE=%d > get_nCCE(3,frame_parms,1)=%d\n", nCCE, get_nCCE(3, frame_parms, 1)); return; } if (nCCE < L2) { LOG_D(PHY, "skip DCI decoding: nCCE=%d < L2=%d\n", nCCE, L2); return; } if (mode == NO_DCI) { LOG_D(PHY, "skip DCI decoding: expect no DCIs at nr_tti_rx %d\n", nr_tti_rx); return; } */ if (do_common == 1) { Yk = 0; if (pdcch_vars[eNB_id]->searchSpace[s].searchSpaceType.common_dci_formats == cformat2_0) { // for dci_format_2_0, the nb_candidates is obtained from a different variable switch (L2) { case 1: nb_candidates = pdcch_vars[eNB_id]->searchSpace[s].searchSpaceType.sfi_nrofCandidates_aggrlevel1; break; case 2: nb_candidates = pdcch_vars[eNB_id]->searchSpace[s].searchSpaceType.sfi_nrofCandidates_aggrlevel2; break; case 4: nb_candidates = pdcch_vars[eNB_id]->searchSpace[s].searchSpaceType.sfi_nrofCandidates_aggrlevel4; break; case 8: nb_candidates = pdcch_vars[eNB_id]->searchSpace[s].searchSpaceType.sfi_nrofCandidates_aggrlevel8; break; case 16: nb_candidates = pdcch_vars[eNB_id]->searchSpace[s].searchSpaceType.sfi_nrofCandidates_aggrlevel16; break; default: break; } } else if (pdcch_vars[eNB_id]->searchSpace[s].searchSpaceType.common_dci_formats == cformat2_3) { // for dci_format_2_3, the nb_candidates is obtained from a different variable nb_candidates = pdcch_vars[eNB_id]->searchSpace[s].searchSpaceType.srs_nrofCandidates; } else { nb_candidates = (L2 == 4) ? 4 : ((L2 == 8)? 2 : 1); // according to Table 10.1-1 (38.213 section 10.1) #ifdef NR_PDCCH_DCI_DEBUG printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_dci_decoding_procedure0)-> we are in common searchSpace and nb_candidates=%d for L2=%d\n",nb_candidates,L2); #endif } } else { switch (L2) { case 1: nb_candidates = pdcch_vars[eNB_id]->searchSpace[s].nrofCandidates_aggrlevel1; break; case 2: nb_candidates = pdcch_vars[eNB_id]->searchSpace[s].nrofCandidates_aggrlevel2; break; case 4: nb_candidates = pdcch_vars[eNB_id]->searchSpace[s].nrofCandidates_aggrlevel4; break; case 8: nb_candidates = pdcch_vars[eNB_id]->searchSpace[s].nrofCandidates_aggrlevel8; break; case 16: nb_candidates = pdcch_vars[eNB_id]->searchSpace[s].nrofCandidates_aggrlevel16; break; default: break; } // Find first available in ue specific search space // according to procedure in Section 10.1 of 38.213 // compute Yk Yk = (unsigned int) pdcch_vars[eNB_id]->crnti; for (i = 0; i <= nr_tti_rx; i++) Yk = (Yk * A[p%3]) % 65537; } #ifdef NR_PDCCH_DCI_DEBUG printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_dci_decoding_procedure0)-> L2(%d) | nCCE[%d](%d) | Yk(%d) | nb_candidates(%d)\n",L2,p,nCCE[p],Yk,nb_candidates); #endif /* for (CCEind=0; CCEind<nCCE2; CCEind+=(1<<L)) {*/ // if (nb_candidates * L2 > nCCE[p]) // nb_candidates = nCCE[p] / L2; // In the next code line there is maybe a bug. The spec is not comparing Table 10.1-2 with nb_candidates, but with total number of candidates for all s and all p int m_p_s_L_max = (m_max_slot_pdcch_Table10_1_2[1]<=nb_candidates ? m_max_slot_pdcch_Table10_1_2[1] : nb_candidates); if (L==4) m_p_s_L_max=1; // Table 10.1-2 is not defined for L=4 #ifdef NR_PDCCH_DCI_DEBUG printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_dci_decoding_procedure0)-> m_max_slot_pdcch_Table10_1_2(%d)=%d\n",L,m_max_slot_pdcch_Table10_1_2[L]); #endif for (m = 0; m < nb_candidates; m++) { int n_ci = 0; if (nCCE[p] < L2) return; int debug1 = nCCE[p] / L2; int debug2 = L2*m_p_s_L_max; #ifdef NR_PDCCH_DCI_DEBUG printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_dci_decoding_procedure0)-> debug1(%d)=nCCE[p]/L2 | nCCE[%d](%d) | L2(%d)\n",debug1,p,nCCE[p],L2); printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_dci_decoding_procedure0)-> debug2(%d)=L2*m_p_s_L_max | L2(%d) | m_p_s_L_max(%d)\n",debug2,L2,m_p_s_L_max); #endif CCEind = (((Yk + (uint16_t)(floor((m*nCCE[p])/(L2*m_p_s_L_max))) + n_ci) % (uint16_t)(floor(nCCE[p] / L2))) * L2); #ifdef NR_PDCCH_DCI_DEBUG printf ("\t\t<-NR_PDCCH_DCI_DEBUG (nr_dci_decoding_procedure0)-> CCEind(%d) = (((Yk(%d) + ((m(%d)*nCCE[p](%d))/(L2(%d)*m_p_s_L_max(%d)))) % (nCCE[p] / L2)) * L2)\n", CCEind,Yk,m,nCCE[p],L2,m_p_s_L_max); printf ("\t\t<-NR_PDCCH_DCI_DEBUG (nr_dci_decoding_procedure0)-> n_candidate(m)=%d | CCEind=%d |",m,CCEind); #endif if (CCEind < 32) CCEmap = CCEmap0; else if (CCEind < 64) CCEmap = CCEmap1; else if (CCEind < 96) CCEmap = CCEmap2; else { LOG_E(PHY, "Illegal CCEind %d (Yk %d, m %d, nCCE %d, L2 %d\n",CCEind, Yk, m, nCCE, L2); //mac_xface->macphy_exit("Illegal CCEind\n"); return; // not reached } switch (L2) { case 1: CCEmap_mask = (1 << (CCEind & 0x1f)); break; case 2: CCEmap_mask = (3 << (CCEind & 0x1f)); break; case 4: CCEmap_mask = (0xf << (CCEind & 0x1f)); break; case 8: CCEmap_mask = (0xff << (CCEind & 0x1f)); break; case 16: CCEmap_mask = (0xfff << (CCEind & 0x1f)); break; default: LOG_E(PHY, "Illegal L2 value %d\n", L2); //mac_xface->macphy_exit("Illegal L2\n"); return; // not reached } CCEmap_cand = (*CCEmap) & CCEmap_mask; // CCE is not allocated yet #ifdef NR_PDCCH_DCI_DEBUG printf ("\t\t<-NR_PDCCH_DCI_DEBUG (nr_dci_decoding_procedure0)-> CCEmap_cand=%d \n",CCEmap_cand); #endif if (CCEmap_cand == 0) { #ifdef DEBUG_DCI_DECODING if (do_common == 1) LOG_I(PHY,"[DCI search nPdcch %d - common] Attempting candidate %d Aggregation Level %d DCI length %d at CCE %d/%d (CCEmap %x,CCEmap_cand %x)\n", pdcch_vars[eNB_id]->num_pdcch_symbols,m,L2,sizeof_bits,CCEind,nCCE,*CCEmap,CCEmap_mask); else LOG_I(PHY,"[DCI search nPdcch %d - ue spec] Attempting candidate %d Aggregation Level %d DCI length %d at CCE %d/%d (CCEmap %x,CCEmap_cand %x) format %d\n", pdcch_vars[eNB_id]->num_pdcch_symbols,m,L2,sizeof_bits,CCEind,nCCE,*CCEmap,CCEmap_mask,format_c); #endif #ifndef NR_PDCCH_DCI_DEBUG printf ("\t\t<-NR_PDCCH_DCI_DEBUG (nr_dci_decoding_procedure0)-> ... we enter function dci_decoding(sizeof_bits=%d L=%d) -----\n",sizeof_bits,L); printf ("\t\t<-NR_PDCCH_DCI_DEBUG (nr_dci_decoding_procedure0)-> ... we have to replace this part of the code by polar decoding\n"); #endif // for (int m=0; m < (nCCE[p]*6*9*2); m++) #ifdef NR_PDCCH_DCI_DEBUG printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_dci_decoding_procedure0: polar decoding)-> polar intput (with coreset_time_dur=%d, coreset_nbr_rb=%d, p=%d, CCEind=%d): \n", coreset_time_dur,coreset_nbr_rb,p,CCEind); #endif int reg_p,reg_e; for (int m=0; m < (L2*6); m++){ reg_p = (((int)floor(m/coreset_time_dur))+((m%coreset_time_dur)*(L2*6/coreset_time_dur)))*9*2; reg_e = m*9*2; for (int i=0; i<9*2; i++){ //polar_input[reg_p+i] = (pdcch_vars[eNB_id]->e_rx[((CCEind*9*6*2) + reg_e + i)]>0) ? (1.0):(-1.0); polar_input[reg_e+i] = (pdcch_vars[eNB_id]->e_rx[((CCEind*9*6*2) + reg_e + i)]>0) ? (1/sqrt(2)):((-1)/sqrt(2)); //printf("\t m=%d \tpolar_input[%d]=%lf <-> e_rx[%d]=%d\n",m,reg_e+i,polar_input[reg_e+i], // ((CCEind*9*6*2) + reg_e + i),pdcch_vars[eNB_id]->e_rx[((CCEind*9*6*2) + reg_e + i)]); //printf("\t m=%d \tpolar_input[%d]=%lf <-> e_rx[%d]=%d\n",m,reg_p+i,polar_input[reg_p+i], // ((CCEind*9*6*2) + reg_e + i),pdcch_vars[eNB_id]->e_rx[((CCEind*9*6*2) + reg_e + i)]); } } #ifndef NR_PDCCH_DCI_DEBUG printf("\n"); int j=0; uint32_t polar_hex[27] = {0}; for (int i=0; i<L2*9*6*2; i++){ if ((i%32 == 0) && (i!=0)) j++; //polar_hex[j] = (polar_hex[j]<<1) + ((polar_input[i]==-1)? 1:0); polar_hex[j] = polar_hex[j] + (((polar_input[i]==((-1)/sqrt(2)))?1:0)<<(i%32)); } for (j=0;j<27;j++) printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_dci_decoding_procedure0: polar decoding input)-> polar_hex[%d]=%x\n",j,polar_hex[j]); #endif uint32_t dci_estimation[4]={0}; uint16_t rnti=3; #ifdef PDCCH_TEST_POLAR_TEMP_FIX t_nrPolar_paramsPtr nrPolar_params = NULL; nr_polar_init(&nrPolar_params, 1, 41, 8); t_nrPolar_paramsPtr currentPtrDCI=nr_polar_params(nrPolar_params, 1, 41, 8); decoderState = polar_decoder_dci(polar_input, dci_estimation, currentPtrDCI,//nrPolar_params, 8,//NR_POLAR_DECODER_LISTSIZE, 0,//NR_POLAR_DECODER_PATH_METRIC_APPROXIMATION, rnti); //rnti printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_dci_decoding_procedure0: \t\tpolar decoding)-> decoderState %d\n", decoderState); #endif //dci_estimation[0] = 0x01189400; printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_dci_decoding_procedure0: \t\tdci_estimation: [0]->0x%08x \t [1]->0x%08x \t [2]->0x%08x \t [3]->0x%08x\n", dci_estimation[0], dci_estimation[1], dci_estimation[2], dci_estimation[3]); crc = rnti; //crc = (crc16(&dci_decoded_output[current_thread_id][0], sizeof_bits) >> 16) ^ extract_crc(&dci_decoded_output[current_thread_id][0], sizeof_bits); #ifndef NR_PDCCH_DCI_DEBUG printf ("\t\t<-NR_PDCCH_DCI_DEBUG (nr_dci_decoding_procedure0)-> ... we end function dci_decoding() with crc=%x\n",crc); printf ("\t\t<-NR_PDCCH_DCI_DEBUG (nr_dci_decoding_procedure0)-> ... we have to replace this part of the code by polar decoding\n"); #endif #ifdef DEBUG_DCI_DECODING printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_dci_decoding_procedure0: crc =>%d\n",crc); #endif //uint16_t tc_rnti, uint16_t int_rnti, uint16_t sfi_rnti, uint16_t tpc_pusch_rnti, uint16_t tpc_pucch_rnti, uint16_t tpc_srs__rnti #ifdef NR_PDCCH_DCI_DEBUG printf ("\t\t<-NR_PDCCH_DCI_DEBUG (nr_dci_decoding_procedure0)-> format_found=%d\n",*format_found); printf ("\t\t<-NR_PDCCH_DCI_DEBUG (nr_dci_decoding_procedure0)-> crc_scrambled=%d\n",*crc_scrambled); #endif if (crc == crc_scrambled_values[_C_RNTI_]) { *crc_scrambled =_c_rnti; *format_found=1; } if (crc == crc_scrambled_values[_CS_RNTI_]) { *crc_scrambled =_cs_rnti; *format_found=1; } if (crc == crc_scrambled_values[_NEW_RNTI_]) { *crc_scrambled =_new_rnti; *format_found=1; } if (crc == crc_scrambled_values[_TC_RNTI_]) { *crc_scrambled =_tc_rnti; *format_found=_format_1_0_found; } if (crc == crc_scrambled_values[_P_RNTI_]) { *crc_scrambled =_p_rnti; *format_found=_format_1_0_found; } if (crc == crc_scrambled_values[_SI_RNTI_]) { *crc_scrambled =_si_rnti; *format_found=_format_1_0_found; } if (crc == crc_scrambled_values[_RA_RNTI_]) { *crc_scrambled =_ra_rnti; *format_found=_format_1_0_found; printf(""); } if (crc == crc_scrambled_values[_SP_CSI_RNTI_]) { *crc_scrambled =_sp_csi_rnti; *format_found=_format_0_1_found; } if (crc == crc_scrambled_values[_SFI_RNTI_]) { *crc_scrambled =_sfi_rnti; *format_found=_format_2_0_found; } if (crc == crc_scrambled_values[_INT_RNTI_]) { *crc_scrambled =_int_rnti; *format_found=_format_2_1_found; } if (crc == crc_scrambled_values[_TPC_PUSCH_RNTI_]) { *crc_scrambled =_tpc_pusch_rnti; *format_found=_format_2_2_found; } if (crc == crc_scrambled_values[_TPC_PUCCH_RNTI_]) { *crc_scrambled =_tpc_pucch_rnti; *format_found=_format_2_2_found; } if (crc == crc_scrambled_values[_TPC_SRS_RNTI_]) { *crc_scrambled =_tpc_srs_rnti; *format_found=_format_2_3_found; } #ifdef NR_PDCCH_DCI_DEBUG printf ("\t\t<-NR_PDCCH_DCI_DEBUG (nr_dci_decoding_procedure0)-> format_found=%d\n",*format_found); printf ("\t\t<-NR_PDCCH_DCI_DEBUG (nr_dci_decoding_procedure0)-> crc_scrambled=%d\n",*crc_scrambled); #endif if (*format_found!=255) { dci_alloc[*dci_cnt].dci_length = sizeof_bits; dci_alloc[*dci_cnt].rnti = crc; dci_alloc[*dci_cnt].L = L; dci_alloc[*dci_cnt].firstCCE = CCEind; dci_alloc[*dci_cnt].dci_pdu[0] = dci_estimation[0]; dci_alloc[*dci_cnt].dci_pdu[1] = dci_estimation[1]; dci_alloc[*dci_cnt].dci_pdu[2] = dci_estimation[2]; dci_alloc[*dci_cnt].dci_pdu[3] = dci_estimation[3]; #ifdef NR_PDCCH_DCI_DEBUG printf ("\t\t<-NR_PDCCH_DCI_DEBUG (nr_dci_decoding_procedure0)-> rnti matches -> DCI FOUND !!! crc =>%x, sizeof_bits %d, sizeof_bytes %d \n", dci_alloc[*dci_cnt].rnti, dci_alloc[*dci_cnt].dci_length, sizeof_bytes); printf ("\t\t<-NR_PDCCH_DCI_DEBUG (nr_dci_decoding_procedure0)-> dci_cnt %d (format_css %d crc_scrambled %d) L %d, firstCCE %d pdu[0] %x pdu[1] %x pdu[2] %x pdu[3] %x \n", *dci_cnt, format_css,*crc_scrambled,dci_alloc[*dci_cnt].L, dci_alloc[*dci_cnt].firstCCE,dci_alloc[*dci_cnt].dci_pdu[0],dci_alloc[*dci_cnt].dci_pdu[1],dci_alloc[*dci_cnt].dci_pdu[2],dci_alloc[*dci_cnt].dci_pdu[3]); #endif if ((format_css == cformat0_0_and_1_0) || (format_uss == uformat0_0_and_1_0)){ if ((*crc_scrambled == _p_rnti) || (*crc_scrambled == _si_rnti) || (*crc_scrambled == _ra_rnti)){ dci_alloc[*dci_cnt].format = format1_0; *dci_cnt = *dci_cnt + 1; format_found=_format_1_0_found; printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_dci_decoding_procedure0)-> a format1_0=%d and dci_cnt=%d\n",format_found,*dci_cnt); } else { if (dci_estimation[0]&1 == 0){ dci_alloc[*dci_cnt].format = format0_0; *dci_cnt = *dci_cnt + 1; format_found=_format_0_0_found; printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_dci_decoding_procedure0)-> b format0_0=%d and dci_cnt=%d\n",format_found,*dci_cnt); } if (dci_estimation[0]&1 == 1){ dci_alloc[*dci_cnt].format = format1_0; *dci_cnt = *dci_cnt + 1; format_found=_format_1_0_found; printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_dci_decoding_procedure0)-> c format1_0=%d and dci_cnt=%d\n",format_found,*dci_cnt); } } } if (format_css == cformat2_0){ dci_alloc[*dci_cnt].format = format2_0; *dci_cnt = *dci_cnt + 1; } if (format_css == cformat2_1){ dci_alloc[*dci_cnt].format = format2_1; *dci_cnt = *dci_cnt + 1; } if (format_css == cformat2_2){ dci_alloc[*dci_cnt].format = format2_2; *dci_cnt = *dci_cnt + 1; } if (format_css == cformat2_3){ dci_alloc[*dci_cnt].format = format2_3; *dci_cnt = *dci_cnt + 1; } if (format_uss == uformat0_1_and_1_1){ if (dci_estimation[0]&1 == 0){ dci_alloc[*dci_cnt].format = format0_1; *dci_cnt = *dci_cnt + 1; format_found=_format_0_1_found; } if (dci_estimation[0]&1 == 1){ dci_alloc[*dci_cnt].format = format1_1; *dci_cnt = *dci_cnt + 1; format_found=_format_1_1_found; } } // store first nCCE of group for PUCCH transmission of ACK/NAK pdcch_vars[eNB_id]->nCCE[nr_tti_rx] = CCEind; /* if (crc == si_rnti) { dci_alloc[*dci_cnt].format = format_si; *dci_cnt = *dci_cnt + 1; } else if (crc == p_rnti) { dci_alloc[*dci_cnt].format = format_p; *dci_cnt = *dci_cnt + 1; } else if (crc == ra_rnti) { dci_alloc[*dci_cnt].format = format_ra; // store first nCCE of group for PUCCH transmission of ACK/NAK pdcch_vars[eNB_id]->nCCE[nr_tti_rx] = CCEind; *dci_cnt = *dci_cnt + 1; } else if (crc == pdcch_vars[eNB_id]->crnti) { if ((mode & UL_DCI) && (format_c == format0) && ((dci_decoded_output[current_thread_id][0] & 0x80) == 0)) { // check if pdu is format 0 or 1A if (*format0_found == 0) { dci_alloc[*dci_cnt].format = format0; *format0_found = 1; *dci_cnt = *dci_cnt + 1; pdcch_vars[eNB_id]->nCCE[nr_tti_rx] = CCEind; } } else if (format_c == format0) { // this is a format 1A DCI dci_alloc[*dci_cnt].format = format1A; *dci_cnt = *dci_cnt + 1; pdcch_vars[eNB_id]->nCCE[nr_tti_rx] = CCEind; } else { // store first nCCE of group for PUCCH transmission of ACK/NAK if (*format_c_found == 0) { dci_alloc[*dci_cnt].format = format_c; *dci_cnt = *dci_cnt + 1; *format_c_found = 1; pdcch_vars[eNB_id]->nCCE[nr_tti_rx] = CCEind; } } }*/ //LOG_I(PHY,"DCI decoding CRNTI [format: %d, nCCE[nr_tti_rx: %d]: %d ], AggregationLevel %d \n",format_c, nr_tti_rx, pdcch_vars[eNB_id]->nCCE[nr_tti_rx],L2); // memcpy(&dci_alloc[*dci_cnt].dci_pdu[0],dci_decoded_output,sizeof_bytes); switch (1 << L) { case 1: *CCEmap |= (1 << (CCEind & 0x1f)); break; case 2: *CCEmap |= (1 << (CCEind & 0x1f)); break; case 4: *CCEmap |= (1 << (CCEind & 0x1f)); break; case 8: *CCEmap |= (1 << (CCEind & 0x1f)); break; case 16: *CCEmap |= (1 << (CCEind & 0x1f)); break; } #ifdef DEBUG_DCI_DECODING LOG_I(PHY,"[DCI search] Found DCI %d rnti %x Aggregation %d length %d format %s in CCE %d (CCEmap %x) candidate %d / %d \n", *dci_cnt,crc,1<<L,sizeof_bits,dci_format_strings[dci_alloc[*dci_cnt-1].format],CCEind,*CCEmap,m,nb_candidates ); dump_dci(frame_parms,&dci_alloc[*dci_cnt-1]); #endif return; } // rnti match } else { // CCEmap_cand == 0 printf("\n"); } /* if ( agregationLevel != 0xFF && (format_c == format0 && m==0 && si_rnti != SI_RNTI)) { //Only valid for OAI : Save some processing time when looking for DCI format0. From the log we see the DCI only on candidate 0. return; } */ } // candidate loop #ifdef NR_PDCCH_DCI_DEBUG printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_dci_decoding_procedure0)-> end candidate loop\n"); #endif } #endif /*void dci_decoding_procedure0(NR_UE_PDCCH **pdcch_vars, int do_common, dci_detect_mode_t mode, uint8_t nr_tti_rx, DCI_ALLOC_t *dci_alloc, int16_t eNB_id, uint8_t current_thread_id, NR_DL_FRAME_PARMS *frame_parms, uint8_t mi, uint16_t si_rnti, uint16_t ra_rnti, uint16_t p_rnti, uint8_t L, uint8_t format_si, uint8_t format_p, uint8_t format_ra, uint8_t format_c, uint8_t sizeof_bits, uint8_t sizeof_bytes, uint8_t *dci_cnt, uint8_t *format0_found, uint8_t *format_c_found, uint32_t *CCEmap0, uint32_t *CCEmap1, uint32_t *CCEmap2) { uint16_t crc,CCEind,nCCE; uint32_t *CCEmap=NULL,CCEmap_mask=0; int L2=(1<<L); unsigned int Yk,nb_candidates = 0,i,m; unsigned int CCEmap_cand; #ifdef NR_PDCCH_DCI_DEBUG printf("\t\t<-NR_PDCCH_DCI_DEBUG (dci_decoding_procedure0)-> \n"); #endif nCCE = get_nCCE(pdcch_vars[eNB_id]->num_pdcch_symbols,frame_parms,mi); if (nCCE > get_nCCE(3,frame_parms,1)) { LOG_D(PHY,"skip DCI decoding: nCCE=%d > get_nCCE(3,frame_parms,1)=%d\n", nCCE, get_nCCE(3,frame_parms,1)); return; } if (nCCE<L2) { LOG_D(PHY,"skip DCI decoding: nCCE=%d < L2=%d\n", nCCE, L2); return; } if (mode == NO_DCI) { LOG_D(PHY, "skip DCI decoding: expect no DCIs at nr_tti_rx %d\n", nr_tti_rx); return; } if (do_common == 1) { nb_candidates = (L2==4) ? 4 : 2; Yk=0; } else { // Find first available in ue specific search space // according to procedure in Section 9.1.1 of 36.213 (v. 8.6) // compute Yk Yk = (unsigned int)pdcch_vars[eNB_id]->crnti; for (i=0; i<=nr_tti_rx; i++) Yk = (Yk*39827)%65537; Yk = Yk % (nCCE/L2); switch (L2) { case 1: case 2: nb_candidates = 6; break; case 4: case 8: nb_candidates = 2; break; default: DevParam(L2, do_common, eNB_id); break; } } // for (CCEind=0; // CCEind<nCCE2; // CCEind+=(1<<L)) { if (nb_candidates*L2 > nCCE) nb_candidates = nCCE/L2; for (m=0; m<nb_candidates; m++) { CCEind = (((Yk+m)%(nCCE/L2))*L2); if (CCEind<32) CCEmap = CCEmap0; else if (CCEind<64) CCEmap = CCEmap1; else if (CCEind<96) CCEmap = CCEmap2; else { LOG_E(PHY,"Illegal CCEind %d (Yk %d, m %d, nCCE %d, L2 %d\n",CCEind,Yk,m,nCCE,L2); mac_xface->macphy_exit("Illegal CCEind\n"); return; // not reached } switch (L2) { case 1: CCEmap_mask = (1<<(CCEind&0x1f)); break; case 2: CCEmap_mask = (3<<(CCEind&0x1f)); break; case 4: CCEmap_mask = (0xf<<(CCEind&0x1f)); break; case 8: CCEmap_mask = (0xff<<(CCEind&0x1f)); break; default: LOG_E( PHY, "Illegal L2 value %d\n", L2 ); mac_xface->macphy_exit( "Illegal L2\n" ); return; // not reached } CCEmap_cand = (*CCEmap)&CCEmap_mask; // CCE is not allocated yet if (CCEmap_cand == 0) { #ifdef DEBUG_DCI_DECODING if (do_common == 1) LOG_I(PHY,"[DCI search nPdcch %d - common] Attempting candidate %d Aggregation Level %d DCI length %d at CCE %d/%d (CCEmap %x,CCEmap_cand %x)\n", pdcch_vars[eNB_id]->num_pdcch_symbols,m,L2,sizeof_bits,CCEind,nCCE,*CCEmap,CCEmap_mask); else LOG_I(PHY,"[DCI search nPdcch %d - ue spec] Attempting candidate %d Aggregation Level %d DCI length %d at CCE %d/%d (CCEmap %x,CCEmap_cand %x) format %d\n", pdcch_vars[eNB_id]->num_pdcch_symbols,m,L2,sizeof_bits,CCEind,nCCE,*CCEmap,CCEmap_mask,format_c); #endif dci_decoding(sizeof_bits, L, &pdcch_vars[eNB_id]->e_rx[CCEind*72], &dci_decoded_output[current_thread_id][0]); // for (i=0;i<3+(sizeof_bits>>3);i++) // printf("dci_decoded_output[%d] => %x\n",i,dci_decoded_output[i]); crc = (crc16(&dci_decoded_output[current_thread_id][0],sizeof_bits)>>16) ^ extract_crc(&dci_decoded_output[current_thread_id][0],sizeof_bits); #ifdef DEBUG_DCI_DECODING printf("crc =>%x\n",crc); #endif if (((L>1) && ((crc == si_rnti)|| (crc == p_rnti)|| (crc == ra_rnti)))|| (crc == pdcch_vars[eNB_id]->crnti)) { dci_alloc[*dci_cnt].dci_length = sizeof_bits; dci_alloc[*dci_cnt].rnti = crc; dci_alloc[*dci_cnt].L = L; dci_alloc[*dci_cnt].firstCCE = CCEind; //printf("DCI FOUND !!! crc =>%x, sizeof_bits %d, sizeof_bytes %d \n",crc, sizeof_bits, sizeof_bytes); if (sizeof_bytes<=4) { dci_alloc[*dci_cnt].dci_pdu[3] = dci_decoded_output[current_thread_id][0]; dci_alloc[*dci_cnt].dci_pdu[2] = dci_decoded_output[current_thread_id][1]; dci_alloc[*dci_cnt].dci_pdu[1] = dci_decoded_output[current_thread_id][2]; dci_alloc[*dci_cnt].dci_pdu[0] = dci_decoded_output[current_thread_id][3]; #ifdef DEBUG_DCI_DECODING printf("DCI => %x,%x,%x,%x\n",dci_decoded_output[current_thread_id][0], dci_decoded_output[current_thread_id][1], dci_decoded_output[current_thread_id][2], dci_decoded_output[current_thread_id][3]); #endif } else { dci_alloc[*dci_cnt].dci_pdu[7] = dci_decoded_output[current_thread_id][0]; dci_alloc[*dci_cnt].dci_pdu[6] = dci_decoded_output[current_thread_id][1]; dci_alloc[*dci_cnt].dci_pdu[5] = dci_decoded_output[current_thread_id][2]; dci_alloc[*dci_cnt].dci_pdu[4] = dci_decoded_output[current_thread_id][3]; dci_alloc[*dci_cnt].dci_pdu[3] = dci_decoded_output[current_thread_id][4]; dci_alloc[*dci_cnt].dci_pdu[2] = dci_decoded_output[current_thread_id][5]; dci_alloc[*dci_cnt].dci_pdu[1] = dci_decoded_output[current_thread_id][6]; dci_alloc[*dci_cnt].dci_pdu[0] = dci_decoded_output[current_thread_id][7]; #ifdef DEBUG_DCI_DECODING printf("DCI => %x,%x,%x,%x,%x,%x,%x,%x\n", dci_decoded_output[current_thread_id][0],dci_decoded_output[current_thread_id][1],dci_decoded_output[current_thread_id][2],dci_decoded_output[current_thread_id][3], dci_decoded_output[current_thread_id][4],dci_decoded_output[current_thread_id][5],dci_decoded_output[current_thread_id][6],dci_decoded_output[current_thread_id][7]); #endif } if (crc==si_rnti) { dci_alloc[*dci_cnt].format = format_si; *dci_cnt = *dci_cnt+1; } else if (crc==p_rnti) { dci_alloc[*dci_cnt].format = format_p; *dci_cnt = *dci_cnt+1; } else if (crc==ra_rnti) { dci_alloc[*dci_cnt].format = format_ra; // store first nCCE of group for PUCCH transmission of ACK/NAK pdcch_vars[eNB_id]->nCCE[nr_tti_rx]=CCEind; *dci_cnt = *dci_cnt+1; } else if (crc==pdcch_vars[eNB_id]->crnti) { if ((mode&UL_DCI)&&(format_c == format0)&&((dci_decoded_output[current_thread_id][0]&0x80)==0)) {// check if pdu is format 0 or 1A if (*format0_found == 0) { dci_alloc[*dci_cnt].format = format0; *format0_found = 1; *dci_cnt = *dci_cnt+1; pdcch_vars[eNB_id]->nCCE[nr_tti_rx]=CCEind; } } else if (format_c == format0) { // this is a format 1A DCI dci_alloc[*dci_cnt].format = format1A; *dci_cnt = *dci_cnt+1; pdcch_vars[eNB_id]->nCCE[nr_tti_rx]=CCEind; } else { // store first nCCE of group for PUCCH transmission of ACK/NAK if (*format_c_found == 0) { dci_alloc[*dci_cnt].format = format_c; *dci_cnt = *dci_cnt+1; *format_c_found = 1; pdcch_vars[eNB_id]->nCCE[nr_tti_rx]=CCEind; } } } //LOG_I(PHY,"DCI decoding CRNTI [format: %d, nCCE[nr_tti_rx: %d]: %d ], AggregationLevel %d \n",format_c, nr_tti_rx, pdcch_vars[eNB_id]->nCCE[nr_tti_rx],L2); // memcpy(&dci_alloc[*dci_cnt].dci_pdu[0],dci_decoded_output,sizeof_bytes); switch (1<<L) { case 1: *CCEmap|=(1<<(CCEind&0x1f)); break; case 2: *CCEmap|=(1<<(CCEind&0x1f)); break; case 4: *CCEmap|=(1<<(CCEind&0x1f)); break; case 8: *CCEmap|=(1<<(CCEind&0x1f)); break; } #ifdef DEBUG_DCI_DECODING LOG_I(PHY,"[DCI search] Found DCI %d rnti %x Aggregation %d length %d format %s in CCE %d (CCEmap %x) candidate %d / %d \n", *dci_cnt,crc,1<<L,sizeof_bits,dci_format_strings[dci_alloc[*dci_cnt-1].format],CCEind,*CCEmap,m,nb_candidates ); dump_dci(frame_parms,&dci_alloc[*dci_cnt-1]); #endif return; } // rnti match } // CCEmap_cand == 0 // if ( agregationLevel != 0xFF && // (format_c == format0 && m==0 && si_rnti != SI_RNTI)) // { // //Only valid for OAI : Save some processing time when looking for DCI format0. From the log we see the DCI only on candidate 0. // return; // } } // candidate loop } uint16_t dci_CRNTI_decoding_procedure(PHY_VARS_NR_UE *ue, DCI_ALLOC_t *dci_alloc, uint8_t DCIFormat, uint8_t agregationLevel, int16_t eNB_id, uint8_t nr_tti_rx) { uint8_t dci_cnt=0,old_dci_cnt=0; uint32_t CCEmap0=0,CCEmap1=0,CCEmap2=0; NR_UE_PDCCH **pdcch_vars = ue->pdcch_vars[ue->current_thread_id[nr_tti_rx]]; NR_DL_FRAME_PARMS *frame_parms = &ue->frame_parms; uint8_t mi = get_mi(&ue->frame_parms,nr_tti_rx); uint16_t ra_rnti=99; uint8_t format0_found=0,format_c_found=0; uint8_t tmode = ue->transmission_mode[eNB_id]; uint8_t frame_type = frame_parms->frame_type; uint8_t format0_size_bits=0,format0_size_bytes=0; uint8_t format1_size_bits=0,format1_size_bytes=0; dci_detect_mode_t mode = dci_detect_mode_select(&ue->frame_parms,nr_tti_rx); switch (frame_parms->N_RB_DL) { case 6: if (frame_type == TDD) { format0_size_bits = sizeof_DCI0_1_5MHz_TDD_1_6_t; format0_size_bytes = sizeof(DCI0_1_5MHz_TDD_1_6_t); format1_size_bits = sizeof_DCI1_1_5MHz_TDD_t; format1_size_bytes = sizeof(DCI1_1_5MHz_TDD_t); } else { format0_size_bits = sizeof_DCI0_1_5MHz_FDD_t; format0_size_bytes = sizeof(DCI0_1_5MHz_FDD_t); format1_size_bits = sizeof_DCI1_1_5MHz_FDD_t; format1_size_bytes = sizeof(DCI1_1_5MHz_FDD_t); } break; case 25: default: if (frame_type == TDD) { format0_size_bits = sizeof_DCI0_5MHz_TDD_1_6_t; format0_size_bytes = sizeof(DCI0_5MHz_TDD_1_6_t); format1_size_bits = sizeof_DCI1_5MHz_TDD_t; format1_size_bytes = sizeof(DCI1_5MHz_TDD_t); } else { format0_size_bits = sizeof_DCI0_5MHz_FDD_t; format0_size_bytes = sizeof(DCI0_5MHz_FDD_t); format1_size_bits = sizeof_DCI1_5MHz_FDD_t; format1_size_bytes = sizeof(DCI1_5MHz_FDD_t); } break; case 50: if (frame_type == TDD) { format0_size_bits = sizeof_DCI0_10MHz_TDD_1_6_t; format0_size_bytes = sizeof(DCI0_10MHz_TDD_1_6_t); format1_size_bits = sizeof_DCI1_10MHz_TDD_t; format1_size_bytes = sizeof(DCI1_10MHz_TDD_t); } else { format0_size_bits = sizeof_DCI0_10MHz_FDD_t; format0_size_bytes = sizeof(DCI0_10MHz_FDD_t); format1_size_bits = sizeof_DCI1_10MHz_FDD_t; format1_size_bytes = sizeof(DCI1_10MHz_FDD_t); } break; case 100: if (frame_type == TDD) { format0_size_bits = sizeof_DCI0_20MHz_TDD_1_6_t; format0_size_bytes = sizeof(DCI0_20MHz_TDD_1_6_t); format1_size_bits = sizeof_DCI1_20MHz_TDD_t; format1_size_bytes = sizeof(DCI1_20MHz_TDD_t); } else { format0_size_bits = sizeof_DCI0_20MHz_FDD_t; format0_size_bytes = sizeof(DCI0_20MHz_FDD_t); format1_size_bits = sizeof_DCI1_20MHz_FDD_t; format1_size_bytes = sizeof(DCI1_20MHz_FDD_t); } break; } if (ue->prach_resources[eNB_id]) ra_rnti = ue->prach_resources[eNB_id]->ra_RNTI; // Now check UE_SPEC format0/1A ue_spec search spaces at aggregation 8 dci_decoding_procedure0(pdcch_vars,0,mode, nr_tti_rx, dci_alloc, eNB_id, ue->current_thread_id[nr_tti_rx], frame_parms, mi, ((ue->decode_SIB == 1) ? SI_RNTI : 0), ra_rnti, P_RNTI, agregationLevel, format1A, format1A, format1A, format0, format0_size_bits, format0_size_bytes, &dci_cnt, &format0_found, &format_c_found, &CCEmap0, &CCEmap1, &CCEmap2); if ((CCEmap0==0xffff)|| ((format0_found==1)&&(format_c_found==1))) return(dci_cnt); if (DCIFormat == 1) { if ((tmode < 3) || (tmode == 7)) { //printf("Crnti decoding frame param agregation %d DCI %d \n",agregationLevel,DCIFormat); // Now check UE_SPEC format 1 search spaces at aggregation 1 //printf("[DCI search] Format 1/1A aggregation 1\n"); old_dci_cnt=dci_cnt; dci_decoding_procedure0(pdcch_vars,0,mode,nr_tti_rx, dci_alloc, eNB_id, ue->current_thread_id[nr_tti_rx], frame_parms, mi, ((ue->decode_SIB == 1) ? SI_RNTI : 0), ra_rnti, P_RNTI, 0, format1A, format1A, format1A, format1, format1_size_bits, format1_size_bytes, &dci_cnt, &format0_found, &format_c_found, &CCEmap0, &CCEmap1, &CCEmap2); if ((CCEmap0==0xffff) || (format_c_found==1)) return(dci_cnt); if (dci_cnt>old_dci_cnt) return(dci_cnt); //printf("Crnti 1 decoding frame param agregation %d DCI %d \n",agregationLevel,DCIFormat); } else { AssertFatal(0,"Other Transmission mode not yet coded\n"); } } else { AssertFatal(0,"DCI format %d not yet implemented \n",DCIFormat); } return(dci_cnt); } */ #ifdef NR_PDCCH_DCI_RUN uint16_t nr_dci_format_size (PHY_VARS_NR_UE *ue, uint16_t eNB_id, uint8_t nr_tti_rx, int p, crc_scrambled_t crc_scrambled, uint16_t n_RB_ULBWP, uint16_t n_RB_DLBWP, uint8_t dci_fields_sizes[NBR_NR_DCI_FIELDS][NBR_NR_FORMATS], uint8_t format){ #ifdef NR_PDCCH_DCI_DEBUG printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_dci_format_size)-> crc_scrambled=%d, n_RB_ULBWP=%d, n_RB_DLBWP=%d\n",crc_scrambled,n_RB_ULBWP,n_RB_DLBWP); #endif /* * function nr_dci_format_size calculates and returns the size in bits of a determined format * it also returns an bi-dimensional array 'dci_fields_sizes' with x rows and y columns, where: * x is the number of fields defined in TS 38.212 subclause 7.3.1 (Each field is mapped in the order in which it appears in the description in the specification) * y is the number of formats * e.g.: dci_fields_sizes[10][0] contains the size in bits of the field FREQ_DOM_RESOURCE_ASSIGNMENT_UL for format 0_0 */ // pdsch_config contains the PDSCH-Config IE is used to configure the UE specific PDSCH parameters (TS 38.331) PDSCH_Config_t pdsch_config = ue->PDSCH_Config; // pusch_config contains the PUSCH-Config IE is used to configure the UE specific PUSCH parameters (TS 38.331) PUSCH_Config_t pusch_config = ue->pusch_config; PUCCH_Config_t pucch_config_dedicated = ue->pucch_config_dedicated_nr[eNB_id]; crossCarrierSchedulingConfig_t crossCarrierSchedulingConfig = ue->crossCarrierSchedulingConfig; dmrs_UplinkConfig_t dmrs_UplinkConfig = ue->dmrs_UplinkConfig; dmrs_DownlinkConfig_t dmrs_DownlinkConfig = ue->dmrs_DownlinkConfig; csi_MeasConfig_t csi_MeasConfig = ue->csi_MeasConfig; PUSCH_ServingCellConfig_t PUSCH_ServingCellConfig= ue->PUSCH_ServingCellConfig; PDSCH_ServingCellConfig_t PDSCH_ServingCellConfig= ue->PDSCH_ServingCellConfig; NR_UE_PDCCH *pdcch_vars2 = ue->pdcch_vars[ue->current_thread_id[nr_tti_rx]][eNB_id]; // 1 CARRIER_IN // crossCarrierSchedulingConfig from higher layers, variable crossCarrierSchedulingConfig indicates if 'cross carrier scheduling' is enabled or not: // if No cross carrier scheduling: number of bits for CARRIER_IND is 0 // if Cross carrier scheduling: number of bits for CARRIER_IND is 3 // The IE CrossCarrierSchedulingConfig is used to specify the configuration when the cross-carrier scheduling is used in a cell uint8_t crossCarrierSchedulingConfig_ind = 0; if (crossCarrierSchedulingConfig.schedulingCellInfo.other.cif_InSchedulingCell !=0 ) crossCarrierSchedulingConfig_ind=1; // 2 SUL_IND_0_1, // 40 SRS_REQUEST, // 50 SUL_IND_0_0 // UL/SUL indicator (TS 38.331, supplementary uplink is indicated in higher layer parameter ServCellAdd-SUL from IE ServingCellConfig and ServingCellConfigCommon): // 0 bit for UEs not configured with SUL in the cell or UEs configured with SUL in the cell but only PUCCH carrier in the cell is configured for PUSCH transmission // 1 bit for UEs configured with SUL in the cell as defined in Table 7.3.1.1.1-1 // sul_ind indicates whether SUL is configured in cell or not uint8_t sul_ind=ue->supplementaryUplink.supplementaryUplink; // this value will be 0 or 1 depending on higher layer parameter ServCellAdd-SUL. FIXME!!! // 7 BANDWIDTH_PART_IND // number of UL BWPs configured by higher layers uint8_t n_UL_BWP_RRC=1; // initialized to 1 but it has to be initialized by higher layers FIXME!!! (n_UL_BWP_RRC > 3)?n_UL_BWP_RRC:(n_UL_BWP_RRC+1); // number of DL BWPs configured by higher layers uint8_t n_DL_BWP_RRC=1; // initialized to 1 but it has to be initialized by higher layers FIXME!!! (n_DL_BWP_RRC > 3)?n_DL_BWP_RRC:(n_DL_BWP_RRC+1); // 10 FREQ_DOM_RESOURCE_ASSIGNMENT_UL // if format0_0, only resource allocation type 1 is allowed // if format0_1, then resource allocation type 0 can be configured and N_RBG is defined in TS 38.214 subclause 6.1.2.2.1 // for PUSCH hopping with resource allocation type 1 // n_UL_hopping = 1 if the higher layer parameter frequencyHoppingOffsetLists contains two offset values // n_UL_hopping = 2 if the higher layer parameter frequencyHoppingOffsetLists contains four offset values uint8_t n_UL_hopping=pusch_config.n_frequencyHoppingOffsetLists; if (n_UL_hopping == 2) { n_UL_hopping = 1; } else if (n_UL_hopping == 4) { n_UL_hopping = 2; } else { n_UL_hopping = 0; } ul_resourceAllocation_t ul_resource_allocation_type = pusch_config.ul_resourceAllocation; uint8_t ul_res_alloc_type_0 = 0; uint8_t ul_res_alloc_type_1 = 0; if (ul_resource_allocation_type == ul_resourceAllocationType0) ul_res_alloc_type_0 = 1; if (ul_resource_allocation_type == ul_resourceAllocationType1) ul_res_alloc_type_1 = 1; if (ul_resource_allocation_type == ul_dynamicSwitch) { ul_res_alloc_type_0 = 1; ul_res_alloc_type_1 = 1; } uint8_t n_bits_freq_dom_res_assign_ul,n_ul_RGB_tmp; if (ul_res_alloc_type_0 == 1){ // implementation of Table 6.1.2.2.1-1 TC 38.214 subclause 6.1.2.2.1 // config1: PUSCH-Config IE contains rbg-Size ENUMERATED {config1 config2} ul_rgb_Size_t config = pusch_config.ul_rgbSize; uint8_t nominal_RBG_P = (config==ul_rgb_config1?2:4); if (n_RB_ULBWP > 36) nominal_RBG_P = (config==ul_rgb_config1?4:8); if (n_RB_ULBWP > 72) nominal_RBG_P = (config==ul_rgb_config1?8:16); if (n_RB_ULBWP > 144) nominal_RBG_P = 16; n_bits_freq_dom_res_assign_ul = (uint8_t)ceil((n_RB_ULBWP+(0%nominal_RBG_P))/nominal_RBG_P); //FIXME!!! what is 0??? n_ul_RGB_tmp = n_bits_freq_dom_res_assign_ul; } if (ul_res_alloc_type_1 == 1) n_bits_freq_dom_res_assign_ul = (uint8_t)(ceil(log2(n_RB_ULBWP*(n_RB_ULBWP+1)/2)))-n_UL_hopping; if ((ul_res_alloc_type_0 == 1) && (ul_res_alloc_type_1 == 1)) n_bits_freq_dom_res_assign_ul = ((n_bits_freq_dom_res_assign_ul>n_ul_RGB_tmp)?(n_bits_freq_dom_res_assign_ul+1):(n_ul_RGB_tmp+1)); // 11 FREQ_DOM_RESOURCE_ASSIGNMENT_DL // if format1_0, only resource allocation type 1 is allowed // if format1_1, then resource allocation type 0 can be configured and N_RBG is defined in TS 38.214 subclause 5.1.2.2.1 dl_resourceAllocation_t dl_resource_allocation_type = pdsch_config.dl_resourceAllocation; uint8_t dl_res_alloc_type_0 = 0; uint8_t dl_res_alloc_type_1 = 0; if (dl_resource_allocation_type == dl_resourceAllocationType0) dl_res_alloc_type_0 = 1; if (dl_resource_allocation_type == dl_resourceAllocationType1) dl_res_alloc_type_1 = 1; if (dl_resource_allocation_type == dl_dynamicSwitch) { dl_res_alloc_type_0 = 1; dl_res_alloc_type_1 = 1; } uint8_t n_bits_freq_dom_res_assign_dl,n_dl_RGB_tmp; if (dl_res_alloc_type_0 == 1){ // implementation of Table 5.1.2.2.1-1 TC 38.214 subclause 6.1.2.2.1 // config1: PDSCH-Config IE contains rbg-Size ENUMERATED {config1, config2} dl_rgb_Size_t config = pdsch_config.dl_rgbSize; uint8_t nominal_RBG_P = (config==dl_rgb_config1?2:4); if (n_RB_DLBWP > 36) nominal_RBG_P = (config==dl_rgb_config1?4:8); if (n_RB_DLBWP > 72) nominal_RBG_P = (config==dl_rgb_config1?8:16); if (n_RB_DLBWP > 144) nominal_RBG_P = 16; n_bits_freq_dom_res_assign_dl = (uint8_t)ceil((n_RB_DLBWP+(0%nominal_RBG_P))/nominal_RBG_P); //FIXME!!! what is 0??? n_dl_RGB_tmp = n_bits_freq_dom_res_assign_dl; } if (dl_res_alloc_type_1 == 1) n_bits_freq_dom_res_assign_dl = (uint8_t)(ceil(log2(n_RB_DLBWP*(n_RB_DLBWP+1)/2))); if ((dl_res_alloc_type_0 == 1) && (dl_res_alloc_type_1 == 1)) n_bits_freq_dom_res_assign_dl = ((n_bits_freq_dom_res_assign_dl>n_dl_RGB_tmp)?(n_bits_freq_dom_res_assign_dl+1):(n_dl_RGB_tmp+1)); // 12 TIME_DOM_RESOURCE_ASSIGNMENT uint8_t pusch_alloc_list = pusch_config.n_push_alloc_list; uint8_t pdsch_alloc_list = pdsch_config.n_pdsh_alloc_list; // 14 PRB_BUNDLING_SIZE_IND:0 bit if the higher layer parameter PRB_bundling is not configured or is set to 'static', or 1 bit if the higher layer parameter PRB_bundling is set to 'dynamic' according to Subclause 5.1.2.3 of [6, TS 38.214] static_bundleSize_t static_prb_BundlingType = pdsch_config.prbBundleType.staticBundling; bundleSizeSet1_t dynamic_prb_BundlingType1 = pdsch_config.prbBundleType.dynamicBundlig.bundleSizeSet1; bundleSizeSet2_t dynamic_prb_BundlingType2 = pdsch_config.prbBundleType.dynamicBundlig.bundleSizeSet2; uint8_t prb_BundlingType_size=0; if ((static_prb_BundlingType==st_n4)||(static_prb_BundlingType==st_wideband)) prb_BundlingType_size=0; if ((dynamic_prb_BundlingType1==dy_1_n4)||(dynamic_prb_BundlingType1==dy_1_wideband)||(dynamic_prb_BundlingType1==dy_1_n2_wideband)||(dynamic_prb_BundlingType1==dy_1_n4_wideband)|| (dynamic_prb_BundlingType2==dy_2_n4)||(dynamic_prb_BundlingType2==dy_2_wideband)) prb_BundlingType_size=1; // 15 RATE_MATCHING_IND FIXME!!! // according to TS 38.212: Rate matching indicator – 0, 1, or 2 bits according to higher layer parameter rateMatchPattern uint8_t rateMatching_bits = pdsch_config.n_rateMatchPatterns; // 16 ZP_CSI_RS_TRIGGER FIXME!!! // 0, 1, or 2 bits as defined in Subclause 5.1.4.2 of [6, TS 38.214]. // is the number of ZP CSI-RS resource sets in the higher layer parameter zp-CSI-RS-Resource uint8_t n_zp_bits = pdsch_config.n_zp_CSI_RS_ResourceId; // 17 FREQ_HOPPING_FLAG // freqHopping is defined by higher layer parameter frequencyHopping from IE PUSCH-Config. Values are ENUMERATED{mode1, mode2} frequencyHopping_t f_hopping = pusch_config.frequencyHopping; uint8_t freqHopping = 0; if ((f_hopping==f_hop_mode1)||(f_hopping==f_hop_mode2)) freqHopping = 1; // 28 DAI pdsch_HARQ_ACK_Codebook_t pdsch_HARQ_ACK_Codebook = pdsch_config.pdsch_HARQ_ACK_Codebook; uint8_t n_dai = 0; uint8_t n_serving_cell_dl = 1; // this is hardcoded to 1 as we need to get this value from RRC higher layers parameters. FIXME!!! if ((pdsch_HARQ_ACK_Codebook == dynamic) && (n_serving_cell_dl == 1)) n_dai = 2; if ((pdsch_HARQ_ACK_Codebook == dynamic) && (n_serving_cell_dl > 1)) n_dai = 4; // 29 FIRST_DAI uint8_t codebook_HARQ_ACK = 0; // We need to get this value to calculate number of bits of fields 1st DAI and 2nd DAI. if (pdsch_HARQ_ACK_Codebook == semiStatic) codebook_HARQ_ACK = 1; if (pdsch_HARQ_ACK_Codebook == dynamic) codebook_HARQ_ACK = 2; // 30 SECOND_DAI uint8_t n_HARQ_ACK_sub_codebooks = 0; // We need to get this value to calculate number of bits of fields 1st DAI and 2nd DAI. FIXME!!! // 35 PDSCH_TO_HARQ_FEEDBACK_TIME_IND uint8_t pdsch_harq_t_ind = (uint8_t)ceil(log2(pucch_config_dedicated.dl_DataToUL_ACK[0])); // 36 SRS_RESOURCE_IND // n_SRS is the number of configured SRS resources in the SRS resource set associated with the higher layer parameter usage of value 'codeBook' or 'nonCodeBook' // from SRS_ResourceSet_t type we should get the information of the usage parameter (with possible values beamManagement, codebook, nonCodebook, antennaSwitching) // at frame_parms->srs_nr->p_SRS_ResourceSetList[]->usage uint8_t n_SRS = ue->srs.number_srs_Resource_Set; // 37 PRECOD_NBR_LAYERS // 38 ANTENNA_PORTS txConfig_t txConfig = pusch_config.txConfig; transformPrecoder_t transformPrecoder = pusch_config.transformPrecoder; codebookSubset_t codebookSubset = pusch_config.codebookSubset; uint8_t maxRank = pusch_config.maxRank; uint8_t num_antenna_ports = 1; // this is hardcoded. We need to get the real value FIXME!!! uint8_t precond_nbr_layers_bits = 0; uint8_t antenna_ports_bits_ul = 0; // searching number of bits at tables 7.3.1.1.2-2/3/4/5 from TS 38.212 subclause 7.3.1.1.2 if (txConfig == txConfig_codebook){ if (num_antenna_ports == 4) { if ((transformPrecoder == transformPrecoder_disabled) && ((maxRank == 2)||(maxRank == 3)||(maxRank == 4))) { // Table 7.3.1.1.2-2 if (codebookSubset == codebookSubset_fullyAndPartialAndNonCoherent) precond_nbr_layers_bits=6; if (codebookSubset == codebookSubset_partialAndNonCoherent) precond_nbr_layers_bits=5; if (codebookSubset == codebookSubset_nonCoherent) precond_nbr_layers_bits=4; } if (((transformPrecoder == transformPrecoder_enabled)||(transformPrecoder == transformPrecoder_disabled)) && (maxRank == 1)) { // Table 7.3.1.1.2-3 if (codebookSubset == codebookSubset_fullyAndPartialAndNonCoherent) precond_nbr_layers_bits=5; if (codebookSubset == codebookSubset_partialAndNonCoherent) precond_nbr_layers_bits=4; if (codebookSubset == codebookSubset_nonCoherent) precond_nbr_layers_bits=2; } } if (num_antenna_ports == 2) { if ((transformPrecoder == transformPrecoder_disabled) && (maxRank == 2)) { // Table 7.3.1.1.2-4 if (codebookSubset == codebookSubset_fullyAndPartialAndNonCoherent) precond_nbr_layers_bits=4; if (codebookSubset == codebookSubset_nonCoherent) precond_nbr_layers_bits=2; } if (((transformPrecoder == transformPrecoder_enabled)||(transformPrecoder == transformPrecoder_disabled)) && (maxRank == 1)) { // Table 7.3.1.1.2-5 if (codebookSubset == codebookSubset_fullyAndPartialAndNonCoherent) precond_nbr_layers_bits=3; if (codebookSubset == codebookSubset_nonCoherent) precond_nbr_layers_bits=1; } } } if (txConfig == txConfig_nonCodebook){ } // searching number of bits at tables 7.3.1.1.2-6/7/8/9/10/11/12/13/14/15/16/17/18/19 if((dmrs_UplinkConfig.pusch_dmrs_type == pusch_dmrs_type1)){ if ((transformPrecoder == transformPrecoder_enabled) && (dmrs_UplinkConfig.pusch_maxLength == pusch_len1)) antenna_ports_bits_ul = 2; if ((transformPrecoder == transformPrecoder_enabled) && (dmrs_UplinkConfig.pusch_maxLength == pusch_len2)) antenna_ports_bits_ul = 4; if ((transformPrecoder == transformPrecoder_disabled) && (dmrs_UplinkConfig.pusch_maxLength == pusch_len1)) antenna_ports_bits_ul = 3; if ((transformPrecoder == transformPrecoder_disabled) && (dmrs_UplinkConfig.pusch_maxLength == pusch_len2)) antenna_ports_bits_ul = 4; } if((dmrs_UplinkConfig.pusch_dmrs_type == pusch_dmrs_type2)){ if ((transformPrecoder == transformPrecoder_disabled) && (dmrs_UplinkConfig.pusch_maxLength == pusch_len1)) antenna_ports_bits_ul = 4; if ((transformPrecoder == transformPrecoder_disabled) && (dmrs_UplinkConfig.pusch_maxLength == pusch_len2)) antenna_ports_bits_ul = 5; } // for format 1_1 number of bits as defined by Tables 7.3.1.2.2-1/2/3/4 uint8_t antenna_ports_bits_dl = 0; if((dmrs_DownlinkConfig.pdsch_dmrs_type == pdsch_dmrs_type1) && (dmrs_DownlinkConfig.pdsch_maxLength == pdsch_len1)) antenna_ports_bits_dl = 4; // Table 7.3.1.2.2-1 if((dmrs_DownlinkConfig.pdsch_dmrs_type == pdsch_dmrs_type1) && (dmrs_DownlinkConfig.pdsch_maxLength == pdsch_len2)) antenna_ports_bits_dl = 5; // Table 7.3.1.2.2-2 if((dmrs_DownlinkConfig.pdsch_dmrs_type == pdsch_dmrs_type2) && (dmrs_DownlinkConfig.pdsch_maxLength == pdsch_len1)) antenna_ports_bits_dl = 5; // Table 7.3.1.2.2-3 if((dmrs_DownlinkConfig.pdsch_dmrs_type == pdsch_dmrs_type2) && (dmrs_DownlinkConfig.pdsch_maxLength == pdsch_len2)) antenna_ports_bits_dl = 6; // Table 7.3.1.2.2-4 // 39 TCI uint8_t tci_bits=0; if (pdcch_vars2->coreset[p].tciPresentInDCI == tciPresentInDCI_enabled) tci_bits=3; // 42 CSI_REQUEST // reportTriggerSize is defined in the CSI-MeasConfig IE (TS 38.331). // Size of CSI request field in DCI (bits). Corresponds to L1 parameter 'ReportTriggerSize' (see 38.214, section 5.2) uint8_t reportTriggerSize = csi_MeasConfig.reportTriggerSize; // value from 0..6 // 43 CBGTI // for format 0_1 uint8_t maxCodeBlockGroupsPerTransportBlock = 0; if (PUSCH_ServingCellConfig.maxCodeBlockGroupsPerTransportBlock != 0) maxCodeBlockGroupsPerTransportBlock = (uint8_t)PUSCH_ServingCellConfig.maxCodeBlockGroupsPerTransportBlock; // for format 1_1, as defined in Subclause 5.1.7 of [6, TS38.214] uint8_t maxCodeBlockGroupsPerTransportBlock_dl = 0; if (PDSCH_ServingCellConfig.maxCodeBlockGroupsPerTransportBlock_dl != 0) maxCodeBlockGroupsPerTransportBlock_dl = pdsch_config.maxNrofCodeWordsScheduledByDCI; // FIXME!!! // 44 CBGFI uint8_t cbgfi_bit = PDSCH_ServingCellConfig.codeBlockGroupFlushIndicator; // 45 PTRS_DMRS // 0 bit if PTRS-UplinkConfig is not configured and transformPrecoder=disabled, or if transformPrecoder=enabled, or if maxRank=1 // 2 bits otherwise uint8_t ptrs_dmrs_bits=0; //FIXME!!! // 46 BETA_OFFSET_IND // at IE PUSCH-Config, beta_offset indicator – 0 if the higher layer parameter betaOffsets = semiStatic; otherwise 2 bits // uci-OnPUSCH // Selection between and configuration of dynamic and semi-static beta-offset. If the field is absent or released, the UE applies the value 'semiStatic' and the BetaOffsets uint8_t betaOffsets = 0; if (pusch_config.uci_onPusch.betaOffset_type == betaOffset_semiStatic); if (pusch_config.uci_onPusch.betaOffset_type == betaOffset_dynamic) betaOffsets = 2; // 47 DMRS_SEQ_INI uint8_t dmrs_seq_ini_bits_ul = 0; uint8_t dmrs_seq_ini_bits_dl = 0; //1 bit if both scramblingID0 and scramblingID1 are configured in DMRS-UplinkConfig if ((transformPrecoder == transformPrecoder_disabled) && (dmrs_UplinkConfig.scramblingID0 != 0) && (dmrs_UplinkConfig.scramblingID1 != 0)) dmrs_seq_ini_bits_ul = 1; //1 bit if both scramblingID0 and scramblingID1 are configured in DMRS-DownlinkConfig if ((dmrs_DownlinkConfig.scramblingID0 != 0) && (dmrs_DownlinkConfig.scramblingID0 != 0)) dmrs_seq_ini_bits_dl = 1; /* * For format 2_2 * * This format supports power control commands for semi-persistent scheduling. * As we can already support power control commands dynamically with formats 0_0/0_1 (TPC PUSCH) and 1_0/1_1 (TPC PUCCH) * * This format will be implemented in the future FIXME!!! * */ // 5 BLOCK_NUMBER: The parameter tpc-PUSCH or tpc-PUCCH provided by higher layers determines the index to the block number for an UL of a cell // The following fields are defined for each block: Closed loop indicator and TPC command // 6 CLOSE_LOOP_IND // 41 TPC_CMD uint8_t tpc_cmd_bit_2_2 = 2; /* * For format 2_3 * * This format is used for power control of uplink sounding reference signals for devices which have not coupled SRS power control to the PUSCH power control * either because independent control is desirable or because the device is configured without PUCCH and PUSCH * * This format will be implemented in the future FIXME!!! * */ // 40 SRS_REQUEST // 41 TPC_CMD uint8_t tpc_cmd_bit_2_3 = 0; uint8_t dci_field_size_table [NBR_NR_DCI_FIELDS][NBR_NR_FORMATS] = { // This table contains the number of bits for each field (row) contained in each dci format (column). // The values of the variables indicate field sizes in number of bits //Format0_0 Format0_1 Format1_0 Format1_1 Formats2_0/1/2/3 {1, 1, (((crc_scrambled == _p_rnti) || (crc_scrambled == _si_rnti) || (crc_scrambled == _ra_rnti)) ? 0:1), 1, 0,0,0,0}, // 0 IDENTIFIER_DCI_FORMATS: {0, ((crossCarrierSchedulingConfig_ind == 0) ? 0:3), 0, ((crossCarrierSchedulingConfig_ind == 0) ? 0:3), 0,0,0,0}, // 1 CARRIER_IND: 0 or 3 bits, as defined in Subclause x.x of [5, TS38.213] {0, (sul_ind == 0)?0:1, 0, 0, 0,0,0,0}, // 2 SUL_IND_0_1: {0, 0, 0, 0, 1,0,0,0}, // 3 SLOT_FORMAT_IND: size of DCI format 2_0 is configurable by higher layers up to 128 bits, according to Subclause 11.1.1 of [5, TS 38.213] {0, 0, 0, 0, 0,1,0,0}, // 4 PRE_EMPTION_IND: size of DCI format 2_1 is configurable by higher layers up to 126 bits, according to Subclause 11.2 of [5, TS 38.213]. Each pre-emption indication is 14 bits {0, 0, 0, 0, 0,0,0,0}, // 5 BLOCK_NUMBER: starting position of a block is determined by the parameter startingBitOfFormat2_3 {0, 0, 0, 0, 0,0,1,0}, // 6 CLOSE_LOOP_IND {0, (uint8_t)ceil(log2(n_UL_BWP_RRC)), 0, (uint8_t)ceil(log2(n_DL_BWP_RRC)), 0,0,0,0}, // 7 BANDWIDTH_PART_IND: {0, 0, ((crc_scrambled == _p_rnti) ? 2:0), 0, 0,0,0,0}, // 8 SHORT_MESSAGE_IND 2 bits if crc scrambled with P-RNTI {0, 0, ((crc_scrambled == _p_rnti) ? 8:0), 0, 0,0,0,0}, // 9 SHORT_MESSAGES 8 bit8 if crc scrambled with P-RNTI {(uint8_t)(ceil(log2(n_RB_ULBWP*(n_RB_ULBWP+1)/2)))-n_UL_hopping, n_bits_freq_dom_res_assign_ul, 0, 0, 0,0,0,0}, // 10 FREQ_DOM_RESOURCE_ASSIGNMENT_UL: PUSCH hopping with resource allocation type 1 not considered // (NOTE 1) If DCI format 0_0 is monitored in common search space // and if the number of information bits in the DCI format 0_0 prior to padding // is larger than the payload size of the DCI format 1_0 monitored in common search space // the bitwidth of the frequency domain resource allocation field in the DCI format 0_0 // is reduced such that the size of DCI format 0_0 equals to the size of the DCI format 1_0 {0, 0, (uint8_t)ceil(log2(n_RB_DLBWP*(n_RB_DLBWP+1)/2)), n_bits_freq_dom_res_assign_dl, 0,0,0,0}, // 11 FREQ_DOM_RESOURCE_ASSIGNMENT_DL: {4, (uint8_t)log2(pusch_alloc_list), 4, (uint8_t)log2(pdsch_alloc_list), 0,0,0,0}, // 12 TIME_DOM_RESOURCE_ASSIGNMENT: 0, 1, 2, 3, or 4 bits as defined in Subclause 6.1.2.1 of [6, TS 38.214]. The bitwidth for this field is determined as log2(I) bits, // where I the number of entries in the higher layer parameter pusch-AllocationList {0, 0, 1, (((dl_res_alloc_type_0==1)&&(dl_res_alloc_type_1==0))?0:1), 0,0,0,0}, // 13 VRB_TO_PRB_MAPPING: 0 bit if only resource allocation type 0 {0, 0, 0, prb_BundlingType_size, 0,0,0,0}, // 14 PRB_BUNDLING_SIZE_IND:0 bit if the higher layer parameter PRB_bundling is not configured or is set to 'static', or 1 bit if the higher layer parameter PRB_bundling is set to 'dynamic' according to Subclause 5.1.2.3 of [6, TS 38.214] {0, 0, 0, rateMatching_bits, 0,0,0,0}, // 15 RATE_MATCHING_IND: 0, 1, or 2 bits according to higher layer parameter rate-match-PDSCH-resource-set {0, 0, 0, n_zp_bits, 0,0,0,0}, // 16 ZP_CSI_RS_TRIGGER: {1, (((ul_res_alloc_type_0==1)&&(ul_res_alloc_type_1==0))||(freqHopping == 0))?0:1, 0, 0, 0,0,0,0}, // 17 FREQ_HOPPING_FLAG: 0 bit if only resource allocation type 0 {0, 0, 0, 5, 0,0,0,0}, // 18 TB1_MCS: {0, 0, 0, 1, 0,0,0,0}, // 19 TB1_NDI: {0, 0, 0, 2, 0,0,0,0}, // 20 TB1_RV: {0, 0, 0, 5, 0,0,0,0}, // 21 TB2_MCS: {0, 0, 0, 1, 0,0,0,0}, // 22 TB2_NDI: {0, 0, 0, 2, 0,0,0,0}, // 23 TB2_RV: {5, 5, 5, 0, 0,0,0,0}, // 24 MCS: {1, 1, (crc_scrambled == _c_rnti)?1:0,0, 0,0,0,0}, // 25 NDI: {2, 2, (((crc_scrambled == _c_rnti) || (crc_scrambled == _si_rnti)) ? 2:0), 0, 0,0,0,0}, // 26 RV: {4, 4, (crc_scrambled == _c_rnti)?4:0,4, 0,0,0,0}, // 27 HARQ_PROCESS_NUMBER: {0, 0, (crc_scrambled == _c_rnti)?2:0,n_dai, 0,0,0,0}, // 28 DAI: For format1_1: 4 if more than one serving cell are configured in the DL and the higher layer parameter HARQ-ACK-codebook=dynamic, where the 2 MSB bits are the counter DAI and the 2 LSB bits are the total DAI // 2 if one serving cell is configured in the DL and the higher layer parameter HARQ-ACK-codebook=dynamic, where the 2 bits are the counter DAI // 0 otherwise {0, codebook_HARQ_ACK, 0, 0, 0,0,0,0}, // 29 FIRST_DAI: (1 or 2 bits) 1 bit for semi-static HARQ-ACK // 2 bits for dynamic HARQ-ACK codebook with single HARQ-ACK codebook {0, (((codebook_HARQ_ACK == 2) && (n_HARQ_ACK_sub_codebooks==2))?2:0), 0, 0, 0,0,0,0}, // 30 SECOND_DAI: (0 or 2 bits) 2 bits for dynamic HARQ-ACK codebook with two HARQ-ACK sub-codebooks // 0 bits otherwise {0, 0, (((crc_scrambled == _p_rnti) || (crc_scrambled == _ra_rnti)) ? 2:0), 0, 0,0,0,0}, // 31 TB_SCALING {2, 2, 0, 0, 0,0,0,0}, // 32 TPC_PUSCH: {0, 0, (crc_scrambled == _c_rnti)?2:0,2, 0,0,0,0}, // 33 TPC_PUCCH: {0, 0, (crc_scrambled == _c_rnti)?3:0,3, 0,0,0,0}, // 34 PUCCH_RESOURCE_IND: {0, 0, (crc_scrambled == _c_rnti)?3:0,pdsch_harq_t_ind, 0,0,0,0}, // 35 PDSCH_TO_HARQ_FEEDBACK_TIME_IND: {0, (uint8_t)log2(n_SRS), 0, 0, 0,0,0,0}, // 36 SRS_RESOURCE_IND: {0, precond_nbr_layers_bits, 0, 0, 0,0,0,0}, // 37 PRECOD_NBR_LAYERS: {0, antenna_ports_bits_ul, 0, antenna_ports_bits_dl, 0,0,0,0}, // 38 ANTENNA_PORTS: {0, 0, 0, tci_bits, 0,0,0,0}, // 39 TCI: 0 bit if higher layer parameter tci-PresentInDCI is not enabled; otherwise 3 bits {0, (sul_ind == 0)?2:3, 0, (sul_ind == 0)?2:3, 0,0,0,2}, // 40 SRS_REQUEST: {0, 0, 0, 0, 0,0,tpc_cmd_bit_2_2, tpc_cmd_bit_2_3}, // 41 TPC_CMD: {0, reportTriggerSize, 0, 0, 0,0,0,0}, // 42 CSI_REQUEST: {0, maxCodeBlockGroupsPerTransportBlock, 0, maxCodeBlockGroupsPerTransportBlock_dl, 0,0,0,0}, // 43 CBGTI: 0, 2, 4, 6, or 8 bits determined by higher layer parameter maxCodeBlockGroupsPerTransportBlock for the PDSCH {0, 0, 0, cbgfi_bit, 0,0,0,0}, // 44 CBGFI: 0 or 1 bit determined by higher layer parameter codeBlockGroupFlushIndicator {0, ptrs_dmrs_bits, 0, 0, 0,0,0,0}, // 45 PTRS_DMRS: {0, betaOffsets, 0, 0, 0,0,0,0}, // 46 BETA_OFFSET_IND: {0, dmrs_seq_ini_bits_ul, 0, dmrs_seq_ini_bits_dl, 0,0,0,0}, // 47 DMRS_SEQ_INI: 1 bit if the cell has two ULs and the number of bits for DCI format 1_0 before padding // is larger than the number of bits for DCI format 0_0 before padding; 0 bit otherwise {0, 1, 0, 0, 0,0,0,0}, // 48 UL_SCH_IND: value of "1" indicates UL-SCH shall be transmitted on the PUSCH and a value of "0" indicates UL-SCH shall not be transmitted on the PUSCH {0, 0, 0, 0, 0,0,0,0}, // 49 PADDING_NR_DCI: // (NOTE 2) If DCI format 0_0 is monitored in common search space // and if the number of information bits in the DCI format 0_0 prior to padding // is less than the payload size of the DCI format 1_0 monitored in common search space // zeros shall be appended to the DCI format 0_0 // until the payload size equals that of the DCI format 1_0 {(sul_ind == 0)?0:1, 0, 0, 0, 0,0,0,0}, // 50 SUL_IND_0_0: {0, 0, 0, 0, 0,0,0,0}, // 51 RA_PREAMBLE_INDEX (random access procedure initiated by a PDCCH order not implemented, FIXME!!!) {0, 0, 0, 0, 0,0,0,0}, // 52 SUL_IND_1_0 (random access procedure initiated by a PDCCH order not implemented, FIXME!!!) {0, 0, 0, 0, 0,0,0,0}, // 53 SS_PBCH_INDEX (random access procedure initiated by a PDCCH order not implemented, FIXME!!!) {0, 0, 0, 0, 0,0,0,0}, // 54 PRACH_MASK_INDEX (random access procedure initiated by a PDCCH order not implemented, FIXME!!!) {0, 0, ((crc_scrambled == _p_rnti)?6:(((crc_scrambled == _si_rnti) || (crc_scrambled == _ra_rnti))?16:0)), 0, 0,0,0,0} // 55 RESERVED_NR_DCI }; // NOTE 1: adjustments in freq_dom_resource_assignment_UL to be done if necessary // NOTE 2: adjustments in padding to be done if necessary uint8_t dci_size [8] = {0,0,0,0,0,0,0,0}; // will contain size for each format for (int i=0 ; i<NBR_NR_FORMATS ; i++) { //#ifdef NR_PDCCH_DCI_DEBUG // printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_dci_format_size)-> i=%d, j=%d\n", i, j); //#endif for (int j=0; j<NBR_NR_DCI_FIELDS; j++) { dci_size [i] = dci_size [i] + dci_field_size_table[j][i]; // dci_size[i] contains the size in bits of the dci pdu format i //if (i==(int)format-15) { // (int)format-15 indicates the position of each format in the table (e.g. format1_0=17 -> position in table is 2) dci_fields_sizes[j][i] = dci_field_size_table[j][i]; // dci_fields_sizes[j] contains the sizes of each field (j) for a determined format i //} } #ifdef NR_PDCCH_DCI_DEBUG printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_dci_format_size) dci_size[%d]=%d for n_RB_ULBWP=%d\n", i,dci_size[i],n_RB_ULBWP); #endif } #ifndef NR_PDCCH_DCI_DEBUG printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_dci_format_size) dci_fields_sizes[][] = { \n"); for (int j=0; j<NBR_NR_DCI_FIELDS; j++){ printf("\t\t"); for (int i=0; i<NBR_NR_FORMATS ; i++) printf("%d\t",dci_fields_sizes[j][i]); printf("\n"); } printf(" }\n"); #endif #ifdef NR_PDCCH_DCI_DEBUG printf("\n\t\t<-NR_PDCCH_DCI_DEBUG (nr_dci_format_size) dci_size[0_0]=%d, dci_size[0_1]=%d, dci_size[1_0]=%d, dci_size[1_1]=%d,\n",dci_size[0],dci_size[1],dci_size[2],dci_size[3]); #endif //UL/SUL indicator format0_0 (TS 38.212 subclause 7.3.1.1.1) // - 1 bit if the cell has two ULs and the number of bits for DCI format 1_0 before padding is larger than the number of bits for DCI format 0_0 before padding; // - 0 bit otherwise. // The UL/SUL indicator, if present, locates in the last bit position of DCI format 0_0, after the padding bit(s) if ((dci_field_size_table[SUL_IND_0_0][0] == 1) && (dci_size[0] > dci_size[2])){ dci_field_size_table[SUL_IND_0_0][0] = 0; dci_size[0]=dci_size[0]-1; } // if ((format == format0_0) || (format == format1_0)) { // According to Section 7.3.1.1.1 in TS 38.212 // If DCI format 0_0 is monitored in common search space and if the number of information bits in the DCI format 0_0 prior to padding // is less than the payload size of the DCI format 1_0 monitored in common search space for scheduling the same serving cell, // zeros shall be appended to the DCI format 0_0 until the payload size equals that of the DCI format 1_0. if (dci_size[0] < dci_size[2]) { // '0' corresponding to index for format0_0 and '2' corresponding to index of format1_0 //if (format == format0_0) { dci_fields_sizes[PADDING_NR_DCI][0] = dci_size[2] - dci_size[0]; dci_size[0] = dci_size[2]; #ifdef NR_PDCCH_DCI_DEBUG printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_dci_format_size) new dci_size[format0_0]=%d\n",dci_size[0]); #endif //} } // If DCI format 0_0 is monitored in common search space and if the number of information bits in the DCI format 0_0 prior to padding // is larger than the payload size of the DCI format 1_0 monitored in common search space for scheduling the same serving cell, // the bitwidth of the frequency domain resource allocation field in the DCI format 0_0 is reduced // such that the size of DCI format 0_0 equals to the size of the DCI format 1_0.. if (dci_size[0] > dci_size[2]) { //if (format == format0_0) { dci_fields_sizes[FREQ_DOM_RESOURCE_ASSIGNMENT_UL][0] -= (dci_size[0] - dci_size[2]); dci_size[0] = dci_size[2]; #ifdef NR_PDCCH_DCI_DEBUG printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_dci_format_size) new dci_size[format0_0]=%d\n",dci_size[0]); #endif //} } /* * TS 38.212 subclause 7.3.1.1.2 * For a UE configured with SUL in a cell: * if PUSCH is configured to be transmitted on both the SUL and the non-SUL of the cell and * if the number of information bits in format 0_1 for the SUL * is not equal to the number of information bits in format 0_1 for the non-SUL, * zeros shall be appended to smaller format 0_1 until the payload size equals that of the larger format 0_1 * * Not implemented. FIXME!!! * */ // } #ifndef NR_PDCCH_DCI_DEBUG printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_dci_format_size) dci_fields_sizes[][] = { \n"); for (int j=0; j<NBR_NR_DCI_FIELDS; j++){ printf("\t\t"); for (int i=0; i<NBR_NR_FORMATS ; i++) printf("%d\t",dci_fields_sizes[j][i]); printf("\n"); } printf(" }\n"); #endif return dci_size[format]; } #endif #ifdef NR_PDCCH_DCI_RUN uint8_t nr_dci_decoding_procedure(int s, int p, PHY_VARS_NR_UE *ue, NR_DCI_ALLOC_t *dci_alloc, NR_SEARCHSPACE_TYPE_t searchSpacetype, int16_t eNB_id, uint8_t nr_tti_rx, uint8_t dci_fields_sizes_cnt[MAX_NR_DCI_DECODED_SLOT][NBR_NR_DCI_FIELDS][NBR_NR_FORMATS], uint16_t n_RB_ULBWP, uint16_t n_RB_DLBWP, crc_scrambled_t *crc_scrambled, format_found_t *format_found, uint16_t crc_scrambled_values[TOTAL_NBR_SCRAMBLED_VALUES]) { // uint8_t dci_fields_sizes[NBR_NR_DCI_FIELDS][NBR_NR_FORMATS], for (int n=0; n<13; n++) printf("################ 2 crc_scrambled_values[%d]=%d\n",n,crc_scrambled_values[n]); #ifdef NR_PDCCH_DCI_DEBUG printf("\t<-NR_PDCCH_DCI_DEBUG (nr_dci_decoding_procedure) nr_tti_rx=%d n_RB_ULBWP=%d n_RB_DLBWP=%d format_found=%d\n", nr_tti_rx,n_RB_ULBWP,n_RB_DLBWP,*format_found); #endif int do_common = (int)searchSpacetype; uint8_t dci_fields_sizes[NBR_NR_DCI_FIELDS][NBR_NR_FORMATS]; crc_scrambled_t crc_scrambled_ = *crc_scrambled; format_found_t format_found_ = *format_found; uint8_t dci_cnt = 0, old_dci_cnt = 0; uint32_t CCEmap0 = 0, CCEmap1 = 0, CCEmap2 = 0; NR_UE_PDCCH **pdcch_vars = ue->pdcch_vars[ue->current_thread_id[nr_tti_rx]]; NR_UE_PDCCH *pdcch_vars2 = ue->pdcch_vars[ue->current_thread_id[nr_tti_rx]][eNB_id]; uint16_t pdcch_DMRS_scrambling_id = pdcch_vars2->coreset[p].pdcchDMRSScramblingID; uint64_t coreset_freq_dom = pdcch_vars2->coreset[p].frequencyDomainResources; int coreset_time_dur = pdcch_vars2->coreset[p].duration; uint16_t coreset_nbr_rb; for (int i = 0; i < 45; i++) { // this loop counts each bit of the bit map coreset_freq_dom, and increments nbr_RB_coreset for each bit set to '1' if (((coreset_freq_dom & 0x1FFFFFFFFFFF) >> i) & 0x1) coreset_nbr_rb++; } coreset_nbr_rb = 6 * coreset_nbr_rb; // coreset_time_dur,coreset_nbr_rb, NR_DL_FRAME_PARMS *frame_parms = &ue->frame_parms; t_nrPolar_paramsPtr *nrPolar_params = &ue->nrPolar_params; uint8_t mi;// = get_mi(&ue->frame_parms, nr_tti_rx); uint8_t tmode = ue->transmission_mode[eNB_id]; uint8_t frame_type = frame_parms->frame_type; uint8_t format_0_0_1_0_size_bits = 0, format_0_0_1_0_size_bytes = 0; //FIXME uint8_t format_0_1_1_1_size_bits = 0, format_0_1_1_1_size_bytes = 0; //FIXME uint8_t format_2_0_size_bits = 0, format_2_0_size_bytes = 0; //FIXME uint8_t format_2_1_size_bits = 0, format_2_1_size_bytes = 0; //FIXME uint8_t format_2_2_size_bits = 0, format_2_2_size_bytes = 0; //FIXME uint8_t format_2_3_size_bits = 0, format_2_3_size_bytes = 0; //FIXME /* * * The implementation of this function will depend on the information given by the searchSpace IE * * In LTE the UE has no knowledge about: * - the type of search (common or ue-specific) * - the DCI format it is going to be decoded when performing the PDCCH monitoring * So the blind decoding has to be done for common and ue-specific searchSpaces for each aggregation level and for each dci format * * In NR the UE has a knowledge about the search Space type and the DCI format it is going to be decoded, * so in the blind decoding we can call the function nr_dci_decoding_procedure0 with the searchSpace type and the dci format parameter * We will call this function as many times as aggregation levels indicated in searchSpace * Implementation according to 38.213 v15.1.0 Section 10. * */ NR_UE_SEARCHSPACE_CSS_DCI_FORMAT_t css_dci_format = pdcch_vars2->searchSpace[s].searchSpaceType.common_dci_formats; //FIXME!!! NR_UE_SEARCHSPACE_USS_DCI_FORMAT_t uss_dci_format = pdcch_vars2->searchSpace[s].searchSpaceType.ue_specific_dci_formats; //FIXME!!! // The following initialization is only for test purposes. To be removed // NR_UE_SEARCHSPACE_CSS_DCI_FORMAT_t css_dci_format = cformat0_0_and_1_0; //NR_UE_SEARCHSPACE_USS_DCI_FORMAT_t uss_dci_format = uformat0_0_and_1_0; /* * Possible overlap between RE for SS/PBCH blocks (described in section 10, 38.213) has not been implemented yet * This can be implemented by setting variable 'mode = NO_DCI' when overlap occurs */ //dci_detect_mode_t mode = 3; //dci_detect_mode_select(&ue->frame_parms, nr_tti_rx); #ifdef NR_PDCCH_DCI_DEBUG printf("\t<-NR_PDCCH_DCI_DEBUG (nr_dci_decoding_procedure)-> searSpaceType=%d\n",do_common); if (do_common==0) { printf("\t<-NR_PDCCH_DCI_DEBUG (nr_dci_decoding_procedure)-> css_dci_format=%d\n",css_dci_format); } else { printf("\t<-NR_PDCCH_DCI_DEBUG (nr_dci_decoding_procedure)-> uss_dci_format=%d\n",uss_dci_format); } #endif // A set of PDCCH candidates for a UE to monitor is defined in terms of PDCCH search spaces if (do_common==0) { // COMMON SearchSpaceType assigned to current SearchSpace/CORESET // Type0-PDCCH common search space for a DCI format with CRC scrambled by a SI-RNTI // number of consecutive resource blocks and a number of consecutive symbols for // the control resource set of the Type0-PDCCH common search space from // the four most significant bits of RMSI-PDCCH-Config as described in Tables 13-1 through 13-10 // and determines PDCCH monitoring occasions // from the four least significant bits of RMSI-PDCCH-Config, // included in MasterInformationBlock, as described in Tables 13-11 through 13-15 // Type0A-PDCCH common search space for a DCI format with CRC scrambled by a SI-RNTI // Type1-PDCCH common search space for a DCI format with CRC scrambled by a RA-RNTI, or a TC-RNTI, or a C-RNTI // Type2-PDCCH common search space for a DCI format with CRC scrambled by a P-RNTI if (css_dci_format == cformat0_0_and_1_0) { // 38.213 v15.1.0 Table 10.1-1: CCE aggregation levels and maximum number of PDCCH candidates per CCE // aggregation level for Type0/Type0A/Type2-PDCCH common search space // CCE Aggregation Level Number of Candidates // 4 4 // 8 2 // 16 1 // FIXME // We shall consider Table 10.1-1 to calculate the blind decoding only for Type0/Type0A/Type2-PDCCH // Shall we consider the nrofCandidates in SearSpace IE that considers Aggregation Levels 1,2,4,8,16? Our implementation considers Table 10.1-1 // blind decoding (Type0-PDCCH,Type0A-PDCCH,Type1-PDCCH,Type2-PDCCH) // for format0_0 => we are NOT implementing format0_0 for common search spaces. FIXME! // for format0_0 and format1_0, first we calculate dci pdu size format_0_0_1_0_size_bits = nr_dci_format_size(ue,eNB_id,nr_tti_rx,p,_c_rnti,n_RB_ULBWP,n_RB_DLBWP,dci_fields_sizes,0); format_0_0_1_0_size_bytes = (format_0_0_1_0_size_bits%8 == 0) ? (uint8_t)floor(format_0_0_1_0_size_bits/8) : (uint8_t)(floor(format_0_0_1_0_size_bits/8) + 1); #ifdef NR_PDCCH_DCI_DEBUG printf("\t<-NR_PDCCH_DCI_DEBUG (nr_dci_decoding_procedure)-> calculating dci format size for common searchSpaces with format css_dci_format=%d, format_0_0_1_0_size_bits=%d, format_0_0_1_0_size_bytes=%d\n", css_dci_format,format_0_0_1_0_size_bits,format_0_0_1_0_size_bytes); #endif for (int aggregationLevel = 3; aggregationLevel<4 ; aggregationLevel++) { // We fix aggregationLevel to 3 for testing=> nbr of CCE=8 //for (int aggregationLevel = 2; aggregationLevel<5 ; aggregationLevel++) { // for aggregation level aggregationLevel. The number of candidates (for L2= 2^aggregationLevel) will be calculated in function nr_dci_decoding_procedure0 #ifdef NR_PDCCH_DCI_DEBUG printf("\t<-NR_PDCCH_DCI_DEBUG (nr_dci_decoding_procedure)-> common searchSpaces with format css_dci_format=%d and aggregation_level=%d\n", css_dci_format,(1<<aggregationLevel)); #endif old_dci_cnt = dci_cnt; nr_dci_decoding_procedure0(s,p,coreset_time_dur,coreset_nbr_rb,pdcch_vars, 1, nr_tti_rx, dci_alloc, eNB_id, ue->current_thread_id[nr_tti_rx], frame_parms, nrPolar_params,mi, crc_scrambled_values, aggregationLevel, cformat0_0_and_1_0, uformat0_0_and_1_0, format_0_0_1_0_size_bits, format_0_0_1_0_size_bytes, &dci_cnt, &crc_scrambled_, &format_found_, pdcch_DMRS_scrambling_id,&CCEmap0, &CCEmap1, &CCEmap2); if (dci_cnt != old_dci_cnt){ // we will exit the loop as we have found the DCI aggregationLevel = 5; format_0_0_1_0_size_bits = nr_dci_format_size(ue,eNB_id,nr_tti_rx,p,crc_scrambled_,n_RB_ULBWP,n_RB_DLBWP,dci_fields_sizes,0); // after decoding dci successfully we recalculate dci pdu size with correct crc scrambled to get the right field sizes old_dci_cnt = dci_cnt; for (int i=0; i<NBR_NR_DCI_FIELDS; i++) for (int j=0; j<NBR_NR_FORMATS; j++) dci_fields_sizes_cnt[dci_cnt-1][i][j]=dci_fields_sizes[i][j]; } } } // Type3-PDCCH common search space for a DCI format with CRC scrambled by INT-RNTI, or SFI-RNTI, // or TPC-PUSCH-RNTI, or TPC-PUCCH-RNTI, or TPC-SRS-RNTI, or C-RNTI, or CS-RNTI(s), or SP-CSI-RNTI if (css_dci_format == cformat2_0) { // for format2_0, first we calculate dci pdu size format_2_0_size_bits = nr_dci_format_size(ue,eNB_id,nr_tti_rx,p,_sfi_rnti,n_RB_ULBWP,n_RB_DLBWP,dci_fields_sizes,4); format_2_0_size_bytes = (format_2_0_size_bits%8 == 0) ? (uint8_t)floor(format_2_0_size_bits/8) : (uint8_t)(floor(format_2_0_size_bits/8) + 1); #ifdef NR_PDCCH_DCI_DEBUG printf("\t<-NR_PDCCH_DCI_DEBUG (nr_dci_decoding_procedure)-> calculating dci format size for common searchSpaces with format css_dci_format=%d, format2_0_size_bits=%d, format2_0_size_bytes=%d\n", css_dci_format,format_2_0_size_bits,format_2_0_size_bytes); #endif for (int aggregationLevelSFI = 0; aggregationLevelSFI<5 ; aggregationLevelSFI++){ #ifdef NR_PDCCH_DCI_DEBUG printf("\t<-NR_PDCCH_DCI_DEBUG (nr_dci_decoding_procedure)-> common searchSpaces with format css_dci_format=%d and aggregation_level=%d\n", css_dci_format,(1<<aggregationLevelSFI)); #endif // for aggregation level 'aggregationLevelSFI'. The number of candidates (nrofCandidates-SFI) will be calculated in function nr_dci_decoding_procedure0 old_dci_cnt = dci_cnt; nr_dci_decoding_procedure0(s,p,coreset_time_dur,coreset_nbr_rb,pdcch_vars, 1, nr_tti_rx, dci_alloc, eNB_id, ue->current_thread_id[nr_tti_rx], frame_parms, nrPolar_params,mi, crc_scrambled_values, aggregationLevelSFI, cformat2_0, uformat0_0_and_1_0, format_2_0_size_bits, format_2_0_size_bytes, &dci_cnt, &crc_scrambled_, &format_found_,pdcch_DMRS_scrambling_id, &CCEmap0, &CCEmap1, &CCEmap2); if (dci_cnt != old_dci_cnt){ // we will exit the loop as we have found the DCI aggregationLevelSFI = 5; old_dci_cnt = dci_cnt; for (int i=0; i<NBR_NR_DCI_FIELDS; i++) for (int j=0; j<NBR_NR_FORMATS; j++) dci_fields_sizes_cnt[dci_cnt-1][i][j]=dci_fields_sizes[i][j]; } } } if (css_dci_format == cformat2_1) { // for format2_1, first we calculate dci pdu size format_2_1_size_bits = nr_dci_format_size(ue,eNB_id,nr_tti_rx,p,_int_rnti,n_RB_ULBWP,n_RB_DLBWP,dci_fields_sizes,5); format_2_1_size_bytes = (format_2_1_size_bits%8 == 0) ? (uint8_t)floor(format_2_1_size_bits/8) : (uint8_t)(floor(format_2_1_size_bits/8) + 1); #ifdef NR_PDCCH_DCI_DEBUG printf("\t<-NR_PDCCH_DCI_DEBUG (nr_dci_decoding_procedure)-> calculating dci format size for common searchSpaces with format css_dci_format=%d, format2_1_size_bits=%d, format2_1_size_bytes=%d\n", css_dci_format,format_2_1_size_bits,format_2_1_size_bytes); #endif for (int aggregationLevel = 0; aggregationLevel<5 ; aggregationLevel++){ #ifdef NR_PDCCH_DCI_DEBUG printf("\t<-NR_PDCCH_DCI_DEBUG (nr_dci_decoding_procedure)-> common searchSpaces with format css_dci_format=%d and aggregation_level=%d\n", css_dci_format,(1<<aggregationLevel)); #endif // for aggregation level 'aggregationLevelSFI'. The number of candidates (nrofCandidates-SFI) will be calculated in function nr_dci_decoding_procedure0 old_dci_cnt = dci_cnt; nr_dci_decoding_procedure0(s,p,coreset_time_dur,coreset_nbr_rb,pdcch_vars, 1, nr_tti_rx, dci_alloc, eNB_id, ue->current_thread_id[nr_tti_rx], frame_parms, nrPolar_params,mi, crc_scrambled_values, aggregationLevel, cformat2_1, uformat0_0_and_1_0, format_2_1_size_bits, format_2_1_size_bytes, &dci_cnt, &crc_scrambled_, &format_found_,pdcch_DMRS_scrambling_id, &CCEmap0, &CCEmap1, &CCEmap2); if (dci_cnt != old_dci_cnt){ // we will exit the loop as we have found the DCI aggregationLevel = 5; old_dci_cnt = dci_cnt; for (int i=0; i<NBR_NR_DCI_FIELDS; i++) for (int j=0; j<NBR_NR_FORMATS; j++) dci_fields_sizes_cnt[dci_cnt-1][i][j]=dci_fields_sizes[i][j]; } } } if (css_dci_format == cformat2_2) { // for format2_2, first we calculate dci pdu size format_2_2_size_bits = nr_dci_format_size(ue,eNB_id,nr_tti_rx,p,_tpc_pucch_rnti,n_RB_ULBWP,n_RB_DLBWP,dci_fields_sizes,6); format_2_2_size_bytes = (format_2_2_size_bits%8 == 0) ? (uint8_t)floor(format_2_2_size_bits/8) : (uint8_t)(floor(format_2_2_size_bits/8) + 1); #ifdef NR_PDCCH_DCI_DEBUG printf("\t<-NR_PDCCH_DCI_DEBUG (nr_dci_decoding_procedure)-> calculating dci format size for common searchSpaces with format css_dci_format=%d, format2_2_size_bits=%d, format2_2_size_bytes=%d\n", css_dci_format,format_2_2_size_bits,format_2_2_size_bytes); #endif for (int aggregationLevel = 0; aggregationLevel<5 ; aggregationLevel++){ #ifdef NR_PDCCH_DCI_DEBUG printf("\t<-NR_PDCCH_DCI_DEBUG (nr_dci_decoding_procedure)-> common searchSpaces with format css_dci_format=%d and aggregation_level=%d\n", css_dci_format,(1<<aggregationLevel)); #endif // for aggregation level 'aggregationLevelSFI'. The number of candidates (nrofCandidates-SFI) will be calculated in function nr_dci_decoding_procedure0 old_dci_cnt = dci_cnt; nr_dci_decoding_procedure0(s,p,coreset_time_dur,coreset_nbr_rb,pdcch_vars, 1, nr_tti_rx, dci_alloc, eNB_id, ue->current_thread_id[nr_tti_rx], frame_parms, nrPolar_params,mi, crc_scrambled_values, aggregationLevel, cformat2_2, uformat0_0_and_1_0, format_2_2_size_bits, format_2_2_size_bytes, &dci_cnt, &crc_scrambled_, &format_found_,pdcch_DMRS_scrambling_id, &CCEmap0, &CCEmap1, &CCEmap2); if (dci_cnt != old_dci_cnt){ // we will exit the loop as we have found the DCI aggregationLevel = 5; old_dci_cnt = dci_cnt; for (int i=0; i<NBR_NR_DCI_FIELDS; i++) for (int j=0; j<NBR_NR_FORMATS; j++) dci_fields_sizes_cnt[dci_cnt-1][i][j]=dci_fields_sizes[i][j]; } } } if (css_dci_format == cformat2_3) { // for format2_1, first we calculate dci pdu size format_2_3_size_bits = nr_dci_format_size(ue,eNB_id,nr_tti_rx,p,_tpc_srs_rnti,n_RB_ULBWP,n_RB_DLBWP,dci_fields_sizes,7); format_2_3_size_bytes = (format_2_3_size_bits%8 == 0) ? (uint8_t)floor(format_2_3_size_bits/8) : (uint8_t)(floor(format_2_3_size_bits/8) + 1); #ifdef NR_PDCCH_DCI_DEBUG printf("\t<-NR_PDCCH_DCI_DEBUG (nr_dci_decoding_procedure)-> calculating dci format size for common searchSpaces with format css_dci_format=%d, format2_3_size_bits=%d, format2_3_size_bytes=%d\n", css_dci_format,format_2_3_size_bits,format_2_3_size_bytes); #endif for (int aggregationLevel = 0; aggregationLevel<5 ; aggregationLevel++){ #ifdef NR_PDCCH_DCI_DEBUG printf("\t<-NR_PDCCH_DCI_DEBUG (nr_dci_decoding_procedure)-> common searchSpaces with format css_dci_format=%d and aggregation_level=%d\n", css_dci_format,(1<<aggregationLevel)); #endif // for aggregation level 'aggregationLevelSFI'. The number of candidates (nrofCandidates-SFI) will be calculated in function nr_dci_decoding_procedure0 old_dci_cnt = dci_cnt; nr_dci_decoding_procedure0(s,p,coreset_time_dur,coreset_nbr_rb,pdcch_vars, 1, nr_tti_rx, dci_alloc, eNB_id, ue->current_thread_id[nr_tti_rx], frame_parms, nrPolar_params,mi, crc_scrambled_values, aggregationLevel, cformat2_3, uformat0_0_and_1_0, format_2_3_size_bits, format_2_3_size_bytes, &dci_cnt, &crc_scrambled_, &format_found_,pdcch_DMRS_scrambling_id, &CCEmap0, &CCEmap1, &CCEmap2); if (dci_cnt != old_dci_cnt){ // we will exit the loop as we have found the DCI aggregationLevel = 5; old_dci_cnt = dci_cnt; for (int i=0; i<NBR_NR_DCI_FIELDS; i++) for (int j=0; j<NBR_NR_FORMATS; j++) dci_fields_sizes_cnt[dci_cnt-1][i][j]=dci_fields_sizes[i][j]; } } } } else { // UE-SPECIFIC SearchSpaceType assigned to current SearchSpace/CORESET // UE-specific search space for a DCI format with CRC scrambled by C-RNTI, or CS-RNTI(s), or SP-CSI-RNTI if (uss_dci_format == uformat0_0_and_1_0) { // for format0_0 and format1_0, first we calculate dci pdu size format_0_0_1_0_size_bits = nr_dci_format_size(ue,eNB_id,nr_tti_rx,p,_c_rnti,n_RB_ULBWP,n_RB_DLBWP,dci_fields_sizes,0); format_0_0_1_0_size_bytes = (format_0_0_1_0_size_bits%8 == 0) ? (uint8_t)floor(format_0_0_1_0_size_bits/8) : (uint8_t)(floor(format_0_0_1_0_size_bits/8) + 1); #ifdef NR_PDCCH_DCI_DEBUG printf("\t<-NR_PDCCH_DCI_DEBUG (nr_dci_decoding_procedure)-> calculating dci format size for UE-specific searchSpaces with format uss_dci_format=%d, format_0_0_1_0_size_bits=%d, format_0_0_1_0_size_bytes=%d\n", css_dci_format,format_0_0_1_0_size_bits,format_0_0_1_0_size_bytes); #endif for (int aggregationLevel = 0; aggregationLevel<5 ; aggregationLevel++) { // We fix aggregationLevel to 3 for testing=> nbr of CCE=8 //for (int aggregationLevel = 2; aggregationLevel<5 ; aggregationLevel++) { // for aggregation level aggregationLevel. The number of candidates (for L2= 2^aggregationLevel) will be calculated in function nr_dci_decoding_procedure0 #ifdef NR_PDCCH_DCI_DEBUG printf("\t<-NR_PDCCH_DCI_DEBUG (nr_dci_decoding_procedure)-> common searchSpaces with format css_dci_format=%d and aggregation_level=%d\n", css_dci_format,(1<<aggregationLevel)); #endif old_dci_cnt = dci_cnt; nr_dci_decoding_procedure0(s,p,coreset_time_dur,coreset_nbr_rb,pdcch_vars, 0, nr_tti_rx, dci_alloc, eNB_id, ue->current_thread_id[nr_tti_rx], frame_parms,nrPolar_params, mi, crc_scrambled_values, aggregationLevel, cformat0_0_and_1_0, uformat0_0_and_1_0, format_0_0_1_0_size_bits, format_0_0_1_0_size_bytes, &dci_cnt, &crc_scrambled_, &format_found_,pdcch_DMRS_scrambling_id, &CCEmap0, &CCEmap1, &CCEmap2); if (dci_cnt != old_dci_cnt){ // we will exit the loop as we have found the DCI aggregationLevel = 5; old_dci_cnt = dci_cnt; for (int i=0; i<NBR_NR_DCI_FIELDS; i++) for (int j=0; j<NBR_NR_FORMATS; j++) dci_fields_sizes_cnt[dci_cnt-1][i][j]=dci_fields_sizes[i][j]; } } } if (uss_dci_format == uformat0_1_and_1_1) { // for format0_0 and format1_0, first we calculate dci pdu size format_0_1_1_1_size_bits = nr_dci_format_size(ue,eNB_id,nr_tti_rx,p,_c_rnti,n_RB_ULBWP,n_RB_DLBWP,dci_fields_sizes,1); format_0_1_1_1_size_bytes = (format_0_1_1_1_size_bits%8 == 0) ? (uint8_t)floor(format_0_1_1_1_size_bits/8) : (uint8_t)(floor(format_0_1_1_1_size_bits/8) + 1); #ifdef NR_PDCCH_DCI_DEBUG printf("\t<-NR_PDCCH_DCI_DEBUG (nr_dci_decoding_procedure)-> calculating dci format size for UE-specific searchSpaces with format uss_dci_format=%d, format_0_1_1_1_size_bits=%d, format_0_1_1_1_size_bytes=%d\n", css_dci_format,format_0_1_1_1_size_bits,format_0_1_1_1_size_bytes); #endif for (int aggregationLevel = 0; aggregationLevel<5 ; aggregationLevel++) { // We fix aggregationLevel to 3 for testing=> nbr of CCE=8 //for (int aggregationLevel = 2; aggregationLevel<5 ; aggregationLevel++) { // for aggregation level aggregationLevel. The number of candidates (for L2= 2^aggregationLevel) will be calculated in function nr_dci_decoding_procedure0 #ifdef NR_PDCCH_DCI_DEBUG printf("\t<-NR_PDCCH_DCI_DEBUG (nr_dci_decoding_procedure)-> common searchSpaces with format css_dci_format=%d and aggregation_level=%d\n", css_dci_format,(1<<aggregationLevel)); #endif old_dci_cnt = dci_cnt; nr_dci_decoding_procedure0(s,p,coreset_time_dur,coreset_nbr_rb,pdcch_vars, 0, nr_tti_rx, dci_alloc, eNB_id, ue->current_thread_id[nr_tti_rx], frame_parms,nrPolar_params, mi, crc_scrambled_values, aggregationLevel, cformat0_0_and_1_0, uformat0_1_and_1_1, format_0_1_1_1_size_bits, format_0_1_1_1_size_bytes, &dci_cnt, &crc_scrambled_, &format_found_,pdcch_DMRS_scrambling_id, &CCEmap0, &CCEmap1, &CCEmap2); if (dci_cnt != old_dci_cnt){ // we will exit the loop as we have found the DCI aggregationLevel = 5; old_dci_cnt = dci_cnt; for (int i=0; i<NBR_NR_DCI_FIELDS; i++) for (int j=0; j<NBR_NR_FORMATS; j++) dci_fields_sizes_cnt[dci_cnt-1][i][j]=dci_fields_sizes[i][j]; } } } } *crc_scrambled = crc_scrambled_; *format_found = format_found_; #ifdef NR_PDCCH_DCI_DEBUG printf("\t<-NR_PDCCH_DCI_DEBUG (nr_dci_decoding_procedure)-> at the end crc_scrambled=%d and format_found=%d\n",*crc_scrambled,*format_found); #endif /*if (uss_dci_format == uformat0_1_and_1_1) { // Not implemented yet. FIXME!!! // for format0_1, first we calculate dci pdu size format0_1_size_bits = nr_dci_format_size(format0_1,c_rnti,16,n_RB_ULBWP,n_RB_DLBWP,dci_fields_sizes); format0_1_size_bytes = (format0_1_size_bits%8 == 0) ? (uint8_t)floor(format0_1_size_bits/8) : (uint8_t)(floor(format0_1_size_bits/8) + 1); #ifdef NR_PDCCH_DCI_DEBUG printf("\t<-NR_PDCCH_DCI_DEBUG (nr_dci_decoding_procedure)-> calculating dci format size for UE-specific searchSpaces with format uss_dci_format=%d, format0_1_size_bits=%d, format0_1_size_bytes=%d\n", css_dci_format,format0_1_size_bits,format0_1_size_bytes); #endif // blind decoding format0_1 for aggregation level 1. The number of candidates (nrofCandidates) will be calculated in function nr_dci_decoding_procedure0 // blind decoding format0_1 for aggregation level 2. The number of candidates (nrofCandidates) will be calculated in function nr_dci_decoding_procedure0 // blind decoding format0_1 for aggregation level 4. The number of candidates (nrofCandidates) will be calculated in function nr_dci_decoding_procedure0 // blind decoding format0_1 for aggregation level 8. The number of candidates (nrofCandidates) will be calculated in function nr_dci_decoding_procedure0 // blind decoding format0_1 for aggregation level 16. The number of candidates (nrofCandidates) will be calculated in function nr_dci_decoding_procedure0 // for format1_1, first we calculate dci pdu size format1_1_size_bits = nr_dci_format_size(format1_1,c_rnti,16,n_RB_ULBWP,n_RB_DLBWP,dci_fields_sizes); format1_1_size_bytes = (format1_1_size_bits%8 == 0) ? (uint8_t)floor(format1_1_size_bits/8) : (uint8_t)(floor(format1_1_size_bits/8) + 1); #ifdef NR_PDCCH_DCI_DEBUG printf("\t<-NR_PDCCH_DCI_DEBUG (nr_dci_decoding_procedure)-> calculating dci format size for UE-specific searchSpaces with format uss_dci_format=%d, format1_1_size_bits=%d, format1_1_size_bytes=%d\n", css_dci_format,format1_1_size_bits,format1_1_size_bytes); #endif // blind decoding format1_1 for aggregation level 1. The number of candidates (nrofCandidates) will be calculated in function nr_dci_decoding_procedure0 // blind decoding format1_1 for aggregation level 2. The number of candidates (nrofCandidates) will be calculated in function nr_dci_decoding_procedure0 // blind decoding format1_1 for aggregation level 4. The number of candidates (nrofCandidates) will be calculated in function nr_dci_decoding_procedure0 // blind decoding format1_1 for aggregation level 8. The number of candidates (nrofCandidates) will be calculated in function nr_dci_decoding_procedure0 // blind decoding format1_1 for aggregation level 16. The number of candidates (nrofCandidates) will be calculated in function nr_dci_decoding_procedure0 }*/ //} #ifdef NR_PDCCH_DCI_DEBUG printf("\t<-NR_PDCCH_DCI_DEBUG (nr_dci_decoding_procedure)-> at the end dci_cnt=%d \n",dci_cnt); #endif return(dci_cnt); } #endif /* uint16_t dci_decoding_procedure(PHY_VARS_NR_UE *ue, DCI_ALLOC_t *dci_alloc, int do_common, int16_t eNB_id, uint8_t nr_tti_rx) { uint8_t dci_cnt=0,old_dci_cnt=0; uint32_t CCEmap0=0,CCEmap1=0,CCEmap2=0; NR_UE_PDCCH **pdcch_vars = ue->pdcch_vars[ue->current_thread_id[nr_tti_rx]]; NR_DL_FRAME_PARMS *frame_parms = &ue->frame_parms; uint8_t mi = get_mi(&ue->frame_parms,nr_tti_rx); uint16_t ra_rnti=99; uint8_t format0_found=0,format_c_found=0; uint8_t tmode = ue->transmission_mode[eNB_id]; uint8_t frame_type = frame_parms->frame_type; uint8_t format1A_size_bits=0,format1A_size_bytes=0; uint8_t format1C_size_bits=0,format1C_size_bytes=0; uint8_t format0_size_bits=0,format0_size_bytes=0; uint8_t format1_size_bits=0,format1_size_bytes=0; uint8_t format2_size_bits=0,format2_size_bytes=0; uint8_t format2A_size_bits=0,format2A_size_bytes=0; dci_detect_mode_t mode = dci_detect_mode_select(&ue->frame_parms,nr_tti_rx); switch (frame_parms->N_RB_DL) { case 6: if (frame_type == TDD) { format1A_size_bits = sizeof_DCI1A_1_5MHz_TDD_1_6_t; format1A_size_bytes = sizeof(DCI1A_1_5MHz_TDD_1_6_t); format1C_size_bits = sizeof_DCI1C_1_5MHz_t; format1C_size_bytes = sizeof(DCI1C_1_5MHz_t); format0_size_bits = sizeof_DCI0_1_5MHz_TDD_1_6_t; format0_size_bytes = sizeof(DCI0_1_5MHz_TDD_1_6_t); format1_size_bits = sizeof_DCI1_1_5MHz_TDD_t; format1_size_bytes = sizeof(DCI1_1_5MHz_TDD_t); if (frame_parms->nb_antenna_ports_eNB == 2) { format2_size_bits = sizeof_DCI2_1_5MHz_2A_TDD_t; format2_size_bytes = sizeof(DCI2_1_5MHz_2A_TDD_t); format2A_size_bits = sizeof_DCI2A_1_5MHz_2A_TDD_t; format2A_size_bytes = sizeof(DCI2A_1_5MHz_2A_TDD_t); } else if (frame_parms->nb_antenna_ports_eNB == 4) { format2_size_bits = sizeof_DCI2_1_5MHz_4A_TDD_t; format2_size_bytes = sizeof(DCI2_1_5MHz_4A_TDD_t); format2A_size_bits = sizeof_DCI2A_1_5MHz_4A_TDD_t; format2A_size_bytes = sizeof(DCI2A_1_5MHz_4A_TDD_t); } } else { format1A_size_bits = sizeof_DCI1A_1_5MHz_FDD_t; format1A_size_bytes = sizeof(DCI1A_1_5MHz_FDD_t); format1C_size_bits = sizeof_DCI1C_1_5MHz_t; format1C_size_bytes = sizeof(DCI1C_1_5MHz_t); format0_size_bits = sizeof_DCI0_1_5MHz_FDD_t; format0_size_bytes = sizeof(DCI0_1_5MHz_FDD_t); format1_size_bits = sizeof_DCI1_1_5MHz_FDD_t; format1_size_bytes = sizeof(DCI1_1_5MHz_FDD_t); if (frame_parms->nb_antenna_ports_eNB == 2) { format2_size_bits = sizeof_DCI2_1_5MHz_2A_FDD_t; format2_size_bytes = sizeof(DCI2_1_5MHz_2A_FDD_t); format2A_size_bits = sizeof_DCI2A_1_5MHz_2A_FDD_t; format2A_size_bytes = sizeof(DCI2A_1_5MHz_2A_FDD_t); } else if (frame_parms->nb_antenna_ports_eNB == 4) { format2_size_bits = sizeof_DCI2_1_5MHz_4A_FDD_t; format2_size_bytes = sizeof(DCI2_1_5MHz_4A_FDD_t); format2A_size_bits = sizeof_DCI2A_1_5MHz_4A_FDD_t; format2A_size_bytes = sizeof(DCI2A_1_5MHz_4A_FDD_t); } } break; case 25: default: if (frame_type == TDD) { format1A_size_bits = sizeof_DCI1A_5MHz_TDD_1_6_t; format1A_size_bytes = sizeof(DCI1A_5MHz_TDD_1_6_t); format1C_size_bits = sizeof_DCI1C_5MHz_t; format1C_size_bytes = sizeof(DCI1C_5MHz_t); format0_size_bits = sizeof_DCI0_5MHz_TDD_1_6_t; format0_size_bytes = sizeof(DCI0_5MHz_TDD_1_6_t); format1_size_bits = sizeof_DCI1_5MHz_TDD_t; format1_size_bytes = sizeof(DCI1_5MHz_TDD_t); if (frame_parms->nb_antenna_ports_eNB == 2) { format2_size_bits = sizeof_DCI2_5MHz_2A_TDD_t; format2_size_bytes = sizeof(DCI2_5MHz_2A_TDD_t); format2A_size_bits = sizeof_DCI2A_5MHz_2A_TDD_t; format2A_size_bytes = sizeof(DCI2A_5MHz_2A_TDD_t); } else if (frame_parms->nb_antenna_ports_eNB == 4) { format2_size_bits = sizeof_DCI2_5MHz_4A_TDD_t; format2_size_bytes = sizeof(DCI2_5MHz_4A_TDD_t); format2A_size_bits = sizeof_DCI2A_5MHz_4A_TDD_t; format2A_size_bytes = sizeof(DCI2A_5MHz_4A_TDD_t); } } else { format1A_size_bits = sizeof_DCI1A_5MHz_FDD_t; format1A_size_bytes = sizeof(DCI1A_5MHz_FDD_t); format1C_size_bits = sizeof_DCI1C_5MHz_t; format1C_size_bytes = sizeof(DCI1C_5MHz_t); format0_size_bits = sizeof_DCI0_5MHz_FDD_t; format0_size_bytes = sizeof(DCI0_5MHz_FDD_t); format1_size_bits = sizeof_DCI1_5MHz_FDD_t; format1_size_bytes = sizeof(DCI1_5MHz_FDD_t); if (frame_parms->nb_antenna_ports_eNB == 2) { format2_size_bits = sizeof_DCI2_5MHz_2A_FDD_t; format2_size_bytes = sizeof(DCI2_5MHz_2A_FDD_t); format2A_size_bits = sizeof_DCI2A_5MHz_2A_FDD_t; format2A_size_bytes = sizeof(DCI2A_5MHz_2A_FDD_t); } else if (frame_parms->nb_antenna_ports_eNB == 4) { format2_size_bits = sizeof_DCI2_5MHz_4A_FDD_t; format2_size_bytes = sizeof(DCI2_5MHz_4A_FDD_t); format2A_size_bits = sizeof_DCI2A_5MHz_4A_FDD_t; format2A_size_bytes = sizeof(DCI2A_5MHz_4A_FDD_t); } } break; case 50: if (frame_type == TDD) { format1A_size_bits = sizeof_DCI1A_10MHz_TDD_1_6_t; format1A_size_bytes = sizeof(DCI1A_10MHz_TDD_1_6_t); format1C_size_bits = sizeof_DCI1C_10MHz_t; format1C_size_bytes = sizeof(DCI1C_10MHz_t); format0_size_bits = sizeof_DCI0_10MHz_TDD_1_6_t; format0_size_bytes = sizeof(DCI0_10MHz_TDD_1_6_t); format1_size_bits = sizeof_DCI1_10MHz_TDD_t; format1_size_bytes = sizeof(DCI1_10MHz_TDD_t); if (frame_parms->nb_antenna_ports_eNB == 2) { format2_size_bits = sizeof_DCI2_10MHz_2A_TDD_t; format2_size_bytes = sizeof(DCI2_10MHz_2A_TDD_t); format2A_size_bits = sizeof_DCI2A_10MHz_2A_TDD_t; format2A_size_bytes = sizeof(DCI2A_10MHz_2A_TDD_t); } else if (frame_parms->nb_antenna_ports_eNB == 4) { format2_size_bits = sizeof_DCI2_10MHz_4A_TDD_t; format2_size_bytes = sizeof(DCI2_10MHz_4A_TDD_t); format2A_size_bits = sizeof_DCI2A_10MHz_4A_TDD_t; format2A_size_bytes = sizeof(DCI2A_10MHz_4A_TDD_t); } } else { format1A_size_bits = sizeof_DCI1A_10MHz_FDD_t; format1A_size_bytes = sizeof(DCI1A_10MHz_FDD_t); format1C_size_bits = sizeof_DCI1C_10MHz_t; format1C_size_bytes = sizeof(DCI1C_10MHz_t); format0_size_bits = sizeof_DCI0_10MHz_FDD_t; format0_size_bytes = sizeof(DCI0_10MHz_FDD_t); format1_size_bits = sizeof_DCI1_10MHz_FDD_t; format1_size_bytes = sizeof(DCI1_10MHz_FDD_t); if (frame_parms->nb_antenna_ports_eNB == 2) { format2_size_bits = sizeof_DCI2_10MHz_2A_FDD_t; format2_size_bytes = sizeof(DCI2_10MHz_2A_FDD_t); format2A_size_bits = sizeof_DCI2A_10MHz_2A_FDD_t; format2A_size_bytes = sizeof(DCI2A_10MHz_2A_FDD_t); } else if (frame_parms->nb_antenna_ports_eNB == 4) { format2_size_bits = sizeof_DCI2_10MHz_4A_FDD_t; format2_size_bytes = sizeof(DCI2_10MHz_4A_FDD_t); format2A_size_bits = sizeof_DCI2A_10MHz_4A_FDD_t; format2A_size_bytes = sizeof(DCI2A_10MHz_4A_FDD_t); } } break; case 100: if (frame_type == TDD) { format1A_size_bits = sizeof_DCI1A_20MHz_TDD_1_6_t; format1A_size_bytes = sizeof(DCI1A_20MHz_TDD_1_6_t); format1C_size_bits = sizeof_DCI1C_20MHz_t; format1C_size_bytes = sizeof(DCI1C_20MHz_t); format0_size_bits = sizeof_DCI0_20MHz_TDD_1_6_t; format0_size_bytes = sizeof(DCI0_20MHz_TDD_1_6_t); format1_size_bits = sizeof_DCI1_20MHz_TDD_t; format1_size_bytes = sizeof(DCI1_20MHz_TDD_t); if (frame_parms->nb_antenna_ports_eNB == 2) { format2_size_bits = sizeof_DCI2_20MHz_2A_TDD_t; format2_size_bytes = sizeof(DCI2_20MHz_2A_TDD_t); format2A_size_bits = sizeof_DCI2A_20MHz_2A_TDD_t; format2A_size_bytes = sizeof(DCI2A_20MHz_2A_TDD_t); } else if (frame_parms->nb_antenna_ports_eNB == 4) { format2_size_bits = sizeof_DCI2_20MHz_4A_TDD_t; format2_size_bytes = sizeof(DCI2_20MHz_4A_TDD_t); format2A_size_bits = sizeof_DCI2A_20MHz_4A_TDD_t; format2A_size_bytes = sizeof(DCI2A_20MHz_4A_TDD_t); } } else { format1A_size_bits = sizeof_DCI1A_20MHz_FDD_t; format1A_size_bytes = sizeof(DCI1A_20MHz_FDD_t); format1C_size_bits = sizeof_DCI1C_20MHz_t; format1C_size_bytes = sizeof(DCI1C_20MHz_t); format0_size_bits = sizeof_DCI0_20MHz_FDD_t; format0_size_bytes = sizeof(DCI0_20MHz_FDD_t); format1_size_bits = sizeof_DCI1_20MHz_FDD_t; format1_size_bytes = sizeof(DCI1_20MHz_FDD_t); if (frame_parms->nb_antenna_ports_eNB == 2) { format2_size_bits = sizeof_DCI2_20MHz_2A_FDD_t; format2_size_bytes = sizeof(DCI2_20MHz_2A_FDD_t); format2A_size_bits = sizeof_DCI2A_20MHz_2A_FDD_t; format2A_size_bytes = sizeof(DCI2A_20MHz_2A_FDD_t); } else if (frame_parms->nb_antenna_ports_eNB == 4) { format2_size_bits = sizeof_DCI2_20MHz_4A_FDD_t; format2_size_bytes = sizeof(DCI2_20MHz_4A_FDD_t); format2A_size_bits = sizeof_DCI2A_20MHz_4A_FDD_t; format2A_size_bytes = sizeof(DCI2A_20MHz_4A_FDD_t); } } break; } if (do_common == 1) { #ifdef DEBUG_DCI_DECODING printf("[DCI search] doing common search/format0 aggregation 4\n"); #endif if (ue->prach_resources[eNB_id]) ra_rnti = ue->prach_resources[eNB_id]->ra_RNTI; // First check common search spaces at aggregation 4 (SI_RNTI, P_RNTI and RA_RNTI format 0/1A), // and UE_SPEC format0 (PUSCH) too while we're at it dci_decoding_procedure0(pdcch_vars,1,mode,nr_tti_rx, dci_alloc, eNB_id, ue->current_thread_id[nr_tti_rx], frame_parms, mi, ((ue->decode_SIB == 1) ? SI_RNTI : 0) , ra_rnti, P_RNTI, 2, format1A, format1A, format1A, format0, format1A_size_bits, format1A_size_bytes, &dci_cnt, &format0_found, &format_c_found, &CCEmap0, &CCEmap1, &CCEmap2); if ((CCEmap0==0xffff) || ((format0_found==1)&&(format_c_found==1))) return(dci_cnt); // Now check common search spaces at aggregation 4 (SI_RNTI,P_RNTI and RA_RNTI and C-RNTI format 1C), // and UE_SPEC format0 (PUSCH) too while we're at it dci_decoding_procedure0(pdcch_vars,1,mode,nr_tti_rx, dci_alloc, eNB_id, ue->current_thread_id[nr_tti_rx], frame_parms, mi, ((ue->decode_SIB == 1) ? SI_RNTI : 0), ra_rnti, P_RNTI, 2, format1C, format1C, format1C, format1C, format1C_size_bits, format1C_size_bytes, &dci_cnt, &format0_found, &format_c_found, &CCEmap0, &CCEmap1, &CCEmap2); if ((CCEmap0==0xffff) || ((format0_found==1)&&(format_c_found==1))) return(dci_cnt); // Now check common search spaces at aggregation 8 (SI_RNTI,P_RNTI and RA_RNTI format 1A), // and UE_SPEC format0 (PUSCH) too while we're at it // printf("[DCI search] doing common search/format0 aggregation 3\n"); #ifdef DEBUG_DCI_DECODING printf("[DCI search] doing common search/format0 aggregation 8\n"); #endif dci_decoding_procedure0(pdcch_vars,1,mode,nr_tti_rx, dci_alloc, eNB_id, ue->current_thread_id[nr_tti_rx], frame_parms, mi, ((ue->decode_SIB == 1) ? SI_RNTI : 0), P_RNTI, ra_rnti, 3, format1A, format1A, format1A, format0, format1A_size_bits, format1A_size_bytes, &dci_cnt, &format0_found, &format_c_found, &CCEmap0, &CCEmap1, &CCEmap2); if ((CCEmap0==0xffff)|| ((format0_found==1)&&(format_c_found==1))) return(dci_cnt); // Now check common search spaces at aggregation 8 (SI_RNTI and RA_RNTI and C-RNTI format 1C), // and UE_SPEC format0 (PUSCH) too while we're at it dci_decoding_procedure0(pdcch_vars,1,mode,nr_tti_rx, dci_alloc, eNB_id, ue->current_thread_id[nr_tti_rx], frame_parms, mi, ((ue->decode_SIB == 1) ? SI_RNTI : 0), ra_rnti, P_RNTI, 3, format1C, format1C, format1C, format1C, format1C_size_bits, format1C_size_bytes, &dci_cnt, &format0_found, &format_c_found, &CCEmap0, &CCEmap1, &CCEmap2); //#endif } if (ue->UE_mode[eNB_id] <= PRACH) return(dci_cnt); if (ue->prach_resources[eNB_id]) ra_rnti = ue->prach_resources[eNB_id]->ra_RNTI; // Now check UE_SPEC format0/1A ue_spec search spaces at aggregation 8 // printf("[DCI search] Format 0/1A aggregation 8\n"); dci_decoding_procedure0(pdcch_vars,0,mode, nr_tti_rx, dci_alloc, eNB_id, ue->current_thread_id[nr_tti_rx], frame_parms, mi, ((ue->decode_SIB == 1) ? SI_RNTI : 0), ra_rnti, P_RNTI, 0, format1A, format1A, format1A, format0, format0_size_bits, format0_size_bytes, &dci_cnt, &format0_found, &format_c_found, &CCEmap0, &CCEmap1, &CCEmap2); if ((CCEmap0==0xffff)|| ((format0_found==1)&&(format_c_found==1))) return(dci_cnt); //printf("[DCI search] Format 0 aggregation 1 dci_cnt %d\n",dci_cnt); if (dci_cnt == 0) { // Now check UE_SPEC format 0 search spaces at aggregation 4 dci_decoding_procedure0(pdcch_vars,0,mode, nr_tti_rx, dci_alloc, eNB_id, ue->current_thread_id[nr_tti_rx], frame_parms, mi, ((ue->decode_SIB == 1) ? SI_RNTI : 0), ra_rnti, P_RNTI, 1, format1A, format1A, format1A, format0, format0_size_bits, format0_size_bytes, &dci_cnt, &format0_found, &format_c_found, &CCEmap0, &CCEmap1, &CCEmap2); if ((CCEmap0==0xffff)|| ((format0_found==1)&&(format_c_found==1))) return(dci_cnt); //printf("[DCI search] Format 0 aggregation 2 dci_cnt %d\n",dci_cnt); } if (dci_cnt == 0) { // Now check UE_SPEC format 0 search spaces at aggregation 2 dci_decoding_procedure0(pdcch_vars,0,mode, nr_tti_rx, dci_alloc, eNB_id, ue->current_thread_id[nr_tti_rx], frame_parms, mi, ((ue->decode_SIB == 1) ? SI_RNTI : 0), ra_rnti, P_RNTI, 2, format1A, format1A, format1A, format0, format0_size_bits, format0_size_bytes, &dci_cnt, &format0_found, &format_c_found, &CCEmap0, &CCEmap1, &CCEmap2); if ((CCEmap0==0xffff)|| ((format0_found==1)&&(format_c_found==1))) return(dci_cnt); //printf("[DCI search] Format 0 aggregation 4 dci_cnt %d\n",dci_cnt); } if (dci_cnt == 0) { // Now check UE_SPEC format 0 search spaces at aggregation 1 dci_decoding_procedure0(pdcch_vars,0,mode, nr_tti_rx, dci_alloc, eNB_id, ue->current_thread_id[nr_tti_rx], frame_parms, mi, ((ue->decode_SIB == 1) ? SI_RNTI : 0), ra_rnti, P_RNTI, 3, format1A, format1A, format1A, format0, format0_size_bits, format0_size_bytes, &dci_cnt, &format0_found, &format_c_found, &CCEmap0, &CCEmap1, &CCEmap2); if ((CCEmap0==0xffff)|| ((format0_found==1)&&(format_c_found==1))) return(dci_cnt); //printf("[DCI search] Format 0 aggregation 8 dci_cnt %d\n",dci_cnt); } // These are for CRNTI based on transmission mode if ((tmode < 3) || (tmode == 7)) { // Now check UE_SPEC format 1 search spaces at aggregation 1 old_dci_cnt=dci_cnt; dci_decoding_procedure0(pdcch_vars,0,mode,nr_tti_rx, dci_alloc, eNB_id, ue->current_thread_id[nr_tti_rx], frame_parms, mi, ((ue->decode_SIB == 1) ? SI_RNTI : 0), ra_rnti, P_RNTI, 0, format1A, format1A, format1A, format1, format1_size_bits, format1_size_bytes, &dci_cnt, &format0_found, &format_c_found, &CCEmap0, &CCEmap1, &CCEmap2); //printf("[DCI search] Format 1 aggregation 1 dci_cnt %d\n",dci_cnt); if ((CCEmap0==0xffff) || (format_c_found==1)) return(dci_cnt); if (dci_cnt>old_dci_cnt) return(dci_cnt); // Now check UE_SPEC format 1 search spaces at aggregation 2 old_dci_cnt=dci_cnt; dci_decoding_procedure0(pdcch_vars,0,mode,nr_tti_rx, dci_alloc, eNB_id, ue->current_thread_id[nr_tti_rx], frame_parms, mi, ((ue->decode_SIB == 1) ? SI_RNTI : 0), ra_rnti, P_RNTI, 1, format1A, format1A, format1A, format1, format1_size_bits, format1_size_bytes, &dci_cnt, &format0_found, &format_c_found, &CCEmap0, &CCEmap1, &CCEmap2); //printf("[DCI search] Format 1 aggregation 2 dci_cnt %d\n",dci_cnt); if ((CCEmap0==0xffff)|| (format_c_found==1)) return(dci_cnt); if (dci_cnt>old_dci_cnt) return(dci_cnt); // Now check UE_SPEC format 1 search spaces at aggregation 4 old_dci_cnt=dci_cnt; dci_decoding_procedure0(pdcch_vars,0,mode,nr_tti_rx, dci_alloc, eNB_id, ue->current_thread_id[nr_tti_rx], frame_parms, mi, ((ue->decode_SIB == 1) ? SI_RNTI : 0), ra_rnti, P_RNTI, 2, format1A, format1A, format1A, format1, format1_size_bits, format1_size_bytes, &dci_cnt, &format0_found, &format_c_found, &CCEmap0, &CCEmap1, &CCEmap2); //printf("[DCI search] Format 1 aggregation 4 dci_cnt %d\n",dci_cnt); if ((CCEmap0==0xffff)|| ((format0_found==1)&&(format_c_found==1))) return(dci_cnt); if (dci_cnt>old_dci_cnt) return(dci_cnt); //#ifdef ALL_AGGREGATION // Now check UE_SPEC format 1 search spaces at aggregation 8 old_dci_cnt=dci_cnt; dci_decoding_procedure0(pdcch_vars,0,mode,nr_tti_rx, dci_alloc, eNB_id, ue->current_thread_id[nr_tti_rx], frame_parms, mi, ((ue->decode_SIB == 1) ? SI_RNTI : 0), ra_rnti, P_RNTI, 3, format1A, format1A, format1A, format1, format1_size_bits, format1_size_bytes, &dci_cnt, &format0_found, &format_c_found, &CCEmap0, &CCEmap1, &CCEmap2); //printf("[DCI search] Format 1 aggregation 8 dci_cnt %d\n",dci_cnt); if ((CCEmap0==0xffff)|| ((format0_found==1)&&(format_c_found==1))) return(dci_cnt); if (dci_cnt>old_dci_cnt) return(dci_cnt); //#endif //ALL_AGGREGATION } else if (tmode == 3) { LOG_D(PHY," Now check UE_SPEC format 2A_2A search aggregation 1 dci length: %d[bits] %d[bytes]\n",format2A_size_bits,format2A_size_bytes); // Now check UE_SPEC format 2A_2A search spaces at aggregation 1 old_dci_cnt=dci_cnt; dci_decoding_procedure0(pdcch_vars,0,mode, nr_tti_rx, dci_alloc, eNB_id, ue->current_thread_id[nr_tti_rx], frame_parms, mi, ((ue->decode_SIB == 1) ? SI_RNTI : 0), ra_rnti, P_RNTI, 0, format1A, format1A, format1A, format2A, format2A_size_bits, format2A_size_bytes, &dci_cnt, &format0_found, &format_c_found, &CCEmap0, &CCEmap1, &CCEmap2); LOG_D(PHY," format 2A_2A search CCEmap0 %x, format0_found %d, format_c_found %d \n", CCEmap0, format0_found, format_c_found); if ((CCEmap0==0xffff)|| ((format0_found==1)&&(format_c_found==1))) return(dci_cnt); LOG_D(PHY," format 2A_2A search dci_cnt %d, old_dci_cn t%d \n", dci_cnt, old_dci_cnt); if (dci_cnt>old_dci_cnt) return(dci_cnt); // Now check UE_SPEC format 2 search spaces at aggregation 2 LOG_D(PHY," Now check UE_SPEC format 2A_2A search aggregation 2 dci length: %d[bits] %d[bytes]\n",format2A_size_bits,format2A_size_bytes); old_dci_cnt=dci_cnt; dci_decoding_procedure0(pdcch_vars,0,mode, nr_tti_rx, dci_alloc, eNB_id, ue->current_thread_id[nr_tti_rx], frame_parms, mi, ((ue->decode_SIB == 1) ? SI_RNTI : 0), ra_rnti, P_RNTI, 1, format1A, format1A, format1A, format2A, format2A_size_bits, format2A_size_bytes, &dci_cnt, &format0_found, &format_c_found, &CCEmap0, &CCEmap1, &CCEmap2); if ((CCEmap0==0xffff)|| ((format0_found==1)&&(format_c_found==1))) return(dci_cnt); LOG_D(PHY," format 2A_2A search dci_cnt %d, old_dci_cn t%d \n", dci_cnt, old_dci_cnt); if (dci_cnt>old_dci_cnt) return(dci_cnt); // Now check UE_SPEC format 2_2A search spaces at aggregation 4 LOG_D(PHY," Now check UE_SPEC format 2_2A search spaces at aggregation 4 \n"); old_dci_cnt=dci_cnt; dci_decoding_procedure0(pdcch_vars,0,mode, nr_tti_rx, dci_alloc, eNB_id, ue->current_thread_id[nr_tti_rx], frame_parms, mi, ((ue->decode_SIB == 1) ? SI_RNTI : 0), ra_rnti, P_RNTI, 2, format1A, format1A, format1A, format2A, format2A_size_bits, format2A_size_bytes, &dci_cnt, &format0_found, &format_c_found, &CCEmap0, &CCEmap1, &CCEmap2); if ((CCEmap0==0xffff)|| ((format0_found==1)&&(format_c_found==1))) return(dci_cnt); LOG_D(PHY," format 2A_2A search dci_cnt %d, old_dci_cn t%d \n", dci_cnt, old_dci_cnt); if (dci_cnt>old_dci_cnt) return(dci_cnt); //#ifdef ALL_AGGREGATION // Now check UE_SPEC format 2_2A search spaces at aggregation 8 LOG_D(PHY," Now check UE_SPEC format 2_2A search spaces at aggregation 8 dci length: %d[bits] %d[bytes]\n",format2A_size_bits,format2A_size_bytes); old_dci_cnt=dci_cnt; dci_decoding_procedure0(pdcch_vars,0,mode, nr_tti_rx, dci_alloc, eNB_id, ue->current_thread_id[nr_tti_rx], frame_parms, mi, ((ue->decode_SIB == 1) ? SI_RNTI : 0), ra_rnti, P_RNTI, 3, format1A, format1A, format1A, format2A, format2A_size_bits, format2A_size_bytes, &dci_cnt, &format0_found, &format_c_found, &CCEmap0, &CCEmap1, &CCEmap2); //#endif if ((CCEmap0==0xffff)|| ((format0_found==1)&&(format_c_found==1))) return(dci_cnt); LOG_D(PHY," format 2A_2A search dci_cnt %d, old_dci_cn t%d \n", dci_cnt, old_dci_cnt); if (dci_cnt>old_dci_cnt) return(dci_cnt); } else if (tmode == 4) { // Now check UE_SPEC format 2_2A search spaces at aggregation 1 old_dci_cnt=dci_cnt; dci_decoding_procedure0(pdcch_vars,0,mode, nr_tti_rx, dci_alloc, eNB_id, ue->current_thread_id[nr_tti_rx], frame_parms, mi, ((ue->decode_SIB == 1) ? SI_RNTI : 0), ra_rnti, P_RNTI, 0, format1A, format1A, format1A, format2, format2_size_bits, format2_size_bytes, &dci_cnt, &format0_found, &format_c_found, &CCEmap0, &CCEmap1, &CCEmap2); if ((CCEmap0==0xffff)|| ((format0_found==1)&&(format_c_found==1))) return(dci_cnt); if (dci_cnt>old_dci_cnt) return(dci_cnt); // Now check UE_SPEC format 2 search spaces at aggregation 2 old_dci_cnt=dci_cnt; dci_decoding_procedure0(pdcch_vars,0,mode, nr_tti_rx, dci_alloc, eNB_id, ue->current_thread_id[nr_tti_rx], frame_parms, mi, ((ue->decode_SIB == 1) ? SI_RNTI : 0), ra_rnti, P_RNTI, 1, format1A, format1A, format1A, format2, format2_size_bits, format2_size_bytes, &dci_cnt, &format0_found, &format_c_found, &CCEmap0, &CCEmap1, &CCEmap2); if ((CCEmap0==0xffff)|| ((format0_found==1)&&(format_c_found==1))) return(dci_cnt); if (dci_cnt>old_dci_cnt) return(dci_cnt); // Now check UE_SPEC format 2_2A search spaces at aggregation 4 old_dci_cnt=dci_cnt; dci_decoding_procedure0(pdcch_vars,0,mode, nr_tti_rx, dci_alloc, eNB_id, ue->current_thread_id[nr_tti_rx], frame_parms, mi, ((ue->decode_SIB == 1) ? SI_RNTI : 0), ra_rnti, P_RNTI, 2, format1A, format1A, format1A, format2, format2_size_bits, format2_size_bytes, &dci_cnt, &format0_found, &format_c_found, &CCEmap0, &CCEmap1, &CCEmap2); if ((CCEmap0==0xffff)|| ((format0_found==1)&&(format_c_found==1))) return(dci_cnt); if (dci_cnt>old_dci_cnt) return(dci_cnt); //#ifdef ALL_AGGREGATION // Now check UE_SPEC format 2_2A search spaces at aggregation 8 old_dci_cnt=dci_cnt; dci_decoding_procedure0(pdcch_vars,0,mode, nr_tti_rx, dci_alloc, eNB_id, ue->current_thread_id[nr_tti_rx], frame_parms, mi, ((ue->decode_SIB == 1) ? SI_RNTI : 0), ra_rnti, P_RNTI, 3, format1A, format1A, format1A, format2, format2_size_bits, format2_size_bytes, &dci_cnt, &format0_found, &format_c_found, &CCEmap0, &CCEmap1, &CCEmap2); //#endif } else if ((tmode==5) || (tmode==6)) { // This is MU-MIMO // Now check UE_SPEC format 1E_2A_M10PRB search spaces aggregation 1 #ifdef DEBUG_DCI_DECODING LOG_I(PHY," MU-MIMO check UE_SPEC format 1E_2A_M10PRB\n"); #endif old_dci_cnt=dci_cnt; dci_decoding_procedure0(pdcch_vars,0,mode, nr_tti_rx, dci_alloc, eNB_id, ue->current_thread_id[nr_tti_rx], frame_parms, mi, ((ue->decode_SIB == 1) ? SI_RNTI : 0), ra_rnti, P_RNTI, 0, format1A, format1A, format1A, format1E_2A_M10PRB, sizeof_DCI1E_5MHz_2A_M10PRB_TDD_t, sizeof(DCI1E_5MHz_2A_M10PRB_TDD_t), &dci_cnt, &format0_found, &format_c_found, &CCEmap0, &CCEmap1, &CCEmap2); if ((CCEmap0==0xffff)|| ((format0_found==1)&&(format_c_found==1))) return(dci_cnt); if (dci_cnt>old_dci_cnt) return(dci_cnt); // Now check UE_SPEC format 1E_2A_M10PRB search spaces aggregation 2 old_dci_cnt=dci_cnt; dci_decoding_procedure0(pdcch_vars,0,mode, nr_tti_rx, dci_alloc, eNB_id, ue->current_thread_id[nr_tti_rx], frame_parms, mi, ((ue->decode_SIB == 1) ? SI_RNTI : 0), ra_rnti, P_RNTI, 1, format1A, format1A, format1A, format1E_2A_M10PRB, sizeof_DCI1E_5MHz_2A_M10PRB_TDD_t, sizeof(DCI1E_5MHz_2A_M10PRB_TDD_t), &dci_cnt, &format0_found, &format_c_found, &CCEmap0, &CCEmap1, &CCEmap2); if ((CCEmap0==0xffff)|| ((format0_found==1)&&(format_c_found==1))) return(dci_cnt); if (dci_cnt>old_dci_cnt) return(dci_cnt); // Now check UE_SPEC format 1E_2A_M10PRB search spaces aggregation 4 old_dci_cnt=dci_cnt; dci_decoding_procedure0(pdcch_vars,0,mode, nr_tti_rx, dci_alloc, eNB_id, ue->current_thread_id[nr_tti_rx], frame_parms, mi, ((ue->decode_SIB == 1) ? SI_RNTI : 0), ra_rnti, P_RNTI, 2, format1A, format1A, format1A, format1E_2A_M10PRB, sizeof_DCI1E_5MHz_2A_M10PRB_TDD_t, sizeof(DCI1E_5MHz_2A_M10PRB_TDD_t), &dci_cnt, &format0_found, &format_c_found, &CCEmap0, &CCEmap1, &CCEmap2); if ((CCEmap0==0xffff)|| ((format0_found==1)&&(format_c_found==1))) return(dci_cnt); if (dci_cnt>old_dci_cnt) return(dci_cnt); //#ifdef ALL_AGGREGATION // Now check UE_SPEC format 1E_2A_M10PRB search spaces at aggregation 8 old_dci_cnt=dci_cnt; dci_decoding_procedure0(pdcch_vars,0,mode, nr_tti_rx, dci_alloc, eNB_id, ue->current_thread_id[nr_tti_rx], frame_parms, mi, ((ue->decode_SIB == 1) ? SI_RNTI : 0), ra_rnti, P_RNTI, 3, format1A, format1A, format1A, format1E_2A_M10PRB, sizeof_DCI1E_5MHz_2A_M10PRB_TDD_t, sizeof(DCI1E_5MHz_2A_M10PRB_TDD_t), &dci_cnt, &format0_found, &format_c_found, &CCEmap0, &CCEmap1, &CCEmap2); if ((CCEmap0==0xffff)|| ((format0_found==1)&&(format_c_found==1))) return(dci_cnt); if (dci_cnt>old_dci_cnt) return(dci_cnt); //#endif //ALL_AGGREGATION } return(dci_cnt); } */ #ifdef PHY_ABSTRACTION uint16_t dci_decoding_procedure_emul(NR_UE_PDCCH **pdcch_vars, uint8_t num_ue_spec_dci, uint8_t num_common_dci, DCI_ALLOC_t *dci_alloc_tx, DCI_ALLOC_t *dci_alloc_rx, int16_t eNB_id) { uint8_t dci_cnt=0,i; memcpy(dci_alloc_rx,dci_alloc_tx,num_common_dci*sizeof(DCI_ALLOC_t)); dci_cnt = num_common_dci; LOG_D(PHY,"[DCI][EMUL] : num_common_dci %d\n",num_common_dci); for (i=num_common_dci; i<(num_ue_spec_dci+num_common_dci); i++) { LOG_D(PHY,"[DCI][EMUL] Checking dci %d => %x format %d (bit 0 %d)\n",i,pdcch_vars[eNB_id]->crnti,dci_alloc_tx[i].format, dci_alloc_tx[i].dci_pdu[0]&0x80); if (dci_alloc_tx[i].rnti == pdcch_vars[eNB_id]->crnti) { memcpy(dci_alloc_rx+dci_cnt,dci_alloc_tx+i,sizeof(DCI_ALLOC_t)); dci_cnt++; } } return(dci_cnt); } #endif