nr_dci.c 12.3 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
/*
 * 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/NR_TRANSPORT/nr_dci.c
23
* \brief Implements DCI encoding and PDCCH TX procedures (38.212/38.213/38.214). V15.4.0 2019-01.
24 25 26 27 28 29 30 31 32 33
* \author Guy De Souza
* \date 2018
* \version 0.1
* \company Eurecom
* \email: desouza@eurecom.fr
* \note
* \warning
*/

#include "nr_dci.h"
34
#include "nr_dlsch.h"
Khalid Ahmed's avatar
Khalid Ahmed committed
35
#include "nr_sch_dmrs.h"
36
#include "PHY/MODULATION/nr_modulation.h"
37

38
//#define DEBUG_PDCCH_DMRS
Raymond Knopp's avatar
Raymond Knopp committed
39 40
//#define DEBUG_DCI
//#define DEBUG_CHANNEL_CODING
41

42

yilmazt's avatar
yilmazt committed
43
uint16_t nr_get_dci_size(nfapi_nr_dci_format_e format,
44
                         nfapi_nr_rnti_type_e rnti_type,
45
                         uint16_t N_RB) {
yilmazt's avatar
yilmazt committed
46
  uint16_t size = 0;
47 48

  switch(format) {
49
    /*Only sizes for 0_0 and 1_0 are correct at the moment*/
Guy De Souza's avatar
Guy De Souza committed
50
    case NFAPI_NR_UL_DCI_FORMAT_0_0:
Guy De Souza's avatar
Guy De Souza committed
51 52
      /// fixed: Format identifier 1, Hop flag 1, MCS 5, NDI 1, RV 2, HARQ PID 4, PUSCH TPC 2 Time Domain assgnmt 4 --20
      size += 20;
53
      size += (uint8_t)ceil( log2( (N_RB*(N_RB+1))>>1 ) ); // Freq domain assignment -- hopping scenario to be updated
54
      size += nr_get_dci_size(NFAPI_NR_DL_DCI_FORMAT_1_0, rnti_type, N_RB) - size; // Padding to match 1_0 size
Guy De Souza's avatar
Guy De Souza committed
55
      // UL/SUL indicator assumed to be 0
56 57
      break;

Guy De Souza's avatar
Guy De Souza committed
58
    case NFAPI_NR_UL_DCI_FORMAT_0_1:
59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79
      /// fixed: Format identifier 1, MCS 5, NDI 1, RV 2, HARQ PID 4, PUSCH TPC 2, SRS request 2 --17
      size += 17;
      // Carrier indicator
      // UL/SUL indicator
      // BWP Indicator
      // Freq domain assignment
      // Time domain assignment
      // VRB to PRB mapping
      // Frequency Hopping flag
      // 1st DAI
      // 2nd DAI
      // SRS resource indicator
      // Precoding info and number of layers
      // Antenna ports
      // CSI request
      // CBGTI
      // PTRS - DMRS association
      // beta offset indicator
      // DMRS sequence init
      break;

Guy De Souza's avatar
Guy De Souza committed
80
    case NFAPI_NR_DL_DCI_FORMAT_1_0:
Guy De Souza's avatar
Guy De Souza committed
81 82
      /// fixed: Format identifier 1, VRB2PRB 1, MCS 5, NDI 1, RV 2, HARQ PID 4, DAI 2, PUCCH TPC 2, PUCCH RInd 3, PDSCH to HARQ TInd 3 Time Domain assgnmt 4 -- 28
      size += 28;
83
      size += (uint8_t)ceil( log2( (N_RB*(N_RB+1))>>1 ) ); // Freq domain assignment
84 85
      break;

Guy De Souza's avatar
Guy De Souza committed
86
    case NFAPI_NR_DL_DCI_FORMAT_1_1:
87 88 89 90 91 92 93 94 95
      // Carrier indicator
      size += 1; // Format identifier
      // BWP Indicator
      // Freq domain assignment
      // Time domain assignment
      // VRB to PRB mapping
      // PRB bundling size indicator
      // Rate matching indicator
      // ZP CSI-RS trigger
96
      /// TB1- MCS 5, NDI 1, RV 2
97 98 99 100 101 102 103 104 105 106 107 108 109 110 111
      size += 8;
      // TB2
      size += 4 ;  // HARQ PID
      // DAI
      size += 2; // TPC PUCCH
      size += 3; // PUCCH resource indicator
      size += 3; // PDSCH to HARQ timing indicator
      // Antenna ports
      // Tx Config Indication
      size += 2; // SRS request
      // CBGTI
      // CBGFI
      size += 1; // DMRS sequence init
      break;

Guy De Souza's avatar
Guy De Souza committed
112
    case NFAPI_NR_DL_DCI_FORMAT_2_0:
113 114
      break;

Guy De Souza's avatar
Guy De Souza committed
115
    case NFAPI_NR_DL_DCI_FORMAT_2_1:
116 117
      break;

Guy De Souza's avatar
Guy De Souza committed
118
    case NFAPI_NR_DL_DCI_FORMAT_2_2:
119 120
      break;

Guy De Souza's avatar
Guy De Souza committed
121
    case NFAPI_NR_DL_DCI_FORMAT_2_3:
122 123
      break;

124 125
    default:
      AssertFatal(1==0, "Invalid NR DCI format %d\n", format);
126 127 128 129 130
  }

  return size;
}

131
void nr_pdcch_scrambling(uint32_t *in,
132
                         uint32_t size,
133 134
                         uint32_t Nid,
                         uint32_t n_RNTI,
135
                         uint32_t *out) {
136 137 138 139
  uint8_t reset;
  uint32_t x1, x2, s=0;
  reset = 1;
  x2 = (n_RNTI<<16) + Nid;
140
  for (int i=0; i<size; i++) {
141 142 143
    if ((i&0x1f)==0) {
      s = lte_gold_generic(&x1, &x2, reset);
      reset = 0;
144 145 146 147

      if (i) {
        in++;
        out++;
148
      }
149
    }
150

Hongzhi's avatar
Hongzhi committed
151
    (*out) ^= ((((*in)>>(i&0x1f))&1) ^ ((s>>(i&0x1f))&1))<<(i&0x1f);
152
  }
153 154
}

155

Raymond Knopp's avatar
Raymond Knopp committed
156
uint8_t nr_generate_dci_top(nfapi_nr_dl_tti_pdcch_pdu *pdcch_pdu,
157
			    nfapi_nr_ul_dci_request_pdus_t    *ul_dci_pdu,
Guy De Souza's avatar
Guy De Souza committed
158
                            uint32_t **gold_pdcch_dmrs,
159
                            int32_t *txdataF,
Guy De Souza's avatar
Guy De Souza committed
160
                            int16_t amp,
161 162
                            NR_DL_FRAME_PARMS frame_parms) {

163
  int16_t mod_dmrs[NR_MAX_CSET_DURATION][NR_MAX_PDCCH_DMRS_LENGTH>>1]; // 3 for the max coreset duration
164 165
  uint16_t cset_start_sc;
  uint8_t cset_start_symb, cset_nsymb;
166
  int k,l,k_prime,dci_idx, dmrs_idx;
167
  /*First iteration: single DCI*/
168

169
  nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu_rel15=NULL;
170

171

172 173 174 175
  // find coreset descriptor
    
  int rb_offset;
  int n_rb;
176

177
  AssertFatal(pdcch_pdu!=NULL || ul_dci_pdu!=NULL,"At least one pointer has to be !NULL\n");
178 179
  AssertFatal(pdcch_pdu==NULL || ul_dci_pdu==NULL,"Can't handle both DL and UL DCI in same slot\n");

180

181 182 183
  if (pdcch_pdu) pdcch_pdu_rel15 = &pdcch_pdu->pdcch_pdu_rel15;
  else if (ul_dci_pdu) pdcch_pdu_rel15 = &ul_dci_pdu->pdcch_pdu.pdcch_pdu_rel15;

184
  get_coreset_rballoc(pdcch_pdu_rel15->FreqDomainResource,&n_rb,&rb_offset);
185

186
  // compute rb_offset and n_prb based on frequency allocation
187

188 189 190 191 192 193 194 195 196 197 198 199 200 201 202
  if (pdcch_pdu_rel15->CoreSetType == NFAPI_NR_CSET_CONFIG_MIB_SIB1) {
    cset_start_sc = frame_parms.first_carrier_offset + (frame_parms.ssb_start_subcarrier/NR_NB_SC_PER_RB +
							rb_offset)*NR_NB_SC_PER_RB;
  } else
    cset_start_sc = frame_parms.first_carrier_offset + rb_offset*NR_NB_SC_PER_RB;

  for (int d=0;d<pdcch_pdu_rel15->numDlDci;d++) {
    /*The coreset is initialised
     * in frequency: the first subcarrier is obtained by adding the first CRB overlapping the SSB and the rb_offset for coreset 0
     * or the rb_offset for other coresets
     * in time: by its first slot and its first symbol*/

    cset_start_symb = pdcch_pdu_rel15->StartSymbolIndex;
    cset_nsymb = pdcch_pdu_rel15->DurationSymbols;
    dci_idx = 0;
203
    LOG_D(PHY, "Coreset rb_offset %d, nb_rb %d\n",rb_offset,n_rb);
204 205
    LOG_D(PHY, "Coreset starting subcarrier %d on symbol %d (%d symbols)\n", cset_start_sc, cset_start_symb, cset_nsymb);
    // DMRS length is per OFDM symbol
206 207 208
    AssertFatal(pdcch_pdu_rel15->CceRegMappingType == NFAPI_NR_CCE_REG_MAPPING_NON_INTERLEAVED,
		"Interleaved CCE REG MAPPING not supported\n");
    uint32_t dmrs_length = (pdcch_pdu_rel15->CceRegMappingType == NFAPI_NR_CCE_REG_MAPPING_NON_INTERLEAVED)?
209 210
      (n_rb*6) : (pdcch_pdu_rel15->AggregationLevel[d]*36/cset_nsymb); //2(QPSK)*3(per RB)*6(REG per CCE)
    uint32_t encoded_length = pdcch_pdu_rel15->AggregationLevel[d]*108; //2(QPSK)*9(per RB)*6(REG per CCE)
211
    LOG_D(PHY, "DMRS length per symbol %d\t DCI encoded length %d (precoder_granularity %d,reg_mapping %d)\n", dmrs_length, encoded_length,pdcch_pdu_rel15->precoderGranularity,pdcch_pdu_rel15->CceRegMappingType);
212 213 214 215 216 217 218 219 220 221 222 223 224
    dmrs_length += rb_offset*6; // To accommodate more DMRS symbols in case of rb offset
      
    /// DMRS QPSK modulation
    for (int symb=cset_start_symb; symb<cset_start_symb + pdcch_pdu_rel15->DurationSymbols; symb++) {
      
      nr_modulation(gold_pdcch_dmrs[symb], dmrs_length, DMRS_MOD_ORDER, mod_dmrs[symb]); //Qm = 2 as DMRS is QPSK modulated
      
#ifdef DEBUG_PDCCH_DMRS
      
      for (int i=0; i<dmrs_length>>1; i++)
	printf("symb %d i %d gold seq 0x%08x mod_dmrs %d %d\n", symb, i,
	       gold_pdcch_dmrs[symb][i>>5], mod_dmrs[symb][i<<1], mod_dmrs[symb][(i<<1)+1] );
      
225
#endif
226 227 228 229 230 231 232 233 234
    }
    
    /// DCI payload processing
    // CRC attachment + Scrambling + Channel coding + Rate matching
    uint32_t encoder_output[NR_MAX_DCI_SIZE_DWORD];
    uint16_t n_RNTI = pdcch_pdu_rel15->RNTI[d];
    uint16_t Nid    = pdcch_pdu_rel15->ScramblingId[d];
    t_nrPolar_params *currentPtr = nr_polar_params(NR_POLAR_DCI_MESSAGE_TYPE, 
						   pdcch_pdu_rel15->PayloadSizeBits[d], 
Raymond Knopp's avatar
Raymond Knopp committed
235
						   pdcch_pdu_rel15->AggregationLevel[d],
236 237
						   0,NULL);
    polar_encoder_fast((uint64_t*)pdcch_pdu_rel15->Payload[d], encoder_output, n_RNTI,1,currentPtr);
Guy De Souza's avatar
Guy De Souza committed
238
#ifdef DEBUG_CHANNEL_CODING
239
    printf("polar rnti %x,length %d, L %d\n",n_RNTI, pdcch_pdu_rel15->PayloadSizeBits[d],pdcch_pdu_rel15->AggregationLevel[d]);
240
    printf("DCI PDU: [0]->0x%lx \t [1]->0x%lx\n",
241
	   ((uint64_t*)pdcch_pdu_rel15->Payload[d])[0], ((uint64_t*)pdcch_pdu_rel15->Payload[d])[1]);
242 243 244
    printf("Encoded Payload (length:%d dwords):\n", encoded_length>>5);
    
    for (int i=0; i<encoded_length>>5; i++)
245 246
      printf("[%d]->0x%08x \t", i,encoder_output[i]);    

247
    printf("\n");
Guy De Souza's avatar
Guy De Souza committed
248
#endif
249 250 251
    /// Scrambling
    uint32_t scrambled_output[NR_MAX_DCI_SIZE_DWORD]= {0};
    nr_pdcch_scrambling(encoder_output, encoded_length, Nid, n_RNTI, scrambled_output);
Hongzhi's avatar
Hongzhi committed
252
#ifdef DEBUG_CHANNEL_CODING
253
    printf("scrambled output: [0]->0x%08x \t [1]->0x%08x \t [2]->0x%08x \t [3]->0x%08x\t [4]->0x%08x\t [5]->0x%08x\t \
Hongzhi's avatar
Hongzhi committed
254
[6]->0x%08x \t [7]->0x%08x \t [8]->0x%08x \t [9]->0x%08x\t [10]->0x%08x\t [11]->0x%08x\n",
255 256
	   scrambled_output[0], scrambled_output[1], scrambled_output[2], scrambled_output[3], scrambled_output[4],scrambled_output[5],
	   scrambled_output[6], scrambled_output[7], scrambled_output[8], scrambled_output[9], scrambled_output[10],scrambled_output[11] );
Hongzhi's avatar
Hongzhi committed
257
#endif
258 259 260
    /// QPSK modulation
    int16_t mod_dci[NR_MAX_DCI_SIZE>>1];
    nr_modulation(scrambled_output, encoded_length, DMRS_MOD_ORDER, mod_dci); //Qm = 2 as DMRS is QPSK modulated
Guy De Souza's avatar
Guy De Souza committed
261
#ifdef DEBUG_DCI
262 263 264 265
    
    for (int i=0; i<encoded_length>>1; i++)
      printf("i %d mod_dci %d %d\n", i, mod_dci[i<<1], mod_dci[(i<<1)+1] );
    
Guy De Souza's avatar
Guy De Souza committed
266
#endif
267 268 269 270 271 272 273 274
    
    /// Resource mapping
    
    if (cset_start_sc >= frame_parms.ofdm_symbol_size)
      cset_start_sc -= frame_parms.ofdm_symbol_size;
    
    /*Reorder REG list for a freq first mapping*/
    uint8_t nb_regs = pdcch_pdu_rel15->AggregationLevel[d]*NR_NB_REG_PER_CCE;
275
    uint8_t reg_idx0 = pdcch_pdu_rel15->CceIndex[d]*NR_NB_REG_PER_CCE;
276

277
    /*Mapping the encoded DCI along with the DMRS */
278
    for (int reg_idx=reg_idx0; reg_idx<(nb_regs+reg_idx0); reg_idx++) {
279
      k = cset_start_sc + (12*reg_idx/cset_nsymb);
280 281 282 283
      
      if (k >= frame_parms.ofdm_symbol_size)
	k -= frame_parms.ofdm_symbol_size;
      
284
      l = cset_start_symb + ((reg_idx/cset_nsymb)%cset_nsymb);
285 286 287
      
      // dmrs index depends on reference point for k according to 38.211 7.4.1.3.2
      if (pdcch_pdu_rel15->CoreSetType == NFAPI_NR_CSET_CONFIG_PDCCH_CONFIG)
288
	dmrs_idx = (reg_idx/cset_nsymb)*3;
289
      else
290
	dmrs_idx = ((reg_idx/cset_nsymb)+rb_offset)*3;
291 292 293 294 295
      
      k_prime = 0;
      
      for (int m=0; m<NR_NB_SC_PER_RB; m++) {
	if ( m == (k_prime<<2)+1) { // DMRS if not already mapped
296 297 298
	  if (pdcch_pdu_rel15->CceRegMappingType == NFAPI_NR_CCE_REG_MAPPING_NON_INTERLEAVED) {
	    ((int16_t *)txdataF)[(l*frame_parms.ofdm_symbol_size + k)<<1]       = (2*amp * mod_dmrs[l][dmrs_idx<<1]) >> 15;
	    ((int16_t *)txdataF)[((l*frame_parms.ofdm_symbol_size + k)<<1) + 1] = (2*amp * mod_dmrs[l][(dmrs_idx<<1) + 1]) >> 15;
299
#ifdef DEBUG_PDCCH_DMRS
300
	    printf("PDCCH DMRS: l %d position %d => (%d,%d)\n",l,k,((int16_t *)txdataF)[(l*frame_parms.ofdm_symbol_size + k)<<1],
301
		   ((int16_t *)txdataF)[((l*frame_parms.ofdm_symbol_size + k)<<1)+1]);
302
#endif
303 304 305 306 307 308 309
	    dmrs_idx++;
	  }
	  
	  k_prime++;
	} else { // DCI payload
	  ((int16_t *)txdataF)[(l*frame_parms.ofdm_symbol_size + k)<<1]       = (amp * mod_dci[dci_idx<<1]) >> 15;
	  ((int16_t *)txdataF)[((l*frame_parms.ofdm_symbol_size + k)<<1) + 1] = (amp * mod_dci[(dci_idx<<1) + 1]) >> 15;
310
#ifdef DEBUG_DCI
311
	  printf("PDCCH: l %d position %d => (%d,%d)\n",l,k,((int16_t *)txdataF)[(l*frame_parms.ofdm_symbol_size + k)<<1],
312
		 ((int16_t *)txdataF)[((l*frame_parms.ofdm_symbol_size + k)<<1)+1]);
313
#endif
314 315 316 317 318 319 320 321 322 323
	  dci_idx++;
	}
	
	k++;
	
	if (k >= frame_parms.ofdm_symbol_size)
	  k -= frame_parms.ofdm_symbol_size;
      } // m
    } // reg_idx
  } // for (int d=0;d<pdcch_pdu_rel15->numDlDci;d++)
324 325
  return 0;
}
326