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

/*! \file lte-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

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

36

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

39 40
#include "rt_wrapper.h"

41
#include "assertions.h"
42

43 44 45

#include "PHY/types.h"

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

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

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

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

62 63 64 65 66 67 68 69
#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"
70
#include "common/utils/LOG/log.h"
71 72 73
#include "UTIL/OTG/otg_tx.h"
#include "UTIL/OTG/otg_externs.h"
#include "UTIL/MATH/oml.h"
74
#include "common/utils/LOG/vcd_signal_dumper.h"
75 76
#include "UTIL/OPT/opt.h"
#include "enb_config.h"
77

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

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

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

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

107

108 109 110 111 112 113
#if defined(ENABLE_ITTI)
extern volatile int             start_eNB;
extern volatile int             start_UE;
#endif
extern volatile int                    oai_exit;

Cedric Roux's avatar
Cedric Roux committed
114
extern int transmission_mode;
115

116 117
extern int oaisim_flag;

118 119 120
//uint16_t sf_ahead=4;
extern uint16_t sf_ahead;

121

122
//pthread_t                       main_eNB_thread;
123 124 125

time_stats_t softmodem_stats_mt; // main thread
time_stats_t softmodem_stats_hw; //  hw acquisition
knopp's avatar
knopp committed
126
time_stats_t softmodem_stats_rxtx_sf; // total tx time
127
time_stats_t nfapi_meas; // total tx time
128
time_stats_t softmodem_stats_rx_sf; // total rx time
129 130 131 132 133 134 135 136 137

/* 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;
138
} sync_phy_proc;
139

140 141
extern double cpuf;

142

143
void init_eNB(int,int);
144
void stop_eNB(int nb_inst);
145

146
int wakeup_tx(PHY_VARS_eNB *eNB,RU_proc_t *ru_proc);
Wang Tsu-Han's avatar
Wang Tsu-Han committed
147
int wakeup_txfh(eNB_rxtx_proc_t *proc,RU_proc_t *ru_proc);
148
void wakeup_prach_eNB(PHY_VARS_eNB *eNB,RU_t *ru,int frame,int subframe);
149
#if (RRC_VERSION >= MAKE_VERSION(14, 0, 0))
150 151
void wakeup_prach_eNB_br(PHY_VARS_eNB *eNB,RU_t *ru,int frame,int subframe);
#endif
152 153
extern PARALLEL_CONF_t get_thread_parallel_conf(void);
extern WORKER_CONF_t   get_thread_worker_conf(void);
154

155 156 157 158 159 160
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)
knopp's avatar
knopp committed
161

162

knopp's avatar
knopp committed
163 164
static inline int rxtx(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc, char *thread_name) {
  start_meas(&softmodem_stats_rxtx_sf);
165

166 167 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
  // *******************************************************************

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

knopp's avatar
knopp committed
204 205
  // ****************************************
  // Common RX procedures subframe n
206

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

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

  release_UE_in_freeList(eNB->Mod_id);

knopp's avatar
knopp committed
219
  // UE-specific RX processing for subframe n
220
  if (nfapi_mode == 0 || nfapi_mode == 1) {
221
    phy_procedures_eNB_uespec_RX(eNB, proc);
222
  }
223
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_DLSCH_ULSCH_SCHEDULER , 1 );
224

225
  if(get_thread_parallel_conf() == PARALLEL_RU_L1_TRX_SPLIT){
WANG Tsu-Han's avatar
WANG Tsu-Han committed
226 227 228 229 230
    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);
231 232
  }

233
  pthread_mutex_lock(&eNB->UL_INFO_mutex);
234

235 236 237 238
  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;
239

240
  eNB->if_inst->UL_indication(&eNB->UL_INFO);
241

242
  pthread_mutex_unlock(&eNB->UL_INFO_mutex);
Wang Tsu-Han's avatar
Wang Tsu-Han committed
243 244
  /* this conflict resolution may be totally wrong, to be tested */
  /* CONFLICT RESOLUTION: BEGIN */
245
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_DLSCH_ULSCH_SCHEDULER , 0 );
246
  if(oai_exit) return(-1);
247
  if(get_thread_parallel_conf() == PARALLEL_SINGLE_THREAD){
Wang Tsu-Han's avatar
Wang Tsu-Han committed
248
#ifndef PHY_TX_THREAD
249
    phy_procedures_eNB_TX(eNB, proc, 1);
Wang Tsu-Han's avatar
Wang Tsu-Han committed
250
#endif
251
  }
Wang Tsu-Han's avatar
Wang Tsu-Han committed
252 253 254
  /* 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 */
knopp's avatar
knopp committed
255 256

  stop_meas( &softmodem_stats_rxtx_sf );
257 258 259 260

  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 ",
261
      softmodem_stats_rxtx_sf.p_time, nfapi_meas.p_time,
262 263 264 265
      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),
Wang Tsu-Han's avatar
Wang Tsu-Han committed
266 267
      TICK_TO_US(eNB->ofdm_mod_stats)
      );
268 269 270 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
  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)
      );
knopp's avatar
knopp committed
299 300 301 302
  
  return(0);
}

303

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

    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)
    // *****************************************
326 327 328 329
    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);
330
    
331
    phy_procedures_eNB_TX(eNB, proc, 1);
332
    if (release_thread(&proc->mutex_rxtx,&proc->instance_cnt_rxtx,thread_name)<0) break;
333
	
334 335 336 337 338 339 340 341
    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
342
    wakeup_txfh(proc,eNB_proc->ru_proc);
343 344 345 346 347
  }

  return 0;
}

348
/*!
knopp's avatar
knopp committed
349
 * \brief The RX UE-specific and TX thread of eNB.
350 351 352
 * \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.
 */
353

354 355
static void* eNB_thread_rxtx( void* param ) {

knopp's avatar
knopp committed
356
  static int eNB_thread_rxtx_status;
357 358 359 360 361 362 363 364 365 366 367 368 369
  //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];
  }


370
  PHY_VARS_eNB *eNB = RC.eNB[0][proc->CC_id];
371
  //RU_proc_t *ru_proc = NULL;
372

knopp's avatar
knopp committed
373 374
  char thread_name[100];

375 376
  cpu_set_t cpuset;
  CPU_ZERO(&cpuset);
377

378
  // set default return value
knopp's avatar
knopp committed
379
  eNB_thread_rxtx_status = 0;
380 381


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

387

388

389
  while (!oai_exit) {
390 391
    
    
knopp's avatar
knopp committed
392
    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_RXTX0+(proc->subframe_rx&1), 0 );
393
    T(T_ENB_MASTER_TICK, T_INT(0), T_INT(proc->frame_rx), T_INT(proc->subframe_rx));
394

knopp's avatar
knopp committed
395
    if (wait_on_condition(&proc->mutex_rxtx,&proc->cond_rxtx,&proc->instance_cnt_rxtx,thread_name)<0) break;
396

397
    VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_CPUID_ENB_THREAD_RXTX,sched_getcpu());
knopp's avatar
knopp committed
398
    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_RXTX0+(proc->subframe_rx&1), 1 );
399 400 401 402 403 404
   
    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);
 
405

406 407
    if (oai_exit) break;

408
    if (eNB->CC_id==0)
409
    {
410
      if (rxtx(eNB,proc,thread_name) < 0) break;
411
    }
412 413

    if (release_thread(&proc->mutex_rxtx,&proc->instance_cnt_rxtx,thread_name)<0) break;
414 415 416 417 418 419 420 421
    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
422
    if (nfapi_mode!=2){
423 424
    	if(get_thread_parallel_conf() == PARALLEL_RU_L1_TRX_SPLIT)      wakeup_tx(eNB,eNB->proc.ru_proc);
    	else if(get_thread_parallel_conf() == PARALLEL_RU_L1_SPLIT)
Wang Tsu-Han's avatar
Wang Tsu-Han committed
425 426 427 428
    	{
    		phy_procedures_eNB_TX(eNB, proc, 1);
    		wakeup_txfh(proc,eNB->proc.ru_proc);
    	}
429
    }
430

knopp's avatar
knopp committed
431
  } // while !oai_exit
432

knopp's avatar
knopp committed
433
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_RXTX0+(proc->subframe_rx&1), 0 );
434

435
  LOG_D(PHY, " *** Exiting eNB thread RXn_TXnp4\n");
436

knopp's avatar
knopp committed
437 438
  eNB_thread_rxtx_status = 0;
  return &eNB_thread_rxtx_status;
439 440
}

441
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
442
{
443 444
  eNB_proc_t *proc           = &eNB->proc;
  eNB_rxtx_proc_t *proc_rxtx = &proc->proc_rxtx[0];
445
  LTE_DL_FRAME_PARMS *fp = ru->frame_parms;
knopp's avatar
knopp committed
446
  RU_proc_t *ru_proc=&ru->proc;
447

448 449
  proc->frame_rx    = frame_rx;
  proc->subframe_rx = subframe_rx;
knopp's avatar
knopp committed
450

Cedric Roux's avatar
Cedric Roux committed
451
  if (!oai_exit) {
452
    T(T_ENB_MASTER_TICK, T_INT(0), T_INT(proc->frame_rx), T_INT(proc->subframe_rx));
knopp's avatar
knopp committed
453

knopp's avatar
knopp committed
454 455 456 457 458
    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;
knopp's avatar
knopp committed
459

460
    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);
knopp's avatar
knopp committed
461 462 463
    ru_proc->timestamp_tx = proc_rxtx->timestamp_tx;
    ru_proc->subframe_tx  = proc_rxtx->subframe_tx;
    ru_proc->frame_tx     = proc_rxtx->frame_tx;
464
  }
knopp's avatar
knopp committed
465 466
}

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

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

509 510 511 512
int wakeup_tx(PHY_VARS_eNB *eNB,RU_proc_t *ru_proc) {

  eNB_proc_t *proc=&eNB->proc;

513 514
  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];
515 516 517 518 519 520

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

534
  ++proc_rxtx1->instance_cnt_rxtx;
535 536

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

  return(0);
}
knopp's avatar
knopp committed
554

555 556 557
int wakeup_rxtx(PHY_VARS_eNB *eNB,RU_t *ru) {

  eNB_proc_t *proc=&eNB->proc;
558
  RU_proc_t *ru_proc=&ru->proc;
559

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

  LTE_DL_FRAME_PARMS *fp = &eNB->frame_parms;
565 566 567 568

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




591 592
  wait.tv_sec=0;
  wait.tv_nsec=5000000L;
593

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

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

615
  ++proc_rxtx0->instance_cnt_rxtx;
616 617 618 619 620
  
  // 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, 
621 622
  // 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
623 624 625 626 627
  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;
628

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

  return(0);
}

641
void wakeup_prach_eNB(PHY_VARS_eNB *eNB,RU_t *ru,int frame,int subframe) {
642 643 644

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

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

}

700
#if (RRC_VERSION >= MAKE_VERSION(14, 0, 0))
701 702 703 704 705 706 707 708 709 710
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]) {
knopp's avatar
knopp committed
711
	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);
712 713 714 715 716 717 718 719
	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);
knopp's avatar
knopp committed
720
      return;
721 722 723 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
    }
    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

Wang Tsu-Han's avatar
Wang Tsu-Han committed
761

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

770 771 772

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

774 775 776
  // set default return value
  eNB_thread_prach_status = 0;

777
  thread_top_init("eNB_thread_prach",1,500000,1000000,20000000);
778

779
  //wait_sync("eNB_thread_prach");
780

781 782 783
  while (!oai_exit) {
    

784
    
knopp's avatar
knopp committed
785
    if (wait_on_condition(&proc->mutex_prach,&proc->cond_prach,&proc->instance_cnt_prach,"eNB_prach_thread") < 0) break;
786
    if (oai_exit) break;
787 788

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

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

800 801
  eNB_thread_prach_status = 0;
  return &eNB_thread_prach_status;
802 803
}

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

820
  thread_top_init("eNB_thread_prach_br",1,500000,1000000,20000000);
821 822 823 824 825 826

  while (!oai_exit) {
    
    

    if (wait_on_condition(&proc->mutex_prach_br,&proc->cond_prach_br,&proc->instance_cnt_prach_br,"eNB_prach_thread_br") < 0) break;
827
    if (oai_exit) break;
828 829 830 831 832 833 834 835 836 837 838 839 840 841

    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
knopp's avatar
knopp committed
842

knopp's avatar
knopp committed
843

844

Wang Tsu-Han's avatar
Wang Tsu-Han committed
845
extern void init_td_thread(PHY_VARS_eNB *);
Eurecom's avatar
Eurecom committed
846
extern void init_te_thread(PHY_VARS_eNB *);
Wang Tsu-Han's avatar
Wang Tsu-Han committed
847 848
extern void kill_td_thread(PHY_VARS_eNB *);
extern void kill_te_thread(PHY_VARS_eNB *);
849

850
static void* process_stats_thread(void* param) {
851 852 853

  PHY_VARS_eNB     *eNB      = (PHY_VARS_eNB*)param;

854
  wait_sync("process_stats_thread");
855 856

  while (!oai_exit) {
Wang Tsu-Han's avatar
Wang Tsu-Han committed
857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873
    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);
       }
874
       print_meas(&eNB->dlsch_modulation_stats,"dlsch_modulation",NULL,NULL);
875 876 877 878 879
     }
  }
  return(NULL);
}

880

881
void init_eNB_proc(int inst) {
882
  
883
  /*int i=0;*/
884
  int CC_id;
885 886
  PHY_VARS_eNB *eNB;
  eNB_proc_t *proc;
knopp's avatar
knopp committed
887
  eNB_rxtx_proc_t *proc_rxtx;
Wang Tsu-Han's avatar
Wang Tsu-Han committed
888
  pthread_attr_t *attr0=NULL,*attr1=NULL,*attr_prach=NULL;
889
#if (RRC_VERSION >= MAKE_VERSION(14, 0, 0))
890 891
  pthread_attr_t *attr_prach_br=NULL;
#endif
knopp's avatar
knopp committed
892

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

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

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

knopp's avatar
knopp committed
912 913
    proc->first_rx=1;
    proc->first_tx=1;
914 915
    proc->RU_mask=0;
    proc->RU_mask_prach=0;
knopp's avatar
knopp committed
916

917
    pthread_mutex_init( &eNB->UL_INFO_mutex, NULL);
918 919 920 921
    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);
knopp's avatar
knopp committed
922 923 924

    pthread_mutex_init( &proc->mutex_prach, NULL);
    pthread_mutex_init( &proc->mutex_asynch_rxtx, NULL);
925 926
    pthread_mutex_init( &proc->mutex_RU,NULL);
    pthread_mutex_init( &proc->mutex_RU_PRACH,NULL);
knopp's avatar
knopp committed
927

928
    pthread_cond_init( &proc->cond_prach, NULL);
929
    pthread_cond_init( &proc->cond_asynch_rxtx, NULL);
930 931 932 933 934

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

knopp's avatar
knopp committed
951 952
    //    attr_td     = &proc->attr_td;
    //    attr_te     = &proc->attr_te; 
knopp's avatar
knopp committed
953
#endif
Wang Tsu-Han's avatar
Wang Tsu-Han committed
954

955
    if(get_thread_worker_conf() == WORKER_ENABLE)
956 957
    {
      init_te_thread(eNB);
Wang Tsu-Han's avatar
Wang Tsu-Han committed
958
      init_td_thread(eNB);
959
    }
knopp's avatar
knopp committed
960 961


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

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

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

983
    if (opp_enabled == 1) pthread_create(&proc->process_stats_thread,NULL,process_stats_thread,(void*)eNB);
984

985
    
986
  }
987

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

993 994 995
     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*));
996

997 998 999 1000 1001 1002 1003
     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);
     }
     }
     }
  */
1004

1005 1006 1007 1008
  /* 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;
1009 1010
  
  
1011 1012
}

1013

1014

1015 1016 1017
/*!
 * \brief Terminate eNB TX and RX threads.
 */
1018
void kill_eNB_proc(int inst) {
1019

1020
  int *status;
1021 1022
  PHY_VARS_eNB *eNB;
  eNB_proc_t *proc;
knopp's avatar
knopp committed
1023
  eNB_rxtx_proc_t *proc_rxtx;
1024
  int i;
1025
  for (int CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
1026
    eNB=RC.eNB[inst][CC_id];
1027 1028
    
    proc = &eNB->proc;
knopp's avatar
knopp committed
1029
    proc_rxtx = &proc->proc_rxtx[0];
1030

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

1048
    pthread_cond_signal( &proc->cond_asynch_rxtx );
1049
    pthread_cond_broadcast(&sync_phy_proc.cond_phy_proc_tx);
Raymond Knopp's avatar
Raymond Knopp committed
1050

1051
    LOG_D(PHY, "joining pthread_prach\n");
1052
    pthread_join( proc->pthread_prach, (void**)&status );    
1053

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

    pthread_attr_destroy(&proc->attr_prach);
    pthread_attr_destroy(&proc->attr_asynch_rxtx);
    pthread_attr_destroy(&proc_rxtx[0].attr_rxtx);
    pthread_attr_destroy(&proc_rxtx[1].attr_rxtx);
#ifdef Rel14
    pthread_mutex_destroy(&proc->mutex_RU_PRACH_br);
    pthread_attr_destroy(&proc->attr_prach_br);
#endif

1083
  }
1084 1085
}

1086

1087 1088 1089


void reset_opp_meas(void) {
1090

1091 1092 1093 1094 1095
  int sfn;
  reset_meas(&softmodem_stats_mt);
  reset_meas(&softmodem_stats_hw);
  
  for (sfn=0; sfn < 10; sfn++) {
knopp's avatar
knopp committed
1096
    reset_meas(&softmodem_stats_rxtx_sf);
1097
    reset_meas(&softmodem_stats_rx_sf);
1098 1099 1100
  }
}

1101

1102 1103 1104 1105 1106 1107 1108
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++) {
knopp's avatar
knopp committed
1109
    print_meas(&softmodem_stats_rxtx_sf,"[eNB][total_phy_proc_rxtx]",NULL, NULL);
1110
    print_meas(&softmodem_stats_rx_sf,"[eNB][total_phy_proc_rx]",NULL,NULL);
1111 1112
  }
}
1113

1114 1115 1116 1117 1118 1119
void free_transport(PHY_VARS_eNB *eNB)
{
  int i;
  int j;

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

1123
    LOG_D(PHY, "Freeing Transport Channel Buffer for ULSCH, UE %d\n",i);
1124 1125 1126 1127 1128
    free_eNB_ulsch(eNB->ulsch[1+i]);
  }
  free_eNB_ulsch(eNB->ulsch[0]);
}

1129
void init_transport(PHY_VARS_eNB *eNB) {
1130

1131 1132 1133
  int i;
  int j;
  LTE_DL_FRAME_PARMS *fp = &eNB->frame_parms;
knopp's avatar
knopp committed
1134

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

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

void init_eNB_afterRU(void) {
knopp's avatar
knopp committed
1195

1196 1197
  int inst,CC_id,ru_id,i,aa;
  PHY_VARS_eNB *eNB;
1198

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

1201
  for (inst=0;inst<RC.nb_inst;inst++) {
1202
    LOG_I(PHY,"RC.nb_CC[inst]:%d\n", RC.nb_CC[inst]);
1203
    for (CC_id=0;CC_id<RC.nb_CC[inst];CC_id++) {
1204 1205 1206

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

1207 1208 1209
      eNB                                  =  RC.eNB[inst][CC_id];
      phy_init_lte_eNB(eNB,0,0);
      // map antennas and PRACH signals to eNB RX
1210
      if (0) AssertFatal(eNB->num_RU>0,"Number of RU attached to eNB %d is zero\n",eNB->Mod_id);
1211
      LOG_I(PHY,"Mapping RX ports from %d RUs to eNB %d\n",eNB->num_RU,eNB->Mod_id);
1212
      eNB->frame_parms.nb_antennas_rx       = 0;
1213