nr-uesoftmodem.c 21.4 KB
Newer Older
laurent's avatar
laurent committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
/*
 * 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
 */


#define _GNU_SOURCE             /* See feature_test_macros(7) */
#include <sched.h>
25 26
#include <stdbool.h>
#include <signal.h>
laurent's avatar
laurent committed
27 28 29 30 31

#include "T.h"
#include "assertions.h"
#include "PHY/types.h"
#include "PHY/defs_nr_UE.h"
Hongzhi Wang's avatar
Hongzhi Wang committed
32
#include "SCHED_NR_UE/defs.h"
laurent's avatar
laurent committed
33 34
#include "common/ran_context.h"
#include "common/config/config_userapi.h"
35
//#include "common/utils/threadPool/thread-pool.h"
laurent's avatar
laurent committed
36 37
#include "common/utils/load_module_shlib.h"
//#undef FRAME_LENGTH_COMPLEX_SAMPLES //there are two conflicting definitions, so we better make sure we don't use it at all
38
#include "common/utils/nr/nr_common.h"
laurent's avatar
laurent committed
39

francescomani's avatar
francescomani committed
40
#include "radio/COMMON/common_lib.h"
41
#include "radio/ETHERNET/if_defs.h"
laurent's avatar
laurent committed
42 43

//#undef FRAME_LENGTH_COMPLEX_SAMPLES //there are two conflicting definitions, so we better make sure we don't use it at all
44
#include "openair1/PHY/MODULATION/nr_modulation.h"
laurent's avatar
laurent committed
45
#include "PHY/phy_vars_nr_ue.h"
46
#include "PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h"
47
#include "PHY/NR_TRANSPORT/nr_dlsch.h"
laurent's avatar
laurent committed
48 49 50 51
//#include "../../SIMU/USER/init_lte.h"

#include "RRC/LTE/rrc_vars.h"
#include "PHY_INTERFACE/phy_interface_vars.h"
52
#include "NR_IF_Module.h"
53
#include "openair1/SIMULATION/TOOLS/sim.h"
laurent's avatar
laurent committed
54 55 56 57 58 59 60 61 62 63

#ifdef SMBV
#include "PHY/TOOLS/smbv.h"
unsigned short config_frames[4] = {2,9,11,13};
#endif
#include "common/utils/LOG/log.h"
#include "common/utils/LOG/vcd_signal_dumper.h"

#include "UTIL/OPT/opt.h"
#include "enb_config.h"
64
#include "LAYER2/nr_pdcp/nr_pdcp_oai_api.h"
laurent's avatar
laurent committed
65 66 67

#include "intertask_interface.h"

68
#include "PHY/INIT/nr_phy_init.h"
laurent's avatar
laurent committed
69 70
#include "system.h"
#include <openair2/RRC/NR_UE/rrc_proto.h>
laurent's avatar
laurent committed
71 72
#include <openair2/LAYER2/NR_MAC_UE/mac_defs.h>
#include <openair2/LAYER2/NR_MAC_UE/mac_proto.h>
laurent's avatar
laurent committed
73 74 75
#include <openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.h>
#include <openair1/SCHED_NR_UE/fapi_nr_ue_l1.h>

Laurent's avatar
Laurent committed
76
/* Callbacks, globals and object handlers */
77

laurent's avatar
laurent committed
78 79
//#include "stats.h"
// current status is that every UE has a DL scope for a SINGLE eNB (eNB_id=0)
80
#include "PHY/TOOLS/phy_scope_interface.h"
laurent's avatar
laurent committed
81
#include "PHY/TOOLS/nr_phy_scope.h"
laurent's avatar
laurent committed
82
#include <executables/nr-uesoftmodem.h>
83 84
#include "executables/softmodem-common.h"
#include "executables/thread-common.h"
laurent's avatar
laurent committed
85

86
#include "nr_nas_msg_sim.h"
Laurent THOMAS's avatar
Laurent THOMAS committed
87
#include <openair1/PHY/MODULATION/nr_modulation.h>
Melissa Elkadi's avatar
Melissa Elkadi committed
88
#include "openair2/GNB_APP/gnb_paramdef.h"
89

90
extern const char *duplex_mode[];
91
THREAD_STRUCT thread_struct;
92
nrUE_params_t nrUE_params;
93

94
// Thread variables
95 96 97 98 99 100 101 102
pthread_cond_t nfapi_sync_cond;
pthread_mutex_t nfapi_sync_mutex;
int nfapi_sync_var=-1; //!< protected by mutex \ref nfapi_sync_mutex
uint16_t sf_ahead=6; //??? value ???
pthread_cond_t sync_cond;
pthread_mutex_t sync_mutex;
int sync_var=-1; //!< protected by mutex \ref sync_mutex.
int config_sync_var=-1;
103

Laurent THOMAS's avatar
Laurent THOMAS committed
104 105 106
// not used in UE
instance_t CUuniqInstance=0;
instance_t DUuniqInstance=0;
107

108 109
int get_node_type() {return -1;}

laurent's avatar
laurent committed
110
RAN_CONTEXT_t RC;
111
int oai_exit = 0;
laurent's avatar
laurent committed
112 113


114 115
extern int16_t  nr_dlsch_demod_shift;
static int      tx_max_power[MAX_NUM_CCs] = {0};
laurent's avatar
laurent committed
116

117 118 119
int      single_thread_flag = 1;
int                 tddflag = 0;
int                 vcdflag = 0;
120

121 122
double          rx_gain_off = 0.0;
char             *usrp_args = NULL;
123 124
char             *tx_subdev = NULL;
char             *rx_subdev = NULL;
125
char       *rrc_config_path = NULL;
Sagar Parsawar's avatar
Sagar Parsawar committed
126 127
char *reconfig_file = NULL;
char *rbconfig_file = NULL;
128
char            *uecap_file = NULL;
129 130 131 132
int               dumpframe = 0;

uint64_t        downlink_frequency[MAX_NUM_CCs][4];
int32_t         uplink_frequency_offset[MAX_NUM_CCs][4];
133
uint64_t        sidelink_frequency[MAX_NUM_CCs][4];
134
int             rx_input_level_dBm;
laurent's avatar
laurent committed
135 136 137 138 139 140 141 142 143 144 145

#if MAX_NUM_CCs == 1
rx_gain_t                rx_gain_mode[MAX_NUM_CCs][4] = {{max_gain,max_gain,max_gain,max_gain}};
double tx_gain[MAX_NUM_CCs][4] = {{20,0,0,0}};
double rx_gain[MAX_NUM_CCs][4] = {{110,0,0,0}};
#else
rx_gain_t                rx_gain_mode[MAX_NUM_CCs][4] = {{max_gain,max_gain,max_gain,max_gain},{max_gain,max_gain,max_gain,max_gain}};
double tx_gain[MAX_NUM_CCs][4] = {{20,0,0,0},{20,0,0,0}};
double rx_gain[MAX_NUM_CCs][4] = {{110,0,0,0},{20,0,0,0}};
#endif

146
// UE and OAI config variables
laurent's avatar
laurent committed
147

148 149 150 151 152
openair0_config_t openair0_cfg[MAX_CARDS];
int16_t           node_synch_ref[MAX_NUM_CCs];
int               otg_enabled;
double            cpuf;

153

154
int          chain_offset = 0;
cig's avatar
cig committed
155
int           card_offset = 0;
156 157 158 159
uint64_t num_missed_slots = 0; // counter for the number of missed slots
int            numerology = 0;
int           oaisim_flag = 0;
int            emulate_rf = 0;
rmagueta's avatar
rmagueta committed
160
uint32_t       N_RB_DL    = 106;
laurent's avatar
laurent committed
161 162 163 164 165 166

/* see file openair2/LAYER2/MAC/main.c for why abstraction_flag is needed
 * this is very hackish - find a proper solution
 */
uint8_t abstraction_flag=0;

167
nr_bler_struct nr_bler_data[NR_NUM_MCS];
168

Melissa Elkadi's avatar
Melissa Elkadi committed
169
static void init_bler_table(char*);
170

laurent's avatar
laurent committed
171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192
/*---------------------BMC: timespec helpers -----------------------------*/

struct timespec min_diff_time = { .tv_sec = 0, .tv_nsec = 0 };
struct timespec max_diff_time = { .tv_sec = 0, .tv_nsec = 0 };

struct timespec clock_difftime(struct timespec start, struct timespec end) {
  struct timespec temp;

  if ((end.tv_nsec-start.tv_nsec)<0) {
    temp.tv_sec = end.tv_sec-start.tv_sec-1;
    temp.tv_nsec = 1000000000+end.tv_nsec-start.tv_nsec;
  } else {
    temp.tv_sec = end.tv_sec-start.tv_sec;
    temp.tv_nsec = end.tv_nsec-start.tv_nsec;
  }

  return temp;
}

void print_difftimes(void) {
  LOG_I(HW,"difftimes min = %lu ns ; max = %lu ns\n", min_diff_time.tv_nsec, max_diff_time.tv_nsec);
}
193

194 195 196 197 198 199
int create_tasks_nrue(uint32_t ue_nb) {
  LOG_D(NR_RRC, "%s(ue_nb:%d)\n", __FUNCTION__, ue_nb);
  itti_wait_ready(1);

  if (ue_nb > 0) {
    LOG_I(NR_RRC,"create TASK_RRC_NRUE \n");
200 201
    const ittiTask_parms_t parmsRRC = {NULL, rrc_nrue};
    if (itti_create_task(TASK_RRC_NRUE, rrc_nrue_task, &parmsRRC) < 0) {
202 203 204
      LOG_E(NR_RRC, "Create task for RRC UE failed\n");
      return -1;
    }
205 206 207 208 209 210 211
    if (get_softmodem_params()->nsa) {
      init_connections_with_lte_ue();
      if (itti_create_task (TASK_RRC_NSA_NRUE, recv_msgs_from_lte_ue, NULL) < 0) {
        LOG_E(NR_RRC, "Create task for RRC NSA nr-UE failed\n");
        return -1;
      }
    }
212 213
    const ittiTask_parms_t parmsNAS = {NULL, nas_nrue};
    if (itti_create_task(TASK_NAS_NRUE, nas_nrue_task, &parmsNAS) < 0) {
214
      LOG_E(NR_RRC, "Create task for NAS UE failed\n");
215 216
      return -1;
    }
217
  }
laurent's avatar
laurent committed
218

219
  itti_wait_ready(0);
220

221 222
  return 0;
}
223

224 225
void exit_function(const char *file, const char *function, const int line, const char *s, const int assert)
{
laurent's avatar
laurent committed
226 227 228 229 230 231 232 233 234 235 236 237 238 239 240
  int CC_id;

  if (s != NULL) {
    printf("%s:%d %s() Exiting OAI softmodem: %s\n",file,line, function, s);
  }

  oai_exit = 1;

  if (PHY_vars_UE_g && PHY_vars_UE_g[0]) {
    for(CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
      if (PHY_vars_UE_g[0][CC_id] && PHY_vars_UE_g[0][CC_id]->rfdevice.trx_end_func)
        PHY_vars_UE_g[0][CC_id]->rfdevice.trx_end_func(&PHY_vars_UE_g[0][CC_id]->rfdevice);
    }
  }

241 242 243 244 245 246
  if (assert) {
    abort();
  } else {
    sleep(1); // allow lte-softmodem threads to exit first
    exit(EXIT_SUCCESS);
  }
laurent's avatar
laurent committed
247 248
}

249 250 251
uint64_t get_nrUE_optmask(void) {
  return nrUE_params.optmask;
}
laurent's avatar
laurent committed
252

253 254 255
uint64_t set_nrUE_optmask(uint64_t bitmask) {
  nrUE_params.optmask = nrUE_params.optmask | bitmask;
  return nrUE_params.optmask;
laurent's avatar
laurent committed
256
}
257

258 259
nrUE_params_t *get_nrUE_params(void) {
  return &nrUE_params;
laurent's avatar
laurent committed
260
}
261 262
static void get_options(configmodule_interface_t *cfg)
{
263
  paramdef_t cmdline_params[] =CMDLINE_NRUEPARAMS_DESC ;
264 265
  int numparams = sizeofArray(cmdline_params);
  config_get(cfg, cmdline_params, numparams, NULL);
laurent's avatar
laurent committed
266

267 268
  AssertFatal(rrc_config_path == NULL, "the option \"rrc_config_path\" is deprecated. Please use --reconfig-file and --rbconfig-file separately to point to files reconfig.raw and rbconfig.raw\n");

269 270
  if (vcdflag > 0)
    ouput_vcd = 1;
laurent's avatar
laurent committed
271 272
}

273 274
// set PHY vars from command line
void set_options(int CC_id, PHY_VARS_NR_UE *UE){
275
  NR_DL_FRAME_PARMS *fp = &UE->frame_parms;
276 277 278 279 280 281 282 283

  // Init power variables
  tx_max_power[CC_id] = tx_max_power[0];
  rx_gain[0][CC_id]   = rx_gain[0][0];
  tx_gain[0][CC_id]   = tx_gain[0][0];

  // Set UE variables
  UE->rx_total_gain_dB     = (int)rx_gain[CC_id][0] + rx_gain_off;
284
  UE->tx_total_gain_dB     = (int)tx_gain[CC_id][0];
285
  UE->tx_power_max_dBm     = tx_max_power[CC_id];
cig's avatar
cig committed
286 287
  UE->rf_map.card          = card_offset;
  UE->rf_map.chain         = CC_id + chain_offset;
288 289 290 291 292 293 294 295 296 297 298 299
  UE->max_ldpc_iterations  = nrUE_params.max_ldpc_iterations;
  UE->UE_scan_carrier      = nrUE_params.UE_scan_carrier;
  UE->UE_fo_compensation   = nrUE_params.UE_fo_compensation;
  UE->if_freq              = nrUE_params.if_freq;
  UE->if_freq_off          = nrUE_params.if_freq_off;
  UE->chest_freq           = nrUE_params.chest_freq;
  UE->chest_time           = nrUE_params.chest_time;
  UE->no_timing_correction = nrUE_params.no_timing_correction;
  UE->timing_advance       = nrUE_params.timing_advance;

  LOG_I(PHY,"Set UE_fo_compensation %d, UE_scan_carrier %d, UE_no_timing_correction %d \n, chest-freq %d, chest-time %d\n",
        UE->UE_fo_compensation, UE->UE_scan_carrier, UE->no_timing_correction, UE->chest_freq, UE->chest_time);
300 301

  // Set FP variables
302

303 304 305 306
  if (tddflag){
    fp->frame_type = TDD;
    LOG_I(PHY, "Set UE frame_type %d\n", fp->frame_type);
  }
laurent's avatar
laurent committed
307

308 309 310 311 312 313
  fp->nb_antennas_rx       = nrUE_params.nb_antennas_rx;
  fp->nb_antennas_tx       = nrUE_params.nb_antennas_tx;
  fp->threequarter_fs      = nrUE_params.threequarter_fs;
  fp->N_RB_DL              = nrUE_params.N_RB_DL;
  fp->ssb_start_subcarrier = nrUE_params.ssb_start_subcarrier;
  fp->ofdm_offset_divisor  = nrUE_params.ofdm_offset_divisor;
laurent's avatar
laurent committed
314

315
  LOG_I(PHY, "Set UE nb_rx_antenna %d, nb_tx_antenna %d, threequarter_fs %d, ssb_start_subcarrier %d\n", fp->nb_antennas_rx, fp->nb_antennas_tx, fp->threequarter_fs, fp->ssb_start_subcarrier);
316

laurent's avatar
laurent committed
317 318 319 320
}

void init_openair0(void) {
  int card;
321
  int freq_off = 0;
322
  NR_DL_FRAME_PARMS *frame_parms = &PHY_vars_UE_g[0][0]->frame_parms;
laurent's avatar
laurent committed
323 324

  for (card=0; card<MAX_CARDS; card++) {
325
    uint64_t dl_carrier, ul_carrier, sl_carrier;
326 327 328 329
    openair0_cfg[card].configFilename    = NULL;
    openair0_cfg[card].threequarter_fs   = frame_parms->threequarter_fs;
    openair0_cfg[card].sample_rate       = frame_parms->samples_per_subframe * 1e3;
    openair0_cfg[card].samples_per_frame = frame_parms->samples_per_frame;
laurent's avatar
laurent committed
330

331
    if (frame_parms->frame_type==TDD)
laurent's avatar
laurent committed
332
      openair0_cfg[card].duplex_mode = duplex_mode_TDD;
333
    else
laurent's avatar
laurent committed
334 335 336
      openair0_cfg[card].duplex_mode = duplex_mode_FDD;

    openair0_cfg[card].Mod_id = 0;
337
    openair0_cfg[card].num_rb_dl = frame_parms->N_RB_DL;
338 339
    openair0_cfg[card].clock_source = get_softmodem_params()->clock_source;
    openair0_cfg[card].time_source = get_softmodem_params()->timing_source;
340
    openair0_cfg[card].tune_offset = get_softmodem_params()->tune_offset;
341 342
    openair0_cfg[card].tx_num_channels = min(4, frame_parms->nb_antennas_tx);
    openair0_cfg[card].rx_num_channels = min(4, frame_parms->nb_antennas_rx);
laurent's avatar
laurent committed
343

344
    LOG_I(PHY, "HW: Configuring card %d, sample_rate %f, tx/rx num_channels %d/%d, duplex_mode %s\n",
345
      card,
346
      openair0_cfg[card].sample_rate,
347 348 349
      openair0_cfg[card].tx_num_channels,
      openair0_cfg[card].rx_num_channels,
      duplex_mode[openair0_cfg[card].duplex_mode]);
laurent's avatar
laurent committed
350

351
    nr_get_carrier_frequencies(PHY_vars_UE_g[0][0], &dl_carrier, &ul_carrier);
352

francescomani's avatar
francescomani committed
353
    nr_rf_card_config_freq(&openair0_cfg[card], ul_carrier, dl_carrier, freq_off);
354 355 356 357 358 359

    if (get_softmodem_params()->sl_mode == 2) {
      nr_get_carrier_frequencies_sl(PHY_vars_UE_g[0][0], &sl_carrier);
      nr_rf_card_config_freq(&openair0_cfg[card], sl_carrier, sl_carrier, freq_off);
    }

francescomani's avatar
francescomani committed
360
    nr_rf_card_config_gain(&openair0_cfg[card], rx_gain_off);
361 362

    openair0_cfg[card].configFilename = get_softmodem_params()->rf_config_file;
laurent's avatar
laurent committed
363 364

    if (usrp_args) openair0_cfg[card].sdr_addrs = usrp_args;
365 366
    if (tx_subdev) openair0_cfg[card].tx_subdev = tx_subdev;
    if (rx_subdev) openair0_cfg[card].rx_subdev = rx_subdev;
laurent's avatar
laurent committed
367 368 369 370

  }
}

371
static void init_pdcp(int ue_id) {
372 373
  uint32_t pdcp_initmask = (!IS_SOFTMODEM_NOS1) ? LINK_ENB_PDCP_TO_GTPV1U_BIT : (LINK_ENB_PDCP_TO_GTPV1U_BIT | PDCP_USE_NETLINK_BIT | LINK_ENB_PDCP_TO_IP_DRIVER_BIT);

Robert Schmidt's avatar
Robert Schmidt committed
374
  /*if (IS_SOFTMODEM_RFSIM || (nfapi_getmode()==NFAPI_UE_STUB_PNF)) {
375 376 377
    pdcp_initmask = pdcp_initmask | UE_NAS_USE_TUN_BIT;
  }*/

378
  if (IS_SOFTMODEM_NOKRNMOD) {
379
    pdcp_initmask = pdcp_initmask | UE_NAS_USE_TUN_BIT;
380
  }
381
  if (get_softmodem_params()->nsa && rlc_module_init(0) != 0) {
laurent's avatar
laurent committed
382
    LOG_I(RLC, "Problem at RLC initiation \n");
383
  }
384
  nr_pdcp_layer_init(false);
385
  nr_pdcp_module_init(pdcp_initmask, ue_id);
386 387 388 389
  pdcp_set_rlc_data_req_func((send_rlc_data_req_func_t) rlc_data_req);
  pdcp_set_pdcp_data_ind_func((pdcp_data_ind_func_t) pdcp_data_ind);
}

390
// Stupid function addition because UE itti messages queues definition is common with eNB
laurent's avatar
laurent committed
391
void *rrc_enb_process_msg(void *notUsed) {
laurent's avatar
laurent committed
392
  return NULL;
393 394
}

395 396
static bool stop_immediately = false;
static void trigger_stop(int sig)
Robert Schmidt's avatar
Robert Schmidt committed
397
{
398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413
  if (!oai_exit)
    itti_wait_tasks_unblock();
}
static void trigger_deregistration(int sig)
{
  if (!stop_immediately) {
    MessageDef *msg = itti_alloc_new_message(TASK_RRC_UE_SIM, 0, NAS_DEREGISTRATION_REQ);
    itti_send_msg_to_task(TASK_NAS_NRUE, 0, msg);
    stop_immediately = true;
    static const char m[] = "Press ^C again to trigger immediate shutdown\n";
    __attribute__((unused)) int unused = write(STDOUT_FILENO, m, sizeof(m) - 1);
    signal(SIGALRM, trigger_stop);
    alarm(5);
  } else {
    itti_wait_tasks_unblock();
  }
Robert Schmidt's avatar
Robert Schmidt committed
414 415
}

416 417
static void get_channel_model_mode(configmodule_interface_t *cfg)
{
Melissa Elkadi's avatar
Melissa Elkadi committed
418
  paramdef_t GNBParams[]  = GNBPARAMS_DESC;
419
  config_get(cfg, GNBParams, sizeofArray(GNBParams), NULL);
Melissa Elkadi's avatar
Melissa Elkadi committed
420 421 422 423 424 425 426 427
  int num_xp_antennas = *GNBParams[GNB_PDSCH_ANTENNAPORTS_XP_IDX].iptr;

  if (num_xp_antennas == 2)
    init_bler_table("NR_MIMO2x2_AWGN_RESULTS_DIR");
  else
    init_bler_table("NR_AWGN_RESULTS_DIR");
}

laurent's avatar
laurent committed
428
int NB_UE_INST = 1;
429
configmodule_interface_t *uniqCfg = NULL;
laurent's avatar
laurent committed
430

431
// A global var to reduce the changes size
432
ldpc_interface_t ldpc_interface = {0}, ldpc_interface_offload = {0};
433

laurent's avatar
laurent committed
434
int main( int argc, char **argv ) {
435 436 437 438 439 440 441 442
  int set_exe_prio = 1;
  if (checkIfFedoraDistribution())
    if (checkIfGenericKernelOnFedora())
      if (checkIfInsideContainer())
        set_exe_prio = 0;
  if (set_exe_prio)
    set_priority(79);

laurent's avatar
laurent committed
443 444
  start_background_system();

445
  if ((uniqCfg = load_configmodule(argc, argv, CONFIG_ENABLECMDLINEONLY)) == NULL) {
laurent's avatar
laurent committed
446 447
    exit_fun("[SOFTMODEM] Error, configuration module init failed\n");
  }
Robert Schmidt's avatar
Robert Schmidt committed
448
  //set_softmodem_sighandler();
laurent's avatar
laurent committed
449 450 451 452 453 454
  CONFIG_SETRTFLAG(CONFIG_NOEXITONHELP);
  memset(openair0_cfg,0,sizeof(openair0_config_t)*MAX_CARDS);
  memset(tx_max_power,0,sizeof(int)*MAX_NUM_CCs);
  // initialize logging
  logInit();
  // get options and fill parameters from configuration file
455

456
  get_options(uniqCfg); // Command-line options specific for NRUE
457

458
  get_common_options(uniqCfg, SOFTMODEM_5GUE_BIT);
459
  CONFIG_CLEARRTFLAG(CONFIG_NOEXITONHELP);
laurent's avatar
laurent committed
460 461 462
#if T_TRACER
  T_Config_Init();
#endif
463
  initTpool(get_softmodem_params()->threadPoolConfig, &(nrUE_params.Tpool), cpumeas(CPUMEAS_GETSTATE));
laurent's avatar
laurent committed
464 465
  //randominit (0);
  set_taus_seed (0);
466

laurent's avatar
laurent committed
467
  cpuf=get_cpu_freq_GHz();
Laurent Thomas's avatar
Laurent Thomas committed
468
  itti_init(TASK_MAX, tasks_info);
laurent's avatar
laurent committed
469

470
  init_opt() ;
471 472
  load_LDPClib(NULL, &ldpc_interface);

473 474 475 476
  if (ouput_vcd) {
    vcd_signal_dumper_init("/tmp/openair_dump_nrUE.vcd");
  }

477 478 479 480 481
  #ifndef PACKAGE_VERSION
#  define PACKAGE_VERSION "UNKNOWN-EXPERIMENTAL"
#endif
  LOG_I(HW, "Version: %s\n", PACKAGE_VERSION);

francescomani's avatar
francescomani committed
482 483
  PHY_vars_UE_g = malloc(sizeof(*PHY_vars_UE_g));
  PHY_vars_UE_g[0] = malloc(sizeof(*PHY_vars_UE_g[0]) * MAX_NUM_CCs);
484
  for (int CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) {
francescomani's avatar
francescomani committed
485 486
    PHY_vars_UE_g[0][CC_id] = malloc(sizeof(*PHY_vars_UE_g[0][CC_id]));
    memset(PHY_vars_UE_g[0][CC_id], 0, sizeof(*PHY_vars_UE_g[0][CC_id]));
487 488
  }

489
  init_NR_UE(1, uecap_file, reconfig_file, rbconfig_file);
490

491
  int mode_offset = get_softmodem_params()->nsa ? NUMBER_OF_UE_MAX : 1;
492
  uint16_t node_number = get_softmodem_params()->node_number;
493 494
  ue_id_g = (node_number == 0) ? 0 : node_number - 2;
  AssertFatal(ue_id_g >= 0, "UE id is expected to be nonnegative.\n");
495 496 497 498 499 500 501
  if(IS_SOFTMODEM_NOS1 || get_softmodem_params()->sa || get_softmodem_params()->nsa) {
    if(node_number == 0) {
      init_pdcp(0);
    }
    else {
      init_pdcp(mode_offset + ue_id_g);
    }
502
  }
laurent's avatar
laurent committed
503

504
  if (get_softmodem_params()->emulate_l1) {
Melissa Elkadi's avatar
Melissa Elkadi committed
505
    RCconfig_nr_ue_macrlc();
506
    get_channel_model_mode(uniqCfg);
507
  }
laurent's avatar
laurent committed
508

509 510 511
  if (get_softmodem_params()->do_ra)
    AssertFatal(get_softmodem_params()->phy_test == 0,"RA and phy_test are mutually exclusive\n");

512 513 514
  if (get_softmodem_params()->sa)
    AssertFatal(get_softmodem_params()->phy_test == 0,"Standalone mode and phy_test are mutually exclusive\n");

515
  if (!get_softmodem_params()->nsa && get_softmodem_params()->emulate_l1)
516 517
    start_oai_nrue_threads();

518
  if (!get_softmodem_params()->emulate_l1) {
519 520
    PHY_VARS_NR_UE *UE[MAX_NUM_CCs];
    for (int CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) {
521 522 523 524
      UE[CC_id] = PHY_vars_UE_g[0][CC_id];

      set_options(CC_id, UE[CC_id]);
      NR_UE_MAC_INST_t *mac = get_mac_inst(0);
525

526
      if (get_softmodem_params()->sa) { // set frame config to initial values from command line and assume that the SSB is centered on the grid
527
        uint16_t nr_band = get_softmodem_params()->band;
528
        mac->nr_band = nr_band;
francescomani's avatar
francescomani committed
529
        mac->ssb_start_subcarrier = UE[CC_id]->frame_parms.ssb_start_subcarrier;
530 531 532 533 534 535 536
        nr_init_frame_parms_ue_sa(&UE[CC_id]->frame_parms,
                                  downlink_frequency[CC_id][0],
                                  uplink_frequency_offset[CC_id][0],
                                  get_softmodem_params()->numerology,
                                  nr_band);
      }
      else{
francescomani's avatar
francescomani committed
537 538 539
        DevAssert(mac->if_module != NULL && mac->if_module->phy_config_request != NULL);
        mac->if_module->phy_config_request(&mac->phy_config);
        mac->phy_config_request_sent = true;
540 541
        fapi_nr_config_request_t *nrUE_config = &UE[CC_id]->nrUE_config;

542
        nr_init_frame_parms_ue(&UE[CC_id]->frame_parms, nrUE_config, mac->nr_band);
543
      }
544

545
      init_nr_ue_vars(UE[CC_id], 0, abstraction_flag);
546
    }
547

548 549 550 551
    init_openair0();
    // init UE_PF_PO and mutex lock
    pthread_mutex_init(&ue_pf_po_mutex, NULL);
    memset (&UE_PF_PO[0][0], 0, sizeof(UE_PF_PO_t)*NUMBER_OF_UE_MAX*MAX_NUM_CCs);
552
    set_latency_target();
553

554 555 556 557
    if(IS_SOFTMODEM_DOSCOPE_QT) {
      load_softscope("nrqt",PHY_vars_UE_g[0][0]);
    }

558
    if(IS_SOFTMODEM_DOSCOPE) {
559
      load_softscope("nr",PHY_vars_UE_g[0][0]);
560
    }
561

562 563
    init_NR_UE_threads(1);
    printf("UE threads created by %ld\n", gettid());
laurent's avatar
laurent committed
564 565 566 567
  }

  // wait for end of program
  printf("TYPE <CTRL-C> TO TERMINATE\n");
568

569 570 571 572
  if (create_tasks_nrue(1) < 0) {
    printf("cannot create ITTI tasks\n");
    exit(-1); // need a softer mode
  }
573

Laurent Thomas's avatar
Laurent Thomas committed
574 575
  // Sleep a while before checking all parameters have been used
  // Some are used directly in external threads, asynchronously
Robert Schmidt's avatar
Robert Schmidt committed
576
  sleep(2);
577
  config_check_unknown_cmdlineopt(uniqCfg, CONFIG_CHECKALLSECTIONS);
laurent's avatar
laurent committed
578

Robert Schmidt's avatar
Robert Schmidt committed
579 580 581
  // wait for end of program
  printf("Entering ITTI signals handler\n");
  printf("TYPE <CTRL-C> TO TERMINATE\n");
582
  itti_wait_tasks_end(trigger_deregistration);
Robert Schmidt's avatar
Robert Schmidt committed
583 584 585
  printf("Returned from ITTI signal handler\n");
  oai_exit=1;
  printf("oai_exit=%d\n",oai_exit);
laurent's avatar
laurent committed
586

587 588 589
  if (ouput_vcd)
    vcd_signal_dumper_close();

Robert Schmidt's avatar
Robert Schmidt committed
590 591 592 593 594 595 596 597
  if (PHY_vars_UE_g && PHY_vars_UE_g[0]) {
    for (int CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) {
      PHY_VARS_NR_UE *phy_vars = PHY_vars_UE_g[0][CC_id];
      if (phy_vars && phy_vars->rfdevice.trx_end_func)
        phy_vars->rfdevice.trx_end_func(&phy_vars->rfdevice);
    }
  }

laurent's avatar
laurent committed
598 599
  return 0;
}
600 601

// Read in each MCS file and build BLER-SINR-TB table
Melissa Elkadi's avatar
Melissa Elkadi committed
602
static void init_bler_table(char *env_string) {
603 604
  memset(nr_bler_data, 0, sizeof(nr_bler_data));

Melissa Elkadi's avatar
Melissa Elkadi committed
605
  const char *awgn_results_dir = getenv(env_string);
606
  if (!awgn_results_dir) {
Melissa Elkadi's avatar
Melissa Elkadi committed
607
    LOG_W(NR_MAC, "No %s\n", env_string);
608
    return;
609 610
  }

611
  for (unsigned int i = 0; i < NR_NUM_MCS; i++) {
612
    char fName[1024];
613
    snprintf(fName, sizeof(fName), "%s/mcs%u_awgn_5G.csv", awgn_results_dir, i);
614
    FILE *pFile = fopen(fName, "r");
615 616 617
    if (!pFile) {
      LOG_E(NR_MAC, "%s: open %s: %s\n", __func__, fName, strerror(errno));
      continue;
618 619 620 621 622 623
    }
    size_t bufSize = 1024;
    char * line = NULL;
    char * token;
    char * temp = NULL;
    int nlines = 0;
624 625
    while (getline(&line, &bufSize, pFile) > 0) {
      if (!strncmp(line, "SNR", 3)) {
626 627 628
        continue;
      }

Melissa Elkadi's avatar
Melissa Elkadi committed
629
      if (nlines > NR_NUM_SINR) {
630
        LOG_E(NR_MAC, "BLER FILE ERROR - num lines greater than expected - file: %s\n", fName);
631 632 633 634 635
        abort();
      }

      token = strtok_r(line, ";", &temp);
      int ncols = 0;
636 637 638
      while (token != NULL) {
        if (ncols > NUM_BLER_COL) {
          LOG_E(NR_MAC, "BLER FILE ERROR - num of cols greater than expected\n");
639 640 641 642 643 644 645 646 647 648 649 650 651 652
          abort();
        }

        nr_bler_data[i].bler_table[nlines][ncols] = strtof(token, NULL);
        ncols++;

        token = strtok_r(NULL, ";", &temp);
      }
      nlines++;
    }
    nr_bler_data[i].length = nlines;
    fclose(pFile);
  }
}