lte-uesoftmodem.c 26 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
/*
 * 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
 */

22
/*! \file lte-uesoftmodem.c
23 24 25 26 27
 * \brief Top-level threads for eNodeB
 * \author R. Knopp, F. Kaltenberger, Navid Nikaein
 * \date 2012
 * \version 0.1
 * \company Eurecom
28
 * \email: {knopp, florian.kaltenberger, navid.nikaein}@eurecom.fr
29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
 * \note
 * \warning
 */


#define _GNU_SOURCE             /* See feature_test_macros(7) */
#include <sched.h>

#include "rt_wrapper.h"


#undef MALLOC //there are two conflicting definitions, so we better make sure we don't use it at all

#include "assertions.h"
#include "msc.h"

#include "PHY/types.h"

47
#include "PHY/defs_UE.h"
48 49 50 51 52 53 54 55 56 57 58
#include "common/ran_context.h"
#include "common/config/config_userapi.h"
#include "common/utils/load_module_shlib.h"
#undef MALLOC //there are two conflicting definitions, so we better make sure we don't use it at all
//#undef FRAME_LENGTH_COMPLEX_SAMPLES //there are two conflicting definitions, so we better make sure we don't use it at all

#include "../../ARCH/COMMON/common_lib.h"
#include "../../ARCH/ETHERNET/USERSPACE/LIB/if_defs.h"

//#undef FRAME_LENGTH_COMPLEX_SAMPLES //there are two conflicting definitions, so we better make sure we don't use it at all

59 60 61 62
#include "PHY/phy_vars_ue.h"
#include "PHY/LTE_TRANSPORT/transport_vars.h"
#include "SCHED/sched_common_vars.h"
#include "PHY/MODULATION/modulation_vars.h"
63

64 65 66 67 68
#include "LAYER2/MAC/mac.h"
#include "LAYER2/MAC/mac_vars.h"
#include "LAYER2/MAC/mac_proto.h"
#include "RRC/LTE/rrc_vars.h"
#include "PHY_INTERFACE/phy_interface_vars.h"
Michael Cook's avatar
Michael Cook committed
69
#include "PHY_INTERFACE/phy_stub_UE.h"
70
#include "PHY/TOOLS/phy_scope_interface.h"
71
#include "common/utils/LOG/log.h"
frtabu's avatar
frtabu committed
72
#include "nfapi/oai_integration/vendor_ext.h"
73 74 75
#include "UTIL/OTG/otg_tx.h"
#include "UTIL/OTG/otg_externs.h"
#include "UTIL/MATH/oml.h"
76
#include "common/utils/LOG/vcd_signal_dumper.h"
77 78 79
#include "UTIL/OPT/opt.h"

#ifndef OPENAIR2
80
  #include "UTIL/OTG/otg_vars.h"
81 82
#endif

83
#include "create_tasks.h"
84 85
#include "system.h"

86

87 88
#include "lte-softmodem.h"

89

90 91
/* temporary compilation wokaround (UE/eNB split */
uint16_t sf_ahead;
92

93

94 95 96 97
pthread_cond_t nfapi_sync_cond;
pthread_mutex_t nfapi_sync_mutex;
int nfapi_sync_var=-1; //!< protected by mutex \ref nfapi_sync_mutex

frtabu's avatar
frtabu committed
98

99
#ifdef UESIM_EXPANSION
100
  uint16_t inst_pdcp_list[NUMBER_OF_UE_MAX];
101
#endif
102
uint16_t sf_ahead=2;
Y_Tomita's avatar
Y_Tomita committed
103
int tddflag;
104 105 106
char *emul_iface;


107 108 109 110 111 112 113 114 115 116 117 118 119
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;

uint16_t runtime_phy_rx[29][6]; // SISO [MCS 0-28][RBs 0-5 : 6, 15, 25, 50, 75, 100]
uint16_t runtime_phy_tx[29][6]; // SISO [MCS 0-28][RBs 0-5 : 6, 15, 25, 50, 75, 100]

volatile int             oai_exit = 0;

unsigned int                    mmapped_dma=0;


Cedric Roux's avatar
Cedric Roux committed
120
uint64_t                 downlink_frequency[MAX_NUM_CCs][4];
121 122 123 124 125 126
int32_t                  uplink_frequency_offset[MAX_NUM_CCs][4];



int UE_scan = 1;
int UE_scan_carrier = 0;
frtabu's avatar
frtabu committed
127

128 129 130
runmode_t mode = normal_txrx;

FILE *input_fd=NULL;
131
int otg_enabled=0;
132 133 134 135

#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}};
136
double rx_gain[MAX_NUM_CCs][4] = {{130,0,0,0}};
137 138 139
#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}};
140
double rx_gain[MAX_NUM_CCs][4] = {{130,0,0,0},{20,0,0,0}};
141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164
#endif

double rx_gain_off = 0.0;

double sample_rate=30.72e6;
double bw = 10.0e6;

static int                      tx_max_power[MAX_NUM_CCs]; /* =  {0,0}*/;


uint8_t dci_Format = 0;
uint8_t agregation_Level =0xFF;

uint8_t nb_antenna_tx = 1;
uint8_t nb_antenna_rx = 1;

char ref[128] = "internal";
char channels[128] = "0";

int                      rx_input_level_dBm;



static LTE_DL_FRAME_PARMS      *frame_parms[MAX_NUM_CCs];
165

166 167
uint64_t num_missed_slots=0; // counter for the number of missed slots

168
// prototypes from function implemented in lte-ue.c, probably should be elsewhere in a include file.
169
extern void init_UE_stub_single_thread(int nb_inst,int eMBMS_active, int uecap_xer_in, char *emul_iface);
170
extern PHY_VARS_UE *init_ue_vars(LTE_DL_FRAME_PARMS *frame_parms, uint8_t UE_id, uint8_t abstraction_flag);
171
extern void get_uethreads_params(void);
172 173 174 175

int transmission_mode=1;


176 177
char *usrp_args=NULL;
char *usrp_clksrc=NULL;
178

laurent's avatar
laurent committed
179
THREAD_STRUCT thread_struct;
180 181 182 183 184 185 186 187 188 189 190
/* struct for ethernet specific parameters given in eNB conf file */
eth_params_t *eth_params;

openair0_config_t openair0_cfg[MAX_CARDS];

double cpuf;

extern char uecap_xer[1024];
char uecap_xer_in=0;

int oaisim_flag=0;
191
//threads_t threads= {-1,-1,-1,-1,-1,-1,-1,-1};
192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207

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

/* forward declarations */
void set_default_frame_parms(LTE_DL_FRAME_PARMS *frame_parms[MAX_NUM_CCs]);

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

209 210 211 212 213 214 215
  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;
  }
216

217 218 219 220 221 222 223 224 225 226 227 228 229 230 231
  return temp;
}

void print_difftimes(void) {
#ifdef DEBUG
  printf("difftimes min = %lu ns ; max = %lu ns\n", min_diff_time.tv_nsec, max_diff_time.tv_nsec);
#else
  LOG_I(HW,"difftimes min = %lu ns ; max = %lu ns\n", min_diff_time.tv_nsec, max_diff_time.tv_nsec);
#endif
}

void update_difftimes(struct timespec start, struct timespec end) {
  struct timespec diff_time = { .tv_sec = 0, .tv_nsec = 0 };
  int             changed = 0;
  diff_time = clock_difftime(start, end);
232

233 234 235 236
  if ((min_diff_time.tv_nsec == 0) || (diff_time.tv_nsec < min_diff_time.tv_nsec)) {
    min_diff_time.tv_nsec = diff_time.tv_nsec;
    changed = 1;
  }
237

238 239 240 241
  if ((max_diff_time.tv_nsec == 0) || (diff_time.tv_nsec > max_diff_time.tv_nsec)) {
    max_diff_time.tv_nsec = diff_time.tv_nsec;
    changed = 1;
  }
242

243
#if 1
244

245
  if (changed) print_difftimes();
246

247 248 249 250 251 252 253 254 255 256 257 258
#endif
}

/*------------------------------------------------------------------------*/

unsigned int build_rflocal(int txi, int txq, int rxi, int rxq) {
  return (txi + (txq<<6) + (rxi<<12) + (rxq<<18));
}
unsigned int build_rfdc(int dcoff_i_rxfe, int dcoff_q_rxfe) {
  return (dcoff_i_rxfe + (dcoff_q_rxfe<<8));
}

259

260
void exit_function(const char *file, const char *function, const int line, const char *s) {
261
  int CC_id;
262
  logClean();
263
  printf("%s:%d %s() Exiting OAI softmodem: %s\n",file,line, function, ((s==NULL)?"":s));
264 265 266
  oai_exit = 1;

  for(CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
267
    if (PHY_vars_UE_g)
268
      if (PHY_vars_UE_g[0])
269 270 271 272
        if (PHY_vars_UE_g[0][CC_id])
          if (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);
  }
273

274 275 276
  sleep(1); //allow lte-softmodem threads to exit first

  if(PHY_vars_UE_g != NULL )
277
    itti_terminate_tasks (TASK_UNKNOWN);
278

279
  exit(1);
280 281
}

282
extern int16_t dlsch_demod_shift;
283

284
static void get_options(void) {
285 286
  int CC_id=0;
  int tddflag=0;
287
  char *loopfile=NULL;
288
  int dumpframe=0;
289
  int timingadv=0;
Cedric Roux's avatar
Cedric Roux committed
290
  uint8_t nfapi_mode = NFAPI_MONOLITHIC;
291
  int simL1flag =0;
292 293

  set_default_frame_parms(frame_parms);
294
  CONFIG_SETRTFLAG(CONFIG_NOEXITONHELP);
295 296
  /* unknown parameters on command line will be checked in main
     after all init have been performed                         */
297
  get_common_options(SOFTMODEM_4GUE_BIT );
298
  get_uethreads_params();
299 300 301 302
  paramdef_t cmdline_uemodeparams[] =CMDLINE_UEMODEPARAMS_DESC;
  paramdef_t cmdline_ueparams[] =CMDLINE_UEPARAMS_DESC;
  config_process_cmdline( cmdline_uemodeparams,sizeof(cmdline_uemodeparams)/sizeof(paramdef_t),NULL);
  config_process_cmdline( cmdline_ueparams,sizeof(cmdline_ueparams)/sizeof(paramdef_t),NULL);
frtabu's avatar
frtabu committed
303 304 305 306
  nfapi_setmode(nfapi_mode);

  if (simL1flag)
    set_softmodem_optmask(SOFTMODEM_SIML1_BIT);
307

308
  if (loopfile != NULL) {
309 310 311 312
    printf("Input file for hardware emulation: %s",loopfile);
    mode=loop_through_memory;
    input_fd = fopen(loopfile,"r");
    AssertFatal(input_fd != NULL,"Please provide a valid input file\n");
313 314
  }

315
  get_softmodem_params()->hw_timing_advance = timingadv;
316

317
  if ( (cmdline_uemodeparams[CMDLINE_CALIBUERX_IDX].paramflags &  PARAMFLAG_PARAMSET) != 0) mode = rx_calib_ue;
318

319
  if ( (cmdline_uemodeparams[CMDLINE_CALIBUERXMED_IDX].paramflags &  PARAMFLAG_PARAMSET) != 0) mode = rx_calib_ue_med;
320

321
  if ( (cmdline_uemodeparams[CMDLINE_CALIBUERXBYP_IDX].paramflags &  PARAMFLAG_PARAMSET) != 0) mode = rx_calib_ue_byp;
322

323
  if (cmdline_uemodeparams[CMDLINE_DEBUGUEPRACH_IDX].uptr)
324 325
    if ( *(cmdline_uemodeparams[CMDLINE_DEBUGUEPRACH_IDX].uptr) > 0) mode = debug_prach;

326
  if (cmdline_uemodeparams[CMDLINE_NOL2CONNECT_IDX].uptr)
327 328 329 330 331
    if ( *(cmdline_uemodeparams[CMDLINE_NOL2CONNECT_IDX].uptr) > 0)  mode = no_L2_connect;

  if (cmdline_uemodeparams[CMDLINE_CALIBPRACHTX_IDX].uptr)
    if ( *(cmdline_uemodeparams[CMDLINE_CALIBPRACHTX_IDX].uptr) > 0) mode = calib_prach_tx;

332
  if (dumpframe  > 0)  mode = rx_dump_frame;
333

334 335 336
  for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
    frame_parms[CC_id]->dl_CarrierFreq = downlink_frequency[0][0];
  }
337

338
  UE_scan=0;
frtabu's avatar
frtabu committed
339

340
  if (tddflag > 0) {
341
    for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
342
      frame_parms[CC_id]->frame_type = TDD;
343 344
      frame_parms[CC_id]->tdd_config = tddflag;
    }
345 346 347
  }

  if (frame_parms[0]->N_RB_DL !=0) {
348 349 350 351
    if ( frame_parms[0]->N_RB_DL < 6 ) {
      frame_parms[0]->N_RB_DL = 6;
      printf ( "%i: Invalid number of ressource blocks, adjusted to 6\n",frame_parms[0]->N_RB_DL);
    }
352

353 354 355 356
    if ( frame_parms[0]->N_RB_DL > 100 ) {
      frame_parms[0]->N_RB_DL = 100;
      printf ( "%i: Invalid number of ressource blocks, adjusted to 100\n",frame_parms[0]->N_RB_DL);
    }
357

358 359 360 361
    if ( frame_parms[0]->N_RB_DL > 50 && frame_parms[0]->N_RB_DL < 100 ) {
      frame_parms[0]->N_RB_DL = 50;
      printf ( "%i: Invalid number of ressource blocks, adjusted to 50\n",frame_parms[0]->N_RB_DL);
    }
362

363 364 365 366
    if ( frame_parms[0]->N_RB_DL > 25 && frame_parms[0]->N_RB_DL < 50 ) {
      frame_parms[0]->N_RB_DL = 25;
      printf ( "%i: Invalid number of ressource blocks, adjusted to 25\n",frame_parms[0]->N_RB_DL);
    }
367

368 369
    UE_scan = 0;
    frame_parms[0]->N_RB_UL=frame_parms[0]->N_RB_DL;
370

371 372 373 374 375 376 377 378 379
    for (CC_id=1; CC_id<MAX_NUM_CCs; CC_id++) {
      frame_parms[CC_id]->N_RB_DL=frame_parms[0]->N_RB_DL;
      frame_parms[CC_id]->N_RB_UL=frame_parms[0]->N_RB_UL;
    }
  }

  for (CC_id=1; CC_id<MAX_NUM_CCs; CC_id++) {
    rx_gain[0][CC_id] = rx_gain[0][0];
    tx_gain[0][CC_id] = tx_gain[0][0];
380 381 382 383 384 385 386 387
  }
}


void set_default_frame_parms(LTE_DL_FRAME_PARMS *frame_parms[MAX_NUM_CCs]) {
  int CC_id;

  for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
388
    frame_parms[CC_id] = (LTE_DL_FRAME_PARMS *) calloc(1, sizeof(LTE_DL_FRAME_PARMS));
389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422
    /* Set some default values that may be overwritten while reading options */
    frame_parms[CC_id]->frame_type          = FDD;
    frame_parms[CC_id]->tdd_config          = 3;
    frame_parms[CC_id]->tdd_config_S        = 0;
    frame_parms[CC_id]->N_RB_DL             = 100;
    frame_parms[CC_id]->N_RB_UL             = 100;
    frame_parms[CC_id]->Ncp                 = NORMAL;
    frame_parms[CC_id]->Ncp_UL              = NORMAL;
    frame_parms[CC_id]->Nid_cell            = 0;
    frame_parms[CC_id]->num_MBSFN_config    = 0;
    frame_parms[CC_id]->nb_antenna_ports_eNB  = 1;
    frame_parms[CC_id]->nb_antennas_tx      = 1;
    frame_parms[CC_id]->nb_antennas_rx      = 1;
    frame_parms[CC_id]->nushift             = 0;
    frame_parms[CC_id]->phich_config_common.phich_resource = oneSixth;
    frame_parms[CC_id]->phich_config_common.phich_duration = normal;
    // UL RS Config
    frame_parms[CC_id]->pusch_config_common.ul_ReferenceSignalsPUSCH.cyclicShift = 0;//n_DMRS1 set to 0
    frame_parms[CC_id]->pusch_config_common.ul_ReferenceSignalsPUSCH.groupHoppingEnabled = 0;
    frame_parms[CC_id]->pusch_config_common.ul_ReferenceSignalsPUSCH.sequenceHoppingEnabled = 0;
    frame_parms[CC_id]->pusch_config_common.ul_ReferenceSignalsPUSCH.groupAssignmentPUSCH = 0;
    frame_parms[CC_id]->prach_config_common.rootSequenceIndex=22;
    frame_parms[CC_id]->prach_config_common.prach_ConfigInfo.zeroCorrelationZoneConfig=1;
    frame_parms[CC_id]->prach_config_common.prach_ConfigInfo.prach_ConfigIndex=0;
    frame_parms[CC_id]->prach_config_common.prach_ConfigInfo.highSpeedFlag=0;
    frame_parms[CC_id]->prach_config_common.prach_ConfigInfo.prach_FreqOffset=0;
    downlink_frequency[CC_id][0] = DEFAULT_DLF; // Use float to avoid issue with frequency over 2^31.
    downlink_frequency[CC_id][1] = downlink_frequency[CC_id][0];
    downlink_frequency[CC_id][2] = downlink_frequency[CC_id][0];
    downlink_frequency[CC_id][3] = downlink_frequency[CC_id][0];
    frame_parms[CC_id]->dl_CarrierFreq=downlink_frequency[CC_id][0];
  }
}

423
void init_openair0(LTE_DL_FRAME_PARMS *frame_parms,int rxgain) {
424 425 426 427 428 429 430
  int card;
  int i;

  for (card=0; card<MAX_CARDS; card++) {
    openair0_cfg[card].mmapped_dma=mmapped_dma;
    openair0_cfg[card].configFilename = NULL;

431 432
    if(frame_parms->N_RB_DL == 100) {
      if (frame_parms->threequarter_fs) {
433 434 435 436
        openair0_cfg[card].sample_rate=23.04e6;
        openair0_cfg[card].samples_per_frame = 230400;
        openair0_cfg[card].tx_bw = 10e6;
        openair0_cfg[card].rx_bw = 10e6;
437
      } else {
438 439 440 441
        openair0_cfg[card].sample_rate=30.72e6;
        openair0_cfg[card].samples_per_frame = 307200;
        openair0_cfg[card].tx_bw = 10e6;
        openair0_cfg[card].rx_bw = 10e6;
442
      }
443
    } else if(frame_parms->N_RB_DL == 50) {
444 445 446 447
      openair0_cfg[card].sample_rate=15.36e6;
      openair0_cfg[card].samples_per_frame = 153600;
      openair0_cfg[card].tx_bw = 5e6;
      openair0_cfg[card].rx_bw = 5e6;
448
    } else if (frame_parms->N_RB_DL == 25) {
449 450 451 452
      openair0_cfg[card].sample_rate=7.68e6;
      openair0_cfg[card].samples_per_frame = 76800;
      openair0_cfg[card].tx_bw = 2.5e6;
      openair0_cfg[card].rx_bw = 2.5e6;
453
    } else if (frame_parms->N_RB_DL == 6) {
454 455 456 457 458 459
      openair0_cfg[card].sample_rate=1.92e6;
      openair0_cfg[card].samples_per_frame = 19200;
      openair0_cfg[card].tx_bw = 1.5e6;
      openair0_cfg[card].rx_bw = 1.5e6;
    }

460
    if (frame_parms->frame_type==TDD)
461 462 463 464 465
      openair0_cfg[card].duplex_mode = duplex_mode_TDD;
    else //FDD
      openair0_cfg[card].duplex_mode = duplex_mode_FDD;

    openair0_cfg[card].Mod_id = 0;
466
    openair0_cfg[card].num_rb_dl=frame_parms->N_RB_DL;
467 468
    openair0_cfg[card].clock_source = get_softmodem_params()->clock_source;
    openair0_cfg[card].time_source = get_softmodem_params()->timing_source;
469 470
    openair0_cfg[card].tx_num_channels=min(2,frame_parms->nb_antennas_tx);
    openair0_cfg[card].rx_num_channels=min(2,frame_parms->nb_antennas_rx);
471 472 473

    for (i=0; i<4; i++) {
      if (i<openair0_cfg[card].tx_num_channels)
474
        openair0_cfg[card].tx_freq[i] = downlink_frequency[0][i]+uplink_frequency_offset[0][i];
475
      else
476
        openair0_cfg[card].tx_freq[i]=0.0;
477 478

      if (i<openair0_cfg[card].rx_num_channels)
479
        openair0_cfg[card].rx_freq[i] = downlink_frequency[0][i];
480
      else
481
        openair0_cfg[card].rx_freq[i]=0.0;
482 483 484

      openair0_cfg[card].autocal[i] = 1;
      openair0_cfg[card].tx_gain[i] = tx_gain[0][i];
485
      openair0_cfg[card].rx_gain[i] = rxgain - rx_gain_off;
486
      openair0_cfg[card].configFilename = get_softmodem_params()->rf_config_file;
487
      printf("Card %d, channel %d, Setting tx_gain %f, rx_gain %f, tx_freq %f, rx_freq %f\n",
488 489 490 491
             card,i, openair0_cfg[card].tx_gain[i],
             openair0_cfg[card].rx_gain[i],
             openair0_cfg[card].tx_freq[i],
             openair0_cfg[card].rx_freq[i]);
492
    }
493 494

    if (usrp_args) openair0_cfg[card].sdr_addrs = usrp_args;
495 496 497 498 499
  }
}



frtabu's avatar
frtabu committed
500
/* helper function to terminate a certain ITTI task
501
 */
502
void terminate_task(task_id_t task_id, module_id_t mod_id) {
503 504 505 506 507 508 509
  LOG_I(ENB_APP, "sending TERMINATE_MESSAGE to task %s (%d)\n", itti_get_task_name(task_id), task_id);
  MessageDef *msg;
  msg = itti_alloc_new_message (ENB_APP, TERMINATE_MESSAGE);
  itti_send_msg_to_task (task_id, ENB_MODULE_ID_TO_INSTANCE(mod_id), msg);
}


510 511 512 513 514 515 516 517 518 519 520
static inline void wait_nfapi_init(char *thread_name) {
  printf( "waiting for NFAPI PNF connection and population of global structure (%s)\n",thread_name);
  pthread_mutex_lock( &nfapi_sync_mutex );

  while (nfapi_sync_var<0)
    pthread_cond_wait( &nfapi_sync_cond, &nfapi_sync_mutex );

  pthread_mutex_unlock(&nfapi_sync_mutex);
  printf( "NFAPI: got sync (%s)\n", thread_name);
}

521 522
int stop_L1L2(module_id_t enb_id) {
  return 0;
523 524 525
}


526 527
int restart_L1L2(module_id_t enb_id) {
  return 0;
528 529
}

530 531 532 533 534 535 536 537 538 539 540
void init_pdcp(void) {
  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);

  if (IS_SOFTMODEM_BASICSIM || IS_SOFTMODEM_RFSIM || (nfapi_getmode()==NFAPI_UE_STUB_PNF)) {
    pdcp_initmask = pdcp_initmask | UE_NAS_USE_TUN_BIT;
  }

  if (IS_SOFTMODEM_NOKRNMOD)
    pdcp_initmask = pdcp_initmask | UE_NAS_USE_TUN_BIT;

  pdcp_module_init(pdcp_initmask);
541 542
  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);
543 544
}

545
int main( int argc, char **argv ) {
546 547
  int CC_id;
  uint8_t  abstraction_flag=0;
548 549 550
#ifdef UESIM_EXPANSION
  memset(inst_pdcp_list, 0, sizeof(inst_pdcp_list));
#endif
551 552 553
  // Default value for the number of UEs. It will hold,
  // if not changed from the command line option --num-ues
  NB_UE_INST=1;
554
  NB_THREAD_INST=1;
555
  configmodule_interface_t *config_mod;
556
  start_background_system();
557
  config_mod = load_configmodule(argc, argv, CONFIG_ENABLECMDLINEONLY);
558

559
  if (config_mod == NULL) {
560
    exit_fun("[SOFTMODEM] Error, configuration module init failed\n");
561
  }
562

563 564 565 566 567 568
  mode = normal_txrx;
  memset(&openair0_cfg[0],0,sizeof(openair0_config_t)*MAX_CARDS);
  set_latency_target();
  logInit();
  printf("Reading in command-line options\n");

569
  for (int i=0; i<MAX_NUM_CCs; i++) tx_max_power[i]=23;
570

571
  get_options ();
572

573
  EPC_MODE_ENABLED = !IS_SOFTMODEM_NOS1;
574
  printf("Running with %d UE instances\n",NB_UE_INST);
575

frtabu's avatar
frtabu committed
576
  if (NB_UE_INST > 1 && (!IS_SOFTMODEM_SIML1)  && NFAPI_MODE!=NFAPI_UE_STUB_PNF) {
577 578 579
    printf("Running with more than 1 UE instance and simL1 is not active, this will result in undefined behaviour for now, exiting.\n");
    abort();
  }
580

581
  // Checking option of nums_ue_thread.
582
  if(NB_THREAD_INST < 1) {
583 584 585
    printf("Running with 0 UE rxtx thread, exiting.\n");
    abort();
  }
586

587
  // Checking option's relation between nums_ue_thread and num-ues
588
  if(NB_UE_INST <NB_THREAD_INST ) {
589 590 591
    printf("Number of UEs < number of UE rxtx threads, exiting.\n");
    abort();
  }
592

593
#if T_TRACER
594
  T_Config_Init();
595 596 597 598
#endif
  //randominit (0);
  set_taus_seed (0);
  cpuf=get_cpu_freq_GHz();
599 600 601
  pthread_cond_init(&sync_cond,NULL);
  pthread_mutex_init(&sync_mutex, NULL);

602
  printf("ITTI init\n");
Cedric Roux's avatar
Cedric Roux committed
603
  itti_init(TASK_MAX, THREAD_MAX, MESSAGES_ID_MAX, tasks_info, messages_info);
604 605

  // initialize mscgen log after ITTI
606
  if (get_softmodem_params()->start_msc) {
607
    load_module_shlib("msc",NULL,0,&msc_interface);
608
  }
609

610
  MSC_INIT(MSC_E_UTRAN, THREAD_MAX+TASK_MAX);
611
  init_opt();
612
  init_pdcp();
613
  //TTN for D2D
614 615 616 617
  printf ("RRC control socket\n");
  rrc_control_socket_init();
  printf ("PDCP PC5S socket\n");
  pdcp_pc5_socket_init();
618
  // to make a graceful exit when ctrl-c is pressed
619
  set_softmodem_sighandler();
620 621 622 623 624 625 626 627
  check_clock();
#ifndef PACKAGE_VERSION
#  define PACKAGE_VERSION "UNKNOWN-EXPERIMENTAL"
#endif
  LOG_I(HW, "Version: %s\n", PACKAGE_VERSION);

  // init the parameters
  for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
628 629 630
    frame_parms[CC_id]->nb_antennas_tx     = nb_antenna_tx;
    frame_parms[CC_id]->nb_antennas_rx     = nb_antenna_rx;
    frame_parms[CC_id]->nb_antenna_ports_eNB = 1; //initial value overwritten by initial sync later
631 632
  }

633
  NB_INST=1;
634

635
  if(NFAPI_MODE==NFAPI_UE_STUB_PNF || NFAPI_MODE==NFAPI_MODE_STANDALONE_PNF) { // || NFAPI_MODE_STANDALONE_PNF
636
    PHY_vars_UE_g = malloc(sizeof(PHY_VARS_UE **)*NB_UE_INST);
637

638 639 640 641
    for (int i=0; i<NB_UE_INST; i++) {
      for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
        PHY_vars_UE_g[i] = malloc(sizeof(PHY_VARS_UE *)*MAX_NUM_CCs);
        PHY_vars_UE_g[i][CC_id] = init_ue_vars(frame_parms[CC_id], i,abstraction_flag);
642

643 644 645 646 647 648 649
        if (get_softmodem_params()->phy_test==1)
          PHY_vars_UE_g[i][CC_id]->mac_enabled = 0;
        else
          PHY_vars_UE_g[i][CC_id]->mac_enabled = 1;
      }
    }
  } else init_openair0(frame_parms[0],(int)rx_gain[0][0]);
650

frtabu's avatar
frtabu committed
651
  if (IS_SOFTMODEM_SIML1 ) {
652 653
    RCConfig_sim();
  }
654

655
  cpuf=get_cpu_freq_GHz();
656 657


laurent's avatar
laurent committed
658
#if 0 // #ifndef DEADLINE_SCHEDULER
659

660 661 662 663 664 665 666
  printf("NO deadline scheduler\n");
  /* Currently we set affinity for UHD to CPU 0 for eNB/UE and only if number of CPUS >2 */
  cpu_set_t cpuset;
  int s;
  char cpu_affinity[1024];
  CPU_ZERO(&cpuset);
#ifdef CPU_AFFINITY
Florian Kaltenberger's avatar
Florian Kaltenberger committed
667
  int j;
668
  if (get_nprocs() > 2) {
Florian Kaltenberger's avatar
Florian Kaltenberger committed
669 670
    for (j = 2; j < get_nprocs(); j++)
      CPU_SET(j, &cpuset);
671

672
    s = pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset);
673

674 675 676 677
    if (s != 0) {
      perror( "pthread_setaffinity_np");
      exit_fun("Error setting processor affinity");
    }
Florian Kaltenberger's avatar
Florian Kaltenberger committed
678
    LOG_I(HW, "Setting the affinity of main function to all CPUs, for device library to use CPU 0 only!\n");
679
  }
680

681 682 683
#endif
  /* Check the actual affinity mask assigned to the thread */
  s = pthread_getaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset);
684

685 686 687 688
  if (s != 0) {
    perror( "pthread_getaffinity_np");
    exit_fun("Error getting processor affinity ");
  }
689

690
  memset(cpu_affinity, 0, sizeof(cpu_affinity));
691

692 693 694 695 696 697 698
  for (int j = 0; j < CPU_SETSIZE; j++) {
    if (CPU_ISSET(j, &cpuset)) {
      char temp[1024];
      sprintf(temp, " CPU_%d ", j);
      strcat(cpu_affinity, temp);
    }
  }
699

700 701
  LOG_I(HW, "CPU Affinity of main() function is... %s\n", cpu_affinity);
#endif
702

703
  if (create_tasks_ue(NB_UE_INST) < 0) {
704 705 706
    printf("cannot create ITTI tasks\n");
    exit(-1); // need a softer mode
  }
707

frtabu's avatar
frtabu committed
708
  if (NFAPI_MODE==NFAPI_UE_STUB_PNF) { // UE-STUB-PNF
709 710 711
    UE_config_stub_pnf();
  }

712
  // end of test
713
  printf("ITTI tasks created\n");
714 715
  mlockall(MCL_CURRENT | MCL_FUTURE);
  rt_sleep_ns(10*100000000ULL);
716
  int eMBMS_active = 0;
717

frtabu's avatar
frtabu committed
718 719 720 721 722 723
  if (NFAPI_MODE==NFAPI_UE_STUB_PNF) { // UE-STUB-PNF
    config_sync_var=0;
    wait_nfapi_init("main?");
    //Panos: Temporarily we will be using single set of threads for multiple UEs.
    //init_UE_stub(1,eMBMS_active,uecap_xer_in,emul_iface);
    init_UE_stub_single_thread(NB_UE_INST,eMBMS_active,uecap_xer_in,emul_iface);
724
  } else if (NFAPI_MODE==NFAPI_MODE_STANDALONE_PNF) {
725 726 727 728
    init_queue(&dl_config_req_queue);
    init_queue(&tx_req_pdu_queue);
    init_queue(&hi_dci0_req_queue);
    init_queue(&ul_config_req_queue);
729
    config_sync_var=0;
730
    init_UE_stub_single_thread(NB_UE_INST,eMBMS_active,uecap_xer_in,emul_iface);
731
    init_UE_standalone_thread();
732 733
  }
  else {
frtabu's avatar
frtabu committed
734 735
    init_UE(NB_UE_INST,eMBMS_active,uecap_xer_in,0,get_softmodem_params()->phy_test,UE_scan,UE_scan_carrier,mode,(int)rx_gain[0][0],tx_max_power[0],
            frame_parms[0]);
736
  }
737

Raphael Defosseux's avatar
Raphael Defosseux committed
738
  if (get_softmodem_params()->phy_test==0) {
739 740 741 742 743
    printf("Filling UE band info\n");
    fill_ue_band_info();
    dl_phy_sync_success (0, 0, 0, 1);
  }

frtabu's avatar
frtabu committed
744 745
  if (NFAPI_MODE != NFAPI_UE_STUB_PNF) {
    number_of_cards = 1;
746

frtabu's avatar
frtabu committed
747 748 749
    for(CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
      PHY_vars_UE_g[0][CC_id]->rf_map.card=0;
      PHY_vars_UE_g[0][CC_id]->rf_map.chain=CC_id+(get_softmodem_params()->chain_offset);
750
    }
751
  }
752

753 754 755 756 757 758 759 760
  if (input_fd) {
    printf("Reading in from file to antenna buffer %d\n",0);

    if (fread(PHY_vars_UE_g[0][0]->common_vars.rxdata[0],
              sizeof(int32_t),
              frame_parms[0]->samples_per_tti*10,
              input_fd) != frame_parms[0]->samples_per_tti*10)
      printf("error reading from file\n");
761
  }
762

763 764
  //p_exmimo_config->framing.tdd_config = TXRXSWITCH_TESTRX;

frtabu's avatar
frtabu committed
765
  if (IS_SOFTMODEM_SIML1 )  {
766
    init_ocm();
767 768
    PHY_vars_UE_g[0][0]->no_timing_correction = 1;
  }
769

770 771
  if(IS_SOFTMODEM_DOFORMS)
    load_softscope("ue");
772

773
  config_check_unknown_cmdlineopt(CONFIG_CHECKALLSECTIONS);
774
  printf("Sending sync to all threads (%p,%p,%p)\n",&sync_var,&sync_cond,&sync_mutex);
775 776 777 778
  pthread_mutex_lock(&sync_mutex);
  sync_var=0;
  pthread_cond_broadcast(&sync_cond);
  pthread_mutex_unlock(&sync_mutex);
779
  printf("sync sent\n");
780 781 782 783 784
  /*
    printf("About to call end_configmodule() from %s() %s:%d\n", __FUNCTION__, __FILE__, __LINE__);
    end_configmodule();
    printf("Called end_configmodule() from %s() %s:%d\n", __FUNCTION__, __FILE__, __LINE__);
  */
785 786 787 788 789 790 791 792
  // wait for end of program
  printf("TYPE <CTRL-C> TO TERMINATE\n");
  //getchar();
  printf("Entering ITTI signals handler\n");
  itti_wait_tasks_end();
  printf("Returned from ITTI signal handler\n");
  oai_exit=1;
  printf("oai_exit=%d\n",oai_exit);
793

794
  // stop threads
795 796
  if(IS_SOFTMODEM_DOFORMS)
    end_forms();
797 798 799 800 801

  printf("stopping MODEM threads\n");
  pthread_cond_destroy(&sync_cond);
  pthread_mutex_destroy(&sync_mutex);

802
  //  pthread_mutex_destroy(&ue_pf_po_mutex);
803 804 805 806

  // *** Handle per CC_id openair0
  if (PHY_vars_UE_g[0][0]->rfdevice.trx_end_func)
    PHY_vars_UE_g[0][0]->rfdevice.trx_end_func(&PHY_vars_UE_g[0][0]->rfdevice);
807

808
  terminate_opt();
809
  logClean();
810 811 812
  printf("Bye.\n");
  return 0;
}