/* * 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 "nr_transport_proto_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/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 #ifdef NR_PDCCH_DCI_DEBUG #define LOG_DNL(a, ...) printf("\n\t\t<-NR_PDCCH_DCI_DEBUG (%s)-> " a, __func__, ##__VA_ARGS__ ) #define LOG_DD(a, ...) printf("\t<-NR_PDCCH_DCI_DEBUG (%s)-> " a, __func__, ##__VA_ARGS__ ) #define LOG_DDD(a, ...) printf("\t\t<-NR_PDCCH_DCI_DEBUG (%s)-> " a, __func__, ##__VA_ARGS__ ) #else #define LOG_DNL(a...) #define LOG_DD(a...) #define LOG_DDD(a...) #endif #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 #ifdef LOG_I #undef LOG_I #define LOG_I(A,B...) printf(B) #endif #ifdef NR_PDCCH_DCI_RUN //static const int16_t conjugate[8]__attribute__((aligned(32))) = {-1,1,-1,1,-1,1,-1,1}; void nr_pdcch_demapping_deinterleaving(uint32_t *llr, uint32_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=0,f_reg=0; uint32_t coreset_C=0; 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; LOG_DNL("[r=%d,c=%d] bundle_j(%d) interleaved at f_bundle_j(%d)\n",r,c,bundle_j,f_bundle_j); } f_reg = (f_bundle_j*reg_bundle_size_L)+(reg%reg_bundle_size_L); index_z = 9*reg; 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]; LOG_DDD("[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),*(int16_t *) &z[index_z + i],*(1 + (int16_t *) &z[index_z + i]), f_reg,f_bundle_j,(index_llr + i),*(int16_t *) &llr[index_llr + i], *(1 + (int16_t *) &llr[index_llr + i])); } if ((reg%reg_bundle_size_L) == 0) r++; } } #endif #ifdef NR_PDCCH_DCI_RUN int32_t nr_pdcch_llr(NR_DL_FRAME_PARMS *frame_parms, int32_t **rxdataF_comp, int16_t *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; int16_t *pdcch_llrp; pdcch_llrp = &pdcch_llr[2 * symbol * coreset_nbr_rb * 9]; if (!pdcch_llrp) { LOG_E(PHY,"pdcch_qpsk_llr: llr is null, symbol %d\n", symbol); return (-1); } LOG_DDD("llr logs: pdcch qpsk llr for symbol %d (pos %d), llr offset %ld\n",symbol,(symbol*frame_parms->N_RB_DL*12),pdcch_llrp-pdcch_llr); //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_llrp = 31; else if (*rxF < -32) *pdcch_llrp = -32; else *pdcch_llrp = (*rxF); LOG_DDD("llr logs: rb=%d i=%d *rxF:%d => *pdcch_llrp:%d\n",i/18,i,*rxF,*pdcch_llrp); rxF++; pdcch_llrp++; } 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) { LOG_E(PHY,"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 aarx; #if defined(__x86_64__) || defined(__i386__) __m128i *dl_ch128; __m128i avg128P; #elif defined(__arm__) int16x8_t *dl_ch128; int32x4_t *avg128P; #endif 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[aarx][0]; #elif defined(__arm__) #endif for (rb=0; rb<(nb_rb*3)>>2; 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 // for (int i=0;i<24;i+=2) printf("pdcch channel re %d (%d,%d)\n",(rb*12)+(i>>1),((int16_t*)dl_ch128)[i],((int16_t*)dl_ch128)[i+1]); 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[aarx] = (((int32_t *)&avg128P)[0] + ((int32_t *)&avg128P)[1] + ((int32_t *)&avg128P)[2] + ((int32_t *)&avg128P)[3])/(nb_rb*9); // 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 #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, 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; uint8_t i, j, aarx, bitcnt_coreset_freq_dom=0; int32_t *dl_ch0, *dl_ch0_ext, *rxF, *rxF_ext; c_rb = n_BWP_start; // c_rb is the common resource block: RB within the BWP #ifdef DEBUG_DCI_DECODING uint8_t symbol_mod = (symbol >= (7 - frame_parms->Ncp)) ? symbol - (7 - frame_parms->Ncp) : symbol; 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))]; LOG_DDD("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))); } else { dl_ch0 = &dl_ch_estimates[aarx][0]; LOG_DDD("dl_ch0 = &dl_ch_estimates[aarx = (%d)][0]\n",aarx); } dl_ch0_ext = &dl_ch_estimates_ext[aarx][symbol * (coreset_nbr_rb * NBR_RE_PER_RB_WITH_DMRS)]; LOG_DDD("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)); rxF_ext = &rxdataF_ext[aarx][symbol * (coreset_nbr_rb * NBR_RE_PER_RB_WITH_DMRS)]; LOG_DDD("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)); LOG_DDD("(for symbol=%d, aarx=%d), symbol_mod=%d, nushiftmod3=%d \n", symbol,aarx, (symbol >= (7 - frame_parms->Ncp)) ? symbol - (7 - frame_parms->Ncp) : symbol, frame_parms->nushift % 3); /* * 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 */ LOG_DDD("n_BWP_start=%d, coreset_nbr_rb=%d\n",n_BWP_start,coreset_nbr_rb); 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 - (n_BWP_start/BIT_TO_NBR_RB_CORESET_FREQ_DOMAIN) - 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 ++; LOG_DDD("we entered here as coreset_freq_dom=%lx (bit %d) is 0, coreset_freq_domain is discontiguous\n",coreset_freq_dom, (46 - bitcnt_coreset_freq_dom)); } } //c_rb = c_rb + c_rb_tmp; LOG_DDD("c_rb=%d\n",c_rb); rxF=NULL; // 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)))]; LOG_DDD("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)))); } 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 LOG_DDD("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)))); //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 // LOG_DDD("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)))]; LOG_DDD("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)))); } 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 LOG_DDD("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)))); } 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)))]; LOG_DDD("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)))); /*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 LOG_DDD("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 LOG_DDD("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))); 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]; LOG_DDD("RB[c_rb %d] \t RE[re %d] => rxF_ext[%d]=(%d,%d)\t rxF[%d]=(%d,%d)\n", c_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]; //LOG_DDD("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 { LOG_DDD("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])); } } 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 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 aarx; #if defined(__x86_64__) || defined(__i386__) __m128i mmtmpP0,mmtmpP1,mmtmpP2,mmtmpP3; #elif defined(__arm__) int16x8_t mmtmpP0,mmtmpP1,mmtmpP2,mmtmpP3; #endif #if defined(__x86_64__) || defined(__i386__) __m128i *dl_ch128,*rxdataF128,*rxdataF_comp128; #elif defined(__arm__) #endif 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*coreset_nbr_rb*12]; rxdataF128 = (__m128i *)&rxdataF_ext[aarx][symbol*coreset_nbr_rb*12]; rxdataF_comp128 = (__m128i *)&rxdataF_comp[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*3)>>2; 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); for (int i=0; i<12 ; i++) LOG_DDD("rxdataF128[%d]=(%d,%d) X dlch[%d]=(%d,%d) rxdataF_comp128[%d]=(%d,%d)\n", (rb*12)+i, ((short *)rxdataF128)[i<<1],((short *)rxdataF128)[1+(i<<1)], (rb*12)+i, ((short *)dl_ch128)[i<<1],((short *)dl_ch128)[1+(i<<1)], (rb*12)+i, ((short *)rxdataF_comp128)[i<<1],((short *)rxdataF_comp128)[1+(i<<1)]); 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_detection_mrc(NR_DL_FRAME_PARMS *frame_parms, int32_t **rxdataF_comp, uint8_t symbol) { #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) { #if defined(__x86_64__) || defined(__i386__) rxdataF_comp128_0 = (__m128i *)&rxdataF_comp[0][symbol*frame_parms->N_RB_DL*12]; rxdataF_comp128_1 = (__m128i *)&rxdataF_comp[1][symbol*frame_parms->N_RB_DL*12]; #elif defined(__arm__) rxdataF_comp128_0 = (int16x8_t *)&rxdataF_comp[0][symbol*frame_parms->N_RB_DL*12]; rxdataF_comp128_1 = (int16x8_t *)&rxdataF_comp[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++; } } } #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) { 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, aarx; int32_t avgs; int32_t avgP[4]; // 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/*+(int)floor(frame_parms->ssb_start_subcarrier/NR_NB_SC_PER_RB)*/; // 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; } } LOG_DD("symbol_mon=(%d) and start_symbol=(%d)\n",symbol_mon,start_symbol); LOG_DD("coreset_freq_dom=(%ld) n_rb_offset=(%d) coreset_time_dur=(%d) n_shift=(%d) reg_bundle_size_L=(%d) coreset_interleaver_size_R=(%d) scrambling_ID=(%d) \n", coreset_freq_dom,n_rb_offset,coreset_time_dur,n_shift,reg_bundle_size_L,coreset_interleaver_size_R,pdcch_DMRS_scrambling_id); // // 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) 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 LOG_DD("coreset_freq_dom=(%ld)\n",coreset_freq_dom); 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 LOG_DD("coreset_freq_dom=(%ld,%lx), coreset_nbr_rb=%d\n", coreset_freq_dom,coreset_freq_dom,coreset_nbr_rb); LOG_DD("coreset_nbr_rb=%d, coreset_nbr_reg=%d, coreset_C=(%d/(%d*%d))=%d\n", coreset_nbr_rb, coreset_time_dur * coreset_nbr_rb, coreset_time_dur * coreset_nbr_rb, reg_bundle_size_L,coreset_interleaver_size_R, (uint32_t)((coreset_time_dur * coreset_nbr_rb) / (reg_bundle_size_L * coreset_interleaver_size_R)) ); for (int s = start_symbol; s < (start_symbol + coreset_time_dur); s++) { LOG_DD("we enter nr_pdcch_extract_rbs_single(is_secondary_ue=%d) to remove DM-RS PDCCH\n", is_secondary_ue); LOG_DD("in nr_pdcch_extract_rbs_single(rxdataF -> rxdataF_ext || dl_ch_estimates -> dl_ch_estimates_ext)\n"); nr_pdcch_extract_rbs_single(common_vars->common_vars_rx_data_per_thread[ue->current_thread_id[nr_tti_rx]].rxdataF, pdcch_vars[eNB_id]->dl_ch_estimates, 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); LOG_DD("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); LOG_DD("in pdcch_channel_level(dl_ch_estimates_ext -> dl_ch_estimates_ext)\n"); // 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 (aarx = 0; aarx < frame_parms->nb_antennas_rx; aarx++) avgs = cmax(avgs, avgP[aarx]); 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 LOG_DD("we enter nr_pdcch_channel_compensation(log2_maxh=%d)\n",log2_maxh); LOG_DD("in nr_pdcch_channel_compensation(rxdataF_ext x dl_ch_estimates_ext -> rxdataF_comp)\n"); // 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, NULL, frame_parms, s, log2_maxh, coreset_nbr_rb); // 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 if (frame_parms->nb_antennas_rx > 1) { LOG_DD("we enter pdcch_detection_mrc(frame_parms->nb_antennas_rx=%d)\n", frame_parms->nb_antennas_rx); pdcch_detection_mrc(frame_parms, pdcch_vars[eNB_id]->rxdataF_comp,s); } LOG_DD("we enter nr_pdcch_llr(for symbol %d), pdcch_vars[eNB_id]->rxdataF_comp ---> pdcch_vars[eNB_id]->llr \n",s); LOG_DD("in nr_pdcch_llr(rxdataF_comp -> llr)\n"); nr_pdcch_llr(frame_parms, pdcch_vars[eNB_id]->rxdataF_comp, pdcch_vars[eNB_id]->llr, s, coreset_nbr_rb); #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 } LOG_DD("we enter nr_pdcch_demapping_deinterleaving()\n"); nr_pdcch_demapping_deinterleaving((uint32_t *) pdcch_vars[eNB_id]->llr, (uint32_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); nr_pdcch_unscrambling(pdcch_vars[eNB_id]->crnti, frame_parms, nr_tti_rx, 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); LOG_DD("we end nr_pdcch_unscrambling()\n"); LOG_DD("Ending nr_rx_pdcch() function\n"); 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, int16_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); //mod 2^31 is implicit //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 //LOG_DDD(" (c_init=%d, n_id=%d, n_rnti=%d, length=%d)\n",x2,n_id,n_rnti,length); for (i = 0; i < length; i++) { if ((i & 0x1f) == 0) { s = lte_gold_generic(&x1, &x2, reset); //LOG_DDD("lte_gold[%d]=%x\n",i,s); reset = 0; } /* #ifdef NR_PDCCH_DCI_DEBUG if (i%2 == 0) LOG_DDD(" unscrambling %d : scrambled_z=%d, => ", i,*(char*) &z[(int)floor(i/2)]); if (i%2 == 1) LOG_DDD(" 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]; #ifdef 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 */ LOG_DDD(" unscrambling %d : scrambled_z=%d, => ", i,z[i]); if (((s >> (i % 32)) & 1) == 1) z[i] = -z[i]; LOG_DDD("unscrambled_z=%d\n",z[i]); } } #endif #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, //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) { uint32_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; uint32_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; LOG_DDD("format_found is %d \n", *format_found); //if (mode == NO_DCI) { // #ifdef NR_PDCCH_DCI_DEBUG // LOG_DDD("skip DCI decoding: expect no DCIs at nr_tti_rx %d in current searchSpace\n", nr_tti_rx); // #endif // return; //} LOG_DDD("frequencyDomainResources=%lx, duration=%d\n", pdcch_vars[eNB_id]->coreset[p].frequencyDomainResources, pdcch_vars[eNB_id]->coreset[p].duration); // 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) LOG_DDD("nCCE[%d]=%d\n",p,nCCE[p]); /* 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) LOG_DDD("we are in common searchSpace and nb_candidates=%u for L2=%d\n", nb_candidates, L2); } } 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; } LOG_DDD("L2(%d) | nCCE[%d](%d) | Yk(%u) | nb_candidates(%u)\n", L2, p, nCCE[p], Yk, nb_candidates); /* 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 if(0 <= L && L < 4) LOG_DDD("m_max_slot_pdcch_Table10_1_2(%d)=%d\n",L,m_max_slot_pdcch_Table10_1_2[L]); for (m = 0; m < nb_candidates; m++) { int n_ci = 0; if (nCCE[p] < L2) return; LOG_DDD("debug1(%d)=nCCE[p]/L2 | nCCE[%d](%d) | L2(%d)\n",nCCE[p] / L2,p,nCCE[p],L2); LOG_DDD("debug2(%d)=L2*m_p_s_L_max | L2(%d) | m_p_s_L_max(%d)\n",L2*m_p_s_L_max,L2,m_p_s_L_max); CCEind = (((Yk + (uint16_t)(floor((m*nCCE[p])/(L2*m_p_s_L_max))) + n_ci) % (uint16_t)(floor(nCCE[p] / L2))) * L2); LOG_DDD("CCEind(%d) = (((Yk(%u) + ((m(%u)*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); LOG_DDD("n_candidate(m)=%u | CCEind=%d |",m,CCEind); if (CCEind < 32) CCEmap = CCEmap0; else if (CCEind < 64) CCEmap = CCEmap1; else if (CCEind < 96) CCEmap = CCEmap2; else AssertFatal(1==0,"Illegal CCEind %d (Yk %u, m %u, nCCE %d, L2 %d\n", CCEind, Yk, m, nCCE[p], L2); 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 LOG_DDD("CCEmap_cand=%u \n",CCEmap_cand); 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_uss); #endif LOG_DDD("... we enter function dci_decoding(sizeof_bits=%d L=%d) -----\n",sizeof_bits,L); LOG_DDD("... we have to replace this part of the code by polar decoding\n"); // for (int m=0; m < (nCCE[p]*6*9*2); m++) LOG_DDD("(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); /* int reg_p=0,reg_e=0; 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)]); } } #ifdef 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++){2 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++) LOG_DDD("polar_hex[%d]=%x\n",j,polar_hex[j]); #endif */ uint64_t dci_estimation[2]= {0}; const t_nrPolar_params *currentPtrDCI=nr_polar_params(1, sizeof_bits, L2); decoderState = polar_decoder_int16(&pdcch_vars[eNB_id]->e_rx[CCEind*9*6*2], dci_estimation, 1, currentPtrDCI); crc = decoderState; //crc = (crc16(&dci_decoded_output[current_thread_id][0], sizeof_bits) >> 16) ^ extract_crc(&dci_decoded_output[current_thread_id][0], sizeof_bits); LOG_DDD("... we end function dci_decoding() with crc=%x\n",crc); LOG_DDD("... we have to replace this part of the code by polar decoding\n"); #ifdef DEBUG_DCI_DECODING LOG_DDD("(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 LOG_DDD("format_found=%d\n",*format_found); LOG_DDD("crc_scrambled=%d\n",*crc_scrambled); 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; } 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; } LOG_DDD("format_found=%d\n",*format_found); LOG_DDD("crc_scrambled=%d\n",*crc_scrambled); 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; memcpy(&dci_alloc[*dci_cnt].dci_pdu[0],dci_estimation,8); LOG_DDD("rnti matches -> DCI FOUND !!! crc =>0x%x, sizeof_bits %d, sizeof_bytes %d \n", dci_alloc[*dci_cnt].rnti, dci_alloc[*dci_cnt].dci_length, sizeof_bytes); LOG_DDD("dci_cnt %d (format_css %d crc_scrambled %d) L %d, firstCCE %d pdu[0] 0x%lx pdu[1] 0x%lx \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]); 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; // LOG_DDD("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; // LOG_DDD("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; // LOG_DDD("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; *format_found=_format_2_0_found; } if (format_css == cformat2_1) { dci_alloc[*dci_cnt].format = format2_1; *dci_cnt = *dci_cnt + 1; *format_found=_format_2_1_found; } if (format_css == cformat2_2) { dci_alloc[*dci_cnt].format = format2_2; *dci_cnt = *dci_cnt + 1; *format_found=_format_2_2_found; } if (format_css == cformat2_3) { dci_alloc[*dci_cnt].format = format2_3; *dci_cnt = *dci_cnt + 1; *format_found=_format_2_3_found; } 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 %d in CCE %d (CCEmap %x) candidate %d / %d \n", *dci_cnt,crc,1<<L,sizeof_bits,dci_alloc[*dci_cnt-1].format,CCEind,*CCEmap,m,nb_candidates ); // nr_extract_dci_into( // 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 LOG_DDD("end candidate loop\n"); } #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 LOG_DDD("\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) { LOG_DDD("crc_scrambled=%d, n_RB_ULBWP=%d, n_RB_DLBWP=%d\n",crc_scrambled,n_RB_ULBWP,n_RB_DLBWP); /* * 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 = ((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 = ((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=0,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=0,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 // LOG_DDD("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 //} } LOG_DDD("(nr_dci_format_size) dci_size[%d]=%d for n_RB_ULBWP=%d\n", i,dci_size[i],n_RB_ULBWP); } LOG_DDD("(nr_dci_format_size) dci_fields_sizes[][] = { \n"); #ifdef NR_PDCCH_DCI_DEBUG 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 LOG_DNL("(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]); //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]; LOG_DDD("(nr_dci_format_size) new dci_size[format0_0]=%d\n",dci_size[0]); //} } // 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]; LOG_DDD("(nr_dci_format_size) new dci_size[format0_0]=%d\n",dci_size[0]); //} } /* * 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!!! * */ // } LOG_DDD("(nr_dci_format_size) dci_fields_sizes[][] = { \n"); #ifdef NR_PDCCH_DCI_DEBUG 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], LOG_DD("(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); 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=0; 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; //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); LOG_DD("searSpaceType=%d\n",do_common); LOG_DD("%s_dci_format=%d\n",do_common?"uss":"css",css_dci_format); // 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); LOG_DD("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); 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 LOG_DD("common searchSpaces with format css_dci_format=%d and aggregation_level=%d\n", css_dci_format,(1<<aggregationLevel)); 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, 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); LOG_DD("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); for (int aggregationLevelSFI = 0; aggregationLevelSFI<5 ; aggregationLevelSFI++) { LOG_DD("common searchSpaces with format css_dci_format=%d and aggregation_level=%d\n", css_dci_format,(1<<aggregationLevelSFI)); // 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, 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); LOG_DD("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); for (int aggregationLevel = 0; aggregationLevel<5 ; aggregationLevel++) { LOG_DD("common searchSpaces with format css_dci_format=%d and aggregation_level=%d\n", css_dci_format,(1<<aggregationLevel)); // 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, 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); LOG_DD("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); for (int aggregationLevel = 0; aggregationLevel<5 ; aggregationLevel++) { LOG_DD("common searchSpaces with format css_dci_format=%d and aggregation_level=%d\n", css_dci_format,(1<<aggregationLevel)); // 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, 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); LOG_DD("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); for (int aggregationLevel = 0; aggregationLevel<5 ; aggregationLevel++) { LOG_DD("common searchSpaces with format css_dci_format=%d and aggregation_level=%d\n", css_dci_format,(1<<aggregationLevel)); // 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, 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); LOG_DD("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); 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 LOG_DD("common searchSpaces with format css_dci_format=%d and aggregation_level=%d\n", css_dci_format,(1<<aggregationLevel)); 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, 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); LOG_DD("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); 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 LOG_DD("common searchSpaces with format css_dci_format=%d and aggregation_level=%d\n", css_dci_format,(1<<aggregationLevel)); 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, 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_; LOG_DD("at the end crc_scrambled=%d and format_found=%d\n",*crc_scrambled,*format_found); LOG_DD("at the end dci_cnt=%d \n",dci_cnt); return(dci_cnt); } #endif