phy_procedures_nr_ue.c 88.6 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 56
#include "LAYER2/NR_MAC_UE/mac_proto.h"
#include "LAYER2/NR_MAC_UE/nr_l1_helpers.h"
Agustin's avatar
Agustin committed
57

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

#ifndef PUCCH
#define PUCCH
#endif

68
#include "common/utils/LOG/log.h"
Agustin's avatar
Agustin committed
69 70 71 72 73

#ifdef EMOS
fifo_dump_emos_UE emos_dump_UE;
#endif

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

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

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

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

cig's avatar
cig committed
87
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};
Agustin's avatar
Agustin committed
88

cig's avatar
cig committed
89 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
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,
123
                           NR_UE_DLSCH_t *dlsch1,
cig's avatar
cig committed
124 125
                           uint16_t n_pdus){

126

cig's avatar
cig committed
127 128 129 130 131 132 133
  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
134
    case FAPI_NR_RX_PDU_TYPE_SIB:
135 136 137 138 139
      rx_ind->rx_indication_body[n_pdus - 1].pdsch_pdu.harq_pid = dlsch0->current_harq_pid;
      rx_ind->rx_indication_body[n_pdus - 1].pdsch_pdu.ack_nack = dlsch0->harq_processes[dlsch0->current_harq_pid]->ack;
      rx_ind->rx_indication_body[n_pdus - 1].pdsch_pdu.pdu = dlsch0->harq_processes[dlsch0->current_harq_pid]->b;
      rx_ind->rx_indication_body[n_pdus - 1].pdsch_pdu.pdu_length = dlsch0->harq_processes[dlsch0->current_harq_pid]->TBS / 8;
    break;
cig's avatar
cig committed
140
    case FAPI_NR_RX_PDU_TYPE_DLSCH:
141 142 143 144 145 146 147 148 149 150
      if(dlsch0) {
        rx_ind->rx_indication_body[n_pdus - 1].pdsch_pdu.harq_pid = dlsch0->current_harq_pid;
        rx_ind->rx_indication_body[n_pdus - 1].pdsch_pdu.ack_nack = dlsch0->harq_processes[dlsch0->current_harq_pid]->ack;
        rx_ind->rx_indication_body[n_pdus - 1].pdsch_pdu.pdu = dlsch0->harq_processes[dlsch0->current_harq_pid]->b;
        rx_ind->rx_indication_body[n_pdus - 1].pdsch_pdu.pdu_length = dlsch0->harq_processes[dlsch0->current_harq_pid]->TBS / 8;
      }
      if(dlsch1) {
        AssertFatal(1==0,"Second codeword currently not supported\n");
      }
      break;
cig's avatar
cig committed
151
    case FAPI_NR_RX_PDU_TYPE_RAR:
152 153 154 155
      rx_ind->rx_indication_body[n_pdus - 1].pdsch_pdu.harq_pid = dlsch0->current_harq_pid;
      rx_ind->rx_indication_body[n_pdus - 1].pdsch_pdu.ack_nack = dlsch0->harq_processes[dlsch0->current_harq_pid]->ack;
      rx_ind->rx_indication_body[n_pdus - 1].pdsch_pdu.pdu = dlsch0->harq_processes[dlsch0->current_harq_pid]->b;
      rx_ind->rx_indication_body[n_pdus - 1].pdsch_pdu.pdu_length = dlsch0->harq_processes[dlsch0->current_harq_pid]->TBS / 8;
cig's avatar
cig committed
156
    break;
157 158 159
    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
160
      rx_ind->rx_indication_body[n_pdus - 1].ssb_pdu.ssb_index = (frame_parms->ssb_index)&0x7;
161 162 163
      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;
164
      rx_ind->rx_indication_body[n_pdus - 1].ssb_pdu.rsrp_dBm = ue->measurements.rsrp_dBm[gNB_id];
cig's avatar
cig committed
165 166 167 168 169 170 171 172 173 174
    break;
    default:
    break;
  }

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

}

175
int get_tx_amp_prach(int power_dBm, int power_max_dBm, int N_RB_UL){
Agustin's avatar
Agustin committed
176

177
  int gain_dB = power_dBm - power_max_dBm, amp_x_100 = -1;
Agustin's avatar
Agustin committed
178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198

  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:
199 200
  LOG_E(PHY, "Unknown PRB size %d\n", N_RB_UL);
  return (amp_x_100);
Agustin's avatar
Agustin committed
201
  break;
202
  }
Agustin's avatar
Agustin committed
203
  if (gain_dB < -30) {
204 205 206
    return (amp_x_100/3162);
  } else if (gain_dB > 0)
    return (amp_x_100);
Agustin's avatar
Agustin committed
207
  else
208
    return (amp_x_100/gain_table[-gain_dB]);  // 245 corresponds to the factor sqrt(25/6)
Agustin's avatar
Agustin committed
209

210
  return (amp_x_100);
Agustin's avatar
Agustin committed
211 212
}

cig's avatar
cig committed
213
UE_MODE_t get_nrUE_mode(uint8_t Mod_id,uint8_t CC_id,uint8_t gNB_id){
214 215
  return(PHY_vars_UE_g[Mod_id][CC_id]->UE_mode[gNB_id]);
}
Agustin's avatar
Agustin committed
216

217 218 219 220 221 222 223 224 225
// 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
226
}
Agustin's avatar
Agustin committed
227

cig's avatar
cig committed
228 229 230 231 232 233
// 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
234 235 236 237 238 239 240 241 242
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) {

243 244
      uint16_t ofdm_symbol_size = ue->frame_parms.ofdm_symbol_size;
      uint16_t bw_scaling = get_bw_scaling(ofdm_symbol_size);
245

246
      ue->timing_advance += (ul_time_alignment->ta_command - 31) * bw_scaling;
247

rmagueta's avatar
rmagueta committed
248
      LOG_D(PHY, "In %s: [UE %d] [%d.%d] Got timing advance command %u from MAC, new value is %d\n",
249 250 251 252 253 254
        __FUNCTION__,
        ue->Mod_id,
        frame_tx,
        slot_tx,
        ul_time_alignment->ta_command,
        ue->timing_advance);
Agustin's avatar
Agustin committed
255

cig's avatar
cig committed
256 257
      ul_time_alignment->ta_frame = -1;
      ul_time_alignment->ta_slot = -1;
Agustin's avatar
Agustin committed
258

cig's avatar
cig committed
259 260
    }
  }
Agustin's avatar
Agustin committed
261
}
Agustin's avatar
Agustin committed
262

263
void phy_procedures_nrUE_TX(PHY_VARS_NR_UE *ue,
264
                            UE_nr_rxtx_proc_t *proc,
265
                            uint8_t gNB_id) {
cig's avatar
cig committed
266

267
  int slot_tx = proc->nr_slot_tx;
Agustin's avatar
Agustin committed
268 269
  int frame_tx = proc->frame_tx;

cig's avatar
cig committed
270
  AssertFatal(ue->CC_id == 0, "Transmission on secondary CCs is not supported yet\n");
Agustin's avatar
Agustin committed
271 272 273

  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_TX,VCD_FUNCTION_IN);

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

276
  LOG_D(PHY,"****** start TX-Chain for AbsSubframe %d.%d ******\n", frame_tx, slot_tx);
Agustin's avatar
Agustin committed
277

frtabu's avatar
frtabu committed
278

Agustin's avatar
Agustin committed
279 280
  start_meas(&ue->phy_proc_tx);

281
  if (ue->UE_mode[gNB_id] <= PUSCH){
282

283 284 285 286
    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
287

288
  }
Agustin's avatar
Agustin committed
289 290 291

  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_TX, VCD_FUNCTION_OUT);
  stop_meas(&ue->phy_proc_tx);
frtabu's avatar
frtabu committed
292

293

Agustin's avatar
Agustin committed
294 295
}

cig's avatar
cig committed
296 297 298
void nr_ue_measurement_procedures(uint16_t l,
                                  PHY_VARS_NR_UE *ue,
                                  UE_nr_rxtx_proc_t *proc,
299
                                  uint8_t gNB_id,
cig's avatar
cig committed
300
                                  uint16_t slot){
Agustin's avatar
Agustin committed
301 302

  NR_DL_FRAME_PARMS *frame_parms=&ue->frame_parms;
303 304
  int frame_rx   = proc->frame_rx;
  int nr_slot_rx = proc->nr_slot_rx;
Agustin's avatar
Agustin committed
305 306
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_MEASUREMENT_PROCEDURES, VCD_FUNCTION_IN);

Hongzhi Wang's avatar
Hongzhi Wang committed
307
  if (l==2) {
cig's avatar
cig committed
308 309 310 311 312 313 314 315

    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
316

Agustin's avatar
Agustin committed
317 318
#if T_TRACER
    if(slot == 0)
319
      T(T_UE_PHY_MEAS, T_INT(gNB_id),  T_INT(ue->Mod_id), T_INT(frame_rx%1024), T_INT(nr_slot_rx),
320 321 322 323 324 325 326
	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
327 328 329
#endif
  }

Hongzhi Wang's avatar
Hongzhi Wang committed
330 331 332 333 334 335 336 337
  // 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);


338 339
    //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
340 341
    
    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_GAIN_CONTROL, VCD_FUNCTION_OUT);
Hongzhi Wang's avatar
Hongzhi Wang committed
342 343 344

}

Agustin's avatar
Agustin committed
345 346 347
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_MEASUREMENT_PROCEDURES, VCD_FUNCTION_OUT);
}

348
void nr_ue_pbch_procedures(uint8_t gNB_id,
349 350 351
			   PHY_VARS_NR_UE *ue,
			   UE_nr_rxtx_proc_t *proc,
			   uint8_t abstraction_flag)
Agustin's avatar
Agustin committed
352
{
Hongzhi Wang's avatar
Hongzhi Wang committed
353
  int ret = 0;
Agustin's avatar
Agustin committed
354 355 356 357

  DevAssert(ue);

  int frame_rx = proc->frame_rx;
358
  int nr_slot_rx = proc->nr_slot_rx;
Agustin's avatar
Agustin committed
359 360 361

  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_PBCH_PROCEDURES, VCD_FUNCTION_IN);

362
  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);
363

laurent's avatar
fixes  
laurent committed
364
  ret = nr_rx_pbch(ue, proc,
365 366 367 368 369
                   ue->pbch_vars[gNB_id],
                   &ue->frame_parms,
                   gNB_id,
                   (ue->frame_parms.ssb_index)&7,
                   SISO);
Agustin's avatar
Agustin committed
370

Hongzhi Wang's avatar
Hongzhi Wang committed
371
  if (ret==0) {
372

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

375
    // Switch to PRACH state if it is first PBCH after initial synch and no timing correction is performed
376
    if (ue->UE_mode[gNB_id] == NOT_SYNCHED && ue->no_timing_correction == 1){
377 378 379 380 381 382 383
      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;
      }
384
    }
Agustin's avatar
Agustin committed
385 386

#ifdef DEBUG_PHY_PROC
387
    uint16_t frame_tx;
388
    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
389 390
    ue->Mod_id,
    frame_rx,
391
    nr_slot_rx,
Agustin's avatar
Agustin committed
392
    frame_tx,
Hongzhi Wang's avatar
Hongzhi Wang committed
393
    ue->frame_parms.N_RB_DL);
Agustin's avatar
Agustin committed
394 395 396
#endif

  } else {
397 398
    LOG_E(PHY,"[UE %d] frame %d, nr_slot_rx %d, Error decoding PBCH!\n",
	  ue->Mod_id,frame_rx, nr_slot_rx);
399 400 401 402 403 404 405 406 407 408
    /*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
409

410
    /*
Agustin's avatar
Agustin committed
411 412 413
    write_output("rxsig0.m","rxs0", ue->common_vars.rxdata[0],ue->frame_parms.samples_per_subframe,1,1);


414 415
      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
416

417 418 419 420 421
      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
422 423
    */

424 425
    ue->pbch_vars[gNB_id]->pdu_errors_conseq++;
    ue->pbch_vars[gNB_id]->pdu_errors++;
426

427
    if (ue->pbch_vars[gNB_id]->pdu_errors_conseq>=100) {
428 429 430 431 432 433 434
      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
435 436 437 438
    }
  }

  if (frame_rx % 100 == 0) {
439 440
    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
441 442 443 444
  }

#ifdef DEBUG_PHY_PROC
  LOG_D(PHY,"[UE %d] frame %d, slot %d, PBCH errors = %d, consecutive errors = %d!\n",
445
	ue->Mod_id,frame_rx, nr_slot_rx,
446 447
	ue->pbch_vars[gNB_id]->pdu_errors,
	ue->pbch_vars[gNB_id]->pdu_errors_conseq);
Agustin's avatar
Agustin committed
448 449 450 451 452 453
#endif
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_PBCH_PROCEDURES, VCD_FUNCTION_OUT);
}



454
unsigned int nr_get_tx_amp(int power_dBm, int power_max_dBm, int N_RB_UL, int nb_rb)
455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470
{

  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
471
#ifdef NR_PDCCH_SCHED
472

473
int nr_ue_pdcch_procedures(uint8_t gNB_id,
474 475
                           PHY_VARS_NR_UE *ue,
                           UE_nr_rxtx_proc_t *proc,
476
                           int n_ss)
Agustin's avatar
Agustin committed
477
{
478
  int frame_rx = proc->frame_rx;
479
  int nr_slot_rx = proc->nr_slot_rx;
480
  unsigned int dci_cnt=0;
cig's avatar
cig committed
481 482
  fapi_nr_dci_indication_t dci_ind = {0};
  nr_downlink_indication_t dl_indication;
483

484 485 486
  NR_UE_PDCCH *pdcch_vars = ue->pdcch_vars[proc->thread_id][gNB_id];
  fapi_nr_dl_config_dci_dl_pdu_rel15_t *rel15 = &pdcch_vars->pdcch_config[n_ss];

487
  /*
Agustin's avatar
Agustin committed
488
  //  unsigned int dci_cnt=0, i;  //removed for nr_ue_pdcch_procedures and added in the loop for nb_coreset_active
489 490 491
#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
492 493

  int frame_rx = proc->frame_rx;
494
  int nr_slot_rx = proc->nr_slot_rx;
Agustin's avatar
Agustin committed
495
  NR_DCI_ALLOC_t dci_alloc_rx[8];
496
  
497
  //uint8_t next1_thread_id = proc->thread_id== (RX_NB_TH-1) ? 0:(proc->thread_id+1);
498 499
  //uint8_t next2_thread_id = next1_thread_id== (RX_NB_TH-1) ? 0:(next1_thread_id+1);
  
Agustin's avatar
Agustin committed
500

501 502
  // 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]
503 504
  // 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
505
  uint8_t dci_fields_sizes_cnt[MAX_NR_DCI_DECODED_SLOT][NBR_NR_DCI_FIELDS][NBR_NR_FORMATS];
506

Agustin's avatar
Agustin committed
507
  int nb_searchspace_active=0;
508 509
  NR_UE_PDCCH **pdcch_vars = ue->pdcch_vars[proc->thread_id];
  NR_UE_PDCCH *pdcch_vars2 = ue->pdcch_vars[proc->thread_id][gNB_id];
510 511 512
  // 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;
513

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

cig's avatar
cig committed
516
  uint16_t c_rnti=pdcch_vars[gNB_id]->crnti;
517
  uint16_t cs_rnti=0,new_rnti=0,tc_rnti=0;
518 519
  uint16_t p_rnti=P_RNTI;
  uint16_t si_rnti=SI_RNTI;
520
  uint16_t ra_rnti=99;
laurent's avatar
laurent committed
521
  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
522
  uint16_t crc_scrambled_values[TOTAL_NBR_SCRAMBLED_VALUES] =
523
    {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};
524
  #ifdef NR_PDCCH_SCHED_DEBUG
525
  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
526 527 528
  #endif
  if (nb_searchspace_total>1) nb_searchspace_total=1; // to be removed when fixing bug in FAPI
  #ifdef NR_PDCCH_SCHED_DEBUG
529 530
  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",
531
	 nr_slot_rx,nb_searchspace_total);
532
  #endif
533

534 535 536 537
  //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;
  
538
  // 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)
539
  //int nb_coreset_total = NR_NBR_CORESET_ACT_BWP;
Guy De Souza's avatar
Guy De Souza committed
540
  unsigned int dci_cnt=0;
541
  // 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
542
  //uint8_t dci_fields_sizes[NBR_NR_DCI_FIELDS][NBR_NR_FORMATS] = {{0}};
543
  // this is the UL bandwidth part. FIXME! To be defined where this value comes from
Raymond Knopp's avatar
Raymond Knopp committed
544
  //  uint16_t n_RB_ULBWP = 106;
545
  // this is the DL bandwidth part. FIXME! To be defined where this value comes from
Agustin's avatar
Agustin committed
546 547 548 549

  // 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++){
550
    int nb_coreset_active=nb_searchspace_active;
551
    //int do_pdcch_monitoring_current_slot=1; // this variable can be removed and fapi is handling
552 553 554
    
     // The following code has been removed as it is handled by higher layers (fapi)
     //
555
     // Verify that monitoring is required at the slot nr_slot_rx. We will run pdcch procedure only if do_pdcch_monitoring_current_slot=1
556
     // For Type0-PDCCH searchspace, we need to calculate the monitoring slot from Tables 13-1 .. 13-15 in TS 38.213 Subsection 13
557 558 559
     //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
560
     //} else if (nr_slot_rx%(uint16_t)sl_period_offset_mon == pdcch_vars2->searchSpace[nb_searchspace_active].monitoringSlotPeriodicityAndOffset_offset) {
561 562 563 564 565 566 567
     //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 !!!
     
568
    //int _offset,_index,_M;
569
    //int searchSpace_id                              = pdcch_vars2->searchSpace[nb_searchspace_active].searchSpaceId;
570 571


Agustin's avatar
Agustin committed
572
    #ifdef NR_PDCCH_SCHED_DEBUG
573
      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
574 575 576 577
              nb_searchspace_active,
              do_pdcch_monitoring_current_slot);
    #endif

578
//    if (do_pdcch_monitoring_current_slot) {
579
      // the searchSpace indicates that we need to monitor PDCCH in current nr_slot_rx
Agustin's avatar
Agustin committed
580 581
      // get the parameters describing the current SEARCHSPACE
      // the CORESET id applicable to the current SearchSpace
582
      //int searchSpace_coreset_id                      = pdcch_vars2->searchSpace[nb_searchspace_active].controlResourceSetId;
Agustin's avatar
Agustin committed
583 584 585 586
      // 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
587 588 589 590 591
      //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
592 593
                                                                                                  // FIXME! A table of five enum elements
      // searchSpaceType indicates whether this is a common search space or a UE-specific search space
594
      //int searchSpaceType                             = pdcch_vars2->searchSpace[nb_searchspace_active].searchSpaceType.type;
595
      NR_SEARCHSPACE_TYPE_t searchSpaceType                             = ue_specific;//common;
596 597 598 599 600
      #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

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

Agustin's avatar
Agustin committed
607

608 609 610
    
     //we do not need these parameters yet
    
611
     // get the parameters describing the current CORESET
612 613 614 615 616 617 618 619 620 621
     //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
622

623 624 625 626 627 628 629 630 631 632 633 634 635 636
    // 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
637 638 639



640
    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_PDCCH_PROCEDURES, VCD_FUNCTION_IN);
641
    start_meas(&ue->dlsch_rx_pdcch_stats);
Agustin's avatar
Agustin committed
642

643 644
      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
645 646
      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
647
                  searchSpaceType);
648
#endif
Agustin's avatar
Agustin committed
649
        nr_rx_pdcch(ue,
650 651
                    frame_rx,
                    nr_slot_rx,
cig's avatar
cig committed
652
                    gNB_id,
653
                    //(ue->frame_parms.mode1_flag == 1) ? SISO : ALAMOUTI,
Agustin's avatar
Agustin committed
654 655 656 657 658 659
                    SISO,
                    ue->high_speed_flag,
                    ue->is_secondary_ue,
                    nb_coreset_active,
                    (symbol_within_slot_mon&0x3FFF),
                    searchSpaceType);
660
#ifdef NR_PDCCH_SCHED_DEBUG
661 662
          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
663
                  searchSpaceType);
664 665
#endif

666 667 668
  */
  
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_RX_PDCCH, VCD_FUNCTION_IN);
669
  nr_rx_pdcch(ue, proc, rel15);
670 671
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_RX_PDCCH, VCD_FUNCTION_OUT);
  
Agustin's avatar
Agustin committed
672

673
  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
674

675
#ifdef NR_PDCCH_SCHED_DEBUG
676 677
  printf("<-NR_PDCCH_PHY_PROCEDURES_LTE_UE (nr_ue_pdcch_procedures)-> Entering function nr_dci_decoding_procedure for search space %d)\n",
	 n_ss);
678
#endif
hongzhi wang's avatar
hongzhi wang committed
679

680
  dci_cnt = nr_dci_decoding_procedure(ue, proc, &dci_ind, rel15);
681

682
#ifdef NR_PDCCH_SCHED_DEBUG
683
  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);
684
#endif
685 686
  
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_DCI_DECODING, VCD_FUNCTION_OUT);
687
  //LOG_D(PHY,"[UE  %d][PUSCH] Frame %d nr_slot_rx %d PHICH RX\n",ue->Mod_id,frame_rx,nr_slot_rx);
688 689

  for (int i=0; i<dci_cnt; i++) {
cig's avatar
cig committed
690
    LOG_D(PHY,"[UE  %d] AbsSubFrame %d.%d, Mode %s: DCI %i of %d total DCIs found --> rnti %x : format %d\n",
691
      ue->Mod_id,frame_rx%1024,nr_slot_rx,nr_mode_string[ue->UE_mode[gNB_id]],
cig's avatar
cig committed
692 693 694 695
      i + 1,
      dci_cnt,
      dci_ind.dci_list[i].rnti,
      dci_ind.dci_list[i].dci_format);
696
  }
697
  ue->pdcch_vars[proc->thread_id][gNB_id]->dci_received += dci_cnt;
698

cig's avatar
cig committed
699
  dci_ind.number_of_dcis = dci_cnt;
700
    /*
701
    for (int i=0; i<dci_cnt; i++) {
702
      
703
	memset(&dci_ind.dci_list[i].dci,0,sizeof(fapi_nr_dci_pdu_rel15_t));
704
	
705 706 707 708
	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;
709 710
	
	status = nr_extract_dci_info(ue,
cig's avatar
cig committed
711
				     gNB_id,
712 713 714 715
				     ue->frame_parms.frame_type,
				     dci_alloc_rx[i].dci_length,
				     dci_alloc_rx[i].rnti,
				     dci_alloc_rx[i].dci_pdu,
716
				     &dci_ind.dci_list[i].dci,
717
				     dci_fields_sizes_cnt[i],
718
				     dci_alloc_rx[i].format,
719
				     nr_slot_rx,
720 721 722
				     pdcch_vars2->n_RB_BWP[nb_searchspace_active],
				     pdcch_vars2->n_RB_BWP[nb_searchspace_active],
				     crc_scrambled_values);
723
	
724 725 726 727 728 729
	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");
730
	
Agustin's avatar
Agustin committed
731

732
        
Agustin's avatar
Agustin committed
733
      } // end for loop dci_cnt
734
    */
Agustin's avatar
Agustin committed
735

736
    // fill dl_indication message
cig's avatar
cig committed
737
    nr_fill_dl_indication(&dl_indication, &dci_ind, NULL, proc, ue, gNB_id);
738
    //  send to mac
739
    ue->if_inst->dl_indication(&dl_indication, NULL);
740

Agustin's avatar
Agustin committed
741
  stop_meas(&ue->dlsch_rx_pdcch_stats);
742 743
    
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_PDCCH_PROCEDURES, VCD_FUNCTION_OUT);
744
  return(dci_cnt);
Agustin's avatar
Agustin committed
745
}
746
#endif // NR_PDCCH_SCHED
747

748
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
749

750 751
  int frame_rx = proc->frame_rx;
  int nr_slot_rx = proc->nr_slot_rx;
Agustin's avatar
Agustin committed
752
  int m;
753
  int i_mod,gNB_id_i,dual_stream_UE;
Agustin's avatar
Agustin committed
754 755
  int first_symbol_flag=0;

756
  if (!dlsch0)
757
    return 0;
Agustin's avatar
Agustin committed
758
  if (dlsch0->active == 0)
759
    return 0;
Agustin's avatar
Agustin committed
760

761
  if (!dlsch1)  {
762
    int harq_pid = dlsch0->current_harq_pid;
763
    NR_DL_UE_HARQ_t *dlsch0_harq = dlsch0->harq_processes[harq_pid];
764 765 766 767 768
    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;
769
    bool is_SI              = dlsch0->rnti_type == _SI_RNTI_;
770

771 772
    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
773

774
    for (m = s0; m < (s0 +s1); m++) {
775
      if (dlsch0_harq->dlDmrsSymbPos & (1 << m)) {
776
        for (uint8_t aatx=0; aatx<dlsch0_harq->Nl; aatx++) {//for MIMO Config: it shall loop over no_layers
777
          nr_pdsch_channel_estimation(ue,
778
                                      proc,
779
                                      gNB_id,
780
                                      is_SI,
781
                                      nr_slot_rx,
782 783
                                      aatx /*p*/,
                                      m,
rmagueta's avatar
rmagueta committed
784
                                      BWPStart,
785 786
                                      ue->frame_parms.first_carrier_offset+(BWPStart + pdsch_start_rb)*12,
                                      pdsch_nb_rb);
787
          LOG_D(PHY,"PDSCH Channel estimation gNB id %d, PDSCH antenna port %d, slot %d, symbol %d\n",0,aatx,nr_slot_rx,m);
788 789 790 791 792
#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++) {
793
            sprintf(filename,"PDSCH_CHANNEL_frame%d_slot%d_sym%d_port%d_rx%d.m", nr_frame_rx, nr_slot_rx, m, aatx,aarx);
794
            int **dl_ch_estimates = ue->pdsch_vars[proc->thread_id][gNB_id]->dl_ch_estimates;
795 796 797 798
            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
        }
799 800
      }
    }
801 802

    uint16_t first_symbol_with_data = s0;
803 804
    uint32_t dmrs_data_re;

805
    if (dlsch0_harq->dmrsConfigType == NFAPI_NR_DMRS_TYPE1)
806 807 808 809 810 811
      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++;
812 813
    }

814 815
    for (m = s0; m < (s1 + s0); m++) {
 
816
      dual_stream_UE = 0;
817
      gNB_id_i = gNB_id+1;
818
      i_mod = 0;
819
      if (( m==first_symbol_with_data ) && (m<4))
820
        first_symbol_flag = 1;
Agustin's avatar
Agustin committed
821
      else
822
        first_symbol_flag = 0;
823

Agustin's avatar
Agustin committed
824
      uint8_t slot = 0;
825
      if(m >= ue->frame_parms.symbols_per_slot>>1)
Agustin's avatar
Agustin committed
826
        slot = 1;
827
      start_meas(&ue->dlsch_llr_stats_parallelization[proc->thread_id][slot]);
828 829 830
      // 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) {
831
        if (nr_rx_pdsch(ue,
832 833
                        proc,
                        pdsch,
834 835
                        gNB_id,
                        gNB_id_i,
836 837 838 839 840 841
                        frame_rx,
                        nr_slot_rx,
                        m,
                        first_symbol_flag,
                        dual_stream_UE,
                        i_mod,
842
                        harq_pid) < 0)
843 844 845
          return -1;
      } else AssertFatal(1==0,"Not RA_PDSCH, SI_PDSCH or PDSCH\n");

846
      stop_meas(&ue->dlsch_llr_stats_parallelization[proc->thread_id][slot]);
frtabu's avatar
frtabu committed
847
#if PHYSIM
848
      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
849
#else
850
      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
851 852
#endif

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

861 862 863 864 865 866 867 868
bool nr_ue_dlsch_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,
                            int *dlsch_errors,
                            uint8_t dlsch_parallel) {
Agustin's avatar
Agustin committed
869

870 871
  if (dlsch0==NULL)
    AssertFatal(0,"dlsch0 should be defined at this level \n");
872
  bool dec = false;
Francesco Mani's avatar
Francesco Mani committed
873
  int harq_pid = dlsch0->current_harq_pid;
Agustin's avatar
Agustin committed
874
  int frame_rx = proc->frame_rx;
875
  int nr_slot_rx = proc->nr_slot_rx;
876
  uint32_t ret = UINT32_MAX, ret1 = UINT32_MAX;
Agustin's avatar
Agustin committed
877
  NR_UE_PDSCH *pdsch_vars;
878
  uint16_t dmrs_len = get_num_dmrs(dlsch0->harq_processes[dlsch0->current_harq_pid]->dlDmrsSymbPos);
879 880
  nr_downlink_indication_t dl_indication;
  fapi_nr_rx_indication_t rx_ind;
cig's avatar
cig committed
881
  uint16_t number_pdus = 1;
882
  // params for UL time alignment procedure
883
  NR_UL_TIME_ALIGNMENT_t *ul_time_alignment = &ue->ul_time_alignment[gNB_id];
884 885 886 887 888 889 890

  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;
891 892 893 894 895 896
  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;
  }
897

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

902 903
  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
904 905

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

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

937
    if (pdsch == RA_PDSCH) {
938
      if (ue->prach_resources[gNB_id]!=NULL)
939
        dlsch0->rnti = ue->prach_resources[gNB_id]->ra_RNTI;
Agustin's avatar
Agustin committed
940
      else {
941 942 943
        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);
        //mac_xface->macphy_exit("prach_resources is NULL");
        return false;
Agustin's avatar
Agustin committed
944 945 946
      }
    }

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

Francesco Mani's avatar
Francesco Mani committed
951 952 953 954
    // 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,
955
                                                   dmrs_len,
Francesco Mani's avatar
Francesco Mani committed
956 957
                                                   dlsch0->harq_processes[harq_pid]->Qm,
                                                   dlsch0->harq_processes[harq_pid]->Nl);
frtabu's avatar
frtabu committed
958 959 960 961 962 963 964

      start_meas(&ue->dlsch_unscrambling_stats);
      nr_dlsch_unscrambling(pdsch_vars->llr[0],
                            dlsch0->harq_processes[harq_pid]->G,
                            0,
                            ue->frame_parms.Nid_cell,
                            dlsch0->rnti);
965
      
Hongzhi Wang's avatar
Hongzhi Wang committed
966

frtabu's avatar
frtabu committed
967 968
      stop_meas(&ue->dlsch_unscrambling_stats);

Agustin's avatar
Agustin committed
969 970

#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
#endif

frtabu's avatar
frtabu committed
981

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

mjoang's avatar
mjoang committed
984 985 986 987 988 989 990 991 992 993 994 995 996
    ret = nr_dlsch_decoding(ue,
                            proc,
                            gNB_id,
                            pdsch_vars->llr[0],
                            &ue->frame_parms,
                            dlsch0,
                            dlsch0->harq_processes[harq_pid],
                            frame_rx,
                            nb_symb_sch,
                            nr_slot_rx,
                            harq_pid,
                            pdsch==PDSCH?1:0,
                            dlsch0->harq_processes[harq_pid]->TBS>256?1:0);
997 998
    if( dlsch_parallel) {
      LOG_T(PHY,"dlsch decoding is parallelized, ret = %d\n", ret);
999
    }
1000
    else {
1001
      LOG_T(PHY,"Sequential dlsch decoding , ret = %d\n", ret);
1002
    }
1003

1004 1005
    if(ret<dlsch0->max_ldpc_iterations+1)
      dec = true;
Agustin's avatar
Agustin committed
1006

1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024
    switch (pdsch) {
      case RA_PDSCH:
        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, NULL, number_pdus);
        ue->UE_mode[gNB_id] = RA_RESPONSE;
        break;
      case PDSCH:
        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, NULL, number_pdus);
        break;
      case SI_PDSCH:
        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, NULL, number_pdus);
        break;
      default:
        break;
    }

1025
    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);
1026

1027

Agustin's avatar
Agustin committed
1028

frtabu's avatar
frtabu committed
1029 1030 1031

      stop_meas(&ue->dlsch_decoding_stats[proc->thread_id]);
#if PHYSIM
1032 1033 1034 1035
    printf(" --> Unscrambling for CW0 %5.3f\n",
           (ue->dlsch_unscrambling_stats.p_time)/(cpuf*1000.0));
    printf("AbsSubframe %d.%d --> LDPC Decoding for CW0 %5.3f\n",
           frame_rx%1024, nr_slot_rx,(ue->dlsch_decoding_stats[proc->thread_id].p_time)/(cpuf*1000.0));
Agustin's avatar
Agustin committed
1036
#else
1037 1038 1039 1040
    LOG_I(PHY, " --> Unscrambling for CW0 %5.3f\n",
          (ue->dlsch_unscrambling_stats.p_time)/(cpuf*1000.0));
    LOG_I(PHY, "AbsSubframe %d.%d --> LDPC Decoding for CW0 %5.3f\n",
          frame_rx%1024, nr_slot_rx,(ue->dlsch_decoding_stats[proc->thread_id].p_time)/(cpuf*1000.0));
Agustin's avatar
Agustin committed
1041 1042
#endif

1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057
    if(is_cw1_active) {
      // start ldpc decode for CW 1
      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,
                                                     dlsch1->harq_processes[harq_pid]->Nl);
      start_meas(&ue->dlsch_unscrambling_stats);
      nr_dlsch_unscrambling(pdsch_vars->llr[1],
                            dlsch1->harq_processes[harq_pid]->G,
                            0,
                            ue->frame_parms.Nid_cell,
                            dlsch1->rnti);
      stop_meas(&ue->dlsch_unscrambling_stats);
Agustin's avatar
Agustin committed
1058 1059

#if 0
1060 1061 1062 1063 1064 1065
          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);
1066
          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
1067 1068
#endif

1069
      start_meas(&ue->dlsch_decoding_stats[proc->thread_id]);
frtabu's avatar
frtabu committed
1070

Agustin's avatar
Agustin committed
1071

mjoang's avatar
mjoang committed
1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084
      ret1 = nr_dlsch_decoding(ue,
                               proc,
                               gNB_id,
                               pdsch_vars->llr[1],
                               &ue->frame_parms,
                               dlsch1,
                               dlsch1->harq_processes[harq_pid],
                               frame_rx,
                               nb_symb_sch,
                               nr_slot_rx,
                               harq_pid,
                               pdsch==PDSCH?1:0,//proc->decoder_switch,
                               dlsch1->harq_processes[harq_pid]->TBS>256?1:0);
1085 1086 1087 1088
      if(dlsch_parallel) {
        LOG_T(PHY,"CW dlsch decoding is parallelized, ret1 = %d\n", ret1);
      }
      else {
mjoang's avatar
mjoang committed
1089

1090 1091
        LOG_T(PHY,"CWW sequential dlsch decoding, ret1 = %d\n", ret1);
      }
Agustin's avatar
Agustin committed
1092

frtabu's avatar
frtabu committed
1093 1094 1095

    stop_meas(&ue->dlsch_decoding_stats[proc->thread_id]);
#if PHYSIM
1096 1097 1098 1099
      printf(" --> Unscrambling for CW1 %5.3f\n",
             (ue->dlsch_unscrambling_stats.p_time)/(cpuf*1000.0));
      printf("AbsSubframe %d.%d --> ldpc Decoding for CW1 %5.3f\n",
             frame_rx%1024, nr_slot_rx,(ue->dlsch_decoding_stats[proc->thread_id].p_time)/(cpuf*1000.0));
Agustin's avatar
Agustin committed
1100
#else
1101 1102 1103 1104
      LOG_D(PHY, " --> Unscrambling for CW1 %5.3f\n",
            (ue->dlsch_unscrambling_stats.p_time)/(cpuf*1000.0));
      LOG_D(PHY, "AbsSubframe %d.%d --> ldpc Decoding for CW1 %5.3f\n",
            frame_rx%1024, nr_slot_rx,(ue->dlsch_decoding_stats[proc->thread_id].p_time)/(cpuf*1000.0));
Agustin's avatar
Agustin committed
1105 1106
#endif

frtabu's avatar
frtabu committed
1107

1108
      LOG_D(PHY,"AbsSubframe %d.%d --> ldpc Decoding for CW1 %5.3f\n",
1109
            frame_rx%1024, nr_slot_rx,(ue->dlsch_decoding_stats[proc->thread_id].p_time)/(cpuf*1000.0));
cig's avatar
cig committed
1110

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

1114
    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
1115

1116 1117 1118
    //  send to mac
    if (ue->if_inst && ue->if_inst->dl_indication) {
      ue->if_inst->dl_indication(&dl_indication, ul_time_alignment);
1119
    }
1120

1121
    if (ue->mac_enabled == 1) { // TODO: move this from PHY to MAC layer!
1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141

      /* 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 */
      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;

1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183
      NR_UE_MAC_INST_t *mac = get_mac_inst(0);

      NR_PUSCH_TimeDomainResourceAllocationList_t *pusch_TimeDomainAllocationList = NULL;
      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;
      NR_PDSCH_TimeDomainResourceAllocationList_t *pdsch_TimeDomainAllocationList = NULL;
      if (mac->DLbwp[0] && mac->DLbwp[0]->bwp_Dedicated->pdsch_Config->choice.setup->pdsch_TimeDomainAllocationList)
        pdsch_TimeDomainAllocationList = pdsch_Config->pdsch_TimeDomainAllocationList->choice.setup;
      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;
1184
      }
Agustin's avatar
Agustin committed
1185

1186 1187 1188
      pdsch_dmrs_AdditionalPosition_t add_pos_dl = pdsch_dmrs_pos2;
      if (NR_DMRS_dlconfig && NR_DMRS_dlconfig->dmrs_AdditionalPosition)
        add_pos_dl = *NR_DMRS_dlconfig->dmrs_AdditionalPosition;
1189

1190 1191
      /* PDSCH decoding time N_1 for processing capability 1 */
      int N_1;
1192

1193
      if (add_pos_dl == pdsch_dmrs_pos0)
1194
        N_1 = pdsch_N_1_capability_1[numerology][1];
1195
      else if (add_pos_dl == pdsch_dmrs_pos1 || add_pos_dl == pdsch_dmrs_pos2)
1196 1197 1198
        N_1 = pdsch_N_1_capability_1[numerology][2];
      else
        N_1 = pdsch_N_1_capability_1[numerology][3];
1199

1200
      /* PUSCH preapration time N_2 for processing capability 1 */
1201
      const int N_2 = pusch_N_2_timing_capability_1[numerology][1];
1202

1203 1204 1205
      /* d_1_1 depending on the number of PDSCH symbols allocated */
      const int d = 0; // TODO number of overlapping symbols of the scheduling PDCCH and the scheduled PDSCH
      int d_1_1 = 0;
1206 1207
      if (mapping_type_dl == NR_PDSCH_TimeDomainResourceAllocation__mappingType_typeA)
       if (nb_symb_sch + start_symbol < 7)
1208
          d_1_1 = 7 - (nb_symb_sch + start_symbol);
1209
        else
1210
          d_1_1 = 0;
1211 1212 1213 1214 1215 1216 1217
      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;
        }
1218

1219 1220
      /* d_2_1 */
      int d_2_1;
1221
      if (mapping_type_ul == NR_PUSCH_TimeDomainResourceAllocation__mappingType_typeB && start_symbol != 0)
1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245
        d_2_1 = 0;
      else
        d_2_1 = 1;

      /* 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

      /* 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 */
      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;
      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
      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);

      if (ul_time_alignment->apply_ta == 1){
        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){
          ul_time_alignment->ta_frame = (frame_rx + 1) % 1024;
        } else {
          ul_time_alignment->ta_frame = frame_rx;
1246
        }
1247 1248 1249 1250
        // reset TA flag
        ul_time_alignment->apply_ta = 0;
        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);
1251
      }
1252
    }
1253
  }
1254
  return dec;
Agustin's avatar
Agustin committed
1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267
}


/*!
 * \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) {

1268 1269 1270 1271
  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
1272

1273 1274 1275
  uint8_t pilot1;

  proc->instance_cnt_slot1_dl_processing=-1;
1276
  proc->nr_slot_rx = proc->sub_frame_start * ue->frame_parms.slots_per_subframe;
1277 1278 1279

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

1281 1282 1283 1284
  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);
1285
  if ( RX_NB_TH > 1 && (proc->sub_frame_start+1)%RX_NB_TH == 1 && threads.slot1_proc_two != -1 )
1286
    CPU_SET(threads.slot1_proc_two, &cpuset);
1287
  if ( RX_NB_TH > 2 && (proc->sub_frame_start+1)%RX_NB_TH == 2 && threads.slot1_proc_three != -1 )
1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306
    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");
    }

1307 1308 1309 1310
    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;
1311

1312 1313
    uint8_t slot1  = proc->nr_slot_rx + 1;
    uint8_t pilot0 = 0;
1314

1315
    //printf("AbsSubframe %d.%d execute dl slot1 processing \n", frame_rx, nr_slot_rx);
1316 1317 1318 1319 1320 1321 1322 1323

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

    /**** Slot1 FE Processing ****/
frtabu's avatar
frtabu committed
1324

1325
    start_meas(&ue->ue_front_end_per_slot_stat[proc->thread_id][1]);
frtabu's avatar
frtabu committed
1326

1327
    // I- start dl slot1 processing
1328
    // do first symbol of next downlink nr_slot_rx for channel estimation
1329
    /*
1330 1331
    // 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)
1332 1333 1334 1335 1336 1337 1338
    {
    front_end_fft(ue,
    pilot0,
    next_subframe_slot0,
    0,
    0);
    }
Agustin's avatar
Agustin committed
1339

1340 1341 1342 1343 1344 1345 1346
    front_end_fft(ue,
    pilot1,
    slot1,
    0,
    0);
    */
    // 1- perform FFT
1347
    for (int l=1; l<ue->frame_parms.symbols_per_slot>>1; l++)
1348 1349 1350
      {
	//if( (l != pilot0) && (l != pilot1))
	{
frtabu's avatar
frtabu committed
1351

1352 1353
	  start_meas(&ue->ofdm_demod_stats);
	  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SLOT_FEP, VCD_FUNCTION_IN);
1354
	  //printf("AbsSubframe %d.%d FFT slot %d, symbol %d\n", frame_rx,nr_slot_rx,slot1,l);
1355
	  front_end_fft(ue,
Agustin's avatar
Agustin committed
1356 1357 1358 1359
                        l,
                        slot1,
                        0,
                        0);
1360 1361 1362 1363
	  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SLOT_FEP, VCD_FUNCTION_OUT);
	  stop_meas(&ue->ofdm_demod_stats);
	}
      } // for l=1..l2
Agustin's avatar
Agustin committed
1364

1365
    if (nr_subframe_select(&ue->frame_parms,next_nr_slot_rx) != SF_UL)
1366
      {
1367
	//printf("AbsSubframe %d.%d FFT slot %d, symbol %d\n", frame_rx,nr_slot_rx,next_subframe_slot0,pilot0);
1368 1369 1370 1371 1372 1373
	front_end_fft(ue,
		      pilot0,
		      next_subframe_slot0,
		      0,
		      0);
      }
Agustin's avatar
Agustin committed
1374

1375
    // 2- perform Channel Estimation for slot1
1376
    for (int l=1; l<ue->frame_parms.symbols_per_slot>>1; l++)
1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388
      {
	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);
	  }
1389
	//printf("AbsSubframe %d.%d ChanEst slot %d, symbol %d\n", frame_rx,nr_slot_rx,slot1,l);
1390 1391 1392 1393
	front_end_chanEst(ue,
			  l,
			  slot1,
			  0);
1394
	ue_measurement_procedures(l-1,ue,proc,0,slot1,0,ue->mode);
1395
      }
1396
    //printf("AbsSubframe %d.%d ChanEst slot %d, symbol %d\n", frame_rx,nr_slot_rx,next_subframe_slot0,pilot0);
1397 1398 1399 1400
    front_end_chanEst(ue,
		      pilot0,
		      next_subframe_slot0,
		      0);
Agustin's avatar
Agustin committed
1401

1402
    if ( (nr_slot_rx == 0) && (ue->decode_MIB == 1))
1403
      {
1404
	ue_pbch_procedures(0,ue,proc,0);
1405
      }
Agustin's avatar
Agustin committed
1406

1407
    proc->chan_est_slot1_available = 1;
1408 1409
    //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
1410

1411
    //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
1412 1413


frtabu's avatar
frtabu committed
1414

1415
    stop_meas(&ue->ue_front_end_per_slot_stat[proc->thread_id][1]);
frtabu's avatar
frtabu committed
1416
#if PHYSIM
1417
    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
1418
#else
1419
    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
1420 1421 1422 1423 1424 1425
#endif


    //wait until pdcch is decoded
    uint32_t wait = 0;
    while(proc->dci_slot0_available == 0)
1426
      {
Agustin's avatar
Agustin committed
1427 1428
        usleep(1);
        wait++;
1429
      }
1430
    //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
1431 1432 1433 1434

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


1438
    start_meas(&ue->pdsch_procedures_per_slot_stat[proc->thread_id][1]);
frtabu's avatar
frtabu committed
1439

Agustin's avatar
Agustin committed
1440 1441
    // start slave thread for Pdsch Procedure (slot1)
    // do procedures for C-RNTI
1442
    uint8_t gNB_id = 0;
1443

1444
    if (ue->dlsch[proc->thread_id][gNB_id][0]->active == 1) {
1445 1446 1447 1448 1449 1450 1451
      //wait until first ofdm symbol is processed
      //wait = 0;
      //while(proc->first_symbol_available == 0)
      //{
      //    usleep(1);
      //    wait++;
      //}
1452
      //printf("[slot1 dl processing] AbsSubframe %d.%d LLR Computation Start wait First Ofdm Sym %d\n",frame_rx,nr_slot_rx,wait);
1453 1454 1455 1456

      //VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDSCH_PROC, VCD_FUNCTION_IN);
      ue_pdsch_procedures(ue,
			  proc,
1457
			  gNB_id,
1458
			  PDSCH,
1459
			  ue->dlsch[proc->thread_id][gNB_id][0],
1460
			  NULL,
1461 1462
			  (ue->frame_parms.symbols_per_slot>>1),
			  ue->frame_parms.symbols_per_slot-1,
1463
			  abstraction_flag);
1464 1465
      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
1466 1467 1468
    }

    // do procedures for SI-RNTI
1469
    if ((ue->dlsch_SI[gNB_id]) && (ue->dlsch_SI[gNB_id]->active == 1)) {
1470 1471
      ue_pdsch_procedures(ue,
			  proc,
1472
			  gNB_id,
1473
			  SI_PDSCH,
1474
			  ue->dlsch_SI[gNB_id],
1475
			  NULL,
1476 1477
			  (ue->frame_parms.symbols_per_slot>>1),
			  ue->frame_parms.symbols_per_slot-1,
1478
			  abstraction_flag);
Agustin's avatar
Agustin committed
1479 1480 1481
    }

    // do procedures for P-RNTI
1482
    if ((ue->dlsch_p[gNB_id]) && (ue->dlsch_p[gNB_id]->active == 1)) {
1483 1484
      ue_pdsch_procedures(ue,
			  proc,
1485
			  gNB_id,
1486
			  P_PDSCH,
1487
			  ue->dlsch_p[gNB_id],
1488
			  NULL,
1489 1490
			  (ue->frame_parms.symbols_per_slot>>1),
			  ue->frame_parms.symbols_per_slot-1,
1491
			  abstraction_flag);
Agustin's avatar
Agustin committed
1492 1493
    }
    // do procedures for RA-RNTI
1494
    if ((ue->dlsch_ra[gNB_id]) && (ue->dlsch_ra[gNB_id]->active == 1) && (UE_mode != PUSCH)) {
1495 1496
      ue_pdsch_procedures(ue,
			  proc,
1497
			  gNB_id,
1498
			  RA_PDSCH,
1499
			  ue->dlsch_ra[gNB_id],
1500
			  NULL,
1501 1502
			  (ue->frame_parms.symbols_per_slot>>1),
			  ue->frame_parms.symbols_per_slot-1,
1503
			  abstraction_flag);
Agustin's avatar
Agustin committed
1504 1505 1506
    }

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

1509
    stop_meas(&ue->pdsch_procedures_per_slot_stat[proc->thread_id][1]);
frtabu's avatar
frtabu committed
1510
#if PHYSIM
1511
    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
1512
#else
1513
    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
1514 1515
#endif

1516 1517 1518 1519 1520 1521 1522 1523
    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
1524
    }
1525 1526 1527 1528
  }
  // thread finished
  free(arg);
  return &UE_dl_slot1_processing_retval;
Agustin's avatar
Agustin committed
1529 1530 1531
}
#endif

1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579
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
1580
   else AssertFatal(0==1, "Invalid Lmax %u for the synchronization block\n", Lmax);
1581 1582 1583 1584
  }
  else return 0;

}
Agustin's avatar
Agustin committed
1585

1586
int is_pbch_in_slot(fapi_nr_config_request_t *config, int frame, int slot, NR_DL_FRAME_PARMS *fp)  {
1587

1588
  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
1589

1590
  if (config->ssb_table.ssb_period == 0) {  
1591
    // check for pbch in corresponding slot each half frame
1592 1593
    if (fp->half_frame_bit)
      return(slot == ssb_slot_decoded || slot == ssb_slot_decoded - fp->slots_per_frame/2);
1594
    else
1595
      return(slot == ssb_slot_decoded || slot == ssb_slot_decoded + fp->slots_per_frame/2);
1596 1597 1598
  }
  else {
    // if the current frame is supposed to contain ssb
1599
    if (!(frame%(1<<(config->ssb_table.ssb_period-1))))
1600 1601 1602
      return(slot == ssb_slot_decoded);
    else
      return 0;
1603 1604 1605
  }
}

Agustin's avatar
Agustin committed
1606

1607 1608
int phy_procedures_nrUE_RX(PHY_VARS_NR_UE *ue,
                           UE_nr_rxtx_proc_t *proc,
cig's avatar
cig committed
1609
                           uint8_t gNB_id,
1610 1611
                           uint8_t dlsch_parallel,
                           notifiedFIFO_t *txFifo
1612 1613
                           )
{                                         
Agustin's avatar
Agustin committed
1614
  int frame_rx = proc->frame_rx;
1615
  int nr_slot_rx = proc->nr_slot_rx;
1616
  int slot_pbch;
Hongzhi Wang's avatar
Hongzhi Wang committed
1617
  int slot_ssb;
1618
  NR_UE_PDCCH *pdcch_vars  = ue->pdcch_vars[proc->thread_id][0];
1619
  fapi_nr_config_request_t *cfg = &ue->nrUE_config;
1620

1621
  uint8_t nb_symb_pdcch = pdcch_vars->nb_search_space > 0 ? pdcch_vars->pdcch_config[0].coreset.duration : 0;
1622
  uint8_t dci_cnt = 0;
1623
  NR_DL_FRAME_PARMS *fp = &ue->frame_parms;
1624
  
Hongzhi Wang's avatar
Hongzhi Wang committed
1625
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_RX, VCD_FUNCTION_IN);
cig's avatar
cig committed
1626

1627
  LOG_D(PHY," ****** start RX-Chain for Frame.Slot %d.%d (energy %d dB)******  \n",
Eurecom's avatar
Eurecom committed
1628 1629
        frame_rx%1024, nr_slot_rx,
        dB_fixed(signal_energy(ue->common_vars.common_vars_rx_data_per_thread[proc->thread_id].rxdataF[0],2048*14)));
Agustin's avatar
Agustin committed
1630

1631
  /*
1632
  uint8_t next1_thread_id = proc->thread_id== (RX_NB_TH-1) ? 0:(proc->thread_id+1);
Agustin's avatar
Agustin committed
1633
  uint8_t next2_thread_id = next1_thread_id== (RX_NB_TH-1) ? 0:(next1_thread_id+1);
1634
  */
Agustin's avatar
Agustin committed
1635

1636 1637
  int coreset_nb_rb=0;
  int coreset_start_rb=0;
1638

1639 1640
  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);
Hongzhi Wang's avatar
Hongzhi Wang committed
1641

1642
  slot_pbch = is_pbch_in_slot(cfg, frame_rx, nr_slot_rx, fp);
1643
  slot_ssb  = is_ssb_in_slot(cfg, frame_rx, nr_slot_rx, fp);
Hongzhi Wang's avatar
Hongzhi Wang committed
1644 1645

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

1651
      nr_slot_fep(ue,
1652
                  proc,
1653
                  (ue->symbol_offset+i)%(fp->symbols_per_slot),
1654
                  nr_slot_rx);
Hongzhi Wang's avatar
Hongzhi Wang committed
1655

frtabu's avatar
frtabu committed
1656

1657
      start_meas(&ue->dlsch_channel_estimation_stats);
1658
      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);
1659 1660
      stop_meas(&ue->dlsch_channel_estimation_stats);
    }
1661

cig's avatar
cig committed
1662
    nr_ue_rsrp_measurements(ue, gNB_id, proc, nr_slot_rx, 0);
1663

1664
    if ((ue->decode_MIB == 1) && slot_pbch) {
1665

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

      if (ue->no_timing_correction==0) {
1670
        LOG_D(PHY,"start adjust sync slot = %d no timing %d\n", nr_slot_rx, ue->no_timing_correction);
1671
        nr_adjust_synch_ue(fp,
cig's avatar
cig committed
1672
                           ue,
cig's avatar
cig committed
1673
                           gNB_id,
1674
                           frame_rx,
1675
                           nr_slot_rx,
cig's avatar
cig committed
1676 1677
                           0,
                           16384);
Hongzhi Wang's avatar
Hongzhi Wang committed
1678
      }
cig's avatar
cig committed
1679 1680 1681

      LOG_D(PHY, "Doing N0 measurements in %s\n", __FUNCTION__);
      nr_ue_rrc_measurements(ue, proc, nr_slot_rx);
1682
      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
1683
    }
1684
  }
1685

1686
  if ((frame_rx%64 == 0) && (nr_slot_rx==0)) {
rmagueta's avatar
rmagueta committed
1687 1688 1689
    LOG_I(NR_PHY,"============================================\n");
    LOG_I(NR_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]);
    LOG_I(NR_PHY,"============================================\n");
1690 1691
  }

1692
#ifdef NR_PDCCH_SCHED
1693

1694
  LOG_D(PHY," ------ --> PDCCH ChannelComp/LLR Frame.slot %d.%d ------  \n", frame_rx%1024, nr_slot_rx);
1695
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SLOT_FEP_PDCCH, VCD_FUNCTION_IN);
1696

1697
  for (uint16_t l=0; l<nb_symb_pdcch; l++) {
cig's avatar
cig committed
1698

1699 1700
    start_meas(&ue->ofdm_demod_stats);
    nr_slot_fep(ue,
1701
                proc,
cig's avatar
cig committed
1702
                l,
1703
                nr_slot_rx);
1704
  }
1705

1706 1707 1708
  dci_cnt = 0;
  for(int n_ss = 0; n_ss<pdcch_vars->nb_search_space; n_ss++) {
    for (uint16_t l=0; l<nb_symb_pdcch; l++) {
1709

1710
      // note: this only works if RBs for PDCCH are contigous!
1711 1712
      LOG_D(PHY, "pdcch_channel_estimation: first_carrier_offset %d, BWPStart %d, coreset_start_rb %d, coreset_nb_rb %d\n",
            fp->first_carrier_offset, pdcch_vars->pdcch_config[n_ss].BWPStart, coreset_start_rb, coreset_nb_rb);
1713 1714 1715 1716

      if (coreset_nb_rb > 0)
        nr_pdcch_channel_estimation(ue,
                                    proc,
1717
                                    gNB_id,
1718 1719 1720 1721
                                    nr_slot_rx,
                                    l,
                                    fp->first_carrier_offset+(pdcch_vars->pdcch_config[n_ss].BWPStart + coreset_start_rb)*12,
                                    coreset_nb_rb);
1722

1723
      stop_meas(&ue->ofdm_demod_stats);
frtabu's avatar
frtabu committed
1724

1725
    }
1726
    dci_cnt = dci_cnt + nr_ue_pdcch_procedures(gNB_id, ue, proc, n_ss);
1727
  }
1728
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SLOT_FEP_PDCCH, VCD_FUNCTION_OUT);
1729 1730 1731

  if (dci_cnt > 0) {

1732
    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
1733

Raphael Defosseux's avatar
Raphael Defosseux committed
1734
    NR_UE_DLSCH_t *dlsch = NULL;
1735 1736
    if (ue->dlsch[proc->thread_id][gNB_id][0]->active == 1){
      dlsch = ue->dlsch[proc->thread_id][gNB_id][0];
1737 1738
    } else if (ue->dlsch_SI[0]->active == 1){
      dlsch = ue->dlsch_SI[0];
cig's avatar
cig committed
1739 1740 1741
    } else if (ue->dlsch_ra[0]->active == 1){
      dlsch = ue->dlsch_ra[0];
    }
1742 1743

    if (dlsch) {
1744
      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SLOT_FEP_PDSCH, VCD_FUNCTION_IN);
1745 1746 1747 1748 1749
      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;

1750
      LOG_D(PHY," ------ --> PDSCH ChannelComp/LLR Frame.slot %d.%d ------  \n", frame_rx%1024, nr_slot_rx);
1751 1752 1753 1754
      //to update from pdsch config

      for (uint16_t m=start_symb_sch;m<(nb_symb_sch+start_symb_sch) ; m++){
        nr_slot_fep(ue,
1755 1756
                    proc,
                    m,  //to be updated from higher layer
1757
                    nr_slot_rx);
1758
      }
1759
      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SLOT_FEP_PDSCH, VCD_FUNCTION_OUT);
1760
    }
cig's avatar
cig committed
1761
  } else {
1762
    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
1763
  }
cig's avatar
cig committed
1764 1765

#endif //NR_PDCCH_SCHED
1766

1767
  // Start PUSCH processing here. It runs in parallel with PDSCH processing
1768 1769
  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);
1770 1771
  curMsg->proc = *proc;
  curMsg->UE = ue;
1772
  curMsg->ue_sched_mode = ONLY_PUSCH;
1773
  pushTpool(&(get_nrUE_params()->Tpool), newElt);
Agustin's avatar
Agustin committed
1774 1775
  start_meas(&ue->generic_stat);
  // do procedures for C-RNTI
1776
  int ret_pdsch = 0;
1777
  if (ue->dlsch[proc->thread_id][gNB_id][0]->active == 1) {
1778

1779
    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDSCH_PROC_C, VCD_FUNCTION_IN);
1780
    ret_pdsch = nr_ue_pdsch_procedures(ue,
1781 1782 1783 1784 1785
                                       proc,
                                       gNB_id,
                                       PDSCH,
                                       ue->dlsch[proc->thread_id][gNB_id][0],
                                       NULL);
cig's avatar
cig committed
1786

cig's avatar
cig committed
1787
    nr_ue_measurement_procedures(2, ue, proc, gNB_id, nr_slot_rx);
1788
    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDSCH_PROC_C, VCD_FUNCTION_OUT);
Agustin's avatar
Agustin committed
1789
  }
1790

Agustin's avatar
Agustin committed
1791
  // do procedures for SI-RNTI
cig's avatar
cig committed
1792
  if ((ue->dlsch_SI[gNB_id]) && (ue->dlsch_SI[gNB_id]->active == 1)) {
Agustin's avatar
Agustin committed
1793
    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDSCH_PROC_SI, VCD_FUNCTION_IN);
1794
    nr_ue_pdsch_procedures(ue,
1795 1796 1797 1798 1799
                           proc,
                           gNB_id,
                           SI_PDSCH,
                           ue->dlsch_SI[gNB_id],
                           NULL);
1800
    
1801 1802 1803 1804 1805 1806 1807
    nr_ue_dlsch_procedures(ue,
                           proc,
                           gNB_id,
                           SI_PDSCH,
                           ue->dlsch_SI[gNB_id],
                           NULL,
                           &ue->dlsch_SI_errors[gNB_id],
1808
                           dlsch_parallel);
1809 1810 1811 1812

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

Agustin's avatar
Agustin committed
1813 1814
    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDSCH_PROC_SI, VCD_FUNCTION_OUT);
  }
1815

1816
  // do procedures for P-RNTI
cig's avatar
cig committed
1817
  if ((ue->dlsch_p[gNB_id]) && (ue->dlsch_p[gNB_id]->active == 1)) {
Agustin's avatar
Agustin committed
1818
    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDSCH_PROC_P, VCD_FUNCTION_IN);
1819
    nr_ue_pdsch_procedures(ue,
1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832
                           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],
1833
                           dlsch_parallel);
1834 1835 1836

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

Agustin's avatar
Agustin committed
1840
  // do procedures for RA-RNTI
cig's avatar
cig committed
1841
  if ((ue->dlsch_ra[gNB_id]) && (ue->dlsch_ra[gNB_id]->active == 1) && (ue->UE_mode[gNB_id] != PUSCH)) {
Agustin's avatar
Agustin committed
1842
    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDSCH_PROC_RA, VCD_FUNCTION_IN);
1843
    nr_ue_pdsch_procedures(ue,
1844 1845 1846 1847 1848
                           proc,
                           gNB_id,
                           RA_PDSCH,
                           ue->dlsch_ra[gNB_id],
                           NULL);
1849

1850 1851
    nr_ue_dlsch_procedures(ue,
                           proc,
cig's avatar
cig committed
1852
                           gNB_id,
1853
                           RA_PDSCH,
cig's avatar
cig committed
1854
                           ue->dlsch_ra[gNB_id],
1855
                           NULL,
cig's avatar
cig committed
1856
                           &ue->dlsch_ra_errors[gNB_id],
1857
                           dlsch_parallel);
1858

1859 1860 1861 1862
    // 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
1863 1864
  }
  // do procedures for C-RNTI
1865
  if (ue->dlsch[proc->thread_id][gNB_id][0]->active == 1) {
cig's avatar
cig committed
1866

francescomani's avatar
francescomani committed
1867
    LOG_D(PHY, "DLSCH data reception at nr_slot_rx: %d\n", nr_slot_rx);
Agustin's avatar
Agustin committed
1868
    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDSCH_PROC, VCD_FUNCTION_IN);
1869

1870
    start_meas(&ue->dlsch_procedures_stat[proc->thread_id]);
hongzhi wang's avatar
hongzhi wang committed
1871

1872 1873
    if (ret_pdsch >= 0)
      nr_ue_dlsch_procedures(ue,
1874
			   proc,
cig's avatar
cig committed
1875
			   gNB_id,
1876
			   PDSCH,
1877 1878
			   ue->dlsch[proc->thread_id][gNB_id][0],
			   ue->dlsch[proc->thread_id][gNB_id][1],
cig's avatar
cig committed
1879
			   &ue->dlsch_errors[gNB_id],
1880
			   dlsch_parallel);
1881

1882
  stop_meas(&ue->dlsch_procedures_stat[proc->thread_id]);
frtabu's avatar
frtabu committed
1883
#if PHYSIM
1884 1885
  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
1886
#else
1887 1888
  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
1889 1890
#endif

frtabu's avatar
frtabu committed
1891

Agustin's avatar
Agustin committed
1892

1893
  // deactivate dlsch once dlsch proc is done
1894
  ue->dlsch[proc->thread_id][gNB_id][0]->active = 0;
1895

1896
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDSCH_PROC, VCD_FUNCTION_OUT);
Agustin's avatar
Agustin committed
1897

1898
 }
1899

1900
start_meas(&ue->generic_stat);
Agustin's avatar
Agustin committed
1901 1902

#if 0
1903

1904
  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
1905
       //write_output("decoder_llr.m","decllr",dlsch_llr,G,1,0);
1906
       //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);
1907

1908
       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);
1909
       //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);
1910

1911
       //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);
1912

1913
       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);
1914 1915 1916 1917
       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);
1918

Agustin's avatar
Agustin committed
1919 1920 1921
       AssertFatal (0,"");
  }
#endif
1922

Agustin's avatar
Agustin committed
1923
  // duplicate harq structure
1924
/*
1925 1926
  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
1927 1928
  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];
1929
  */
1930 1931 1932
  /*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];
1933
*/
Agustin's avatar
Agustin committed
1934

1935
  //copy_harq_proc_struct(harq_processes_dest, current_harq_processes);
1936
//copy_ack_struct(harq_ack_dest, current_harq_ack);
Agustin's avatar
Agustin committed
1937

1938
//copy_harq_proc_struct(harq_processes_dest1, current_harq_processes);
1939
//copy_ack_struct(harq_ack_dest1, current_harq_ack);
Agustin's avatar
Agustin committed
1940

1941
if (nr_slot_rx==9) {
1942
  if (frame_rx % 10 == 0) {
cig's avatar
cig committed
1943 1944
    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
1945

cig's avatar
cig committed
1946 1947
    ue->dlsch_errors_last[gNB_id] = ue->dlsch_errors[gNB_id];
    ue->dlsch_received_last[gNB_id] = ue->dlsch_received[gNB_id];
1948
  }
Agustin's avatar
Agustin committed
1949 1950


cig's avatar
cig committed
1951 1952
  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];
1953
  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
1954 1955
	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
1956

1957 1958
#if UE_AUTOTEST_TRACE
  if ((frame_rx % 100 == 0)) {
cig's avatar
cig committed
1959
    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
1960
  }
1961 1962 1963
#endif

 }
Agustin's avatar
Agustin committed
1964

1965
stop_meas(&ue->generic_stat);
frtabu's avatar
frtabu committed
1966
#if PHYSIM
1967
printf("after tubo until end of Rx %5.2f \n",ue->generic_stat.p_time/(cpuf*1000.0));
Agustin's avatar
Agustin committed
1968 1969
#endif

1970
#ifdef EMOS
cig's avatar
cig committed
1971
phy_procedures_emos_UE_RX(ue,slot,gNB_id);
1972
#endif
Agustin's avatar
Agustin committed
1973 1974


1975
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_RX, VCD_FUNCTION_OUT);
Agustin's avatar
Agustin committed
1976

1977
stop_meas(&ue->phy_proc_rx[proc->thread_id]);
frtabu's avatar
frtabu committed
1978
#if PHYSIM
1979
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
1980
#else
1981
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
1982 1983
#endif

1984
//#endif //pdsch
1985

1986
LOG_D(PHY," ****** end RX-Chain  for AbsSubframe %d.%d ******  \n", frame_rx%1024, nr_slot_rx);
1987
return (0);
Agustin's avatar
Agustin committed
1988
}
1989 1990


1991
uint8_t nr_is_cqi_TXOp(PHY_VARS_NR_UE *ue,
1992 1993 1994
		            UE_nr_rxtx_proc_t *proc,
					uint8_t gNB_id)
{
1995
  int subframe = proc->nr_slot_tx / ue->frame_parms.slots_per_subframe;
1996 1997
  int frame    = proc->frame_tx;
  CQI_REPORTPERIODIC *cqirep = &ue->cqi_report_config[gNB_id].CQI_ReportPeriodic;
1998

1999 2000 2001 2002
  //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));
2003

2004 2005 2006 2007 2008 2009
  if (cqirep->cqi_PMI_ConfigIndex==-1)
    return(0);
  else if (((10*frame + subframe) % cqirep->Npd) == cqirep->N_OFFSET_CQI)
    return(1);
  else
    return(0);
2010 2011 2012
}


2013
uint8_t nr_is_ri_TXOp(PHY_VARS_NR_UE *ue,
2014 2015 2016
		           UE_nr_rxtx_proc_t *proc,
				   uint8_t gNB_id)
{
2017
  int subframe = proc->nr_slot_tx / ue->frame_parms.slots_per_subframe;
2018 2019 2020 2021
  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;
2022

2023 2024 2025 2026 2027 2028 2029 2030 2031 2032
  //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);
2033 2034
}

cig's avatar
cig committed
2035 2036
// todo:
// - power control as per 38.213 ch 7.4
cig's avatar
cig committed
2037
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
2038

2039
  int frame_tx = proc->frame_tx, nr_slot_tx = proc->nr_slot_tx, prach_power; // tx_amp
2040
  uint8_t mod_id = ue->Mod_id;
cig's avatar
cig committed
2041
  NR_PRACH_RESOURCES_t * prach_resources = ue->prach_resources[gNB_id];
2042
  AssertFatal(prach_resources != NULL, "ue->prach_resources[%u] == NULL\n", gNB_id);
2043
  uint8_t nr_prach = 0;
2044 2045 2046

  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_TX_PRACH, VCD_FUNCTION_IN);

cig's avatar
cig committed
2047
  if (ue->mac_enabled == 0){
cig's avatar
cig committed
2048

cig's avatar
cig committed
2049 2050 2051
    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
2052
    nr_prach = 1;
cig's avatar
cig committed
2053 2054
    prach_resources->init_msg1 = 1;

cig's avatar
cig committed
2055
  } else {
cig's avatar
cig committed
2056

2057
    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);
2058
    LOG_D(PHY, "In %s:[%d.%d] getting PRACH resources : %d\n", __FUNCTION__, frame_tx, nr_slot_tx,nr_prach);
2059 2060
  }

2061
  if (nr_prach == GENERATE_PREAMBLE) {
2062

2063 2064
    if (ue->mac_enabled == 1) {
      int16_t pathloss = get_nr_PL(mod_id, ue->CC_id, gNB_id);
cig's avatar
cig committed
2065
      int16_t ra_preamble_rx_power = (int16_t)(prach_resources->ra_PREAMBLE_RECEIVED_TARGET_POWER - pathloss + 30);
2066
      ue->tx_power_dBm[nr_slot_tx] = min(nr_get_Pcmax(mod_id), ra_preamble_rx_power);
2067

cig's avatar
cig committed
2068 2069
      LOG_D(PHY, "In %s: [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",
        __FUNCTION__,
2070 2071 2072 2073 2074 2075 2076 2077
        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
2078
    }
2079

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

cig's avatar
cig committed
2082
    /* #if defined(EXMIMO) || defined(OAI_USRP) || defined(OAI_BLADERF) || defined(OAI_LMSSDR) || defined(OAI_ADRV9371_ZC706)
2083
      tx_amp = get_tx_amp_prach(ue->tx_power_dBm[nr_slot_tx], ue->tx_power_max_dBm, ue->frame_parms.N_RB_UL);
2084 2085
      if (tx_amp != -1)
        ue->prach_vars[gNB_id]->amp = tx_amp;
2086
    #else
cig's avatar
cig committed
2087
      ue->prach_vars[gNB_id]->amp = AMP;
cig's avatar
cig committed
2088
    #endif */
2089 2090 2091

    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_GENERATE_PRACH, VCD_FUNCTION_IN);

2092
    prach_power = generate_nr_prach(ue, gNB_id, nr_slot_tx);
2093 2094

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

cig's avatar
cig committed
2096
    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
2097
      __FUNCTION__,
2098 2099 2100
      mod_id,
      frame_tx,
      nr_slot_tx,
2101
      ue->tx_power_dBm[nr_slot_tx],
2102 2103 2104 2105
      dB_fixed(prach_power),
      ue->prach_vars[gNB_id]->amp);

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

2108 2109
  } 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
2110
    ue->UE_mode[gNB_id] = RA_WAIT_CR;
2111
  } else if (nr_prach == RA_SUCCEEDED) {
2112 2113
    LOG_D(PHY, "In %s: [UE %d] RA completed, setting UE mode to PUSCH\n", __FUNCTION__, mod_id);
    ue->UE_mode[gNB_id] = PUSCH;
2114
  } else if(nr_prach == RA_FAILED){
2115 2116
    LOG_D(PHY, "In %s: [UE %d] RA failed, setting UE mode to PRACH\n", __FUNCTION__, mod_id);
    ue->UE_mode[gNB_id] = PRACH;
2117 2118 2119
  }

  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_TX_PRACH, VCD_FUNCTION_OUT);
2120

2121
}