lte-enb.c 39.8 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
/*
 * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The OpenAirInterface Software Alliance licenses this file to You under
 * the OAI Public License, Version 1.0  (the "License"); you may not use this file
 * except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.openairinterface.org/?page_id=698
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *-------------------------------------------------------------------------------
 * For more information about the OpenAirInterface (OAI) Software Alliance:
 *      contact@openairinterface.org
 */
21 22 23 24 25 26 27 28 29 30 31

/*! \file lte-enb.c
 * \brief Top-level threads for eNodeB
 * \author R. Knopp, F. Kaltenberger, Navid Nikaein
 * \date 2012
 * \version 0.1
 * \company Eurecom
 * \email: knopp@eurecom.fr,florian.kaltenberger@eurecom.fr, navid.nikaein@eurecom.fr
 * \note
 * \warning
 */
32

Raymond Knopp's avatar
Raymond Knopp committed
33 34
#define _GNU_SOURCE
#include <pthread.h>
35

36 37
#include "time_utils.h"

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

40 41
#include "rt_wrapper.h"

42
#include "assertions.h"
43

44 45 46 47 48 49 50 51 52 53 54

#include "PHY/types.h"

#include "PHY/defs.h"
#undef MALLOC //there are two conflicting definitions, so we better make sure we don't use it at all
//#undef FRAME_LENGTH_COMPLEX_SAMPLES //there are two conflicting definitions, so we better make sure we don't use it at all

#include "../../ARCH/COMMON/common_lib.h"

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

55
#include "PHY/LTE_TRANSPORT/if4_tools.h"
56
#include "PHY/LTE_TRANSPORT/if5_tools.h"
57

58 59 60 61 62 63 64 65 66 67 68
#include "PHY/extern.h"
#include "SCHED/extern.h"
#include "LAYER2/MAC/extern.h"

#include "../../SIMU/USER/init_lte.h"

#include "LAYER2/MAC/defs.h"
#include "LAYER2/MAC/extern.h"
#include "LAYER2/MAC/proto.h"
#include "RRC/LITE/extern.h"
#include "PHY_INTERFACE/extern.h"
69
#include "PHY_INTERFACE/defs.h"
70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95
#ifdef SMBV
#include "PHY/TOOLS/smbv.h"
unsigned short config_frames[4] = {2,9,11,13};
#endif
#include "UTIL/LOG/log_extern.h"
#include "UTIL/OTG/otg_tx.h"
#include "UTIL/OTG/otg_externs.h"
#include "UTIL/MATH/oml.h"
#include "UTIL/LOG/vcd_signal_dumper.h"
#include "UTIL/OPT/opt.h"
#include "enb_config.h"
//#include "PHY/TOOLS/time_meas.h"

#ifndef OPENAIR2
#include "UTIL/OTG/otg_extern.h"
#endif

#if defined(ENABLE_ITTI)
# if defined(ENABLE_USE_MME)
#   include "s1ap_eNB.h"
#ifdef PDCP_USE_NETLINK
#   include "SIMULATION/ETH_TRANSPORT/proto.h"
#endif
# endif
#endif

Rohit Gupta's avatar
Rohit Gupta committed
96 97
#include "T.h"

98 99 100 101 102 103 104 105 106 107
//#define DEBUG_THREADS 1

//#define USRP_DEBUG 1
struct timing_info_t {
  //unsigned int frame, hw_slot, last_slot, next_slot;
  RTIME time_min, time_max, time_avg, time_last, time_now;
  //unsigned int mbox0, mbox1, mbox2, mbox_target;
  unsigned int n_samples;
} timing_info;

108 109
// Fix per CC openair rf/if device update
// extern openair0_device openair0;
110

111

112 113 114 115 116 117 118 119
#if defined(ENABLE_ITTI)
extern volatile int             start_eNB;
extern volatile int             start_UE;
#endif
extern volatile int                    oai_exit;

extern openair0_config_t openair0_cfg[MAX_CARDS];

Cedric Roux's avatar
Cedric Roux committed
120
extern int transmission_mode;
121

122 123
extern int oaisim_flag;

124
//pthread_t                       main_eNB_thread;
125 126 127

time_stats_t softmodem_stats_mt; // main thread
time_stats_t softmodem_stats_hw; //  hw acquisition
128
time_stats_t softmodem_stats_rxtx_sf; // total tx time
129
time_stats_t softmodem_stats_rx_sf; // total rx time
130 131 132 133 134 135 136 137 138

/* mutex, cond and variable to serialize phy proc TX calls
 * (this mechanism may be relaxed in the future for better
 * performances)
 */
static struct {
  pthread_mutex_t  mutex_phy_proc_tx;
  pthread_cond_t   cond_phy_proc_tx;
  volatile uint8_t phy_proc_CC_id;
139
} sync_phy_proc;
140

141 142
extern double cpuf;

143 144
void exit_fun(const char* s);

145
void init_eNB(int,int);
146
void stop_eNB(int nb_inst);
147

148
int wakeup_tx(PHY_VARS_eNB *eNB,RU_proc_t *ru_proc);
Wang Tsu-Han's avatar
Wang Tsu-Han committed
149
int wakeup_txfh(eNB_rxtx_proc_t *proc,RU_proc_t *ru_proc);
150
void wakeup_prach_eNB(PHY_VARS_eNB *eNB,RU_t *ru,int frame,int subframe);
151 152 153
#ifdef Rel14
void wakeup_prach_eNB_br(PHY_VARS_eNB *eNB,RU_t *ru,int frame,int subframe);
#endif
Wang Tsu-Han's avatar
Wang Tsu-Han committed
154
extern int codingw;
155

Raymond Knopp's avatar
Raymond Knopp committed
156 157 158
static inline int rxtx(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc, char *thread_name) {

  start_meas(&softmodem_stats_rxtx_sf);
159

Raymond Knopp's avatar
Raymond Knopp committed
160 161
  // ****************************************
  // Common RX procedures subframe n
162

Cedric Roux's avatar
Cedric Roux committed
163 164
  T(T_ENB_PHY_DL_TICK, T_INT(eNB->Mod_id), T_INT(proc->frame_tx), T_INT(proc->subframe_tx));

165
  // if this is IF5 or 3GPP_eNB
166 167 168 169 170 171
  if (eNB->RU_list[0]->function < NGFI_RAU_IF4p5) {
    wakeup_prach_eNB(eNB,NULL,proc->frame_rx,proc->subframe_rx);
#ifdef Rel14
    wakeup_prach_eNB_br(eNB,NULL,proc->frame_rx,proc->subframe_rx);
#endif
  }
Raymond Knopp's avatar
Raymond Knopp committed
172
  // UE-specific RX processing for subframe n
173
  phy_procedures_eNB_uespec_RX(eNB, proc, no_relay );
174
  
175
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_DLSCH_ULSCH_SCHEDULER , 1 );
176
    
177
  pthread_mutex_lock(&eNB->UL_INFO_mutex);
178 179 180 181 182
  eNB->UL_INFO.frame     = proc->frame_rx;
  eNB->UL_INFO.subframe  = proc->subframe_rx;
  eNB->UL_INFO.module_id = eNB->Mod_id;
  eNB->UL_INFO.CC_id     = eNB->CC_id;
  eNB->if_inst->UL_indication(&eNB->UL_INFO);
183
  pthread_mutex_unlock(&eNB->UL_INFO_mutex);
Raymond Knopp's avatar
Raymond Knopp committed
184
  
185
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_DLSCH_ULSCH_SCHEDULER , 0 );
186
  if(get_nprocs() >= 8)
Wang Tsu-Han's avatar
Wang Tsu-Han committed
187 188 189
  {
    wakeup_tx(eNB,eNB->proc.ru_proc);
  }
190
  else if(get_nprocs() > 4)
Wang Tsu-Han's avatar
Wang Tsu-Han committed
191 192 193 194
  {
    if(oai_exit) return(-1);
    phy_procedures_eNB_TX(eNB, proc, no_relay, NULL, 1);
    
Wang Tsu-Han's avatar
Wang Tsu-Han committed
195
    wakeup_txfh(proc,eNB->proc.ru_proc);
Wang Tsu-Han's avatar
Wang Tsu-Han committed
196 197 198 199 200 201
  }
  else
  {
    if(oai_exit) return(-1);
    phy_procedures_eNB_TX(eNB, proc, no_relay, NULL, 1);
  }
Raymond Knopp's avatar
Raymond Knopp committed
202 203 204 205 206 207

  stop_meas( &softmodem_stats_rxtx_sf );
  
  return(0);
}

208

209 210 211 212 213 214 215
static void* tx_thread(void* param) {

  eNB_proc_t *eNB_proc  = (eNB_proc_t*)param;
  eNB_rxtx_proc_t *proc = &eNB_proc->proc_rxtx[1];
  PHY_VARS_eNB *eNB = RC.eNB[0][proc->CC_id];
  
  char thread_name[100];
216
  sprintf(thread_name,"TXnp4_%d\n",&eNB->proc.proc_rxtx[0] == proc ? 0 : 1);
217
  thread_top_init(thread_name,1,470000,500000,500000);
218
  
219
  //wait_sync("tx_thread");
Eurecom's avatar
Eurecom committed
220
  
221
  while (!oai_exit) {
222 223 224 225 226 227 228 229 230
    
    pthread_mutex_lock( &proc->mutex_rxtx );
    proc->pipe_ready++;
    // the thread can now be woken up
    if (pthread_cond_signal(&proc->cond_rxtx) != 0) {
      LOG_E( PHY, "[eNB] ERROR pthread_cond_signal for eNB TXnp4 thread\n");
      exit_fun( "ERROR pthread_cond_signal" );
    }
    pthread_mutex_unlock( &proc->mutex_rxtx );
231 232 233 234 235 236 237 238

    if (wait_on_condition(&proc->mutex_rxtx,&proc->cond_rxtx,&proc->instance_cnt_rxtx,thread_name)<0) break;
    if (oai_exit) break;    
    // *****************************************
    // TX processing for subframe n+4
    // run PHY TX procedures the one after the other for all CCs to avoid race conditions
    // (may be relaxed in the future for performance reasons)
    // *****************************************
239 240 241 242
    VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_TX1_ENB,proc->subframe_tx);
    VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_RX1_ENB,proc->subframe_rx);
    VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX1_ENB,proc->frame_tx);
    VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX1_ENB,proc->frame_rx);
243 244 245 246
    
    phy_procedures_eNB_TX(eNB, proc, no_relay, NULL, 1);
	if (release_thread(&proc->mutex_rxtx,&proc->instance_cnt_rxtx,thread_name)<0) break;
	
Wang Tsu-Han's avatar
Wang Tsu-Han committed
247
    wakeup_txfh(proc,eNB_proc->ru_proc);
248 249 250 251 252
  }

  return 0;
}

253
/*!
254
 * \brief The RX UE-specific and TX thread of eNB.
255 256 257
 * \param param is a \ref eNB_proc_t structure which contains the info what to process.
 * \returns a pointer to an int. The storage is not on the heap and must not be freed.
 */
258

259 260
static void* eNB_thread_rxtx( void* param ) {

261
  static int eNB_thread_rxtx_status;
262 263
  eNB_proc_t *eNB_proc  = (eNB_proc_t*)param;
  eNB_rxtx_proc_t *proc = &eNB_proc->proc_rxtx[0];
264
  PHY_VARS_eNB *eNB = RC.eNB[0][proc->CC_id];
265
  //RU_proc_t *ru_proc = NULL;
266

Raymond Knopp's avatar
Raymond Knopp committed
267 268
  char thread_name[100];

269 270
  cpu_set_t cpuset;
  CPU_ZERO(&cpuset);
271

272
  // set default return value
273
  eNB_thread_rxtx_status = 0;
274 275


Raymond Knopp's avatar
Raymond Knopp committed
276
  sprintf(thread_name,"RXn_TXnp4_%d\n",&eNB->proc.proc_rxtx[0] == proc ? 0 : 1);
277 278 279
  thread_top_init(thread_name,1,470000,500000,500000);
  pthread_setname_np( pthread_self(),"rxtx processing");
  LOG_I(PHY,"thread rxtx created id=%ld\n", syscall(__NR_gettid));
280

281 282
  //CPU_SET(3, &cpuset);
  //pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset);
Eurecom's avatar
Eurecom committed
283
  
284
  //wait_sync("eNB_thread_rxtx");
285

286
  while (!oai_exit) {
287 288 289 290 291 292 293 294 295 296
    
    pthread_mutex_lock( &proc->mutex_rxtx );
    proc->pipe_ready++;
    // the thread can now be woken up
    if (pthread_cond_signal(&proc->cond_rxtx) != 0) {
      LOG_E( PHY, "[eNB] ERROR pthread_cond_signal for eNB TXnp4 thread\n");
      exit_fun( "ERROR pthread_cond_signal" );
    }
    pthread_mutex_unlock( &proc->mutex_rxtx );
    
297
    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_RXTX0+(proc->subframe_rx&1), 0 );
298
    T(T_ENB_MASTER_TICK, T_INT(0), T_INT(proc->frame_rx), T_INT(proc->subframe_rx));
299

Raymond Knopp's avatar
Raymond Knopp committed
300
    if (wait_on_condition(&proc->mutex_rxtx,&proc->cond_rxtx,&proc->instance_cnt_rxtx,thread_name)<0) break;
301

302
    VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_CPUID_ENB_THREAD_RXTX,sched_getcpu());
303
    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_RXTX0+(proc->subframe_rx&1), 1 );
304 305 306 307 308 309 310
    //ru_proc = eNB_proc->ru_proc;
   
    VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_TX0_ENB,proc->subframe_tx);
    VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_RX0_ENB,proc->subframe_rx);
    VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX0_ENB,proc->frame_tx);
    VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX0_ENB,proc->frame_rx);
 
311
  
312 313
    if (oai_exit) break;

314 315
    if (eNB->CC_id==0)
      if (rxtx(eNB,proc,thread_name) < 0) break;
316 317 318

    if (release_thread(&proc->mutex_rxtx,&proc->instance_cnt_rxtx,thread_name)<0) break;
  
Raymond Knopp's avatar
Raymond Knopp committed
319
  } // while !oai_exit
320

321
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_RXTX0+(proc->subframe_rx&1), 0 );
322

Raymond Knopp's avatar
Raymond Knopp committed
323
  printf( "Exiting eNB thread RXn_TXnp4\n");
324

325 326
  eNB_thread_rxtx_status = 0;
  return &eNB_thread_rxtx_status;
327 328
}

329

Raymond Knopp's avatar
Raymond Knopp committed
330 331
#if 0 //defined(ENABLE_ITTI) && defined(ENABLE_USE_MME)
// Wait for eNB application initialization to be complete (eNB registration to MME)
332 333
static void wait_system_ready (char *message, volatile int *start_flag) {
  
334
  static char *indicator[] = {".    ", "..   ", "...  ", ".... ", ".....",
335
			      " ....", "  ...", "   ..", "    .", "     "};
336 337 338 339 340 341 342
  int i = 0;
  
  while ((!oai_exit) && (*start_flag == 0)) {
    LOG_N(EMU, message, indicator[i]);
    fflush(stdout);
    i = (i + 1) % (sizeof(indicator) / sizeof(indicator[0]));
    usleep(200000);
343
  }
344 345
  
  LOG_D(EMU,"\n");
346 347
}
#endif
348

Raymond Knopp's avatar
Raymond Knopp committed
349 350


351

Raymond Knopp's avatar
Raymond Knopp committed
352

353
void eNB_top(PHY_VARS_eNB *eNB, int frame_rx, int subframe_rx, char *string,RU_t *ru)
Cedric Roux's avatar
Cedric Roux committed
354
{
355 356
  eNB_proc_t *proc           = &eNB->proc;
  eNB_rxtx_proc_t *proc_rxtx = &proc->proc_rxtx[0];
357

358 359
  proc->frame_rx    = frame_rx;
  proc->subframe_rx = subframe_rx;
Raymond Knopp's avatar
Raymond Knopp committed
360

Cedric Roux's avatar
Cedric Roux committed
361
  if (!oai_exit) {
362
    LOG_D(PHY,"eNB_top in %p (proc %p, CC_id %d), frame %d, subframe %d, instance_cnt_prach %d\n",
Raymond Knopp's avatar
Raymond Knopp committed
363
	  (void*)pthread_self(), proc, eNB->CC_id, proc->frame_rx,proc->subframe_rx,proc->instance_cnt_prach);
Raymond Knopp's avatar
Raymond Knopp committed
364

365
    T(T_ENB_MASTER_TICK, T_INT(0), T_INT(proc->frame_rx), T_INT(proc->subframe_rx));
Raymond Knopp's avatar
Raymond Knopp committed
366

367 368 369 370 371 372
    proc_rxtx->subframe_rx = proc->subframe_rx;
    proc_rxtx->frame_rx    = proc->frame_rx;
    proc_rxtx->subframe_tx = (proc->subframe_rx+4)%10;
    proc_rxtx->frame_tx    = (proc->subframe_rx>5) ? (1+proc->frame_rx)&1023 : proc->frame_rx;
    proc->frame_tx         = proc_rxtx->frame_tx;
    proc_rxtx->timestamp_tx = proc->timestamp_tx;
Raymond Knopp's avatar
Raymond Knopp committed
373

374
    if (rxtx(eNB,proc_rxtx,string) < 0) LOG_E(PHY,"eNB %d CC_id %d failed during execution\n",eNB->Mod_id,eNB->CC_id);
375
    LOG_D(PHY,"eNB_top out %p (proc %p, CC_id %d), frame %d, subframe %d, instance_cnt_prach %d\n",
Raymond Knopp's avatar
Raymond Knopp committed
376
	  (void*)pthread_self(), proc, eNB->CC_id, proc->frame_rx,proc->subframe_rx,proc->instance_cnt_prach);
377
  }
Raymond Knopp's avatar
Raymond Knopp committed
378 379
}

Wang Tsu-Han's avatar
Wang Tsu-Han committed
380
int wakeup_txfh(eNB_rxtx_proc_t *proc,RU_proc_t *ru_proc) {
381 382 383 384
  
  struct timespec wait;
  wait.tv_sec=0;
  wait.tv_nsec=5000000L;
Wang Tsu-Han's avatar
Wang Tsu-Han committed
385

386
  
387 388 389
  if(wait_on_condition(&ru_proc->mutex_eNBs,&ru_proc->cond_eNBs,&ru_proc->ru_tx_ready,"wakeup_txfh")<0) {
    LOG_E(PHY,"Frame %d, subframe %d: TX FH not ready\n", ru_proc->frame_tx, ru_proc->subframe_tx);
    return(-1);
390
  }
391 392
  if (release_thread(&ru_proc->mutex_eNBs,&ru_proc->ru_tx_ready,"wakeup_txfh")<0) return(-1);
  
393
  if (ru_proc->instance_cnt_eNBs == 0) {
Wang Tsu-Han's avatar
Wang Tsu-Han committed
394
    LOG_E(PHY,"Frame %d, subframe %d: TX FH thread busy, dropping Frame %d, subframe %d\n", ru_proc->frame_tx, ru_proc->subframe_tx, proc->frame_rx, proc->subframe_rx);
395 396
    return(-1);
  }
397 398 399 400 401 402 403
  if (pthread_mutex_timedlock(&ru_proc->mutex_eNBs,&wait) != 0) {
    LOG_E( PHY, "[eNB] ERROR pthread_mutex_lock for eNB TX1 thread %d (IC %d)\n", ru_proc->subframe_rx&1,ru_proc->instance_cnt_eNBs );
    exit_fun( "error locking mutex_eNB" );
    return(-1);
  }

    ++ru_proc->instance_cnt_eNBs;
Wang Tsu-Han's avatar
Wang Tsu-Han committed
404 405 406
    ru_proc->timestamp_tx = proc->timestamp_tx;
    ru_proc->subframe_tx  = proc->subframe_tx;
    ru_proc->frame_tx     = proc->frame_tx;
407 408 409 410 411 412 413 414 415 416 417 418 419
  
  // the thread can now be woken up
  if (pthread_cond_signal(&ru_proc->cond_eNBs) != 0) {
    LOG_E( PHY, "[eNB] ERROR pthread_cond_signal for eNB TXnp4 thread\n");
    exit_fun( "ERROR pthread_cond_signal" );
    return(-1);
  }
  
  pthread_mutex_unlock( &ru_proc->mutex_eNBs );

  return(0);
}

420 421 422 423
int wakeup_tx(PHY_VARS_eNB *eNB,RU_proc_t *ru_proc) {

  eNB_proc_t *proc=&eNB->proc;

424 425
  eNB_rxtx_proc_t *proc_rxtx1=&proc->proc_rxtx[1];//*proc_rxtx=&proc->proc_rxtx[proc->frame_rx&1];
  eNB_rxtx_proc_t *proc_rxtx0=&proc->proc_rxtx[0];
426 427 428 429 430 431 432

  LTE_DL_FRAME_PARMS *fp = &eNB->frame_parms;
  
  struct timespec wait;
  wait.tv_sec=0;
  wait.tv_nsec=5000000L;
  
433 434
  int pipe_ready_tx  = proc_rxtx1->pipe_ready;
  
435 436 437
  if(wait_on_condition(&proc_rxtx1->mutex_rxtx,&proc_rxtx1->cond_rxtx,&proc_rxtx1->pipe_ready,"wakeup_tx")<0) {
    LOG_E(PHY,"Frame %d, subframe %d: TX1 not ready\n",proc_rxtx1->frame_rx,proc_rxtx1->subframe_rx);
    return(-1);
438
  }
439 440
  if (release_thread(&proc_rxtx1->mutex_rxtx,&proc_rxtx1->pipe_ready,"wakeup_tx")<0)  return(-1);
  
441 442
  if (proc_rxtx1->instance_cnt_rxtx == 0) {
    LOG_E(PHY,"Frame %d, subframe %d: TX1 thread busy, dropping\n",proc_rxtx1->frame_rx,proc_rxtx1->subframe_rx);
443 444 445
    return(-1);
  }
  
446 447
  if (pthread_mutex_timedlock(&proc_rxtx1->mutex_rxtx,&wait) != 0) {
    LOG_E( PHY, "[eNB] ERROR pthread_mutex_lock for eNB TX1 thread %d (IC %d)\n", proc_rxtx1->subframe_rx&1,proc_rxtx1->instance_cnt_rxtx );
448
    exit_fun( "error locking mutex_tx" );
449 450 451
    return(-1);
  }

452
  ++proc_rxtx1->instance_cnt_rxtx;
453 454

  
455 456 457 458 459
  proc_rxtx1->subframe_rx   = proc_rxtx0->subframe_rx;
  proc_rxtx1->frame_rx      = proc_rxtx0->frame_rx;
  proc_rxtx1->subframe_tx   = proc_rxtx0->subframe_tx;
  proc_rxtx1->frame_tx      = proc_rxtx0->frame_tx;
  proc_rxtx1->timestamp_tx  = proc_rxtx0->timestamp_tx;
460 461
  
  // the thread can now be woken up
462
  if (pthread_cond_signal(&proc_rxtx1->cond_rxtx) != 0) {
463
    LOG_E( PHY, "[eNB] ERROR pthread_cond_signal for eNB TXnp4 thread\n");
464 465 466 467
    exit_fun( "ERROR pthread_cond_signal" );
    return(-1);
  }
  
468
  pthread_mutex_unlock( &proc_rxtx1->mutex_rxtx );
469 470 471

  return(0);
}
Raymond Knopp's avatar
Raymond Knopp committed
472

473 474 475
int wakeup_rxtx(PHY_VARS_eNB *eNB,RU_t *ru) {

  eNB_proc_t *proc=&eNB->proc;
476
  RU_proc_t *ru_proc=&ru->proc;
477

478
  eNB_rxtx_proc_t *proc_rxtx0=&proc->proc_rxtx[0];//*proc_rxtx=&proc->proc_rxtx[proc->frame_rx&1];
Wang Tsu-Han's avatar
Wang Tsu-Han committed
479
  //eNB_rxtx_proc_t *proc_rxtx1=&proc->proc_rxtx[1];
480
  
481 482

  LTE_DL_FRAME_PARMS *fp = &eNB->frame_parms;
483 484 485 486

  int i;
  struct timespec wait;
  
487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507
  pthread_mutex_lock(&proc->mutex_RU);
  for (i=0;i<eNB->num_RU;i++) {
    if (ru == eNB->RU_list[i]) {
      if ((proc->RU_mask&(1<<i)) > 0)
	LOG_E(PHY,"eNB %d frame %d, subframe %d : previous information from RU %d (num_RU %d,mask %x) has not been served yet!\n",
	      eNB->Mod_id,proc->frame_rx,proc->subframe_rx,ru->idx,eNB->num_RU,proc->RU_mask);
      proc->RU_mask |= (1<<i);
    }
  }
  if (proc->RU_mask != (1<<eNB->num_RU)-1) {  // not all RUs have provided their information so return
    pthread_mutex_unlock(&proc->mutex_RU);
    return(0);
  }
  else { // all RUs have provided their information so continue on and wakeup eNB processing
    proc->RU_mask = 0;
    pthread_mutex_unlock(&proc->mutex_RU);
  }




508 509
  wait.tv_sec=0;
  wait.tv_nsec=5000000L;
510

511
  
512 513 514
  if(wait_on_condition(&proc_rxtx0->mutex_rxtx,&proc_rxtx0->cond_rxtx,&proc_rxtx0->pipe_ready,"wakeup_rxtx")<0) {
    LOG_E(PHY,"Frame %d, subframe %d: RXTX0 not ready\n",proc_rxtx0->frame_rx,proc_rxtx0->subframe_rx);
    return(-1);
515
  }
516 517
  if (release_thread(&proc_rxtx0->mutex_rxtx,&proc_rxtx0->pipe_ready,"wakeup_rxtx")<0) return(-1);
  
518 519
  if (proc_rxtx0->instance_cnt_rxtx == 0) {
    LOG_E(PHY,"Frame %d, subframe %d: RXTX0 thread busy, dropping\n",proc_rxtx0->frame_rx,proc_rxtx0->subframe_rx);
520 521 522 523 524
    return(-1);
  }

  // wake up TX for subframe n+4
  // lock the TX mutex and make sure the thread is ready
525 526
  if (pthread_mutex_timedlock(&proc_rxtx0->mutex_rxtx,&wait) != 0) {
    LOG_E( PHY, "[eNB] ERROR pthread_mutex_lock for eNB RXTX thread %d (IC %d)\n", proc_rxtx0->subframe_rx&1,proc_rxtx0->instance_cnt_rxtx );
527 528 529 530
    exit_fun( "error locking mutex_rxtx" );
    return(-1);
  }
  
531

532
  ++proc_rxtx0->instance_cnt_rxtx;
533 534 535 536 537
  
  // We have just received and processed the common part of a subframe, say n. 
  // TS_rx is the last received timestamp (start of 1st slot), TS_tx is the desired 
  // transmitted timestamp of the next TX slot (first).
  // The last (TS_rx mod samples_per_frame) was n*samples_per_tti, 
Raymond Knopp's avatar
Raymond Knopp committed
538 539
  // we want to generate subframe (n+4), so TS_tx = TX_rx+4*samples_per_tti,
  // and proc->subframe_tx = proc->subframe_rx+4
540
  /*proc_rxtx->timestamp_tx = proc->timestamp_rx + (4*fp->samples_per_tti);
541 542 543 544
  proc_rxtx->frame_rx     = proc->frame_rx;
  proc_rxtx->subframe_rx  = proc->subframe_rx;
  proc_rxtx->frame_tx     = (proc_rxtx->subframe_rx > 5) ? (proc_rxtx->frame_rx+1)&1023 : proc_rxtx->frame_rx;
  proc_rxtx->subframe_tx  = (proc_rxtx->subframe_rx + 4)%10;
545 546
  */
  
547 548 549 550 551 552 553
  proc_rxtx0->subframe_rx = ru_proc->subframe_rx;
  proc_rxtx0->frame_rx    = ru_proc->frame_rx;
  proc_rxtx0->subframe_tx = (ru_proc->subframe_rx+4)%10;
  proc_rxtx0->frame_tx    = (ru_proc->subframe_rx>5) ? (1+ru_proc->frame_rx)&1023 : ru_proc->frame_rx;
  proc->frame_tx         = proc_rxtx0->frame_tx;
  proc->frame_rx         = proc_rxtx0->frame_rx;
  proc_rxtx0->timestamp_tx = ru_proc->timestamp_rx+(4*fp->samples_per_tti);
554 555
  
  // the thread can now be woken up
556
  if (pthread_cond_signal(&proc_rxtx0->cond_rxtx) != 0) {
557 558 559 560 561
    LOG_E( PHY, "[eNB] ERROR pthread_cond_signal for eNB RXn-TXnp4 thread\n");
    exit_fun( "ERROR pthread_cond_signal" );
    return(-1);
  }
  
562
  pthread_mutex_unlock( &proc_rxtx0->mutex_rxtx );
563 564 565 566

  return(0);
}

567
void wakeup_prach_eNB(PHY_VARS_eNB *eNB,RU_t *ru,int frame,int subframe) {
568 569 570

  eNB_proc_t *proc = &eNB->proc;
  LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms;
571
  int i;
572

573 574 575 576
  if (ru!=NULL) {
    pthread_mutex_lock(&proc->mutex_RU_PRACH);
    for (i=0;i<eNB->num_RU;i++) {
      if (ru == eNB->RU_list[i]) {
Raymond Knopp's avatar
Raymond Knopp committed
577
	LOG_D(PHY,"frame %d, subframe %d: RU %d for eNB %d signals PRACH (mask %x, num_RU %d)\n",frame,subframe,i,eNB->Mod_id,proc->RU_mask_prach,eNB->num_RU);
578 579
	if ((proc->RU_mask_prach&(1<<i)) > 0)
	  LOG_E(PHY,"eNB %d frame %d, subframe %d : previous information (PRACH) from RU %d (num_RU %d, mask %x) has not been served yet!\n",
580
		eNB->Mod_id,frame,subframe,ru->idx,eNB->num_RU,proc->RU_mask_prach);
581 582 583 584 585
	proc->RU_mask_prach |= (1<<i);
      }
    }
    if (proc->RU_mask_prach != (1<<eNB->num_RU)-1) {  // not all RUs have provided their information so return
      pthread_mutex_unlock(&proc->mutex_RU_PRACH);
Raymond Knopp's avatar
Raymond Knopp committed
586
      return;
587 588 589 590 591 592 593
    }
    else { // all RUs have provided their information so continue on and wakeup eNB processing
      proc->RU_mask_prach = 0;
      pthread_mutex_unlock(&proc->mutex_RU_PRACH);
    }
  }
    
594
  // check if we have to detect PRACH first
595
  if (is_prach_subframe(fp,frame,subframe)>0) { 
596
    LOG_D(PHY,"Triggering prach processing, frame %d, subframe %d\n",frame,subframe);
597
    if (proc->instance_cnt_prach == 0) {
598
      LOG_W(PHY,"[eNB] Frame %d Subframe %d, dropping PRACH\n", frame,subframe);
599 600 601 602 603 604 605 606 607 608 609 610
      return;
    }
    
    // wake up thread for PRACH RX
    if (pthread_mutex_lock(&proc->mutex_prach) != 0) {
      LOG_E( PHY, "[eNB] ERROR pthread_mutex_lock for eNB PRACH thread %d (IC %d)\n", proc->thread_index, proc->instance_cnt_prach);
      exit_fun( "error locking mutex_prach" );
      return;
    }
    
    ++proc->instance_cnt_prach;
    // set timing for prach thread
611 612
    proc->frame_prach = frame;
    proc->subframe_prach = subframe;
613 614 615 616 617 618 619 620 621 622 623 624 625
    
    // the thread can now be woken up
    if (pthread_cond_signal(&proc->cond_prach) != 0) {
      LOG_E( PHY, "[eNB] ERROR pthread_cond_signal for eNB PRACH thread %d\n", proc->thread_index);
      exit_fun( "ERROR pthread_cond_signal" );
      return;
    }
    
    pthread_mutex_unlock( &proc->mutex_prach );
  }

}

626 627 628 629 630 631 632 633 634 635 636
#ifdef Rel14
void wakeup_prach_eNB_br(PHY_VARS_eNB *eNB,RU_t *ru,int frame,int subframe) {

  eNB_proc_t *proc = &eNB->proc;
  LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms;
  int i;

  if (ru!=NULL) {
    pthread_mutex_lock(&proc->mutex_RU_PRACH_br);
    for (i=0;i<eNB->num_RU;i++) {
      if (ru == eNB->RU_list[i]) {
Raymond Knopp's avatar
Raymond Knopp committed
637
	LOG_D(PHY,"frame %d, subframe %d: RU %d for eNB %d signals PRACH BR (mask %x, num_RU %d)\n",frame,subframe,i,eNB->Mod_id,proc->RU_mask_prach_br,eNB->num_RU);
638 639 640 641 642 643 644 645
	if ((proc->RU_mask_prach_br&(1<<i)) > 0)
	  LOG_E(PHY,"eNB %d frame %d, subframe %d : previous information (PRACH BR) from RU %d (num_RU %d, mask %x) has not been served yet!\n",
		eNB->Mod_id,frame,subframe,ru->idx,eNB->num_RU,proc->RU_mask_prach_br);
	proc->RU_mask_prach_br |= (1<<i);
      }
    }
    if (proc->RU_mask_prach_br != (1<<eNB->num_RU)-1) {  // not all RUs have provided their information so return
      pthread_mutex_unlock(&proc->mutex_RU_PRACH_br);
Raymond Knopp's avatar
Raymond Knopp committed
646
      return;
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
    }
    else { // all RUs have provided their information so continue on and wakeup eNB processing
      proc->RU_mask_prach_br = 0;
      pthread_mutex_unlock(&proc->mutex_RU_PRACH_br);
    }
  }
    
  // check if we have to detect PRACH first
  if (is_prach_subframe(fp,frame,subframe)>0) { 
    LOG_D(PHY,"Triggering prach br processing, frame %d, subframe %d\n",frame,subframe);
    if (proc->instance_cnt_prach_br == 0) {
      LOG_W(PHY,"[eNB] Frame %d Subframe %d, dropping PRACH BR\n", frame,subframe);
      return;
    }
    
    // wake up thread for PRACH RX
    if (pthread_mutex_lock(&proc->mutex_prach_br) != 0) {
      LOG_E( PHY, "[eNB] ERROR pthread_mutex_lock for eNB PRACH thread %d (IC %d)\n", proc->thread_index, proc->instance_cnt_prach_br);
      exit_fun( "error locking mutex_prach" );
      return;
    }
    
    ++proc->instance_cnt_prach_br;
    // set timing for prach thread
    proc->frame_prach_br = frame;
    proc->subframe_prach_br = subframe;
    
    // the thread can now be woken up
    if (pthread_cond_signal(&proc->cond_prach_br) != 0) {
      LOG_E( PHY, "[eNB] ERROR pthread_cond_signal for eNB PRACH BR thread %d\n", proc->thread_index);
      exit_fun( "ERROR pthread_cond_signal" );
      return;
    }
    
    pthread_mutex_unlock( &proc->mutex_prach_br );
  }

}
#endif

687 688 689 690 691
/*!
 * \brief The prach receive thread of eNB.
 * \param param is a \ref eNB_proc_t structure which contains the info what to process.
 * \returns a pointer to an int. The storage is not on the heap and must not be freed.
 */
692
static void* eNB_thread_prach( void* param ) {
693 694
  static int eNB_thread_prach_status;

695 696 697

  PHY_VARS_eNB *eNB= (PHY_VARS_eNB *)param;
  eNB_proc_t *proc = &eNB->proc;
Raymond Knopp's avatar
Raymond Knopp committed
698

699 700 701
  // set default return value
  eNB_thread_prach_status = 0;

702
  thread_top_init("eNB_thread_prach",1,500000,1000000,20000000);
703

704
  //wait_sync("eNB_thread_prach");
705

706 707 708 709
  while (!oai_exit) {
    
    if (oai_exit) break;

710
    
Raymond Knopp's avatar
Raymond Knopp committed
711
    if (wait_on_condition(&proc->mutex_prach,&proc->cond_prach,&proc->instance_cnt_prach,"eNB_prach_thread") < 0) break;
712 713

    LOG_D(PHY,"Running eNB prach procedures\n");
714 715 716 717 718
    prach_procedures(eNB
#ifdef Rel14
		     ,0
#endif
		     );
719
    
Raymond Knopp's avatar
Raymond Knopp committed
720
    if (release_thread(&proc->mutex_prach,&proc->instance_cnt_prach,"eNB_prach_thread") < 0) break;
721
  }
722

723
  LOG_I(PHY, "Exiting eNB thread PRACH\n");
Raymond Knopp's avatar
Raymond Knopp committed
724

725 726
  eNB_thread_prach_status = 0;
  return &eNB_thread_prach_status;
727 728
}

729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744
#ifdef Rel14
/*!
 * \brief The prach receive thread of eNB for BL/CE UEs.
 * \param param is a \ref eNB_proc_t structure which contains the info what to process.
 * \returns a pointer to an int. The storage is not on the heap and must not be freed.
 */
static void* eNB_thread_prach_br( void* param ) {
  static int eNB_thread_prach_status;


  PHY_VARS_eNB *eNB= (PHY_VARS_eNB *)param;
  eNB_proc_t *proc = &eNB->proc;

  // set default return value
  eNB_thread_prach_status = 0;

745
  thread_top_init("eNB_thread_prach_br",1,500000,1000000,20000000);
746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766

  while (!oai_exit) {
    
    if (oai_exit) break;
    

    if (wait_on_condition(&proc->mutex_prach_br,&proc->cond_prach_br,&proc->instance_cnt_prach_br,"eNB_prach_thread_br") < 0) break;

    LOG_D(PHY,"Running eNB prach procedures for BL/CE UEs\n");
    prach_procedures(eNB,1);
    
    if (release_thread(&proc->mutex_prach_br,&proc->instance_cnt_prach_br,"eNB_prach_thread_br") < 0) break;
  }

  LOG_I(PHY, "Exiting eNB thread PRACH BR\n");

  eNB_thread_prach_status = 0;
  return &eNB_thread_prach_status;
}

#endif
Raymond Knopp's avatar
Raymond Knopp committed
767

Raymond Knopp's avatar
Raymond Knopp committed
768

769

Wang Tsu-Han's avatar
Wang Tsu-Han committed
770
extern void init_td_thread(PHY_VARS_eNB *);
Eurecom's avatar
Eurecom committed
771
extern void init_te_thread(PHY_VARS_eNB *);
Wang Tsu-Han's avatar
Wang Tsu-Han committed
772 773
extern void kill_td_thread(PHY_VARS_eNB *);
extern void kill_te_thread(PHY_VARS_eNB *);
774 775
//////////////////////////////////////need to modified////////////////*****

776
static void* process_stats_thread(void* param) {
777 778 779

  PHY_VARS_eNB     *eNB      = (PHY_VARS_eNB*)param;

780
  wait_sync("process_stats_thread");
781 782 783 784 785

  while (!oai_exit) {
     sleep(1);
     if (opp_enabled == 1) {
       if (eNB->td) print_meas(&eNB->ulsch_decoding_stats,"ulsch_decoding",NULL,NULL);
786 787
       if (eNB->te)
       {
Wang Tsu-Han's avatar
Wang Tsu-Han committed
788
         print_meas(&eNB->dlsch_turbo_encoding_preperation_stats,"dlsch_coding_crc",NULL,NULL);
789
         print_meas(&eNB->dlsch_turbo_encoding_segmentation_stats,"dlsch_segmentation",NULL,NULL);
790
         print_meas(&eNB->dlsch_encoding_stats,"dlsch_encoding",NULL,NULL);
791
         print_meas(&eNB->dlsch_turbo_encoding_signal_stats,"coding_signal",NULL,NULL);
792 793
         print_meas(&eNB->dlsch_turbo_encoding_main_stats,"coding_main",NULL,NULL);
         print_meas(&eNB->dlsch_turbo_encoding_waiting_stats,"coding_wait",NULL,NULL);
794 795 796 797
         print_meas(&eNB->dlsch_turbo_encoding_wakeup_stats0,"coding_worker_0",NULL,NULL);
         print_meas(&eNB->dlsch_turbo_encoding_wakeup_stats1,"coding_worker_1",NULL,NULL);
	   }
       print_meas(&eNB->dlsch_modulation_stats,"dlsch_modulation",NULL,NULL);
798 799 800 801 802
     }
  }
  return(NULL);
}

803

804
void init_eNB_proc(int inst) {
805
  
Rohit Gupta's avatar
Rohit Gupta committed
806
  int i=0;
807
  int CC_id;
808 809
  PHY_VARS_eNB *eNB;
  eNB_proc_t *proc;
810
  eNB_rxtx_proc_t *proc_rxtx;
Wang Tsu-Han's avatar
Wang Tsu-Han committed
811
  pthread_attr_t *attr0=NULL,*attr1=NULL,*attr_prach=NULL;
812 813 814
#ifdef Rel14
  pthread_attr_t *attr_prach_br=NULL;
#endif
Raymond Knopp's avatar
Raymond Knopp committed
815

816
  for (CC_id=0; CC_id<RC.nb_CC[inst]; CC_id++) {
817
    eNB = RC.eNB[inst][CC_id];
laurent's avatar
laurent committed
818
#ifndef OCP_FRAMEWORK
819
    LOG_I(PHY,"Initializing eNB processes %d CC_id %d \n",inst,CC_id);
laurent's avatar
laurent committed
820
#endif
821
    proc = &eNB->proc;
Raymond Knopp's avatar
Raymond Knopp committed
822

823
    proc_rxtx                      = proc->proc_rxtx;
824 825
    proc_rxtx[0].instance_cnt_rxtx = -1;
    proc_rxtx[1].instance_cnt_rxtx = -1;
826 827
    proc_rxtx[0].pipe_ready        = 0;
    proc_rxtx[1].pipe_ready        = 0;
828
    proc->instance_cnt_prach       = -1;
829
    proc->instance_cnt_asynch_rxtx = -1;
Eurecom's avatar
Eurecom committed
830
    proc->instance_cnt_synch       = -1;
831
    proc->CC_id                    = CC_id;    
832

Raymond Knopp's avatar
Raymond Knopp committed
833 834
    proc->first_rx=1;
    proc->first_tx=1;
835 836
    proc->RU_mask=0;
    proc->RU_mask_prach=0;
Raymond Knopp's avatar
Raymond Knopp committed
837

838
    pthread_mutex_init( &eNB->UL_INFO_mutex, NULL);
839 840 841 842
    pthread_mutex_init( &proc_rxtx[0].mutex_rxtx, NULL);
    pthread_mutex_init( &proc_rxtx[1].mutex_rxtx, NULL);
    pthread_cond_init( &proc_rxtx[0].cond_rxtx, NULL);
    pthread_cond_init( &proc_rxtx[1].cond_rxtx, NULL);
Raymond Knopp's avatar
Raymond Knopp committed
843 844 845

    pthread_mutex_init( &proc->mutex_prach, NULL);
    pthread_mutex_init( &proc->mutex_asynch_rxtx, NULL);
846 847
    pthread_mutex_init( &proc->mutex_RU,NULL);
    pthread_mutex_init( &proc->mutex_RU_PRACH,NULL);
Raymond Knopp's avatar
Raymond Knopp committed
848

849
    pthread_cond_init( &proc->cond_prach, NULL);
850
    pthread_cond_init( &proc->cond_asynch_rxtx, NULL);
851 852 853 854 855

    pthread_attr_init( &proc->attr_prach);
    pthread_attr_init( &proc->attr_asynch_rxtx);
    pthread_attr_init( &proc_rxtx[0].attr_rxtx);
    pthread_attr_init( &proc_rxtx[1].attr_rxtx);
856 857 858 859 860 861 862 863
#ifdef Rel14
    proc->instance_cnt_prach_br    = -1;
    proc->RU_mask_prach_br=0;
    pthread_mutex_init( &proc->mutex_prach_br, NULL);
    pthread_mutex_init( &proc->mutex_RU_PRACH_br,NULL);
    pthread_cond_init( &proc->cond_prach_br, NULL);
    pthread_attr_init( &proc->attr_prach_br);
#endif
864
#ifndef DEADLINE_SCHEDULER
Raymond Knopp's avatar
Raymond Knopp committed
865 866 867
    attr0       = &proc_rxtx[0].attr_rxtx;
    attr1       = &proc_rxtx[1].attr_rxtx;
    attr_prach  = &proc->attr_prach;
868 869 870 871
#ifdef Rel14
    attr_prach_br  = &proc->attr_prach_br;
#endif

Raymond Knopp's avatar
Raymond Knopp committed
872 873
    //    attr_td     = &proc->attr_td;
    //    attr_te     = &proc->attr_te; 
Raymond Knopp's avatar
Raymond Knopp committed
874
#endif
875 876 877 878
    //////////////////////////////////////need to modified////////////////*****
    if(get_nprocs() > 2 && codingw)
    {
      init_te_thread(eNB);
Wang Tsu-Han's avatar
Wang Tsu-Han committed
879
      init_td_thread(eNB);
880 881
    }
    //////////////////////////////////////need to modified////////////////*****
882
	pthread_create( &proc_rxtx[0].pthread_rxtx, attr0, eNB_thread_rxtx, proc );
883
	pthread_create( &proc_rxtx[1].pthread_rxtx, attr1, tx_thread, proc);
884 885 886 887
    if (eNB->single_thread_flag==0) {
      pthread_create( &proc_rxtx[0].pthread_rxtx, attr0, eNB_thread_rxtx, &proc_rxtx[0] );
      pthread_create( &proc_rxtx[1].pthread_rxtx, attr1, eNB_thread_rxtx, &proc_rxtx[1] );
    }
888
    pthread_create( &proc->pthread_prach, attr_prach, eNB_thread_prach, eNB );
889 890 891
#ifdef Rel14
    pthread_create( &proc->pthread_prach_br, attr_prach_br, eNB_thread_prach_br, eNB );
#endif
892
    char name[16];
893 894 895 896 897 898
    if (eNB->single_thread_flag==0) {
      snprintf( name, sizeof(name), "RXTX0 %d", i );
      pthread_setname_np( proc_rxtx[0].pthread_rxtx, name );
      snprintf( name, sizeof(name), "RXTX1 %d", i );
      pthread_setname_np( proc_rxtx[1].pthread_rxtx, name );
    }
899 900

    AssertFatal(proc->instance_cnt_prach == -1,"instance_cnt_prach = %d\n",proc->instance_cnt_prach);
901
	
902

Wang Tsu-Han's avatar
Wang Tsu-Han committed
903
    if (opp_enabled == 1) pthread_create(&proc->process_stats_thread,NULL,process_stats_thread,(void*)eNB);
904

905
    
906
  }
907

908
  //for multiple CCs: setup master and slaves
909 910 911
  /* 
     for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
     eNB = PHY_vars_eNB_g[inst][CC_id];
912

913 914 915
     if (eNB->node_timing == synch_to_ext_device) { //master
     eNB->proc.num_slaves = MAX_NUM_CCs-1;
     eNB->proc.slave_proc = (eNB_proc_t**)malloc(eNB->proc.num_slaves*sizeof(eNB_proc_t*));
916

917 918 919 920 921 922 923
     for (i=0; i< eNB->proc.num_slaves; i++) {
     if (i < CC_id)  eNB->proc.slave_proc[i] = &(PHY_vars_eNB_g[inst][i]->proc);
     if (i >= CC_id)  eNB->proc.slave_proc[i] = &(PHY_vars_eNB_g[inst][i+1]->proc);
     }
     }
     }
  */
924

925 926 927 928
  /* setup PHY proc TX sync mechanism */
  pthread_mutex_init(&sync_phy_proc.mutex_phy_proc_tx, NULL);
  pthread_cond_init(&sync_phy_proc.cond_phy_proc_tx, NULL);
  sync_phy_proc.phy_proc_CC_id = 0;
929 930
  
  
931 932
}

933

934

935 936 937
/*!
 * \brief Terminate eNB TX and RX threads.
 */
938
void kill_eNB_proc(int inst) {
939

940
  int *status;
941 942
  PHY_VARS_eNB *eNB;
  eNB_proc_t *proc;
943
  eNB_rxtx_proc_t *proc_rxtx;
944
  for (int CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
945
    eNB=RC.eNB[inst][CC_id];
946 947
    
    proc = &eNB->proc;
948
    proc_rxtx = &proc->proc_rxtx[0];
949
    
950

Wang Tsu-Han's avatar
Wang Tsu-Han committed
951 952
    kill_td_thread(eNB);
    kill_te_thread(eNB);
953
    LOG_I(PHY, "Killing TX CC_id %d inst %d\n", CC_id, inst );
Wang Tsu-Han's avatar
Wang Tsu-Han committed
954 955
    proc_rxtx[0].instance_cnt_rxtx = 0; // FIXME data race!
    proc_rxtx[1].instance_cnt_rxtx = 0; // FIXME data race!
956 957 958 959
    if (eNB->single_thread_flag==0) {
      pthread_cond_signal( &proc_rxtx[0].cond_rxtx );    
      pthread_cond_signal( &proc_rxtx[1].cond_rxtx );
    }
Raymond Knopp's avatar
Raymond Knopp committed
960 961
    proc->instance_cnt_prach = 0;
    pthread_cond_signal( &proc->cond_prach );
962

963
    pthread_cond_broadcast(&sync_phy_proc.cond_phy_proc_tx);
964
    pthread_join( proc->pthread_prach, (void**)&status );    
965

966
    LOG_I(PHY, "Destroying prach mutex/cond\n");
967
    pthread_mutex_destroy( &proc->mutex_prach );
968 969
    pthread_cond_destroy( &proc->cond_prach );
#ifdef Rel14
970
    proc->instance_cnt_prach_br = 0;
971 972 973 974 975
    pthread_cond_signal( &proc->cond_prach_br );
    pthread_join( proc->pthread_prach_br, (void**)&status );    
    pthread_mutex_destroy( &proc->mutex_prach_br );
    pthread_cond_destroy( &proc->cond_prach_br );
#endif         
976
    LOG_I(PHY, "Destroying UL_INFO mutex\n");
977
    pthread_mutex_destroy(&eNB->UL_INFO_mutex);
978
    int i;
Wang Tsu-Han's avatar
Wang Tsu-Han committed
979
    for (i=0;i<2;i++) {
980
      pthread_cond_signal( &proc_rxtx[i].cond_rxtx );
Wang Tsu-Han's avatar
Wang Tsu-Han committed
981 982 983 984 985
      LOG_I(PHY, "Joining rxtx[%d] mutex/cond\n",i);
      pthread_join( proc_rxtx[i].pthread_rxtx, (void**)&status );
      LOG_I(PHY, "Destroying rxtx[%d] mutex/cond\n",i);
      pthread_mutex_destroy( &proc_rxtx[i].mutex_rxtx );
      pthread_cond_destroy( &proc_rxtx[i].cond_rxtx );
986
    }
987
  }
988 989
}

990

991 992 993


void reset_opp_meas(void) {
994

995 996 997 998 999
  int sfn;
  reset_meas(&softmodem_stats_mt);
  reset_meas(&softmodem_stats_hw);
  
  for (sfn=0; sfn < 10; sfn++) {
1000
    reset_meas(&softmodem_stats_rxtx_sf);
1001
    reset_meas(&softmodem_stats_rx_sf);
1002 1003 1004
  }
}

1005

1006 1007 1008 1009 1010 1011 1012
void print_opp_meas(void) {

  int sfn=0;
  print_meas(&softmodem_stats_mt, "Main ENB Thread", NULL, NULL);
  print_meas(&softmodem_stats_hw, "HW Acquisation", NULL, NULL);
  
  for (sfn=0; sfn < 10; sfn++) {
1013
    print_meas(&softmodem_stats_rxtx_sf,"[eNB][total_phy_proc_rxtx]",NULL, NULL);
1014
    print_meas(&softmodem_stats_rx_sf,"[eNB][total_phy_proc_rx]",NULL,NULL);
1015 1016
  }
}
1017

1018
void init_transport(PHY_VARS_eNB *eNB) {
1019

1020 1021 1022
  int i;
  int j;
  LTE_DL_FRAME_PARMS *fp = &eNB->frame_parms;
1023

1024 1025 1026 1027 1028 1029
  for (i=0; i<NUMBER_OF_UE_MAX; i++) {
    LOG_I(PHY,"Allocating Transport Channel Buffers for DLSCH, UE %d\n",i);
    for (j=0; j<2; j++) {
      eNB->dlsch[i][j] = new_eNB_dlsch(1,8,NSOFT,fp->N_RB_DL,0,fp);
      if (!eNB->dlsch[i][j]) {
	LOG_E(PHY,"Can't get eNB dlsch structures for UE %d \n", i);
1030
	exit(-1);
1031 1032 1033
      } else {
	LOG_D(PHY,"dlsch[%d][%d] => %p\n",i,j,eNB->dlsch[i][j]);
	eNB->dlsch[i][j]->rnti=0;
1034 1035
      }
    }
1036 1037 1038 1039 1040 1041
    
    LOG_I(PHY,"Allocating Transport Channel Buffer for ULSCH, UE %d\n",i);
    eNB->ulsch[1+i] = new_eNB_ulsch(MAX_TURBO_ITERATIONS,fp->N_RB_UL, 0);
    
    if (!eNB->ulsch[1+i]) {
      LOG_E(PHY,"Can't get eNB ulsch structures\n");
1042 1043
      exit(-1);
    }
1044 1045 1046 1047
    
    // this is the transmission mode for the signalling channels
    // this will be overwritten with the real transmission mode by the RRC once the UE is connected
    eNB->transmission_mode[i] = fp->nb_antenna_ports_eNB==1 ? 1 : 2;
1048
  }
1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064
  // ULSCH for RA
  eNB->ulsch[0] = new_eNB_ulsch(MAX_TURBO_ITERATIONS, fp->N_RB_UL, 0);
  
  if (!eNB->ulsch[0]) {
    LOG_E(PHY,"Can't get eNB ulsch structures\n");
    exit(-1);
  }
  eNB->dlsch_SI  = new_eNB_dlsch(1,8,NSOFT,fp->N_RB_DL, 0, fp);
  LOG_D(PHY,"eNB %d.%d : SI %p\n",eNB->Mod_id,eNB->CC_id,eNB->dlsch_SI);
  eNB->dlsch_ra  = new_eNB_dlsch(1,8,NSOFT,fp->N_RB_DL, 0, fp);
  LOG_D(PHY,"eNB %d.%d : RA %p\n",eNB->Mod_id,eNB->CC_id,eNB->dlsch_ra);
  eNB->dlsch_MCH = new_eNB_dlsch(1,8,NSOFT,fp->N_RB_DL, 0, fp);
  LOG_D(PHY,"eNB %d.%d : MCH %p\n",eNB->Mod_id,eNB->CC_id,eNB->dlsch_MCH);
  
  
  eNB->rx_total_gain_dB=130;
1065
  
1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079
  for(i=0; i<NUMBER_OF_UE_MAX; i++)
    eNB->mu_mimo_mode[i].dl_pow_off = 2;
  
  eNB->check_for_total_transmissions = 0;
  
  eNB->check_for_MUMIMO_transmissions = 0;
  
  eNB->FULL_MUMIMO_transmissions = 0;
  
  eNB->check_for_SUMIMO_transmissions = 0;
  
  fp->pucch_config_common.deltaPUCCH_Shift = 1;
    
} 
Raymond Knopp's avatar
Raymond Knopp committed
1080 1081

void init_eNB_afterRU(void) {
1082

1083 1084
  int inst,CC_id,ru_id,i,aa;
  PHY_VARS_eNB *eNB;
1085 1086


1087 1088 1089 1090 1091 1092 1093
  for (inst=0;inst<RC.nb_inst;inst++) {
    for (CC_id=0;CC_id<RC.nb_CC[inst];CC_id++) {
      eNB                                  =  RC.eNB[inst][CC_id];
      phy_init_lte_eNB(eNB,0,0);
      // map antennas and PRACH signals to eNB RX
      AssertFatal(eNB->num_RU>0,"Number of RU attached to eNB %d is zero\n",eNB->Mod_id);
      LOG_I(PHY,"Mapping RX ports from %d RUs to eNB %d\n",eNB->num_RU,eNB->Mod_id);
1094
      eNB->frame_parms.nb_antennas_rx       = 0;
Raymond Knopp's avatar
Raymond Knopp committed
1095
      eNB->prach_vars.rxsigF[0] = (int16_t**)malloc16(64*sizeof(int16_t*));
1096 1097
#ifdef Rel14
      for (int ce_level=0;ce_level<4;ce_level++)
Raymond Knopp's avatar
Raymond Knopp committed
1098
	eNB->prach_vars_br.rxsigF[ce_level] = (int16_t**)malloc16(64*sizeof(int16_t*));
1099
#endif
1100 1101
      for (ru_id=0,aa=0;ru_id<eNB->num_RU;ru_id++) {
	eNB->frame_parms.nb_antennas_rx    += eNB->RU_list[ru_id]->nb_rx;
1102 1103 1104 1105 1106 1107 1108 1109 1110

	AssertFatal(eNB->RU_list[ru_id]->common.rxdataF!=NULL,
		    "RU %d : common.rxdataF is NULL\n",
		    eNB->RU_list[ru_id]->idx);

	AssertFatal(eNB->RU_list[ru_id]->prach_rxsigF!=NULL,
		    "RU %d : prach_rxsigF is NULL\n",
		    eNB->RU_list[ru_id]->idx);

1111 1112
	for (i=0;i<eNB->RU_list[ru_id]->nb_rx;aa++,i++) { 
	  LOG_I(PHY,"Attaching RU %d antenna %d to eNB antenna %d\n",eNB->RU_list[ru_id]->idx,i,aa);
Raymond Knopp's avatar
Raymond Knopp committed
1113 1114 1115 1116 1117
	  eNB->prach_vars.rxsigF[0][aa]    =  eNB->RU_list[ru_id]->prach_rxsigF[i];
#ifdef Rel14
	  for (int ce_level=0;ce_level<4;ce_level++)
	    eNB->prach_vars_br.rxsigF[ce_level][aa] = eNB->RU_list[ru_id]->prach_rxsigF_br[ce_level][i];
#endif
1118 1119 1120
	  eNB->common_vars.rxdataF[aa]     =  eNB->RU_list[ru_id]->common.rxdataF[i];
	}
      }
1121 1122 1123
      AssertFatal(eNB->frame_parms.nb_antennas_rx >0,
		  "inst %d, CC_id %d : nb_antennas_rx %d\n",inst,CC_id,eNB->frame_parms.nb_antennas_rx);
      LOG_I(PHY,"inst %d, CC_id %d : nb_antennas_rx %d\n",inst,CC_id,eNB->frame_parms.nb_antennas_rx);
1124 1125

      init_transport(eNB);
Raymond Knopp's avatar
Raymond Knopp committed
1126
      //init_precoding_weights(RC.eNB[inst][CC_id]);
1127 1128 1129
    }
    init_eNB_proc(inst);
  }
1130

1131
  for (ru_id=0;ru_id<RC.nb_RU;ru_id++) {
1132 1133

    AssertFatal(RC.ru[ru_id]!=NULL,"ru_id %d is null\n",ru_id);
1134
    
1135 1136 1137 1138
    RC.ru[ru_id]->wakeup_rxtx         = wakeup_rxtx;
    RC.ru[ru_id]->wakeup_prach_eNB    = wakeup_prach_eNB;
    RC.ru[ru_id]->wakeup_prach_eNB_br = wakeup_prach_eNB_br;
    RC.ru[ru_id]->eNB_top             = eNB_top;
1139 1140
  }
}
1141

1142
void init_eNB(int single_thread_flag,int wait_for_sync) {
1143
  
1144
  int CC_id;
1145
  int inst;
1146
  PHY_VARS_eNB *eNB;
Raymond Knopp's avatar
Raymond Knopp committed
1147

1148 1149
  if (RC.eNB == NULL) RC.eNB = (PHY_VARS_eNB***) malloc(RC.nb_L1_inst*sizeof(PHY_VARS_eNB **));
  for (inst=0;inst<RC.nb_L1_inst;inst++) {
1150
    if (RC.eNB[inst] == NULL) RC.eNB[inst] = (PHY_VARS_eNB**) malloc(RC.nb_CC[inst]*sizeof(PHY_VARS_eNB *));
1151
    for (CC_id=0;CC_id<RC.nb_L1_CC[inst];CC_id++) {
1152 1153
      if (RC.eNB[inst][CC_id] == NULL) RC.eNB[inst][CC_id] = (PHY_VARS_eNB*) malloc(sizeof(PHY_VARS_eNB));
      eNB                     = RC.eNB[inst][CC_id]; 
1154
      eNB->abstraction_flag   = 0;
Raymond Knopp's avatar
Raymond Knopp committed
1155
      eNB->single_thread_flag = single_thread_flag;
1156

1157

laurent's avatar
laurent committed
1158
#ifndef OCP_FRAMEWORK
1159
      LOG_I(PHY,"Initializing eNB %d CC_id %d\n",inst,CC_id);
laurent's avatar
laurent committed
1160
#endif
Raymond Knopp's avatar
Raymond Knopp committed
1161 1162


1163
      eNB->td                   = ulsch_decoding_data_all;//(get_nprocs()<=4) ? ulsch_decoding_data : ulsch_decoding_data_2thread;
1164
      eNB->te                   = dlsch_encoding_all;//(get_nprocs()<=4) ? dlsch_encoding : dlsch_encoding_2threads;
1165

1166
      
1167
      LOG_I(PHY,"Registering with MAC interface module\n");
1168 1169 1170 1171 1172 1173 1174 1175
      AssertFatal((eNB->if_inst         = IF_Module_init(inst))!=NULL,"Cannot register interface");
      eNB->if_inst->schedule_response   = schedule_response;
      eNB->if_inst->PHY_config_req      = phy_config_request;
      memset((void*)&eNB->UL_INFO,0,sizeof(eNB->UL_INFO));
      memset((void*)&eNB->Sched_INFO,0,sizeof(eNB->Sched_INFO));
      LOG_I(PHY,"Setting indication lists\n");
      eNB->UL_INFO.rx_ind.rx_pdu_list   = eNB->rx_pdu_list;
      eNB->UL_INFO.crc_ind.crc_pdu_list = eNB->crc_pdu_list;
1176 1177 1178 1179
      eNB->UL_INFO.sr_ind.sr_pdu_list = eNB->sr_pdu_list;
      eNB->UL_INFO.harq_ind.harq_pdu_list = eNB->harq_pdu_list;
      eNB->UL_INFO.cqi_ind.cqi_pdu_list = eNB->cqi_pdu_list;
      eNB->UL_INFO.cqi_ind.cqi_raw_pdu_list = eNB->cqi_raw_pdu_list;
1180 1181
    }

1182
  }
1183

1184

1185
  LOG_I(PHY,"[lte-softmodem.c] eNB structure allocated\n");
1186
  
1187 1188


1189 1190 1191
}


1192
void stop_eNB(int nb_inst) {
1193

1194
  for (int inst=0;inst<nb_inst;inst++) {
1195
    LOG_I(PHY,"Killing eNB %d processing threads\n",inst);
1196 1197
    kill_eNB_proc(inst);
  }
1198
}