lte-enb.c 45.7 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-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

#include "PHY/types.h"

47 48 49 50 51 52
#include "PHY/INIT/phy_init.h"

#include "PHY/defs_eNB.h"
#include "SCHED/sched_eNB.h"
#include "PHY/LTE_TRANSPORT/transport_proto.h"

53 54 55 56 57 58 59
#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

60
#include "PHY/LTE_TRANSPORT/if4_tools.h"
61
#include "PHY/LTE_TRANSPORT/if5_tools.h"
62

63 64 65 66 67 68 69 70
#include "PHY/phy_extern.h"


#include "LAYER2/MAC/mac.h"
#include "LAYER2/MAC/mac_extern.h"
#include "LAYER2/MAC/mac_proto.h"
#include "RRC/LTE/rrc_extern.h"
#include "PHY_INTERFACE/phy_interface.h"
71
#include "common/utils/LOG/log.h"
72 73 74
#include "UTIL/OTG/otg_tx.h"
#include "UTIL/OTG/otg_externs.h"
#include "UTIL/MATH/oml.h"
75
#include "common/utils/LOG/vcd_signal_dumper.h"
76 77
#include "UTIL/OPT/opt.h"
#include "enb_config.h"
78

79 80 81 82 83 84 85 86 87 88 89 90 91 92

#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
93 94
#include "T.h"

95 96 97 98 99 100 101 102 103 104
//#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;

105 106
// Fix per CC openair rf/if device update
// extern openair0_device openair0;
107

108

109 110 111 112 113 114 115 116
#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
117
extern int transmission_mode;
118

119 120
extern int oaisim_flag;

121 122 123
//uint16_t sf_ahead=4;
extern uint16_t sf_ahead;

124

125
//pthread_t                       main_eNB_thread;
126 127 128

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

/* 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;
141
} sync_phy_proc;
142

143 144
extern double cpuf;

145 146
void exit_fun(const char* s);

147
void init_eNB(int,int);
148
void stop_eNB(int nb_inst);
149

150
int wakeup_tx(PHY_VARS_eNB *eNB,RU_proc_t *ru_proc);
Wang Tsu-Han's avatar
Wang Tsu-Han committed
151
int wakeup_txfh(eNB_rxtx_proc_t *proc,RU_proc_t *ru_proc);
152
void wakeup_prach_eNB(PHY_VARS_eNB *eNB,RU_t *ru,int frame,int subframe);
153
#if (RRC_VERSION >= MAKE_VERSION(14, 0, 0))
154 155
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
156
extern int codingw;
157

158 159 160 161 162 163 164 165
extern uint8_t nfapi_mode;
extern void oai_subframe_ind(uint16_t sfn, uint16_t sf);
extern void add_subframe(uint16_t *frameP, uint16_t *subframeP, int offset);

//#define TICK_TO_US(ts) (ts.diff)
#define TICK_TO_US(ts) (ts.trials==0?0:ts.diff/ts.trials)


Raymond Knopp's avatar
Raymond Knopp committed
166 167
static inline int rxtx(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc, char *thread_name) {
  start_meas(&softmodem_stats_rxtx_sf);
168

169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206
  // *******************************************************************

  if (nfapi_mode == 1) {

    // I am a PNF and I need to let nFAPI know that we have a (sub)frame tick
    uint16_t frame = proc->frame_rx;
    uint16_t subframe = proc->subframe_rx;

    //add_subframe(&frame, &subframe, 4);

    //oai_subframe_ind(proc->frame_tx, proc->subframe_tx);
    //LOG_D(PHY, "oai_subframe_ind(frame:%u, subframe:%d) - NOT CALLED ********\n", frame, subframe);
    start_meas(&nfapi_meas);
    oai_subframe_ind(frame, subframe);
    stop_meas(&nfapi_meas);

    if (eNB->UL_INFO.rx_ind.rx_indication_body.number_of_pdus||
        eNB->UL_INFO.harq_ind.harq_indication_body.number_of_harqs ||
        eNB->UL_INFO.crc_ind.crc_indication_body.number_of_crcs ||
        eNB->UL_INFO.rach_ind.rach_indication_body.number_of_preambles ||
        eNB->UL_INFO.cqi_ind.number_of_cqis
       ) {
      LOG_D(PHY, "UL_info[rx_ind:%05d:%d harqs:%05d:%d crcs:%05d:%d preambles:%05d:%d cqis:%d] RX:%04d%d TX:%04d%d num_pdcch_symbols:%d\n", 
          NFAPI_SFNSF2DEC(eNB->UL_INFO.rx_ind.sfn_sf),   eNB->UL_INFO.rx_ind.rx_indication_body.number_of_pdus, 
          NFAPI_SFNSF2DEC(eNB->UL_INFO.harq_ind.sfn_sf), eNB->UL_INFO.harq_ind.harq_indication_body.number_of_harqs, 
          NFAPI_SFNSF2DEC(eNB->UL_INFO.crc_ind.sfn_sf),  eNB->UL_INFO.crc_ind.crc_indication_body.number_of_crcs, 
          NFAPI_SFNSF2DEC(eNB->UL_INFO.rach_ind.sfn_sf), eNB->UL_INFO.rach_ind.rach_indication_body.number_of_preambles,
          eNB->UL_INFO.cqi_ind.number_of_cqis, 
          proc->frame_rx, proc->subframe_rx, 
      proc->frame_tx, proc->subframe_tx, eNB->pdcch_vars[proc->subframe_tx&1].num_pdcch_symbols);
    }
  }

  if (nfapi_mode == 1 && eNB->pdcch_vars[proc->subframe_tx&1].num_pdcch_symbols == 0) {
    LOG_E(PHY, "eNB->pdcch_vars[proc->subframe_tx&1].num_pdcch_symbols == 0");
    return 0;
  }

Raymond Knopp's avatar
Raymond Knopp committed
207 208
  // ****************************************
  // Common RX procedures subframe n
209

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

212
  // if this is IF5 or 3GPP_eNB
213
  if (eNB && eNB->RU_list && eNB->RU_list[0] && eNB->RU_list[0]->function < NGFI_RAU_IF4p5) {
214
    wakeup_prach_eNB(eNB,NULL,proc->frame_rx,proc->subframe_rx);
215
#if (RRC_VERSION >= MAKE_VERSION(14, 0, 0))
216 217 218
    wakeup_prach_eNB_br(eNB,NULL,proc->frame_rx,proc->subframe_rx);
#endif
  }
219

220
  release_UE_in_freeList(eNB->Mod_id);
221

Raymond Knopp's avatar
Raymond Knopp committed
222
  // UE-specific RX processing for subframe n
223
  if (nfapi_mode == 0 || nfapi_mode == 1) {
224
    phy_procedures_eNB_uespec_RX(eNB, proc);
225
  }
226
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_DLSCH_ULSCH_SCHEDULER , 1 );
227

Wang Tsu-Han's avatar
Wang Tsu-Han committed
228
  if(!eNB->single_thread_flag && get_nprocs() >= 8){
WANG Tsu-Han's avatar
WANG Tsu-Han committed
229 230 231 232 233
    if(wait_on_condition(&proc[1].mutex_rxtx,&proc[1].cond_rxtx,&proc[1].pipe_ready,"wakeup_tx")<0) {
      LOG_E(PHY,"Frame %d, subframe %d: TX1 not ready\n",proc[1].frame_rx,proc[1].subframe_rx);
      return(-1);
    }
    if (release_thread(&proc[1].mutex_rxtx,&proc[1].pipe_ready,"wakeup_tx")<0)  return(-1);
234
  }
235 236

  pthread_mutex_lock(&eNB->UL_INFO_mutex);
237

238 239 240 241
  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;
242

243
  eNB->if_inst->UL_indication(&eNB->UL_INFO);
244

245
  pthread_mutex_unlock(&eNB->UL_INFO_mutex);
246 247
  /* this conflict resolution may be totally wrong, to be tested */
  /* CONFLICT RESOLUTION: BEGIN */
248
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_DLSCH_ULSCH_SCHEDULER , 0 );
249
  if(oai_exit) return(-1);
Wang Tsu-Han's avatar
Wang Tsu-Han committed
250
  if(eNB->single_thread_flag || get_nprocs() <= 4){
251
#ifndef PHY_TX_THREAD
252
    phy_procedures_eNB_TX(eNB, proc, 1);
253
#endif
254
  }
255 256 257
  /* CONFLICT RESOLUTION: what about this release_thread call, has it to be done? if yes, where? */
  //if (release_thread(&proc->mutex_rxtx,&proc->instance_cnt_rxtx,thread_name)<0) return(-1);
  /* CONFLICT RESOLUTION: END */
Raymond Knopp's avatar
Raymond Knopp committed
258 259

  stop_meas( &softmodem_stats_rxtx_sf );
260 261 262 263 264 265 266 267 268

  LOG_D(PHY,"%s() Exit proc[rx:%d%d tx:%d%d]\n", __FUNCTION__, proc->frame_rx, proc->subframe_rx, proc->frame_tx, proc->subframe_tx);

  LOG_D(PHY, "rxtx:%lld nfapi:%lld phy:%lld tx:%lld rx:%lld prach:%lld ofdm:%lld ",
      softmodem_stats_rxtx_sf.diff_now, nfapi_meas.diff_now,
      TICK_TO_US(eNB->phy_proc),
      TICK_TO_US(eNB->phy_proc_tx),
      TICK_TO_US(eNB->phy_proc_rx),
      TICK_TO_US(eNB->rx_prach),
269 270
      TICK_TO_US(eNB->ofdm_mod_stats)
      );
271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301
  LOG_D(PHY,
    "dlsch[enc:%lld mod:%lld scr:%lld rm:%lld t:%lld i:%lld] rx_dft:%lld ",
      TICK_TO_US(eNB->dlsch_encoding_stats),
      TICK_TO_US(eNB->dlsch_modulation_stats),
      TICK_TO_US(eNB->dlsch_scrambling_stats),
      TICK_TO_US(eNB->dlsch_rate_matching_stats),
      TICK_TO_US(eNB->dlsch_turbo_encoding_stats),
      TICK_TO_US(eNB->dlsch_interleaving_stats),
      TICK_TO_US(eNB->rx_dft_stats));

  LOG_D(PHY," ulsch[ch:%lld freq:%lld dec:%lld demod:%lld ru:%lld ",
      TICK_TO_US(eNB->ulsch_channel_estimation_stats),
      TICK_TO_US(eNB->ulsch_freq_offset_estimation_stats),
      TICK_TO_US(eNB->ulsch_decoding_stats),
      TICK_TO_US(eNB->ulsch_demodulation_stats),
      TICK_TO_US(eNB->ulsch_rate_unmatching_stats));

  LOG_D(PHY, "td:%lld dei:%lld dem:%lld llr:%lld tci:%lld ",
      TICK_TO_US(eNB->ulsch_turbo_decoding_stats),
      TICK_TO_US(eNB->ulsch_deinterleaving_stats),
      TICK_TO_US(eNB->ulsch_demultiplexing_stats),
      TICK_TO_US(eNB->ulsch_llr_stats),
      TICK_TO_US(eNB->ulsch_tc_init_stats));
  LOG_D(PHY, "tca:%lld tcb:%lld tcg:%lld tce:%lld l1:%lld l2:%lld]\n\n", 
      TICK_TO_US(eNB->ulsch_tc_alpha_stats),
      TICK_TO_US(eNB->ulsch_tc_beta_stats),
      TICK_TO_US(eNB->ulsch_tc_gamma_stats),
      TICK_TO_US(eNB->ulsch_tc_ext_stats),
      TICK_TO_US(eNB->ulsch_tc_intl1_stats),
      TICK_TO_US(eNB->ulsch_tc_intl2_stats)
      );
Raymond Knopp's avatar
Raymond Knopp committed
302 303 304 305
  
  return(0);
}

306

307 308 309 310 311 312 313
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];
314
  sprintf(thread_name,"TXnp4_%d\n",&eNB->proc.proc_rxtx[0] == proc ? 0 : 1);
315
  thread_top_init(thread_name,1,470000,500000,500000);
316
  
317
  //wait_sync("tx_thread");
Eurecom's avatar
Eurecom committed
318
  
319
  while (!oai_exit) {
320
    
321 322 323 324 325 326 327 328

    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)
    // *****************************************
329 330 331 332
    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);
333
    
334
    phy_procedures_eNB_TX(eNB, proc, 1);
335
    if (release_thread(&proc->mutex_rxtx,&proc->instance_cnt_rxtx,thread_name)<0) break;
336
	
337 338 339 340 341 342 343 344
    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 );
Wang Tsu-Han's avatar
Wang Tsu-Han committed
345
    wakeup_txfh(proc,eNB_proc->ru_proc);
346 347 348 349 350
  }

  return 0;
}

351
/*!
352
 * \brief The RX UE-specific and TX thread of eNB.
353 354 355
 * \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.
 */
356

357 358
static void* eNB_thread_rxtx( void* param ) {

359
  static int eNB_thread_rxtx_status;
360 361 362 363 364 365 366 367 368 369 370 371
  //eNB_proc_t *eNB_proc  = (eNB_proc_t*)param;
  eNB_rxtx_proc_t *proc;

  // Working
  if(nfapi_mode ==2){
	  proc = (eNB_rxtx_proc_t*)param;
  }
  else{
	  eNB_proc_t *eNB_proc  = (eNB_proc_t*)param;
	  proc = &eNB_proc->proc_rxtx[0];
  }

372

373
  PHY_VARS_eNB *eNB = RC.eNB[0][proc->CC_id];
374
  //RU_proc_t *ru_proc = NULL;
375

Raymond Knopp's avatar
Raymond Knopp committed
376 377
  char thread_name[100];

378 379
  cpu_set_t cpuset;
  CPU_ZERO(&cpuset);
380

381
  // set default return value
382
  eNB_thread_rxtx_status = 0;
383 384


Raymond Knopp's avatar
Raymond Knopp committed
385
  sprintf(thread_name,"RXn_TXnp4_%d\n",&eNB->proc.proc_rxtx[0] == proc ? 0 : 1);
386 387 388
  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));
389

390

391 392

  while (!oai_exit) {
393 394
    
    
395
    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_RXTX0+(proc->subframe_rx&1), 0 );
396
    T(T_ENB_MASTER_TICK, T_INT(0), T_INT(proc->frame_rx), T_INT(proc->subframe_rx));
397

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

400
    VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_CPUID_ENB_THREAD_RXTX,sched_getcpu());
401
    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_RXTX0+(proc->subframe_rx&1), 1 );
402 403 404 405 406 407
   
    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);
 
408

409 410
    if (oai_exit) break;

411
    if (eNB->CC_id==0)
412
    {
413
      if (rxtx(eNB,proc,thread_name) < 0) break;
414 415 416
    }

    if (release_thread(&proc->mutex_rxtx,&proc->instance_cnt_rxtx,thread_name)<0) break;
417 418 419 420 421 422 423 424
    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 );
425 426 427 428 429 430 431
    if (nfapi_mode!=2){
    	if(get_nprocs() >= 8)      wakeup_tx(eNB,eNB->proc.ru_proc);
    	else
    	{
    		phy_procedures_eNB_TX(eNB, proc, 1);
    		wakeup_txfh(proc,eNB->proc.ru_proc);
    	}
432
    }
433

Raymond Knopp's avatar
Raymond Knopp committed
434
  } // while !oai_exit
435

436
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_RXTX0+(proc->subframe_rx&1), 0 );
437

438
  LOG_D(PHY, " *** Exiting eNB thread RXn_TXnp4\n");
439

440 441
  eNB_thread_rxtx_status = 0;
  return &eNB_thread_rxtx_status;
442 443
}

444
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
445
{
446 447
  eNB_proc_t *proc           = &eNB->proc;
  eNB_rxtx_proc_t *proc_rxtx = &proc->proc_rxtx[0];
Guy De Souza's avatar
Guy De Souza committed
448
  LTE_DL_FRAME_PARMS *fp = ru->frame_parms;
Raymond Knopp's avatar
Raymond Knopp committed
449
  RU_proc_t *ru_proc=&ru->proc;
450

451 452
  proc->frame_rx    = frame_rx;
  proc->subframe_rx = subframe_rx;
Raymond Knopp's avatar
Raymond Knopp committed
453

Cedric Roux's avatar
Cedric Roux committed
454
  if (!oai_exit) {
455
    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
456

Raymond Knopp's avatar
Raymond Knopp committed
457 458 459 460 461
    proc_rxtx->timestamp_tx = ru_proc->timestamp_rx + (sf_ahead*fp->samples_per_tti);
    proc_rxtx->frame_rx     = ru_proc->frame_rx;
    proc_rxtx->subframe_rx  = ru_proc->subframe_rx;
    proc_rxtx->frame_tx     = (proc_rxtx->subframe_rx > (9-sf_ahead)) ? (proc_rxtx->frame_rx+1)&1023 : proc_rxtx->frame_rx;
    proc_rxtx->subframe_tx  = (proc_rxtx->subframe_rx + sf_ahead)%10;
Raymond Knopp's avatar
Raymond Knopp committed
462

463
    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);
Raymond Knopp's avatar
Raymond Knopp committed
464 465 466
    ru_proc->timestamp_tx = proc_rxtx->timestamp_tx;
    ru_proc->subframe_tx  = proc_rxtx->subframe_tx;
    ru_proc->frame_tx     = proc_rxtx->frame_tx;
467
  }
Raymond Knopp's avatar
Raymond Knopp committed
468 469
}

Wang Tsu-Han's avatar
Wang Tsu-Han committed
470
int wakeup_txfh(eNB_rxtx_proc_t *proc,RU_proc_t *ru_proc) {
471
  
472 473
	if(ru_proc == NULL)
		return(0);
474 475 476
  struct timespec wait;
  wait.tv_sec=0;
  wait.tv_nsec=5000000L;
Wang Tsu-Han's avatar
Wang Tsu-Han committed
477

478
  
479 480 481
  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);
482
  }
483 484
  if (release_thread(&ru_proc->mutex_eNBs,&ru_proc->ru_tx_ready,"wakeup_txfh")<0) return(-1);
  
485
  if (ru_proc->instance_cnt_eNBs == 0) {
Wang Tsu-Han's avatar
Wang Tsu-Han committed
486
    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);
487 488
    return(-1);
  }
489 490 491 492 493 494 495
  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
496 497 498
    ru_proc->timestamp_tx = proc->timestamp_tx;
    ru_proc->subframe_tx  = proc->subframe_tx;
    ru_proc->frame_tx     = proc->frame_tx;
499 500 501 502 503 504
  
  // 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);
505
  }
506 507 508 509
  
  pthread_mutex_unlock( &ru_proc->mutex_eNBs );

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

512 513 514 515
int wakeup_tx(PHY_VARS_eNB *eNB,RU_proc_t *ru_proc) {

  eNB_proc_t *proc=&eNB->proc;

516 517
  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];
518 519 520 521 522 523

  
  struct timespec wait;
  wait.tv_sec=0;
  wait.tv_nsec=5000000L;
  
524
  
525
  
526 527
  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);
528 529 530
    return(-1);
  }
  
531 532
  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 );
533
    exit_fun( "error locking mutex_tx" );
534 535 536
    return(-1);
  }

537
  ++proc_rxtx1->instance_cnt_rxtx;
538 539

  
540 541 542 543 544
  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;
545 546
  
  // the thread can now be woken up
547
  if (pthread_cond_signal(&proc_rxtx1->cond_rxtx) != 0) {
548
    LOG_E( PHY, "[eNB] ERROR pthread_cond_signal for eNB TXnp4 thread\n");
549 550 551 552
    exit_fun( "ERROR pthread_cond_signal" );
    return(-1);
  }
  
553
  pthread_mutex_unlock( &proc_rxtx1->mutex_rxtx );
554 555 556

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

558 559 560
int wakeup_rxtx(PHY_VARS_eNB *eNB,RU_t *ru) {

  eNB_proc_t *proc=&eNB->proc;
561
  RU_proc_t *ru_proc=&ru->proc;
562

Wang Tsu-Han's avatar
Wang Tsu-Han committed
563
  eNB_rxtx_proc_t *proc_rxtx0=&proc->proc_rxtx[0];
Wang Tsu-Han's avatar
Wang Tsu-Han committed
564
  //eNB_rxtx_proc_t *proc_rxtx1=&proc->proc_rxtx[1];
565
  
566 567

  LTE_DL_FRAME_PARMS *fp = &eNB->frame_parms;
568 569 570 571

  int i;
  struct timespec wait;
  
572 573 574 575 576 577 578 579 580 581
  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
582
    LOG_E(PHY,"Not all RUs have provided their info\n");
583 584 585 586 587 588 589 590 591 592 593
    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);
  }




594 595 596
  wait.tv_sec=0;
  wait.tv_nsec=5000000L;

597
  
598 599 600
  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);
601
  }
602 603
  if (release_thread(&proc_rxtx0->mutex_rxtx,&proc_rxtx0->pipe_ready,"wakeup_rxtx")<0) return(-1);
  
604 605
  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);
606 607 608
    return(-1);
  }

Cedric Roux's avatar
Cedric Roux committed
609
  // wake up TX for subframe n+sf_ahead
610
  // lock the TX mutex and make sure the thread is ready
611 612
  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 );
613 614 615 616
    exit_fun( "error locking mutex_rxtx" );
    return(-1);
  }
  
617

618
  ++proc_rxtx0->instance_cnt_rxtx;
619 620 621 622 623
  
  // 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, 
624 625
  // we want to generate subframe (n+sf_ahead), so TS_tx = TX_rx+sf_ahead*samples_per_tti,
  // and proc->subframe_tx = proc->subframe_rx+sf_ahead
626 627 628 629 630
  proc_rxtx0->timestamp_tx = ru_proc->timestamp_rx + (sf_ahead*fp->samples_per_tti);
  proc_rxtx0->frame_rx     = ru_proc->frame_rx;
  proc_rxtx0->subframe_rx  = ru_proc->subframe_rx;
  proc_rxtx0->frame_tx     = (proc_rxtx0->subframe_rx > (9-sf_ahead)) ? (proc_rxtx0->frame_rx+1)&1023 : proc_rxtx0->frame_rx;
  proc_rxtx0->subframe_tx  = (proc_rxtx0->subframe_rx + sf_ahead)%10;
631

632
  // the thread can now be woken up
633
  if (pthread_cond_signal(&proc_rxtx0->cond_rxtx) != 0) {
634 635 636 637 638
    LOG_E( PHY, "[eNB] ERROR pthread_cond_signal for eNB RXn-TXnp4 thread\n");
    exit_fun( "ERROR pthread_cond_signal" );
    return(-1);
  }
  
639
  pthread_mutex_unlock( &proc_rxtx0->mutex_rxtx );
640 641 642 643

  return(0);
}

644
void wakeup_prach_eNB(PHY_VARS_eNB *eNB,RU_t *ru,int frame,int subframe) {
645 646 647

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

650 651 652 653
  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
654
	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);
655 656
	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",
657
		eNB->Mod_id,frame,subframe,ru->idx,eNB->num_RU,proc->RU_mask_prach);
658 659 660 661 662
	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
663
      return;
664 665 666 667 668 669 670
    }
    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);
    }
  }
    
671
  // check if we have to detect PRACH first
672
  if (is_prach_subframe(fp,frame,subframe)>0) { 
673
    LOG_D(PHY,"Triggering prach processing, frame %d, subframe %d\n",frame,subframe);
674
    if (proc->instance_cnt_prach == 0) {
675
      LOG_W(PHY,"[eNB] Frame %d Subframe %d, dropping PRACH\n", frame,subframe);
676 677 678 679 680 681 682 683 684 685 686 687
      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
688 689
    proc->frame_prach = frame;
    proc->subframe_prach = subframe;
690 691 692 693 694 695 696 697 698 699 700 701 702
    
    // 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 );
  }

}

703
#if (RRC_VERSION >= MAKE_VERSION(14, 0, 0))
704 705 706 707 708 709 710 711 712 713
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
714
	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);
715 716 717 718 719 720 721 722
	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
723
      return;
724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763
    }
    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

Xu Bo's avatar
Xu Bo committed
764

765 766 767 768 769
/*!
 * \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.
 */
770
static void* eNB_thread_prach( void* param ) {
771 772
  static int eNB_thread_prach_status;

773 774 775

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

777 778 779
  // set default return value
  eNB_thread_prach_status = 0;

780
  thread_top_init("eNB_thread_prach",1,500000,1000000,20000000);
781

782
  //wait_sync("eNB_thread_prach");
783

784 785 786 787
  while (!oai_exit) {
    
    if (oai_exit) break;

788
    
Raymond Knopp's avatar
Raymond Knopp committed
789
    if (wait_on_condition(&proc->mutex_prach,&proc->cond_prach,&proc->instance_cnt_prach,"eNB_prach_thread") < 0) break;
790 791

    LOG_D(PHY,"Running eNB prach procedures\n");
792
    prach_procedures(eNB
793
#if (RRC_VERSION >= MAKE_VERSION(14, 0, 0))
794 795 796
		     ,0
#endif
		     );
797
    
Raymond Knopp's avatar
Raymond Knopp committed
798
    if (release_thread(&proc->mutex_prach,&proc->instance_cnt_prach,"eNB_prach_thread") < 0) break;
799
  }
800

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

803 804
  eNB_thread_prach_status = 0;
  return &eNB_thread_prach_status;
805 806
}

807
#if (RRC_VERSION >= MAKE_VERSION(14, 0, 0))
808 809 810 811 812 813 814 815 816 817 818 819 820 821 822
/*!
 * \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;

823
  thread_top_init("eNB_thread_prach_br",1,500000,1000000,20000000);
824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844

  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
845

Raymond Knopp's avatar
Raymond Knopp committed
846

847

Wang Tsu-Han's avatar
Wang Tsu-Han committed
848
extern void init_td_thread(PHY_VARS_eNB *);
Eurecom's avatar
Eurecom committed
849
extern void init_te_thread(PHY_VARS_eNB *);
Wang Tsu-Han's avatar
Wang Tsu-Han committed
850 851
extern void kill_td_thread(PHY_VARS_eNB *);
extern void kill_te_thread(PHY_VARS_eNB *);
852

853
static void* process_stats_thread(void* param) {
854 855 856

  PHY_VARS_eNB     *eNB      = (PHY_VARS_eNB*)param;

857
  wait_sync("process_stats_thread");
858 859

  while (!oai_exit) {
Wang Tsu-Han's avatar
Wang Tsu-Han committed
860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876
    sleep(1);
      if (opp_enabled == 1) {
        if (eNB->td) print_meas(&eNB->ulsch_decoding_stats,"ulsch_decoding",NULL,NULL);
        if (eNB->te)
        {
          print_meas(&eNB->dlsch_turbo_encoding_preperation_stats,"dlsch_coding_crc",NULL,NULL);
          print_meas(&eNB->dlsch_turbo_encoding_segmentation_stats,"dlsch_segmentation",NULL,NULL);
          print_meas(&eNB->dlsch_encoding_stats,"dlsch_encoding",NULL,NULL);
          print_meas(&eNB->dlsch_turbo_encoding_signal_stats,"coding_signal",NULL,NULL);
          print_meas(&eNB->dlsch_turbo_encoding_main_stats,"coding_main",NULL,NULL);
          print_meas(&eNB->dlsch_turbo_encoding_stats,"turbo_encoding",NULL,NULL);
          print_meas(&eNB->dlsch_interleaving_stats,"turbo_interleaving",NULL,NULL);
          print_meas(&eNB->dlsch_rate_matching_stats,"turbo_rate_matching",NULL,NULL);
          print_meas(&eNB->dlsch_turbo_encoding_waiting_stats,"coding_wait",NULL,NULL);
          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);
       }
877
       print_meas(&eNB->dlsch_modulation_stats,"dlsch_modulation",NULL,NULL);
878 879 880 881 882
     }
  }
  return(NULL);
}

883

884
void init_eNB_proc(int inst) {
885
  
Rohit Gupta's avatar
Rohit Gupta committed
886
  int i=0;
887
  int CC_id;
888 889
  PHY_VARS_eNB *eNB;
  eNB_proc_t *proc;
890
  eNB_rxtx_proc_t *proc_rxtx;
Raymond Knopp's avatar
Raymond Knopp committed
891
  pthread_attr_t *attr0=NULL,*attr1=NULL,*attr_prach=NULL;
892
#if (RRC_VERSION >= MAKE_VERSION(14, 0, 0))
893 894
  pthread_attr_t *attr_prach_br=NULL;
#endif
Raymond Knopp's avatar
Raymond Knopp committed
895

896 897
  LOG_I(PHY,"%s(inst:%d) RC.nb_CC[inst]:%d \n",__FUNCTION__,inst,RC.nb_CC[inst]);

898
  for (CC_id=0; CC_id<RC.nb_CC[inst]; CC_id++) {
899
    eNB = RC.eNB[inst][CC_id];
laurent's avatar
laurent committed
900
#ifndef OCP_FRAMEWORK
901
    LOG_I(PHY,"Initializing eNB processes instance:%d CC_id %d \n",inst,CC_id);
laurent's avatar
laurent committed
902
#endif
903
    proc = &eNB->proc;
Raymond Knopp's avatar
Raymond Knopp committed
904

905
    proc_rxtx                      = proc->proc_rxtx;
906 907
    proc_rxtx[0].instance_cnt_rxtx = -1;
    proc_rxtx[1].instance_cnt_rxtx = -1;
908 909
    proc_rxtx[0].pipe_ready        = 0;
    proc_rxtx[1].pipe_ready        = 0;
910
    proc->instance_cnt_prach       = -1;
911
    proc->instance_cnt_asynch_rxtx = -1;
Eurecom's avatar
Eurecom committed
912
    proc->instance_cnt_synch       = -1;
913
    proc->CC_id                    = CC_id;    
914

Raymond Knopp's avatar
Raymond Knopp committed
915 916
    proc->first_rx=1;
    proc->first_tx=1;
917 918
    proc->RU_mask=0;
    proc->RU_mask_prach=0;
Raymond Knopp's avatar
Raymond Knopp committed
919

920
    pthread_mutex_init( &eNB->UL_INFO_mutex, NULL);
921 922 923 924
    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
925 926 927

    pthread_mutex_init( &proc->mutex_prach, NULL);
    pthread_mutex_init( &proc->mutex_asynch_rxtx, NULL);
928 929
    pthread_mutex_init( &proc->mutex_RU,NULL);
    pthread_mutex_init( &proc->mutex_RU_PRACH,NULL);
Raymond Knopp's avatar
Raymond Knopp committed
930

931
    pthread_cond_init( &proc->cond_prach, NULL);
932
    pthread_cond_init( &proc->cond_asynch_rxtx, NULL);
933 934 935 936 937

    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);
938
#if (RRC_VERSION >= MAKE_VERSION(14, 0, 0))
939 940 941 942 943 944 945
    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
946
#ifndef DEADLINE_SCHEDULER
Raymond Knopp's avatar
Raymond Knopp committed
947 948 949
    attr0       = &proc_rxtx[0].attr_rxtx;
    attr1       = &proc_rxtx[1].attr_rxtx;
    attr_prach  = &proc->attr_prach;
950
#if (RRC_VERSION >= MAKE_VERSION(14, 0, 0))
951 952 953
    attr_prach_br  = &proc->attr_prach_br;
#endif

Raymond Knopp's avatar
Raymond Knopp committed
954 955
    //    attr_td     = &proc->attr_td;
    //    attr_te     = &proc->attr_te; 
Raymond Knopp's avatar
Raymond Knopp committed
956
#endif
Wang Tsu-Han's avatar
Wang Tsu-Han committed
957

958 959 960
    if(get_nprocs() > 2 && codingw)
    {
      init_te_thread(eNB);
Wang Tsu-Han's avatar
Wang Tsu-Han committed
961
      init_td_thread(eNB);
962
    }
963

Raymond Knopp's avatar
Raymond Knopp committed
964

965 966
    LOG_I(PHY,"eNB->single_thread_flag:%d\n", eNB->single_thread_flag);

967
    if (eNB->single_thread_flag==0 && nfapi_mode!=2) {
Wang Tsu-Han's avatar
Wang Tsu-Han committed
968 969
      pthread_create( &proc_rxtx[0].pthread_rxtx, attr0, eNB_thread_rxtx, proc );
      pthread_create( &proc_rxtx[1].pthread_rxtx, attr1, tx_thread, proc);
970
    }
971
    pthread_create( &proc->pthread_prach, attr_prach, eNB_thread_prach, eNB );
972
#if (RRC_VERSION >= MAKE_VERSION(14, 0, 0))
973 974
    pthread_create( &proc->pthread_prach_br, attr_prach_br, eNB_thread_prach_br, eNB );
#endif
975
    char name[16];
976 977 978 979 980 981
    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 );
    }
982 983

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

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

988
    
989
  }
990

991
  //for multiple CCs: setup master and slaves
992 993 994
  /* 
     for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
     eNB = PHY_vars_eNB_g[inst][CC_id];
995

996 997 998
     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*));
999

1000 1001 1002 1003 1004 1005 1006
     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);
     }
     }
     }
  */
1007

1008 1009 1010 1011
  /* 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;
1012 1013
  
  
1014 1015
}

1016

1017

1018 1019 1020
/*!
 * \brief Terminate eNB TX and RX threads.
 */
1021
void kill_eNB_proc(int inst) {
1022

1023
  int *status;
1024 1025
  PHY_VARS_eNB *eNB;
  eNB_proc_t *proc;
1026
  eNB_rxtx_proc_t *proc_rxtx;
1027
  int i;
1028
  for (int CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
1029
    eNB=RC.eNB[inst][CC_id];
1030 1031
    
    proc = &eNB->proc;
1032
    proc_rxtx = &proc->proc_rxtx[0];
1033

1034 1035 1036 1037 1038 1039 1040
    if(get_nprocs() > 2 && codingw)
    {
      kill_td_thread(eNB);
      kill_te_thread(eNB);
      LOG_I(PHY, "Killing TX CC_id %d inst %d\n", CC_id, inst );
    }
    
1041 1042 1043
    for (i=0; i<2; i++) {
      pthread_mutex_lock(&proc_rxtx[i].mutex_rxtx);
      proc_rxtx[i].instance_cnt_rxtx = 0;
Wang Tsu-Han's avatar
Wang Tsu-Han committed
1044
      proc_rxtx[i].pipe_ready = 0;
1045
      pthread_cond_signal(&proc_rxtx[i].cond_rxtx);
1046
      pthread_mutex_unlock(&proc_rxtx[i].mutex_rxtx);
1047
    }
Raymond Knopp's avatar
Raymond Knopp committed
1048 1049
    proc->instance_cnt_prach = 0;
    pthread_cond_signal( &proc->cond_prach );
1050

1051
    pthread_cond_signal( &proc->cond_asynch_rxtx );
1052
    pthread_cond_broadcast(&sync_phy_proc.cond_phy_proc_tx);
Raymond Knopp's avatar
Raymond Knopp committed
1053

1054
    LOG_D(PHY, "joining pthread_prach\n");
1055
    pthread_join( proc->pthread_prach, (void**)&status );    
1056

1057
    LOG_I(PHY, "Destroying prach mutex/cond\n");
1058
    pthread_mutex_destroy( &proc->mutex_prach );
1059
    pthread_cond_destroy( &proc->cond_prach );
1060
#if (RRC_VERSION >= MAKE_VERSION(14, 0, 0))
1061
    proc->instance_cnt_prach_br = 0;
1062 1063 1064 1065
    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 );
1066
#endif
1067
    LOG_I(PHY, "Destroying UL_INFO mutex\n");
1068
    pthread_mutex_destroy(&eNB->UL_INFO_mutex);
Wang Tsu-Han's avatar
Wang Tsu-Han committed
1069 1070 1071 1072 1073 1074
    for (i=0;i<2;i++) {
      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 );
1075
    }
1076
  }
1077 1078
}

1079

1080 1081 1082


void reset_opp_meas(void) {
1083

1084 1085 1086 1087 1088
  int sfn;
  reset_meas(&softmodem_stats_mt);
  reset_meas(&softmodem_stats_hw);
  
  for (sfn=0; sfn < 10; sfn++) {
1089
    reset_meas(&softmodem_stats_rxtx_sf);
1090
    reset_meas(&softmodem_stats_rx_sf);
1091 1092 1093
  }
}

1094

1095 1096 1097 1098 1099 1100 1101
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++) {
1102
    print_meas(&softmodem_stats_rxtx_sf,"[eNB][total_phy_proc_rxtx]",NULL, NULL);
1103
    print_meas(&softmodem_stats_rx_sf,"[eNB][total_phy_proc_rx]",NULL,NULL);
1104 1105
  }
}
1106

1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121
void free_transport(PHY_VARS_eNB *eNB)
{
  int i;
  int j;

  for (i=0; i<NUMBER_OF_UE_MAX; i++) {
    LOG_I(PHY, "Freeing Transport Channel Buffers for DLSCH, UE %d\n",i);
    for (j=0; j<2; j++) free_eNB_dlsch(eNB->dlsch[i][j]);

    LOG_I(PHY, "Freeing Transport Channel Buffer for ULSCH, UE %d\n",i);
    free_eNB_ulsch(eNB->ulsch[1+i]);
  }
  free_eNB_ulsch(eNB->ulsch[0]);
}

1122
void init_transport(PHY_VARS_eNB *eNB) {
1123

1124 1125 1126
  int i;
  int j;
  LTE_DL_FRAME_PARMS *fp = &eNB->frame_parms;
1127

Cedric Roux's avatar
Cedric Roux committed
1128
  LOG_I(PHY, "Initialise transport\n");
1129

1130
  for (i=0; i<NUMBER_OF_UE_MAX; i++) {
1131
    LOG_D(PHY,"Allocating Transport Channel Buffers for DLSCH, UE %d\n",i);
1132 1133 1134 1135
    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);
1136
	exit(-1);
1137 1138
      } else {
	eNB->dlsch[i][j]->rnti=0;
1139
	LOG_D(PHY,"dlsch[%d][%d] => %p rnti:%d\n",i,j,eNB->dlsch[i][j], eNB->dlsch[i][j]->rnti);
1140 1141
      }
    }
1142
    
1143
    LOG_D(PHY,"Allocating Transport Channel Buffer for ULSCH, UE %d\n",i);
1144 1145 1146 1147
    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");
1148 1149
      exit(-1);
    }
1150 1151 1152 1153
    
    // 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;
1154
  }
1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170
  // 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;
1171
  
1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185
  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
1186 1187

void init_eNB_afterRU(void) {
1188

1189 1190
  int inst,CC_id,ru_id,i,aa;
  PHY_VARS_eNB *eNB;
1191

1192
  LOG_I(PHY,"%s() RC.nb_inst:%d\n", __FUNCTION__, RC.nb_inst);
1193

1194
  for (inst=0;inst<RC.nb_inst;inst++) {
1195
    LOG_I(PHY,"RC.nb_CC[inst]:%d\n", RC.nb_CC[inst]);
1196
    for (CC_id=0;CC_id<RC.nb_CC[inst];CC_id++) {
1197 1198 1199

      LOG_I(PHY,"RC.nb_CC[inst:%d][CC_id:%d]:%p\n", inst, CC_id, RC.eNB[inst][CC_id]);

1200 1201 1202
      eNB                                  =  RC.eNB[inst][CC_id];
      phy_init_lte_eNB(eNB,0,0);
      // map antennas and PRACH signals to eNB RX
1203
      if (0) AssertFatal(eNB->num_RU>0,"Number of RU attached to eNB %d is zero\n",eNB->Mod_id);
1204
      LOG_I(PHY,"Mapping RX ports from %d RUs to eNB %d\n",eNB->num_RU,eNB->Mod_id);
1205
      eNB->frame_parms.nb_antennas_rx       = 0;
1206

Cedric Roux's avatar
Cedric Roux committed
1207
      LOG_I(PHY,"Overwriting eNB->prach_vars.rxsigF[0]:%p\n", eNB->prach_vars.rxsigF[0]);
1208

Raymond Knopp's avatar
Raymond Knopp committed
1209
      eNB->prach_vars.rxsigF[0] = (int16_t**)malloc16(64*sizeof(int16_t*));
1210
#if (RRC_VERSION >= MAKE_VERSION(14, 0, 0))
1211
      for (int ce_level=0;ce_level<4;ce_level++) {
Cedric Roux's avatar
Cedric Roux committed
1212
        LOG_I(PHY,"Overwriting eNB->prach_vars_br.rxsigF.rxsigF[0]:%p\n", eNB->prach_vars_br.rxsigF[ce_level]);
1213 1214
        eNB->prach_vars_br.rxsigF[ce_level] = (int16_t**)malloc16(64*sizeof(int16_t*));
      }
1215
#endif
1216 1217 1218

      LOG_I(PHY,"eNB->num_RU:%d\n", eNB->num_RU);

1219 1220
      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;
1221 1222 1223 1224 1225 1226 1227 1228 1229

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

1230 1231
	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
1232
	  eNB->prach_vars.rxsigF[0][aa]    =  eNB->RU_list[ru_id]->prach_rxsigF[i];
1233
#if (RRC_VERSION >= MAKE_VERSION(14, 0, 0))
Raymond Knopp's avatar
Raymond Knopp committed
1234 1235 1236
	  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
1237 1238 1239
	  eNB->common_vars.rxdataF[aa]     =  eNB->RU_list[ru_id]->common.rxdataF[i];
	}
      }
1240 1241 1242



Cedric Roux's avatar
Cedric Roux committed
1243 1244 1245 1246
      /* TODO: review this code, there is something wrong.
       * In monolithic mode, we come here with nb_antennas_rx == 0
       * (not tested in other modes).
       */
1247 1248 1249 1250 1251 1252 1253
      if (eNB->frame_parms.nb_antennas_rx < 1)
      {
        LOG_I(PHY, "%s() ************* DJP ***** eNB->frame_parms.nb_antennas_rx:%d - GOING TO HARD CODE TO 1", __FUNCTION__, eNB->frame_parms.nb_antennas_rx);
        eNB->frame_parms.nb_antennas_rx = 1;
      }
      else
      {
Cedric Roux's avatar
Cedric Roux committed
1254
        //LOG_I(PHY," Delete code\n");
1255 1256 1257 1258 1259 1260 1261 1262 1263
      }

      if (eNB->frame_parms.nb_antennas_tx < 1)
      {
        LOG_I(PHY, "%s() ************* DJP ***** eNB->frame_parms.nb_antennas_tx:%d - GOING TO HARD CODE TO 1", __FUNCTION__, eNB->frame_parms.nb_antennas_tx);
        eNB->frame_parms.nb_antennas_tx = 1;
      }
      else
      {
Cedric Roux's avatar
Cedric Roux committed
1264
        //LOG_I(PHY," Delete code\n");
1265 1266 1267 1268 1269
      }




1270 1271 1272
      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);
1273 1274

      init_transport(eNB);
Raymond Knopp's avatar
Raymond Knopp committed
1275
      //init_precoding_weights(RC.eNB[inst][CC_id]);
1276 1277 1278
    }
    init_eNB_proc(inst);
  }
1279

1280
  for (ru_id=0;ru_id<RC.nb_RU;ru_id++) {
1281 1282

    AssertFatal(RC.ru[ru_id]!=NULL,"ru_id %d is null\n",ru_id);
1283
    
1284 1285
    RC.ru[ru_id]->wakeup_rxtx         = wakeup_rxtx;
    RC.ru[ru_id]->wakeup_prach_eNB    = wakeup_prach_eNB;
1286
#if (RRC_VERSION >= MAKE_VERSION(14, 0, 0))
1287
    RC.ru[ru_id]->wakeup_prach_eNB_br = wakeup_prach_eNB_br;
1288
#endif
1289
    RC.ru[ru_id]->eNB_top             = eNB_top;
1290 1291
  }
}
1292

1293
void init_eNB(int single_thread_flag,int wait_for_sync) {
1294
  
1295
  int CC_id;
1296
  int inst;
1297
  PHY_VARS_eNB *eNB;
Raymond Knopp's avatar
Raymond Knopp committed
1298

1299 1300
  LOG_I(PHY,"[lte-softmodem.c] eNB structure about to allocated RC.nb_L1_inst:%d RC.nb_L1_CC[0]:%d\n",RC.nb_L1_inst,RC.nb_L1_CC[0]);

1301
  if (RC.eNB == NULL) RC.eNB = (PHY_VARS_eNB***) malloc(RC.nb_L1_inst*sizeof(PHY_VARS_eNB **));
1302
  LOG_I(PHY,"[lte-softmodem.c] eNB structure RC.eNB allocated\n");
1303
  for (inst=0;inst<RC.nb_L1_inst;inst++) {
1304
    if (RC.eNB[inst] == NULL) RC.eNB[inst] = (PHY_VARS_eNB**) malloc(RC.nb_CC[inst]*sizeof(PHY_VARS_eNB *));
1305
    for (CC_id=0;CC_id<RC.nb_L1_CC[inst];CC_id++) {
1306 1307
      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]; 
1308
      eNB->abstraction_flag   = 0;
Raymond Knopp's avatar
Raymond Knopp committed
1309
      eNB->single_thread_flag = single_thread_flag;
1310

1311

1312
      LOG_I(PHY,"Initializing eNB %d CC_id %d single_thread_flag:%d\n",inst,CC_id,single_thread_flag);
laurent's avatar
laurent committed
1313
#ifndef OCP_FRAMEWORK
1314
      LOG_I(PHY,"Initializing eNB %d CC_id %d\n",inst,CC_id);
laurent's avatar
laurent committed
1315
#endif
Raymond Knopp's avatar
Raymond Knopp committed
1316 1317


1318
      eNB->td                   = ulsch_decoding_data_all;//(get_nprocs()<=4) ? ulsch_decoding_data : ulsch_decoding_data_2thread;
1319
      eNB->te                   = dlsch_encoding_all;//(get_nprocs()<=4) ? dlsch_encoding : dlsch_encoding_2threads;
1320

1321
      
1322
      LOG_I(PHY,"Registering with MAC interface module\n");
1323 1324 1325 1326 1327 1328
      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");
1329 1330 1331 1332
      eNB->UL_INFO.rx_ind.rx_indication_body.rx_pdu_list   = eNB->rx_pdu_list;
      eNB->UL_INFO.crc_ind.crc_indication_body.crc_pdu_list = eNB->crc_pdu_list;
      eNB->UL_INFO.sr_ind.sr_indication_body.sr_pdu_list = eNB->sr_pdu_list;
      eNB->UL_INFO.harq_ind.harq_indication_body.harq_pdu_list = eNB->harq_pdu_list;
1333 1334
      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;
1335
      eNB->prach_energy_counter = 0;
1336 1337
    }

1338
  }
1339

1340
  LOG_I(PHY,"[lte-softmodem.c] eNB structure allocated\n");
1341 1342 1343
}


1344
void stop_eNB(int nb_inst) {
1345

1346
  for (int inst=0;inst<nb_inst;inst++) {
1347
    LOG_I(PHY,"Killing eNB %d processing threads\n",inst);
1348 1349
    kill_eNB_proc(inst);
  }
1350
}