phy_procedures_nr_ue.c 88.5 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
/*
 * 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_procedures_nr_ue.c
 * \brief Implementation of UE procedures from 36.213 LTE specifications
24
 * \author R. Knopp, F. Kaltenberger, N. Nikaein, A. Mico Pereperez, G. Casati
Agustin's avatar
Agustin committed
25 26 27
 * \date 2018
 * \version 0.1
 * \company Eurecom
28
 * \email: knopp@eurecom.fr,florian.kaltenberger@eurecom.fr, navid.nikaein@eurecom.fr, guido.casati@iis.fraunhofer.de
Agustin's avatar
Agustin committed
29 30 31 32 33 34
 * \note
 * \warning
 */

#define _GNU_SOURCE

rmagueta's avatar
rmagueta committed
35
#include "nr/nr_common.h"
Agustin's avatar
Agustin committed
36 37 38
#include "assertions.h"
#include "defs.h"
#include "PHY/defs_nr_UE.h"
39
#include "PHY/phy_extern_nr_ue.h"
Hongzhi Wang's avatar
Hongzhi Wang committed
40
#include "PHY/MODULATION/modulation_UE.h"
41
#include "PHY/NR_REFSIG/refsig_defs_ue.h"
42 43
#include "PHY/NR_UE_TRANSPORT/nr_transport_ue.h"
#include "PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h"
Agustin's avatar
Agustin committed
44
#include "SCHED_NR_UE/defs.h"
Sakthivel Velumani's avatar
Sakthivel Velumani committed
45
#include "SCHED_NR_UE/pucch_uci_ue_nr.h"
Agustin's avatar
Agustin committed
46
#include "SCHED_NR/extern.h"
47
#include "SCHED_NR_UE/phy_sch_processing_time.h"
hongzhi wang's avatar
hongzhi wang committed
48
#include "PHY/NR_UE_ESTIMATION/nr_estimation.h"
49
#include "PHY/NR_TRANSPORT/nr_dci.h"
Agustin's avatar
Agustin committed
50 51 52
#ifdef EMOS
#include "SCHED/phy_procedures_emos.h"
#endif
53
#include "executables/softmodem-common.h"
54
#include "executables/nr-uesoftmodem.h"
55
#include "openair2/LAYER2/NR_MAC_UE/mac_proto.h"
Agustin's avatar
Agustin committed
56

57
//#define DEBUG_PHY_PROC
Agustin's avatar
Agustin committed
58
#define NR_PDCCH_SCHED
59
//#define NR_PDCCH_SCHED_DEBUG
60 61
//#define NR_PUCCH_SCHED
//#define NR_PUCCH_SCHED_DEBUG
Agustin's avatar
Agustin committed
62 63 64 65 66

#ifndef PUCCH
#define PUCCH
#endif

67
#include "LAYER2/NR_MAC_UE/mac_defs.h"
68
#include "LAYER2/NR_MAC_UE/mac_proto.h"
69
#include "common/utils/LOG/log.h"
Agustin's avatar
Agustin committed
70 71 72 73 74

#ifdef EMOS
fifo_dump_emos_UE emos_dump_UE;
#endif

75
#include "common/utils/LOG/vcd_signal_dumper.h"
Agustin's avatar
Agustin committed
76
#include "UTIL/OPT/opt.h"
77
#include "intertask_interface.h"
Agustin's avatar
Agustin committed
78 79
#include "T.h"

80
char nr_mode_string[NUM_UE_MODE][20] = {"NOT SYNCHED","PRACH","RAR","RA_WAIT_CR", "PUSCH", "RESYNCH"};
81

82 83
const uint8_t nr_rv_round_map_ue[4] = {0, 2, 1, 3};

Agustin's avatar
Agustin committed
84
#if defined(EXMIMO) || defined(OAI_USRP) || defined(OAI_BLADERF) || defined(OAI_LMSSDR) || defined(OAI_ADRV9371_ZC706)
85
extern uint64_t downlink_frequency[MAX_NUM_CCs][4];
Agustin's avatar
Agustin committed
86 87
#endif

cig's avatar
cig committed
88 89
unsigned int gain_table[31] = {100,112,126,141,158,178,200,224,251,282,316,359,398,447,501,562,631,708,794,891,1000,1122,1258,1412,1585,1778,1995,2239,2512,2818,3162};

cig's avatar
cig committed
90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134
void nr_fill_dl_indication(nr_downlink_indication_t *dl_ind,
                           fapi_nr_dci_indication_t *dci_ind,
                           fapi_nr_rx_indication_t *rx_ind,
                           UE_nr_rxtx_proc_t *proc,
                           PHY_VARS_NR_UE *ue,
                           uint8_t gNB_id){

  memset((void*)dl_ind, 0, sizeof(nr_downlink_indication_t));

  dl_ind->gNB_index = gNB_id;
  dl_ind->module_id = ue->Mod_id;
  dl_ind->cc_id     = ue->CC_id;
  dl_ind->frame     = proc->frame_rx;
  dl_ind->slot      = proc->nr_slot_rx;
  dl_ind->thread_id = proc->thread_id;

  if (dci_ind) {

    dl_ind->rx_ind = NULL; //no data, only dci for now
    dl_ind->dci_ind = dci_ind;

  } else if (rx_ind) {

    dl_ind->rx_ind = rx_ind; //  hang on rx_ind instance
    dl_ind->dci_ind = NULL;

  }

}

void nr_fill_rx_indication(fapi_nr_rx_indication_t *rx_ind,
                           uint8_t pdu_type,
                           uint8_t gNB_id,
                           PHY_VARS_NR_UE *ue,
                           NR_UE_DLSCH_t *dlsch0,
                           uint16_t n_pdus){

  int harq_pid;
  NR_DL_FRAME_PARMS *frame_parms = &ue->frame_parms;

  if (n_pdus > 1){
    LOG_E(PHY, "In %s: multiple number of DL PDUs not supported yet...\n", __FUNCTION__);
  }

  switch (pdu_type){
rmagueta's avatar
rmagueta committed
135
    case FAPI_NR_RX_PDU_TYPE_SIB:
cig's avatar
cig committed
136
    case FAPI_NR_RX_PDU_TYPE_DLSCH:
cig's avatar
cig committed
137
    case FAPI_NR_RX_PDU_TYPE_RAR:
cig's avatar
cig committed
138 139 140 141
      harq_pid = dlsch0->current_harq_pid;
      rx_ind->rx_indication_body[n_pdus - 1].pdsch_pdu.pdu = dlsch0->harq_processes[harq_pid]->b;
      rx_ind->rx_indication_body[n_pdus - 1].pdsch_pdu.pdu_length = dlsch0->harq_processes[harq_pid]->TBS / 8;
    break;
142 143 144
    case FAPI_NR_RX_PDU_TYPE_SSB:
      rx_ind->rx_indication_body[n_pdus - 1].ssb_pdu.pdu = ue->pbch_vars[gNB_id]->decoded_output;
      rx_ind->rx_indication_body[n_pdus - 1].ssb_pdu.additional_bits = ue->pbch_vars[gNB_id]->xtra_byte;
francescomani's avatar
francescomani committed
145
      rx_ind->rx_indication_body[n_pdus - 1].ssb_pdu.ssb_index = (frame_parms->ssb_index)&0x7;
146 147 148
      rx_ind->rx_indication_body[n_pdus - 1].ssb_pdu.ssb_length = frame_parms->Lmax;
      rx_ind->rx_indication_body[n_pdus - 1].ssb_pdu.cell_id = frame_parms->Nid_cell;
      rx_ind->rx_indication_body[n_pdus - 1].ssb_pdu.ssb_start_subcarrier = frame_parms->ssb_start_subcarrier;
cig's avatar
cig committed
149 150 151 152 153 154 155 156 157 158
    break;
    default:
    break;
  }

  rx_ind->rx_indication_body[n_pdus -1].pdu_type = pdu_type;
  rx_ind->number_pdus = n_pdus;

}

159
int get_tx_amp_prach(int power_dBm, int power_max_dBm, int N_RB_UL){
Agustin's avatar
Agustin committed
160

161
  int gain_dB = power_dBm - power_max_dBm, amp_x_100 = -1;
Agustin's avatar
Agustin committed
162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182

  switch (N_RB_UL) {
  case 6:
  amp_x_100 = AMP;      // PRACH is 6 PRBS so no scale
  break;
  case 15:
  amp_x_100 = 158*AMP;  // 158 = 100*sqrt(15/6)
  break;
  case 25:
  amp_x_100 = 204*AMP;  // 204 = 100*sqrt(25/6)
  break;
  case 50:
  amp_x_100 = 286*AMP;  // 286 = 100*sqrt(50/6)
  break;
  case 75:
  amp_x_100 = 354*AMP;  // 354 = 100*sqrt(75/6)
  break;
  case 100:
  amp_x_100 = 408*AMP;  // 408 = 100*sqrt(100/6)
  break;
  default:
183 184
  LOG_E(PHY, "Unknown PRB size %d\n", N_RB_UL);
  return (amp_x_100);
Agustin's avatar
Agustin committed
185 186 187
  break;
  }
  if (gain_dB < -30) {
188 189 190
    return (amp_x_100/3162);
  } else if (gain_dB > 0)
    return (amp_x_100);
Agustin's avatar
Agustin committed
191
  else
192 193 194 195
    return (amp_x_100/gain_table[-gain_dB]);  // 245 corresponds to the factor sqrt(25/6)

  return (amp_x_100);
}
Agustin's avatar
Agustin committed
196

cig's avatar
cig committed
197
UE_MODE_t get_nrUE_mode(uint8_t Mod_id,uint8_t CC_id,uint8_t gNB_id){
198 199
  return(PHY_vars_UE_g[Mod_id][CC_id]->UE_mode[gNB_id]);
}
200

cig's avatar
cig committed
201 202 203 204 205 206
uint8_t get_ra_PreambleIndex(uint8_t Mod_id, uint8_t CC_id, uint8_t gNB_id){

  return PHY_vars_UE_g[Mod_id][CC_id]->prach_resources[gNB_id]->ra_PreambleIndex;

}

207 208 209 210 211 212 213 214 215
// convert time factor "16 * 64 * T_c / (2^mu)" in N_TA calculation in TS38.213 section 4.2 to samples by multiplying with samples per second
//   16 * 64 * T_c            / (2^mu) * samples_per_second
// = 16 * T_s                 / (2^mu) * samples_per_second
// = 16 * 1 / (15 kHz * 2048) / (2^mu) * (15 kHz * 2^mu * ofdm_symbol_size)
// = 16 * 1 /           2048           *                  ofdm_symbol_size
// = 16 * ofdm_symbol_size / 2048
static inline
uint16_t get_bw_scaling(uint16_t ofdm_symbol_size){
  return 16 * ofdm_symbol_size / 2048;
cig's avatar
cig committed
216 217
}

cig's avatar
cig committed
218 219 220 221 222 223
// UL time alignment procedures:
// - If the current tx frame and slot match the TA configuration in ul_time_alignment
//   then timing advance is processed and set to be applied in the next UL transmission
// - Application of timing adjustment according to TS 38.213 p4.2
// todo:
// - handle RAR TA application as per ch 4.2 TS 38.213
224 225 226 227 228 229 230 231 232
void ue_ta_procedures(PHY_VARS_NR_UE *ue, int slot_tx, int frame_tx){

  if (ue->mac_enabled == 1) {

    uint8_t gNB_id = 0;
    NR_UL_TIME_ALIGNMENT_t *ul_time_alignment = &ue->ul_time_alignment[gNB_id];

    if (frame_tx == ul_time_alignment->ta_frame && slot_tx == ul_time_alignment->ta_slot) {

233 234
      uint16_t ofdm_symbol_size = ue->frame_parms.ofdm_symbol_size;
      uint16_t bw_scaling = get_bw_scaling(ofdm_symbol_size);
235

236
      ue->timing_advance += (ul_time_alignment->ta_command - 31) * bw_scaling;
237

rmagueta's avatar
rmagueta committed
238
      LOG_D(PHY, "In %s: [UE %d] [%d.%d] Got timing advance command %u from MAC, new value is %d\n",
239 240 241 242 243 244
        __FUNCTION__,
        ue->Mod_id,
        frame_tx,
        slot_tx,
        ul_time_alignment->ta_command,
        ue->timing_advance);
245

cig's avatar
cig committed
246 247
      ul_time_alignment->ta_frame = -1;
      ul_time_alignment->ta_slot = -1;
248

cig's avatar
cig committed
249 250
    }
  }
251 252
}

253
void phy_procedures_nrUE_TX(PHY_VARS_NR_UE *ue,
254
                            UE_nr_rxtx_proc_t *proc,
255
                            uint8_t gNB_id) {
cig's avatar
cig committed
256

257
  int slot_tx = proc->nr_slot_tx;
Agustin's avatar
Agustin committed
258 259
  int frame_tx = proc->frame_tx;

cig's avatar
cig committed
260
  AssertFatal(ue->CC_id == 0, "Transmission on secondary CCs is not supported yet\n");
Agustin's avatar
Agustin committed
261 262 263

  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_TX,VCD_FUNCTION_IN);

264 265
  memset(ue->common_vars.txdataF[0], 0, sizeof(int)*14*ue->frame_parms.ofdm_symbol_size);

266
  LOG_D(PHY,"****** start TX-Chain for AbsSubframe %d.%d ******\n", frame_tx, slot_tx);
Agustin's avatar
Agustin committed
267 268 269 270 271

#if UE_TIMING_TRACE
  start_meas(&ue->phy_proc_tx);
#endif

272
  if (ue->UE_mode[gNB_id] <= PUSCH){
273

274 275 276 277
    for (uint8_t harq_pid = 0; harq_pid < ue->ulsch[proc->thread_id][gNB_id][0]->number_harq_processes_for_pusch; harq_pid++) {
      if (ue->ulsch[proc->thread_id][gNB_id][0]->harq_processes[harq_pid]->status == ACTIVE)
        nr_ue_ulsch_procedures(ue, harq_pid, frame_tx, slot_tx, proc->thread_id, gNB_id);
    }
Agustin's avatar
Agustin committed
278

279
  }
Agustin's avatar
Agustin committed
280 281 282 283 284

  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_TX, VCD_FUNCTION_OUT);
#if UE_TIMING_TRACE
  stop_meas(&ue->phy_proc_tx);
#endif
285

Agustin's avatar
Agustin committed
286 287
}

cig's avatar
cig committed
288 289 290
void nr_ue_measurement_procedures(uint16_t l,
                                  PHY_VARS_NR_UE *ue,
                                  UE_nr_rxtx_proc_t *proc,
291
                                  uint8_t gNB_id,
cig's avatar
cig committed
292
                                  uint16_t slot){
Agustin's avatar
Agustin committed
293 294

  NR_DL_FRAME_PARMS *frame_parms=&ue->frame_parms;
295 296
  int frame_rx   = proc->frame_rx;
  int nr_slot_rx = proc->nr_slot_rx;
Agustin's avatar
Agustin committed
297 298
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_MEASUREMENT_PROCEDURES, VCD_FUNCTION_IN);

Hongzhi Wang's avatar
Hongzhi Wang committed
299
  if (l==2) {
cig's avatar
cig committed
300 301 302 303 304 305 306 307

    LOG_D(PHY,"Doing UE measurement procedures in symbol l %u Ncp %d nr_slot_rx %d, rxdata %p\n",
      l,
      ue->frame_parms.Ncp,
      nr_slot_rx,
      ue->common_vars.rxdata);

    nr_ue_measurements(ue, proc, nr_slot_rx);
Hongzhi Wang's avatar
Hongzhi Wang committed
308

Agustin's avatar
Agustin committed
309 310
#if T_TRACER
    if(slot == 0)
311
      T(T_UE_PHY_MEAS, T_INT(gNB_id),  T_INT(ue->Mod_id), T_INT(frame_rx%1024), T_INT(nr_slot_rx),
312 313 314 315 316 317 318
	T_INT((int)(10*log10(ue->measurements.rsrp[0])-ue->rx_total_gain_dB)),
	T_INT((int)ue->measurements.rx_rssi_dBm[0]),
	T_INT((int)(ue->measurements.rx_power_avg_dB[0] - ue->measurements.n0_power_avg_dB)),
	T_INT((int)ue->measurements.rx_power_avg_dB[0]),
	T_INT((int)ue->measurements.n0_power_avg_dB),
	T_INT((int)ue->measurements.wideband_cqi_avg[0]),
	T_INT((int)ue->common_vars.freq_offset));
Agustin's avatar
Agustin committed
319 320 321
#endif
  }

Hongzhi Wang's avatar
Hongzhi Wang committed
322 323 324 325 326 327 328 329
  // accumulate and filter timing offset estimation every subframe (instead of every frame)
  if (( slot == 2) && (l==(2-frame_parms->Ncp))) {

    // AGC

    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_GAIN_CONTROL, VCD_FUNCTION_IN);


330 331
    //printf("start adjust gain power avg db %d\n", ue->measurements.rx_power_avg_dB[gNB_id]);
    phy_adjust_gain_nr (ue,ue->measurements.rx_power_avg_dB[gNB_id],gNB_id);
Hongzhi Wang's avatar
Hongzhi Wang committed
332 333
    
    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_GAIN_CONTROL, VCD_FUNCTION_OUT);
Hongzhi Wang's avatar
Hongzhi Wang committed
334 335 336

}

Agustin's avatar
Agustin committed
337 338 339
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_MEASUREMENT_PROCEDURES, VCD_FUNCTION_OUT);
}

340
void nr_ue_pbch_procedures(uint8_t gNB_id,
341 342 343
			   PHY_VARS_NR_UE *ue,
			   UE_nr_rxtx_proc_t *proc,
			   uint8_t abstraction_flag)
Agustin's avatar
Agustin committed
344
{
Hongzhi Wang's avatar
Hongzhi Wang committed
345
  int ret = 0;
Agustin's avatar
Agustin committed
346 347 348 349

  DevAssert(ue);

  int frame_rx = proc->frame_rx;
350
  int nr_slot_rx = proc->nr_slot_rx;
Agustin's avatar
Agustin committed
351 352 353

  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_PBCH_PROCEDURES, VCD_FUNCTION_IN);

354
  LOG_D(PHY,"[UE  %d] Frame %d Slot %d, Trying PBCH (NidCell %d, gNB_id %d)\n",ue->Mod_id,frame_rx,nr_slot_rx,ue->frame_parms.Nid_cell,gNB_id);
355

laurent's avatar
fixes  
laurent committed
356
  ret = nr_rx_pbch(ue, proc,
357
		   ue->pbch_vars[gNB_id],
358
		   &ue->frame_parms,
359
		   gNB_id,
360
		   (ue->frame_parms.ssb_index)&7,
361 362
		   SISO,
		   ue->high_speed_flag);
Agustin's avatar
Agustin committed
363

Hongzhi Wang's avatar
Hongzhi Wang committed
364
  if (ret==0) {
365

366
    ue->pbch_vars[gNB_id]->pdu_errors_conseq = 0;
Agustin's avatar
Agustin committed
367

368
    // Switch to PRACH state if it is first PBCH after initial synch and no timing correction is performed
369
    if (ue->UE_mode[gNB_id] == NOT_SYNCHED && ue->no_timing_correction == 1){
370 371 372 373 374 375 376
      if (get_softmodem_params()->do_ra) {
        ue->UE_mode[gNB_id] = PRACH;
        ue->prach_resources[gNB_id]->sync_frame = frame_rx;
        ue->prach_resources[gNB_id]->init_msg1 = 0;
      } else {
        ue->UE_mode[gNB_id] = PUSCH;
      }
377
    }
Agustin's avatar
Agustin committed
378 379

#ifdef DEBUG_PHY_PROC
380
    uint16_t frame_tx;
381
    LOG_D(PHY,"[UE %d] frame %d, nr_slot_rx %d, Received PBCH (MIB): frame_tx %d. N_RB_DL %d\n",
Agustin's avatar
Agustin committed
382 383
    ue->Mod_id,
    frame_rx,
384
    nr_slot_rx,
Agustin's avatar
Agustin committed
385
    frame_tx,
Hongzhi Wang's avatar
Hongzhi Wang committed
386
    ue->frame_parms.N_RB_DL);
Agustin's avatar
Agustin committed
387 388 389
#endif

  } else {
390 391
    LOG_E(PHY,"[UE %d] frame %d, nr_slot_rx %d, Error decoding PBCH!\n",
	  ue->Mod_id,frame_rx, nr_slot_rx);
392 393 394 395 396 397 398 399 400 401
    /*FILE *fd;
    if ((fd = fopen("rxsig_frame0.dat","w")) != NULL) {
                  fwrite((void *)&ue->common_vars.rxdata[0][0],
                         sizeof(int32_t),
                         ue->frame_parms.samples_per_frame,
                         fd);
                  LOG_I(PHY,"Dummping Frame ... bye bye \n");
                  fclose(fd);
                  exit(0);
                }*/
Agustin's avatar
Agustin committed
402

403
    /*
Agustin's avatar
Agustin committed
404 405 406
    write_output("rxsig0.m","rxs0", ue->common_vars.rxdata[0],ue->frame_parms.samples_per_subframe,1,1);


407 408
      write_output("H00.m","h00",&(ue->common_vars.dl_ch_estimates[0][0][0]),((ue->frame_parms.Ncp==0)?7:6)*(ue->frame_parms.ofdm_symbol_size),1,1);
      write_output("H10.m","h10",&(ue->common_vars.dl_ch_estimates[0][2][0]),((ue->frame_parms.Ncp==0)?7:6)*(ue->frame_parms.ofdm_symbol_size),1,1);
Agustin's avatar
Agustin committed
409

410 411 412 413 414
      write_output("rxsigF0.m","rxsF0", ue->common_vars.rxdataF[0],8*ue->frame_parms.ofdm_symbol_size,1,1);
      write_output("PBCH_rxF0_ext.m","pbch0_ext",ue->pbch_vars[0]->rxdataF_ext[0],12*4*6,1,1);
      write_output("PBCH_rxF0_comp.m","pbch0_comp",ue->pbch_vars[0]->rxdataF_comp[0],12*4*6,1,1);
      write_output("PBCH_rxF_llr.m","pbch_llr",ue->pbch_vars[0]->llr,(ue->frame_parms.Ncp==0) ? 1920 : 1728,1,4);
      exit(-1);
Agustin's avatar
Agustin committed
415 416
    */

417 418
    ue->pbch_vars[gNB_id]->pdu_errors_conseq++;
    ue->pbch_vars[gNB_id]->pdu_errors++;
419

420
    if (ue->pbch_vars[gNB_id]->pdu_errors_conseq>=100) {
421 422 423 424 425 426 427
      if (get_softmodem_params()->non_stop) {
        LOG_E(PHY,"More that 100 consecutive PBCH errors! Going back to Sync mode!\n");
        ue->lost_sync = 1;
      } else {
        LOG_E(PHY,"More that 100 consecutive PBCH errors! Exiting!\n");
        exit_fun("More that 100 consecutive PBCH errors! Exiting!\n");
      }
Agustin's avatar
Agustin committed
428 429 430 431
    }
  }

  if (frame_rx % 100 == 0) {
432 433
    ue->pbch_vars[gNB_id]->pdu_fer = ue->pbch_vars[gNB_id]->pdu_errors - ue->pbch_vars[gNB_id]->pdu_errors_last;
    ue->pbch_vars[gNB_id]->pdu_errors_last = ue->pbch_vars[gNB_id]->pdu_errors;
Agustin's avatar
Agustin committed
434 435 436 437
  }

#ifdef DEBUG_PHY_PROC
  LOG_D(PHY,"[UE %d] frame %d, slot %d, PBCH errors = %d, consecutive errors = %d!\n",
438
	ue->Mod_id,frame_rx, nr_slot_rx,
439 440
	ue->pbch_vars[gNB_id]->pdu_errors,
	ue->pbch_vars[gNB_id]->pdu_errors_conseq);
Agustin's avatar
Agustin committed
441 442 443 444 445 446
#endif
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_PBCH_PROCEDURES, VCD_FUNCTION_OUT);
}



447
unsigned int nr_get_tx_amp(int power_dBm, int power_max_dBm, int N_RB_UL, int nb_rb)
448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463
{

  int gain_dB = power_dBm - power_max_dBm;
  double gain_lin;

  gain_lin = pow(10,.1*gain_dB);
  if ((nb_rb >0) && (nb_rb <= N_RB_UL)) {
    return((int)(AMP*sqrt(gain_lin*N_RB_UL/(double)nb_rb)));
  }
  else {
    LOG_E(PHY,"Illegal nb_rb/N_RB_UL combination (%d/%d)\n",nb_rb,N_RB_UL);
    //mac_xface->macphy_exit("");
  }
  return(0);
}

Agustin's avatar
Agustin committed
464
#ifdef NR_PDCCH_SCHED
465

466 467 468
int nr_ue_pdcch_procedures(uint8_t gNB_id,
			   PHY_VARS_NR_UE *ue,
			   UE_nr_rxtx_proc_t *proc)
Agustin's avatar
Agustin committed
469
{
470
  int frame_rx = proc->frame_rx;
471
  int nr_slot_rx = proc->nr_slot_rx;
472
  unsigned int dci_cnt=0;
cig's avatar
cig committed
473 474
  fapi_nr_dci_indication_t dci_ind = {0};
  nr_downlink_indication_t dl_indication;
475 476

  /*
Agustin's avatar
Agustin committed
477
  //  unsigned int dci_cnt=0, i;  //removed for nr_ue_pdcch_procedures and added in the loop for nb_coreset_active
478 479 480
#ifdef NR_PDCCH_SCHED_DEBUG
  printf("<-NR_PDCCH_PHY_PROCEDURES_LTE_UE (nr_ue_pdcch_procedures)-> Entering function nr_ue_pdcch_procedures() \n");
#endif
Agustin's avatar
Agustin committed
481 482

  int frame_rx = proc->frame_rx;
483
  int nr_slot_rx = proc->nr_slot_rx;
Agustin's avatar
Agustin committed
484
  NR_DCI_ALLOC_t dci_alloc_rx[8];
485
  
486
  //uint8_t next1_thread_id = proc->thread_id== (RX_NB_TH-1) ? 0:(proc->thread_id+1);
487 488
  //uint8_t next2_thread_id = next1_thread_id== (RX_NB_TH-1) ? 0:(next1_thread_id+1);
  
Agustin's avatar
Agustin committed
489

490 491
  // table dci_fields_sizes_cnt contains dci_fields_sizes for each time a dci is decoded in the slot
  // each element represents the size in bits for each dci field, for each decoded dci -> [dci_cnt-1]
492 493
  // each time a dci is decode at dci_cnt, the values of the table dci_fields_sizes[i][j] will be copied at table dci_fields_sizes_cnt[dci_cnt-1][i][j]
  // table dci_fields_sizes_cnt[dci_cnt-1][i][j] will then be used in function nr_extract_dci_info
494
  uint8_t dci_fields_sizes_cnt[MAX_NR_DCI_DECODED_SLOT][NBR_NR_DCI_FIELDS][NBR_NR_FORMATS];
495

Agustin's avatar
Agustin committed
496
  int nb_searchspace_active=0;
497 498
  NR_UE_PDCCH **pdcch_vars = ue->pdcch_vars[proc->thread_id];
  NR_UE_PDCCH *pdcch_vars2 = ue->pdcch_vars[proc->thread_id][gNB_id];
499 500 501
  // s in TS 38.212 Subclause 10.1, for each active BWP the UE can deal with 10 different search spaces
  // Higher layers have updated the number of searchSpaces with are active in the current slot and this value is stored in variable nb_searchspace_total
  int nb_searchspace_total = pdcch_vars2->nb_search_space;
502

cig's avatar
cig committed
503
  pdcch_vars[gNB_id]->crnti = 0x1234; //to be check how to set when using loop memory
504

cig's avatar
cig committed
505
  uint16_t c_rnti=pdcch_vars[gNB_id]->crnti;
506
  uint16_t cs_rnti=0,new_rnti=0,tc_rnti=0;
507 508
  uint16_t p_rnti=P_RNTI;
  uint16_t si_rnti=SI_RNTI;
509
  uint16_t ra_rnti=99;
laurent's avatar
laurent committed
510
  uint16_t sp_csi_rnti=0,sfi_rnti=0,int_rnti=0,tpc_pusch_rnti=0,tpc_pucch_rnti=0,tpc_srs_rnti=0; //FIXME
511
  uint16_t crc_scrambled_values[TOTAL_NBR_SCRAMBLED_VALUES] =
512
    {c_rnti,cs_rnti,new_rnti,tc_rnti,p_rnti,si_rnti,ra_rnti,sp_csi_rnti,sfi_rnti,int_rnti,tpc_pusch_rnti,tpc_pucch_rnti,tpc_srs_rnti};
513
  #ifdef NR_PDCCH_SCHED_DEBUG
514
  printf("<-NR_PDCCH_PHY_PROCEDURES_LTE_UE (nr_ue_pdcch_procedures)-> there is a bug in FAPI to calculate nb_searchspace_total=%d\n",nb_searchspace_total);
hongzhi wang's avatar
hongzhi wang committed
515 516 517
  #endif
  if (nb_searchspace_total>1) nb_searchspace_total=1; // to be removed when fixing bug in FAPI
  #ifdef NR_PDCCH_SCHED_DEBUG
518 519
  printf("<-NR_PDCCH_PHY_PROCEDURES_LTE_UE (nr_ue_pdcch_procedures)-> there is a bug in FAPI to calculate nb_searchspace_total so we set it to 1...\n");
  printf("<-NR_PDCCH_PHY_PROCEDURES_LTE_UE (nr_ue_pdcch_procedures)-> the number of searchSpaces active in the current slot(%d) is %d) \n",
520
	 nr_slot_rx,nb_searchspace_total);
521
  #endif
522

523 524 525 526
  //FK: we define dci_ind and dl_indication as local variables, this way the call to the mac should be thread safe
  fapi_nr_dci_indication_t dci_ind;
  nr_downlink_indication_t dl_indication;
  
527
  // p in TS 38.212 Subclause 10.1, for each active BWP the UE can deal with 3 different CORESETs (including coresetId 0 for common search space)
528
  //int nb_coreset_total = NR_NBR_CORESET_ACT_BWP;
Guy De Souza's avatar
Guy De Souza committed
529
  unsigned int dci_cnt=0;
530
  // this table contains 56 (NBR_NR_DCI_FIELDS) elements for each dci field and format described in TS 38.212. Each element represents the size in bits for each dci field
531
  //uint8_t dci_fields_sizes[NBR_NR_DCI_FIELDS][NBR_NR_FORMATS] = {{0}};
532
  // this is the UL bandwidth part. FIXME! To be defined where this value comes from
Raymond Knopp's avatar
Raymond Knopp committed
533
  //  uint16_t n_RB_ULBWP = 106;
534
  // this is the DL bandwidth part. FIXME! To be defined where this value comes from
Agustin's avatar
Agustin committed
535 536 537 538

  // First we have to identify each searchSpace active at a time and do PDCCH monitoring corresponding to current searchSpace
  // Up to 10 searchSpaces can be configured to UE (s<=10)
  for (nb_searchspace_active=0; nb_searchspace_active<nb_searchspace_total; nb_searchspace_active++){
539
    int nb_coreset_active=nb_searchspace_active;
540
    //int do_pdcch_monitoring_current_slot=1; // this variable can be removed and fapi is handling
541 542 543
    
     // The following code has been removed as it is handled by higher layers (fapi)
     //
544
     // Verify that monitoring is required at the slot nr_slot_rx. We will run pdcch procedure only if do_pdcch_monitoring_current_slot=1
545
     // For Type0-PDCCH searchspace, we need to calculate the monitoring slot from Tables 13-1 .. 13-15 in TS 38.213 Subsection 13
546 547 548
     //NR_UE_SLOT_PERIOD_OFFSET_t sl_period_offset_mon = pdcch_vars2->searchSpace[nb_searchspace_active].monitoringSlotPeriodicityAndOffset;
     //if (sl_period_offset_mon == nr_sl1) {
     //do_pdcch_monitoring_current_slot=1; // PDCCH monitoring in every slot
549
     //} else if (nr_slot_rx%(uint16_t)sl_period_offset_mon == pdcch_vars2->searchSpace[nb_searchspace_active].monitoringSlotPeriodicityAndOffset_offset) {
550 551 552 553 554 555 556
     //do_pdcch_monitoring_current_slot=1; // PDCCH monitoring in every monitoringSlotPeriodicityAndOffset slot with offset
     //}
    
     // FIXME
     // For PDCCH monitoring when overlap with SS/PBCH according to 38.213 v15.1.0 Section 10
     // To be implemented LATER !!!
     
557
    //int _offset,_index,_M;
558
    //int searchSpace_id                              = pdcch_vars2->searchSpace[nb_searchspace_active].searchSpaceId;
559 560


Agustin's avatar
Agustin committed
561
    #ifdef NR_PDCCH_SCHED_DEBUG
562
      printf("<-NR_PDCCH_PHY_PROCEDURES_LTE_UE (nr_ue_pdcch_procedures)-> nb_searchspace_active=%d do_pdcch_monitoring_current_slot=%d (to be removed)\n",
Agustin's avatar
Agustin committed
563 564 565 566
              nb_searchspace_active,
              do_pdcch_monitoring_current_slot);
    #endif

567
//    if (do_pdcch_monitoring_current_slot) {
568
      // the searchSpace indicates that we need to monitor PDCCH in current nr_slot_rx
Agustin's avatar
Agustin committed
569 570
      // get the parameters describing the current SEARCHSPACE
      // the CORESET id applicable to the current SearchSpace
571
      //int searchSpace_coreset_id                      = pdcch_vars2->searchSpace[nb_searchspace_active].controlResourceSetId;
Agustin's avatar
Agustin committed
572 573 574 575
      // FIXME this variable is a bit string (14 bits) identifying every OFDM symbol in a slot.
      // at the moment we will not take into consideration this variable and we will consider that the OFDM symbol offset is always the first OFDM in a symbol
      uint16_t symbol_within_slot_mon                 = pdcch_vars2->searchSpace[nb_searchspace_active].monitoringSymbolWithinSlot;
      // get the remaining parameters describing the current SEARCHSPACE:     // FIXME! To be defined where we get this information from
576 577 578 579 580
      //NR_UE_SEARCHSPACE_nbrCAND_t num_cand_L1         = pdcch_vars2->searchSpace[nb_searchspace_active].nrofCandidates_aggrlevel1;
      //NR_UE_SEARCHSPACE_nbrCAND_t num_cand_L2         = pdcch_vars2->searchSpace[nb_searchspace_active].nrofCandidates_aggrlevel2;
      //NR_UE_SEARCHSPACE_nbrCAND_t num_cand_L4         = pdcch_vars2->searchSpace[nb_searchspace_active].nrofCandidates_aggrlevel4;
      //NR_UE_SEARCHSPACE_nbrCAND_t num_cand_L8         = pdcch_vars2->searchSpace[nb_searchspace_active].nrofCandidates_aggrlevel8;
      //NR_UE_SEARCHSPACE_nbrCAND_t num_cand_L16        = pdcch_vars2->searchSpace[nb_searchspace_active].nrofCandidates_aggrlevel16;
Agustin's avatar
Agustin committed
581 582
                                                                                                  // FIXME! A table of five enum elements
      // searchSpaceType indicates whether this is a common search space or a UE-specific search space
583
      //int searchSpaceType                             = pdcch_vars2->searchSpace[nb_searchspace_active].searchSpaceType.type;
584
      NR_SEARCHSPACE_TYPE_t searchSpaceType                             = ue_specific;//common;
585 586 587 588 589
      #ifdef NR_PDCCH_SCHED_DEBUG
        printf("<-NR_PDCCH_PHY_PROCEDURES_LTE_UE (nr_ue_pdcch_procedures)-> searchSpaceType=%d is hardcoded THIS HAS TO BE FIXED!!!\n",
                searchSpaceType);
      #endif

590
      //while ((searchSpace_coreset_id != pdcch_vars2->coreset[nb_coreset_active].controlResourceSetId) && (nb_coreset_active<nb_coreset_total)) {
Agustin's avatar
Agustin committed
591
        // we need to identify the CORESET associated to the active searchSpace
592
        //nb_coreset_active++;
Agustin's avatar
Agustin committed
593
      if (nb_coreset_active >= nb_coreset_total) return 0; // the coreset_id could not be found. There is a problem
594
      }
595

Agustin's avatar
Agustin committed
596

597 598 599
    
     //we do not need these parameters yet
    
600
     // get the parameters describing the current CORESET
601 602 603 604 605 606 607 608 609 610
     //int coreset_duration                                      = pdcch_vars2->coreset[nb_coreset_active].duration;
     //uint64_t coreset_freq_dom                                 = pdcch_vars2->coreset[nb_coreset_active].frequencyDomainResources;
     //int coreset_shift_index                                   = pdcch_vars2->coreset[nb_coreset_active].cce_reg_mappingType.shiftIndex;
    // NR_UE_CORESET_REG_bundlesize_t coreset_bundlesize         = pdcch_vars2->coreset[nb_coreset_active].cce_reg_mappingType.reg_bundlesize;
    // NR_UE_CORESET_interleaversize_t coreset_interleaversize   = pdcch_vars2->coreset[nb_coreset_active].cce_reg_mappingType.interleaversize;
    // NR_UE_CORESET_precoder_granularity_t precoder_granularity = pdcch_vars2->coreset[nb_coreset_active].precoderGranularity;
    // int tci_statesPDCCH                                       = pdcch_vars2->coreset[nb_coreset_active].tciStatesPDCCH;
    // int tci_present                                           = pdcch_vars2->coreset[nb_coreset_active].tciPresentInDCI;
    // uint16_t pdcch_DMRS_scrambling_id                         = pdcch_vars2->coreset[nb_coreset_active].pdcchDMRSScramblingID;
    
Agustin's avatar
Agustin committed
611

612 613 614 615 616 617 618 619 620 621 622 623 624 625
    // A set of PDCCH candidates for a UE to monitor is defined in terms of PDCCH search spaces.
    // Searchspace types:
    // Type0-PDCCH  common search space for a DCI format with CRC scrambled by a SI-RNTI
    // number of consecutive resource blocks and a number of consecutive symbols for
    // the control resource set of the Type0-PDCCH common search space from
    // the four most significant bits of RMSI-PDCCH-Config as described in Tables 13-1 through 13-10
    // and determines PDCCH monitoring occasions
    // from the four least significant bits of RMSI-PDCCH-Config,
    // included in MasterInformationBlock, as described in Tables 13-11 through 13-15
    // Type0A-PDCCH common search space for a DCI format with CRC scrambled by a SI-RNTI
    // Type1-PDCCH  common search space for a DCI format with CRC scrambled by a RA-RNTI, or a TC-RNTI, or a C-RNTI
    // Type2-PDCCH  common search space for a DCI format with CRC scrambled by a P-RNTI
    // Type3-PDCCH  common search space for a DCI format with CRC scrambled by INT-RNTI, or SFI-RNTI,
    // or TPC-PUSCH-RNTI, or TPC-PUCCH-RNTI, or TPC-SRS-RNTI, or C-RNTI, or CS-RNTI(s), or SP-CSI-RNTI
Agustin's avatar
Agustin committed
626 627 628



629
    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_PDCCH_PROCEDURES, VCD_FUNCTION_IN);
Agustin's avatar
Agustin committed
630
#if UE_TIMING_TRACE
631
      start_meas(&ue->dlsch_rx_pdcch_stats);
Agustin's avatar
Agustin committed
632 633
#endif

634 635
      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_RX_PDCCH, VCD_FUNCTION_IN);
#ifdef NR_PDCCH_SCHED_DEBUG
cig's avatar
cig committed
636 637
      printf("<-NR_PDCCH_PHY_PROCEDURES_LTE_UE (nr_ue_pdcch_procedures)-> Entering function nr_rx_pdcch with gNB_id=%d (nb_coreset_active=%d, (symbol_within_slot_mon&0x3FFF)=%d, searchSpaceType=%d)\n",
                  gNB_id,nb_coreset_active,(symbol_within_slot_mon&0x3FFF),
Agustin's avatar
Agustin committed
638
                  searchSpaceType);
639
#endif
Agustin's avatar
Agustin committed
640
        nr_rx_pdcch(ue,
641 642
                    frame_rx,
                    nr_slot_rx,
cig's avatar
cig committed
643
                    gNB_id,
644
                    //(ue->frame_parms.mode1_flag == 1) ? SISO : ALAMOUTI,
Agustin's avatar
Agustin committed
645 646 647 648 649 650
                    SISO,
                    ue->high_speed_flag,
                    ue->is_secondary_ue,
                    nb_coreset_active,
                    (symbol_within_slot_mon&0x3FFF),
                    searchSpaceType);
651
#ifdef NR_PDCCH_SCHED_DEBUG
652 653
          printf("<-NR_PDCCH_PHY_PROCEDURES_LTE_UE (nr_ue_pdcch_procedures)-> Ending function nr_rx_pdcch(nb_coreset_active=%d, (symbol_within_slot_mon&0x3FFF)=%d, searchSpaceType=%d)\n",
                  nb_coreset_active,(symbol_within_slot_mon&0x3FFF),
Agustin's avatar
Agustin committed
654
                  searchSpaceType);
655 656
#endif

657 658 659
  */
  
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_RX_PDCCH, VCD_FUNCTION_IN);
660
  nr_rx_pdcch(ue, proc);
661 662
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_RX_PDCCH, VCD_FUNCTION_OUT);
  
Agustin's avatar
Agustin committed
663

664
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_DCI_DECODING, VCD_FUNCTION_IN);
Guy De Souza's avatar
Guy De Souza committed
665

666
#ifdef NR_PDCCH_SCHED_DEBUG
667 668
  printf("<-NR_PDCCH_PHY_PROCEDURES_LTE_UE (nr_ue_pdcch_procedures)-> Entering function nr_dci_decoding_procedure with (nb_searchspace_active=%d)\n",
	 pdcch_vars->nb_search_space);
669
#endif
hongzhi wang's avatar
hongzhi wang committed
670

671
  dci_cnt = nr_dci_decoding_procedure(ue, proc, &dci_ind);
672

673
#ifdef NR_PDCCH_SCHED_DEBUG
674
  LOG_I(PHY,"<-NR_PDCCH_PHY_PROCEDURES_LTE_UE (nr_ue_pdcch_procedures)-> Ending function nr_dci_decoding_procedure() -> dci_cnt=%u\n",dci_cnt);
675
#endif
676 677
  
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_DCI_DECODING, VCD_FUNCTION_OUT);
678
  //LOG_D(PHY,"[UE  %d][PUSCH] Frame %d nr_slot_rx %d PHICH RX\n",ue->Mod_id,frame_rx,nr_slot_rx);
679 680

  for (int i=0; i<dci_cnt; i++) {
cig's avatar
cig committed
681
    LOG_D(PHY,"[UE  %d] AbsSubFrame %d.%d, Mode %s: DCI %i of %d total DCIs found --> rnti %x : format %d\n",
682
      ue->Mod_id,frame_rx%1024,nr_slot_rx,nr_mode_string[ue->UE_mode[gNB_id]],
cig's avatar
cig committed
683 684 685 686
      i + 1,
      dci_cnt,
      dci_ind.dci_list[i].rnti,
      dci_ind.dci_list[i].dci_format);
687
  }
688
  ue->pdcch_vars[proc->thread_id][gNB_id]->dci_received += dci_cnt;
689

cig's avatar
cig committed
690
  dci_ind.number_of_dcis = dci_cnt;
691
    /*
692
    for (int i=0; i<dci_cnt; i++) {
693
      
694
	memset(&dci_ind.dci_list[i].dci,0,sizeof(fapi_nr_dci_pdu_rel15_t));
695
	
696 697 698 699
	dci_ind.dci_list[i].rnti = dci_alloc_rx[i].rnti;
	dci_ind.dci_list[i].dci_format = dci_alloc_rx[i].format;
	dci_ind.dci_list[i].n_CCE = dci_alloc_rx[i].firstCCE;
	dci_ind.dci_list[i].N_CCE = (int)dci_alloc_rx[i].L;
700 701
	
	status = nr_extract_dci_info(ue,
cig's avatar
cig committed
702
				     gNB_id,
703 704 705 706
				     ue->frame_parms.frame_type,
				     dci_alloc_rx[i].dci_length,
				     dci_alloc_rx[i].rnti,
				     dci_alloc_rx[i].dci_pdu,
707
				     &dci_ind.dci_list[i].dci,
708
				     dci_fields_sizes_cnt[i],
709
				     dci_alloc_rx[i].format,
710
				     nr_slot_rx,
711 712 713
				     pdcch_vars2->n_RB_BWP[nb_searchspace_active],
				     pdcch_vars2->n_RB_BWP[nb_searchspace_active],
				     crc_scrambled_values);
714
	
715 716 717 718 719 720
	if(status == 0) {
	  LOG_W(PHY,"<-NR_PDCCH_PHY_PROCEDURES_UE (nr_ue_pdcch_procedures)-> bad DCI %d !!! \n",dci_alloc_rx[i].format);
	  return(-1);
	}
	
	LOG_D(PHY,"<-NR_PDCCH_PHY_PROCEDURES_UE (nr_ue_pdcch_procedures)-> Ending function nr_extract_dci_info()\n");
721
	
Agustin's avatar
Agustin committed
722

723
        
Agustin's avatar
Agustin committed
724
      } // end for loop dci_cnt
725
    */
Agustin's avatar
Agustin committed
726

727
    // fill dl_indication message
cig's avatar
cig committed
728
    nr_fill_dl_indication(&dl_indication, &dci_ind, NULL, proc, ue, gNB_id);
729
    //  send to mac
730
    ue->if_inst->dl_indication(&dl_indication, NULL);
731

Agustin's avatar
Agustin committed
732 733 734
#if UE_TIMING_TRACE
  stop_meas(&ue->dlsch_rx_pdcch_stats);
#endif
735 736
    
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_PDCCH_PROCEDURES, VCD_FUNCTION_OUT);
737
  return(dci_cnt);
Agustin's avatar
Agustin committed
738
}
739
#endif // NR_PDCCH_SCHED
740

741
int nr_ue_pdsch_procedures(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, int gNB_id, PDSCH_t pdsch, NR_UE_DLSCH_t *dlsch0, NR_UE_DLSCH_t *dlsch1) {
Agustin's avatar
Agustin committed
742

743 744
  int frame_rx = proc->frame_rx;
  int nr_slot_rx = proc->nr_slot_rx;
Agustin's avatar
Agustin committed
745
  int m;
746
  int i_mod,gNB_id_i,dual_stream_UE;
Agustin's avatar
Agustin committed
747 748
  int first_symbol_flag=0;

749
  if (!dlsch0)
750
    return 0;
Agustin's avatar
Agustin committed
751
  if (dlsch0->active == 0)
752
    return 0;
Agustin's avatar
Agustin committed
753

754
  if (!dlsch1)  {
755
    int harq_pid = dlsch0->current_harq_pid;
756
    NR_DL_UE_HARQ_t *dlsch0_harq = dlsch0->harq_processes[harq_pid];
757 758 759 760 761
    uint16_t BWPStart       = dlsch0_harq->BWPStart;
    uint16_t pdsch_start_rb = dlsch0_harq->start_rb;
    uint16_t pdsch_nb_rb    = dlsch0_harq->nb_rb;
    uint16_t s0             = dlsch0_harq->start_symbol;
    uint16_t s1             = dlsch0_harq->nb_symbols;
762
    bool is_SI              = dlsch0->rnti_type == _SI_RNTI_;
763

764
    LOG_D(PHY,"[UE %d] PDSCH type %d active in nr_slot_rx %d, harq_pid %d (%d), rb_start %d, nb_rb %d, symbol_start %d, nb_symbols %d, DMRS mask %x\n",ue->Mod_id,pdsch,nr_slot_rx,harq_pid,dlsch0_harq->status,pdsch_start_rb,pdsch_nb_rb,s0,s1,dlsch0_harq->dlDmrsSymbPos);
Agustin's avatar
Agustin committed
765

766
    for (m = s0; m < (s0 +s1); m++) {
767
      if (dlsch0_harq->dlDmrsSymbPos & (1 << m)) {
768
        for (uint8_t aatx=0; aatx<dlsch0_harq->Nl; aatx++) {//for MIMO Config: it shall loop over no_layers
769
          nr_pdsch_channel_estimation(ue,
770
                                      proc,
771
                                      gNB_id,
772
                                      is_SI,
773
                                      nr_slot_rx,
774 775
                                      aatx /*p*/,
                                      m,
rmagueta's avatar
rmagueta committed
776
                                      BWPStart,
777 778
                                      ue->frame_parms.first_carrier_offset+(BWPStart + pdsch_start_rb)*12,
                                      pdsch_nb_rb);
779
          LOG_D(PHY,"PDSCH Channel estimation gNB id %d, PDSCH antenna port %d, slot %d, symbol %d\n",0,aatx,nr_slot_rx,m);
780 781 782 783 784
#if 0
          ///LOG_M: the channel estimation
          int nr_frame_rx = proc->frame_rx;
          char filename[100];
          for (uint8_t aarx=0; aarx<ue->frame_parms.nb_antennas_rx; aarx++) {
785
            sprintf(filename,"PDSCH_CHANNEL_frame%d_slot%d_sym%d_port%d_rx%d.m", nr_frame_rx, nr_slot_rx, m, aatx,aarx);
786
            int **dl_ch_estimates = ue->pdsch_vars[proc->thread_id][gNB_id]->dl_ch_estimates;
787 788 789 790
            LOG_M(filename,"channel_F",&dl_ch_estimates[aatx*ue->frame_parms.nb_antennas_rx+aarx][ue->frame_parms.ofdm_symbol_size*m],ue->frame_parms.ofdm_symbol_size, 1, 1);
          }
#endif
        }
791 792
        if ( ue->high_speed_flag == 0 ) //for slow speed case only estimate the channel once per slot
          break;
793 794
      }
    }
795 796

    uint16_t first_symbol_with_data = s0;
797 798
    uint32_t dmrs_data_re;

799
    if (dlsch0_harq->dmrsConfigType == NFAPI_NR_DMRS_TYPE1)
800 801 802 803 804 805
      dmrs_data_re = 12 - 6 * dlsch0_harq->n_dmrs_cdm_groups;
    else
      dmrs_data_re = 12 - 4 * dlsch0_harq->n_dmrs_cdm_groups;

    while ((dmrs_data_re == 0) && (dlsch0_harq->dlDmrsSymbPos & (1 << first_symbol_with_data))) {
      first_symbol_with_data++;
806 807
    }

808 809
    for (m = s0; m < (s1 + s0); m++) {
 
810
      dual_stream_UE = 0;
811
      gNB_id_i = gNB_id+1;
812
      i_mod = 0;
813
      if (( m==first_symbol_with_data ) && (m<4))
814
        first_symbol_flag = 1;
Agustin's avatar
Agustin committed
815
      else
816
        first_symbol_flag = 0;
817

Agustin's avatar
Agustin committed
818 819
#if UE_TIMING_TRACE
      uint8_t slot = 0;
820
      if(m >= ue->frame_parms.symbols_per_slot>>1)
Agustin's avatar
Agustin committed
821
        slot = 1;
822
      start_meas(&ue->dlsch_llr_stats_parallelization[proc->thread_id][slot]);
Agustin's avatar
Agustin committed
823
#endif
824 825 826
      // process DLSCH received symbols in the slot
      // symbol by symbol processing (if data/DMRS are multiplexed is checked inside the function)
      if (pdsch == PDSCH || pdsch == SI_PDSCH || pdsch == RA_PDSCH) {
827
        if (nr_rx_pdsch(ue,
828 829
                        proc,
                        pdsch,
830 831
                        gNB_id,
                        gNB_id_i,
832 833 834 835 836 837
                        frame_rx,
                        nr_slot_rx,
                        m,
                        first_symbol_flag,
                        dual_stream_UE,
                        i_mod,
838
                        harq_pid) < 0)
839 840 841
          return -1;
      } else AssertFatal(1==0,"Not RA_PDSCH, SI_PDSCH or PDSCH\n");

Agustin's avatar
Agustin committed
842
#if UE_TIMING_TRACE
843
      stop_meas(&ue->dlsch_llr_stats_parallelization[proc->thread_id][slot]);
Agustin's avatar
Agustin committed
844
#if DISABLE_LOG_X
845
      printf("[AbsSFN %d.%d] LLR Computation Symbol %d %5.2f \n",frame_rx,nr_slot_rx,m,ue->dlsch_llr_stats_parallelization[proc->thread_id][slot].p_time/(cpuf*1000.0));
Agustin's avatar
Agustin committed
846
#else
847
      LOG_D(PHY, "[AbsSFN %d.%d] LLR Computation Symbol %d %5.2f \n",frame_rx,nr_slot_rx,m,ue->dlsch_llr_stats_parallelization[proc->thread_id][slot].p_time/(cpuf*1000.0));
Agustin's avatar
Agustin committed
848 849 850
#endif
#endif

851 852 853
      if(first_symbol_flag) {
        proc->first_symbol_available = 1;
      }
Agustin's avatar
Agustin committed
854 855
    } // CRNTI active
  }
856
  return 0;
Agustin's avatar
Agustin committed
857 858
}

Hongzhi Wang's avatar
Hongzhi Wang committed
859
void nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue,
860
       UE_nr_rxtx_proc_t *proc,
861
       int gNB_id,
862 863 864 865
       PDSCH_t pdsch,
       NR_UE_DLSCH_t *dlsch0,
       NR_UE_DLSCH_t *dlsch1,
       int *dlsch_errors,
866
       uint8_t dlsch_parallel) {
Agustin's avatar
Agustin committed
867

868 869 870
  if (dlsch0==NULL)
    AssertFatal(0,"dlsch0 should be defined at this level \n");

Francesco Mani's avatar
Francesco Mani committed
871
  int harq_pid = dlsch0->current_harq_pid;
Agustin's avatar
Agustin committed
872
  int frame_rx = proc->frame_rx;
873
  int nr_slot_rx = proc->nr_slot_rx;
874
  uint32_t ret = UINT32_MAX, ret1 = UINT32_MAX;
Agustin's avatar
Agustin committed
875
  NR_UE_PDSCH *pdsch_vars;
876
  uint16_t dmrs_len = get_num_dmrs(dlsch0->harq_processes[dlsch0->current_harq_pid]->dlDmrsSymbPos);
877 878
  nr_downlink_indication_t dl_indication;
  fapi_nr_rx_indication_t rx_ind;
cig's avatar
cig committed
879
  uint16_t number_pdus = 1;
880
  // params for UL time alignment procedure
881
  NR_UL_TIME_ALIGNMENT_t *ul_time_alignment = &ue->ul_time_alignment[gNB_id];
882 883 884 885 886 887 888

  uint8_t is_cw0_active = dlsch0->harq_processes[harq_pid]->status;
  uint16_t nb_symb_sch = dlsch0->harq_processes[harq_pid]->nb_symbols;
  uint16_t start_symbol = dlsch0->harq_processes[harq_pid]->start_symbol;
  uint8_t dmrs_type = dlsch0->harq_processes[harq_pid]->dmrsConfigType;

  uint8_t nb_re_dmrs;
889 890 891 892 893 894
  if (dmrs_type==NFAPI_NR_DMRS_TYPE1) {
    nb_re_dmrs = 6*dlsch0->harq_processes[harq_pid]->n_dmrs_cdm_groups;
  }
  else {
    nb_re_dmrs = 4*dlsch0->harq_processes[harq_pid]->n_dmrs_cdm_groups;
  }
895

896
  uint8_t is_cw1_active = 0;
Agustin's avatar
Agustin committed
897 898 899
  if(dlsch1)
    is_cw1_active = dlsch1->harq_processes[harq_pid]->status;

900 901
  LOG_D(PHY,"AbsSubframe %d.%d Start LDPC Decoder for CW0 [harq_pid %d] ? %d \n", frame_rx%1024, nr_slot_rx, harq_pid, is_cw0_active);
  LOG_D(PHY,"AbsSubframe %d.%d Start LDPC Decoder for CW1 [harq_pid %d] ? %d \n", frame_rx%1024, nr_slot_rx, harq_pid, is_cw1_active);
Agustin's avatar
Agustin committed
902 903

  if(is_cw0_active && is_cw1_active)
904
    {
Agustin's avatar
Agustin committed
905 906
      dlsch0->Kmimo = 2;
      dlsch1->Kmimo = 2;
907
    }
Agustin's avatar
Agustin committed
908
  else
909
    {
Agustin's avatar
Agustin committed
910
      dlsch0->Kmimo = 1;
911
    }
Agustin's avatar
Agustin committed
912 913 914 915 916 917
  if (1) {
    switch (pdsch) {
    case SI_PDSCH:
    case RA_PDSCH:
    case P_PDSCH:
    case PDSCH:
918
      pdsch_vars = ue->pdsch_vars[proc->thread_id][gNB_id];
Agustin's avatar
Agustin committed
919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934
      break;
    case PMCH:
    case PDSCH1:
      LOG_E(PHY,"Illegal PDSCH %d for ue_pdsch_procedures\n",pdsch);
      pdsch_vars = NULL;
      return;
      break;
    default:
      pdsch_vars = NULL;
      return;
      break;

    }
    if (frame_rx < *dlsch_errors)
      *dlsch_errors=0;

935
    if (pdsch == RA_PDSCH) {
936 937
      if (ue->prach_resources[gNB_id]!=NULL)
	      dlsch0->rnti = ue->prach_resources[gNB_id]->ra_RNTI;
Agustin's avatar
Agustin committed
938
      else {
939
	      LOG_E(PHY,"[UE %d] Frame %d, nr_slot_rx %d: FATAL, prach_resources is NULL\n", ue->Mod_id, frame_rx, nr_slot_rx);
940 941
	      //mac_xface->macphy_exit("prach_resources is NULL");
	      return;
Agustin's avatar
Agustin committed
942 943 944
      }
    }

945 946 947
    // exit dlsch procedures as there are no active dlsch
    if (is_cw0_active != ACTIVE && is_cw1_active != ACTIVE)
      return;
Agustin's avatar
Agustin committed
948

Francesco Mani's avatar
Francesco Mani committed
949 950 951 952
    // start ldpc decode for CW 0
    dlsch0->harq_processes[harq_pid]->G = nr_get_G(dlsch0->harq_processes[harq_pid]->nb_rb,
                                                   nb_symb_sch,
                                                   nb_re_dmrs,
953
                                                   dmrs_len,
Francesco Mani's avatar
Francesco Mani committed
954 955
                                                   dlsch0->harq_processes[harq_pid]->Qm,
                                                   dlsch0->harq_processes[harq_pid]->Nl);
Agustin's avatar
Agustin committed
956 957 958
#if UE_TIMING_TRACE
      start_meas(&ue->dlsch_unscrambling_stats);
#endif
Hongzhi Wang's avatar
Hongzhi Wang committed
959
      nr_dlsch_unscrambling(pdsch_vars->llr[0],
cig's avatar
cig committed
960 961 962 963
                            dlsch0->harq_processes[harq_pid]->G,
                            0,
                            ue->frame_parms.Nid_cell,
                            dlsch0->rnti);
964
      
Hongzhi Wang's avatar
Hongzhi Wang committed
965

Agustin's avatar
Agustin committed
966 967 968 969 970
#if UE_TIMING_TRACE
      stop_meas(&ue->dlsch_unscrambling_stats);
#endif

#if 0
971 972 973 974 975 976 977
      LOG_I(PHY," ------ start ldpc decoder for AbsSubframe %d.%d / %d  ------  \n", frame_rx, nr_slot_rx, harq_pid);
      LOG_I(PHY,"start ldpc decode for CW 0 for AbsSubframe %d.%d / %d --> nb_rb %d \n", frame_rx, nr_slot_rx, harq_pid, dlsch0->harq_processes[harq_pid]->nb_rb);
      LOG_I(PHY,"start ldpc decode for CW 0 for AbsSubframe %d.%d / %d  --> rb_alloc_even %x \n", frame_rx, nr_slot_rx, harq_pid, dlsch0->harq_processes[harq_pid]->rb_alloc_even);
      LOG_I(PHY,"start ldpc decode for CW 0 for AbsSubframe %d.%d / %d  --> Qm %d \n", frame_rx, nr_slot_rx, harq_pid, dlsch0->harq_processes[harq_pid]->Qm);
      LOG_I(PHY,"start ldpc decode for CW 0 for AbsSubframe %d.%d / %d  --> Nl %d \n", frame_rx, nr_slot_rx, harq_pid, dlsch0->harq_processes[harq_pid]->Nl);
      LOG_I(PHY,"start ldpc decode for CW 0 for AbsSubframe %d.%d / %d  --> G  %d \n", frame_rx, nr_slot_rx, harq_pid, dlsch0->harq_processes[harq_pid]->G);
      LOG_I(PHY,"start ldpc decode for CW 0 for AbsSubframe %d.%d / %d  --> Kmimo  %d \n", frame_rx, nr_slot_rx, harq_pid, dlsch0->Kmimo);
978
      LOG_I(PHY,"start ldpc decode for CW 0 for AbsSubframe %d.%d / %d  --> Pdcch Sym  %d \n", frame_rx, nr_slot_rx, harq_pid, ue->pdcch_vars[proc->thread_id][gNB_id]->num_pdcch_symbols);
Agustin's avatar
Agustin committed
979 980 981
#endif

#if UE_TIMING_TRACE
982
      start_meas(&ue->dlsch_decoding_stats[proc->thread_id]);
Agustin's avatar
Agustin committed
983 984
#endif

985
  if( dlsch_parallel)
986 987
    {
    ret = nr_dlsch_decoding_mthread(ue,
988
			   proc,
989
			   gNB_id,
Agustin's avatar
Agustin committed
990 991 992 993 994
			   pdsch_vars->llr[0],
			   &ue->frame_parms,
			   dlsch0,
			   dlsch0->harq_processes[harq_pid],
			   frame_rx,
Hongzhi Wang's avatar
Hongzhi Wang committed
995
			   nb_symb_sch,
996
			   nr_slot_rx,
Agustin's avatar
Agustin committed
997 998 999
			   harq_pid,
			   pdsch==PDSCH?1:0,
			   dlsch0->harq_processes[harq_pid]->TBS>256?1:0);
1000 1001 1002 1003 1004
    LOG_T(PHY,"dlsch decoding is parallelized, ret = %d\n", ret);
    }
  else
    {
    ret = nr_dlsch_decoding(ue,
1005
			   proc,
1006
			   gNB_id,
Agustin's avatar
Agustin committed
1007 1008 1009 1010 1011
			   pdsch_vars->llr[0],
			   &ue->frame_parms,
			   dlsch0,
			   dlsch0->harq_processes[harq_pid],
			   frame_rx,
Hongzhi Wang's avatar
Hongzhi Wang committed
1012
			   nb_symb_sch,
1013
			   nr_slot_rx,
Agustin's avatar
Agustin committed
1014
			   harq_pid,
1015
			   pdsch==PDSCH?1:0,
Agustin's avatar
Agustin committed
1016
			   dlsch0->harq_processes[harq_pid]->TBS>256?1:0);
1017 1018 1019
      LOG_T(PHY,"Sequential dlsch decoding , ret = %d\n", ret);
     }

Agustin's avatar
Agustin committed
1020 1021

#if UE_TIMING_TRACE
1022
      stop_meas(&ue->dlsch_decoding_stats[proc->thread_id]);
Agustin's avatar
Agustin committed
1023 1024 1025
#if DISABLE_LOG_X
      printf(" --> Unscrambling for CW0 %5.3f\n",
              (ue->dlsch_unscrambling_stats.p_time)/(cpuf*1000.0));
Hongzhi Wang's avatar
Hongzhi Wang committed
1026
      printf("AbsSubframe %d.%d --> LDPC Decoding for CW0 %5.3f\n",
1027
              frame_rx%1024, nr_slot_rx,(ue->dlsch_decoding_stats[proc->thread_id].p_time)/(cpuf*1000.0));
Agustin's avatar
Agustin committed
1028 1029 1030
#else
      LOG_I(PHY, " --> Unscrambling for CW0 %5.3f\n",
              (ue->dlsch_unscrambling_stats.p_time)/(cpuf*1000.0));
Hongzhi Wang's avatar
Hongzhi Wang committed
1031
      LOG_I(PHY, "AbsSubframe %d.%d --> LDPC Decoding for CW0 %5.3f\n",
1032
              frame_rx%1024, nr_slot_rx,(ue->dlsch_decoding_stats[proc->thread_id].p_time)/(cpuf*1000.0));
Agustin's avatar
Agustin committed
1033 1034 1035 1036 1037
#endif

#endif
      if(is_cw1_active)
      {
Hongzhi Wang's avatar
Hongzhi Wang committed
1038
          // start ldpc decode for CW 1
1039 1040 1041 1042 1043
        dlsch1->harq_processes[harq_pid]->G = nr_get_G(dlsch1->harq_processes[harq_pid]->nb_rb,
                                                       nb_symb_sch,
                                                       nb_re_dmrs,
                                                       dmrs_len,
                                                       dlsch1->harq_processes[harq_pid]->Qm,
1044
							 dlsch1->harq_processes[harq_pid]->Nl);
Agustin's avatar
Agustin committed
1045 1046 1047
#if UE_TIMING_TRACE
          start_meas(&ue->dlsch_unscrambling_stats);
#endif
Hongzhi Wang's avatar
Hongzhi Wang committed
1048
          nr_dlsch_unscrambling(pdsch_vars->llr[1],
cig's avatar
cig committed
1049 1050 1051 1052
                                dlsch1->harq_processes[harq_pid]->G,
                                0,
                                ue->frame_parms.Nid_cell,
                                dlsch1->rnti);
Agustin's avatar
Agustin committed
1053 1054 1055 1056 1057
#if UE_TIMING_TRACE
          stop_meas(&ue->dlsch_unscrambling_stats);
#endif

#if 0
1058 1059 1060 1061 1062 1063
          LOG_I(PHY,"start ldpc decode for CW 1 for AbsSubframe %d.%d / %d --> nb_rb %d \n", frame_rx, nr_slot_rx, harq_pid, dlsch1->harq_processes[harq_pid]->nb_rb);
          LOG_I(PHY,"start ldpc decode for CW 1 for AbsSubframe %d.%d / %d  --> rb_alloc_even %x \n", frame_rx, nr_slot_rx, harq_pid, dlsch1->harq_processes[harq_pid]->rb_alloc_even);
          LOG_I(PHY,"start ldpc decode for CW 1 for AbsSubframe %d.%d / %d  --> Qm %d \n", frame_rx, nr_slot_rx, harq_pid, dlsch1->harq_processes[harq_pid]->Qm);
          LOG_I(PHY,"start ldpc decode for CW 1 for AbsSubframe %d.%d / %d  --> Nl %d \n", frame_rx, nr_slot_rx, harq_pid, dlsch1->harq_processes[harq_pid]->Nl);
          LOG_I(PHY,"start ldpc decode for CW 1 for AbsSubframe %d.%d / %d  --> G  %d \n", frame_rx, nr_slot_rx, harq_pid, dlsch1->harq_processes[harq_pid]->G);
          LOG_I(PHY,"start ldpc decode for CW 1 for AbsSubframe %d.%d / %d  --> Kmimo  %d \n", frame_rx, nr_slot_rx, harq_pid, dlsch1->Kmimo);
1064
          LOG_I(PHY,"start ldpc decode for CW 1 for AbsSubframe %d.%d / %d  --> Pdcch Sym  %d \n", frame_rx, nr_slot_rx, harq_pid, ue->pdcch_vars[proc->thread_id][gNB_id]->num_pdcch_symbols);
Agustin's avatar
Agustin committed
1065 1066 1067
#endif

#if UE_TIMING_TRACE
1068
          start_meas(&ue->dlsch_decoding_stats[proc->thread_id]);
Agustin's avatar
Agustin committed
1069 1070
#endif

1071
  if(dlsch_parallel)
1072 1073 1074
    {
    ret1 = nr_dlsch_decoding_mthread(ue,
                                     proc,
1075
                                     gNB_id,
1076 1077 1078 1079 1080 1081
                                     pdsch_vars->llr[1],
                                     &ue->frame_parms,
                                     dlsch1,
                                     dlsch1->harq_processes[harq_pid],
                                     frame_rx,
                                     nb_symb_sch,
1082
				     nr_slot_rx,
1083 1084 1085 1086 1087 1088 1089 1090 1091
                                     harq_pid,
                                     pdsch==PDSCH?1:0,
                                     dlsch1->harq_processes[harq_pid]->TBS>256?1:0);
          LOG_T(PHY,"CW dlsch decoding is parallelized, ret1 = %d\n", ret1);
    }
    else
    {
    ret1 = nr_dlsch_decoding(ue,
			     proc,
1092
			     gNB_id,
1093 1094 1095 1096 1097 1098
                             pdsch_vars->llr[1],
                             &ue->frame_parms,
                             dlsch1,
                             dlsch1->harq_processes[harq_pid],
                             frame_rx,
                             nb_symb_sch,
1099
                             nr_slot_rx,
1100 1101 1102 1103 1104
                             harq_pid,
                             pdsch==PDSCH?1:0,//proc->decoder_switch,
                             dlsch1->harq_processes[harq_pid]->TBS>256?1:0);
    LOG_T(PHY,"CWW sequential dlsch decoding, ret1 = %d\n", ret1);
    }
Agustin's avatar
Agustin committed
1105 1106

#if UE_TIMING_TRACE
1107
          stop_meas(&ue->dlsch_decoding_stats[proc->thread_id]);
Agustin's avatar
Agustin committed
1108 1109 1110
#if DISABLE_LOG_X
          printf(" --> Unscrambling for CW1 %5.3f\n",
                  (ue->dlsch_unscrambling_stats.p_time)/(cpuf*1000.0));
Hongzhi Wang's avatar
Hongzhi Wang committed
1111
          printf("AbsSubframe %d.%d --> ldpc Decoding for CW1 %5.3f\n",
1112
                  frame_rx%1024, nr_slot_rx,(ue->dlsch_decoding_stats[proc->thread_id].p_time)/(cpuf*1000.0));
Agustin's avatar
Agustin committed
1113 1114 1115
#else
          LOG_D(PHY, " --> Unscrambling for CW1 %5.3f\n",
                  (ue->dlsch_unscrambling_stats.p_time)/(cpuf*1000.0));
Hongzhi Wang's avatar
Hongzhi Wang committed
1116
          LOG_D(PHY, "AbsSubframe %d.%d --> ldpc Decoding for CW1 %5.3f\n",
1117
                  frame_rx%1024, nr_slot_rx,(ue->dlsch_decoding_stats[proc->thread_id].p_time)/(cpuf*1000.0));
Agustin's avatar
Agustin committed
1118 1119 1120
#endif

#endif
Hongzhi Wang's avatar
Hongzhi Wang committed
1121
          LOG_I(PHY,"AbsSubframe %d.%d --> ldpc Decoding for CW1 %5.3f\n",
1122
                  frame_rx%1024, nr_slot_rx,(ue->dlsch_decoding_stats[proc->thread_id].p_time)/(cpuf*1000.0));
cig's avatar
cig committed
1123 1124

        LOG_D(PHY, "harq_pid: %d, TBS expected dlsch1: %d \n", harq_pid, dlsch1->harq_processes[harq_pid]->TBS);
1125
      }
Agustin's avatar
Agustin committed
1126

1127
      LOG_D(PHY," ------ end ldpc decoder for AbsSubframe %d.%d ------ decoded in %d \n", frame_rx, nr_slot_rx, ret);
cig's avatar
cig committed
1128
      LOG_D(PHY, "harq_pid: %d, TBS expected dlsch0: %d  \n",harq_pid, dlsch0->harq_processes[harq_pid]->TBS);
cig's avatar
cig committed
1129

1130
      if(ret<dlsch0->max_ldpc_iterations+1){
1131

cig's avatar
cig committed
1132 1133
        switch (pdsch) {
          case RA_PDSCH:
1134 1135
            nr_fill_dl_indication(&dl_indication, NULL, &rx_ind, proc, ue, gNB_id);
            nr_fill_rx_indication(&rx_ind, FAPI_NR_RX_PDU_TYPE_RAR, gNB_id, ue, dlsch0, number_pdus);
cig's avatar
cig committed
1136

1137
            ue->UE_mode[gNB_id] = RA_RESPONSE;
1138
            break;
cig's avatar
cig committed
1139
          case PDSCH:
1140 1141
            nr_fill_dl_indication(&dl_indication, NULL, &rx_ind, proc, ue, gNB_id);
            nr_fill_rx_indication(&rx_ind, FAPI_NR_RX_PDU_TYPE_DLSCH, gNB_id, ue, dlsch0, number_pdus);
1142
            break;
1143
          case SI_PDSCH:
1144 1145
            nr_fill_dl_indication(&dl_indication, NULL, &rx_ind, proc, ue, gNB_id);
            nr_fill_rx_indication(&rx_ind, FAPI_NR_RX_PDU_TYPE_SIB, gNB_id, ue, dlsch0, number_pdus);
1146
            break;
cig's avatar
cig committed
1147
          default:
1148
            break;
cig's avatar
cig committed
1149 1150
        }

cig's avatar
cig committed
1151
        LOG_D(PHY, "In %s DL PDU length in bits: %d, in bytes: %d \n", __FUNCTION__, dlsch0->harq_processes[harq_pid]->TBS, dlsch0->harq_processes[harq_pid]->TBS / 8);
1152

cig's avatar
cig committed
1153
        //  send to mac
cig's avatar
cig committed
1154 1155 1156
        if (ue->if_inst && ue->if_inst->dl_indication) {
          ue->if_inst->dl_indication(&dl_indication, ul_time_alignment);
        }
1157
      }
Agustin's avatar
Agustin committed
1158

1159
      if (ue->mac_enabled == 1) { // TODO: move this from PHY to MAC layer!
1160

1161 1162 1163 1164 1165 1166
        /* Time Alignment procedure
        // - UE processing capability 1
        // - Setting the TA update to be applied after the reception of the TA command
        // - Timing adjustment computed according to TS 38.213 section 4.2
        // - Durations of N1 and N2 symbols corresponding to PDSCH and PUSCH are
        //   computed according to sections 5.3 and 6.4 of TS 38.214 */
1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178
        const int numerology = ue->frame_parms.numerology_index;
        const int ofdm_symbol_size = ue->frame_parms.ofdm_symbol_size;
        const int nb_prefix_samples = ue->frame_parms.nb_prefix_samples;
        const int samples_per_subframe = ue->frame_parms.samples_per_subframe;
        const int slots_per_frame = ue->frame_parms.slots_per_frame;
        const int slots_per_subframe = ue->frame_parms.slots_per_subframe;

        const double tc_factor = 1.0 / samples_per_subframe;
        const uint16_t bw_scaling = get_bw_scaling(ofdm_symbol_size);

        const int Ta_max = 3846; // Max value of 12 bits TA Command
        const double N_TA_max = Ta_max * bw_scaling * tc_factor;
1179

1180 1181
        NR_UE_MAC_INST_t *mac = get_mac_inst(0);

1182
        NR_PUSCH_TimeDomainResourceAllocationList_t *pusch_TimeDomainAllocationList = NULL;
1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206
        if (mac->ULbwp[0] &&
            mac->ULbwp[0]->bwp_Dedicated &&
            mac->ULbwp[0]->bwp_Dedicated->pusch_Config &&
            mac->ULbwp[0]->bwp_Dedicated->pusch_Config->choice.setup &&
            mac->ULbwp[0]->bwp_Dedicated->pusch_Config->choice.setup->pusch_TimeDomainAllocationList) {
          pusch_TimeDomainAllocationList = mac->ULbwp[0]->bwp_Dedicated->pusch_Config->choice.setup->pusch_TimeDomainAllocationList->choice.setup;
        }
        else if (mac->ULbwp[0] &&
                 mac->ULbwp[0]->bwp_Common &&
                 mac->ULbwp[0]->bwp_Common->pusch_ConfigCommon &&
                 mac->ULbwp[0]->bwp_Common->pusch_ConfigCommon->choice.setup &&
                 mac->ULbwp[0]->bwp_Common->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList) {
          pusch_TimeDomainAllocationList = mac->ULbwp[0]->bwp_Common->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList;
        }
        else if (mac->scc_SIB &&
                 mac->scc_SIB->uplinkConfigCommon &&
                 mac->scc_SIB->uplinkConfigCommon->initialUplinkBWP.pusch_ConfigCommon &&
                 mac->scc_SIB->uplinkConfigCommon->initialUplinkBWP.pusch_ConfigCommon->choice.setup &&
                 mac->scc_SIB->uplinkConfigCommon->initialUplinkBWP.pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList) {
          pusch_TimeDomainAllocationList = mac->scc_SIB->uplinkConfigCommon->initialUplinkBWP.pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList;
        }
        long mapping_type_ul = pusch_TimeDomainAllocationList ? pusch_TimeDomainAllocationList->list.array[0]->mappingType : NR_PUSCH_TimeDomainResourceAllocation__mappingType_typeA;

        NR_PDSCH_Config_t *pdsch_Config = (mac->DLbwp[0] && mac->DLbwp[0]->bwp_Dedicated->pdsch_Config->choice.setup) ? mac->DLbwp[0]->bwp_Dedicated->pdsch_Config->choice.setup : NULL;
1207
        NR_PDSCH_TimeDomainResourceAllocationList_t *pdsch_TimeDomainAllocationList = NULL;
1208
        if (mac->DLbwp[0] && mac->DLbwp[0]->bwp_Dedicated->pdsch_Config->choice.setup->pdsch_TimeDomainAllocationList)
1209
          pdsch_TimeDomainAllocationList = pdsch_Config->pdsch_TimeDomainAllocationList->choice.setup;
1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221
        else if (mac->DLbwp[0] && mac->DLbwp[0]->bwp_Common->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList)
          pdsch_TimeDomainAllocationList = mac->DLbwp[0]->bwp_Common->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList;
        else if (mac->scc_SIB && mac->scc_SIB->downlinkConfigCommon.initialDownlinkBWP.pdsch_ConfigCommon->choice.setup)
          pdsch_TimeDomainAllocationList = mac->scc_SIB->downlinkConfigCommon.initialDownlinkBWP.pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList;
        long mapping_type_dl = pdsch_TimeDomainAllocationList ? pdsch_TimeDomainAllocationList->list.array[0]->mappingType : NR_PDSCH_TimeDomainResourceAllocation__mappingType_typeA;

        NR_DMRS_DownlinkConfig_t *NR_DMRS_dlconfig = NULL;
        if (pdsch_Config) {
          if (mapping_type_dl == NR_PDSCH_TimeDomainResourceAllocation__mappingType_typeA)
            NR_DMRS_dlconfig = (NR_DMRS_DownlinkConfig_t *)pdsch_Config->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup;
          else
            NR_DMRS_dlconfig = (NR_DMRS_DownlinkConfig_t *)pdsch_Config->dmrs_DownlinkForPDSCH_MappingTypeB->choice.setup;
1222
        }
1223 1224

        pdsch_dmrs_AdditionalPosition_t add_pos_dl = pdsch_dmrs_pos2;
1225
        if (NR_DMRS_dlconfig && NR_DMRS_dlconfig->dmrs_AdditionalPosition)
1226 1227
          add_pos_dl = *NR_DMRS_dlconfig->dmrs_AdditionalPosition;

1228
        /* PDSCH decoding time N_1 for processing capability 1 */
1229
        int N_1;
1230 1231

        if (add_pos_dl == pdsch_dmrs_pos0)
1232
          N_1 = pdsch_N_1_capability_1[numerology][1];
1233
        else if (add_pos_dl == pdsch_dmrs_pos1 || add_pos_dl == pdsch_dmrs_pos2)
1234 1235 1236 1237 1238
          N_1 = pdsch_N_1_capability_1[numerology][2];
        else
          N_1 = pdsch_N_1_capability_1[numerology][3];

        /* PUSCH preapration time N_2 for processing capability 1 */
1239
        const int N_2 = pusch_N_2_timing_capability_1[numerology][1];
1240 1241

        /* d_1_1 depending on the number of PDSCH symbols allocated */
1242 1243
        const int d = 0; // TODO number of overlapping symbols of the scheduling PDCCH and the scheduled PDSCH
        int d_1_1 = 0;
1244
        if (mapping_type_dl == NR_PDSCH_TimeDomainResourceAllocation__mappingType_typeA)
1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257
         if (nb_symb_sch + start_symbol < 7)
          d_1_1 = 7 - (nb_symb_sch + start_symbol);
         else
          d_1_1 = 0;
        else // mapping type B
          switch (nb_symb_sch){
            case 7: d_1_1 = 0; break;
            case 4: d_1_1 = 3; break;
            case 2: d_1_1 = 3 + d; break;
            default: break;
          }

        /* d_2_1 */
1258
        int d_2_1;
1259
        if (mapping_type_ul == NR_PUSCH_TimeDomainResourceAllocation__mappingType_typeB && start_symbol != 0)
1260 1261 1262 1263
          d_2_1 = 0;
        else
          d_2_1 = 1;

1264 1265 1266
        /* d_2_2 */
        const double d_2_2 = 0.0; // set to 0 because there is only 1 BWP: TODO this should corresponds to the switching time as defined in TS 38.133

1267 1268
        /* N_t_1 time duration in msec of N_1 symbols corresponding to a PDSCH reception time
        // N_t_2 time duration in msec of N_2 symbols corresponding to a PUSCH preparation time */
1269 1270
        double N_t_1 = (N_1 + d_1_1) * (ofdm_symbol_size + nb_prefix_samples) * tc_factor;
        double N_t_2 = (N_2 + d_2_1) * (ofdm_symbol_size + nb_prefix_samples) * tc_factor;
1271 1272 1273 1274
        if (N_t_2 < d_2_2) N_t_2 = d_2_2;

        /* Time alignment procedure */
        // N_t_1 + N_t_2 + N_TA_max must be in msec
1275 1276
        const double t_subframe = 1.0; // subframe duration of 1 msec
        const int ul_tx_timing_adjustment = 1 + (int)ceil(slots_per_subframe*(N_t_1 + N_t_2 + N_TA_max + 0.5)/t_subframe);
1277

1278
        if (ul_time_alignment->apply_ta == 1){
1279 1280
          ul_time_alignment->ta_slot = (nr_slot_rx + ul_tx_timing_adjustment) % slots_per_frame;
          if (nr_slot_rx + ul_tx_timing_adjustment > slots_per_frame){
1281 1282 1283 1284 1285 1286
            ul_time_alignment->ta_frame = (frame_rx + 1) % 1024;
          } else {
            ul_time_alignment->ta_frame = frame_rx;
          }
          // reset TA flag
          ul_time_alignment->apply_ta = 0;
1287
          LOG_D(PHY,"Frame %d slot %d -- Starting UL time alignment procedures. TA update will be applied at frame %d slot %d\n", frame_rx, nr_slot_rx, ul_time_alignment->ta_frame, ul_time_alignment->ta_slot);
1288
        }
1289 1290
      }
  }
Agustin's avatar
Agustin committed
1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303
}


/*!
 * \brief This is the UE synchronize thread.
 * It performs band scanning and synchonization.
 * \param arg is a pointer to a \ref PHY_VARS_NR_UE structure.
 * \returns a pointer to an int. The storage is not on the heap and must not be freed.
 */
#ifdef UE_SLOT_PARALLELISATION
#define FIFO_PRIORITY   40
void *UE_thread_slot1_dl_processing(void *arg) {

1304 1305 1306 1307
  static __thread int UE_dl_slot1_processing_retval;
  struct rx_tx_thread_data *rtd = arg;
  UE_nr_rxtx_proc_t *proc = rtd->proc;
  PHY_VARS_NR_UE    *ue   = rtd->UE;
Agustin's avatar
Agustin committed
1308

1309 1310 1311
  uint8_t pilot1;

  proc->instance_cnt_slot1_dl_processing=-1;
1312
  proc->nr_slot_rx = proc->sub_frame_start * ue->frame_parms.slots_per_subframe;
1313 1314 1315

  char threadname[256];
  sprintf(threadname,"UE_thread_slot1_dl_processing_%d", proc->sub_frame_start);
Agustin's avatar
Agustin committed
1316

1317 1318 1319 1320
  cpu_set_t cpuset;
  CPU_ZERO(&cpuset);
  if ( (proc->sub_frame_start+1)%RX_NB_TH == 0 && threads.slot1_proc_one != -1 )
    CPU_SET(threads.slot1_proc_one, &cpuset);
1321
  if ( RX_NB_TH > 1 && (proc->sub_frame_start+1)%RX_NB_TH == 1 && threads.slot1_proc_two != -1 )
1322
    CPU_SET(threads.slot1_proc_two, &cpuset);
1323
  if ( RX_NB_TH > 2 && (proc->sub_frame_start+1)%RX_NB_TH == 2 && threads.slot1_proc_three != -1 )
1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342
    CPU_SET(threads.slot1_proc_three, &cpuset);

  init_thread(900000,1000000 , FIFO_PRIORITY-1, &cpuset,
	      threadname);

  while (!oai_exit) {
    if (pthread_mutex_lock(&proc->mutex_slot1_dl_processing) != 0) {
      LOG_E( PHY, "[SCHED][UE] error locking mutex for UE slot1 dl processing\n" );
      exit_fun("nothing to add");
    }
    while (proc->instance_cnt_slot1_dl_processing < 0) {
      // most of the time, the thread is waiting here
      pthread_cond_wait( &proc->cond_slot1_dl_processing, &proc->mutex_slot1_dl_processing );
    }
    if (pthread_mutex_unlock(&proc->mutex_slot1_dl_processing) != 0) {
      LOG_E( PHY, "[SCHED][UE] error unlocking mutex for UE slot1 dl processing \n" );
      exit_fun("nothing to add");
    }

1343 1344 1345 1346
    int frame_rx            = proc->frame_rx;
    uint8_t subframe_rx         = proc->nr_slot_rx / ue->frame_parms.slots_per_subframe;
    uint8_t next_subframe_rx    = (1 + subframe_rx) % NR_NUMBER_OF_SUBFRAMES_PER_FRAME;
    uint8_t next_subframe_slot0 = next_subframe_rx * ue->frame_parms.slots_per_subframe;
1347

1348 1349
    uint8_t slot1  = proc->nr_slot_rx + 1;
    uint8_t pilot0 = 0;
1350

1351
    //printf("AbsSubframe %d.%d execute dl slot1 processing \n", frame_rx, nr_slot_rx);
1352 1353 1354 1355 1356 1357 1358 1359

    if (ue->frame_parms.Ncp == 0) {  // normal prefix
      pilot1 = 4;
    } else { // extended prefix
      pilot1 = 3;
    }

    /**** Slot1 FE Processing ****/
Agustin's avatar
Agustin committed
1360
#if UE_TIMING_TRACE
1361
    start_meas(&ue->ue_front_end_per_slot_stat[proc->thread_id][1]);
Agustin's avatar
Agustin committed
1362
#endif
1363
    // I- start dl slot1 processing
1364
    // do first symbol of next downlink nr_slot_rx for channel estimation
1365
    /*
1366 1367
    // 1- perform FFT for pilot ofdm symbols first (ofdmSym0 next nr_slot_rx ofdmSym11)
    if (nr_subframe_select(&ue->frame_parms,next_nr_slot_rx) != SF_UL)
1368 1369 1370 1371 1372 1373 1374
    {
    front_end_fft(ue,
    pilot0,
    next_subframe_slot0,
    0,
    0);
    }
Agustin's avatar
Agustin committed
1375

1376 1377 1378 1379 1380 1381 1382
    front_end_fft(ue,
    pilot1,
    slot1,
    0,
    0);
    */
    // 1- perform FFT
1383
    for (int l=1; l<ue->frame_parms.symbols_per_slot>>1; l++)
1384 1385 1386
      {
	//if( (l != pilot0) && (l != pilot1))
	{
Agustin's avatar
Agustin committed
1387
#if UE_TIMING_TRACE
1388
	  start_meas(&ue->ofdm_demod_stats);
Agustin's avatar
Agustin committed
1389
#endif
1390
	  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SLOT_FEP, VCD_FUNCTION_IN);
1391
	  //printf("AbsSubframe %d.%d FFT slot %d, symbol %d\n", frame_rx,nr_slot_rx,slot1,l);
1392
	  front_end_fft(ue,
Agustin's avatar
Agustin committed
1393 1394 1395 1396
                        l,
                        slot1,
                        0,
                        0);
1397
	  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SLOT_FEP, VCD_FUNCTION_OUT);
Agustin's avatar
Agustin committed
1398
#if UE_TIMING_TRACE
1399
	  stop_meas(&ue->ofdm_demod_stats);
Agustin's avatar
Agustin committed
1400
#endif
1401 1402
	}
      } // for l=1..l2
Agustin's avatar
Agustin committed
1403

1404
    if (nr_subframe_select(&ue->frame_parms,next_nr_slot_rx) != SF_UL)
1405
      {
1406
	//printf("AbsSubframe %d.%d FFT slot %d, symbol %d\n", frame_rx,nr_slot_rx,next_subframe_slot0,pilot0);
1407 1408 1409 1410 1411 1412
	front_end_fft(ue,
		      pilot0,
		      next_subframe_slot0,
		      0,
		      0);
      }
Agustin's avatar
Agustin committed
1413

1414
    // 2- perform Channel Estimation for slot1
1415
    for (int l=1; l<ue->frame_parms.symbols_per_slot>>1; l++)
1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427
      {
	if(l == pilot1)
	  {
	    //wait until channel estimation for pilot0/slot1 is available
	    uint32_t wait = 0;
	    while(proc->chan_est_pilot0_slot1_available == 0)
	      {
		usleep(1);
		wait++;
	      }
	    //printf("[slot1 dl processing] ChanEst symbol %d slot %d wait%d\n",l,slot1,wait);
	  }
1428
	//printf("AbsSubframe %d.%d ChanEst slot %d, symbol %d\n", frame_rx,nr_slot_rx,slot1,l);
1429 1430 1431 1432
	front_end_chanEst(ue,
			  l,
			  slot1,
			  0);
1433
	ue_measurement_procedures(l-1,ue,proc,0,slot1,0,ue->mode);
1434
      }
1435
    //printf("AbsSubframe %d.%d ChanEst slot %d, symbol %d\n", frame_rx,nr_slot_rx,next_subframe_slot0,pilot0);
1436 1437 1438 1439
    front_end_chanEst(ue,
		      pilot0,
		      next_subframe_slot0,
		      0);
Agustin's avatar
Agustin committed
1440

1441
    if ( (nr_slot_rx == 0) && (ue->decode_MIB == 1))
1442
      {
1443
	ue_pbch_procedures(0,ue,proc,0);
1444
      }
Agustin's avatar
Agustin committed
1445

1446
    proc->chan_est_slot1_available = 1;
1447 1448
    //printf("Set available slot 1channelEst to 1 AbsSubframe %d.%d \n",frame_rx,nr_slot_rx);
    //printf(" [slot1 dl processing] ==> FFT/CHanEst Done for AbsSubframe %d.%d \n", proc->frame_rx, proc->nr_slot_rx);
Agustin's avatar
Agustin committed
1449

1450
    //printf(" [slot1 dl processing] ==> Start LLR Comuptation slot1 for AbsSubframe %d.%d \n", proc->frame_rx, proc->nr_slot_rx);
Agustin's avatar
Agustin committed
1451 1452 1453


#if UE_TIMING_TRACE
1454
    stop_meas(&ue->ue_front_end_per_slot_stat[proc->thread_id][1]);
Agustin's avatar
Agustin committed
1455
#if DISABLE_LOG_X
1456
    printf("[AbsSFN %d.%d] Slot1: FFT + Channel Estimate + Pdsch Proc Slot0 %5.2f \n",frame_rx,nr_slot_rx,ue->ue_front_end_per_slot_stat[proc->thread_id][1].p_time/(cpuf*1000.0));
Agustin's avatar
Agustin committed
1457
#else
1458
    LOG_D(PHY, "[AbsSFN %d.%d] Slot1: FFT + Channel Estimate + Pdsch Proc Slot0 %5.2f \n",frame_rx,nr_slot_rx,ue->ue_front_end_per_slot_stat[proc->thread_id][1].p_time/(cpuf*1000.0));
Agustin's avatar
Agustin committed
1459 1460 1461 1462 1463 1464 1465
#endif
#endif


    //wait until pdcch is decoded
    uint32_t wait = 0;
    while(proc->dci_slot0_available == 0)
1466
      {
Agustin's avatar
Agustin committed
1467 1468
        usleep(1);
        wait++;
1469
      }
1470
    //printf("[slot1 dl processing] AbsSubframe %d.%d LLR Computation Start wait DCI %d\n",frame_rx,nr_slot_rx,wait);
Agustin's avatar
Agustin committed
1471 1472 1473 1474

    /**** Pdsch Procedure Slot1 ****/
    // start slot1 thread for Pdsch Procedure (slot1)
    // do procedures for C-RNTI
1475
    //printf("AbsSubframe %d.%d Pdsch Procedure (slot1)\n",frame_rx,nr_slot_rx);
Agustin's avatar
Agustin committed
1476 1477 1478


#if UE_TIMING_TRACE
1479
    start_meas(&ue->pdsch_procedures_per_slot_stat[proc->thread_id][1]);
Agustin's avatar
Agustin committed
1480 1481 1482
#endif
    // start slave thread for Pdsch Procedure (slot1)
    // do procedures for C-RNTI
1483
    uint8_t gNB_id = 0;
1484

1485
    if (ue->dlsch[proc->thread_id][gNB_id][0]->active == 1) {
1486 1487 1488 1489 1490 1491 1492
      //wait until first ofdm symbol is processed
      //wait = 0;
      //while(proc->first_symbol_available == 0)
      //{
      //    usleep(1);
      //    wait++;
      //}
1493
      //printf("[slot1 dl processing] AbsSubframe %d.%d LLR Computation Start wait First Ofdm Sym %d\n",frame_rx,nr_slot_rx,wait);
1494 1495 1496 1497

      //VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDSCH_PROC, VCD_FUNCTION_IN);
      ue_pdsch_procedures(ue,
			  proc,
1498
			  gNB_id,
1499
			  PDSCH,
1500
			  ue->dlsch[proc->thread_id][gNB_id][0],
1501
			  NULL,
1502 1503
			  (ue->frame_parms.symbols_per_slot>>1),
			  ue->frame_parms.symbols_per_slot-1,
1504
			  abstraction_flag);
1505 1506
      LOG_D(PHY," ------ end PDSCH ChannelComp/LLR slot 0: AbsSubframe %d.%d ------  \n", frame_rx%1024, nr_slot_rx);
      LOG_D(PHY," ------ --> PDSCH Turbo Decoder slot 0/1: AbsSubframe %d.%d ------  \n", frame_rx%1024, nr_slot_rx);
Agustin's avatar
Agustin committed
1507 1508 1509
    }

    // do procedures for SI-RNTI
1510
    if ((ue->dlsch_SI[gNB_id]) && (ue->dlsch_SI[gNB_id]->active == 1)) {
1511 1512
      ue_pdsch_procedures(ue,
			  proc,
1513
			  gNB_id,
1514
			  SI_PDSCH,
1515
			  ue->dlsch_SI[gNB_id],
1516
			  NULL,
1517 1518
			  (ue->frame_parms.symbols_per_slot>>1),
			  ue->frame_parms.symbols_per_slot-1,
1519
			  abstraction_flag);
Agustin's avatar
Agustin committed
1520 1521 1522
    }

    // do procedures for P-RNTI
1523
    if ((ue->dlsch_p[gNB_id]) && (ue->dlsch_p[gNB_id]->active == 1)) {
1524 1525
      ue_pdsch_procedures(ue,
			  proc,
1526
			  gNB_id,
1527
			  P_PDSCH,
1528
			  ue->dlsch_p[gNB_id],
1529
			  NULL,
1530 1531
			  (ue->frame_parms.symbols_per_slot>>1),
			  ue->frame_parms.symbols_per_slot-1,
1532
			  abstraction_flag);
Agustin's avatar
Agustin committed
1533 1534
    }
    // do procedures for RA-RNTI
1535
    if ((ue->dlsch_ra[gNB_id]) && (ue->dlsch_ra[gNB_id]->active == 1) && (UE_mode != PUSCH)) {
1536 1537
      ue_pdsch_procedures(ue,
			  proc,
1538
			  gNB_id,
1539
			  RA_PDSCH,
1540
			  ue->dlsch_ra[gNB_id],
1541
			  NULL,
1542 1543
			  (ue->frame_parms.symbols_per_slot>>1),
			  ue->frame_parms.symbols_per_slot-1,
1544
			  abstraction_flag);
Agustin's avatar
Agustin committed
1545 1546 1547
    }

    proc->llr_slot1_available=1;
1548
    //printf("Set available LLR slot1 to 1 AbsSubframe %d.%d \n",frame_rx,nr_slot_rx);
Agustin's avatar
Agustin committed
1549 1550

#if UE_TIMING_TRACE
1551
    stop_meas(&ue->pdsch_procedures_per_slot_stat[proc->thread_id][1]);
Agustin's avatar
Agustin committed
1552
#if DISABLE_LOG_X
1553
    printf("[AbsSFN %d.%d] Slot1: LLR Computation %5.2f \n",frame_rx,nr_slot_rx,ue->pdsch_procedures_per_slot_stat[proc->thread_id][1].p_time/(cpuf*1000.0));
Agustin's avatar
Agustin committed
1554
#else
1555
    LOG_D(PHY, "[AbsSFN %d.%d] Slot1: LLR Computation %5.2f \n",frame_rx,nr_slot_rx,ue->pdsch_procedures_per_slot_stat[proc->thread_id][1].p_time/(cpuf*1000.0));
Agustin's avatar
Agustin committed
1556 1557 1558
#endif
#endif

1559 1560 1561 1562 1563 1564 1565 1566
    if (pthread_mutex_lock(&proc->mutex_slot1_dl_processing) != 0) {
      LOG_E( PHY, "[SCHED][UE] error locking mutex for UE RXTX\n" );
      exit_fun("noting to add");
    }
    proc->instance_cnt_slot1_dl_processing--;
    if (pthread_mutex_unlock(&proc->mutex_slot1_dl_processing) != 0) {
      LOG_E( PHY, "[SCHED][UE] error unlocking mutex for UE FEP Slo1\n" );
      exit_fun("noting to add");
Agustin's avatar
Agustin committed
1567
    }
1568 1569 1570 1571
  }
  // thread finished
  free(arg);
  return &UE_dl_slot1_processing_retval;
Agustin's avatar
Agustin committed
1572 1573 1574
}
#endif

1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622
int is_ssb_in_slot(fapi_nr_config_request_t *config, int frame, int slot, NR_DL_FRAME_PARMS *fp)
{
  int mu = fp->numerology_index;
  //uint8_t half_frame_index = fp->half_frame_bit;
  //uint8_t i_ssb = fp->ssb_index;
  uint8_t Lmax = fp->Lmax;

  if (!(frame%(1<<(config->ssb_table.ssb_period-1)))){

    if(Lmax <= 8) {
      if(slot <=3 && (((config->ssb_table.ssb_mask_list[0].ssb_mask << 2*slot)&0x80000000) == 0x80000000 || ((config->ssb_table.ssb_mask_list[0].ssb_mask << (2*slot +1))&0x80000000) == 0x80000000))
      return 1;
      else return 0;
    
    }
    else if(Lmax == 64) {
      if (mu == NR_MU_3){

        if (slot>=0 && slot <= 7){
          if(((config->ssb_table.ssb_mask_list[0].ssb_mask << 2*slot)&0x80000000) == 0x80000000 || ((config->ssb_table.ssb_mask_list[0].ssb_mask << (2*slot +1))&0x80000000) == 0x80000000)
          return 1;
          else return 0;
        }
      else if (slot>=10 && slot <=17){
         if(((config->ssb_table.ssb_mask_list[0].ssb_mask << 2*(slot-2))&0x80000000) == 0x80000000 || ((config->ssb_table.ssb_mask_list[0].ssb_mask << (2*(slot-2) +1))&0x80000000) == 0x80000000)
         return 1;
         else return 0;
      }
      else if (slot>=20 && slot <=27){
         if(((config->ssb_table.ssb_mask_list[1].ssb_mask << 2*(slot-20))&0x80000000) == 0x80000000 || ((config->ssb_table.ssb_mask_list[1].ssb_mask << (2*(slot-20) +1))&0x80000000) == 0x80000000)
         return 1;
         else return 0;
      }
      else if (slot>=30 && slot <=37){
         if(((config->ssb_table.ssb_mask_list[1].ssb_mask << 2*(slot-22))&0x80000000) == 0x80000000 || ((config->ssb_table.ssb_mask_list[1].ssb_mask << (2*(slot-22) +1))&0x80000000) == 0x80000000)
         return 1;
         else return 0;
       }
      else return 0;

    }


    else if (mu == NR_MU_4) {
         AssertFatal(0==1, "not implemented for mu =  %d yet\n", mu);
    }
    else AssertFatal(0==1, "Invalid numerology index %d for the synchronization block\n", mu);
   }
Florian Kaltenberger's avatar
Florian Kaltenberger committed
1623
   else AssertFatal(0==1, "Invalid Lmax %u for the synchronization block\n", Lmax);
1624 1625 1626 1627
  }
  else return 0;

}
Agustin's avatar
Agustin committed
1628

1629
int is_pbch_in_slot(fapi_nr_config_request_t *config, int frame, int slot, NR_DL_FRAME_PARMS *fp)  {
1630

1631
  int ssb_slot_decoded = (fp->ssb_index>>1) + ((fp->ssb_index>>4)<<1); //slot in which the decoded SSB can be found
Agustin's avatar
Agustin committed
1632

1633
  if (config->ssb_table.ssb_period == 0) {  
1634
    // check for pbch in corresponding slot each half frame
1635 1636
    if (fp->half_frame_bit)
      return(slot == ssb_slot_decoded || slot == ssb_slot_decoded - fp->slots_per_frame/2);
1637
    else
1638
      return(slot == ssb_slot_decoded || slot == ssb_slot_decoded + fp->slots_per_frame/2);
1639 1640 1641
  }
  else {
    // if the current frame is supposed to contain ssb
1642
    if (!(frame%(1<<(config->ssb_table.ssb_period-1))))
1643 1644 1645
      return(slot == ssb_slot_decoded);
    else
      return 0;
1646 1647 1648
  }
}

Agustin's avatar
Agustin committed
1649

1650 1651
int phy_procedures_nrUE_RX(PHY_VARS_NR_UE *ue,
                           UE_nr_rxtx_proc_t *proc,
cig's avatar
cig committed
1652
                           uint8_t gNB_id,
1653 1654
                           uint8_t dlsch_parallel,
                           notifiedFIFO_t *txFifo
1655 1656
                           )
{                                         
Agustin's avatar
Agustin committed
1657
  int frame_rx = proc->frame_rx;
1658
  int nr_slot_rx = proc->nr_slot_rx;
1659
  int slot_pbch;
Hongzhi Wang's avatar
Hongzhi Wang committed
1660
  int slot_ssb;
1661
  NR_UE_PDCCH *pdcch_vars  = ue->pdcch_vars[proc->thread_id][0];
1662
  fapi_nr_config_request_t *cfg = &ue->nrUE_config;
1663

1664
  uint8_t nb_symb_pdcch = pdcch_vars->nb_search_space > 0 ? pdcch_vars->pdcch_config[0].coreset.duration : 0;
1665
  uint8_t dci_cnt = 0;
1666
  NR_DL_FRAME_PARMS *fp = &ue->frame_parms;
1667
  
Hongzhi Wang's avatar
Hongzhi Wang committed
1668
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_RX, VCD_FUNCTION_IN);
cig's avatar
cig committed
1669

1670
  LOG_D(PHY," ****** start RX-Chain for Frame.Slot %d.%d ******  \n", frame_rx%1024, nr_slot_rx);
Agustin's avatar
Agustin committed
1671

1672
  /*
1673
  uint8_t next1_thread_id = proc->thread_id== (RX_NB_TH-1) ? 0:(proc->thread_id+1);
Agustin's avatar
Agustin committed
1674
  uint8_t next2_thread_id = next1_thread_id== (RX_NB_TH-1) ? 0:(next1_thread_id+1);
1675
  */
Agustin's avatar
Agustin committed
1676

1677 1678
  int coreset_nb_rb=0;
  int coreset_start_rb=0;
1679

1680 1681
  if (pdcch_vars->nb_search_space > 0)
    get_coreset_rballoc(pdcch_vars->pdcch_config[0].coreset.frequency_domain_resource,&coreset_nb_rb,&coreset_start_rb);
1682

1683
  slot_pbch = is_pbch_in_slot(cfg, frame_rx, nr_slot_rx, fp);
1684
  slot_ssb  = is_ssb_in_slot(cfg, frame_rx, nr_slot_rx, fp);
Hongzhi Wang's avatar
Hongzhi Wang committed
1685 1686

  // looking for pbch only in slot where it is supposed to be
1687
  if (slot_ssb) {
1688
    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SLOT_FEP_PBCH, VCD_FUNCTION_IN);
1689
    LOG_D(PHY," ------  PBCH ChannelComp/LLR: frame.slot %d.%d ------  \n", frame_rx%1024, nr_slot_rx);
1690
    for (int i=1; i<4; i++) {
Hongzhi Wang's avatar
Hongzhi Wang committed
1691

1692
      nr_slot_fep(ue,
1693
                  proc,
1694
                  (ue->symbol_offset+i)%(fp->symbols_per_slot),
1695
                  nr_slot_rx);
Hongzhi Wang's avatar
Hongzhi Wang committed
1696 1697

#if UE_TIMING_TRACE
1698
      start_meas(&ue->dlsch_channel_estimation_stats);
Hongzhi Wang's avatar
Hongzhi Wang committed
1699
#endif
1700
      nr_pbch_channel_estimation(ue,proc,gNB_id,nr_slot_rx,(ue->symbol_offset+i)%(fp->symbols_per_slot),i-1,(fp->ssb_index)&7,fp->half_frame_bit);
Hongzhi Wang's avatar
Hongzhi Wang committed
1701
#if UE_TIMING_TRACE
1702
      stop_meas(&ue->dlsch_channel_estimation_stats);
Hongzhi Wang's avatar
Hongzhi Wang committed
1703
#endif
1704
    }
1705

cig's avatar
cig committed
1706
    nr_ue_rsrp_measurements(ue, gNB_id, proc, nr_slot_rx, 0);
1707

1708
    if ((ue->decode_MIB == 1) && slot_pbch) {
1709

1710
      LOG_D(PHY," ------  Decode MIB: frame.slot %d.%d ------  \n", frame_rx%1024, nr_slot_rx);
cig's avatar
cig committed
1711
      nr_ue_pbch_procedures(gNB_id, ue, proc, 0);
Hongzhi Wang's avatar
Hongzhi Wang committed
1712 1713

      if (ue->no_timing_correction==0) {
1714
        LOG_D(PHY,"start adjust sync slot = %d no timing %d\n", nr_slot_rx, ue->no_timing_correction);
1715
        nr_adjust_synch_ue(fp,
cig's avatar
cig committed
1716
                           ue,
cig's avatar
cig committed
1717
                           gNB_id,
1718
                           frame_rx,
1719
                           nr_slot_rx,
cig's avatar
cig committed
1720 1721
                           0,
                           16384);
Hongzhi Wang's avatar
Hongzhi Wang committed
1722
      }
cig's avatar
cig committed
1723 1724 1725

      LOG_D(PHY, "Doing N0 measurements in %s\n", __FUNCTION__);
      nr_ue_rrc_measurements(ue, proc, nr_slot_rx);
1726
      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SLOT_FEP_PBCH, VCD_FUNCTION_OUT);
Hongzhi Wang's avatar
Hongzhi Wang committed
1727
    }
1728
  }
1729

1730
  if ((frame_rx%64 == 0) && (nr_slot_rx==0)) {
rmagueta's avatar
rmagueta committed
1731
    LOG_I(PHY,"============================================\n");
1732
    LOG_I(PHY,"Harq round stats for Downlink: %d/%d/%d/%d DLSCH errors: %d\n",ue->dl_stats[0],ue->dl_stats[1],ue->dl_stats[2],ue->dl_stats[3],ue->dl_stats[4]);
rmagueta's avatar
rmagueta committed
1733
    LOG_I(PHY,"============================================\n");
1734 1735
  }

1736
#ifdef NR_PDCCH_SCHED
1737

1738
  LOG_D(PHY," ------ --> PDCCH ChannelComp/LLR Frame.slot %d.%d ------  \n", frame_rx%1024, nr_slot_rx);
1739
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SLOT_FEP_PDCCH, VCD_FUNCTION_IN);
1740
  for (uint16_t l=0; l<nb_symb_pdcch; l++) {
cig's avatar
cig committed
1741

Agustin's avatar
Agustin committed
1742
#if UE_TIMING_TRACE
1743
    start_meas(&ue->ofdm_demod_stats);
Agustin's avatar
Agustin committed
1744
#endif
1745
    nr_slot_fep(ue,
1746
                proc,
cig's avatar
cig committed
1747
                l,
1748
                nr_slot_rx);
1749

1750 1751 1752
    dci_cnt = 0;
    for(int n_ss = 0; n_ss<pdcch_vars->nb_search_space; n_ss++) {

1753
    // note: this only works if RBs for PDCCH are contigous!
1754 1755 1756
    LOG_D(PHY, "pdcch_channel_estimation: first_carrier_offset %d, BWPStart %d, coreset_start_rb %d\n",
          fp->first_carrier_offset, pdcch_vars->pdcch_config[n_ss].BWPStart, coreset_start_rb);

1757 1758
    if (coreset_nb_rb > 0)
      nr_pdcch_channel_estimation(ue,
1759
                                  proc,
1760
                                  gNB_id,
1761 1762
                                  nr_slot_rx,
                                  l,
rmagueta's avatar
rmagueta committed
1763
                                  fp->first_carrier_offset+(pdcch_vars->pdcch_config[n_ss].BWPStart + coreset_start_rb)*12,
1764 1765
                                  coreset_nb_rb);

Agustin's avatar
Agustin committed
1766
#if UE_TIMING_TRACE
1767
    stop_meas(&ue->ofdm_demod_stats);
Agustin's avatar
Agustin committed
1768
#endif
Raymond Knopp's avatar
Raymond Knopp committed
1769

rmagueta's avatar
rmagueta committed
1770
      dci_cnt = dci_cnt + nr_ue_pdcch_procedures(gNB_id, ue, proc);
1771 1772
    }
  }
1773
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SLOT_FEP_PDCCH, VCD_FUNCTION_OUT);
1774 1775 1776

  if (dci_cnt > 0) {

1777
    LOG_D(PHY,"[UE %d] Frame %d, nr_slot_rx %d: found %d DCIs\n", ue->Mod_id, frame_rx, nr_slot_rx, dci_cnt);
Hongzhi Wang's avatar
Hongzhi Wang committed
1778

Raphael Defosseux's avatar
Raphael Defosseux committed
1779
    NR_UE_DLSCH_t *dlsch = NULL;
1780 1781
    if (ue->dlsch[proc->thread_id][gNB_id][0]->active == 1){
      dlsch = ue->dlsch[proc->thread_id][gNB_id][0];
1782 1783
    } else if (ue->dlsch_SI[0]->active == 1){
      dlsch = ue->dlsch_SI[0];
cig's avatar
cig committed
1784 1785 1786
    } else if (ue->dlsch_ra[0]->active == 1){
      dlsch = ue->dlsch_ra[0];
    }
1787 1788

    if (dlsch) {
1789
      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SLOT_FEP_PDSCH, VCD_FUNCTION_IN);
1790 1791 1792 1793 1794
      uint8_t harq_pid = dlsch->current_harq_pid;
      NR_DL_UE_HARQ_t *dlsch0_harq = dlsch->harq_processes[harq_pid];
      uint16_t nb_symb_sch = dlsch0_harq->nb_symbols;
      uint16_t start_symb_sch = dlsch0_harq->start_symbol;

1795
      LOG_D(PHY," ------ --> PDSCH ChannelComp/LLR Frame.slot %d.%d ------  \n", frame_rx%1024, nr_slot_rx);
1796 1797 1798 1799
      //to update from pdsch config

      for (uint16_t m=start_symb_sch;m<(nb_symb_sch+start_symb_sch) ; m++){
        nr_slot_fep(ue,
1800 1801
                    proc,
                    m,  //to be updated from higher layer
1802
                    nr_slot_rx);
1803
      }
1804
      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SLOT_FEP_PDSCH, VCD_FUNCTION_OUT);
1805
    }
cig's avatar
cig committed
1806
  } else {
1807
    LOG_D(PHY,"[UE %d] Frame %d, nr_slot_rx %d: No DCIs found\n", ue->Mod_id, frame_rx, nr_slot_rx);
hongzhi wang's avatar
hongzhi wang committed
1808
  }
cig's avatar
cig committed
1809 1810

#endif //NR_PDCCH_SCHED
1811

1812
  // Start PUSCH processing here. It runs in parallel with PDSCH processing
1813 1814
  notifiedFIFO_elt_t *newElt = newNotifiedFIFO_elt(sizeof(nr_rxtx_thread_data_t), proc->nr_slot_tx,txFifo,processSlotTX);
  nr_rxtx_thread_data_t *curMsg=(nr_rxtx_thread_data_t *)NotifiedFifoData(newElt);
1815 1816
  curMsg->proc = *proc;
  curMsg->UE = ue;
1817
  pushTpool(&(get_nrUE_params()->Tpool), newElt);
1818

Agustin's avatar
Agustin committed
1819 1820
#if UE_TIMING_TRACE
  start_meas(&ue->generic_stat);
1821
#endif
Agustin's avatar
Agustin committed
1822
  // do procedures for C-RNTI
1823
  int ret_pdsch = 0;
1824
  if (ue->dlsch[proc->thread_id][gNB_id][0]->active == 1) {
1825
    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDSCH_PROC_C, VCD_FUNCTION_IN);
1826
    ret_pdsch = nr_ue_pdsch_procedures(ue,
1827
			   proc,
cig's avatar
cig committed
1828
			   gNB_id,
1829
			   PDSCH,
1830
			   ue->dlsch[proc->thread_id][gNB_id][0],
1831
			   NULL);
cig's avatar
cig committed
1832

cig's avatar
cig committed
1833
    nr_ue_measurement_procedures(2, ue, proc, gNB_id, nr_slot_rx);
1834
    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDSCH_PROC_C, VCD_FUNCTION_OUT);
Agustin's avatar
Agustin committed
1835
  }
1836

Agustin's avatar
Agustin committed
1837
  // do procedures for SI-RNTI
cig's avatar
cig committed
1838
  if ((ue->dlsch_SI[gNB_id]) && (ue->dlsch_SI[gNB_id]->active == 1)) {
Agustin's avatar
Agustin committed
1839
    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDSCH_PROC_SI, VCD_FUNCTION_IN);
1840
    nr_ue_pdsch_procedures(ue,
1841 1842 1843 1844 1845
                           proc,
                           gNB_id,
                           SI_PDSCH,
                           ue->dlsch_SI[gNB_id],
                           NULL);
1846
    
1847 1848 1849 1850 1851 1852 1853
    nr_ue_dlsch_procedures(ue,
                           proc,
                           gNB_id,
                           SI_PDSCH,
                           ue->dlsch_SI[gNB_id],
                           NULL,
                           &ue->dlsch_SI_errors[gNB_id],
1854
                           dlsch_parallel);
1855 1856 1857 1858

    // deactivate dlsch once dlsch proc is done
    ue->dlsch_SI[gNB_id]->active = 0;

Agustin's avatar
Agustin committed
1859 1860
    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDSCH_PROC_SI, VCD_FUNCTION_OUT);
  }
1861

1862
  // do procedures for P-RNTI
cig's avatar
cig committed
1863
  if ((ue->dlsch_p[gNB_id]) && (ue->dlsch_p[gNB_id]->active == 1)) {
Agustin's avatar
Agustin committed
1864
    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDSCH_PROC_P, VCD_FUNCTION_IN);
1865
    nr_ue_pdsch_procedures(ue,
1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878
                           proc,
                           gNB_id,
                           P_PDSCH,
                           ue->dlsch_p[gNB_id],
                           NULL);

    nr_ue_dlsch_procedures(ue,
                           proc,
                           gNB_id,
                           P_PDSCH,
                           ue->dlsch_p[gNB_id],
                           NULL,
                           &ue->dlsch_p_errors[gNB_id],
1879
                           dlsch_parallel);
1880 1881 1882

    // deactivate dlsch once dlsch proc is done
    ue->dlsch_p[gNB_id]->active = 0;
Agustin's avatar
Agustin committed
1883 1884
    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDSCH_PROC_P, VCD_FUNCTION_OUT);
  }
1885

Agustin's avatar
Agustin committed
1886
  // do procedures for RA-RNTI
cig's avatar
cig committed
1887
  if ((ue->dlsch_ra[gNB_id]) && (ue->dlsch_ra[gNB_id]->active == 1) && (ue->UE_mode[gNB_id] != PUSCH)) {
Agustin's avatar
Agustin committed
1888
    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDSCH_PROC_RA, VCD_FUNCTION_IN);
1889
    nr_ue_pdsch_procedures(ue,
1890 1891 1892 1893 1894
                           proc,
                           gNB_id,
                           RA_PDSCH,
                           ue->dlsch_ra[gNB_id],
                           NULL);
1895

1896 1897
    nr_ue_dlsch_procedures(ue,
                           proc,
cig's avatar
cig committed
1898
                           gNB_id,
1899
                           RA_PDSCH,
cig's avatar
cig committed
1900
                           ue->dlsch_ra[gNB_id],
1901
                           NULL,
cig's avatar
cig committed
1902
                           &ue->dlsch_ra_errors[gNB_id],
1903
                           dlsch_parallel);
1904

1905 1906 1907 1908
    // deactivate dlsch once dlsch proc is done
    ue->dlsch_ra[gNB_id]->active = 0;

    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDSCH_PROC_RA, VCD_FUNCTION_OUT);
Agustin's avatar
Agustin committed
1909
  }
Raymond Knopp's avatar
Raymond Knopp committed
1910
    
Agustin's avatar
Agustin committed
1911
  // do procedures for C-RNTI
1912
  if (ue->dlsch[proc->thread_id][gNB_id][0]->active == 1) {
cig's avatar
cig committed
1913

1914
    LOG_D(PHY, "DLSCH data reception at nr_slot_rx: %d \n \n", nr_slot_rx);
Agustin's avatar
Agustin committed
1915
    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDSCH_PROC, VCD_FUNCTION_IN);
1916

Agustin's avatar
Agustin committed
1917
#if UE_TIMING_TRACE
1918
    start_meas(&ue->dlsch_procedures_stat[proc->thread_id]);
1919
#endif
hongzhi wang's avatar
hongzhi wang committed
1920

1921 1922
    if (ret_pdsch >= 0)
      nr_ue_dlsch_procedures(ue,
1923
			   proc,
cig's avatar
cig committed
1924
			   gNB_id,
1925
			   PDSCH,
1926 1927
			   ue->dlsch[proc->thread_id][gNB_id][0],
			   ue->dlsch[proc->thread_id][gNB_id][1],
cig's avatar
cig committed
1928
			   &ue->dlsch_errors[gNB_id],
1929
			   dlsch_parallel);
1930 1931


Agustin's avatar
Agustin committed
1932
#if UE_TIMING_TRACE
1933
  stop_meas(&ue->dlsch_procedures_stat[proc->thread_id]);
Agustin's avatar
Agustin committed
1934
#if DISABLE_LOG_X
1935 1936
  printf("[SFN %d] Slot1:       Pdsch Proc %5.2f\n",nr_slot_rx,ue->pdsch_procedures_stat[proc->thread_id].p_time/(cpuf*1000.0));
  printf("[SFN %d] Slot0 Slot1: Dlsch Proc %5.2f\n",nr_slot_rx,ue->dlsch_procedures_stat[proc->thread_id].p_time/(cpuf*1000.0));
Agustin's avatar
Agustin committed
1937
#else
1938 1939
  LOG_D(PHY, "[SFN %d] Slot1:       Pdsch Proc %5.2f\n",nr_slot_rx,ue->pdsch_procedures_stat[proc->thread_id].p_time/(cpuf*1000.0));
  LOG_D(PHY, "[SFN %d] Slot0 Slot1: Dlsch Proc %5.2f\n",nr_slot_rx,ue->dlsch_procedures_stat[proc->thread_id].p_time/(cpuf*1000.0));
Agustin's avatar
Agustin committed
1940 1941 1942 1943
#endif

#endif

1944
  // deactivate dlsch once dlsch proc is done
1945
  ue->dlsch[proc->thread_id][gNB_id][0]->active = 0;
1946

1947
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDSCH_PROC, VCD_FUNCTION_OUT);
Agustin's avatar
Agustin committed
1948

1949
 }
1950

Agustin's avatar
Agustin committed
1951
#if UE_TIMING_TRACE
1952
start_meas(&ue->generic_stat);
Agustin's avatar
Agustin committed
1953 1954 1955
#endif

#if 0
1956

1957
  if(nr_slot_rx==5 &&  ue->dlsch[proc->thread_id][gNB_id][0]->harq_processes[ue->dlsch[proc->thread_id][gNB_id][0]->current_harq_pid]->nb_rb > 20){
Agustin's avatar
Agustin committed
1958
       //write_output("decoder_llr.m","decllr",dlsch_llr,G,1,0);
1959
       //write_output("llr.m","llr",  &ue->pdsch_vars[proc->thread_id][gNB_id]->llr[0][0],(14*nb_rb*12*dlsch1_harq->Qm) - 4*(nb_rb*4*dlsch1_harq->Qm),1,0);
1960

1961
       write_output("rxdataF0_current.m"    , "rxdataF0", &ue->common_vars.common_vars_rx_data_per_thread[proc->thread_id].rxdataF[0][0],14*fp->ofdm_symbol_size,1,1);
1962
       //write_output("rxdataF0_previous.m"    , "rxdataF0_prev_sss", &ue->common_vars.common_vars_rx_data_per_thread[next_thread_id].rxdataF[0][0],14*fp->ofdm_symbol_size,1,1);
1963

1964
       //write_output("rxdataF0_previous.m"    , "rxdataF0_prev", &ue->common_vars.common_vars_rx_data_per_thread[next_thread_id].rxdataF[0][0],14*fp->ofdm_symbol_size,1,1);
1965

1966
       write_output("dl_ch_estimates.m", "dl_ch_estimates_sfn5", &ue->common_vars.common_vars_rx_data_per_thread[proc->thread_id].dl_ch_estimates[0][0][0],14*fp->ofdm_symbol_size,1,1);
1967 1968 1969 1970
       write_output("dl_ch_estimates_ext.m", "dl_ch_estimatesExt_sfn5", &ue->pdsch_vars[proc->thread_id][gNB_id]->dl_ch_estimates_ext[0][0],14*fp->N_RB_DL*12,1,1);
       write_output("rxdataF_comp00.m","rxdataF_comp00",         &ue->pdsch_vars[proc->thread_id][gNB_id]->rxdataF_comp0[0][0],14*fp->N_RB_DL*12,1,1);
       //write_output("magDLFirst.m", "magDLFirst", &phy_vars_ue->pdsch_vars[proc->thread_id][gNB_id]->dl_ch_mag0[0][0],14*fp->N_RB_DL*12,1,1);
       //write_output("magDLSecond.m", "magDLSecond", &phy_vars_ue->pdsch_vars[proc->thread_id][gNB_id]->dl_ch_magb0[0][0],14*fp->N_RB_DL*12,1,1);
1971

Agustin's avatar
Agustin committed
1972 1973 1974
       AssertFatal (0,"");
  }
#endif
1975

Agustin's avatar
Agustin committed
1976
  // duplicate harq structure
1977
/*
1978 1979
  uint8_t          current_harq_pid        = ue->dlsch[proc->thread_id][gNB_id][0]->current_harq_pid;
  NR_DL_UE_HARQ_t *current_harq_processes = ue->dlsch[proc->thread_id][gNB_id][0]->harq_processes[current_harq_pid];
cig's avatar
cig committed
1980 1981
  NR_DL_UE_HARQ_t *harq_processes_dest    = ue->dlsch[next1_thread_id][gNB_id][0]->harq_processes[current_harq_pid];
  NR_DL_UE_HARQ_t *harq_processes_dest1    = ue->dlsch[next2_thread_id][gNB_id][0]->harq_processes[current_harq_pid];
1982
  */
1983 1984 1985
  /*nr_harq_status_t *current_harq_ack = &ue->dlsch[proc->thread_id][gNB_id][0]->harq_ack[nr_slot_rx];
  nr_harq_status_t *harq_ack_dest    = &ue->dlsch[next1_thread_id][gNB_id][0]->harq_ack[nr_slot_rx];
  nr_harq_status_t *harq_ack_dest1    = &ue->dlsch[next2_thread_id][gNB_id][0]->harq_ack[nr_slot_rx];
1986
*/
Agustin's avatar
Agustin committed
1987

1988
  //copy_harq_proc_struct(harq_processes_dest, current_harq_processes);
1989
//copy_ack_struct(harq_ack_dest, current_harq_ack);
Agustin's avatar
Agustin committed
1990

1991
//copy_harq_proc_struct(harq_processes_dest1, current_harq_processes);
1992
//copy_ack_struct(harq_ack_dest1, current_harq_ack);
Agustin's avatar
Agustin committed
1993

1994
if (nr_slot_rx==9) {
1995
  if (frame_rx % 10 == 0) {
cig's avatar
cig committed
1996 1997
    if ((ue->dlsch_received[gNB_id] - ue->dlsch_received_last[gNB_id]) != 0)
      ue->dlsch_fer[gNB_id] = (100*(ue->dlsch_errors[gNB_id] - ue->dlsch_errors_last[gNB_id]))/(ue->dlsch_received[gNB_id] - ue->dlsch_received_last[gNB_id]);
Agustin's avatar
Agustin committed
1998

cig's avatar
cig committed
1999 2000
    ue->dlsch_errors_last[gNB_id] = ue->dlsch_errors[gNB_id];
    ue->dlsch_received_last[gNB_id] = ue->dlsch_received[gNB_id];
2001
  }
Agustin's avatar
Agustin committed
2002 2003


cig's avatar
cig committed
2004 2005
  ue->bitrate[gNB_id] = (ue->total_TBS[gNB_id] - ue->total_TBS_last[gNB_id])*100;
  ue->total_TBS_last[gNB_id] = ue->total_TBS[gNB_id];
2006
  LOG_D(PHY,"[UE %d] Calculating bitrate Frame %d: total_TBS = %d, total_TBS_last = %d, bitrate %f kbits\n",
cig's avatar
cig committed
2007 2008
	ue->Mod_id,frame_rx,ue->total_TBS[gNB_id],
	ue->total_TBS_last[gNB_id],(float) ue->bitrate[gNB_id]/1000.0);
Agustin's avatar
Agustin committed
2009

2010 2011
#if UE_AUTOTEST_TRACE
  if ((frame_rx % 100 == 0)) {
cig's avatar
cig committed
2012
    LOG_I(PHY,"[UE  %d] AUTOTEST Metric : UE_DLSCH_BITRATE = %5.2f kbps (frame = %d) \n", ue->Mod_id, (float) ue->bitrate[gNB_id]/1000.0, frame_rx);
Agustin's avatar
Agustin committed
2013
  }
2014 2015 2016
#endif

 }
Agustin's avatar
Agustin committed
2017 2018

#if UE_TIMING_TRACE
2019 2020
stop_meas(&ue->generic_stat);
printf("after tubo until end of Rx %5.2f \n",ue->generic_stat.p_time/(cpuf*1000.0));
Agustin's avatar
Agustin committed
2021 2022
#endif

2023
#ifdef EMOS
cig's avatar
cig committed
2024
phy_procedures_emos_UE_RX(ue,slot,gNB_id);
2025
#endif
Agustin's avatar
Agustin committed
2026 2027


2028
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_RX, VCD_FUNCTION_OUT);
Agustin's avatar
Agustin committed
2029 2030

#if UE_TIMING_TRACE
2031
stop_meas(&ue->phy_proc_rx[proc->thread_id]);
Agustin's avatar
Agustin committed
2032
#if DISABLE_LOG_X
2033
printf("------FULL RX PROC [SFN %d]: %5.2f ------\n",nr_slot_rx,ue->phy_proc_rx[proc->thread_id].p_time/(cpuf*1000.0));
Agustin's avatar
Agustin committed
2034
#else
2035
LOG_D(PHY, "------FULL RX PROC [SFN %d]: %5.2f ------\n",nr_slot_rx,ue->phy_proc_rx[proc->thread_id].p_time/(cpuf*1000.0));
Agustin's avatar
Agustin committed
2036 2037 2038
#endif
#endif

2039
//#endif //pdsch
2040

2041
LOG_D(PHY," ****** end RX-Chain  for AbsSubframe %d.%d ******  \n", frame_rx%1024, nr_slot_rx);
2042
return (0);
Agustin's avatar
Agustin committed
2043
}
2044 2045


2046
uint8_t nr_is_cqi_TXOp(PHY_VARS_NR_UE *ue,
2047 2048 2049
		            UE_nr_rxtx_proc_t *proc,
					uint8_t gNB_id)
{
2050
  int subframe = proc->nr_slot_tx / ue->frame_parms.slots_per_subframe;
2051 2052
  int frame    = proc->frame_tx;
  CQI_REPORTPERIODIC *cqirep = &ue->cqi_report_config[gNB_id].CQI_ReportPeriodic;
2053

2054 2055 2056 2057
  //LOG_I(PHY,"[UE %d][CRNTI %x] AbsSubFrame %d.%d Checking for CQI TXOp (cqi_ConfigIndex %d) isCQIOp %d\n",
  //      ue->Mod_id,ue->pdcch_vars[gNB_id]->crnti,frame,subframe,
  //      cqirep->cqi_PMI_ConfigIndex,
  //      (((10*frame + subframe) % cqirep->Npd) == cqirep->N_OFFSET_CQI));
2058

2059 2060 2061 2062 2063 2064
  if (cqirep->cqi_PMI_ConfigIndex==-1)
    return(0);
  else if (((10*frame + subframe) % cqirep->Npd) == cqirep->N_OFFSET_CQI)
    return(1);
  else
    return(0);
2065 2066 2067
}


2068
uint8_t nr_is_ri_TXOp(PHY_VARS_NR_UE *ue,
2069 2070 2071
		           UE_nr_rxtx_proc_t *proc,
				   uint8_t gNB_id)
{
2072
  int subframe = proc->nr_slot_tx / ue->frame_parms.slots_per_subframe;
2073 2074 2075 2076
  int frame    = proc->frame_tx;
  CQI_REPORTPERIODIC *cqirep = &ue->cqi_report_config[gNB_id].CQI_ReportPeriodic;
  int log2Mri = cqirep->ri_ConfigIndex/161;
  int N_OFFSET_RI = cqirep->ri_ConfigIndex % 161;
2077

2078 2079 2080 2081 2082 2083 2084 2085 2086 2087
  //LOG_I(PHY,"[UE %d][CRNTI %x] AbsSubFrame %d.%d Checking for RI TXOp (ri_ConfigIndex %d) isRIOp %d\n",
  //      ue->Mod_id,ue->pdcch_vars[gNB_id]->crnti,frame,subframe,
  //      cqirep->ri_ConfigIndex,
  //      (((10*frame + subframe + cqirep->N_OFFSET_CQI - N_OFFSET_RI) % (cqirep->Npd<<log2Mri)) == 0));
  if (cqirep->ri_ConfigIndex==-1)
    return(0);
  else if (((10*frame + subframe + cqirep->N_OFFSET_CQI - N_OFFSET_RI) % (cqirep->Npd<<log2Mri)) == 0)
    return(1);
  else
    return(0);
2088 2089
}

cig's avatar
cig committed
2090 2091
// todo:
// - power control as per 38.213 ch 7.4
cig's avatar
cig committed
2092
void nr_ue_prach_procedures(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, uint8_t gNB_id) {
cig's avatar
cig committed
2093

2094
  int frame_tx = proc->frame_tx, nr_slot_tx = proc->nr_slot_tx, prach_power; // tx_amp
2095
  uint8_t mod_id = ue->Mod_id;
cig's avatar
cig committed
2096
  NR_PRACH_RESOURCES_t * prach_resources = ue->prach_resources[gNB_id];
2097
  AssertFatal(prach_resources != NULL, "ue->prach_resources[%u] == NULL\n", gNB_id);
2098
  uint8_t nr_prach = 0;
2099 2100 2101

  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_TX_PRACH, VCD_FUNCTION_IN);

cig's avatar
cig committed
2102
  if (ue->mac_enabled == 0){
cig's avatar
cig committed
2103

cig's avatar
cig committed
2104 2105 2106
    prach_resources->ra_TDD_map_index = 0;
    prach_resources->ra_PREAMBLE_RECEIVED_TARGET_POWER = 10;
    prach_resources->ra_RNTI = 0x1234;
cig's avatar
cig committed
2107
    nr_prach = 1;
cig's avatar
cig committed
2108 2109
    prach_resources->init_msg1 = 1;

cig's avatar
cig committed
2110
  } else {
cig's avatar
cig committed
2111

2112
    nr_prach = nr_ue_get_rach(prach_resources, &ue->prach_vars[0]->prach_pdu, mod_id, ue->CC_id, frame_tx, gNB_id, nr_slot_tx);
2113
    LOG_D(PHY, "In %s:[%d.%d] getting PRACH resources : %d\n", __FUNCTION__, frame_tx, nr_slot_tx,nr_prach);
2114 2115
  }

2116
  if (nr_prach == GENERATE_PREAMBLE) {
2117

2118 2119
    if (ue->mac_enabled == 1) {
      int16_t pathloss = get_nr_PL(mod_id, ue->CC_id, gNB_id);
cig's avatar
cig committed
2120
      int16_t ra_preamble_rx_power = (int16_t)(prach_resources->ra_PREAMBLE_RECEIVED_TARGET_POWER - pathloss + 30);
2121
      ue->tx_power_dBm[nr_slot_tx] = min(nr_get_Pcmax(mod_id), ra_preamble_rx_power);
2122

2123
      LOG_D(PHY,"DEBUG [UE %d][RAPROC][%d.%d]: Generating PRACH Msg1 (preamble %d, PL %d dB, P0_PRACH %d, TARGET_RECEIVED_POWER %d dBm, RA-RNTI %x)\n",
2124 2125 2126 2127 2128 2129 2130 2131
        mod_id,
        frame_tx,
        nr_slot_tx,
        prach_resources->ra_PreambleIndex,
        pathloss,
        ue->tx_power_dBm[nr_slot_tx],
        prach_resources->ra_PREAMBLE_RECEIVED_TARGET_POWER,
        prach_resources->ra_RNTI);
cig's avatar
cig committed
2132
    }
2133

cig's avatar
cig committed
2134
    ue->prach_vars[gNB_id]->amp = AMP;
2135

cig's avatar
cig committed
2136
    /* #if defined(EXMIMO) || defined(OAI_USRP) || defined(OAI_BLADERF) || defined(OAI_LMSSDR) || defined(OAI_ADRV9371_ZC706)
2137
      tx_amp = get_tx_amp_prach(ue->tx_power_dBm[nr_slot_tx], ue->tx_power_max_dBm, ue->frame_parms.N_RB_UL);
2138 2139
      if (tx_amp != -1)
        ue->prach_vars[gNB_id]->amp = tx_amp;
2140
    #else
cig's avatar
cig committed
2141
      ue->prach_vars[gNB_id]->amp = AMP;
cig's avatar
cig committed
2142
    #endif */
2143 2144 2145

    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_GENERATE_PRACH, VCD_FUNCTION_IN);

2146
    prach_power = generate_nr_prach(ue, gNB_id, nr_slot_tx);
2147 2148

    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_GENERATE_PRACH, VCD_FUNCTION_OUT);
cig's avatar
cig committed
2149

cig's avatar
cig committed
2150
    LOG_D(PHY, "In %s: [UE %d][RAPROC][%d.%d]: Generated PRACH Msg1 (TX power PRACH %d dBm, digital power %d dBW (amp %d)\n",
cig's avatar
cig committed
2151
      __FUNCTION__,
2152 2153 2154
      mod_id,
      frame_tx,
      nr_slot_tx,
2155
      ue->tx_power_dBm[nr_slot_tx],
2156 2157 2158 2159
      dB_fixed(prach_power),
      ue->prach_vars[gNB_id]->amp);

    if (ue->mac_enabled == 1)
2160
      nr_Msg1_transmitted(mod_id, ue->CC_id, frame_tx, gNB_id);
2161

2162 2163
  } else if (nr_prach == WAIT_CONTENTION_RESOLUTION) {
    LOG_D(PHY, "In %s: [UE %d] RA waiting contention resolution\n", __FUNCTION__, mod_id);
rmagueta's avatar
rmagueta committed
2164
    ue->UE_mode[gNB_id] = RA_WAIT_CR;
2165
  } else if (nr_prach == RA_SUCCEEDED) {
2166 2167
    LOG_D(PHY, "In %s: [UE %d] RA completed, setting UE mode to PUSCH\n", __FUNCTION__, mod_id);
    ue->UE_mode[gNB_id] = PUSCH;
2168
  } else if(nr_prach == RA_FAILED){
2169 2170
    LOG_D(PHY, "In %s: [UE %d] RA failed, setting UE mode to PRACH\n", __FUNCTION__, mod_id);
    ue->UE_mode[gNB_id] = PRACH;
2171 2172 2173
  }

  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_TX_PRACH, VCD_FUNCTION_OUT);
2174

2175
}