nr_dci.c 13.9 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"
35

36
//#define DEBUG_PDCCH_DMRS
Florian Kaltenberger's avatar
Florian Kaltenberger committed
37 38
//#define DEBUG_DCI
//#define DEBUG_CHANNEL_CODING
39

40

41 42
extern short nr_mod_table[NR_MOD_TABLE_SIZE_SHORT];

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

  switch(format) {
50
    /*Only sizes for 0_0 and 1_0 are correct at the moment*/
Guy De Souza's avatar
Guy De Souza committed
51
    case NFAPI_NR_UL_DCI_FORMAT_0_0:
Guy De Souza's avatar
Guy De Souza committed
52 53
      /// 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;
54
      size += (uint8_t)ceil( log2( (N_RB*(N_RB+1))>>1 ) ); // Freq domain assignment -- hopping scenario to be updated
Guy De Souza's avatar
Guy De Souza committed
55
      size += nr_get_dci_size(NFAPI_NR_DL_DCI_FORMAT_1_0, rnti_type, N_RB, config) - size; // Padding to match 1_0 size
Guy De Souza's avatar
Guy De Souza committed
56
      // UL/SUL indicator assumed to be 0
57 58
      break;

Guy De Souza's avatar
Guy De Souza committed
59
    case NFAPI_NR_UL_DCI_FORMAT_0_1:
60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80
      /// 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
81
    case NFAPI_NR_DL_DCI_FORMAT_1_0:
Guy De Souza's avatar
Guy De Souza committed
82 83
      /// 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;
84
      size += (uint8_t)ceil( log2( (N_RB*(N_RB+1))>>1 ) ); // Freq domain assignment
85 86
      break;

Guy De Souza's avatar
Guy De Souza committed
87
    case NFAPI_NR_DL_DCI_FORMAT_1_1:
88 89 90 91 92 93 94 95 96
      // 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
97
      /// TB1- MCS 5, NDI 1, RV 2
98 99 100 101 102 103 104 105 106 107 108 109 110 111 112
      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
113
    case NFAPI_NR_DL_DCI_FORMAT_2_0:
114 115
      break;

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

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

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

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

  return size;
}

132
void nr_pdcch_scrambling(uint32_t *in,
Hongzhi's avatar
Hongzhi committed
133
                         uint16_t size,
134 135
                         uint32_t Nid,
                         uint32_t n_RNTI,
136
                         uint32_t *out) {
137 138 139 140 141
  uint8_t reset;
  uint32_t x1, x2, s=0;
  reset = 1;
  x2 = (n_RNTI<<16) + Nid;

142
  for (int i=0; i<size; i++) {
143 144 145
    if ((i&0x1f)==0) {
      s = lte_gold_generic(&x1, &x2, reset);
      reset = 0;
146 147 148 149

      if (i) {
        in++;
        out++;
150
      }
151
    }
152

Hongzhi's avatar
Hongzhi committed
153
    (*out) ^= ((((*in)>>(i&0x1f))&1) ^ ((s>>(i&0x1f))&1))<<(i&0x1f);
154
    //printf("nr_pdcch_scrambling: in %d seq 0x%08x => out %d\n",((*in)>>(i&0x1f))&1,s,((*out)>>(i&0x1f))&1);
155
  }
156 157
}

158
uint8_t nr_generate_dci_top(NR_gNB_PDCCH pdcch_vars,
Guy De Souza's avatar
Guy De Souza committed
159
                            uint32_t **gold_pdcch_dmrs,
160
                            int32_t *txdataF,
Guy De Souza's avatar
Guy De Souza committed
161
                            int16_t amp,
162
                            NR_DL_FRAME_PARMS frame_parms,
163
                            nfapi_nr_config_request_t config) {
164
  int16_t mod_dmrs[NR_MAX_CSET_DURATION][NR_MAX_PDCCH_DMRS_LENGTH>>1]; // 3 for the max coreset duration
165 166 167 168
  uint32_t dmrs_seq[NR_MAX_PDCCH_DMRS_INIT_LENGTH_DWORD];
  uint16_t dmrs_offset=0;
  uint16_t cset_start_sc;
  uint8_t cset_start_symb, cset_nsymb;
169
  int k,l,k_prime,dci_idx, dmrs_idx;
170
  nr_cce_t cce;
171 172
  nr_reg_t reg;
  nr_reg_t reg_mapping_list[NR_MAX_PDCCH_AGG_LEVEL*NR_NB_REG_PER_CCE];
173 174 175
  /*First iteration: single DCI*/
  NR_gNB_DCI_ALLOC_t dci_alloc = pdcch_vars.dci_alloc[0];
  nfapi_nr_dl_config_pdcch_parameters_rel15_t pdcch_params = dci_alloc.pdcch_params;
176

Guy De Souza's avatar
Guy De Souza committed
177
  /*The coreset is initialised
178 179
  * 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
Guy De Souza's avatar
Guy De Souza committed
180
  * in time: by its first slot and its first symbol*/
181
  if (pdcch_params.config_type == NFAPI_NR_CSET_CONFIG_MIB_SIB1) {
Guy De Souza's avatar
Guy De Souza committed
182
    cset_start_sc = frame_parms.first_carrier_offset + (frame_parms.ssb_start_subcarrier/NR_NB_SC_PER_RB +
183 184
                    pdcch_params.rb_offset)*NR_NB_SC_PER_RB;
  } else
185 186 187 188
    cset_start_sc = frame_parms.first_carrier_offset + pdcch_params.rb_offset*NR_NB_SC_PER_RB;

  cset_start_symb = pdcch_params.first_symbol;
  cset_nsymb = pdcch_params.n_symb;
Guy De Souza's avatar
Guy De Souza committed
189
  dci_idx = 0;
190
  LOG_I(PHY, "Coreset starting subcarrier %d on symbol %d (%d symbols)\n", cset_start_sc, cset_start_symb, cset_nsymb);
191 192
  // DMRS length is per OFDM symbol
  uint16_t dmrs_length = (pdcch_params.precoder_granularity == NFAPI_NR_CSET_ALL_CONTIGUOUS_RBS)?
193
                         (pdcch_params.n_rb*6) : (dci_alloc.L*36/cset_nsymb); //2(QPSK)*3(per RB)*6(REG per CCE)
194 195 196
  uint16_t encoded_length = dci_alloc.L*108; //2(QPSK)*9(per RB)*6(REG per CCE)
  LOG_I(PHY, "DMRS length per symbol %d\t DCI encoded length %d\n", dmrs_length, encoded_length);

Guy De Souza's avatar
Guy De Souza committed
197
  /// DMRS QPSK modulation
198 199
  /*There is a need to shift from which index the pregenerated DMRS sequence is used
   * see 38211 r15.2.0 section 7.4.1.3.2: assumption is the reference point for k refers to the DMRS sequence*/
200
  if (pdcch_params.config_type == NFAPI_NR_CSET_CONFIG_PDCCH_CONFIG) {
Guy De Souza's avatar
Guy De Souza committed
201 202
    for (int symb=cset_start_symb; symb<cset_start_symb + pdcch_params.n_symb; symb++)
      gold_pdcch_dmrs[symb] += (pdcch_params.rb_offset*3)>>5;
203

204
    dmrs_offset = (pdcch_params.rb_offset*3)&0x1f;
205
    LOG_I(PHY, "PDCCH DMRS offset %d\n", dmrs_offset);
206
  }
207

Guy De Souza's avatar
Guy De Souza committed
208
  for (int symb=cset_start_symb; symb<cset_start_symb + pdcch_params.n_symb; symb++) {
209 210 211
    if (dmrs_offset) {
      // a non zero offset requires the DMRS sequence to be rearranged
      memset(dmrs_seq,0, NR_MAX_PDCCH_DMRS_INIT_LENGTH_DWORD*sizeof(uint32_t));
212

213 214 215
      for (int i=0; i<dmrs_length; i++) {
        dmrs_seq[(i>>5)] |= ((gold_pdcch_dmrs[symb][(i+dmrs_offset)>>5]>>((i+dmrs_offset)&0x1f))&1)<<(i&0x1f);
#ifdef DEBUG_PDCCH_DMRS
216
        //printf("out 0x%08x in 0x%08x \n", dmrs_seq[(i>>5)], gold_pdcch_dmrs[symb][(i+dmrs_offset)>>5]);
217 218
#endif
      }
219

220
      nr_modulation(dmrs_seq, dmrs_length, MOD_QPSK, mod_dmrs[symb]);
221
    } else
222 223 224 225
      nr_modulation(gold_pdcch_dmrs[symb], dmrs_length, MOD_QPSK, mod_dmrs[symb]);

#ifdef DEBUG_PDCCH_DMRS

226 227 228 229 230 231 232
    for (int i=0; i<dmrs_length>>1; i++)
      if (dmrs_offset)
        printf("symb %d i %d gold seq 0x%08x mod_dmrs %d %d\n", symb, i, dmrs_seq[i>>5],
               mod_dmrs[symb][i<<1], mod_dmrs[symb][(i<<1)+1] );
      else
        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] );
233

234 235
#endif
  }
236

237
  /// DCI payload processing
238
  // CRC attachment + Scrambling + Channel coding + Rate matching
yilmazt's avatar
yilmazt committed
239
  uint32_t encoder_output[NR_MAX_DCI_SIZE_DWORD];
Guy De Souza's avatar
Guy De Souza committed
240
  uint16_t n_RNTI = (pdcch_params.search_space_type == NFAPI_NR_SEARCH_SPACE_TYPE_UE_SPECIFIC)? pdcch_params.rnti:0;
241
  uint16_t Nid = (pdcch_params.search_space_type == NFAPI_NR_SEARCH_SPACE_TYPE_UE_SPECIFIC)?
242 243
                 pdcch_params.scrambling_id : config.sch_config.physical_cell_id.value;
  t_nrPolar_params *currentPtr = nr_polar_params(NR_POLAR_DCI_MESSAGE_TYPE, dci_alloc.size, dci_alloc.L);
244
  polar_encoder_fast(dci_alloc.dci_pdu, encoder_output, pdcch_params.rnti,currentPtr);
Guy De Souza's avatar
Guy De Souza committed
245
#ifdef DEBUG_CHANNEL_CODING
Hongzhi's avatar
Hongzhi committed
246
  printf("polar rnti %d\n",pdcch_params.rnti);
Guy De Souza's avatar
Guy De Souza committed
247
  printf("DCI PDU: [0]->0x%lx \t [1]->0x%lx\n",
248
         dci_alloc.dci_pdu[0], dci_alloc.dci_pdu[1]);
Guy De Souza's avatar
Guy De Souza committed
249
  printf("Encoded Payload (length:%d dwords):\n", encoded_length>>5);
250 251

  for (int i=0; i<encoded_length>>5; i++)
Guy De Souza's avatar
Guy De Souza committed
252
    printf("[%d]->0x%08x \t", i,encoder_output[i]);
253

Guy De Souza's avatar
Guy De Souza committed
254
  printf("\n");
Guy De Souza's avatar
Guy De Souza committed
255
#endif
Guy De Souza's avatar
Guy De Souza committed
256
  /// Scrambling
257
  uint32_t scrambled_output[NR_MAX_DCI_SIZE_DWORD]= {0};
Guy De Souza's avatar
Guy De Souza committed
258
  nr_pdcch_scrambling(encoder_output, encoded_length, Nid, n_RNTI, scrambled_output);
Hongzhi's avatar
Hongzhi committed
259
#ifdef DEBUG_CHANNEL_CODING
260
  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
261
[6]->0x%08x \t [7]->0x%08x \t [8]->0x%08x \t [9]->0x%08x\t [10]->0x%08x\t [11]->0x%08x\n",
262 263
         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
264
#endif
265
  /// QPSK modulation
Guy De Souza's avatar
Guy De Souza committed
266
  int16_t mod_dci[NR_MAX_DCI_SIZE>>1];
267
  nr_modulation(scrambled_output, encoded_length, MOD_QPSK, mod_dci);
Guy De Souza's avatar
Guy De Souza committed
268
#ifdef DEBUG_DCI
269

270 271
  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] );
272

Guy De Souza's avatar
Guy De Souza committed
273
#endif
274 275 276

  /// Resource mapping

277 278
  if (cset_start_sc >= frame_parms.ofdm_symbol_size)
    cset_start_sc -= frame_parms.ofdm_symbol_size;
279

280 281 282 283
  /*Reorder REG list for a freq first mapping*/
  uint8_t symb_idx[NR_MAX_CSET_DURATION] = {0,0,0};
  uint8_t nb_regs = dci_alloc.L*NR_NB_REG_PER_CCE;
  uint8_t regs_per_symb = nb_regs/cset_nsymb;
Guy De Souza's avatar
Guy De Souza committed
284

285 286 287 288 289 290
  for (int cce_idx=0; cce_idx<dci_alloc.L; cce_idx++) {
    cce = dci_alloc.cce_list[cce_idx];

    for (int reg_idx=0; reg_idx<NR_NB_REG_PER_CCE; reg_idx++) {
      reg = cce.reg_list[reg_idx];
      reg_mapping_list[reg.symb_idx*regs_per_symb + symb_idx[reg.symb_idx]++] = reg;
Guy De Souza's avatar
Guy De Souza committed
291
    }
292 293
  }

Guy De Souza's avatar
Guy De Souza committed
294
#ifdef DEBUG_DCI
295 296 297 298 299 300
  printf("\n Ordered REG list:\n");

  for (int i=0; i<nb_regs; i++)
    printf("%d\t",reg_mapping_list[i].reg_idx );

  printf("\n");
Guy De Souza's avatar
Guy De Souza committed
301
#endif
302 303

  if (pdcch_params.precoder_granularity == NFAPI_NR_CSET_ALL_CONTIGUOUS_RBS) {
Guy De Souza's avatar
Guy De Souza committed
304
    /*in this case the DMRS are mapped on all the coreset*/
305 306 307 308 309 310 311
    for (l=cset_start_symb; l<cset_start_symb+ cset_nsymb; l++) {
      dmrs_idx = 0;
      k = cset_start_sc + 1;

      while (dmrs_idx<3*pdcch_params.n_rb) {
        ((int16_t *)txdataF)[(l*frame_parms.ofdm_symbol_size + k)<<1]       = ((amp>>1) * mod_dmrs[l][dmrs_idx<<1]) >> 15;
        ((int16_t *)txdataF)[((l*frame_parms.ofdm_symbol_size + k)<<1) + 1] = ((amp>>1) * mod_dmrs[l][(dmrs_idx<<1) + 1]) >> 15;
312
#ifdef DEBUG_PDCCH_DMRS
313 314
        printf("symbol %d position %d => (%d,%d)\n",l,k,((int16_t *)txdataF)[(l*frame_parms.ofdm_symbol_size + k)<<1],
               ((int16_t *)txdataF)[((l*frame_parms.ofdm_symbol_size + k)<<1)+1]);
315
#endif
316
        k+=4;
Guy De Souza's avatar
Guy De Souza committed
317

318
        if (k >= frame_parms.ofdm_symbol_size)
Guy De Souza's avatar
Guy De Souza committed
319
          k -= frame_parms.ofdm_symbol_size;
320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343

        dmrs_idx++;
      }
    }
  }

  /*Now mapping the encoded DCI based on newly constructed REG list
   * and the DMRS for the precoder granularity same as REG bundle*/
  for (int reg_idx=0; reg_idx<nb_regs; reg_idx++) {
    reg = reg_mapping_list[reg_idx];
    k = cset_start_sc + reg.start_sc_idx;

    if (k >= frame_parms.ofdm_symbol_size)
      k -= frame_parms.ofdm_symbol_size;

    l = cset_start_symb + reg.symb_idx;
    dmrs_idx = (reg.reg_idx/cset_nsymb)*3;
    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
        if (pdcch_params.precoder_granularity == NFAPI_NR_CSET_SAME_AS_REG_BUNDLE) {
          ((int16_t *)txdataF)[(l*frame_parms.ofdm_symbol_size + k)<<1]       = ((amp>>1) * mod_dmrs[l][dmrs_idx<<1]) >> 15;
          ((int16_t *)txdataF)[((l*frame_parms.ofdm_symbol_size + k)<<1) + 1] = ((amp>>1) * mod_dmrs[l][(dmrs_idx<<1) + 1]) >> 15;
344
#ifdef DEBUG_PDCCH_DMRS
345 346
          printf("l %d position %d => (%d,%d)\n",l,k,((int16_t *)txdataF)[(l*frame_parms.ofdm_symbol_size + k)<<1],
                 ((int16_t *)txdataF)[((l*frame_parms.ofdm_symbol_size + k)<<1)+1]);
347
#endif
348
          dmrs_idx++;
349
        }
350 351 352 353 354

        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;
355
#ifdef DEBUG_DCI
356 357
        printf("l %d position %d => (%d,%d)\n",l,k,((int16_t *)txdataF)[(l*frame_parms.ofdm_symbol_size + k)<<1],
               ((int16_t *)txdataF)[((l*frame_parms.ofdm_symbol_size + k)<<1)+1]);
358
#endif
359
        dci_idx++;
360
      }
361 362 363 364 365

      k++;

      if (k >= frame_parms.ofdm_symbol_size)
        k -= frame_parms.ofdm_symbol_size;
366
    }
367
  }
368

369 370
  return 0;
}