lte-enb.c 50.5 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
 */
ISIP CS/NCTU's avatar
ISIP CS/NCTU committed
32 33 34 35 36 37 38 39 40 41 42 43
 
/*! \function wakeup_txfh
 * \brief Implementation of creating multiple RU threads for beamforming emulation
 * \author TH Wang(Judy), TY Hsu, SY Yeh(fdragon)
 * \date 2018
 * \version 0.1
 * \company Eurecom and ISIP@NCTU
 * \email: Tsu-Han.Wang@eurecom.fr,tyhsu@cs.nctu.edu.tw,fdragon.cs96g@g2.nctu.edu.tw
 * \note
 * \warning
 */

44

Raymond Knopp's avatar
Raymond Knopp committed
45 46
#define _GNU_SOURCE
#include <pthread.h>
47

48

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

51 52
#include "rt_wrapper.h"

53
#include "assertions.h"
54

55 56 57

#include "PHY/types.h"

58 59 60 61 62 63
#include "PHY/INIT/phy_init.h"

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

64 65 66 67 68 69 70
#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

71
#include "PHY/LTE_TRANSPORT/if4_tools.h"
72
#include "PHY/LTE_TRANSPORT/if5_tools.h"
73

74 75 76 77 78 79 80 81
#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"
82
#include "common/utils/LOG/log.h"
83 84 85
#include "UTIL/OTG/otg_tx.h"
#include "UTIL/OTG/otg_externs.h"
#include "UTIL/MATH/oml.h"
86
#include "common/utils/LOG/vcd_signal_dumper.h"
87 88
#include "UTIL/OPT/opt.h"
#include "enb_config.h"
89

90 91

#ifndef OPENAIR2
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
92
  #include "UTIL/OTG/otg_extern.h"
93 94 95
#endif

#if defined(ENABLE_ITTI)
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
96 97 98 99 100 101
  #if defined(ENABLE_USE_MME)
    #include "s1ap_eNB.h"
    #ifdef PDCP_USE_NETLINK
      #include "SIMULATION/ETH_TRANSPORT/proto.h"
    #endif
  #endif
102 103
#endif

Rohit Gupta's avatar
Rohit Gupta committed
104 105
#include "T.h"

106 107 108 109 110 111 112 113 114 115
//#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;

116 117
// Fix per CC openair rf/if device update
// extern openair0_device openair0;
118

119

120
#if defined(ENABLE_ITTI)
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
121 122
  extern volatile int             start_eNB;
  extern volatile int             start_UE;
123 124 125
#endif
extern volatile int                    oai_exit;

Cedric Roux's avatar
Cedric Roux committed
126
extern int transmission_mode;
127

128 129
extern int oaisim_flag;

130 131 132
//uint16_t sf_ahead=4;
extern uint16_t sf_ahead;

133

134
//pthread_t                       main_eNB_thread;
135 136 137

time_stats_t softmodem_stats_mt; // main thread
time_stats_t softmodem_stats_hw; //  hw acquisition
138
time_stats_t softmodem_stats_rxtx_sf; // total tx time
139
time_stats_t nfapi_meas; // total tx time
140
time_stats_t softmodem_stats_rx_sf; // total rx time
141 142 143 144 145 146 147 148 149

/* 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;
150
} sync_phy_proc;
151

152 153
extern double cpuf;

154

155
void init_eNB(int,int);
156
void stop_eNB(int nb_inst);
157

158
int wakeup_tx(PHY_VARS_eNB *eNB);
159
int wakeup_txfh(L1_rxtx_proc_t *proc,PHY_VARS_eNB *eNB);
160
void wakeup_prach_eNB(PHY_VARS_eNB *eNB,RU_t *ru,int frame,int subframe);
161
#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0))
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
162
  void wakeup_prach_eNB_br(PHY_VARS_eNB *eNB,RU_t *ru,int frame,int subframe);
163
#endif
164

165 166 167 168 169 170 171 172
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)


173
static inline int rxtx(PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc, char *thread_name) {
Raymond Knopp's avatar
Raymond Knopp committed
174
  start_meas(&softmodem_stats_rxtx_sf);
175

176
  //L1_rxtx_proc_t *L1_proc_tx = &eNB->proc.L1_proc_tx;
177

178 179
  // *******************************************************************

180
#if defined(PRE_SCD_THREAD)
181
    RU_t *ru = RC.ru[0];
182
#endif
183

184

185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201
  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
       ) {
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
202 203 204 205 206 207 208 209
      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);
210 211 212 213 214 215 216 217
    }
  }

  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
218 219
  // ****************************************
  // Common RX procedures subframe n
Cedric Roux's avatar
Cedric Roux committed
220 221
  T(T_ENB_PHY_DL_TICK, T_INT(eNB->Mod_id), T_INT(proc->frame_tx), T_INT(proc->subframe_tx));

222
  // if this is IF5 or 3GPP_eNB
223
  if (eNB && eNB->RU_list && eNB->RU_list[0] && eNB->RU_list[0]->function < NGFI_RAU_IF4p5) {
224
    wakeup_prach_eNB(eNB,NULL,proc->frame_rx,proc->subframe_rx);
225
#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0))
226 227 228
    wakeup_prach_eNB_br(eNB,NULL,proc->frame_rx,proc->subframe_rx);
#endif
  }
229

Wang Tsu-Han's avatar
Wang Tsu-Han committed
230 231
  release_UE_in_freeList(eNB->Mod_id);

Raymond Knopp's avatar
Raymond Knopp committed
232
  // UE-specific RX processing for subframe n
233
  if (nfapi_mode == 0 || nfapi_mode == 1) {
234
    phy_procedures_eNB_uespec_RX(eNB, proc);
235
  }
236

Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
237 238
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_DLSCH_ULSCH_SCHEDULER, 1 );

239 240 241 242
#if defined(PRE_SCD_THREAD)
    if (nfapi_mode == 2){
      new_dlsch_ue_select_tbl_in_use = dlsch_ue_select_tbl_in_use;
      dlsch_ue_select_tbl_in_use = !dlsch_ue_select_tbl_in_use;
243 244 245 246 247 248 249

// L2-emulator can work only one eNB.
//      memcpy(&pre_scd_eNB_UE_stats,&RC.mac[ru->eNB_list[0]->Mod_id]->UE_list.eNB_UE_stats, sizeof(eNB_UE_STATS)*MAX_NUM_CCs*NUMBER_OF_UE_MAX);
//      memcpy(&pre_scd_activeUE, &RC.mac[ru->eNB_list[0]->Mod_id]->UE_list.active, sizeof(boolean_t)*NUMBER_OF_UE_MAX);
      memcpy(&pre_scd_eNB_UE_stats,&RC.mac[0]->UE_list.eNB_UE_stats, sizeof(eNB_UE_STATS)*MAX_NUM_CCs*NUMBER_OF_UE_MAX);
      memcpy(&pre_scd_activeUE, &RC.mac[0]->UE_list.active, sizeof(boolean_t)*NUMBER_OF_UE_MAX);

250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270
      if (pthread_mutex_lock(&ru->proc.mutex_pre_scd)!= 0) {
          LOG_E( PHY, "[eNB] error locking proc mutex for eNB pre scd\n");
          exit_fun("error locking mutex_time");
      }

      ru->proc.instance_pre_scd++;

      if (ru->proc.instance_pre_scd == 0) {
          if (pthread_cond_signal(&ru->proc.cond_pre_scd) != 0) {
              LOG_E( PHY, "[eNB] ERROR pthread_cond_signal for eNB pre scd\n" );
              exit_fun( "ERROR pthread_cond_signal cond_pre_scd" );
          }
      }else{
          LOG_E( PHY, "[eNB] frame %d subframe %d rxtx busy instance_pre_scd %d\n",
                 proc->frame_rx,proc->subframe_rx,ru->proc.instance_pre_scd );
      }

      if (pthread_mutex_unlock(&ru->proc.mutex_pre_scd)!= 0) {
          LOG_E( PHY, "[eNB] error unlocking mutex_pre_scd mutex for eNB pre scd\n");
          exit_fun("error unlocking mutex_pre_scd");
      }
271
    }
272
#endif
273 274

  pthread_mutex_lock(&eNB->UL_INFO_mutex);
275 276 277 278 279
  eNB->UL_INFO.frame     = proc->frame_rx;
  eNB->UL_INFO.subframe  = proc->subframe_rx;
  eNB->UL_INFO.module_id = eNB->Mod_id;
  eNB->UL_INFO.CC_id     = eNB->CC_id;
  eNB->if_inst->UL_indication(&eNB->UL_INFO);
280
  pthread_mutex_unlock(&eNB->UL_INFO_mutex);
281

Wang Tsu-Han's avatar
Wang Tsu-Han committed
282 283
  /* this conflict resolution may be totally wrong, to be tested */
  /* CONFLICT RESOLUTION: BEGIN */
284

Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
285 286
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_DLSCH_ULSCH_SCHEDULER, 0 );

287
  if(oai_exit) return(-1);
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
288 289

  if(get_thread_parallel_conf() == PARALLEL_SINGLE_THREAD) {
Wang Tsu-Han's avatar
Wang Tsu-Han committed
290
#ifndef PHY_TX_THREAD
291
    phy_procedures_eNB_TX(eNB, proc, 1);
Wang Tsu-Han's avatar
Wang Tsu-Han committed
292
#endif
293
  }
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
294

Wang Tsu-Han's avatar
Wang Tsu-Han committed
295 296 297
  /* 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
298
  stop_meas( &softmodem_stats_rxtx_sf );
299

300
  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);
301
  LOG_D(PHY, "rxtx:%lld nfapi:%lld tx:%lld rx:%lld prach:%lld ofdm:%lld ",
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
302 303 304 305 306 307
        softmodem_stats_rxtx_sf.p_time, nfapi_meas.p_time,
        TICK_TO_US(eNB->phy_proc_tx),
        TICK_TO_US(eNB->phy_proc_rx),
        TICK_TO_US(eNB->rx_prach),
        TICK_TO_US(eNB->ofdm_mod_stats)
       );
308 309

  LOG_D(PHY,
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
310 311 312 313 314 315 316 317
        "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));
318
  LOG_D(PHY," ulsch[ch:%lld freq:%lld dec:%lld demod:%lld ru:%lld ",
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
319 320 321 322 323
        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));
324
  LOG_D(PHY, "td:%lld dei:%lld dem:%lld llr:%lld tci:%lld ",
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
325 326 327 328 329 330 331 332 333 334 335 336 337
        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
338 339 340
  return(0);
}

341

Wang Tsu-Han's avatar
Wang Tsu-Han committed
342
static void* L1_thread_tx(void* param) {
343

344 345
  L1_proc_t *eNB_proc  = (L1_proc_t*)param;
  L1_rxtx_proc_t *proc = &eNB_proc->L1_proc_tx;
346 347
  PHY_VARS_eNB *eNB = RC.eNB[0][proc->CC_id];
  char thread_name[100];
Wang Tsu-Han's avatar
Wang Tsu-Han committed
348
  sprintf(thread_name,"TXnp4_%d\n",&eNB->proc.L1_proc == proc ? 0 : 1);
349
  thread_top_init(thread_name,1,470000,500000,500000);
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
350

351
  //wait_sync("tx_thread");
352

353
  while (!oai_exit) {
Raymond Knopp's avatar
Raymond Knopp committed
354
    LOG_D(PHY,"L1_thread_tx: Waiting for signal (IC %d)\n",proc->instance_cnt);
Wang Tsu-Han's avatar
Wang Tsu-Han committed
355
    if (wait_on_condition(&proc->mutex,&proc->cond,&proc->instance_cnt,thread_name)<0) break;
356
    if (oai_exit) break;  
357

Raymond Knopp's avatar
Raymond Knopp committed
358
    LOG_D(PHY,"L1_thread_tx: Running for %d.%d\n",proc->frame_tx,proc->subframe_tx);
359 360 361 362 363
    // *****************************************
    // 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)
    // *****************************************
364 365 366 367
    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);
368
    phy_procedures_eNB_TX(eNB, proc, 1);
369

Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
370

Wang Tsu-Han's avatar
Wang Tsu-Han committed
371
    pthread_mutex_lock( &proc->mutex );
372
    VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_L1_PROC_TX_IC,proc->instance_cnt);
373
    proc->instance_cnt = -1;
374
    // the thread can now be woken up
Raymond Knopp's avatar
Raymond Knopp committed
375
    LOG_D(PHY,"L1_thread_tx: signaling completion in %d.%d\n",proc->frame_tx,proc->subframe_tx);
Wang Tsu-Han's avatar
Wang Tsu-Han committed
376
    if (pthread_cond_signal(&proc->cond) != 0) {
377 378 379
      LOG_E( PHY, "[eNB] ERROR pthread_cond_signal for eNB TXnp4 thread\n");
      exit_fun( "ERROR pthread_cond_signal" );
    }
Wang Tsu-Han's avatar
Wang Tsu-Han committed
380
    pthread_mutex_unlock( &proc->mutex );
magounak's avatar
magounak committed
381
    wakeup_txfh(proc,eNB);
382 383 384 385 386
  }

  return 0;
}

387
/*!
388
 * \brief The RX UE-specific and TX thread of eNB.
389
 * \param param is a \ref L1_proc_t structure which contains the info what to process.
390 391
 * \returns a pointer to an int. The storage is not on the heap and must not be freed.
 */
392

Wang Tsu-Han's avatar
Wang Tsu-Han committed
393
static void* L1_thread( void* param ) {
394

395
  static int eNB_thread_rxtx_status;
396
  L1_rxtx_proc_t *proc;
397 398
  // Working
  if(nfapi_mode ==2){
399
    proc = (L1_rxtx_proc_t*)param;
400 401
  }
  else{
402 403
    L1_proc_t *eNB_proc  = (L1_proc_t*)param;
    proc = &eNB_proc->L1_proc;
404 405
  }

406
  PHY_VARS_eNB *eNB = RC.eNB[0][proc->CC_id];
407

Raymond Knopp's avatar
Raymond Knopp committed
408
  char thread_name[100];
409 410
  cpu_set_t cpuset;
  CPU_ZERO(&cpuset);
411
  // set default return value
412
  eNB_thread_rxtx_status = 0;
413

Wang Tsu-Han's avatar
Wang Tsu-Han committed
414
  sprintf(thread_name,"RXn_TXnp4_%d\n",&eNB->proc.L1_proc == proc ? 0 : 1);
415 416 417
  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));
418 419

  while (!oai_exit) {
420
    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_RXTX0+(proc->subframe_rx&1), 0 );
421
    T(T_ENB_MASTER_TICK, T_INT(0), T_INT(proc->frame_rx), T_INT(proc->subframe_rx));
422

Wang Tsu-Han's avatar
Wang Tsu-Han committed
423
    if (wait_on_condition(&proc->mutex,&proc->cond,&proc->instance_cnt,thread_name)<0) break;
424

Raymond Knopp's avatar
Raymond Knopp committed
425
    LOG_D(PHY,"L1_thread wakeup %d.%d\n",proc->frame_rx,proc->subframe_rx);
426
    VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_CPUID_ENB_THREAD_RXTX,sched_getcpu());
427
    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_RXTX0+(proc->subframe_rx&1), 1 );
428 429 430 431
    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);
432
  
433 434
    if (oai_exit) break;

Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
435
    if (eNB->CC_id==0) {
436
      if (rxtx(eNB,proc,thread_name) < 0) break;
437 438
    }

439
    LOG_D(PHY,"L1_thread: RX done in %d.%d\n",proc->frame_rx,proc->subframe_rx);
440
    if(get_thread_parallel_conf() == PARALLEL_RU_L1_SPLIT)              phy_procedures_eNB_TX(eNB, proc, 1);
Wang Tsu-Han's avatar
Wang Tsu-Han committed
441
    if (release_thread(&proc->mutex,&proc->instance_cnt,thread_name)<0) break;
442
    LOG_D(PHY,"L1_thread: IC %d\n",proc->instance_cnt);
443
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_L1_PROC_IC,proc->instance_cnt);
Wang Tsu-Han's avatar
Wang Tsu-Han committed
444
    if (nfapi_mode!=2){
445
    	if(get_thread_parallel_conf() == PARALLEL_RU_L1_TRX_SPLIT)      wakeup_tx(eNB);
446
    	else if(get_thread_parallel_conf() == PARALLEL_RU_L1_SPLIT)     wakeup_txfh(proc,eNB);
447
    }
Raymond Knopp's avatar
Raymond Knopp committed
448
  } // while !oai_exit
449

450
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_RXTX0+(proc->subframe_rx&1), 0 );
451
  LOG_D(PHY, " *** Exiting eNB thread RXn_TXnp4\n");
452 453
  eNB_thread_rxtx_status = 0;
  return &eNB_thread_rxtx_status;
454 455
}

456
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
457
{
458 459
  L1_proc_t *proc           = &eNB->proc;
  L1_rxtx_proc_t *L1_proc = &proc->L1_proc;
Raymond Knopp's avatar
Raymond Knopp committed
460 461
  LTE_DL_FRAME_PARMS *fp = &ru->frame_parms;
  RU_proc_t *ru_proc=&ru->proc;
462 463
  proc->frame_rx    = frame_rx;
  proc->subframe_rx = subframe_rx;
Raymond Knopp's avatar
Raymond Knopp committed
464

Cedric Roux's avatar
Cedric Roux committed
465
  if (!oai_exit) {
466
    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
467

Wang Tsu-Han's avatar
Wang Tsu-Han committed
468 469 470 471 472
    L1_proc->timestamp_tx = ru_proc->timestamp_rx + (sf_ahead*fp->samples_per_tti);
    L1_proc->frame_rx     = ru_proc->frame_rx;
    L1_proc->subframe_rx  = ru_proc->subframe_rx;
    L1_proc->frame_tx     = (L1_proc->subframe_rx > (9-sf_ahead)) ? (L1_proc->frame_rx+1)&1023 : L1_proc->frame_rx;
    L1_proc->subframe_tx  = (L1_proc->subframe_rx + sf_ahead)%10;
Raymond Knopp's avatar
Raymond Knopp committed
473

Wang Tsu-Han's avatar
Wang Tsu-Han committed
474 475 476 477
    if (rxtx(eNB,L1_proc,string) < 0) LOG_E(PHY,"eNB %d CC_id %d failed during execution\n",eNB->Mod_id,eNB->CC_id);
    ru_proc->timestamp_tx = L1_proc->timestamp_tx;
    ru_proc->subframe_tx  = L1_proc->subframe_tx;
    ru_proc->frame_tx     = L1_proc->frame_tx;
478
  }
Raymond Knopp's avatar
Raymond Knopp committed
479 480
}

481
int wakeup_txfh(L1_rxtx_proc_t *proc,PHY_VARS_eNB *eNB) {
Wang Tsu-Han's avatar
Wang Tsu-Han committed
482
  RU_t *ru;
ISIP CS/NCTU's avatar
ISIP CS/NCTU committed
483
  RU_proc_t *ru_proc;
Raymond Knopp's avatar
Raymond Knopp committed
484
  LTE_DL_FRAME_PARMS *fp; 
485 486


487 488 489
  struct timespec wait;
  wait.tv_sec=0;
  wait.tv_nsec=5000000L;
490

491
  LOG_D(PHY,"wakeup_txfh %d.%d IC_RU = %d\n", proc->frame_tx, proc->subframe_tx, proc->instance_cnt_RUs);
492
  if(wait_on_condition(&proc->mutex_RUs,&proc->cond_RUs,&proc->instance_cnt_RUs,"wakeup_txfh")<0) {
Wang Tsu-Han's avatar
Wang Tsu-Han committed
493
    LOG_E(PHY,"Frame %d, subframe %d: TX FH not ready\n", proc->frame_tx, proc->subframe_tx);
494
    return(-1);
495
  }
Raymond Knopp's avatar
Raymond Knopp committed
496
/*
497
  pthread_mutex_lock(&eNB->proc.mutex_RU_tx);
magounak's avatar
magounak committed
498
  //eNB->proc.RU_mask_tx = 0;
499
  pthread_mutex_unlock(&eNB->proc.mutex_RU_tx);
Raymond Knopp's avatar
Raymond Knopp committed
500
*/
501
  if (release_thread(&proc->mutex_RUs,&proc->instance_cnt_RUs,"wakeup_txfh")<0) return(-1);
magounak's avatar
magounak committed
502

503
  for(int ru_id=0; ru_id<eNB->num_RU; ru_id++){
504 505
    ru_proc = &eNB->RU_list[ru_id]->proc;
    fp = &eNB->RU_list[ru_id]->frame_parms;
Raymond Knopp's avatar
Raymond Knopp committed
506 507 508 509 510 511 512 513
    if (((fp->frame_type == TDD) && (subframe_select(fp,proc->subframe_tx)==SF_UL))||
        (eNB->RU_list[ru_id]->state == RU_SYNC)||
        (eNB->RU_list[ru_id]->wait_cnt>0)){
       pthread_mutex_lock(&proc->mutex_RUs);
       proc->instance_cnt_RUs = 0;
       pthread_mutex_unlock(&proc->mutex_RUs);
       continue;//hacking only works when all RU_tx works on the same subframe #TODO: adding mask stuff
    }
Wang Tsu-Han's avatar
Wang Tsu-Han committed
514
    if (ru_proc->instance_cnt_eNBs == 0) {
Raymond Knopp's avatar
Raymond Knopp committed
515 516
        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);
        return(-1);
Wang Tsu-Han's avatar
Wang Tsu-Han committed
517
    }
Raymond Knopp's avatar
Raymond Knopp committed
518 519 520 521
    if (pthread_mutex_lock(&ru_proc->mutex_eNBs) != 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);
Wang Tsu-Han's avatar
Wang Tsu-Han committed
522
    }
523
    ru_proc->instance_cnt_eNBs = 0;
Raymond Knopp's avatar
Raymond Knopp committed
524
    //VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_IC_ENB+ru_id,ru_proc->instance_cnt_eNBs);
Wang Tsu-Han's avatar
Wang Tsu-Han committed
525 526 527
    ru_proc->timestamp_tx = proc->timestamp_tx;
    ru_proc->subframe_tx  = proc->subframe_tx;
    ru_proc->frame_tx     = proc->frame_tx;
Raymond Knopp's avatar
Raymond Knopp committed
528 529
        
   // printf("wakeup_txfh: RU %d, frame_tx %d, subframe_tx %d\n",ru_id,ru_proc->frame_tx,ru_proc->subframe_tx);
530
        
Wang Tsu-Han's avatar
Wang Tsu-Han committed
531 532
    // the thread can now be woken up
    if (pthread_cond_signal(&ru_proc->cond_eNBs) != 0) {
Raymond Knopp's avatar
Raymond Knopp committed
533 534 535
       LOG_E( PHY, "[eNB] ERROR pthread_cond_signal for eNB TXnp4 thread\n");
       exit_fun( "ERROR pthread_cond_signal" );
       return(-1);
Wang Tsu-Han's avatar
Wang Tsu-Han committed
536 537
    }
    pthread_mutex_unlock( &ru_proc->mutex_eNBs );
538
  }
539
  return(0);
Raymond Knopp's avatar
Raymond Knopp committed
540 541
}

542
int wakeup_tx(PHY_VARS_eNB *eNB) {
543

544
  L1_proc_t *proc=&eNB->proc;
545

546 547
  L1_rxtx_proc_t *L1_proc_tx = &proc->L1_proc_tx;
  L1_rxtx_proc_t *L1_proc    = &proc->L1_proc;
548 549 550 551 552

  
  struct timespec wait;
  wait.tv_sec=0;
  wait.tv_nsec=5000000L;
Raymond Knopp's avatar
Raymond Knopp committed
553
  LOG_D(PHY,"ENTERED wakeup_tx (IC %d)\n",L1_proc_tx->instance_cnt);
554
  
magounak's avatar
magounak committed
555
  if (pthread_mutex_lock(&L1_proc_tx->mutex) != 0) {
556 557
    LOG_E(PHY, "[SCHED][eNB] ERROR locking mutex for eNB L1_thread_tx\n");
    exit_fun("ERROR pthread_lock");
558 559
    return(-1);
  }
magounak's avatar
magounak committed
560
  while(L1_proc_tx->instance_cnt == 0){ //check if the previous has finished
561
    pthread_cond_wait(&L1_proc_tx->cond,&L1_proc_tx->mutex);
562
  }
563
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_L1_PROC_TX_IC,L1_proc_tx->instance_cnt);
magounak's avatar
magounak committed
564
  L1_proc_tx->instance_cnt = 0; // set go for the current one
565
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_L1_PROC_TX_IC,L1_proc_tx->instance_cnt);
566
  
Wang Tsu-Han's avatar
Wang Tsu-Han committed
567 568 569 570 571
  L1_proc_tx->subframe_rx   = L1_proc->subframe_rx;
  L1_proc_tx->frame_rx      = L1_proc->frame_rx;
  L1_proc_tx->subframe_tx   = L1_proc->subframe_tx;
  L1_proc_tx->frame_tx      = L1_proc->frame_tx;
  L1_proc_tx->timestamp_tx  = L1_proc->timestamp_tx;
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
572

573
  // the thread can now be woken up
Raymond Knopp's avatar
Raymond Knopp committed
574
  LOG_D(PHY,"Waking up TX thread in %d.%d\n",L1_proc->frame_tx,L1_proc->subframe_tx);
Wang Tsu-Han's avatar
Wang Tsu-Han committed
575
  if (pthread_cond_signal(&L1_proc_tx->cond) != 0) {
576
    LOG_E( PHY, "[eNB] ERROR pthread_cond_signal for eNB TXnp4 thread\n");
577 578 579 580
    exit_fun( "ERROR pthread_cond_signal" );
    return(-1);
  }
  
Wang Tsu-Han's avatar
Wang Tsu-Han committed
581
  pthread_mutex_unlock( &L1_proc_tx->mutex);
582 583
  return(0);
}
Raymond Knopp's avatar
Raymond Knopp committed
584

585 586
int wakeup_rxtx(PHY_VARS_eNB *eNB,RU_t *ru) {

587
  L1_proc_t *proc=&eNB->proc;
588
  RU_proc_t *ru_proc=&ru->proc;
589

590
  L1_rxtx_proc_t *L1_proc=&proc->L1_proc;
591
  LTE_DL_FRAME_PARMS *fp = &eNB->frame_parms;
magounak's avatar
magounak committed
592
  
593
  LOG_D(PHY,"ENTERED wakeup_rxtx, %d.%d\n",ru_proc->frame_rx,ru_proc->subframe_rx);
magounak's avatar
magounak committed
594
  
595 596 597 598 599 600
  int i;
  struct timespec wait;
  
  wait.tv_sec=0;
  wait.tv_nsec=5000000L;

Cedric Roux's avatar
Cedric Roux committed
601
  // wake up TX for subframe n+sf_ahead
602
  // lock the TX mutex and make sure the thread is ready
magounak's avatar
magounak committed
603
  if (pthread_mutex_lock(&L1_proc->mutex) != 0) {
Wang Tsu-Han's avatar
Wang Tsu-Han committed
604
    LOG_E( PHY, "[eNB] ERROR pthread_mutex_lock for eNB RXTX thread %d (IC %d)\n", L1_proc->subframe_rx&1,L1_proc->instance_cnt );
605 606 607
    exit_fun( "error locking mutex_rxtx" );
    return(-1);
  }
608
  if (L1_proc->instance_cnt == 0) {
609 610 611 612 613 614 615 616
    pthread_mutex_unlock(&L1_proc->mutex);
    usleep(200);
    if (pthread_mutex_lock(&L1_proc->mutex) != 0) {
      LOG_E( PHY, "[eNB] ERROR pthread_mutex_lock for eNB RXTX thread %d (IC %d)\n", L1_proc->subframe_rx&1,L1_proc->instance_cnt );
      exit_fun( "error locking mutex_rxtx" );
      return(-1);
    }
    if (L1_proc->instance_cnt == 0) LOG_E(PHY,"Frame %d, subframe %d: RXTX0 thread busy, dropping\n",ru_proc->frame_rx,ru_proc->subframe_rx);
617
  }
618
  if (L1_proc->instance_cnt == -1) {
619 620 621
    VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_L1_PROC_IC,L1_proc->instance_cnt);
    ++L1_proc->instance_cnt;
    VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_L1_PROC_IC,L1_proc->instance_cnt);
622

623 624 625
  // 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).
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
626
  // The last (TS_rx mod samples_per_frame) was n*samples_per_tti,
627 628
  // 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
629 630 631 632 633
    L1_proc->timestamp_tx = ru_proc->timestamp_rx + (sf_ahead*fp->samples_per_tti);
    L1_proc->frame_rx     = ru_proc->frame_rx;
    L1_proc->subframe_rx  = ru_proc->subframe_rx;
    L1_proc->frame_tx     = (L1_proc->subframe_rx > (9-sf_ahead)) ? (L1_proc->frame_rx+1)&1023 : L1_proc->frame_rx;
    L1_proc->subframe_tx  = (L1_proc->subframe_rx + sf_ahead)%10;
634

635
    LOG_D(PHY,"wakeup_rxtx: L1_proc->subframe_rx %d, L1_proc->subframe_tx %d, RU %d\n",L1_proc->subframe_rx,L1_proc->subframe_tx,ru->idx);
636

637 638 639 640
    VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_WAKEUP_RXTX_RX_RU+ru->idx, L1_proc->frame_rx);
    VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_WAKEUP_RXTX_RX_RU+ru->idx, L1_proc->subframe_rx);
    VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_WAKEUP_RXTX_TX_RU+ru->idx, L1_proc->frame_tx);
    VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_WAKEUP_RXTX_TX_RU+ru->idx, L1_proc->subframe_tx);
magounak's avatar
magounak committed
641

642
  // the thread can now be woken up
643 644 645 646 647
    if (pthread_cond_signal(&L1_proc->cond) != 0) {
      LOG_E( PHY, "[eNB] ERROR pthread_cond_signal for eNB RXn-TXnp4 thread\n");
      exit_fun( "ERROR pthread_cond_signal" );
      return(-1);
    }
648
  }
Wang Tsu-Han's avatar
Wang Tsu-Han committed
649
  pthread_mutex_unlock( &L1_proc->mutex);
650 651 652
  return(0);
}

653
void wakeup_prach_eNB(PHY_VARS_eNB *eNB,RU_t *ru,int frame,int subframe) {
654

655
  L1_proc_t *proc = &eNB->proc;
656
  LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms;
657
  int i;
658

659 660
  if (ru!=NULL) {
    pthread_mutex_lock(&proc->mutex_RU_PRACH);
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
661 662

    for (i=0; i<eNB->num_RU; i++) {
663
      if (ru == eNB->RU_list[i]) {
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
664 665 666 667 668 669
        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);

        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",
                eNB->Mod_id,frame,subframe,ru->idx,eNB->num_RU,proc->RU_mask_prach);

670
        proc->RU_mask_prach |= (1<<i);
671 672
      }
    }
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
673

674 675
    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
676
      return;
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
677
    } else { // all RUs have provided their information so continue on and wakeup eNB processing
678 679 680 681
      proc->RU_mask_prach = 0;
      pthread_mutex_unlock(&proc->mutex_RU_PRACH);
    }
  }
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
682

683
  // check if we have to detect PRACH first
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
684
  if (is_prach_subframe(fp,frame,subframe)>0) {
685
    LOG_D(PHY,"Triggering prach processing, frame %d, subframe %d\n",frame,subframe);
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
686

687
    if (proc->instance_cnt_prach == 0) {
688
      LOG_W(PHY,"[eNB] Frame %d Subframe %d, dropping PRACH\n", frame,subframe);
689 690
      return;
    }
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
691

692 693 694 695 696 697
    // 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;
    }
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
698

699 700
    ++proc->instance_cnt_prach;
    // set timing for prach thread
701 702
    proc->frame_prach = frame;
    proc->subframe_prach = subframe;
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
703

704 705 706 707 708 709
    // 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;
    }
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
710

711 712 713 714
    pthread_mutex_unlock( &proc->mutex_prach );
  }
}

715
#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0))
716 717
void wakeup_prach_eNB_br(PHY_VARS_eNB *eNB,RU_t *ru,int frame,int subframe) {

718
  L1_proc_t *proc = &eNB->proc;
719 720 721 722 723
  LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms;
  int i;

  if (ru!=NULL) {
    pthread_mutex_lock(&proc->mutex_RU_PRACH_br);
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
724 725

    for (i=0; i<eNB->num_RU; i++) {
726
      if (ru == eNB->RU_list[i]) {
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
727 728 729 730 731
        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);

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

Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
733
        proc->RU_mask_prach_br |= (1<<i);
734 735
      }
    }
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
736

737 738
    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
739
      return;
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
740
    } else { // all RUs have provided their information so continue on and wakeup eNB processing
741 742 743 744
      proc->RU_mask_prach_br = 0;
      pthread_mutex_unlock(&proc->mutex_RU_PRACH_br);
    }
  }
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
745

746
  // check if we have to detect PRACH first
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
747
  if (is_prach_subframe(fp,frame,subframe)>0) {
748
    LOG_D(PHY,"Triggering prach br processing, frame %d, subframe %d\n",frame,subframe);
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
749

750 751 752 753
    if (proc->instance_cnt_prach_br == 0) {
      LOG_W(PHY,"[eNB] Frame %d Subframe %d, dropping PRACH BR\n", frame,subframe);
      return;
    }
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
754

755 756 757 758 759 760
    // 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;
    }
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
761

762 763 764 765
    ++proc->instance_cnt_prach_br;
    // set timing for prach thread
    proc->frame_prach_br = frame;
    proc->subframe_prach_br = subframe;
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
766

767 768 769 770 771 772
    // 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;
    }
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
773

774 775 776 777 778
    pthread_mutex_unlock( &proc->mutex_prach_br );
  }
}
#endif

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

780 781
/*!
 * \brief The prach receive thread of eNB.
782
 * \param param is a \ref L1_proc_t structure which contains the info what to process.
783 784
 * \returns a pointer to an int. The storage is not on the heap and must not be freed.
 */
785
static void *eNB_thread_prach( void *param ) {
786
  static int eNB_thread_prach_status;
787
  PHY_VARS_eNB *eNB= (PHY_VARS_eNB *)param;
788
  L1_proc_t *proc = &eNB->proc;
Raymond Knopp's avatar
Raymond Knopp committed
789

790 791
  // set default return value
  eNB_thread_prach_status = 0;
792
  thread_top_init("eNB_thread_prach",1,500000,1000000,20000000);
793

794
  //wait_sync("eNB_thread_prach");
795

796
  while (!oai_exit) {
Raymond Knopp's avatar
Raymond Knopp committed
797
    if (wait_on_condition(&proc->mutex_prach,&proc->cond_prach,&proc->instance_cnt_prach,"eNB_prach_thread") < 0) break;
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
798

799
    if (oai_exit) break;
800 801

    LOG_D(PHY,"Running eNB prach procedures\n");
802
    prach_procedures(eNB
803
#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0))
804
                     ,0
805
#endif
806
                    );
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
807

Raymond Knopp's avatar
Raymond Knopp committed
808
    if (release_thread(&proc->mutex_prach,&proc->instance_cnt_prach,"eNB_prach_thread") < 0) break;
809
  }
810

811
  LOG_I(PHY, "Exiting eNB thread PRACH\n");
812 813
  eNB_thread_prach_status = 0;
  return &eNB_thread_prach_status;
814 815
}

816
#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0))
817 818
/*!
 * \brief The prach receive thread of eNB for BL/CE UEs.
819
 * \param param is a \ref L1_proc_t structure which contains the info what to process.
820 821
 * \returns a pointer to an int. The storage is not on the heap and must not be freed.
 */
822
static void *eNB_thread_prach_br( void *param ) {
823 824
  static int eNB_thread_prach_status;
  PHY_VARS_eNB *eNB= (PHY_VARS_eNB *)param;
825
  L1_proc_t *proc = &eNB->proc;
826 827 828

  // set default return value
  eNB_thread_prach_status = 0;
829
  thread_top_init("eNB_thread_prach_br",1,500000,1000000,20000000);
830 831 832

  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;
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
833

834
    if (oai_exit) break;
835 836 837

    LOG_D(PHY,"Running eNB prach procedures for BL/CE UEs\n");
    prach_procedures(eNB,1);
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
838

839 840 841 842 843 844 845 846 847
    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
848

Raymond Knopp's avatar
Raymond Knopp committed
849

850

Wang Tsu-Han's avatar
Wang Tsu-Han committed
851
extern void init_td_thread(PHY_VARS_eNB *);
Eurecom's avatar
Eurecom committed
852
extern void init_te_thread(PHY_VARS_eNB *);
Wang Tsu-Han's avatar
Wang Tsu-Han committed
853 854
extern void kill_td_thread(PHY_VARS_eNB *);
extern void kill_te_thread(PHY_VARS_eNB *);
855

856 857
static void *process_stats_thread(void *param) {
  PHY_VARS_eNB     *eNB      = (PHY_VARS_eNB *)param;
858
  wait_sync("process_stats_thread");
859 860

  while (!oai_exit) {
Wang Tsu-Han's avatar
Wang Tsu-Han committed
861
    sleep(1);
862 863

    if (opp_enabled == 1) {
864 865
      if ( eNB->ulsch_decoding_stats.trials>0)
        print_meas(&eNB->ulsch_decoding_stats,"ulsch_decoding",NULL,NULL);
866

867
      if (eNB->dlsch_encoding_stats.trials >0) {
868 869 870 871 872 873 874 875 876 877 878
        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);
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
879
      }
880

881 882
      print_meas(&eNB->dlsch_modulation_stats,"dlsch_modulation",NULL,NULL);
    }
883
  }
884

885 886 887
  return(NULL);
}

888

889
void init_eNB_proc(int inst) {
890
  /*int i=0;*/
891
  int CC_id;
892
  PHY_VARS_eNB *eNB;
893 894
  L1_proc_t *proc;
  L1_rxtx_proc_t *L1_proc, *L1_proc_tx;
Raymond Knopp's avatar
Raymond Knopp committed
895
  pthread_attr_t *attr0=NULL,*attr1=NULL,*attr_prach=NULL;
896
#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0))
897 898
  pthread_attr_t *attr_prach_br=NULL;
#endif
899 900
  LOG_I(PHY,"%s(inst:%d) RC.nb_CC[inst]:%d \n",__FUNCTION__,inst,RC.nb_CC[inst]);

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

Wang Tsu-Han's avatar
Wang Tsu-Han committed
908 909 910 911
    L1_proc                        = &proc->L1_proc;
    L1_proc_tx                     = &proc->L1_proc_tx;
    L1_proc->instance_cnt          = -1;
    L1_proc_tx->instance_cnt       = -1;
912 913
    L1_proc->instance_cnt_RUs      = 0;
    L1_proc_tx->instance_cnt_RUs   = 0;
914
    proc->instance_cnt_prach       = -1;
915
    proc->instance_cnt_asynch_rxtx = -1;
Eurecom's avatar
Eurecom committed
916
    proc->instance_cnt_synch       = -1;
917
    proc->CC_id                    = CC_id;    
918

Wang Tsu-Han's avatar
Wang Tsu-Han committed
919 920
    proc->first_rx                 =1;
    proc->first_tx                 =1;
Wang Tsu-Han's avatar
Wang Tsu-Han committed
921
    proc->RU_mask_tx               = (1<<eNB->num_RU)-1;
922
    memset((void*)proc->RU_mask,0,10*sizeof(proc->RU_mask[0]));
Wang Tsu-Han's avatar
Wang Tsu-Han committed
923
    proc->RU_mask_prach            =0;
Raymond Knopp's avatar
Raymond Knopp committed
924

925
    pthread_mutex_init( &eNB->UL_INFO_mutex, NULL);
Wang Tsu-Han's avatar
Wang Tsu-Han committed
926 927 928 929
    pthread_mutex_init( &L1_proc->mutex, NULL);
    pthread_mutex_init( &L1_proc_tx->mutex, NULL);
    pthread_cond_init( &L1_proc->cond, NULL);
    pthread_cond_init( &L1_proc_tx->cond, NULL);
930 931 932 933
    pthread_mutex_init( &L1_proc->mutex_RUs, NULL);
    pthread_mutex_init( &L1_proc_tx->mutex_RUs, NULL);
    pthread_cond_init( &L1_proc->cond_RUs, NULL);
    pthread_cond_init( &L1_proc_tx->cond_RUs, NULL);
Raymond Knopp's avatar
Raymond Knopp committed
934 935 936

    pthread_mutex_init( &proc->mutex_prach, NULL);
    pthread_mutex_init( &proc->mutex_asynch_rxtx, NULL);
937
    pthread_mutex_init( &proc->mutex_RU,NULL);
Wang Tsu-Han's avatar
Wang Tsu-Han committed
938
    pthread_mutex_init( &proc->mutex_RU_tx,NULL);
939
    pthread_mutex_init( &proc->mutex_RU_PRACH,NULL);
940
    pthread_cond_init( &proc->cond_prach, NULL);
941
    pthread_cond_init( &proc->cond_asynch_rxtx, NULL);
942 943
    pthread_attr_init( &proc->attr_prach);
    pthread_attr_init( &proc->attr_asynch_rxtx);
Wang Tsu-Han's avatar
Wang Tsu-Han committed
944 945
    pthread_attr_init( &L1_proc->attr);
    pthread_attr_init( &L1_proc_tx->attr);
946
#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0))
947 948 949 950 951 952 953
    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
954
#ifndef DEADLINE_SCHEDULER
Wang Tsu-Han's avatar
Wang Tsu-Han committed
955 956
    attr0       = &L1_proc->attr;
    attr1       = &L1_proc_tx->attr;
Raymond Knopp's avatar
Raymond Knopp committed
957
    attr_prach  = &proc->attr_prach;
958
#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0))
959 960
    attr_prach_br  = &proc->attr_prach_br;
#endif
Raymond Knopp's avatar
Raymond Knopp committed
961
    //    attr_td     = &proc->attr_td;
962
    //    attr_te     = &proc->attr_te;
Raymond Knopp's avatar
Raymond Knopp committed
963
#endif
Wang Tsu-Han's avatar
Wang Tsu-Han committed
964

965
    if(get_thread_worker_conf() == WORKER_ENABLE) {
966
      init_te_thread(eNB);
Wang Tsu-Han's avatar
Wang Tsu-Han committed
967
      init_td_thread(eNB);
968
    }
969

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

972
    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
973 974
      pthread_create( &L1_proc->pthread, attr0, L1_thread, proc );
      pthread_create( &L1_proc_tx->pthread, attr1, L1_thread_tx, proc);
975
    } else if (nfapi_mode == 2) { // this is neccesary in VNF or L2 FAPI simulator.
976 977 978
      // Original Code from Fujitsu w/ old structure/field name
      //pthread_create( &proc_rxtx[0].pthread_rxtx, attr0, eNB_thread_rxtx, &proc_rxtx[0] );
      //pthread_create( &proc_rxtx[1].pthread_rxtx, attr1, eNB_thread_rxtx, &proc_rxtx[1] );
979 980
      pthread_create( &L1_proc->pthread, attr0, L1_thread, L1_proc );
      pthread_create( &L1_proc_tx->pthread, attr1, L1_thread, L1_proc_tx);
981
    }
982

983
    pthread_create( &proc->pthread_prach, attr_prach, eNB_thread_prach, eNB );
984
#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0))
985 986
    pthread_create( &proc->pthread_prach_br, attr_prach_br, eNB_thread_prach_br, eNB );
#endif
987 988

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

990
    if (opp_enabled == 1) pthread_create(&proc->process_stats_thread,NULL,process_stats_thread,(void *)eNB);
991
  }
992

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

998 999
     if (eNB->node_timing == synch_to_ext_device) { //master
     eNB->proc.num_slaves = MAX_NUM_CCs-1;
1000
     eNB->proc.slave_proc = (L1_proc_t**)malloc(eNB->proc.num_slaves*sizeof(L1_proc_t*));
1001

1002 1003 1004 1005 1006 1007 1008
     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);
     }
     }
     }
  */
1009 1010 1011 1012
  /* 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;
1013 1014
}

1015

1016

1017 1018 1019
/*!
 * \brief Terminate eNB TX and RX threads.
 */
1020
void kill_eNB_proc(int inst) {
1021
  int *status;
1022
  PHY_VARS_eNB *eNB;
1023 1024
  L1_proc_t *proc;
  L1_rxtx_proc_t *L1_proc, *L1_proc_tx;
1025

1026
  for (int CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
1027
    eNB=RC.eNB[inst][CC_id];
Wang Tsu-Han's avatar
Wang Tsu-Han committed
1028 1029 1030
    proc        = &eNB->proc;
    L1_proc     = &proc->L1_proc;
    L1_proc_tx  = &proc->L1_proc_tx;
1031

1032
    if(get_thread_worker_conf() == WORKER_ENABLE) {
1033 1034 1035
      kill_td_thread(eNB);
      kill_te_thread(eNB);
    }
Wang Tsu-Han's avatar
Wang Tsu-Han committed
1036

1037
    LOG_I(PHY, "Killing TX CC_id %d inst %d\n", CC_id, inst );
Wang Tsu-Han's avatar
Wang Tsu-Han committed
1038

1039 1040 1041 1042 1043 1044 1045 1046 1047 1048
    if ((get_thread_parallel_conf() == PARALLEL_RU_L1_SPLIT || get_thread_parallel_conf() == PARALLEL_RU_L1_TRX_SPLIT) && nfapi_mode!=2) {
      pthread_mutex_lock(&L1_proc->mutex);
      L1_proc->instance_cnt = 0;
      pthread_cond_signal(&L1_proc->cond);
      pthread_mutex_unlock(&L1_proc->mutex);

      pthread_mutex_lock(&L1_proc_tx->mutex);
      L1_proc_tx->instance_cnt = 0;
      pthread_cond_signal(&L1_proc_tx->cond);
      pthread_mutex_unlock(&L1_proc_tx->mutex);
1049
    }
Wang Tsu-Han's avatar
Wang Tsu-Han committed
1050

Robert Schmidt's avatar
Robert Schmidt committed
1051
    pthread_mutex_lock(&proc->mutex_prach);
Raymond Knopp's avatar
Raymond Knopp committed
1052 1053
    proc->instance_cnt_prach = 0;
    pthread_cond_signal( &proc->cond_prach );
Robert Schmidt's avatar
Robert Schmidt committed
1054
    pthread_mutex_unlock(&proc->mutex_prach);
1055
    pthread_cond_signal( &proc->cond_asynch_rxtx );
1056
    pthread_cond_broadcast(&sync_phy_proc.cond_phy_proc_tx);
1057
    LOG_D(PHY, "joining pthread_prach\n");
1058
    pthread_join( proc->pthread_prach, (void **)&status );
1059
    LOG_I(PHY, "Destroying prach mutex/cond\n");
1060
    pthread_mutex_destroy( &proc->mutex_prach );
1061
    pthread_cond_destroy( &proc->cond_prach );
1062
#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0))
1063
    proc->instance_cnt_prach_br = 0;
1064
    pthread_cond_signal( &proc->cond_prach_br );
1065
    pthread_join( proc->pthread_prach_br, (void **)&status );
1066 1067
    pthread_mutex_destroy( &proc->mutex_prach_br );
    pthread_cond_destroy( &proc->cond_prach_br );
Wang Tsu-Han's avatar
Wang Tsu-Han committed
1068
#endif
1069
    LOG_I(PHY, "Destroying UL_INFO mutex\n");
1070
    pthread_mutex_destroy(&eNB->UL_INFO_mutex);
Wang Tsu-Han's avatar
Wang Tsu-Han committed
1071 1072 1073 1074 1075 1076

    if ((get_thread_parallel_conf() == PARALLEL_RU_L1_SPLIT || get_thread_parallel_conf() == PARALLEL_RU_L1_TRX_SPLIT) && nfapi_mode!=2) {
      LOG_I(PHY, "Joining L1_proc mutex/cond\n");
      pthread_join( L1_proc->pthread, (void**)&status );
      LOG_I(PHY, "Joining L1_proc_tx mutex/cond\n");
      pthread_join( L1_proc_tx->pthread, (void**)&status );
1077
    }
Wang Tsu-Han's avatar
Wang Tsu-Han committed
1078 1079 1080
    LOG_I(PHY, "Destroying L1_proc mutex/cond\n");
    pthread_mutex_destroy( &L1_proc->mutex );
    pthread_cond_destroy( &L1_proc->cond );
1081 1082
    pthread_mutex_destroy( &L1_proc->mutex_RUs );
    pthread_cond_destroy( &L1_proc->cond_RUs );
Wang Tsu-Han's avatar
Wang Tsu-Han committed
1083 1084 1085
    LOG_I(PHY, "Destroying L1_proc_tx mutex/cond\n");
    pthread_mutex_destroy( &L1_proc_tx->mutex );
    pthread_cond_destroy( &L1_proc_tx->cond );
1086 1087
    pthread_mutex_destroy( &L1_proc_tx->mutex_RUs );
    pthread_cond_destroy( &L1_proc_tx->cond_RUs );
Robert Schmidt's avatar
Robert Schmidt committed
1088 1089 1090

    pthread_attr_destroy(&proc->attr_prach);
    pthread_attr_destroy(&proc->attr_asynch_rxtx);
Wang Tsu-Han's avatar
Wang Tsu-Han committed
1091 1092
    pthread_attr_destroy(&L1_proc->attr);
    pthread_attr_destroy(&L1_proc_tx->attr);
1093
#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0))
Robert Schmidt's avatar
Robert Schmidt committed
1094 1095 1096
    pthread_mutex_destroy(&proc->mutex_RU_PRACH_br);
    pthread_attr_destroy(&proc->attr_prach_br);
#endif
1097
  }
1098 1099
}

1100

1101 1102 1103 1104 1105 1106


void reset_opp_meas(void) {
  int sfn;
  reset_meas(&softmodem_stats_mt);
  reset_meas(&softmodem_stats_hw);
1107

1108
  for (sfn=0; sfn < 10; sfn++) {
1109
    reset_meas(&softmodem_stats_rxtx_sf);
1110
    reset_meas(&softmodem_stats_rx_sf);
1111 1112 1113
  }
}

1114

1115 1116 1117 1118
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);
1119

1120
  for (sfn=0; sfn < 10; sfn++) {
1121
    print_meas(&softmodem_stats_rxtx_sf,"[eNB][total_phy_proc_rxtx]",NULL, NULL);
1122
    print_meas(&softmodem_stats_rx_sf,"[eNB][total_phy_proc_rx]",NULL,NULL);
1123 1124
  }
}
1125

1126
void free_transport(PHY_VARS_eNB *eNB) {
1127 1128 1129 1130
  int i;
  int j;

  for (i=0; i<NUMBER_OF_UE_MAX; i++) {
1131
    LOG_D(PHY, "Freeing Transport Channel Buffers for DLSCH, UE %d\n",i);
1132 1133 1134

    for (j=0; j<2; j++) free_eNB_dlsch(eNB->dlsch[i][j]);

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

1139 1140 1141
  free_eNB_ulsch(eNB->ulsch[0]);
}

1142 1143 1144 1145
void init_transport(PHY_VARS_eNB *eNB) {
  int i;
  int j;
  LTE_DL_FRAME_PARMS *fp = &eNB->frame_parms;
Cedric Roux's avatar
Cedric Roux committed
1146
  LOG_I(PHY, "Initialise transport\n");
1147

1148
  for (i=0; i<NUMBER_OF_UE_MAX; i++) {
Wang Tsu-Han's avatar
Wang Tsu-Han committed
1149
    LOG_D(PHY,"Allocating Transport Channel Buffers for DLSCH, UE %d\n",i);
1150

1151 1152
    for (j=0; j<2; j++) {
      eNB->dlsch[i][j] = new_eNB_dlsch(1,8,NSOFT,fp->N_RB_DL,0,fp);
1153

1154
      if (!eNB->dlsch[i][j]) {
1155
        LOG_E(PHY,"Can't get eNB dlsch structures for UE %d \n", i);
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
1156
        exit(-1);
1157
      } else {
1158 1159
        eNB->dlsch[i][j]->rnti=0;
        LOG_D(PHY,"dlsch[%d][%d] => %p rnti:%d\n",i,j,eNB->dlsch[i][j], eNB->dlsch[i][j]->rnti);
1160 1161
      }
    }
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
1162

Wang Tsu-Han's avatar
Wang Tsu-Han committed
1163
    LOG_D(PHY,"Allocating Transport Channel Buffer for ULSCH, UE %d\n",i);
1164
    eNB->ulsch[1+i] = new_eNB_ulsch(MAX_TURBO_ITERATIONS,fp->N_RB_UL, 0);
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
1165

1166 1167
    if (!eNB->ulsch[1+i]) {
      LOG_E(PHY,"Can't get eNB ulsch structures\n");
1168 1169
      exit(-1);
    }
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
1170

1171 1172 1173
    // 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;
1174
  }
1175

1176 1177
  // ULSCH for RA
  eNB->ulsch[0] = new_eNB_ulsch(MAX_TURBO_ITERATIONS, fp->N_RB_UL, 0);
1178

1179 1180 1181 1182
  if (!eNB->ulsch[0]) {
    LOG_E(PHY,"Can't get eNB ulsch structures\n");
    exit(-1);
  }
1183

1184 1185 1186 1187 1188 1189 1190
  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;
1191

1192 1193
  for(i=0; i<NUMBER_OF_UE_MAX; i++)
    eNB->mu_mimo_mode[i].dl_pow_off = 2;
1194

1195 1196 1197 1198 1199
  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;
1200
}
Raymond Knopp's avatar
Raymond Knopp committed
1201 1202

void init_eNB_afterRU(void) {
1203 1204
  int inst,CC_id,ru_id,i,aa;
  PHY_VARS_eNB *eNB;
1205
  LOG_I(PHY,"%s() RC.nb_inst:%d\n", __FUNCTION__, RC.nb_inst);
1206

1207
  for (inst=0; inst<RC.nb_inst; inst++) {
1208 1209
    LOG_I(PHY,"RC.nb_CC[inst]:%d\n", RC.nb_CC[inst]);

1210
    for (CC_id=0; CC_id<RC.nb_CC[inst]; CC_id++) {
1211
      LOG_I(PHY,"RC.nb_CC[inst:%d][CC_id:%d]:%p\n", inst, CC_id, RC.eNB[inst][CC_id]);
1212 1213
      eNB                                  =  RC.eNB[inst][CC_id];
      phy_init_lte_eNB(eNB,0,0);
1214

1215
      // map antennas and PRACH signals to eNB RX
1216
      if (0) AssertFatal(eNB->num_RU>0,"Number of RU attached to eNB %d is zero\n",eNB->Mod_id);
1217

1218
      LOG_I(PHY,"Mapping RX ports from %d RUs to eNB %d\n",eNB->num_RU,eNB->Mod_id);
1219
      eNB->frame_parms.nb_antennas_rx       = 0;
Cedric Roux's avatar
Cedric Roux committed
1220
      LOG_I(PHY,"Overwriting eNB->prach_vars.rxsigF[0]:%p\n", eNB->prach_vars.rxsigF[0]);
1221
      eNB->prach_vars.rxsigF[0] = (int16_t **)malloc16(64*sizeof(int16_t *));
1222
#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0))
1223

1224
      for (int ce_level=0; ce_level<4; ce_level++) {
Cedric Roux's avatar
Cedric Roux committed
1225
        LOG_I(PHY,"Overwriting eNB->prach_vars_br.rxsigF.rxsigF[0]:%p\n", eNB->prach_vars_br.rxsigF[ce_level]);
1226
        eNB->prach_vars_br.rxsigF[ce_level] = (int16_t **)malloc16(64*sizeof(int16_t *));
1227 1228
      }

Raymond Knopp's avatar
Raymond Knopp committed
1229
#endif
1230 1231
      LOG_I(PHY,"eNB->num_RU:%d\n", eNB->num_RU);

1232 1233 1234 1235 1236 1237 1238 1239
      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;
        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);
1240

1241 1242 1243
        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);
          eNB->prach_vars.rxsigF[0][aa]    =  eNB->RU_list[ru_id]->prach_rxsigF[i];
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
1244
#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0))
1245

1246 1247
          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];
1248

Raymond Knopp's avatar
Raymond Knopp committed
1249
#endif
1250
          eNB->common_vars.rxdataF[aa]     =  eNB->RU_list[ru_id]->common.rxdataF[i];
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
1251
        }
1252
      }
1253

Cedric Roux's avatar
Cedric Roux committed
1254 1255 1256 1257
      /* TODO: review this code, there is something wrong.
       * In monolithic mode, we come here with nb_antennas_rx == 0
       * (not tested in other modes).
       */
1258
      if (eNB->frame_parms.nb_antennas_rx < 1) {
1259 1260
        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;
1261
      } else {
Cedric Roux's avatar
Cedric Roux committed
1262
        //LOG_I(PHY," Delete code\n");
1263 1264
      }

1265
      if (eNB->frame_parms.nb_antennas_tx < 1) {
1266 1267
        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;
1268
      } else {
Cedric Roux's avatar
Cedric Roux committed
1269
        //LOG_I(PHY," Delete code\n");
1270 1271
      }

1272
      AssertFatal(eNB->frame_parms.nb_antennas_rx >0,
1273
                  "inst %d, CC_id %d : nb_antennas_rx %d\n",inst,CC_id,eNB->frame_parms.nb_antennas_rx);
1274
      LOG_I(PHY,"inst %d, CC_id %d : nb_antennas_rx %d\n",inst,CC_id,eNB->frame_parms.nb_antennas_rx);
1275
      init_transport(eNB);
Raymond Knopp's avatar
Raymond Knopp committed
1276
      //init_precoding_weights(RC.eNB[inst][CC_id]);
1277
    }
1278

1279 1280
    init_eNB_proc(inst);
  }
1281

1282
  for (ru_id=0; ru_id<RC.nb_RU; ru_id++) {
1283
    AssertFatal(RC.ru[ru_id]!=NULL,"ru_id %d is null\n",ru_id);
1284 1285
    RC.ru[ru_id]->wakeup_rxtx         = wakeup_rxtx;
    RC.ru[ru_id]->wakeup_prach_eNB    = wakeup_prach_eNB;
1286
#if (LTE_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
  int CC_id;
1295
  int inst;
1296
  PHY_VARS_eNB *eNB;
1297 1298
  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]);

1299
  if (RC.eNB == NULL) RC.eNB = (PHY_VARS_eNB ** *) malloc(RC.nb_L1_inst*sizeof(PHY_VARS_eNB **));
Raymond Knopp's avatar
Raymond Knopp committed
1300

1301
  LOG_I(PHY,"[lte-softmodem.c] eNB structure RC.eNB allocated\n");
1302

1303 1304
  for (inst=0; inst<RC.nb_L1_inst; inst++) {
    if (RC.eNB[inst] == NULL) RC.eNB[inst] = (PHY_VARS_eNB **) malloc(RC.nb_CC[inst]*sizeof(PHY_VARS_eNB *));
1305

1306 1307
    for (CC_id=0; CC_id<RC.nb_L1_CC[inst]; CC_id++) {
      if (RC.eNB[inst][CC_id] == NULL) RC.eNB[inst][CC_id] = (PHY_VARS_eNB *) malloc(sizeof(PHY_VARS_eNB));
1308

1309 1310 1311
      eNB                     = RC.eNB[inst][CC_id];
      eNB->abstraction_flag   = 0;
      eNB->single_thread_flag = single_thread_flag;
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
1316
      LOG_I(PHY,"Registering with MAC interface module\n");
1317 1318 1319
      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;
1320 1321
      memset((void *)&eNB->UL_INFO,0,sizeof(eNB->UL_INFO));
      memset((void *)&eNB->Sched_INFO,0,sizeof(eNB->Sched_INFO));
1322
      LOG_I(PHY,"Setting indication lists\n");
1323 1324 1325 1326
      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;
1327 1328
      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;
1329
      eNB->prach_energy_counter = 0;
1330
    }
1331
  }
1332

1333

1334
  LOG_I(PHY,"[lte-softmodem.c] eNB structure allocated\n");
1335
  
1336 1337


1338 1339 1340
}


1341
void stop_eNB(int nb_inst) {
1342
  for (int inst=0; inst<nb_inst; inst++) {
1343
    LOG_I(PHY,"Killing eNB %d processing threads\n",inst);
1344 1345
    kill_eNB_proc(inst);
  }
1346
}