lte-ue.c 86.2 KB
Newer Older
1 2 3 4 5
/*
 * 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
6
 * the OAI Public License, Version 1.1  (the "License"); you may not use this file
7 8 9 10 11 12 13 14 15 16 17 18 19 20
 * 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
 */
21 22 23 24 25 26 27 28 29 30 31

/*! \file lte-ue.c
 * \brief threads and support functions for real-time LTE UE target
 * \author R. Knopp, F. Kaltenberger, Navid Nikaein
 * \date 2015
 * \version 0.1
 * \company Eurecom
 * \email: knopp@eurecom.fr,florian.kaltenberger@eurecom.fr, navid.nikaein@eurecom.fr
 * \note
 * \warning
 */
32
#include "lte-softmodem.h"
33 34

#include "rt_wrapper.h"
35
#include "system.h"
36

37 38
#include "LAYER2/MAC/mac.h"
#include "RRC/LTE/rrc_extern.h"
39
#include "PHY_INTERFACE/phy_stub_UE.h"
40
#include "PHY_INTERFACE/phy_interface_extern.h"
41 42 43
#include "PHY/INIT/phy_init.h"
#include "PHY/MODULATION/modulation_UE.h"
#include "PHY/LTE_ESTIMATION/lte_estimation.h"
44 45 46 47

#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

48 49 50
#include "PHY/phy_extern_ue.h"
#include "LAYER2/MAC/mac_extern.h"
#include "LAYER2/MAC/mac_proto.h"
51 52 53
#include "SCHED_UE/sched_UE.h"
#include "PHY/LTE_UE_TRANSPORT/transport_proto_ue.h"

54
#include <inttypes.h>
55

56
#include "common/utils/LOG/log.h"
frtabu's avatar
frtabu committed
57
#include "nfapi/oai_integration/vendor_ext.h"
58 59 60
#include "UTIL/OTG/otg_tx.h"
#include "UTIL/OTG/otg_externs.h"
#include "UTIL/MATH/oml.h"
61
#include "common/utils/LOG/vcd_signal_dumper.h"
62
#include "UTIL/OPT/opt.h"
63
#include "lte-softmodem.h"
64
#include "common/config/config_userapi.h"
65 66
#include "T.h"

hbilel's avatar
hbilel committed
67
extern double cpuf;
frtabu's avatar
frtabu committed
68

hbilel's avatar
hbilel committed
69

70 71
#define FRAME_PERIOD    100000000ULL
#define DAQ_PERIOD      66667ULL
laurent's avatar
laurent committed
72
#define FIFO_PRIORITY   40
73 74

typedef enum {
75 76 77
  pss=0,
  pbch=1,
  si=2
78 79
} sync_mode_t;

80
void init_UE_threads(int);
81 82
void init_UE_threads_stub(int);
void init_UE_single_thread_stub(int);
83
void *UE_thread(void *arg);
84
void init_UE(int nb_inst,int eMBMS_active, int uecap_xer_in, int timing_correction, int phy_test, int UE_scan, int UE_scan_carrier, runmode_t mode,int rxgain,int txpowermax,LTE_DL_FRAME_PARMS *fp);
85 86
void init_UE_stub(int nb_inst,int,int,char *);
void init_UE_stub_single_thread(int nb_inst,int,int,char *);
87 88 89
int init_timer_thread(void);
extern void oai_subframe_ind(uint16_t sfn, uint16_t sf);
extern void multicast_link_start(void (*rx_handlerP) (unsigned int, char *),
90
                                 unsigned char _multicast_group, char *multicast_ifname);
91
extern int oai_nfapi_crc_indication(nfapi_crc_indication_t *crc_ind);
92
extern int oai_nfapi_cqi_indication(nfapi_cqi_indication_t *cqi_ind);
93 94 95 96 97
extern int oai_nfapi_harq_indication(nfapi_harq_indication_t *harq_ind);
extern int oai_nfapi_sr_indication(nfapi_sr_indication_t *ind);
extern int oai_nfapi_rx_ind(nfapi_rx_indication_t *ind);
extern int multicast_link_write_sock(int groupP, char *dataP, uint32_t sizeP);

98

99
int	tx_req_num_elems;
Y_Tomita's avatar
Y_Tomita committed
100
extern uint16_t sf_ahead;
101 102 103
//extern int tx_req_UE_MAC1();

void ue_stub_rx_handler(unsigned int, char *);
104

105 106
int32_t **rxdata;
int32_t **txdata;
107

108 109 110 111 112
int timer_subframe = 0;
int timer_frame = 0;
SF_ticking *phy_stub_ticking = NULL;
int next_ra_frame = 0;
module_id_t next_Mod_id = 0;
113

114
#define KHz (1000UL)
115
#define MHz (1000*KHz)
116 117

typedef struct eutra_band_s {
118 119 120 121 122 123
  int16_t band;
  uint32_t ul_min;
  uint32_t ul_max;
  uint32_t dl_min;
  uint32_t dl_max;
  lte_frame_type_t frame_type;
124 125 126
} eutra_band_t;

typedef struct band_info_s {
127 128
  int nbands;
  eutra_band_t band_info[100];
129 130 131 132
} band_info_t;

band_info_t bands_to_scan;

133
static const eutra_band_t eutra_bands[] = {
134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162
  { 1, 1920    * MHz, 1980    * MHz, 2110    * MHz, 2170    * MHz, FDD},
  { 2, 1850    * MHz, 1910    * MHz, 1930    * MHz, 1990    * MHz, FDD},
  { 3, 1710    * MHz, 1785    * MHz, 1805    * MHz, 1880    * MHz, FDD},
  { 4, 1710    * MHz, 1755    * MHz, 2110    * MHz, 2155    * MHz, FDD},
  { 5,  824    * MHz,  849    * MHz,  869    * MHz,  894    * MHz, FDD},
  { 6,  830    * MHz,  840    * MHz,  875    * MHz,  885    * MHz, FDD},
  { 7, 2500    * MHz, 2570    * MHz, 2620    * MHz, 2690    * MHz, FDD},
  { 8,  880    * MHz,  915    * MHz,  925    * MHz,  960    * MHz, FDD},
  { 9, 1749900 * KHz, 1784900 * KHz, 1844900 * KHz, 1879900 * KHz, FDD},
  {10, 1710    * MHz, 1770    * MHz, 2110    * MHz, 2170    * MHz, FDD},
  {11, 1427900 * KHz, 1452900 * KHz, 1475900 * KHz, 1500900 * KHz, FDD},
  {12,  698    * MHz,  716    * MHz,  728    * MHz,  746    * MHz, FDD},
  {13,  777    * MHz,  787    * MHz,  746    * MHz,  756    * MHz, FDD},
  {14,  788    * MHz,  798    * MHz,  758    * MHz,  768    * MHz, FDD},
  {17,  704    * MHz,  716    * MHz,  734    * MHz,  746    * MHz, FDD},
  {20,  832    * MHz,  862    * MHz,  791    * MHz,  821    * MHz, FDD},
  {22, 3510    * MHz, 3590    * MHz, 3410    * MHz, 3490    * MHz, FDD},
  {33, 1900    * MHz, 1920    * MHz, 1900    * MHz, 1920    * MHz, TDD},
  {34, 2010    * MHz, 2025    * MHz, 2010    * MHz, 2025    * MHz, TDD},
  {35, 1850    * MHz, 1910    * MHz, 1850    * MHz, 1910    * MHz, TDD},
  {36, 1930    * MHz, 1990    * MHz, 1930    * MHz, 1990    * MHz, TDD},
  {37, 1910    * MHz, 1930    * MHz, 1910    * MHz, 1930    * MHz, TDD},
  {38, 2570    * MHz, 2620    * MHz, 2570    * MHz, 2630    * MHz, TDD},
  {39, 1880    * MHz, 1920    * MHz, 1880    * MHz, 1920    * MHz, TDD},
  {40, 2300    * MHz, 2400    * MHz, 2300    * MHz, 2400    * MHz, TDD},
  {41, 2496    * MHz, 2690    * MHz, 2496    * MHz, 2690    * MHz, TDD},
  {42, 3400    * MHz, 3600    * MHz, 3400    * MHz, 3600    * MHz, TDD},
  {43, 3600    * MHz, 3800    * MHz, 3600    * MHz, 3800    * MHz, TDD},
  {44, 703    * MHz, 803    * MHz, 703    * MHz, 803    * MHz, TDD},
163 164
};

165

166
threads_t threads= {-1,-1,-1,-1,-1,-1,-1,-1};
167

168 169 170 171
pthread_t                       main_ue_thread;
pthread_attr_t                  attr_UE_thread;
struct sched_param              sched_param_UE_thread;

172 173 174 175 176 177 178

void get_uethreads_params(void) {
  paramdef_t cmdline_threadsparams[] =CMDLINE_UETHREADSPARAMS_DESC;
  config_process_cmdline( cmdline_threadsparams,sizeof(cmdline_threadsparams)/sizeof(paramdef_t),NULL);
}


179
void phy_init_lte_ue_transport(PHY_VARS_UE *ue,int absraction_flag);
180

181 182 183
PHY_VARS_UE *init_ue_vars(LTE_DL_FRAME_PARMS *frame_parms,
                          uint8_t UE_id,
                          uint8_t abstraction_flag)
184 185

{
Laurent THOMAS's avatar
Laurent THOMAS committed
186
  PHY_VARS_UE *ue = (PHY_VARS_UE *)calloc(1,sizeof(PHY_VARS_UE));
187
  AssertFatal(ue,"");
188
  if (frame_parms!=(LTE_DL_FRAME_PARMS *)NULL) { // if we want to give initial frame parms, allocate the PHY_VARS_UE structure and put them in
189
    memcpy(&(ue->frame_parms), frame_parms, sizeof(LTE_DL_FRAME_PARMS));
190
  }
191

192
  ue->hw_timing_advance=get_softmodem_params()->hw_timing_advance;
193 194
  ue->Mod_id      = UE_id;
  ue->mac_enabled = 1;
195

196
  // In phy_stub_UE (MAC-to-MAC) mode these init functions don't need to get called. Is this correct?
frtabu's avatar
frtabu committed
197
  if (NFAPI_MODE!=NFAPI_UE_STUB_PNF) {
198 199 200 201 202
    // initialize all signal buffers
    init_lte_ue_signal(ue,1,abstraction_flag);
    // intialize transport
    init_lte_ue_transport(ue,abstraction_flag);
  }
203 204

  return(ue);
205 206
}

207

208 209
char uecap_xer[1024];

210 211


212
void init_thread(int sched_runtime,
213 214 215 216
                 int sched_deadline,
                 int sched_fifo,
                 cpu_set_t *cpuset,
                 char *name)
217
{
laurent's avatar
laurent committed
218
#ifdef DEADLINE_SCHEDULER
219

220 221 222 223 224 225 226 227
  if (sched_runtime!=0) {
    struct sched_attr attr= {0};
    attr.size = sizeof(attr);
    attr.sched_policy = SCHED_DEADLINE;
    attr.sched_runtime  = sched_runtime;
    attr.sched_deadline = sched_deadline;
    attr.sched_period   = 0;
    AssertFatal(sched_setattr(0, &attr, 0) == 0,
228
                "[SCHED] %s thread: sched_setattr failed %s \n", name, strerror(errno));
229
    LOG_I(HW,"[SCHED][eNB] %s deadline thread %lu started on CPU %d\n",
230
          name, (unsigned long)gettid(), sched_getcpu());
231
  }
232

laurent's avatar
laurent committed
233
#else
234
  int settingPriority = 1;
235

236 237 238 239 240 241 242 243 244 245 246 247 248 249
  if (checkIfFedoraDistribution())
    if (checkIfGenericKernelOnFedora())
      if (checkIfInsideContainer())
        settingPriority = 0;

  if (settingPriority) {
    if (CPU_COUNT(cpuset) > 0)
      AssertFatal( 0 == pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), cpuset), "");

    struct sched_param sp;
    sp.sched_priority = sched_fifo;
    AssertFatal(pthread_setschedparam(pthread_self(),SCHED_FIFO,&sp)==0,
                "Can't set thread priority, Are you root?\n");
  }
250

251 252
  /* Check the actual affinity mask assigned to the thread */
  cpu_set_t *cset=CPU_ALLOC(CPU_SETSIZE);
253

254
  if (0 == pthread_getaffinity_np(pthread_self(), CPU_ALLOC_SIZE(CPU_SETSIZE), cset)) {
255 256
    char txt[512]= {0};

257 258
    for (int j = 0; j < CPU_SETSIZE; j++)
      if (CPU_ISSET(j, cset))
259 260
        sprintf(txt+strlen(txt), " %d ", j);

261 262
    printf("CPU Affinity of thread %s is %s\n", name, txt);
  }
263

264
  CPU_FREE(cset);
265
#endif
laurent's avatar
laurent committed
266
}
267

268
void init_UE(int nb_inst,
269 270 271 272 273 274 275 276 277 278
             int eMBMS_active,
             int uecap_xer_in,
             int timing_correction,
             int phy_test,
             int UE_scan,
             int UE_scan_carrier,
             runmode_t mode,
             int rxgain,
             int txpowermax,
             LTE_DL_FRAME_PARMS *fp0)
279
{
Raymond Knopp's avatar
Raymond Knopp committed
280
  PHY_VARS_UE *UE;
281 282
  int         inst;
  int         ret;
283
  LTE_DL_FRAME_PARMS *fp;
284
  LOG_I(PHY,"UE : Calling Layer 2 for initialization\n");
285
  l2_init_ue(eMBMS_active,(uecap_xer_in==1)?uecap_xer:NULL,
286 287 288 289 290 291 292
             0,// cba_group_active
             0); // HO flag

  if (PHY_vars_UE_g==NULL) PHY_vars_UE_g = (PHY_VARS_UE ***)calloc(1+nb_inst,sizeof(PHY_VARS_UE **));

  for (inst=0; inst<nb_inst; inst++) {
    if (PHY_vars_UE_g[inst]==NULL) PHY_vars_UE_g[inst] = (PHY_VARS_UE **)calloc(1+MAX_NUM_CCs,sizeof(PHY_VARS_UE *));
293

294
    LOG_I(PHY,"Allocating UE context %d\n",inst);
Raymond Knopp's avatar
Raymond Knopp committed
295

296
    PHY_vars_UE_g[inst][0] = init_ue_vars(fp0,inst,0);
297

298 299
    // turn off timing control loop in UE
    PHY_vars_UE_g[inst][0]->no_timing_correction = timing_correction;
300
    UE = PHY_vars_UE_g[inst][0];
301
    fp = &UE->frame_parms;
302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327
    printf("PHY_vars_UE_g[0][0] = %p\n",UE);

    if (phy_test==1)
      UE->mac_enabled = 0;
    else
      UE->mac_enabled = 1;

    if (UE->mac_enabled == 0) {  //set default UL parameters for testing mode
      for (int i=0; i<NUMBER_OF_CONNECTED_eNB_MAX; i++) {
        UE->pusch_config_dedicated[i].betaOffset_ACK_Index = 0;
        UE->pusch_config_dedicated[i].betaOffset_RI_Index  = 0;
        UE->pusch_config_dedicated[i].betaOffset_CQI_Index = 2;
        UE->scheduling_request_config[i].sr_PUCCH_ResourceIndex = 0;
        UE->scheduling_request_config[i].sr_ConfigIndex = 7+(0%3);
        UE->scheduling_request_config[i].dsr_TransMax = sr_n4;
      }
    }

    UE->UE_scan = UE_scan;
    UE->UE_scan_carrier = UE_scan_carrier;
    UE->mode    = mode;
    printf("UE->mode = %d\n",mode);

    if (UE->mac_enabled == 1) {
      UE->pdcch_vars[0][0]->crnti = 0x1234;
      UE->pdcch_vars[1][0]->crnti = 0x1234;
328
    } else {
329 330 331
      UE->pdcch_vars[0][0]->crnti = 0x1235;
      UE->pdcch_vars[1][0]->crnti = 0x1235;
    }
332

333 334
    UE->rx_total_gain_dB =  rxgain;
    UE->tx_power_max_dBm = txpowermax;
335
    UE->frame_parms.nb_antennas_tx = fp0->nb_antennas_tx;
336
    UE->frame_parms.nb_antennas_rx = fp0->nb_antennas_rx;
337

338 339
    if (fp->frame_type == TDD) {
      switch (fp->N_RB_DL) {
340 341 342
        case 100:
          if (fp->threequarter_fs) UE->N_TA_offset = (624*3)/4;
          else                              UE->N_TA_offset = 624;
343

344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368
          break;

        case 75:
          UE->N_TA_offset = (624*3)/4;
          break;

        case 50:
          UE->N_TA_offset = 624/2;
          break;

        case 25:
          UE->N_TA_offset = 624/4;
          break;

        case 15:
          UE->N_TA_offset = 624/8;
          break;

        case 6:
          UE->N_TA_offset = 624/16;
          break;

        default:
          AssertFatal(1==0,"illegal N_RB_DL %d\n",fp->N_RB_DL);
          break;
369
      }
370
    } else UE->N_TA_offset = 0;
371

372
    if( IS_SOFTMODEM_BASICSIM)
373 374 375
      /* this is required for the basic simulator in TDD mode
       * TODO: find a proper cleaner solution
       */
376 377
      UE->N_TA_offset = 0;

378
    LOG_I(PHY,"Intializing UE Threads for instance %d (%p,%p)...\n",inst,PHY_vars_UE_g[inst],PHY_vars_UE_g[inst][0]);
Raymond Knopp's avatar
Raymond Knopp committed
379
    init_UE_threads(inst);
Raymond Knopp's avatar
Raymond Knopp committed
380

381
    ret = openair0_device_load(&(UE->rfdevice), &openair0_cfg[0]);
382

383 384
    if (ret !=0) {
      exit_fun("Error loading device library");
Rohit Gupta's avatar
Rohit Gupta committed
385
    }
386

387
    UE->rfdevice.host_type = RAU_HOST;
Raymond Knopp's avatar
Raymond Knopp committed
388
    //    UE->rfdevice.type      = NONE_DEV;
389 390 391
    AssertFatal(0 == pthread_create(&UE->proc.pthread_ue,
                                    &UE->proc.attr_ue,
                                    UE_thread,
392
                                    (void *)UE), "");
393 394
  }

395
  printf("UE threads created by %ld\n", gettid());
396 397
}

398
// Initiating all UEs within a single set of threads for PHY_STUB. Future extensions -> multiple
399
// set of threads for multiple UEs.
400
void init_UE_stub_single_thread(int nb_inst,
401 402 403
                                int eMBMS_active,
                                int uecap_xer_in,
                                char *emul_iface)
404
{
405 406 407
  int         inst;
  LOG_I(PHY,"UE : Calling Layer 2 for initialization, nb_inst: %d \n", nb_inst);
  l2_init_ue(eMBMS_active,(uecap_xer_in==1)?uecap_xer:NULL,
408 409
             0,// cba_group_active
             0); // HO flag
410

411
  for (inst=0; inst<nb_inst; inst++) {
412
    LOG_I(PHY,"Initializing memory for UE instance %d (%p)\n",inst,PHY_vars_UE_g[inst]);
Y_Tomita's avatar
Y_Tomita committed
413
    // PHY_vars_UE_g[inst][0] = init_ue_vars(NULL,inst,0);
414
  }
415

416 417 418 419 420
  init_timer_thread();
  init_UE_single_thread_stub(nb_inst);
  printf("UE threads created \n");
  LOG_I(PHY,"Starting multicast link on %s\n",emul_iface);

frtabu's avatar
frtabu committed
421
  if(NFAPI_MODE!=NFAPI_UE_STUB_PNF)
422
    multicast_link_start(ue_stub_rx_handler,0,emul_iface);
423 424 425
}


426
void init_UE_stub(int nb_inst,
427 428 429
                  int eMBMS_active,
                  int uecap_xer_in,
                  char *emul_iface)
430
{
431 432 433
  int         inst;
  LOG_I(PHY,"UE : Calling Layer 2 for initialization\n");
  l2_init_ue(eMBMS_active,(uecap_xer_in==1)?uecap_xer:NULL,
434 435
             0,// cba_group_active
             0); // HO flag
436

437
  for (inst=0; inst<nb_inst; inst++) {
438 439 440 441
    LOG_I(PHY,"Initializing memory for UE instance %d (%p)\n",inst,PHY_vars_UE_g[inst]);
    PHY_vars_UE_g[inst][0] = init_ue_vars(NULL,inst,0);
  }

442
  init_timer_thread();
443

444
  for (inst=0; inst<nb_inst; inst++) {
445 446 447 448 449 450 451
    LOG_I(PHY,"Intializing UE Threads for instance %d (%p,%p)...\n",inst,PHY_vars_UE_g[inst],PHY_vars_UE_g[inst][0]);
    init_UE_threads_stub(inst);
  }

  printf("UE threads created \n");
  LOG_I(PHY,"Starting multicast link on %s\n",emul_iface);

frtabu's avatar
frtabu committed
452
  if(NFAPI_MODE!=NFAPI_UE_STUB_PNF)
453
    multicast_link_start(ue_stub_rx_handler,0,emul_iface);
454 455 456
}


457 458
/*!
 * \brief This is the UE synchronize thread.
459
 * It performs band scanning and synchonization.
460 461 462
 * \param arg is a pointer to a \ref PHY_VARS_UE structure.
 * \returns a pointer to an int. The storage is not on the heap and must not be freed.
 */
laurent's avatar
laurent committed
463

464 465
static void *UE_thread_synch(void *arg)
{
466
  static int UE_thread_synch_retval;
467
  int i ;
468
  PHY_VARS_UE *UE = (PHY_VARS_UE *) arg;
469 470
  int current_band = 0;
  int current_offset = 0;
471
  sync_mode_t sync_mode = pbch;
472
  int CC_id = UE->CC_id;
473 474
  int ind;
  int found;
475
  int freq_offset=0;
476
  char threadname[128];
477
  printf("UE_thread_sync in with PHY_vars_UE %p\n",arg);
478
  cpu_set_t cpuset;
479
  CPU_ZERO(&cpuset);
Florian Kaltenberger's avatar
Florian Kaltenberger committed
480 481
  if ( threads.sync != -1 )
    CPU_SET(threads.sync, &cpuset);
482

483 484 485
  // this thread priority must be lower that the main acquisition thread
  sprintf(threadname, "sync UE %d\n", UE->Mod_id);
  init_thread(100000, 500000, FIFO_PRIORITY-1, &cpuset, threadname);
486
  printf("starting UE synch thread (IC %d)\n",UE->proc.instance_cnt_synch);
487 488
  ind = 0;
  found = 0;
489

490 491
  if (UE->UE_scan == 0) {
    do  {
492
      current_band = eutra_bands[ind].band;
Raymond Knopp's avatar
 
Raymond Knopp committed
493
      printf( "Scanning band %d, dl_min %"PRIu32", ul_min %"PRIu32"\n", current_band, eutra_bands[ind].dl_min,eutra_bands[ind].ul_min);
494

495
      if ((eutra_bands[ind].dl_min <= UE->frame_parms.dl_CarrierFreq) && (eutra_bands[ind].dl_max >= UE->frame_parms.dl_CarrierFreq)) {
496 497
        for (i=0; i<4; i++)
          uplink_frequency_offset[CC_id][i] = eutra_bands[ind].ul_min - eutra_bands[ind].dl_min;
498 499 500 501

        found = 1;
        break;
      }
502

503
      ind++;
504
    } while (ind < sizeof(eutra_bands) / sizeof(eutra_bands[0]));
505

506
    if (found == 0) {
Florian Kaltenberger's avatar
Florian Kaltenberger committed
507
      LOG_E(PHY,"Can't find EUTRA band for frequency %d",UE->frame_parms.dl_CarrierFreq);
508
      exit_fun("Can't find EUTRA band for frequency");
509
      return &UE_thread_synch_retval;
510
    }
511

512 513
    LOG_I( PHY, "[SCHED][UE] Check absolute frequency DL %"PRIu32", UL %"PRIu32" (oai_exit %d, rx_num_channels %d)\n", UE->frame_parms.dl_CarrierFreq, UE->frame_parms.ul_CarrierFreq,oai_exit,
           openair0_cfg[0].rx_num_channels);
514

515
    for (i=0; i<openair0_cfg[UE->rf_map.card].rx_num_channels; i++) {
516 517
      openair0_cfg[UE->rf_map.card].rx_freq[UE->rf_map.chain+i] = UE->frame_parms.dl_CarrierFreq;
      openair0_cfg[UE->rf_map.card].tx_freq[UE->rf_map.chain+i] = UE->frame_parms.ul_CarrierFreq;
518
      openair0_cfg[UE->rf_map.card].autocal[UE->rf_map.chain+i] = 1;
519

520
      if (uplink_frequency_offset[CC_id][i] != 0) //
521
        openair0_cfg[UE->rf_map.card].duplex_mode = duplex_mode_FDD;
522
      else //FDD
523
        openair0_cfg[UE->rf_map.card].duplex_mode = duplex_mode_TDD;
524 525
    }

526 527
    sync_mode = pbch;
  } else if  (UE->UE_scan == 1) {
528
    current_band=0;
529

530 531
    for (i=0; i<openair0_cfg[UE->rf_map.card].rx_num_channels; i++) {
      downlink_frequency[UE->rf_map.card][UE->rf_map.chain+i] = bands_to_scan.band_info[CC_id].dl_min;
532
      uplink_frequency_offset[UE->rf_map.card][UE->rf_map.chain+i] =
533
        bands_to_scan.band_info[CC_id].ul_min-bands_to_scan.band_info[CC_id].dl_min;
534
      openair0_cfg[UE->rf_map.card].rx_freq[UE->rf_map.chain+i] = downlink_frequency[CC_id][i];
535
      openair0_cfg[UE->rf_map.card].tx_freq[UE->rf_map.chain+i] =
536
        downlink_frequency[CC_id][i]+uplink_frequency_offset[CC_id][i];
537
      openair0_cfg[UE->rf_map.card].rx_gain[UE->rf_map.chain+i] = UE->rx_total_gain_dB;
538 539
    }
  }
540

541 542 543 544 545
  /*
    while (sync_var<0)
      pthread_cond_wait(&sync_cond, &sync_mutex);
    pthread_mutex_unlock(&sync_mutex);
  */
546
  wait_sync("UE_thread_sync");
547
  printf("Started device, unlocked sync_mutex (UE_sync_thread)\n");
548

549
  while (oai_exit==0) {
550
    AssertFatal ( 0== pthread_mutex_lock(&UE->proc.mutex_synch), "");
551

552
    while (UE->proc.instance_cnt_synch < 0)
553
      // the thread waits here most of the time
554
      pthread_cond_wait( &UE->proc.cond_synch, &UE->proc.mutex_synch );
555

556
    AssertFatal ( 0== pthread_mutex_unlock(&UE->proc.mutex_synch), "");
557

558
    switch (sync_mode) {
559 560 561 562 563 564 565 566 567
      case pss:
        LOG_I(PHY,"[SCHED][UE] Scanning band %d (%d), freq %u\n",bands_to_scan.band_info[current_band].band, current_band,bands_to_scan.band_info[current_band].dl_min+current_offset);
        lte_sync_timefreq(UE,current_band,bands_to_scan.band_info[current_band].dl_min+current_offset);
        current_offset += 20000000; // increase by 20 MHz

        if (current_offset > bands_to_scan.band_info[current_band].dl_max-bands_to_scan.band_info[current_band].dl_min) {
          current_band++;
          current_offset=0;
        }
568

569 570 571 572
        if (current_band==bands_to_scan.nbands) {
          current_band=0;
          oai_exit=1;
        }
573

574 575 576 577 578 579
        for (i=0; i<openair0_cfg[UE->rf_map.card].rx_num_channels; i++) {
          downlink_frequency[UE->rf_map.card][UE->rf_map.chain+i] = bands_to_scan.band_info[current_band].dl_min+current_offset;
          uplink_frequency_offset[UE->rf_map.card][UE->rf_map.chain+i] = bands_to_scan.band_info[current_band].ul_min-bands_to_scan.band_info[0].dl_min + current_offset;
          openair0_cfg[UE->rf_map.card].rx_freq[UE->rf_map.chain+i] = downlink_frequency[CC_id][i];
          openair0_cfg[UE->rf_map.card].tx_freq[UE->rf_map.chain+i] = downlink_frequency[CC_id][i]+uplink_frequency_offset[CC_id][i];
          openair0_cfg[UE->rf_map.card].rx_gain[UE->rf_map.chain+i] = UE->rx_total_gain_dB;
580

581 582 583 584
          if (UE->UE_scan_carrier) {
            openair0_cfg[UE->rf_map.card].autocal[UE->rf_map.chain+i] = 1;
          }
        }
585

586
        break;
587

588 589 590 591
      case pbch:
        LOG_I(PHY, "[UE thread Synch] Running Initial Synch (mode %d)\n",UE->mode);

        if (initial_sync( UE, UE->mode ) == 0) {
frtabu's avatar
frtabu committed
592
          LOG_I( HW, "Got synch: hw_slot_offset %d, carrier off %d Hz, rxgain %d (DL %lu, UL %lu), UE_scan_carrier %d\n",
593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716
                 (UE->rx_offset<<1) / UE->frame_parms.samples_per_tti,
                 freq_offset,
                 UE->rx_total_gain_dB,
                 downlink_frequency[0][0]+freq_offset,
                 downlink_frequency[0][0]+uplink_frequency_offset[0][0]+freq_offset,
                 UE->UE_scan_carrier );

          // rerun with new cell parameters and frequency-offset
          for (i=0; i<openair0_cfg[UE->rf_map.card].rx_num_channels; i++) {
            openair0_cfg[UE->rf_map.card].rx_gain[UE->rf_map.chain+i] = UE->rx_total_gain_dB;//-USRP_GAIN_OFFSET;

            if (UE->UE_scan_carrier == 1) {
              if (freq_offset >= 0)
                openair0_cfg[UE->rf_map.card].rx_freq[UE->rf_map.chain+i] += abs(UE->common_vars.freq_offset);
              else
                openair0_cfg[UE->rf_map.card].rx_freq[UE->rf_map.chain+i] -= abs(UE->common_vars.freq_offset);

              openair0_cfg[UE->rf_map.card].tx_freq[UE->rf_map.chain+i] =
                openair0_cfg[UE->rf_map.card].rx_freq[UE->rf_map.chain+i]+uplink_frequency_offset[CC_id][i];
              downlink_frequency[CC_id][i] = openair0_cfg[CC_id].rx_freq[i];
              freq_offset=0;
            }
          }

          // reconfigure for potentially different bandwidth
          switch(UE->frame_parms.N_RB_DL) {
            case 6:
              openair0_cfg[UE->rf_map.card].sample_rate =1.92e6;
              openair0_cfg[UE->rf_map.card].rx_bw          =.96e6;
              openair0_cfg[UE->rf_map.card].tx_bw          =.96e6;
              //            openair0_cfg[0].rx_gain[0] -= 12;
              break;

            case 25:
              openair0_cfg[UE->rf_map.card].sample_rate =7.68e6;
              openair0_cfg[UE->rf_map.card].rx_bw          =2.5e6;
              openair0_cfg[UE->rf_map.card].tx_bw          =2.5e6;
              //            openair0_cfg[0].rx_gain[0] -= 6;
              break;

            case 50:
              openair0_cfg[UE->rf_map.card].sample_rate =15.36e6;
              openair0_cfg[UE->rf_map.card].rx_bw          =5.0e6;
              openair0_cfg[UE->rf_map.card].tx_bw          =5.0e6;
              //            openair0_cfg[0].rx_gain[0] -= 3;
              break;

            case 100:
              openair0_cfg[UE->rf_map.card].sample_rate=30.72e6;
              openair0_cfg[UE->rf_map.card].rx_bw=10.0e6;
              openair0_cfg[UE->rf_map.card].tx_bw=10.0e6;
              //            openair0_cfg[0].rx_gain[0] -= 0;
              break;
          }

          UE->rfdevice.trx_set_freq_func(&UE->rfdevice,&openair0_cfg[0],0);
          //UE->rfdevice.trx_set_gains_func(&openair0,&openair0_cfg[0]);
          //UE->rfdevice.trx_stop_func(&UE->rfdevice);
          sleep(1);
          init_frame_parms(&UE->frame_parms,1);

          /*if (UE->rfdevice.trx_start_func(&UE->rfdevice) != 0 ) {
            LOG_E(HW,"Could not start the device\n");
            oai_exit=1;
            }*/

          if (UE->UE_scan_carrier == 1) {
            UE->UE_scan_carrier = 0;
          } else {
            AssertFatal ( 0== pthread_mutex_lock(&UE->proc.mutex_synch), "");
            UE->is_synchronized = 1;
            AssertFatal ( 0== pthread_mutex_unlock(&UE->proc.mutex_synch), "");

            if( UE->mode == rx_dump_frame ) {
              FILE *fd;

              if ((UE->proc.proc_rxtx[0].frame_rx&1) == 0) {  // this guarantees SIB1 is present
                if ((fd = fopen("rxsig_frame0.dat","w")) != NULL) {
                  fwrite((void *)&UE->common_vars.rxdata[0][0],
                         sizeof(int32_t),
                         10*UE->frame_parms.samples_per_tti,
                         fd);
                  LOG_I(PHY,"Dummping Frame ... bye bye \n");
                  fclose(fd);
                  exit(0);
                } else {
                  LOG_E(PHY,"Cannot open file for writing\n");
                  exit(0);
                }
              } else {
                AssertFatal ( 0== pthread_mutex_lock(&UE->proc.mutex_synch), "");
                UE->is_synchronized = 0;
                AssertFatal ( 0== pthread_mutex_unlock(&UE->proc.mutex_synch), "");
              }
            }
          }
        } else {
          // initial sync failed
          // calculate new offset and try again
          if (UE->UE_scan_carrier == 1) {
            if (freq_offset >= 0)
              freq_offset += 100;

            freq_offset *= -1;

            if (abs(freq_offset) > 7500) {
              LOG_I( PHY, "[initial_sync] No cell synchronization found, abandoning\n" );
              FILE *fd;

              if ((fd = fopen("rxsig_frame0.dat","w"))!=NULL) {
                fwrite((void *)&UE->common_vars.rxdata[0][0],
                       sizeof(int32_t),
                       10*UE->frame_parms.samples_per_tti,
                       fd);
                LOG_I(PHY,"Dummping Frame ... bye bye \n");
                fclose(fd);
                exit(0);
              }

              AssertFatal(1==0,"No cell synchronization found, abandoning");
              return &UE_thread_synch_retval; // not reached
            }
          }

frtabu's avatar
frtabu committed
717
          LOG_I(PHY, "[initial_sync] trying carrier off %d Hz, rxgain %d (DL %lu, UL %lu)\n",
718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733
                freq_offset,
                UE->rx_total_gain_dB,
                downlink_frequency[0][0]+freq_offset,
                downlink_frequency[0][0]+uplink_frequency_offset[0][0]+freq_offset );

          for (i=0; i<openair0_cfg[UE->rf_map.card].rx_num_channels; i++) {
            openair0_cfg[UE->rf_map.card].rx_freq[UE->rf_map.chain+i] = downlink_frequency[CC_id][i]+freq_offset;
            openair0_cfg[UE->rf_map.card].tx_freq[UE->rf_map.chain+i] = downlink_frequency[CC_id][i]+uplink_frequency_offset[CC_id][i]+freq_offset;
            openair0_cfg[UE->rf_map.card].rx_gain[UE->rf_map.chain+i] = UE->rx_total_gain_dB;//-USRP_GAIN_OFFSET;

            if (UE->UE_scan_carrier==1)
              openair0_cfg[UE->rf_map.card].autocal[UE->rf_map.chain+i] = 1;
          }

          UE->rfdevice.trx_set_freq_func(&UE->rfdevice,&openair0_cfg[0],0);
        }// initial_sync=0
734

735
        break;
laurent's avatar
laurent committed
736

737 738 739
      case si:
      default:
        break;
740 741 742 743 744 745 746 747 748 749
    }

    AssertFatal ( 0== pthread_mutex_lock(&UE->proc.mutex_synch), "");
    // indicate readiness
    UE->proc.instance_cnt_synch--;
    AssertFatal ( 0== pthread_mutex_unlock(&UE->proc.mutex_synch), "");
    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_UE_THREAD_SYNCH, 0 );
  }  // while !oai_exit

  return &UE_thread_synch_retval;
750 751
}

752
/*!
753
 * \brief This is the UE thread for RX subframe n and TX subframe n+4.
754
 * This thread performs the phy_procedures_UE_RX() on every received slot.
laurent's avatar
laurent committed
755
 * then, if TX is enabled it performs TX for n+4.
756 757 758
 * \param arg is a pointer to a \ref PHY_VARS_UE structure.
 * \returns a pointer to an int. The storage is not on the heap and must not be freed.
 */
759 760
const char *get_connectionloss_errstr(int errcode)
{
761 762 763 764 765 766 767 768 769 770 771
  switch (errcode) {
    case CONNECTION_LOST:
      return "RRC Connection lost, returning to PRACH";

    case PHY_RESYNCH:
      return "RRC Connection lost, trying to resynch";

    case RESYNCH:
      return "return to PRACH and perform a contention-free access";
  };

772 773
  return "UNKNOWN RETURN CODE";
}
774

775 776
static void *UE_thread_rxn_txnp4(void *arg)
{
777 778 779 780 781 782 783 784 785 786 787 788
  static __thread int UE_thread_rxtx_retval;
  struct rx_tx_thread_data *rtd = arg;
  UE_rxtx_proc_t *proc = rtd->proc;
  PHY_VARS_UE    *UE   = rtd->UE;
  proc->subframe_rx=proc->sub_frame_start;
  char threadname[256];
  sprintf(threadname,"UE_%d_proc_%d", UE->Mod_id, proc->sub_frame_start);
  cpu_set_t cpuset;
  CPU_ZERO(&cpuset);

  if ( (proc->sub_frame_start+1)%RX_NB_TH == 0 && threads.one != -1 )
    CPU_SET(threads.one, &cpuset);
789

Thomas Schlichter's avatar
Thomas Schlichter committed
790
  if ( RX_NB_TH > 1 && (proc->sub_frame_start+1)%RX_NB_TH == 1 && threads.two != -1 )
791
    CPU_SET(threads.two, &cpuset);
792

Thomas Schlichter's avatar
Thomas Schlichter committed
793
  if ( RX_NB_TH > 2 && (proc->sub_frame_start+1)%RX_NB_TH == 2 && threads.three != -1 )
794
    CPU_SET(threads.three, &cpuset);
795

796
  //CPU_SET(threads.three, &cpuset);
797 798
  init_thread(900000,1000000, FIFO_PRIORITY-1, &cpuset,
              threadname);
799 800 801 802 803 804

  while (!oai_exit) {
    if (pthread_mutex_lock(&proc->mutex_rxtx) != 0) {
      LOG_E( PHY, "[SCHED][UE] error locking mutex for UE RXTX\n" );
      exit_fun("nothing to add");
    }
805

806 807 808 809 810
    while (proc->instance_cnt_rxtx < 0) {
      // most of the time, the thread is waiting here
      pthread_cond_wait( &proc->cond_rxtx, &proc->mutex_rxtx );
    }

811
    //printf("Processing sub frqme %d in %s\n", proc->subframe_rx, threadname);
812 813 814 815 816 817 818
    initRefTimes(t2);
    initRefTimes(t3);
    pickTime(current);
    updateTimes(proc->gotIQs, &t2, 10000, "Delay to wake up UE_Thread_Rx (case 2)");
    // Process Rx data for one sub-frame
    lte_subframe_t sf_type = subframe_select( &UE->frame_parms, proc->subframe_rx);

819 820 821
    if ((sf_type == SF_DL) ||
        (UE->frame_parms.frame_type == FDD) ||
        (sf_type == SF_S)) {
822
      if (UE->frame_parms.frame_type == TDD) {
823 824 825 826 827 828
        LOG_D(PHY, "%s,TDD%d,%s: calling UE_RX\n",
              threadname,
              UE->frame_parms.tdd_config,
              (sf_type==SF_DL? "SF_DL" :
               (sf_type==SF_UL? "SF_UL" :
                (sf_type==SF_S ? "SF_S"  : "UNKNOWN_SF_TYPE"))));
829
      } else {
830 831 832 833 834 835 836
        LOG_D(PHY, "%s,%s,%s: calling UE_RX\n",
              threadname,
              (UE->frame_parms.frame_type==FDD? "FDD":
               (UE->frame_parms.frame_type==TDD? "TDD":"UNKNOWN_DUPLEX_MODE")),
              (sf_type==SF_DL? "SF_DL" :
               (sf_type==SF_UL? "SF_UL" :
                (sf_type==SF_S ? "SF_S"  : "UNKNOWN_SF_TYPE"))));
837
      }
838

839
#ifdef UE_SLOT_PARALLELISATION
840
      phy_procedures_slot_parallelization_UE_RX( UE, proc, 0, 0, 1, UE->mode, no_relay, NULL );
841
#else
842
      phy_procedures_UE_RX(UE, proc, 0, 0, 1, UE->mode);
843
#endif
844
    }
hbilel's avatar
hbilel committed
845

gabrielC's avatar
gabrielC committed
846
#if UE_TIMING_TRACE
847
    start_meas(&UE->generic_stat);
gabrielC's avatar
gabrielC committed
848
#endif
849

850
    if (UE->mac_enabled==1) {
851
      int ret = ue_scheduler(UE->Mod_id,
852 853 854 855 856 857 858 859
                             proc->frame_rx,
                             proc->subframe_rx,
                             proc->frame_tx,
                             proc->subframe_tx,
                             subframe_select(&UE->frame_parms,proc->subframe_tx),
                             0,
                             0/*FIXME CC_id*/);

860
      if ( ret != CONNECTION_OK) {
861 862
        LOG_E( PHY, "[UE %"PRIu8"] Frame %"PRIu32", subframe %u %s\n",
               UE->Mod_id, proc->frame_rx, proc->subframe_tx,get_connectionloss_errstr(ret) );
863 864
      }
    }
865

gabrielC's avatar
gabrielC committed
866
#if UE_TIMING_TRACE
867
    stop_meas(&UE->generic_stat);
gabrielC's avatar
gabrielC committed
868
#endif
hbilel's avatar
hbilel committed
869

870 871 872
    // Prepare the future Tx data

    if ((subframe_select( &UE->frame_parms, proc->subframe_tx) == SF_UL) ||
873
        (UE->frame_parms.frame_type == FDD) )
874
      if (UE->mode != loop_through_memory)
875
        phy_procedures_UE_TX(UE,proc,0,0,UE->mode);
876 877

    if ((subframe_select( &UE->frame_parms, proc->subframe_tx) == SF_S) &&
878
        (UE->frame_parms.frame_type == TDD))
879
      if (UE->mode != loop_through_memory)
880
        phy_procedures_UE_S_TX(UE,0,0);
881

882 883
    updateTimes(current, &t3, 10000, "Delay to process sub-frame (case 3)");
    proc->instance_cnt_rxtx--;
884

885
    if ( IS_SOFTMODEM_BASICSIM || IS_SOFTMODEM_RFSIM ) {
886
      if (pthread_cond_signal(&proc->cond_rxtx) != 0) abort();
887
    }
888

889 890 891 892 893 894 895 896 897 898 899 900 901
    if (pthread_mutex_unlock(&proc->mutex_rxtx) != 0) {
      LOG_E( PHY, "[SCHED][UE] error unlocking mutex for UE RXTX\n" );
      exit_fun("noting to add");
    }
  }

  // thread finished
  free(arg);
  return &UE_thread_rxtx_retval;
}

unsigned int emulator_absSF;

902
void ue_stub_rx_handler(unsigned int num_bytes,
903
                        char *rx_buffer)
904
{
905 906
  PHY_VARS_UE *UE;
  UE = PHY_vars_UE_g[0][0];
907 908 909 910 911 912 913
  UE_tport_t *pdu = (UE_tport_t *)rx_buffer;
  SLSCH_t *slsch = (SLSCH_t *)&pdu->slsch;
  SLDCH_t *sldch = (SLDCH_t *)&pdu->sldch;

  switch (((UE_tport_header_t *)rx_buffer)->packet_type) {
    case TTI_SYNC:
      emulator_absSF = ((UE_tport_header_t *)rx_buffer)->absSF;
914
      wakeup_thread(&UE->timer_mutex,&UE->timer_cond,&UE->instance_cnt_timer,"timer_thread",100,1);
915
      break;
916

917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935
    case SLSCH:
      LOG_I(PHY,"Emulator SFN.SF %d.%d, Got SLSCH packet\n",emulator_absSF/10,emulator_absSF%10);
      LOG_I(PHY,"Received %d bytes on UE-UE link for SFN.SF %d.%d, sending SLSCH payload (%d bytes) to MAC\n",num_bytes,
            pdu->header.absSF/10,pdu->header.absSF%10,
            slsch->payload_length);
      printf("SLSCH:");

      for (int i=0; i<sizeof(SLSCH_t); i++) printf("%x ",((uint8_t *)slsch)[i]);

      printf("\n");
      ue_send_sl_sdu(0,
                     0,
                     pdu->header.absSF/10,
                     pdu->header.absSF%10,
                     pdu->payload,
                     slsch->payload_length,
                     0,
                     SL_DISCOVERY_FLAG_NO);
      break;
936

937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955
    case SLDCH:
      LOG_I(PHY,"Emulator SFN.SF %d.%d, Got SLDCH packet\n",emulator_absSF/10,emulator_absSF%10);
      LOG_I(PHY,"Received %d bytes on UE-UE link for SFN.SF %d.%d, sending SLDCH payload (%d bytes) to MAC\n",num_bytes,
            pdu->header.absSF/10,pdu->header.absSF%10,
            sldch->payload_length);
      printf("SLDCH:");

      for (int i=0; i<sizeof(SLDCH_t); i++) printf("%x ",((uint8_t *)sldch)[i]);

      printf("\n");
      ue_send_sl_sdu(0,
                     0,
                     pdu->header.absSF/10,
                     pdu->header.absSF%10,
                     sldch->payload,
                     sldch->payload_length,
                     0,
                     SL_DISCOVERY_FLAG_YES);
      break;
956 957 958 959 960 961 962 963 964 965 966 967
  }
}


/*!
 * \brief This is the UE thread for RX subframe n and TX subframe n+4.
 * This thread performs the phy_procedures_UE_RX() on every received slot.
 * then, if TX is enabled it performs TX for n+4.
 * \param arg is a pointer to a \ref PHY_VARS_UE structure.
 * \returns a pointer to an int. The storage is not on the heap and must not be freed.
 */

968 969
static void *UE_phy_stub_single_thread_rxn_txnp4(void *arg)
{
970 971 972 973
  thread_top_init("UE_phy_stub_thread_rxn_txnp4",1,870000L,1000000L,1000000L);
  // for multipule UE's L2-emulator
  //module_id_t Mod_id = 0;
  //int init_ra_UE = -1; // This counter is used to initiate the RA of each UE in different SFrames
974 975 976
  static __thread int UE_thread_rxtx_retval;
  struct rx_tx_thread_data *rtd = arg;

977
  if (rtd == NULL) {
978 979
    LOG_E( MAC, "[SCHED][UE] rx_tx_thread_data *rtd: NULL pointer\n" );
    exit_fun("nothing to add");
980
  }
981

982
  UE_rxtx_proc_t *proc = rtd->proc;
983 984 985 986 987
  // settings for nfapi-L2-emulator mode
  module_id_t ue_thread_id = rtd->ue_thread_id;
  uint16_t     ue_index = 0;
  uint16_t     ue_num = NB_UE_INST/NB_THREAD_INST+((NB_UE_INST%NB_THREAD_INST > ue_thread_id) ? 1 :0);
  module_id_t ue_Mod_id;
988
  PHY_VARS_UE    *UE = NULL;
989
  int ret;
990 991 992
  uint8_t   end_flag;
  proc = &PHY_vars_UE_g[0][0]->proc.proc_rxtx[0];
  phy_stub_ticking->num_single_thread[ue_thread_id] = -1;
993
  UE = rtd->UE;
994

995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007
  UL_INFO = (UL_IND_t *)malloc(sizeof(UL_IND_t));
  UL_INFO->rx_ind.rx_indication_body.rx_pdu_list = calloc(NB_UE_INST, sizeof(nfapi_rx_indication_pdu_t));
  UL_INFO->rx_ind.rx_indication_body.number_of_pdus = 0;
  UL_INFO->crc_ind.crc_indication_body.crc_pdu_list = calloc(NB_UE_INST, sizeof(nfapi_crc_indication_pdu_t));
  UL_INFO->crc_ind.crc_indication_body.number_of_crcs = 0;
  UL_INFO->harq_ind.harq_indication_body.harq_pdu_list = calloc(NB_UE_INST, sizeof(nfapi_harq_indication_pdu_t));
  UL_INFO->harq_ind.harq_indication_body.number_of_harqs = 0;
  UL_INFO->sr_ind.sr_indication_body.sr_pdu_list = calloc(NB_UE_INST, sizeof(nfapi_sr_indication_pdu_t));
  UL_INFO->sr_ind.sr_indication_body.number_of_srs = 0;
  UL_INFO->cqi_ind.cqi_indication_body.cqi_pdu_list =  calloc(NB_UE_INST, sizeof(nfapi_cqi_indication_pdu_t));
  UL_INFO->cqi_ind.cqi_indication_body.cqi_raw_pdu_list = calloc(NB_UE_INST, sizeof(nfapi_cqi_indication_raw_pdu_t));
  UL_INFO->cqi_ind.cqi_indication_body.number_of_cqis = 0;

1008
  if(ue_thread_id == 0) {
1009 1010 1011 1012 1013 1014 1015 1016 1017
    phy_stub_ticking->ticking_var = -1;
    proc->subframe_rx=proc->sub_frame_start;
    // Initializations for nfapi-L2-emulator mode
    dl_config_req = NULL;
    ul_config_req = NULL;
    hi_dci0_req        = NULL;
    tx_request_pdu_list = NULL;

    // waiting for all UE's threads set phy_stub_ticking->num_single_thread[ue_thread_id] = -1.
1018
    do {
1019
      end_flag = 1;
1020 1021 1022

      for(uint16_t i = 0; i< NB_THREAD_INST; i++) {
        if(phy_stub_ticking->num_single_thread[i] == 0) {
1023 1024 1025
          end_flag = 0;
        }
      }
1026
    } while(end_flag == 0);
1027

1028 1029
    sync_var=0;
  }
1030 1031 1032 1033 1034

  //PANOS: CAREFUL HERE!
  wait_sync("UE_phy_stub_single_thread_rxn_txnp4");

  while (!oai_exit) {
1035 1036 1037 1038
    if(ue_thread_id == 0) {
      if (pthread_mutex_lock(&phy_stub_ticking->mutex_ticking) != 0) {
        LOG_E( MAC, "[SCHED][UE] error locking mutex for UE RXTX\n" );
        exit_fun("nothing to add");
1039
      }
1040

1041 1042 1043 1044 1045 1046
      while (phy_stub_ticking->ticking_var < 0) {
        // most of the time, the thread is waiting here
        //pthread_cond_wait( &proc->cond_rxtx, &proc->mutex_rxtx )
        LOG_D(MAC,"Waiting for ticking_var\n");
        pthread_cond_wait( &phy_stub_ticking->cond_ticking, &phy_stub_ticking->mutex_ticking);
      }
1047

1048
      phy_stub_ticking->ticking_var--;
1049

1050 1051 1052 1053
      if (pthread_mutex_unlock(&phy_stub_ticking->mutex_ticking) != 0) {
        LOG_E( MAC, "[SCHED][UE] error unlocking mutex for UE RXn_TXnp4\n" );
        exit_fun("nothing to add");
      }
1054

1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069
      proc->subframe_rx=timer_subframe;
      proc->frame_rx = timer_frame;
      // FDD and TDD tx timing settings.
      // XXX:It is the result of timing adjustment in debug.
      // It is necessary to investigate why this will work in the future.
      proc->subframe_tx=(timer_subframe+sf_ahead)%10;
      proc->frame_tx = proc->frame_rx + (proc->subframe_rx>(9-sf_ahead)?1:0);
      //oai_subframe_ind(proc->frame_rx, proc->subframe_rx);

      if (UE != NULL) {
        if (UE->frame_parms.frame_type == FDD) {
          oai_subframe_ind(proc->frame_rx, proc->subframe_rx);
        } else {
          oai_subframe_ind(proc->frame_tx, proc->subframe_tx);
        }
1070
      } else {
1071 1072
        // Default will be FDD
        oai_subframe_ind(proc->frame_rx, proc->subframe_rx);
1073 1074
      }

1075 1076 1077 1078 1079 1080 1081 1082 1083 1084
      //Guessing that the next 4 lines are not needed for the phy_stub mode.
      /*initRefTimes(t2);
        initRefTimes(t3);
        pickTime(current);
        updateTimes(proc->gotIQs, &t2, 10000, "Delay to wake up UE_Thread_Rx (case 2)");*/

      if (pthread_mutex_lock(&phy_stub_ticking->mutex_single_thread) != 0) {
        LOG_E( MAC, "[SCHED][UE] error locking mutex for ue_thread_id %d (mutex_single_thread)\n",ue_thread_id);
        exit_fun("nothing to add");
      }
1085

1086 1087
      memset(&phy_stub_ticking->num_single_thread[0],0,sizeof(int)*NB_THREAD_INST);
      pthread_cond_broadcast(&phy_stub_ticking->cond_single_thread);
1088

1089 1090 1091
      if (pthread_mutex_unlock(&phy_stub_ticking->mutex_single_thread) != 0) {
        LOG_E( MAC, "[SCHED][UE] error unlocking mutex for ue_thread_id %d (mutex_single_thread)\n",ue_thread_id);
        exit_fun("nothing to add");
1092
      }
1093 1094 1095 1096
    } else {
      if (pthread_mutex_lock(&phy_stub_ticking->mutex_single_thread) != 0) {
        LOG_E( MAC, "[SCHED][UE] error locking mutex for ue_thread_id %d (mutex_single_thread)\n",ue_thread_id);
        exit_fun("nothing to add");
1097 1098
      }

1099 1100 1101 1102 1103
      while (phy_stub_ticking->num_single_thread[ue_thread_id] < 0) {
        // most of the time, the thread is waiting here
        LOG_D(MAC,"Waiting for single_thread (ue_thread_id %d)\n",ue_thread_id);
        pthread_cond_wait( &phy_stub_ticking->cond_single_thread, &phy_stub_ticking->mutex_single_thread);
      }
1104

1105 1106 1107 1108
      if (pthread_mutex_unlock(&phy_stub_ticking->mutex_single_thread) != 0) {
        LOG_E( MAC, "[SCHED][UE] error unlocking mutex for ue_thread_id %d (mutex_single_thread)\n",ue_thread_id);
        exit_fun("nothing to add");
      }
1109
    }
1110

1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134
    if (dl_config_req && tx_request_pdu_list) {
      nfapi_dl_config_request_body_t* dl_config_req_body = &dl_config_req->dl_config_request_body;
      for (int i = 0; i < dl_config_req_body->number_pdu; ++i) {
        nfapi_dl_config_request_pdu_t* pdu = &dl_config_req_body->dl_config_pdu_list[i];
        if (pdu->pdu_type ==  NFAPI_DL_CONFIG_DCI_DL_PDU_TYPE) {
          i += 1;
          AssertFatal(i < dl_config_req->dl_config_request_body.number_pdu,
                      "Need PDU following DCI at index %d, but not found\n",
                      i);
          nfapi_dl_config_request_pdu_t *dlsch = &dl_config_req_body->dl_config_pdu_list[i];
          if (dlsch->pdu_type != NFAPI_DL_CONFIG_DLSCH_PDU_TYPE) {
            LOG_E(MAC, "expected DLSCH PDU at index %d\n", i);
            continue;
          }
          dl_config_req_UE_MAC_dci(NFAPI_SFNSF2SFN(dl_config_req->sfn_sf),
                                   NFAPI_SFNSF2SF(dl_config_req->sfn_sf),
                                   pdu,
                                   dlsch,
                                   ue_num);
        } else if (pdu->pdu_type == NFAPI_DL_CONFIG_BCH_PDU_TYPE) {
          dl_config_req_UE_MAC_bch(NFAPI_SFNSF2SFN(dl_config_req->sfn_sf),
                                   NFAPI_SFNSF2SF(dl_config_req->sfn_sf),
                                   pdu,
                                   ue_num);
Javier Morgade's avatar
Javier Morgade committed
1135 1136 1137 1138 1139
        } else if (pdu->pdu_type == NFAPI_DL_CONFIG_MCH_PDU_TYPE) {
          dl_config_req_UE_MAC_mch(NFAPI_SFNSF2SFN(dl_config_req->sfn_sf),
                                   NFAPI_SFNSF2SF(dl_config_req->sfn_sf),
                                   pdu,
                                   ue_num);
1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154
        }
      }
    }

    if (hi_dci0_req) {
      nfapi_hi_dci0_request_body_t *hi_dci0_body = &hi_dci0_req->hi_dci0_request_body;
      for (int i = 0; i < hi_dci0_body->number_of_dci + hi_dci0_body->number_of_hi; i++) {
        nfapi_hi_dci0_request_pdu_t* pdu = &hi_dci0_body->hi_dci0_pdu_list[i];
        hi_dci0_req_UE_MAC(NFAPI_SFNSF2SFN(hi_dci0_req->sfn_sf),
                           NFAPI_SFNSF2SF(hi_dci0_req->sfn_sf),
                           pdu,
                           ue_num);
      }
    }

1155 1156
    //for (Mod_id=0; Mod_id<NB_UE_INST; Mod_id++) {
    for (ue_index=0; ue_index < ue_num; ue_index++) {
1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179
      ue_Mod_id = ue_thread_id + NB_THREAD_INST*ue_index;
      UE = PHY_vars_UE_g[ue_Mod_id][0];
      //LOG_D(MAC, "UE_phy_stub_single_thread_rxn_txnp4, NB_UE_INST:%d, Mod_id:%d \n", NB_UE_INST, Mod_id);
      //UE = PHY_vars_UE_g[Mod_id][0];
      lte_subframe_t sf_type = subframe_select( &UE->frame_parms, proc->subframe_rx);

      if ((sf_type == SF_DL) ||
          (UE->frame_parms.frame_type == FDD) ||
          (sf_type == SF_S)) {
        if (UE->frame_parms.frame_type == TDD) {
          LOG_D(PHY, "TDD%d,%s: calling UE_RX\n",
                UE->frame_parms.tdd_config,
                (sf_type==SF_DL? "SF_DL" :
                 (sf_type==SF_UL? "SF_UL" :
                  (sf_type==SF_S ? "SF_S"  : "UNKNOWN_SF_TYPE"))));
        } else {
          LOG_D(PHY, "%s,%s: calling UE_RX\n",
                (UE->frame_parms.frame_type==FDD? "FDD":
                 (UE->frame_parms.frame_type==TDD? "TDD":"UNKNOWN_DUPLEX_MODE")),
                (sf_type==SF_DL? "SF_DL" :
                 (sf_type==SF_UL? "SF_UL" :
                  (sf_type==SF_S ? "SF_S"  : "UNKNOWN_SF_TYPE"))));
        }
1180

1181
        phy_procedures_UE_SL_RX(UE,proc);
1182

frtabu's avatar
frtabu committed
1183
        if(NFAPI_MODE!=NFAPI_UE_STUB_PNF)
1184
          phy_procedures_UE_SL_TX(UE,proc);
1185 1186 1187
      }

#if UE_TIMING_TRACE
1188
      start_meas(&UE->generic_stat);
1189
#endif
1190

1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204
      if (UE->mac_enabled==1) {
        ret = ue_scheduler(ue_Mod_id,
                           proc->frame_rx,
                           proc->subframe_rx,
                           proc->frame_tx,
                           proc->subframe_tx,
                           subframe_select(&UE->frame_parms,proc->subframe_tx),
                           0,
                           0/*FIXME CC_id*/);

        if ( ret != CONNECTION_OK) {
          LOG_E( PHY, "[UE %"PRIu8"] Frame %"PRIu32", subframe %u %s\n",
                 UE->Mod_id, proc->frame_rx, proc->subframe_tx,get_connectionloss_errstr(ret) );
        }
1205
      }
1206

1207
#if UE_TIMING_TRACE
1208
      stop_meas(&UE->generic_stat);
1209 1210
#endif

1211 1212 1213 1214 1215 1216 1217 1218 1219 1220
      // Prepare the future Tx data

      if ((subframe_select( &UE->frame_parms, proc->subframe_tx) == SF_UL) ||
          (UE->frame_parms.frame_type == FDD) )
        if (UE->mode != loop_through_memory) {
          // We make the start of RA between consecutive UEs differ by 20 frames
          //if ((UE_mac_inst[Mod_id].UE_mode[0] == PRACH  && Mod_id == 0) || (UE_mac_inst[Mod_id].UE_mode[0] == PRACH && Mod_id>0 && proc->frame_rx >= UE_mac_inst[Mod_id-1].ra_frame + 20) ) {
          if (UE_mac_inst[ue_Mod_id].UE_mode[0] == PRACH  && ue_Mod_id == next_Mod_id) {
            next_ra_frame++;

Robert Schmidt's avatar
Robert Schmidt committed
1221
            if(next_ra_frame > 500) {
1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237
              // check if we have PRACH opportunity
              if (is_prach_subframe(&UE->frame_parms,proc->frame_tx, proc->subframe_tx) &&  UE_mac_inst[ue_Mod_id].SI_Decoded == 1) {
                // The one working strangely...
                //if (is_prach_subframe(&UE->frame_parms,proc->frame_tx, proc->subframe_tx && Mod_id == (module_id_t) init_ra_UE) ) {
                PRACH_RESOURCES_t *prach_resources = ue_get_rach(ue_Mod_id, 0, proc->frame_tx, 0, proc->subframe_tx);

                if(prach_resources!=NULL ) {
                  UE_mac_inst[ue_Mod_id].ra_frame = proc->frame_rx;
                  LOG_D(MAC, "UE_phy_stub_thread_rxn_txnp4 before RACH, Mod_id: %d frame %d subframe %d\n", ue_Mod_id,proc->frame_tx, proc->subframe_tx);
                  fill_rach_indication_UE_MAC(ue_Mod_id, proc->frame_tx,proc->subframe_tx, UL_INFO, prach_resources->ra_PreambleIndex, prach_resources->ra_RNTI);
                  Msg1_transmitted(ue_Mod_id, 0, proc->frame_tx, 0);
                  UE_mac_inst[ue_Mod_id].UE_mode[0] = RA_RESPONSE;
                  next_Mod_id = ue_Mod_id + 1;
                  //next_ra_frame = (proc->frame_rx + 20)%1000;
                  next_ra_frame = 0;
                }
1238

1239 1240 1241 1242
                //ue_prach_procedures(ue,proc,eNB_id,abstraction_flag,mode);
              }
            }
          } // mode is PRACH
1243

1244 1245 1246 1247 1248
          // Substitute call to phy_procedures Tx with call to phy_stub functions in order to trigger
          // UE Tx procedures directly at the MAC layer, based on the received ul_config requests from the vnf (eNB).
          // Generate UL_indications which correspond to UL traffic.
          if(ul_config_req!=NULL) { //&& UE_mac_inst[Mod_id].ul_config_req->ul_config_request_body.ul_config_pdu_list != NULL){
            ul_config_req_UE_MAC(ul_config_req, timer_frame, timer_subframe, ue_Mod_id);
1249
          }
1250
        }
1251

1252
      phy_procedures_UE_SL_RX(UE,proc);
1253 1254
    } //for (Mod_id=0; Mod_id<NB_UE_INST; Mod_id++)

1255 1256 1257
    phy_stub_ticking->num_single_thread[ue_thread_id] = -1;

    // waiting for all UE's threads set phy_stub_ticking->num_single_thread[ue_thread_id] = -1.
1258 1259
    if(ue_thread_id == 0) {
      do {
1260
        end_flag = 1;
1261 1262 1263 1264

        for(uint16_t i = 0; i< NB_THREAD_INST; i++) {
          if(phy_stub_ticking->num_single_thread[i] == 0) {
            end_flag = 0;
1265 1266
          }
        }
1267 1268 1269 1270 1271 1272 1273 1274 1275
      } while(end_flag == 0);

      if (UL_INFO->crc_ind.crc_indication_body.number_of_crcs>0) {
        //LOG_D(PHY,"UL_info->crc_ind.crc_indication_body.number_of_crcs:%d CRC_IND:SFN/SF:%d\n", UL_info->crc_ind.crc_indication_body.number_of_crcs, NFAPI_SFNSF2DEC(UL_info->crc_ind.sfn_sf));
        //LOG_I(MAC, "ul_config_req_UE_MAC 2.2, SFN/SF of PNF counter:%d.%d, number_of_crcs: %d \n", timer_frame, timer_subframe, UL_INFO->crc_ind.crc_indication_body.number_of_crcs);
        oai_nfapi_crc_indication(&UL_INFO->crc_ind);
        //LOG_I(MAC, "ul_config_req_UE_MAC 2.21 \n");
        UL_INFO->crc_ind.crc_indication_body.number_of_crcs = 0;
      }
1276

1277 1278 1279 1280
      if (UL_INFO->rx_ind.rx_indication_body.number_of_pdus>0) {
        //LOG_D(PHY,"UL_info->rx_ind.number_of_pdus:%d RX_IND:SFN/SF:%d\n", UL_info->rx_ind.rx_indication_body.number_of_pdus, NFAPI_SFNSF2DEC(UL_info->rx_ind.sfn_sf));
        //LOG_I(MAC, "ul_config_req_UE_MAC 2.3, SFN/SF of PNF counter:%d.%d, number_of_pdus: %d \n", timer_frame, timer_subframe, UL_INFO->rx_ind.rx_indication_body.number_of_pdus);
        oai_nfapi_rx_ind(&UL_INFO->rx_ind);
1281

1282 1283 1284
        for(uint8_t num_pdu = 0; num_pdu < UL_INFO->rx_ind.rx_indication_body.number_of_pdus; num_pdu++) {
          free(UL_INFO->rx_ind.rx_indication_body.rx_pdu_list[num_pdu].data);
        }
1285

1286 1287
        //LOG_I(MAC, "ul_config_req_UE_MAC 2.31 \n");
        UL_INFO->rx_ind.rx_indication_body.number_of_pdus = 0;
1288 1289
      }

1290 1291 1292 1293 1294
      if (UL_INFO->cqi_ind.cqi_indication_body.number_of_cqis > 0) {
        oai_nfapi_cqi_indication(&UL_INFO->cqi_ind);
        UL_INFO->cqi_ind.cqi_indication_body.number_of_cqis = 0;
      }

1295 1296 1297 1298 1299
      if(UL_INFO->harq_ind.harq_indication_body.number_of_harqs>0) {
        //LOG_D(MAC, "ul_config_req_UE_MAC 2.4, SFN/SF of PNF counter:%d.%d, number_of_harqs: %d \n", timer_frame, timer_subframe, UL_INFO->harq_ind.harq_indication_body.number_of_harqs);
        oai_nfapi_harq_indication(&UL_INFO->harq_ind);
        //LOG_I(MAC, "ul_config_req_UE_MAC 2.41 \n");
        UL_INFO->harq_ind.harq_indication_body.number_of_harqs =0;
1300
      }
1301 1302 1303 1304 1305 1306

      if(UL_INFO->sr_ind.sr_indication_body.number_of_srs>0) {
        //LOG_I(MAC, "ul_config_req_UE_MAC 2.5, SFN/SF of PNF counter:%d.%d, number_of_srs: %d \n", timer_frame, timer_subframe, UL_INFO->sr_ind.sr_indication_body.number_of_srs);
        oai_nfapi_sr_indication(&UL_INFO->sr_ind);
        //LOG_I(MAC, "ul_config_req_UE_MAC 2.51 \n");
        UL_INFO->sr_ind.sr_indication_body.number_of_srs = 0;
1307 1308 1309
      }

      // De-allocate memory of nfapi requests copies before next subframe round
1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322
      if(dl_config_req!=NULL) {
        if(dl_config_req->vendor_extension!=NULL) {
          free(dl_config_req->vendor_extension);
          dl_config_req->vendor_extension = NULL;
        }

        if(dl_config_req->dl_config_request_body.dl_config_pdu_list!=NULL) {
          free(dl_config_req->dl_config_request_body.dl_config_pdu_list);
          dl_config_req->dl_config_request_body.dl_config_pdu_list = NULL;
        }

        free(dl_config_req);
        dl_config_req = NULL;
1323 1324
      }

1325
      if(tx_request_pdu_list!=NULL) {
1326 1327 1328 1329 1330 1331 1332
        for (int i = 0; i < tx_req_num_elems; i++) {
          for (int j = 0; j < tx_request_pdu_list[i].num_segments; j++) {
            free(tx_request_pdu_list[i].segments[j].segment_data);
            tx_request_pdu_list[i].segments[j].segment_data = NULL;
          }
        }
        tx_req_num_elems = 0;
1333 1334
        free(tx_request_pdu_list);
        tx_request_pdu_list = NULL;
1335 1336
      }

1337 1338 1339 1340 1341
      if(ul_config_req!=NULL) {
        if(ul_config_req->ul_config_request_body.ul_config_pdu_list != NULL) {
          free(ul_config_req->ul_config_request_body.ul_config_pdu_list);
          ul_config_req->ul_config_request_body.ul_config_pdu_list = NULL;
        }
1342

1343 1344
        free(ul_config_req);
        ul_config_req = NULL;
1345 1346
      }

1347 1348 1349 1350 1351
      if(hi_dci0_req!=NULL) {
        if(hi_dci0_req->hi_dci0_request_body.hi_dci0_pdu_list!=NULL) {
          free(hi_dci0_req->hi_dci0_request_body.hi_dci0_pdu_list);
          hi_dci0_req->hi_dci0_request_body.hi_dci0_pdu_list = NULL;
        }
1352

1353 1354 1355 1356
        free(hi_dci0_req);
        hi_dci0_req = NULL;
      }
    }
1357
  }
1358

1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374
  // Free UL_INFO messages
  free(UL_INFO->cqi_ind.cqi_indication_body.cqi_raw_pdu_list);
  UL_INFO->cqi_ind.cqi_indication_body.cqi_raw_pdu_list = NULL;
  free(UL_INFO->cqi_ind.cqi_indication_body.cqi_pdu_list);
  UL_INFO->cqi_ind.cqi_indication_body.cqi_pdu_list = NULL;
  free(UL_INFO->sr_ind.sr_indication_body.sr_pdu_list);
  UL_INFO->sr_ind.sr_indication_body.sr_pdu_list = NULL;
  free(UL_INFO->harq_ind.harq_indication_body.harq_pdu_list);
  UL_INFO->harq_ind.harq_indication_body.harq_pdu_list = NULL;
  free(UL_INFO->crc_ind.crc_indication_body.crc_pdu_list);
  UL_INFO->crc_ind.crc_indication_body.crc_pdu_list = NULL;
  free(UL_INFO->rx_ind.rx_indication_body.rx_pdu_list);
  UL_INFO->rx_ind.rx_indication_body.rx_pdu_list = NULL;
  free(UL_INFO);
  UL_INFO = NULL;

1375 1376 1377
  // thread finished
  free(arg);
  return &UE_thread_rxtx_retval;
Florian Kaltenberger's avatar
 
Florian Kaltenberger committed
1378
}
1379

1380 1381 1382 1383 1384 1385 1386 1387 1388

/*!
 * \brief This is the UE thread for RX subframe n and TX subframe n+4.
 * This thread performs the phy_procedures_UE_RX() on every received slot.
 * then, if TX is enabled it performs TX for n+4.
 * \param arg is a pointer to a \ref PHY_VARS_UE structure.
 * \returns a pointer to an int. The storage is not on the heap and must not be freed.
 */

1389 1390
static void *UE_phy_stub_thread_rxn_txnp4(void *arg)
{
1391 1392
  thread_top_init("UE_phy_stub_thread_rxn_txnp4",1,870000L,1000000L,1000000L);
  module_id_t Mod_id = 0;
1393 1394 1395 1396 1397 1398
  static __thread int UE_thread_rxtx_retval;
  struct rx_tx_thread_data *rtd = arg;
  UE_rxtx_proc_t *proc = rtd->proc;
  PHY_VARS_UE    *UE   = rtd->UE;
  phy_stub_ticking->ticking_var = -1;
  proc->subframe_rx=proc->sub_frame_start;
1399
  // CAREFUL HERE!
1400 1401 1402 1403 1404 1405 1406
  wait_sync("UE_phy_stub_thread_rxn_txnp4");

  while (!oai_exit) {
    if (pthread_mutex_lock(&phy_stub_ticking->mutex_ticking) != 0) {
      LOG_E( MAC, "[SCHED][UE] error locking mutex for UE RXTX\n" );
      exit_fun("nothing to add");
    }
1407

1408 1409 1410 1411 1412 1413
    while (phy_stub_ticking->ticking_var < 0) {
      // most of the time, the thread is waiting here
      //pthread_cond_wait( &proc->cond_rxtx, &proc->mutex_rxtx )
      LOG_D(MAC,"Waiting for ticking_var\n");
      pthread_cond_wait( &phy_stub_ticking->cond_ticking, &phy_stub_ticking->mutex_ticking);
    }
1414

1415
    phy_stub_ticking->ticking_var--;
1416

1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428
    if (pthread_mutex_unlock(&phy_stub_ticking->mutex_ticking) != 0) {
      LOG_E( MAC, "[SCHED][UE] error unlocking mutex for UE RXn_TXnp4\n" );
      exit_fun("nothing to add");
    }

    proc->subframe_rx=timer_subframe;
    proc->frame_rx = timer_frame;
    proc->subframe_tx=(timer_subframe+4)%10;
    proc->frame_tx = proc->frame_rx + (proc->subframe_rx>5?1:0);
    // Process Rx data for one sub-frame
    lte_subframe_t sf_type = subframe_select( &UE->frame_parms, proc->subframe_rx);

1429 1430 1431
    if ((sf_type == SF_DL) ||
        (UE->frame_parms.frame_type == FDD) ||
        (sf_type == SF_S)) {
1432
      if (UE->frame_parms.frame_type == TDD) {
1433 1434 1435 1436 1437
        LOG_D(PHY, "TDD%d,%s: calling UE_RX\n",
              UE->frame_parms.tdd_config,
              (sf_type==SF_DL? "SF_DL" :
               (sf_type==SF_UL? "SF_UL" :
                (sf_type==SF_S ? "SF_S"  : "UNKNOWN_SF_TYPE"))));
1438
      } else {
1439 1440 1441 1442 1443 1444
        LOG_D(PHY, "%s,%s: calling UE_RX\n",
              (UE->frame_parms.frame_type==FDD? "FDD":
               (UE->frame_parms.frame_type==TDD? "TDD":"UNKNOWN_DUPLEX_MODE")),
              (sf_type==SF_DL? "SF_DL" :
               (sf_type==SF_UL? "SF_UL" :
                (sf_type==SF_S ? "SF_S"  : "UNKNOWN_SF_TYPE"))));
1445 1446 1447
      }

      phy_procedures_UE_SL_RX(UE,proc);
1448
      oai_subframe_ind(timer_frame, timer_subframe);
1449 1450

      if(dl_config_req!= NULL) {
1451 1452
        AssertFatal(0, "dl_config_req_UE_MAC() not handled\n");
        //dl_config_req_UE_MAC(dl_config_req, Mod_id);
1453
      }
1454

1455
      //if(UE_mac_inst[Mod_id].hi_dci0_req!= NULL){
1456
      if (hi_dci0_req!=NULL && hi_dci0_req->hi_dci0_request_body.hi_dci0_pdu_list!=NULL) {
1457 1458
        AssertFatal(0, "hi_dci0_req_UE_MAC() not handled\n");
        //hi_dci0_req_UE_MAC(hi_dci0_req, Mod_id);
1459 1460 1461 1462 1463 1464 1465 1466 1467
        //if(UE_mac_inst[Mod_id].hi_dci0_req->hi_dci0_request_body.hi_dci0_pdu_list!=NULL){
        free(hi_dci0_req->hi_dci0_request_body.hi_dci0_pdu_list);
        hi_dci0_req->hi_dci0_request_body.hi_dci0_pdu_list = NULL;
        //}
        free(hi_dci0_req);
        hi_dci0_req = NULL;
      } else if(hi_dci0_req!=NULL) {
        free(hi_dci0_req);
        hi_dci0_req = NULL;
1468 1469
      }

frtabu's avatar
frtabu committed
1470
      if (NFAPI_MODE!=NFAPI_UE_STUB_PNF)
1471 1472 1473 1474 1475 1476 1477
        phy_procedures_UE_SL_TX(UE,proc);
    }

#if UE_TIMING_TRACE
    start_meas(&UE->generic_stat);
#endif

1478
    if (UE->mac_enabled==1) {
1479
      int ret = ue_scheduler(UE->Mod_id,
1480 1481 1482 1483 1484 1485 1486 1487
                             proc->frame_rx,
                             proc->subframe_rx,
                             proc->frame_tx,
                             proc->subframe_tx,
                             subframe_select(&UE->frame_parms,proc->subframe_tx),
                             0,
                             0);

1488
      if (ret != CONNECTION_OK)
1489 1490
        LOG_E( PHY, "[UE %"PRIu8"] Frame %"PRIu32", subframe %u %s\n",
               UE->Mod_id, proc->frame_rx, proc->subframe_tx,get_connectionloss_errstr(ret) );
1491
    }
1492

1493 1494 1495 1496 1497 1498 1499
#if UE_TIMING_TRACE
    stop_meas(&UE->generic_stat);
#endif

    // Prepare the future Tx data

    if ((subframe_select( &UE->frame_parms, proc->subframe_tx) == SF_UL) ||
1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534
        (UE->frame_parms.frame_type == FDD) )
      if (UE->mode != loop_through_memory) {
        if ((UE_mac_inst[Mod_id].UE_mode[0] == PRACH) ) {
          // check if we have PRACH opportunity
          if (is_prach_subframe(&UE->frame_parms,proc->frame_tx, proc->subframe_tx)) {
            PRACH_RESOURCES_t *prach_resources = ue_get_rach(Mod_id, 0, proc->frame_tx, 0, proc->subframe_tx);

            if(prach_resources!=NULL) {
              fill_rach_indication_UE_MAC(Mod_id, proc->frame_tx,proc->subframe_tx, UL_INFO, prach_resources->ra_PreambleIndex, prach_resources->ra_RNTI);
              Msg1_transmitted(Mod_id, 0, proc->frame_tx, 0);
              UE_mac_inst[Mod_id].UE_mode[0] = RA_RESPONSE;
            }

            //ue_prach_procedures(ue,proc,eNB_id,abstraction_flag,mode);
          }
        } // mode is PRACH

        // Substitute call to phy_procedures Tx with call to phy_stub functions in order to trigger
        // UE Tx procedures directly at the MAC layer, based on the received ul_config requests from the vnf (eNB).
        // Generate UL_indications which correspond to UL traffic.
        if(ul_config_req!= NULL && ul_config_req->ul_config_request_body.ul_config_pdu_list != NULL) {
          //LOG_I(MAC, "UE_phy_stub_thread_rxn_txnp4 ul_config_req is not NULL \n");
          ul_config_req_UE_MAC(ul_config_req, timer_frame, timer_subframe, Mod_id);

          if(ul_config_req->ul_config_request_body.ul_config_pdu_list != NULL) {
            free(ul_config_req->ul_config_request_body.ul_config_pdu_list);
            ul_config_req->ul_config_request_body.ul_config_pdu_list = NULL;
          }

          free(ul_config_req);
          ul_config_req = NULL;
        } else if(ul_config_req!=NULL) {
          free(ul_config_req);
          ul_config_req = NULL;
        }
1535 1536 1537 1538
      }

    phy_procedures_UE_SL_RX(UE,proc);
  }
1539

1540 1541 1542 1543 1544 1545
  // thread finished
  free(arg);
  return &UE_thread_rxtx_retval;
}


1546 1547 1548
/*!
 * \brief This is the main UE thread.
 * This thread controls the other three UE threads:
1549 1550
 * - UE_thread_rxn_txnp4 (even subframes)
 * - UE_thread_rxn_txnp4 (odd subframes)
1551 1552 1553 1554
 * - UE_thread_synch
 * \param arg unused
 * \returns a pointer to an int. The storage is not on the heap and must not be freed.
 */
1555 1556 1557 1558 1559 1560 1561 1562 1563 1564
void write_dummy(PHY_VARS_UE *UE,  openair0_timestamp timestamp) {
  // we have to write to tell explicitly to the eNB, else it will wait for us forever
  // we write the next subframe (always write in future of what we received)
  //
  struct complex16 v= {0};
  void *samplesVoid[UE->frame_parms.nb_antennas_tx];
  
  for ( int i=0; i < UE->frame_parms.nb_antennas_tx; i++)
    samplesVoid[i]=(void *)&v;
  
1565 1566 1567 1568 1569 1570
  AssertFatal( 1 == UE->rfdevice.trx_write_func(&UE->rfdevice,
						timestamp+2*UE->frame_parms.samples_per_tti,
						samplesVoid, 
						1,
						UE->frame_parms.nb_antennas_tx,
						1),"");
1571
}
1572

1573 1574
void *UE_thread(void *arg)
{
1575 1576 1577 1578
  PHY_VARS_UE *UE = (PHY_VARS_UE *) arg;
  //  int tx_enabled = 0;
  int dummy_rx[UE->frame_parms.nb_antennas_rx][UE->frame_parms.samples_per_tti] __attribute__((aligned(32)));
  openair0_timestamp timestamp,timestamp1;
1579
  void *rxp[NB_ANTENNAS_RX], *txp[NB_ANTENNAS_TX];
1580 1581 1582 1583
  int start_rx_stream = 0;
  int i;
  int th_id;
  static uint8_t thread_idx = 0;
Cedric Roux's avatar
Cedric Roux committed
1584
  int ret;
1585 1586
  cpu_set_t cpuset;
  CPU_ZERO(&cpuset);
Florian Kaltenberger's avatar
Florian Kaltenberger committed
1587 1588
  if ( threads.main != -1 )
    CPU_SET(threads.main, &cpuset);
1589
  init_thread(100000, 500000, FIFO_PRIORITY, &cpuset, "UHD Threads");
1590

1591 1592 1593 1594 1595
  /*
  while (sync_var<0)
    pthread_cond_wait(&sync_cond, &sync_mutex);
  pthread_mutex_unlock(&sync_mutex);
  */
Raymond Knopp's avatar
Raymond Knopp committed
1596
  wait_sync("UE thread");
1597
#ifdef NAS_UE
1598
  MessageDef *message_p;
1599
  message_p = itti_alloc_new_message(TASK_NAS_UE, 0, INITIALIZE_MESSAGE);
1600
  itti_send_msg_to_task (TASK_NAS_UE, UE->Mod_id + NB_eNB_INST, message_p);
1601
#endif
1602 1603
  int sub_frame=-1;
  //int cumulated_shift=0;
1604

1605 1606 1607 1608
  if (UE->rfdevice.trx_start_func(&UE->rfdevice) != 0 ) {
    LOG_E(HW,"Could not start the device\n");
    oai_exit=1;
  }
laurent's avatar
laurent committed
1609

1610
  while (!oai_exit) {
1611
    if (IS_SOFTMODEM_BASICSIM)
1612 1613 1614 1615
      while (!(UE->proc.instance_cnt_synch < 0)) {
        printf("ue sync not ready\n");
        usleep(500*1000);
      }
1616

1617 1618 1619 1620
    AssertFatal ( 0== pthread_mutex_lock(&UE->proc.mutex_synch), "");
    int instance_cnt_synch = UE->proc.instance_cnt_synch;
    int is_synchronized    = UE->is_synchronized;
    AssertFatal ( 0== pthread_mutex_unlock(&UE->proc.mutex_synch), "");
1621
    
1622 1623
    if (is_synchronized == 0) {
      if (instance_cnt_synch < 0) {  // we can invoke the synch
1624
        // grab 10 ms of signal and wakeup synch thread
1625

1626
        if (UE->mode != loop_through_memory) {
1627 1628 1629 1630 1631
          if (IS_SOFTMODEM_RFSIM ) {
	    for(int sf=0; sf<10; sf++) {
	      for (int i=0; i<UE->frame_parms.nb_antennas_rx; i++)
		rxp[i] = (void *)&UE->common_vars.rxdata[i][UE->frame_parms.samples_per_tti*sf];
	      
1632
              AssertFatal(UE->frame_parms.samples_per_tti == UE->rfdevice.trx_read_func(&UE->rfdevice,
1633 1634 1635 1636 1637 1638 1639
						      &timestamp,
						      rxp,
						      UE->frame_parms.samples_per_tti,
						      UE->frame_parms.nb_antennas_rx), "");
	      write_dummy(UE, timestamp);
	    }
	  } else {
1640
	    for (int i=0; i<UE->frame_parms.nb_antennas_rx; i++)
1641
	      rxp[i] = (void *)&UE->common_vars.rxdata[i][0];
1642
	    
1643
	    AssertFatal( UE->frame_parms.samples_per_tti*10 ==
1644 1645 1646 1647 1648
                         UE->rfdevice.trx_read_func(&UE->rfdevice,
                                                    &timestamp,
                                                    rxp,
                                                    UE->frame_parms.samples_per_tti*10,
                                                    UE->frame_parms.nb_antennas_rx), "");
1649 1650
	      }
	}
1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662

        AssertFatal ( 0== pthread_mutex_lock(&UE->proc.mutex_synch), "");
        instance_cnt_synch = ++UE->proc.instance_cnt_synch;

        if (instance_cnt_synch == 0) {
          AssertFatal( 0 == pthread_cond_signal(&UE->proc.cond_synch), "");
        } else {
          LOG_E( PHY, "[SCHED][UE] UE sync thread busy!!\n" );
          exit_fun("nothing to add");
        }

        AssertFatal ( 0== pthread_mutex_unlock(&UE->proc.mutex_synch), "");
1663
      } else {
Cedric Roux's avatar
Cedric Roux committed
1664
#if OAISIM
1665 1666
        (void)dummy_rx; /* avoid gcc warnings */
        usleep(500);
Cedric Roux's avatar
Cedric Roux committed
1667
#else
1668 1669 1670 1671
        // grab 10 ms of signal into dummy buffer
        if (UE->mode != loop_through_memory) {
          for (int i=0; i<UE->frame_parms.nb_antennas_rx; i++)
            rxp[i] = (void *)&dummy_rx[i][0];
laurent's avatar
laurent committed
1672

1673
          for (int sf=0; sf<10; sf++) {
1674 1675 1676 1677 1678 1679
            //      printf("Reading dummy sf %d\n",sf);
            UE->rfdevice.trx_read_func(&UE->rfdevice,
                                       &timestamp,
                                       rxp,
                                       UE->frame_parms.samples_per_tti,
                                       UE->frame_parms.nb_antennas_rx);
1680 1681 1682
	    if (IS_SOFTMODEM_RFSIM )
	      write_dummy(UE, timestamp);
	  }
1683
	  }
Cedric Roux's avatar
Cedric Roux committed
1684
#endif
1685 1686 1687 1688 1689 1690 1691 1692 1693
      }
    } // UE->is_synchronized==0
    else {
      if (start_rx_stream==0) {
        start_rx_stream=1;

        if (UE->mode != loop_through_memory) {
          if (UE->no_timing_correction==0) {
            LOG_I(PHY,"Resynchronizing RX by %d samples (mode = %d)\n",UE->rx_offset,UE->mode);
1694 1695
	    while ( UE->rx_offset ) {
	      size_t s=min(UE->rx_offset,UE->frame_parms.samples_per_tti);
1696
              AssertFatal(s == UE->rfdevice.trx_read_func(&UE->rfdevice,
1697 1698 1699 1700 1701 1702 1703 1704
						     &timestamp,
						     (void **)UE->common_vars.rxdata,
						     s,
						     UE->frame_parms.nb_antennas_rx),"");
	      if (IS_SOFTMODEM_RFSIM )
		write_dummy(UE, timestamp);
	      UE->rx_offset-=s;
	    }
1705
          }
laurent's avatar
laurent committed
1706

1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744
          UE->rx_offset=0;
          UE->time_sync_cell=0;

          //UE->proc.proc_rxtx[0].frame_rx++;
          //UE->proc.proc_rxtx[1].frame_rx++;
          for (th_id=0; th_id < RX_NB_TH; th_id++) {
            UE->proc.proc_rxtx[th_id].frame_rx++;
          }

          // read in first symbol
          AssertFatal (UE->frame_parms.ofdm_symbol_size+UE->frame_parms.nb_prefix_samples0 ==
                       UE->rfdevice.trx_read_func(&UE->rfdevice,
                                                  &timestamp,
                                                  (void **)UE->common_vars.rxdata,
                                                  UE->frame_parms.ofdm_symbol_size+UE->frame_parms.nb_prefix_samples0,
                                                  UE->frame_parms.nb_antennas_rx),"");
          slot_fep(UE,0, 0, 0, 0, 0);
        } //UE->mode != loop_through_memory
        else
          rt_sleep_ns(1000*1000);
      } else {
        sub_frame++;
        sub_frame%=10;
        UE_rxtx_proc_t *proc = &UE->proc.proc_rxtx[thread_idx];
        // update thread index for received subframe
        UE->current_thread_id[sub_frame] = thread_idx;

        if (IS_SOFTMODEM_BASICSIM || IS_SOFTMODEM_RFSIM ) {
          int t;

          for (t = 0; t < 2; t++) {
            UE_rxtx_proc_t *proc = &UE->proc.proc_rxtx[t];
            pthread_mutex_lock(&proc->mutex_rxtx);

            while (proc->instance_cnt_rxtx >= 0) pthread_cond_wait( &proc->cond_rxtx, &proc->mutex_rxtx );

            pthread_mutex_unlock(&proc->mutex_rxtx);
          }
1745
	  usleep(300);
1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827
        }

        LOG_D(PHY,"Process Subframe %d thread Idx %d \n", sub_frame, UE->current_thread_id[sub_frame]);
        thread_idx++;

        if(thread_idx>=RX_NB_TH)
          thread_idx = 0;

        if (UE->mode != loop_through_memory) {
          for (i=0; i<UE->frame_parms.nb_antennas_rx; i++)
            rxp[i] = (void *)&UE->common_vars.rxdata[i][UE->frame_parms.ofdm_symbol_size+
                     UE->frame_parms.nb_prefix_samples0+
                     sub_frame*UE->frame_parms.samples_per_tti];

          for (i=0; i<UE->frame_parms.nb_antennas_tx; i++)
            txp[i] = (void *)&UE->common_vars.txdata[i][((sub_frame+2)%10)*UE->frame_parms.samples_per_tti];

          int readBlockSize, writeBlockSize;

          if (sub_frame<9) {
            readBlockSize=UE->frame_parms.samples_per_tti;
            writeBlockSize=UE->frame_parms.samples_per_tti;
          } else {
            // set TO compensation to zero
            UE->rx_offset_diff = 0;

            // compute TO compensation that should be applied for this frame

            if (UE->no_timing_correction == 0) {
              if ( UE->rx_offset < 5*UE->frame_parms.samples_per_tti  &&
                   UE->rx_offset > 0 )
                UE->rx_offset_diff = -1 ;

              if ( UE->rx_offset > 5*UE->frame_parms.samples_per_tti &&
                   UE->rx_offset < 10*UE->frame_parms.samples_per_tti )
                UE->rx_offset_diff = 1;
            }

            LOG_D(PHY,"AbsSubframe %d.%d SET rx_off_diff to %d rx_offset %d \n",proc->frame_rx,sub_frame,UE->rx_offset_diff,UE->rx_offset);
            readBlockSize=UE->frame_parms.samples_per_tti -
                          UE->frame_parms.ofdm_symbol_size -
                          UE->frame_parms.nb_prefix_samples0 -
                          UE->rx_offset_diff;
            writeBlockSize=UE->frame_parms.samples_per_tti -
                           UE->rx_offset_diff;
          }

          AssertFatal(readBlockSize ==
                      UE->rfdevice.trx_read_func(&UE->rfdevice,
                                                 &timestamp,
                                                 rxp,
                                                 readBlockSize,
                                                 UE->frame_parms.nb_antennas_rx),"");
          AssertFatal( writeBlockSize ==
                       UE->rfdevice.trx_write_func(&UE->rfdevice,
                           timestamp+
                           (2*UE->frame_parms.samples_per_tti) -
                           UE->frame_parms.ofdm_symbol_size-UE->frame_parms.nb_prefix_samples0 -
                           openair0_cfg[0].tx_sample_advance,
                           txp,
                           writeBlockSize,
                           UE->frame_parms.nb_antennas_tx,
                           1),"");

          if( sub_frame==9) {
            // read in first symbol of next frame and adjust for timing drift
            int first_symbols=writeBlockSize-readBlockSize;

            if ( first_symbols > 0 )
              AssertFatal(first_symbols ==
                          UE->rfdevice.trx_read_func(&UE->rfdevice,
                                                     &timestamp1,
                                                     (void **)UE->common_vars.rxdata,
                                                     first_symbols,
                                                     UE->frame_parms.nb_antennas_rx),"");

            if ( first_symbols <0 )
              LOG_E(PHY,"can't compensate: diff =%d\n", first_symbols);
          }

          pickTime(gotIQs);

Cedric Roux's avatar
Cedric Roux committed
1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843
          /* no timeout in IS_SOFTMODEM_BASICSIM or IS_SOFTMODEM_RFSIM mode */
          if (IS_SOFTMODEM_BASICSIM || IS_SOFTMODEM_RFSIM) {
            ret = pthread_mutex_lock(&proc->mutex_rxtx);
          } else {
            struct timespec tv;
            if (clock_gettime(CLOCK_REALTIME, &tv) != 0) {
              perror("clock_gettime");
              exit(1);
            }
            tv.tv_nsec += 10*1000;
            if (tv.tv_nsec >= 1000 * 1000 * 1000) {
              tv.tv_sec++;
              tv.tv_nsec -= 1000 * 1000 * 1000;
            }
            ret = pthread_mutex_timedlock(&proc->mutex_rxtx, &tv);
          }
1844 1845

          // operate on thread sf mod 2
Cedric Roux's avatar
Cedric Roux committed
1846 1847
          if (ret != 0) {
            if (ret == ETIMEDOUT) {
1848 1849
              LOG_E(PHY,"Missed real time\n");
              continue;
laurent's avatar
laurent committed
1850
            } else {
1851
              LOG_E(PHY,"System error %s (%d)\n",strerror(errno),errno);
1852 1853 1854
              abort();
            }
          }
laurent's avatar
laurent committed
1855

1856
          //          usleep(3000);
1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878
          if(sub_frame == 0) {
            //UE->proc.proc_rxtx[0].frame_rx++;
            //UE->proc.proc_rxtx[1].frame_rx++;
            for (th_id=0; th_id < RX_NB_TH; th_id++) {
              UE->proc.proc_rxtx[th_id].frame_rx++;
            }
          }

          //UE->proc.proc_rxtx[0].gotIQs=readTime(gotIQs);
          //UE->proc.proc_rxtx[1].gotIQs=readTime(gotIQs);
          for (th_id=0; th_id < RX_NB_TH; th_id++) {
            UE->proc.proc_rxtx[th_id].gotIQs=readTime(gotIQs);
          }

          proc->subframe_rx=sub_frame;
          proc->subframe_tx=(sub_frame+4)%10;
          proc->frame_tx = proc->frame_rx + (proc->subframe_rx>5?1:0);
          proc->timestamp_tx = timestamp+
                               (4*UE->frame_parms.samples_per_tti)-
                               UE->frame_parms.ofdm_symbol_size-UE->frame_parms.nb_prefix_samples0;
          proc->instance_cnt_rxtx++;
          LOG_D( PHY, "[SCHED][UE %d] UE RX instance_cnt_rxtx %d subframe %d !!\n", UE->Mod_id, proc->instance_cnt_rxtx,proc->subframe_rx);
Cedric Roux's avatar
Cedric Roux committed
1879
          T(T_UE_MASTER_TICK, T_INT(0), T_INT(proc->frame_rx%1024), T_INT(proc->subframe_rx));
1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892
          AssertFatal (pthread_cond_signal(&proc->cond_rxtx) ==0,"");
          AssertFatal(pthread_mutex_unlock(&proc->mutex_rxtx) ==0,"");
          initRefTimes(t1);
          initStaticTime(lastTime);
          updateTimes(lastTime, &t1, 20000, "Delay between two IQ acquisitions (case 1)");
          pickStaticTime(lastTime);
        } else {
          printf("Processing subframe %d",proc->subframe_rx);
          getchar();
        }
      } // start_rx_stream==1
    } // UE->is_synchronized==1
  } // while !oai_exit
laurent's avatar
laurent committed
1893

1894
  return NULL;
1895 1896
}

1897

1898 1899 1900
/*!
 * \brief Initialize the UE theads.
 * Creates the UE threads:
1901 1902
 * - UE_thread_rxtx0
 * - UE_thread_rxtx1
1903
 * - UE_thread_synch
1904 1905 1906 1907
 * - UE_thread_fep_slot0
 * - UE_thread_fep_slot1
 * - UE_thread_dlsch_proc_slot0
 * - UE_thread_dlsch_proc_slot1
1908 1909
 * and the locking between them.
 */
1910 1911
void init_UE_threads(int inst)
{
1912 1913 1914 1915 1916 1917 1918 1919 1920 1921
  struct rx_tx_thread_data *rtd;
  PHY_VARS_UE *UE;
  AssertFatal(PHY_vars_UE_g!=NULL,"PHY_vars_UE_g is NULL\n");
  AssertFatal(PHY_vars_UE_g[inst]!=NULL,"PHY_vars_UE_g[inst] is NULL\n");
  AssertFatal(PHY_vars_UE_g[inst][0]!=NULL,"PHY_vars_UE_g[inst][0] is NULL\n");
  UE = PHY_vars_UE_g[inst][0];
  pthread_attr_init (&UE->proc.attr_ue);
  pthread_attr_setstacksize(&UE->proc.attr_ue,8192);//5*PTHREAD_STACK_MIN);
  pthread_mutex_init(&UE->proc.mutex_synch,NULL);
  pthread_cond_init(&UE->proc.cond_synch,NULL);
1922 1923
  UE->proc.instance_cnt_synch = -1;
  UE->is_synchronized = 0;
1924 1925
  // the threads are not yet active, therefore access is allowed without locking
  int nb_threads=RX_NB_TH;
1926

1927 1928
  for (int i=0; i<nb_threads; i++) {
    rtd = calloc(1, sizeof(struct rx_tx_thread_data));
1929

1930
    if (rtd == NULL) abort();
1931

1932 1933 1934 1935
    rtd->UE = UE;
    rtd->proc = &UE->proc.proc_rxtx[i];
    pthread_mutex_init(&UE->proc.proc_rxtx[i].mutex_rxtx,NULL);
    pthread_cond_init(&UE->proc.proc_rxtx[i].cond_rxtx,NULL);
1936
    UE->proc.proc_rxtx[i].instance_cnt_rxtx = -1;
1937 1938 1939 1940
    UE->proc.proc_rxtx[i].sub_frame_start=i;
    UE->proc.proc_rxtx[i].sub_frame_step=nb_threads;
    printf("Init_UE_threads rtd %d proc %d nb_threads %d i %d\n",rtd->proc->sub_frame_start, UE->proc.proc_rxtx[i].sub_frame_start,nb_threads, i);
    pthread_create(&UE->proc.proc_rxtx[i].pthread_rxtx, NULL, UE_thread_rxn_txnp4, rtd);
fnabet's avatar
fnabet committed
1941
#ifdef UE_SLOT_PARALLELISATION
1942 1943 1944 1945 1946 1947
    //pthread_mutex_init(&UE->proc.proc_rxtx[i].mutex_slot0_dl_processing,NULL);
    //pthread_cond_init(&UE->proc.proc_rxtx[i].cond_slot0_dl_processing,NULL);
    //pthread_create(&UE->proc.proc_rxtx[i].pthread_slot0_dl_processing,NULL,UE_thread_slot0_dl_processing, rtd);
    pthread_mutex_init(&UE->proc.proc_rxtx[i].mutex_slot1_dl_processing,NULL);
    pthread_cond_init(&UE->proc.proc_rxtx[i].cond_slot1_dl_processing,NULL);
    pthread_create(&UE->proc.proc_rxtx[i].pthread_slot1_dl_processing,NULL,UE_thread_slot1_dl_processing, rtd);
fnabet's avatar
fnabet committed
1948
#endif
1949
  }
1950

1951
  pthread_create(&UE->proc.pthread_synch,NULL,UE_thread_synch,(void *)UE);
1952 1953
}

1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965

/*!
 * \brief Initialize the UE theads.
 * Creates the UE threads:
 * - UE_thread_rxtx0
 * - UE_thread_synch
 * - UE_thread_fep_slot0
 * - UE_thread_fep_slot1
 * - UE_thread_dlsch_proc_slot0
 * - UE_thread_dlsch_proc_slot1
 * and the locking between them.
 */
1966 1967
void init_UE_single_thread_stub(int nb_inst)
{
1968 1969 1970
  struct rx_tx_thread_data *rtd;
  PHY_VARS_UE *UE;

1971 1972 1973 1974 1975
  for (int i=0; i<nb_inst; i++) {
    AssertFatal(PHY_vars_UE_g!=NULL,"PHY_vars_UE_g is NULL\n");
    AssertFatal(PHY_vars_UE_g[i]!=NULL,"PHY_vars_UE_g[inst] is NULL\n");
    AssertFatal(PHY_vars_UE_g[i][0]!=NULL,"PHY_vars_UE_g[inst][0] is NULL\n");

frtabu's avatar
frtabu committed
1976
    if(NFAPI_MODE==NFAPI_UE_STUB_PNF) {
1977
#ifdef NAS_UE
1978
      MessageDef *message_p;
1979
      message_p = itti_alloc_new_message(TASK_NAS_UE, 0, INITIALIZE_MESSAGE);
1980
      itti_send_msg_to_task (TASK_NAS_UE, i + NB_eNB_INST, message_p);
1981
#endif
1982
    }
1983 1984
  }

1985
  UE = PHY_vars_UE_g[0][0];
1986 1987
  pthread_attr_init (&UE->proc.attr_ue);
  pthread_attr_setstacksize(&UE->proc.attr_ue,8192);//5*PTHREAD_STACK_MIN);
1988
  // Don't need synch for phy_stub mode
1989 1990 1991
  //pthread_mutex_init(&UE->proc.mutex_synch,NULL);
  //pthread_cond_init(&UE->proc.cond_synch,NULL);
  // the threads are not yet active, therefore access is allowed without locking
1992
  // In phy_stub_UE mode due to less heavy processing operations we don't need two threads
1993 1994 1995
  //int nb_threads=RX_NB_TH;
  int nb_threads=1;

1996
  for(uint16_t ue_thread_id = 0; ue_thread_id < NB_THREAD_INST; ue_thread_id++) {
1997
    UE = PHY_vars_UE_g[ue_thread_id][0];
1998

1999 2000
    for (int i=0; i<nb_threads; i++) {
      rtd = calloc(1, sizeof(struct rx_tx_thread_data));
2001

2002
      if (rtd == NULL) abort();
2003

2004 2005 2006 2007 2008 2009 2010 2011 2012 2013
      rtd->UE = UE;
      rtd->proc = &UE->proc.proc_rxtx[i];
      rtd->ue_thread_id = ue_thread_id;
      pthread_mutex_init(&UE->proc.proc_rxtx[i].mutex_rxtx,NULL);
      pthread_cond_init(&UE->proc.proc_rxtx[i].cond_rxtx,NULL);
      UE->proc.proc_rxtx[i].sub_frame_start=i;
      UE->proc.proc_rxtx[i].sub_frame_step=nb_threads;
      printf("Init_UE_threads rtd %d proc %d nb_threads %d i %d\n",rtd->proc->sub_frame_start, UE->proc.proc_rxtx[i].sub_frame_start,nb_threads, i);
      pthread_create(&UE->proc.proc_rxtx[i].pthread_rxtx, NULL, UE_phy_stub_single_thread_rxn_txnp4, rtd);
    }
2014
  }
2015

2016
  // Remove thread for UE_sync in phy_stub_UE mode.
2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031
  //pthread_create(&UE->proc.pthread_synch,NULL,UE_thread_synch,(void*)UE);
}


/*!
 * \brief Initialize the UE theads.
 * Creates the UE threads:
 * - UE_thread_rxtx0
 * - UE_thread_synch
 * - UE_thread_fep_slot0
 * - UE_thread_fep_slot1
 * - UE_thread_dlsch_proc_slot0
 * - UE_thread_dlsch_proc_slot1
 * and the locking between them.
 */
2032 2033
void init_UE_threads_stub(int inst)
{
2034 2035 2036 2037 2038 2039 2040 2041
  struct rx_tx_thread_data *rtd;
  PHY_VARS_UE *UE;
  AssertFatal(PHY_vars_UE_g!=NULL,"PHY_vars_UE_g is NULL\n");
  AssertFatal(PHY_vars_UE_g[inst]!=NULL,"PHY_vars_UE_g[inst] is NULL\n");
  AssertFatal(PHY_vars_UE_g[inst][0]!=NULL,"PHY_vars_UE_g[inst][0] is NULL\n");
  UE = PHY_vars_UE_g[inst][0];
  pthread_attr_init (&UE->proc.attr_ue);
  pthread_attr_setstacksize(&UE->proc.attr_ue,8192);//5*PTHREAD_STACK_MIN);
2042
  // Don't need synch for phy_stub mode
2043 2044 2045
  //pthread_mutex_init(&UE->proc.mutex_synch,NULL);
  //pthread_cond_init(&UE->proc.cond_synch,NULL);
  // the threads are not yet active, therefore access is allowed without locking
2046
  // In phy_stub_UE mode due to less heavy processing operations we don't need two threads
2047 2048
  //int nb_threads=RX_NB_TH;
  int nb_threads=1;
2049

2050 2051
  for (int i=0; i<nb_threads; i++) {
    rtd = calloc(1, sizeof(struct rx_tx_thread_data));
2052

2053
    if (rtd == NULL) abort();
2054

2055 2056 2057 2058 2059 2060 2061 2062 2063
    rtd->UE = UE;
    rtd->proc = &UE->proc.proc_rxtx[i];
    pthread_mutex_init(&UE->proc.proc_rxtx[i].mutex_rxtx,NULL);
    pthread_cond_init(&UE->proc.proc_rxtx[i].cond_rxtx,NULL);
    UE->proc.proc_rxtx[i].sub_frame_start=i;
    UE->proc.proc_rxtx[i].sub_frame_step=nb_threads;
    printf("Init_UE_threads rtd %d proc %d nb_threads %d i %d\n",rtd->proc->sub_frame_start, UE->proc.proc_rxtx[i].sub_frame_start,nb_threads, i);
    pthread_create(&UE->proc.proc_rxtx[i].pthread_rxtx, NULL, UE_phy_stub_thread_rxn_txnp4, rtd);
  }
2064

2065
  // Remove thread for UE_sync in phy_stub_UE mode.
2066 2067 2068 2069
  //pthread_create(&UE->proc.pthread_synch,NULL,UE_thread_synch,(void*)UE);
}


Raymond Knopp's avatar
 
Raymond Knopp committed
2070
#ifdef OPENAIR2
2071 2072
void fill_ue_band_info(void)
{
2073
  LTE_UE_EUTRA_Capability_t *UE_EUTRA_Capability = UE_rrc_inst[0].UECap->UE_EUTRA_Capability;
2074 2075 2076 2077 2078 2079
  int i,j;
  bands_to_scan.nbands = UE_EUTRA_Capability->rf_Parameters.supportedBandListEUTRA.list.count;

  for (i=0; i<bands_to_scan.nbands; i++) {
    for (j=0; j<sizeof (eutra_bands) / sizeof (eutra_bands[0]); j++)
      if (eutra_bands[j].band == UE_EUTRA_Capability->rf_Parameters.supportedBandListEUTRA.list.array[i]->bandEUTRA) {
2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091
        memcpy(&bands_to_scan.band_info[i],
               &eutra_bands[j],
               sizeof(eutra_band_t));
        printf("Band %d (%lu) : DL %u..%u Hz, UL %u..%u Hz, Duplex %s \n",
               bands_to_scan.band_info[i].band,
               UE_EUTRA_Capability->rf_Parameters.supportedBandListEUTRA.list.array[i]->bandEUTRA,
               bands_to_scan.band_info[i].dl_min,
               bands_to_scan.band_info[i].dl_max,
               bands_to_scan.band_info[i].ul_min,
               bands_to_scan.band_info[i].ul_max,
               (bands_to_scan.band_info[i].frame_type==FDD) ? "FDD" : "TDD");
        break;
2092 2093
      }
  }
2094
}
Raymond Knopp's avatar
 
Raymond Knopp committed
2095
#endif
2096

2097
int setup_ue_buffers(PHY_VARS_UE **phy_vars_ue,
2098
                     openair0_config_t *openair0_cfg)
2099
{
2100 2101 2102 2103 2104 2105 2106
  int i, CC_id;
  LTE_DL_FRAME_PARMS *frame_parms;

  for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
    AssertFatal( phy_vars_ue[CC_id] !=0, "");
    frame_parms = &(phy_vars_ue[CC_id]->frame_parms);
    // replace RX signal buffers with mmaped HW versions
2107 2108
    rxdata = (int32_t **)malloc16( frame_parms->nb_antennas_rx*sizeof(int32_t *) );
    txdata = (int32_t **)malloc16( frame_parms->nb_antennas_tx*sizeof(int32_t *) );
2109 2110

    for (i=0; i<frame_parms->nb_antennas_rx; i++) {
frtabu's avatar
frtabu committed
2111
      LOG_I(PHY, "Mapping UE CC_id %d, rx_ant %d, freq %lu on card %d, chain %d\n",
2112
            CC_id, i, downlink_frequency[CC_id][i], phy_vars_ue[CC_id]->rf_map.card, (phy_vars_ue[CC_id]->rf_map.chain)+i );
2113
      free( phy_vars_ue[CC_id]->common_vars.rxdata[i] );
2114
      rxdata[i] = (int32_t *)malloc16_clear( 307200*sizeof(int32_t) );
2115 2116 2117 2118
      phy_vars_ue[CC_id]->common_vars.rxdata[i] = rxdata[i]; // what about the "-N_TA_offset" ? // N_TA offset for TDD
    }

    for (i=0; i<frame_parms->nb_antennas_tx; i++) {
frtabu's avatar
frtabu committed
2119
      LOG_I(PHY, "Mapping UE CC_id %d, tx_ant %d, freq %lu on card %d, chain %d\n",
2120
            CC_id, i, downlink_frequency[CC_id][i], phy_vars_ue[CC_id]->rf_map.card, (phy_vars_ue[CC_id]->rf_map.chain)+i );
2121
      free( phy_vars_ue[CC_id]->common_vars.txdata[i] );
2122
      txdata[i] = (int32_t *)malloc16_clear( 307200*sizeof(int32_t) );
2123 2124 2125 2126 2127 2128 2129 2130
      phy_vars_ue[CC_id]->common_vars.txdata[i] = txdata[i];
    }

    // rxdata[x] points now to the same memory region as phy_vars_ue[CC_id]->common_vars.rxdata[x]
    // txdata[x] points now to the same memory region as phy_vars_ue[CC_id]->common_vars.txdata[x]
    // be careful when releasing memory!
    // because no "release_ue_buffers"-function is available, at least rxdata and txdata memory will leak (only some bytes)
  }
2131

2132 2133 2134 2135 2136 2137 2138 2139 2140
  return 0;
}


// Panos: This timer thread is used only in the phy_stub mode as an independent timer
// which will be ticking and provide the SFN/SF values that will be used from the UE threads
// playing the role of nfapi-pnf.

//02/02/2018
2141 2142
static void *timer_thread( void *param )
{
2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155
  thread_top_init("timer_thread",1,870000L,1000000L,1000000L);
  timer_subframe =9;
  timer_frame    =1023;
  //phy_stub_ticking = (SF_ticking*)malloc(sizeof(SF_ticking));
  phy_stub_ticking->ticking_var = -1;
  PHY_VARS_UE *UE;
  UE = PHY_vars_UE_g[0][0];
  //double t_diff;
  int external_timer = 0;
  wait_sync("timer_thread");
  opp_enabled = 1;

  // first check if we are receiving timing indications
frtabu's avatar
frtabu committed
2156
  if(NFAPI_MODE==NFAPI_UE_STUB_OFFNET) {
2157 2158 2159 2160 2161 2162 2163 2164 2165 2166 2167 2168
    usleep(10000);

    if (UE->instance_cnt_timer > 0) {
      external_timer = 1;
      int absSFm1 = ((emulator_absSF+10239)%10240);
      timer_frame = absSFm1/10;
      timer_subframe = absSFm1%10;
      pthread_mutex_lock(&UE->timer_mutex);
      UE->instance_cnt_timer = -1;
      pthread_mutex_unlock(&UE->timer_mutex);
      LOG_I(PHY,"Running with external timer\n");
    } else LOG_I(PHY,"Running with internal timer\n");
2169 2170 2171
  }

  struct timespec t_start;
2172

2173
  struct timespec t_now;
2174

2175
  struct timespec t_sleep;
2176

2177
  uint64_t T_0;
2178

2179
  uint64_t T_now;
2180

2181
  uint64_t T_next_SF;
2182

2183
  uint64_t T_sleep;
2184

2185 2186 2187
  uint64_t sf_cnt = 0; //Total Subframe counter

  clock_gettime(CLOCK_MONOTONIC, &t_start);
2188

2189
  T_0 = (uint64_t) t_start.tv_sec*1000000000 + t_start.tv_nsec;
2190

2191 2192 2193 2194 2195 2196 2197 2198 2199 2200 2201 2202 2203 2204 2205 2206
  LOG_D(MAC, "timer_thread(), T_0 value: %" PRId64 "\n", T_0);

  while (!oai_exit) {
    // these are local subframe/frame counters to check that we are in synch with the fronthaul timing.
    // They are set on the first rx/tx in the underly FH routines.
    if (timer_subframe==9) {
      timer_subframe=0;
      timer_frame++;
      timer_frame&=1023;
    } else {
      timer_subframe++;
    }

    //AssertFatal( 0 == pthread_cond_signal(&phy_stub_ticking->cond_ticking), "");
    AssertFatal(pthread_mutex_lock(&phy_stub_ticking->mutex_ticking) ==0,"");
    phy_stub_ticking->ticking_var++;
2207

2208
    // This should probably be a call to pthread_cond_broadcast when we introduce support for multiple UEs (threads)
2209
    if(phy_stub_ticking->ticking_var == 0) {
2210
      //AssertFatal(phy_stub_ticking->ticking_var == 0,"phy_stub_ticking->ticking_var = %d",
2211
      //phy_stub_ticking->ticking_var);
2212
      if (pthread_cond_signal(&phy_stub_ticking->cond_ticking) != 0) {
2213 2214 2215
        //LOG_E( PHY, "[SCHED][UE %d] ERROR pthread_cond_signal for UE RX thread\n", UE->Mod_id);
        LOG_E( PHY, "timer_thread ERROR pthread_cond_signal for UE_thread\n");
        exit_fun("nothing to add");
2216
      }
2217 2218
    } else
      LOG_D(MAC, "timer_thread() Timing problem! ticking_var value:%d \n \n \n", phy_stub_ticking->ticking_var);
2219 2220 2221 2222 2223 2224

    AssertFatal(pthread_mutex_unlock(&phy_stub_ticking->mutex_ticking) ==0,"");
    start_meas(&UE->timer_stats);

    //clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &start); // get initial time-stamp
    if (external_timer == 0) {
2225 2226 2227 2228 2229 2230 2231 2232 2233 2234 2235 2236 2237 2238
      clock_gettime(CLOCK_MONOTONIC, &t_now);
      sf_cnt++;
      T_next_SF = T_0 + sf_cnt*1000000;
      T_now =(uint64_t) t_now.tv_sec*1000000000 + t_now.tv_nsec;

      if(T_now > T_next_SF) {
        t_sleep.tv_sec =0;
        t_sleep.tv_nsec =0;
      } else {
        T_sleep = T_next_SF - T_now;
        t_sleep.tv_sec =0;
        t_sleep.tv_nsec = (__syscall_slong_t) T_sleep;
      }

2239 2240 2241 2242 2243
      nanosleep(&t_sleep, (struct timespec *)NULL);
      UE_tport_t pdu;
      pdu.header.packet_type = TTI_SYNC;
      pdu.header.absSF = (timer_frame*10)+timer_subframe;

frtabu's avatar
frtabu committed
2244
      if (NFAPI_MODE != NFAPI_UE_STUB_PNF) {
2245 2246 2247 2248 2249
        multicast_link_write_sock(0,
                                  (char *)&pdu,
                                  sizeof(UE_tport_header_t));
      }
    } else {
2250 2251 2252 2253 2254 2255 2256 2257 2258 2259
      wait_on_condition(&UE->timer_mutex,&UE->timer_cond,&UE->instance_cnt_timer,"timer_thread");
      release_thread(&UE->timer_mutex,&UE->instance_cnt_timer,"timer_thread");
    }

    /*stop_meas(&UE->timer_stats);
    t_diff = get_time_meas_us(&UE->timer_stats);

    stop_meas(&UE->timer_stats);
    t_diff = get_time_meas_us(&UE->timer_stats);*/
  }
2260

2261 2262 2263 2264
  free(phy_stub_ticking);
  pthread_cond_destroy(&phy_stub_ticking->cond_ticking);
  pthread_mutex_destroy(&phy_stub_ticking->mutex_ticking);
  return 0;
2265
}
2266

2267

2268 2269
int init_timer_thread(void)
{
2270
  //PHY_VARS_UE *UE=PHY_vars_UE_g[0];
2271 2272
  PHY_VARS_UE *UE=PHY_vars_UE_g[0][0];
  phy_stub_ticking = (SF_ticking *)malloc(sizeof(SF_ticking));
2273 2274 2275
  pthread_mutex_init(&UE->timer_mutex,NULL);
  pthread_cond_init(&UE->timer_cond,NULL);
  UE->instance_cnt_timer = -1;
2276
  memset(&phy_stub_ticking->num_single_thread[0],0,sizeof(int)*NB_THREAD_INST);
2277 2278
  pthread_mutex_init(&phy_stub_ticking->mutex_ticking,NULL);
  pthread_cond_init(&phy_stub_ticking->cond_ticking,NULL);
2279 2280
  pthread_mutex_init(&phy_stub_ticking->mutex_single_thread,NULL);
  pthread_cond_init(&phy_stub_ticking->cond_single_thread,NULL);
2281 2282 2283
  pthread_create(&phy_stub_ticking->pthread_timer, NULL, &timer_thread, NULL);
  return 0;
}
2284 2285 2286 2287 2288


/* HACK: this function is needed to compile the UE
 * fix it somehow
 */
2289
int8_t find_dlsch(uint16_t rnti,
2290 2291
                  PHY_VARS_eNB *eNB,
                  find_type_t type)
2292 2293 2294 2295 2296
{
  printf("you cannot read this\n");
  abort();
}