nr_dci.c 11 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
* \author Guy De Souza
* \date 2018
* \version 0.1
* \company Eurecom
* \email: desouza@eurecom.fr
* \note
* \warning
*/

33

34
#include "nr_dci.h"
35
#include "nr_dlsch.h"
Khalid Ahmed's avatar
Khalid Ahmed committed
36
#include "nr_sch_dmrs.h"
37
#include "PHY/MODULATION/nr_modulation.h"
38
#include "common/utils/nr/nr_common.h"
39

40
//#define DEBUG_PDCCH_DMRS
Raymond Knopp's avatar
Raymond Knopp committed
41 42
//#define DEBUG_DCI
//#define DEBUG_CHANNEL_CODING
43

44
void nr_pdcch_scrambling(uint32_t *in,
45
                         uint32_t size,
46
                         uint32_t Nid,
cig's avatar
cig committed
47
                         uint32_t scrambling_RNTI,
48
                         uint32_t *out) {
49
  uint8_t reset;
50
  uint32_t x1 = 0, x2 = 0, s = 0;
51
  reset = 1;
cig's avatar
cig committed
52
  x2 = (scrambling_RNTI<<16) + Nid;
53
  LOG_D(NR_PHY_DCI, "PDCCH Scrambling x2 %x : scrambling_RNTI %x \n", x2, scrambling_RNTI);
54
  for (int i=0; i<size; i++) {
55 56 57
    if ((i&0x1f)==0) {
      s = lte_gold_generic(&x1, &x2, reset);
      reset = 0;
58 59 60 61

      if (i) {
        in++;
        out++;
62
      }
63
    }
64

Hongzhi's avatar
Hongzhi committed
65
    (*out) ^= ((((*in)>>(i&0x1f))&1) ^ ((s>>(i&0x1f))&1))<<(i&0x1f);
66
  }
67 68
}

69 70
void nr_generate_dci(PHY_VARS_gNB *gNB,
                     nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu_rel15,
71 72
                     int32_t *txdataF,
                     int16_t amp,
73 74
                     NR_DL_FRAME_PARMS *frame_parms,
                     int slot) {
75

76 77
  uint16_t cset_start_sc;
  uint8_t cset_start_symb, cset_nsymb;
78
  int k,l,k_prime,dci_idx, dmrs_idx;
79

francescomani's avatar
francescomani committed
80 81 82 83
  // fill reg list per symbol
  int reg_list[MAX_DCI_CORESET][NR_MAX_PDCCH_AGG_LEVEL * NR_NB_REG_PER_CCE];
  nr_fill_reg_list(reg_list, pdcch_pdu_rel15);
  // compute rb_offset and n_prb based on frequency allocation
84 85 86
  int rb_offset;
  int n_rb;
  get_coreset_rballoc(pdcch_pdu_rel15->FreqDomainResource,&n_rb,&rb_offset);
87
  cset_start_sc = frame_parms->first_carrier_offset + (pdcch_pdu_rel15->BWPStart + rb_offset) * NR_NB_SC_PER_RB;
88

89
  int16_t mod_dmrs[pdcch_pdu_rel15->StartSymbolIndex+pdcch_pdu_rel15->DurationSymbols][(((n_rb+rb_offset+pdcch_pdu_rel15->BWPStart)*6+15)>>4)<<4] __attribute__((aligned(16))); // 3 for the max coreset duration
francescomani's avatar
francescomani committed
90

91 92 93 94 95
  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*/
96
    const nfapi_nr_dl_dci_pdu_t *dci_pdu = &pdcch_pdu_rel15->dci_pdu[d];
97

98 99 100 101 102 103 104
    if(dci_pdu->ScramblingId != gNB->pdcch_gold_init) {
      gNB->pdcch_gold_init = dci_pdu->ScramblingId;
      nr_init_pdcch_dmrs(gNB, dci_pdu->ScramblingId);
    }

    uint32_t **gold_pdcch_dmrs = gNB->nr_gold_pdcch_dmrs[slot];

105 106 107
    cset_start_symb = pdcch_pdu_rel15->StartSymbolIndex;
    cset_nsymb = pdcch_pdu_rel15->DurationSymbols;
    dci_idx = 0;
108 109 110 111 112 113
    LOG_D(NR_PHY_DCI, "pdcch: Coreset rb_offset %d, nb_rb %d BWP Start %d\n", rb_offset, n_rb, pdcch_pdu_rel15->BWPStart);
    LOG_D(NR_PHY_DCI,
          "pdcch: Coreset starting subcarrier %d on symbol %d (%d symbols)\n",
          cset_start_sc,
          cset_start_symb,
          cset_nsymb);
114
    // DMRS length is per OFDM symbol
115
    uint32_t dmrs_length = (n_rb+pdcch_pdu_rel15->BWPStart)*6; //2(QPSK)*3(per RB)*6(REG per CCE)
116
    uint32_t encoded_length = dci_pdu->AggregationLevel*108; //2(QPSK)*9(per RB)*6(REG per CCE)
117
    if (dci_pdu->RNTI != 0xFFFF)
118 119 120 121 122 123 124 125 126 127 128 129
      LOG_D(NR_PHY_DCI,
            "DL_DCI : rb_offset %d, nb_rb %d, DMRS length per symbol %d\t DCI encoded length %d (precoder_granularity %d, "
            "reg_mapping %d), Scrambling_Id %d, ScramblingRNTI %x, PayloadSizeBits %d\n",
            rb_offset,
            n_rb,
            dmrs_length,
            encoded_length,
            pdcch_pdu_rel15->precoderGranularity,
            pdcch_pdu_rel15->CceRegMappingType,
            dci_pdu->ScramblingId,
            dci_pdu->ScramblingRNTI,
            dci_pdu->PayloadSizeBits);
130 131 132 133
    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++) {
134

135 136 137
      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
138 139 140
      if(dci_pdu->RNTI!=0xFFFF) {
        for (int i=0; i<dmrs_length>>1; i++)
          printf("symb %d i %d %p gold seq 0x%08x mod_dmrs %d %d\n", symb, i,
141
                 &gold_pdcch_dmrs[symb][i>>5],gold_pdcch_dmrs[symb][i>>5], mod_dmrs[symb][i<<1], mod_dmrs[symb][(i<<1)+1]);
142
      }
143
#endif
144 145 146 147 148
    }
    
    /// DCI payload processing
    // CRC attachment + Scrambling + Channel coding + Rate matching
    uint32_t encoder_output[NR_MAX_DCI_SIZE_DWORD];
149

150 151 152
    uint16_t n_RNTI = dci_pdu->RNTI;
    uint16_t Nid    = dci_pdu->ScramblingId;
    uint16_t scrambling_RNTI = dci_pdu->ScramblingRNTI;
153

154 155
    polar_encoder_fast((uint64_t*)dci_pdu->Payload, (void*)encoder_output, n_RNTI, 1, 
                       NR_POLAR_DCI_MESSAGE_TYPE, dci_pdu->PayloadSizeBits, dci_pdu->AggregationLevel);
Guy De Souza's avatar
Guy De Souza committed
156
#ifdef DEBUG_CHANNEL_CODING
Laurent THOMAS's avatar
Laurent THOMAS committed
157
//debug dump dci
francescomani's avatar
francescomani committed
158
    printf("polar rnti %x,length %d, L %d\n",n_RNTI, dci_pdu->PayloadSizeBits,pdcch_pdu_rel15->dci_pdu->AggregationLevel);
159
    printf("DCI PDU: [0]->0x%lx \t [1]->0x%lx\n",
160
	   ((uint64_t*)dci_pdu->Payload)[0], ((uint64_t*)dci_pdu->Payload)[1]);
161
    printf("Encoded Payload (length:%u dwords):\n", encoded_length>>5);
162 163
    
    for (int i=0; i<encoded_length>>5; i++)
164 165
      printf("[%d]->0x%08x \t", i,encoder_output[i]);    

166
    printf("\n");
Guy De Souza's avatar
Guy De Souza committed
167
#endif
168 169
    /// Scrambling
    uint32_t scrambled_output[NR_MAX_DCI_SIZE_DWORD]= {0};
170
    nr_pdcch_scrambling(encoder_output, encoded_length, Nid, scrambling_RNTI, scrambled_output);
Hongzhi's avatar
Hongzhi committed
171
#ifdef DEBUG_CHANNEL_CODING
172
    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
173
[6]->0x%08x \t [7]->0x%08x \t [8]->0x%08x \t [9]->0x%08x\t [10]->0x%08x\t [11]->0x%08x\n",
174 175
	   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
176
#endif
177
    /// QPSK modulation
178
    int16_t mod_dci[NR_MAX_DCI_SIZE>>1] __attribute__((aligned(16)));
179
    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
180
#ifdef DEBUG_DCI
181 182 183 184
    
    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
185
#endif
rmagueta's avatar
rmagueta committed
186

187
    /// Resource mapping
rmagueta's avatar
rmagueta committed
188

189 190
    if (cset_start_sc >= frame_parms->ofdm_symbol_size)
      cset_start_sc -= frame_parms->ofdm_symbol_size;
rmagueta's avatar
rmagueta committed
191

francescomani's avatar
francescomani committed
192
    int num_regs = dci_pdu->AggregationLevel * NR_NB_REG_PER_CCE / pdcch_pdu_rel15->DurationSymbols;
193
    /*Mapping the encoded DCI along with the DMRS */
194
    for(int symbol_idx = 0; symbol_idx < pdcch_pdu_rel15->DurationSymbols; symbol_idx++) {
francescomani's avatar
francescomani committed
195 196 197
      // allocating rbs per symbol
      for (int reg_count = 0; reg_count < num_regs; reg_count++) {
        k = cset_start_sc + reg_list[d][reg_count] * NR_NB_SC_PER_RB;
198
        LOG_D(NR_PHY_DCI, "REG %d k %d\n", reg_list[d][reg_count], k);
francescomani's avatar
francescomani committed
199 200
        if (k >= frame_parms->ofdm_symbol_size)
          k -= frame_parms->ofdm_symbol_size;
rmagueta's avatar
rmagueta committed
201

francescomani's avatar
francescomani committed
202
        l = cset_start_symb + symbol_idx;
rmagueta's avatar
rmagueta committed
203

francescomani's avatar
francescomani committed
204 205 206 207 208
        // 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)
          dmrs_idx = (reg_list[d][reg_count] + pdcch_pdu_rel15->BWPStart) * 3;
        else
          dmrs_idx = (reg_list[d][reg_count] + rb_offset) * 3;
rmagueta's avatar
rmagueta committed
209

francescomani's avatar
francescomani committed
210
        k_prime = 0;
rmagueta's avatar
rmagueta committed
211

francescomani's avatar
francescomani committed
212 213 214 215
        for (int m = 0; m < NR_NB_SC_PER_RB; m++) {
          if (m == (k_prime << 2) + 1) { // DMRS if not already mapped
            ((int16_t *)txdataF)[(l * frame_parms->ofdm_symbol_size + k) << 1] = (amp * mod_dmrs[l][dmrs_idx << 1]) >> 15;
            ((int16_t *)txdataF)[((l * frame_parms->ofdm_symbol_size + k) << 1) + 1] = (amp * mod_dmrs[l][(dmrs_idx << 1) + 1]) >> 15;
rmagueta's avatar
rmagueta committed
216

217
#ifdef DEBUG_PDCCH_DMRS
218
            LOG_I(NR_PHY_DCI,
francescomani's avatar
francescomani committed
219 220 221 222 223 224
                  "PDCCH DMRS %d: l %d position %d => (%d,%d)\n",
                  dmrs_idx,
                  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]);
225
#endif
rmagueta's avatar
rmagueta committed
226

francescomani's avatar
francescomani committed
227 228
            dmrs_idx++;
            k_prime++;
rmagueta's avatar
rmagueta committed
229

francescomani's avatar
francescomani committed
230 231 232
          } 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;
233
#ifdef DEBUG_DCI
234
            LOG_I(NR_PHY_DCI,
francescomani's avatar
francescomani committed
235 236 237 238 239
                  "PDCCH: 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]);
240
#endif
241

francescomani's avatar
francescomani committed
242 243
            dci_idx++;
          }
rmagueta's avatar
rmagueta committed
244

francescomani's avatar
francescomani committed
245
          k++;
rmagueta's avatar
rmagueta committed
246

francescomani's avatar
francescomani committed
247 248 249 250
          if (k >= frame_parms->ofdm_symbol_size)
            k -= frame_parms->ofdm_symbol_size;
        } // m
      } // reg_count
251
    } // symbol_idx
252

253
    LOG_D(NR_PHY_DCI,
254 255 256
          "DCI: payloadSize = %d | payload = %llx\n",
          dci_pdu->PayloadSizeBits,
          *(unsigned long long *)dci_pdu->Payload);
257
  } // for (int d=0;d<pdcch_pdu_rel15->numDlDci;d++)
258
}
259

260
void nr_generate_dci_top(processingData_L1tx_t *msgTx,
261
                         int slot,
262 263 264
                         int32_t *txdataF,
                         int16_t amp,
                         NR_DL_FRAME_PARMS *frame_parms) {
265

266
  for (int i=0; i<msgTx->num_ul_pdcch; i++)
267
    nr_generate_dci(msgTx->gNB,&msgTx->ul_pdcch_pdu[i].pdcch_pdu.pdcch_pdu_rel15,txdataF,amp,frame_parms,slot);
268
  for (int i=0; i<msgTx->num_dl_pdcch; i++)
269
    nr_generate_dci(msgTx->gNB,&msgTx->pdcch_pdu[i].pdcch_pdu_rel15,txdataF,amp,frame_parms,slot);
270 271 272

}