dci_nr.c 42 KB
Newer Older
Agustin's avatar
Agustin committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
/*
 * 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
 */
32

Laurent THOMAS's avatar
Laurent THOMAS committed
33 34 35
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
36 37


38
#include "executables/softmodem-common.h"
39
#include "nr_transport_proto_ue.h"
hongzhi wang's avatar
hongzhi wang committed
40
#include "PHY/CODING/nrPolar_tools/nr_polar_dci_defs.h"
41
#include "PHY/phy_extern.h"
hongzhi wang's avatar
hongzhi wang committed
42
#include "PHY/CODING/coding_extern.h"
Agustin's avatar
Agustin committed
43
#include "PHY/sse_intrin.h"
44
#include "common/utils/nr/nr_common.h"
Mario Hudon's avatar
Mario Hudon committed
45
#include <openair1/PHY/TOOLS/phy_scope_interface.h>
Agustin's avatar
Agustin committed
46

47
#include "assertions.h"
Agustin's avatar
Agustin committed
48 49
#include "T.h"

50 51 52 53 54 55 56 57 58 59
char nr_dci_format_string[8][30] = {
  "NR_DL_DCI_FORMAT_1_0",
  "NR_DL_DCI_FORMAT_1_1",
  "NR_DL_DCI_FORMAT_2_0",
  "NR_DL_DCI_FORMAT_2_1",
  "NR_DL_DCI_FORMAT_2_2",
  "NR_DL_DCI_FORMAT_2_3",
  "NR_UL_DCI_FORMAT_0_0",
  "NR_UL_DCI_FORMAT_0_1"};

60
//#define DEBUG_DCI_DECODING 1
Agustin's avatar
Agustin committed
61

Florian Kaltenberger's avatar
Florian Kaltenberger committed
62
//#define NR_PDCCH_DCI_DEBUG            // activates NR_PDCCH_DCI_DEBUG logs
63
#ifdef NR_PDCCH_DCI_DEBUG
64
#define LOG_DDD(a, ...) printf("<-NR_PDCCH_DCI_DEBUG (%s)-> " a, __func__, ##__VA_ARGS__ )
65 66 67
#else
#define LOG_DDD(a...)
#endif
Agustin's avatar
Agustin committed
68 69 70 71
#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)


72
#ifdef LOG_I
73 74
  #undef LOG_I
  #define LOG_I(A,B...) printf(B)
75
#endif
Agustin's avatar
Agustin committed
76 77


78 79

//static const int16_t conjugate[8]__attribute__((aligned(32))) = {-1,1,-1,1,-1,1,-1,1};
Agustin's avatar
Agustin committed
80 81


Laurent THOMAS's avatar
Laurent THOMAS committed
82
static void nr_pdcch_demapping_deinterleaving(uint32_t *llr,
83 84 85 86 87 88 89 90 91 92 93
                                              uint32_t *e_rx,
                                              uint8_t coreset_time_dur,
                                              uint8_t start_symbol,
                                              uint32_t coreset_nbr_rb,
                                              uint8_t reg_bundle_size_L,
                                              uint8_t coreset_interleaver_size_R,
                                              uint8_t n_shift,
                                              uint8_t number_of_candidates,
                                              uint16_t *CCE,
                                              uint8_t *L)
{
94 95 96 97
  /*
   * This function will do demapping and deinterleaving from llr containing demodulated symbols
   * Demapping will regroup in REG and bundles
   * Deinterleaving will order the bundles
98
   *
99 100 101
   * 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
102
   *
103 104 105 106 107 108 109 110
   llr --------------------------> e_rx (z) ----> e_rx (z)
   |   ...
   |   ...
   |   REG 26
   symbol 2    |   ...
   |   ...
   |   REG 5
   |   REG 2
111

112 113 114 115 116 117 118
   |   ...
   |   ...
   |   REG 25
   symbol 1    |   ...
   |   ...
   |   REG 4
   |   REG 1
119

120 121 122 123 124 125 126 127 128
   |   ...
   |   ...                           ...              ...
   |   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

  */
rmagueta's avatar
rmagueta committed
129
  int c = 0, r = 0;
130
  uint16_t f_bundle_j = 0;
rmagueta's avatar
rmagueta committed
131
  uint32_t coreset_C = 0;
hongzhi wang's avatar
hongzhi wang committed
132 133
  uint16_t index_z, index_llr;
  int coreset_interleaved = 0;
134
  int N_regs = coreset_nbr_rb * coreset_time_dur;
135

rmagueta's avatar
rmagueta committed
136 137
  if (reg_bundle_size_L != 0) { // interleaving will be done only if reg_bundle_size_L != 0
    coreset_interleaved = 1;
138
    coreset_C = (uint32_t) (N_regs / (coreset_interleaver_size_R * reg_bundle_size_L));
hongzhi wang's avatar
hongzhi wang committed
139
  } else {
rmagueta's avatar
rmagueta committed
140
    reg_bundle_size_L = 6;
hongzhi wang's avatar
hongzhi wang committed
141
  }
Agustin's avatar
Agustin committed
142

143 144 145 146
  int B_rb = reg_bundle_size_L / coreset_time_dur; // nb of RBs occupied by each REG bundle
  int num_bundles_per_cce = 6 / reg_bundle_size_L;
  int n_cce = N_regs / 6;
  int max_bundles = n_cce * num_bundles_per_cce;
147 148 149
  int f_bundle_j_list[max_bundles];
  // for each bundle
  for (int nb = 0; nb < max_bundles; nb++) {
francescomani's avatar
francescomani committed
150 151
    if (coreset_interleaved == 0)
      f_bundle_j = nb;
152
    else {
hongzhi wang's avatar
hongzhi wang committed
153
      if (r == coreset_interleaver_size_R) {
rmagueta's avatar
rmagueta committed
154
        r = 0;
hongzhi wang's avatar
hongzhi wang committed
155
        c++;
Agustin's avatar
Agustin committed
156
      }
157 158
      f_bundle_j = ((r * coreset_C) + c + n_shift) % (N_regs / reg_bundle_size_L);
      r++;
rmagueta's avatar
rmagueta committed
159
    }
160
    f_bundle_j_list[nb] = f_bundle_j;
rmagueta's avatar
rmagueta committed
161
  }
162

163 164
  // Get cce_list indices by bundle index in ascending order
  int f_bundle_j_list_ord[number_of_candidates][max_bundles];
rmagueta's avatar
rmagueta committed
165
  for (int c_id = 0; c_id < number_of_candidates; c_id++ ) {
166 167
    int start_bund_cand = CCE[c_id] * num_bundles_per_cce;
    int max_bund_per_cand = L[c_id] * num_bundles_per_cce;
168 169
    int f_bundle_j_list_id = 0;
    for(int nb = 0; nb < max_bundles; nb++) {
170
      for(int bund_cand = start_bund_cand; bund_cand < start_bund_cand + max_bund_per_cand; bund_cand++){
171 172
        if (f_bundle_j_list[bund_cand] == nb) {
          f_bundle_j_list_ord[c_id][f_bundle_j_list_id] = nb;
rmagueta's avatar
rmagueta committed
173
          f_bundle_j_list_id++;
174

rmagueta's avatar
rmagueta committed
175 176
        }
      }
Agustin's avatar
Agustin committed
177
    }
rmagueta's avatar
rmagueta committed
178 179
  }

180
  int rb_count = 0;
francescomani's avatar
francescomani committed
181
  int data_sc = 9; // 9 sub-carriers with data per PRB
182
  for (int c_id = 0; c_id < number_of_candidates; c_id++ ) {
183
    for (int symbol_idx = start_symbol; symbol_idx < start_symbol+coreset_time_dur; symbol_idx++) {
184
      for (int cce_count = 0; cce_count < L[c_id]; cce_count ++) {
francescomani's avatar
francescomani committed
185 186
        for (int k=0; k<NR_NB_REG_PER_CCE/reg_bundle_size_L; k++) { // loop over REG bundles
          int f = f_bundle_j_list_ord[c_id][k+NR_NB_REG_PER_CCE*cce_count/reg_bundle_size_L];
187
          for(int rb=0; rb<B_rb; rb++) { // loop over the RBs of the bundle
francescomani's avatar
francescomani committed
188 189 190
            index_z = data_sc * rb_count;
            index_llr = (uint16_t) (f*B_rb + rb + symbol_idx * coreset_nbr_rb) * data_sc;
            for (int i = 0; i < data_sc; i++) {
191
              e_rx[index_z + i] = llr[index_llr + i];
192
#ifdef NR_PDCCH_DCI_DEBUG
193
              LOG_I(PHY,"[candidate=%d,symbol_idx=%d,cce=%d,REG bundle=%d,PRB=%d] z[%d]=(%d,%d) <-> \t llr[%d]=(%d,%d) \n",
194
                    c_id,symbol_idx,cce_count,k,f*B_rb + rb,(index_z + i),*(int16_t *) &e_rx[index_z + i],*(1 + (int16_t *) &e_rx[index_z + i]),
195
                    (index_llr + i),*(int16_t *) &llr[index_llr + i], *(1 + (int16_t *) &llr[index_llr + i]));
196
#endif
197 198
            }
            rb_count++;
199 200 201
          }
        }
      }
hongzhi wang's avatar
hongzhi wang committed
202
    }
Agustin's avatar
Agustin committed
203
  }
hongzhi wang's avatar
hongzhi wang committed
204
}
Agustin's avatar
Agustin committed
205

206
int32_t nr_pdcch_llr(NR_DL_FRAME_PARMS *frame_parms, int32_t rx_size, int32_t rxdataF_comp[][rx_size],
207 208
                     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)];
209
  int32_t i;
210 211
  int16_t *pdcch_llrp;
  pdcch_llrp = &pdcch_llr[2 * symbol * coreset_nbr_rb * 9];
Agustin's avatar
Agustin committed
212

213
  if (!pdcch_llrp) {
214
    LOG_E(PHY,"pdcch_qpsk_llr: llr is null, symbol %d\n", symbol);
215 216
    return (-1);
  }
217

218
  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);
219

220 221 222
  //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)
223
      *pdcch_llrp = 31;
224
    else if (*rxF < -32)
225
      *pdcch_llrp = -32;
226
    else
227
      *pdcch_llrp = (*rxF);
228

229
    LOG_DDD("llr logs: rb=%d i=%d *rxF:%d => *pdcch_llrp:%d\n",i/18,i,*rxF,*pdcch_llrp);
230
    rxF++;
231
    pdcch_llrp++;
232
  }
Agustin's avatar
Agustin committed
233

234
  return (0);
Agustin's avatar
Agustin committed
235 236 237
}


238
#if 0
Agustin's avatar
Agustin committed
239 240 241
int32_t pdcch_llr(NR_DL_FRAME_PARMS *frame_parms,
                  int32_t **rxdataF_comp,
                  char *pdcch_llr,
242 243
                  uint8_t symbol) {
  int16_t *rxF= (int16_t *) &rxdataF_comp[0][(symbol*frame_parms->N_RB_DL*12)];
Agustin's avatar
Agustin committed
244 245 246 247 248
  int32_t i;
  char *pdcch_llr8;
  pdcch_llr8 = &pdcch_llr[2*symbol*frame_parms->N_RB_DL*12];

  if (!pdcch_llr8) {
249
    LOG_E(PHY,"pdcch_qpsk_llr: llr is null, symbol %d\n",symbol);
Agustin's avatar
Agustin committed
250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269
    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);
}
270
#endif
Agustin's avatar
Agustin committed
271 272 273 274

//__m128i avg128P;

//compute average channel_level on each (TX,RX) antenna pair
275 276
void nr_pdcch_channel_level(int32_t rx_size,
                            int32_t dl_ch_estimates_ext[][rx_size],
277 278 279 280
                            NR_DL_FRAME_PARMS *frame_parms,
                            int32_t *avg,
                            int symbol,
                            uint8_t nb_rb) {
Agustin's avatar
Agustin committed
281
  int16_t rb;
282
  uint8_t aarx;
Agustin's avatar
Agustin committed
283 284 285
#if defined(__x86_64__) || defined(__i386__)
  __m128i *dl_ch128;
  __m128i avg128P;
286
#elif defined(__arm__) || defined(__aarch64__)
Agustin's avatar
Agustin committed
287 288 289
  int16x8_t *dl_ch128;
  int32x4_t *avg128P;
#endif
290

291 292
  for (aarx=0; aarx<frame_parms->nb_antennas_rx; aarx++) {
    //clear average level
Agustin's avatar
Agustin committed
293
#if defined(__x86_64__) || defined(__i386__)
294
    avg128P = _mm_setzero_si128();
295
    dl_ch128=(__m128i *)&dl_ch_estimates_ext[aarx][symbol*nb_rb*12];
296
#elif defined(__arm__) || defined(__aarch64__)
297
    dl_ch128=(int16x8_t *)&dl_ch_estimates_ext[aarx][symbol*nb_rb*12];
Agustin's avatar
Agustin committed
298
#endif
299

300
    for (rb=0; rb<(nb_rb*3)>>2; rb++) {
Agustin's avatar
Agustin committed
301
#if defined(__x86_64__) || defined(__i386__)
302 303 304
      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]));
305
#elif defined(__arm__) || defined(__aarch64__)
Agustin's avatar
Agustin committed
306
#endif
Raymond Knopp's avatar
Raymond Knopp committed
307
      //      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]);
308 309
      dl_ch128+=3;
      /*
310 311 312 313 314
      if (rb==0) {
      print_shorts("dl_ch128",&dl_ch128[0]);
      print_shorts("dl_ch128",&dl_ch128[1]);
      print_shorts("dl_ch128",&dl_ch128[2]);
      }
315
      */
Agustin's avatar
Agustin committed
316
    }
317

318 319 320 321
    DevAssert(nb_rb);
    avg[aarx] = 0;
    for (int i = 0; i < 4; i++)
      avg[aarx] += ((int32_t *)&avg128P)[i] / (nb_rb * 9);
322
    LOG_DDD("Channel level : %d\n",avg[aarx]);
323
  }
Agustin's avatar
Agustin committed
324 325 326 327 328 329 330 331

#if defined(__x86_64__) || defined(__i386__)
  _mm_empty();
  _m_empty();
#endif
}

#if defined(__x86_64) || defined(__i386__)
332
  __m128i mmtmpPD0,mmtmpPD1,mmtmpPD2,mmtmpPD3;
333
#elif defined(__arm__) || defined(__aarch64__)
Agustin's avatar
Agustin committed
334 335 336 337 338 339 340

#endif




// This function will extract the mapped DM-RS PDCCH REs as per 38.211 Section 7.4.1.3.2 (Mapping to physical resources)
341
void nr_pdcch_extract_rbs_single(uint32_t rxdataF_sz,
342
                                 c16_t rxdataF[][rxdataF_sz],
343 344 345 346 347
                                 int32_t est_size,
                                 int32_t dl_ch_estimates[][est_size],
                                 int32_t rx_size,
                                 int32_t rxdataF_ext[][rx_size],
                                 int32_t dl_ch_estimates_ext[][rx_size],
Agustin's avatar
Agustin committed
348 349
                                 uint8_t symbol,
                                 NR_DL_FRAME_PARMS *frame_parms,
350
                                 uint8_t *coreset_freq_dom,
Agustin's avatar
Agustin committed
351 352
                                 uint32_t coreset_nbr_rb,
                                 uint32_t n_BWP_start) {
353 354 355 356 357 358 359 360 361 362
  /*
   * 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
   *
   */
363

364
#define NBR_RE_PER_RB_WITH_DMRS           12
Agustin's avatar
Agustin committed
365
  // after removing the 3 DMRS RE, the RB contains 9 RE with PDCCH
366
#define NBR_RE_PER_RB_WITHOUT_DMRS         9
367
  uint16_t c_rb;
368
  //uint8_t rb_count_bit;
cig's avatar
cig committed
369
  uint8_t i, j, aarx;
Agustin's avatar
Agustin committed
370
  int32_t *dl_ch0, *dl_ch0_ext, *rxF, *rxF_ext;
371

Agustin's avatar
Agustin committed
372
  for (aarx = 0; aarx < frame_parms->nb_antennas_rx; aarx++) {
373
    dl_ch0 = &dl_ch_estimates[aarx][frame_parms->ofdm_symbol_size*symbol];
374
    LOG_DDD("dl_ch0 = &dl_ch_estimates[aarx = (%d)][0]\n",aarx);
Agustin's avatar
Agustin committed
375

376
    dl_ch0_ext = &dl_ch_estimates_ext[aarx][symbol * (coreset_nbr_rb * NBR_RE_PER_RB_WITH_DMRS)];
377
    LOG_DDD("dl_ch0_ext = &dl_ch_estimates_ext[aarx = (%d)][symbol * (frame_parms->N_RB_DL * 9) = (%d)]\n",
378
           aarx,symbol * (coreset_nbr_rb * NBR_RE_PER_RB_WITH_DMRS));
379
    rxF_ext = &rxdataF_ext[aarx][symbol * (coreset_nbr_rb * NBR_RE_PER_RB_WITH_DMRS)];
380
    LOG_DDD("rxF_ext = &rxdataF_ext[aarx = (%d)][symbol * (frame_parms->N_RB_DL * 9) = (%d)]\n",
381
           aarx,symbol * (coreset_nbr_rb * NBR_RE_PER_RB_WITH_DMRS));
382

383 384 385 386 387 388 389 390 391 392
    /*
     * 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)
393 394 395
     *    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 -> 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          -> IQ symbols are in the upper border of the rxdataF for first 6 IQ element and the lower border of the rxdataF for the last 6 IQ elements
396 397 398 399
     * 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
     */
Agustin's avatar
Agustin committed
400

401
    int c_rb_by6;
rmagueta's avatar
rmagueta committed
402
    c_rb = 0;
403 404
    for (int rb=0;rb<coreset_nbr_rb;rb++,c_rb++) {
      c_rb_by6 = c_rb/6;
Francesco Mani's avatar
Francesco Mani committed
405

406
      // skip zeros in frequency domain bitmap
407
      while ((coreset_freq_dom[c_rb_by6>>3] & (1<<(7-(c_rb_by6&7)))) == 0) {
Francesco Mani's avatar
Francesco Mani committed
408 409 410
        c_rb+=6;
        c_rb_by6 = c_rb/6;
      }
Agustin's avatar
Agustin committed
411

laurent's avatar
laurent committed
412
      rxF=NULL;
413

Agustin's avatar
Agustin committed
414
      // 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)
rmagueta's avatar
rmagueta committed
415
      if (((c_rb + n_BWP_start) < (frame_parms->N_RB_DL >> 1)) && ((frame_parms->N_RB_DL & 1) == 0)) {
Agustin's avatar
Agustin committed
416
        //if RB to be treated is lower than middle system bandwidth then rxdataF pointed at (offset + c_br + symbol * ofdm_symbol_size): even case
417
        rxF = (int32_t *)&rxdataF[aarx][(frame_parms->first_carrier_offset + 12 * c_rb + (symbol * (frame_parms->ofdm_symbol_size)))+n_BWP_start*12];
418
        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",
419
               c_rb,aarx,(frame_parms->first_carrier_offset + 12 * c_rb + (symbol * (frame_parms->ofdm_symbol_size))));
Agustin's avatar
Agustin committed
420
      }
421

rmagueta's avatar
rmagueta committed
422
      if (((c_rb + n_BWP_start) >= (frame_parms->N_RB_DL >> 1)) && ((frame_parms->N_RB_DL & 1) == 0)) {
Agustin's avatar
Agustin committed
423 424
        // 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
425
        rxF = (int32_t *)&rxdataF[aarx][12*(c_rb + n_BWP_start - (frame_parms->N_RB_DL>>1)) + symbol * frame_parms->ofdm_symbol_size]; // we point at the 1st part of the rxdataF in symbol
426 427
        LOG_DDD("in even case c_rb (%d) is higher than half N_RB_DL (not DC) -> rxF = &rxdataF[aarx = (%d)][12*(c_rb + n_BWP_start - (frame_parms->N_RB_DL>>1)) + symbol * frame_parms->ofdm_symbol_size = (%d)]\n",
               c_rb,aarx,(12*(c_rb + n_BWP_start - (frame_parms->N_RB_DL>>1)) + symbol * frame_parms->ofdm_symbol_size));
Agustin's avatar
Agustin committed
428
      }
429

rmagueta's avatar
rmagueta committed
430
      if (((c_rb + n_BWP_start) < (frame_parms->N_RB_DL >> 1)) && ((frame_parms->N_RB_DL & 1) != 0)) {
Agustin's avatar
Agustin committed
431
        //if RB to be treated is lower than middle system bandwidth then rxdataF pointed at (offset + c_br + symbol * ofdm_symbol_size): odd case
432
        rxF = (int32_t *)&rxdataF[aarx][frame_parms->first_carrier_offset + 12 * (c_rb + n_BWP_start) + symbol * frame_parms->ofdm_symbol_size];
433 434
        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 + n_BWP_start) + symbol * frame_parms->ofdm_symbol_size = (%d)]\n",
               c_rb,aarx,(frame_parms->first_carrier_offset + 12 * (c_rb + n_BWP_start) + symbol * frame_parms->ofdm_symbol_size));
Agustin's avatar
Agustin committed
435
      }
436

rmagueta's avatar
rmagueta committed
437
      if (((c_rb + n_BWP_start) > (frame_parms->N_RB_DL >> 1)) && ((frame_parms->N_RB_DL & 1) != 0)) {
Agustin's avatar
Agustin committed
438 439
        // 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
440
        rxF = (int32_t *)&rxdataF[aarx][12*(c_rb + n_BWP_start - (frame_parms->N_RB_DL>>1)) - 6 + symbol * frame_parms->ofdm_symbol_size]; // we point at the 1st part of the rxdataF in symbol
441 442
        LOG_DDD("in odd case c_rb (%d) is higher than half N_RB_DL (not DC) -> rxF = &rxdataF[aarx = (%d)][12*(c_rb + n_BWP_start - (frame_parms->N_RB_DL>>1)) - 6 + symbol * frame_parms->ofdm_symbol_size = (%d)]\n",
               c_rb,aarx,(12*(c_rb + n_BWP_start - (frame_parms->N_RB_DL>>1)) - 6 + symbol * frame_parms->ofdm_symbol_size));
Agustin's avatar
Agustin committed
443
      }
444

rmagueta's avatar
rmagueta committed
445
      if (((c_rb + n_BWP_start) == (frame_parms->N_RB_DL >> 1)) && ((frame_parms->N_RB_DL & 1) != 0)) { // treatment of RB containing the DC
Agustin's avatar
Agustin committed
446 447
        // 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)
448
        rxF = (int32_t *)&rxdataF[aarx][frame_parms->first_carrier_offset + 12 * (c_rb + n_BWP_start) + symbol * frame_parms->ofdm_symbol_size];
449 450
        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 + n_BWP_start) + symbol * frame_parms->ofdm_symbol_size = (%d)]\n",
               c_rb,aarx,(frame_parms->first_carrier_offset + 12 * (c_rb + n_BWP_start) + symbol * frame_parms->ofdm_symbol_size));
Agustin's avatar
Agustin committed
451
        j = 0;
452

Agustin's avatar
Agustin committed
453 454 455
        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];
456 457 458 459 460 461 462 463 464
            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]));
            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]));
Agustin's avatar
Agustin committed
465 466
          }
        }
467

Agustin's avatar
Agustin committed
468
        // then we point at the begining of the symbol part of rxdataF do process second part of RB
469
        rxF = (int32_t *)&rxdataF[aarx][symbol * frame_parms->ofdm_symbol_size]; // we point at the 1st part of the rxdataF in symbol
470 471
        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));
Agustin's avatar
Agustin committed
472 473 474
        for (; i < 12; i++) {
          if ((i != 9)) {
            dl_ch0_ext[j] = dl_ch0[i];
475 476 477 478 479 480 481 482 483
            rxF_ext[j] = rxF[i - 6];
            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-6], *(1 + (short *) &rxF[i-6]));
            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-6], *(1 + (short *) &rxF[i-6]));
Agustin's avatar
Agustin committed
484 485
          }
        }
486

Agustin's avatar
Agustin committed
487 488 489 490 491
        dl_ch0_ext += NBR_RE_PER_RB_WITHOUT_DMRS;
        rxF_ext += NBR_RE_PER_RB_WITHOUT_DMRS;
        dl_ch0 += 12;
      } else { // treatment of any RB that does not contain the DC
        j = 0;
492

Agustin's avatar
Agustin committed
493 494 495
        for (i = 0; i < 12; i++) {
          if ((i != 1) && (i != 5) && (i != 9)) {
            rxF_ext[j] = rxF[i];
496
            LOG_DDD("RB[c_rb %d] \t RE[re %d] => rxF_ext[%d]=(%d,%d)\t rxF[%d]=(%d,%d)\n",
497 498
                   c_rb, i, j, *(short *) &rxF_ext[j],*(1 + (short *) &rxF_ext[j]), i,
                   *(short *) &rxF[i], *(1 + (short *) &rxF[i]));
hongzhi wang's avatar
hongzhi wang committed
499 500
            dl_ch0_ext[j] = dl_ch0[i];
            j++;
Agustin's avatar
Agustin committed
501
          } else {
502
            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",
503 504
                   c_rb, i, j, *(short *) &rxF_ext[j], *(1 + (short *) &rxF_ext[j]), i,
                   *(short *) &rxF[i], *(1 + (short *) &rxF[i]));
Agustin's avatar
Agustin committed
505 506
          }
        }
507

Agustin's avatar
Agustin committed
508 509 510 511 512 513 514 515
        dl_ch0_ext += NBR_RE_PER_RB_WITHOUT_DMRS;
        rxF_ext += NBR_RE_PER_RB_WITHOUT_DMRS;
        dl_ch0 += 12;
      }
    }
  }
}

Eurecom's avatar
Eurecom committed
516
#define print_shorts(s,x) printf("%s %d,%d,%d,%d,%d,%d,%d,%d\n",s,(x)[0],(x)[1],(x)[2],(x)[3],(x)[4],(x)[5],(x)[6],(x)[7])
Agustin's avatar
Agustin committed
517

518 519 520
void nr_pdcch_channel_compensation(int32_t rx_size, int32_t rxdataF_ext[][rx_size],
                                   int32_t dl_ch_estimates_ext[][rx_size],
                                   int32_t rxdataF_comp[][rx_size],
Agustin's avatar
Agustin committed
521 522 523 524
                                   int32_t **rho,
                                   NR_DL_FRAME_PARMS *frame_parms,
                                   uint8_t symbol,
                                   uint8_t output_shift,
525
                                   uint32_t coreset_nbr_rb) {
hongzhi wang's avatar
hongzhi wang committed
526
  uint16_t rb; //,nb_rb=20;
527
  uint8_t aarx;
528
#if defined(__x86_64__) || defined(__i386__)
529
  __m128i mmtmpP0,mmtmpP1,mmtmpP2,mmtmpP3;
530
#elif defined(__arm__) || defined(__aarch64__)
531
  int16x8_t mmtmpP0,mmtmpP1,mmtmpP2,mmtmpP3;
532
#endif
hongzhi wang's avatar
hongzhi wang committed
533 534
#if defined(__x86_64__) || defined(__i386__)
  __m128i *dl_ch128,*rxdataF128,*rxdataF_comp128;
535
#elif defined(__arm__) || defined(__aarch64__)
Agustin's avatar
Agustin committed
536 537
#endif

538
  for (aarx=0; aarx<frame_parms->nb_antennas_rx; aarx++) {
Agustin's avatar
Agustin committed
539
#if defined(__x86_64__) || defined(__i386__)
540 541 542 543 544
    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);
545
    //printf("rxdataf_comp addr %p\n",&rxdataF_comp[(aatx<<1)+aarx][symbol*20*12]);
546
#elif defined(__arm__) || defined(__aarch64__)
547
    // to be filled in
Agustin's avatar
Agustin committed
548
#endif
549

550
    for (rb=0; rb<(coreset_nbr_rb*3)>>2; rb++) {
Agustin's avatar
Agustin committed
551
#if defined(__x86_64__) || defined(__i386__)
552 553
      // multiply by conjugated channel
      mmtmpP0 = _mm_madd_epi16(dl_ch128[0],rxdataF128[0]);
Eurecom's avatar
Eurecom committed
554
      //print_ints("re",&mmtmpP0);
555 556 557
      // 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));
558
      mmtmpP1 = _mm_sign_epi16(mmtmpP1,*(__m128i *)&conjugate[0]);
Eurecom's avatar
Eurecom committed
559
      //print_ints("im",&mmtmpP1);
560 561 562 563 564 565 566 567
      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);
Eurecom's avatar
Eurecom committed
568 569
      //print_ints("c0",&mmtmpP2);
      //print_ints("c1",&mmtmpP3);
570
      rxdataF_comp128[0] = _mm_packs_epi32(mmtmpP2,mmtmpP3);
Eurecom's avatar
Eurecom committed
571 572 573
//      print_shorts("rx:",(int16_t*)rxdataF128);
//      print_shorts("ch:",(int16_t*)dl_ch128);
//      print_shorts("pack:",(int16_t*)rxdataF_comp128);
574 575 576 577 578
      // 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));
579
      mmtmpP1 = _mm_sign_epi16(mmtmpP1,*(__m128i *)&conjugate[0]);
580 581 582 583 584 585 586 587 588 589 590 591 592 593 594
      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));
595
      mmtmpP1 = _mm_sign_epi16(mmtmpP1,*(__m128i *)&conjugate[0]);
596 597 598 599 600 601 602 603 604 605 606
      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);
607

608
      for (int i=0; i<12 ; i++)
609
        LOG_DDD("rxdataF128[%d]=(%d,%d) X dlch[%d]=(%d,%d) rxdataF_comp128[%d]=(%d,%d)\n",
610 611 612
                (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)]);
613

614 615 616
      dl_ch128+=3;
      rxdataF128+=3;
      rxdataF_comp128+=3;
617
#elif defined(__arm__) || defined(__aarch64__)
618
      // to be filled in
Agustin's avatar
Agustin committed
619
#endif
hongzhi wang's avatar
hongzhi wang committed
620
    }
621
  }
622

Agustin's avatar
Agustin committed
623
#if defined(__x86_64__) || defined(__i386__)
hongzhi wang's avatar
hongzhi wang committed
624 625
  _mm_empty();
  _m_empty();
Agustin's avatar
Agustin committed
626 627 628 629
#endif
}


630
void nr_pdcch_detection_mrc(NR_DL_FRAME_PARMS *frame_parms,
631 632
                         int32_t rx_size,
                         int32_t rxdataF_comp[][rx_size],
633
                         uint8_t symbol) {
Agustin's avatar
Agustin committed
634 635
#if defined(__x86_64__) || defined(__i386__)
  __m128i *rxdataF_comp128_0,*rxdataF_comp128_1;
636
#elif defined(__arm__) || defined(__aarch64__)
637
  int16x8_t *rxdataF_comp128_0,*rxdataF_comp128_1;
Agustin's avatar
Agustin committed
638 639 640 641 642
#endif
  int32_t i;

  if (frame_parms->nb_antennas_rx>1) {
#if defined(__x86_64__) || defined(__i386__)
643 644
    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];
645
#elif defined(__arm__) || defined(__aarch64__)
646 647
    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];
Agustin's avatar
Agustin committed
648
#endif
649

650 651
    // MRC on each re of rb
    for (i=0; i<frame_parms->N_RB_DL*3; i++) {
Agustin's avatar
Agustin committed
652
#if defined(__x86_64__) || defined(__i386__)
653
      rxdataF_comp128_0[i] = _mm_adds_epi16(_mm_srai_epi16(rxdataF_comp128_0[i],1),_mm_srai_epi16(rxdataF_comp128_1[i],1));
654
#elif defined(__arm__) || defined(__aarch64__)
655
      rxdataF_comp128_0[i] = vhaddq_s16(rxdataF_comp128_0[i],rxdataF_comp128_1[i]);
Agustin's avatar
Agustin committed
656 657 658 659 660 661 662 663 664 665
#endif
    }
  }

#if defined(__x86_64__) || defined(__i386__)
  _mm_empty();
  _m_empty();
#endif
}

666
int32_t nr_rx_pdcch(PHY_VARS_NR_UE *ue,
667
                    UE_nr_rxtx_proc_t *proc,
668 669 670
                    int32_t pdcch_est_size,
                    int32_t pdcch_dl_ch_estimates[][pdcch_est_size],
                    int16_t *pdcch_e_rx,
671
                    fapi_nr_dl_config_dci_dl_pdu_rel15_t *rel15,
672
                    c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP]) {
673 674 675 676 677 678

  NR_DL_FRAME_PARMS *frame_parms = &ue->frame_parms;

  uint8_t log2_maxh, aarx;
  int32_t avgs;
  int32_t avgP[4];
679
  int n_rb,rb_offset;
680
  get_coreset_rballoc(rel15->coreset.frequency_domain_resource,&n_rb,&rb_offset);
681

682
  // Pointers to extracted PDCCH symbols in frequency-domain.
683
  int32_t rx_size = ((4 * frame_parms->N_RB_DL * 12 + 31) >> 5) << 5;
684 685 686 687 688
  __attribute__ ((aligned(32))) int32_t rxdataF_ext[frame_parms->nb_antennas_rx][rx_size];
  __attribute__ ((aligned(32))) int32_t rxdataF_comp[frame_parms->nb_antennas_rx][rx_size];
  __attribute__ ((aligned(32))) int32_t pdcch_dl_ch_estimates_ext[frame_parms->nb_antennas_rx][rx_size];

  memset(rxdataF_comp, 0, sizeof(rxdataF_comp));
689 690

  // Pointer to llrs, 4-bit resolution.
691
  int32_t llr_size = 2*4*n_rb*9;
692
  int16_t llr[llr_size];
693

694 695
  memset(llr, 0, sizeof(llr));

696 697
  LOG_D(PHY,"pdcch coreset: freq %x, n_rb %d, rb_offset %d\n",
        rel15->coreset.frequency_domain_resource[0],n_rb,rb_offset);
698 699 700
  for (int s=rel15->coreset.StartSymbolIndex; s<(rel15->coreset.StartSymbolIndex+rel15->coreset.duration); s++) {
    LOG_D(PHY,"in nr_pdcch_extract_rbs_single(rxdataF -> rxdataF_ext || dl_ch_estimates -> dl_ch_estimates_ext)\n");

701 702
    nr_pdcch_extract_rbs_single(ue->frame_parms.samples_per_slot_wCP,
                                rxdataF,
703 704 705
                                pdcch_est_size,
                                pdcch_dl_ch_estimates,
                                rx_size,
706
                                rxdataF_ext,
707
                                pdcch_dl_ch_estimates_ext,
708 709 710 711 712 713 714 715 716
                                s,
                                frame_parms,
                                rel15->coreset.frequency_domain_resource,
                                n_rb,
                                rel15->BWPStart);

    LOG_D(PHY,"we enter nr_pdcch_channel_level(avgP=%d) => compute channel level based on ofdm symbol 0, pdcch_vars[eNB_id]->dl_ch_estimates_ext\n",*avgP);
    LOG_D(PHY,"in nr_pdcch_channel_level(dl_ch_estimates_ext -> dl_ch_estimates_ext)\n");
    // compute channel level based on ofdm symbol 0
717 718
    nr_pdcch_channel_level(rx_size,
                           pdcch_dl_ch_estimates_ext,
719 720
                           frame_parms,
                           avgP,
721
                           s,
722 723 724 725 726 727 728
                           n_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;
729

730
#ifdef UE_DEBUG_TRACE
731
    LOG_D(PHY, "slot %d: pdcch log2_maxh = %d (%d,%d)\n", proc->nr_slot_rx, log2_maxh, avgP[0], avgs);
732 733
#endif
#if T_TRACER
734
    T(T_UE_PHY_PDCCH_ENERGY, T_INT(0), T_INT(0), T_INT(proc->frame_rx % 1024), T_INT(proc->nr_slot_rx), T_INT(avgP[0]), T_INT(avgP[1]), T_INT(avgP[2]), T_INT(avgP[3]));
735 736 737 738
#endif
    LOG_D(PHY,"we enter nr_pdcch_channel_compensation(log2_maxh=%d)\n",log2_maxh);
    LOG_D(PHY,"in nr_pdcch_channel_compensation(rxdataF_ext x dl_ch_estimates_ext -> rxdataF_comp)\n");
    // compute LLRs for ofdm symbol 0 only
739 740
    nr_pdcch_channel_compensation(rx_size, rxdataF_ext,
                                  pdcch_dl_ch_estimates_ext,
741
                                  rxdataF_comp,
742 743 744 745 746
                                  NULL,
                                  frame_parms,
                                  s,
                                  log2_maxh,
                                  n_rb); // log2_maxh+I0_shift
Mario Hudon's avatar
Mario Hudon committed
747

748
    UEscopeCopy(ue, pdcchRxdataF_comp, rxdataF_comp, sizeof(struct complex16), frame_parms->nb_antennas_rx, rx_size, 0);
Mario Hudon's avatar
Mario Hudon committed
749

750 751
    if (frame_parms->nb_antennas_rx > 1) {
      LOG_D(PHY,"we enter nr_pdcch_detection_mrc(frame_parms->nb_antennas_rx=%d)\n", frame_parms->nb_antennas_rx);
752
      nr_pdcch_detection_mrc(frame_parms, rx_size, rxdataF_comp,s);
753
    }
754

755 756 757
    LOG_D(PHY,"we enter nr_pdcch_llr(for symbol %d), pdcch_vars[eNB_id]->rxdataF_comp ---> pdcch_vars[eNB_id]->llr \n",s);
    LOG_D(PHY,"in nr_pdcch_llr(rxdataF_comp -> llr)\n");
    nr_pdcch_llr(frame_parms,
758
                 rx_size,
759
                 rxdataF_comp,
760
                 llr,
761 762
                 s,
                 n_rb);
Mario Hudon's avatar
Mario Hudon committed
763

764
    UEscopeCopy(ue, pdcchLlr, llr, sizeof(int16_t), 1, llr_size, 0);
Mario Hudon's avatar
Mario Hudon committed
765

766 767
#if T_TRACER
    
768 769 770
    //  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));
771 772 773
    
#endif
#ifdef DEBUG_DCI_DECODING
774
    printf("demapping: slot %u, mi %d\n",slot,get_mi(frame_parms,slot));
775
#endif
776
  }
777

Eurecom's avatar
Eurecom committed
778
  LOG_D(PHY,"we enter nr_pdcch_demapping_deinterleaving(), number of candidates %d\n",rel15->number_of_candidates);
779 780
  nr_pdcch_demapping_deinterleaving((uint32_t *) llr,
                                    (uint32_t *) pdcch_e_rx,
781
                                    rel15->coreset.duration,
782
                                    rel15->coreset.StartSymbolIndex,
783 784 785 786 787 788 789
                                    n_rb,
                                    rel15->coreset.RegBundleSize,
                                    rel15->coreset.InterleaverSize,
                                    rel15->coreset.ShiftIndex,
                                    rel15->number_of_candidates,
                                    rel15->CCE,
                                    rel15->L);
790

791
  LOG_D(PHY,"we end nr_pdcch_demapping_deinterleaving()\n");
792
  LOG_D(PHY,"Ending nr_rx_pdcch() function\n");
Francesco Mani's avatar
Francesco Mani committed
793 794

  return (0);
795
}
Agustin's avatar
Agustin committed
796 797 798



799
void nr_pdcch_unscrambling(int16_t *e_rx,
cig's avatar
cig committed
800 801 802 803
                           uint16_t scrambling_RNTI,
                           uint32_t length,
                           uint16_t pdcch_DMRS_scrambling_id,
                           int16_t *z2) {
804 805
  int i;
  uint8_t reset;
806
  uint32_t x1 = 0, x2 = 0, s = 0;
807
  uint16_t n_id; //{0,1,...,65535}
cig's avatar
cig committed
808
  uint32_t rnti = (uint32_t) scrambling_RNTI;
809 810
  reset = 1;
  // x1 is set in first call to lte_gold_generic
cig's avatar
cig committed
811 812
  n_id = pdcch_DMRS_scrambling_id;
  x2 = ((rnti<<16) + n_id); //mod 2^31 is implicit //this is c_init in 38.211 v15.1.0 Section 7.3.2.3
813

cig's avatar
cig committed
814
  LOG_D(PHY,"PDCCH Unscrambling x2 %x : scrambling_RNTI %x\n", x2, rnti);
815

816 817 818 819 820
  for (i = 0; i < length; i++) {
    if ((i & 0x1f) == 0) {
      s = lte_gold_generic(&x1, &x2, reset);
      reset = 0;
    }
821

Laurent THOMAS's avatar
Laurent THOMAS committed
822 823 824 825
    if (((s >> (i % 32)) & 1) == 1)
      z2[i] = -e_rx[i];
    else
      z2[i]=e_rx[i];
826
  }
827
}
Agustin's avatar
Agustin committed
828 829


830 831 832
/* This function compares the received DCI bits with
 * re-encoded DCI bits and returns the number of mismatched bits
 */
833 834 835 836 837 838 839 840
static uint16_t nr_dci_false_detection(uint64_t *dci,
                                       int16_t *soft_in,
                                       int encoded_length,
                                       int rnti,
                                       int8_t messageType,
                                       uint16_t messageLength,
                                       uint8_t aggregation_level
                                       ) {
841 842

  uint32_t encoder_output[NR_MAX_DCI_SIZE_DWORD];
843 844
  polar_encoder_fast(dci, (void*)encoder_output, rnti, 1,
                    messageType, messageLength, aggregation_level);
845
  uint8_t *enout_p = (uint8_t*)encoder_output;
846 847 848 849 850 851 852 853 854 855 856 857 858 859 860
  uint16_t x = 0;

  for (int i=0; i<encoded_length/8; i++) {
    x += ( enout_p[i] & 1 ) ^ ( ( soft_in[i*8] >> 15 ) & 1);
    x += ( ( enout_p[i] >> 1 ) & 1 ) ^ ( ( soft_in[i*8+1] >> 15 ) & 1 );
    x += ( ( enout_p[i] >> 2 ) & 1 ) ^ ( ( soft_in[i*8+2] >> 15 ) & 1 );
    x += ( ( enout_p[i] >> 3 ) & 1 ) ^ ( ( soft_in[i*8+3] >> 15 ) & 1 );
    x += ( ( enout_p[i] >> 4 ) & 1 ) ^ ( ( soft_in[i*8+4] >> 15 ) & 1 );
    x += ( ( enout_p[i] >> 5 ) & 1 ) ^ ( ( soft_in[i*8+5] >> 15 ) & 1 );
    x += ( ( enout_p[i] >> 6 ) & 1 ) ^ ( ( soft_in[i*8+6] >> 15 ) & 1 );
    x += ( ( enout_p[i] >> 7 ) & 1 ) ^ ( ( soft_in[i*8+7] >> 15 ) & 1 );
  }
  return x;
}

861
uint8_t nr_dci_decoding_procedure(PHY_VARS_NR_UE *ue,
862
                                  UE_nr_rxtx_proc_t *proc,
863
                                  int16_t *pdcch_e_rx,
864
                                  fapi_nr_dci_indication_t *dci_ind,
865
                                  fapi_nr_dl_config_dci_dl_pdu_rel15_t *rel15) {
866 867 868 869

  //int gNB_id = 0;
  int16_t tmp_e[16*108];
  rnti_t n_rnti;
870
  int e_rx_cand_idx = 0;
871 872 873 874 875 876

  for (int j=0;j<rel15->number_of_candidates;j++) {
    int CCEind = rel15->CCE[j];
    int L = rel15->L[j];

    // Loop over possible DCI lengths
Laurent THOMAS's avatar
Laurent THOMAS committed
877
    
878
    for (int k = 0; k < rel15->num_dci_options; k++) {
879 880 881 882 883 884 885 886 887 888
      // skip this candidate if we've already found one with the
      // same rnti and format at a different aggregation level
      int dci_found=0;
      for (int ind=0;ind < dci_ind->number_of_dcis ; ind++) {
        if (rel15->rnti== dci_ind->dci_list[ind].rnti &&
            rel15->dci_format_options[k]==dci_ind->dci_list[ind].dci_format) {
           dci_found=1;
           break;
        }
      }
laurent's avatar
laurent committed
889 890
      if (dci_found == 1)
        continue;
891 892 893
      int dci_length = rel15->dci_length_options[k];
      uint64_t dci_estimation[2]= {0};

894
      LOG_D(PHY, "(%i.%i) Trying DCI candidate %d of %d number of candidates, CCE %d (%d), L %d, length %d, format %s\n",
895
            proc->frame_rx, proc->nr_slot_rx, j, rel15->number_of_candidates, CCEind, e_rx_cand_idx, L, dci_length, nr_dci_format_string[rel15->dci_format_options[k]]);
896

897

898
      nr_pdcch_unscrambling(&pdcch_e_rx[e_rx_cand_idx], rel15->coreset.scrambling_rnti, L*108, rel15->coreset.pdcch_dmrs_scrambling_id, tmp_e);
899 900

#ifdef DEBUG_DCI_DECODING
901
      uint32_t *z = (uint32_t *) &e_rx[e_rx_cand_idx];
902
      for (int index_z = 0; index_z < L*6; index_z++){
903
        for (int i=0; i<9; i++) {
904
          LOG_I(PHY,"z[%d]=(%d,%d) \n", (9*index_z + i), *(int16_t *) &z[9*index_z + i],*(1 + (int16_t *) &z[9*index_z + i]));
cig's avatar
cig committed
905
        }
906
      }
907 908 909 910
#endif
      uint16_t crc = polar_decoder_int16(tmp_e,
                                         dci_estimation,
                                         1,
911
                                         NR_POLAR_DCI_MESSAGE_TYPE, dci_length, L);
912 913

      n_rnti = rel15->rnti;
Laurent THOMAS's avatar
Laurent THOMAS committed
914 915
      LOG_D(PHY, "(%i.%i) dci indication (rnti %x,dci format %s,n_CCE %d,payloadSize %d,payload %llx )\n",
            proc->frame_rx, proc->nr_slot_rx,n_rnti,nr_dci_format_string[rel15->dci_format_options[k]],CCEind,dci_length, *(unsigned long long*)dci_estimation);
916
      if (crc == n_rnti) {
917
        LOG_D(PHY, "(%i.%i) Received dci indication (rnti %x,dci format %s,n_CCE %d,payloadSize %d,payload %llx)\n",
918
              proc->frame_rx, proc->nr_slot_rx,n_rnti,nr_dci_format_string[rel15->dci_format_options[k]],CCEind,dci_length,*(unsigned long long*)dci_estimation);
919
        uint16_t mb = nr_dci_false_detection(dci_estimation,tmp_e,L*108,n_rnti, NR_POLAR_DCI_MESSAGE_TYPE, dci_length, L);
920
        ue->dci_thres = (ue->dci_thres + mb) / 2;
921
        if (mb > (ue->dci_thres+30)) {
922 923
          LOG_W(PHY,"DCI false positive. Dropping DCI index %d. Mismatched bits: %d/%d. Current DCI threshold: %d\n",j,mb,L*108,ue->dci_thres);
          continue;
laurent's avatar
laurent committed
924
        } else {
925 926
          dci_ind->SFN = proc->frame_rx;
          dci_ind->slot = proc->nr_slot_rx;
927 928 929 930 931
          dci_ind->dci_list[dci_ind->number_of_dcis].rnti = n_rnti;
          dci_ind->dci_list[dci_ind->number_of_dcis].n_CCE = CCEind;
          dci_ind->dci_list[dci_ind->number_of_dcis].N_CCE = L;
          dci_ind->dci_list[dci_ind->number_of_dcis].dci_format = rel15->dci_format_options[k];
          dci_ind->dci_list[dci_ind->number_of_dcis].ss_type = rel15->dci_type_options[k];
932
          dci_ind->dci_list[dci_ind->number_of_dcis].coreset_type = rel15->coreset.CoreSetType;
933 934 935
          int n_rb, rb_offset;
          get_coreset_rballoc(rel15->coreset.frequency_domain_resource, &n_rb, &rb_offset);
          dci_ind->dci_list[dci_ind->number_of_dcis].cset_start = rel15->BWPStart + rb_offset;
936 937 938 939
          dci_ind->dci_list[dci_ind->number_of_dcis].payloadSize = dci_length;
          memcpy((void*)dci_ind->dci_list[dci_ind->number_of_dcis].payloadBits,(void*)dci_estimation,8);
          dci_ind->number_of_dcis++;
          break;    // If DCI is found, no need to check for remaining DCI lengths
cig's avatar
cig committed
940
        }
941 942 943
      } else {
        LOG_D(PHY,"(%i.%i) Decoded crc %x does not match rnti %x for DCI format %d\n", proc->frame_rx, proc->nr_slot_rx, crc, n_rnti, rel15->dci_format_options[k]);
      }
944
    }
945
    e_rx_cand_idx += 9*L*6*2; //e_rx index for next candidate (L CCEs, 6 REGs per CCE and 9 REs per REG and 2 uint16_t per RE)
946 947 948 949
  }
  return(dci_ind->number_of_dcis);
}

Agustin's avatar
Agustin committed
950