lte-enb.c 30.7 KB
Newer Older
1
2
3
4
5
/*
 * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The OpenAirInterface Software Alliance licenses this file to You under
Cedric Roux's avatar
Cedric Roux committed
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
#include "time_utils.h"

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

40
41
#include "rt_wrapper.h"

42
#include "assertions.h"
43

44
45
46
47
48
49
50
51
52
53
54

#include "PHY/types.h"

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

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

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

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

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

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

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

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

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

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

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

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

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

knopp's avatar
knopp committed
111

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

extern openair0_config_t openair0_cfg[MAX_CARDS];

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

122
123
extern int oaisim_flag;

124
//pthread_t                       main_eNB_thread;
125
126
127

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

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

141
142
extern double cpuf;

143
144
void exit_fun(const char* s);

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


149
void wakeup_prach_eNB(PHY_VARS_eNB *eNB,RU_t *ru,int frame,int subframe);
150
151
152
#ifdef Rel14
void wakeup_prach_eNB_br(PHY_VARS_eNB *eNB,RU_t *ru,int frame,int subframe);
#endif
153

knopp's avatar
knopp committed
154
155
156
static inline int rxtx(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc, char *thread_name) {

  start_meas(&softmodem_stats_rxtx_sf);
157

knopp's avatar
knopp committed
158
159
  // ****************************************
  // Common RX procedures subframe n
160

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

163
  // if this is IF5 or 3GPP_eNB
164
165
166
167
168
169
  if (eNB->RU_list[0]->function < NGFI_RAU_IF4p5) {
    wakeup_prach_eNB(eNB,NULL,proc->frame_rx,proc->subframe_rx);
#ifdef Rel14
    wakeup_prach_eNB_br(eNB,NULL,proc->frame_rx,proc->subframe_rx);
#endif
  }
170
171
172

  release_UE_in_freeList(eNB->Mod_id);

knopp's avatar
knopp committed
173
  // UE-specific RX processing for subframe n
174
  phy_procedures_eNB_uespec_RX(eNB, proc, no_relay );
175
176

  pthread_mutex_lock(&eNB->UL_INFO_mutex);
177
178
179
180
181
  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);
182
  pthread_mutex_unlock(&eNB->UL_INFO_mutex);
knopp's avatar
knopp committed
183
184
185
186
187
  // *****************************************
  // 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)
  // *****************************************
188
  //if (wait_CCs(proc)<0) return(-1);
knopp's avatar
knopp committed
189
  
190
191

  
knopp's avatar
knopp committed
192
193
  if (oai_exit) return(-1);
  
194
  phy_procedures_eNB_TX(eNB, proc, no_relay, NULL, 1);
knopp's avatar
knopp committed
195
196
197
198
199
200
201
202
  
  if (release_thread(&proc->mutex_rxtx,&proc->instance_cnt_rxtx,thread_name)<0) return(-1);

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

203

204
/*!
knopp's avatar
knopp committed
205
 * \brief The RX UE-specific and TX thread of eNB.
206
207
208
 * \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.
 */
209

Sandeep Kumar's avatar
Sandeep Kumar committed
210
211
static void* eNB_thread_rxtx( void* param ) {

knopp's avatar
knopp committed
212
  static int eNB_thread_rxtx_status;
213

knopp's avatar
knopp committed
214
  eNB_rxtx_proc_t *proc = (eNB_rxtx_proc_t*)param;
215
  PHY_VARS_eNB *eNB = RC.eNB[0][proc->CC_id];
216

knopp's avatar
knopp committed
217
218
  char thread_name[100];

219

220
  // set default return value
knopp's avatar
knopp committed
221
  eNB_thread_rxtx_status = 0;
222
223


knopp's avatar
knopp committed
224
  sprintf(thread_name,"RXn_TXnp4_%d\n",&eNB->proc.proc_rxtx[0] == proc ? 0 : 1);
225
  thread_top_init(thread_name,1,850000L,1000000L,2000000L);
226
227

  while (!oai_exit) {
knopp's avatar
knopp committed
228
    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_RXTX0+(proc->subframe_rx&1), 0 );
229

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

knopp's avatar
knopp committed
232
    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_RXTX0+(proc->subframe_rx&1), 1 );
233

knopp's avatar
knopp committed
234
    
235
  
236
237
    if (oai_exit) break;

238
239
    if (eNB->CC_id==0)
      if (rxtx(eNB,proc,thread_name) < 0) break;
240

knopp's avatar
knopp committed
241
  } // while !oai_exit
242

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

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

knopp's avatar
knopp committed
247
248
  eNB_thread_rxtx_status = 0;
  return &eNB_thread_rxtx_status;
249
250
}

251

knopp's avatar
knopp committed
252
253
#if 0 //defined(ENABLE_ITTI) && defined(ENABLE_USE_MME)
// Wait for eNB application initialization to be complete (eNB registration to MME)
Sandeep Kumar's avatar
Sandeep Kumar committed
254
255
static void wait_system_ready (char *message, volatile int *start_flag) {
  
256
  static char *indicator[] = {".    ", "..   ", "...  ", ".... ", ".....",
Sandeep Kumar's avatar
Sandeep Kumar committed
257
			      " ....", "  ...", "   ..", "    .", "     "};
258
259
260
261
262
263
264
  int i = 0;
  
  while ((!oai_exit) && (*start_flag == 0)) {
    LOG_N(EMU, message, indicator[i]);
    fflush(stdout);
    i = (i + 1) % (sizeof(indicator) / sizeof(indicator[0]));
    usleep(200000);
265
  }
266
267
  
  LOG_D(EMU,"\n");
268
269
}
#endif
270

knopp's avatar
knopp committed
271
272


knopp's avatar
knopp committed
273

knopp's avatar
knopp committed
274

Cedric Roux's avatar
Cedric Roux committed
275
276
void eNB_top(PHY_VARS_eNB *eNB, int frame_rx, int subframe_rx, char *string)
{
277
278
  eNB_proc_t *proc           = &eNB->proc;
  eNB_rxtx_proc_t *proc_rxtx = &proc->proc_rxtx[0];
279

280
281
  proc->frame_rx    = frame_rx;
  proc->subframe_rx = subframe_rx;
knopp's avatar
knopp committed
282

Cedric Roux's avatar
Cedric Roux committed
283
  if (!oai_exit) {
knopp's avatar
knopp committed
284
    LOG_D(PHY,"eNB_top in %p (proc %p, CC_id %d), frame %d, subframe %d, instance_cnt_prach %d\n",
knopp's avatar
knopp committed
285
	  (void*)pthread_self(), proc, eNB->CC_id, proc->frame_rx,proc->subframe_rx,proc->instance_cnt_prach);
knopp's avatar
knopp committed
286

287
    T(T_ENB_MASTER_TICK, T_INT(0), T_INT(proc->frame_rx), T_INT(proc->subframe_rx));
knopp's avatar
knopp committed
288

289
290
291
292
293
294
    proc_rxtx->subframe_rx = proc->subframe_rx;
    proc_rxtx->frame_rx    = proc->frame_rx;
    proc_rxtx->subframe_tx = (proc->subframe_rx+4)%10;
    proc_rxtx->frame_tx    = (proc->subframe_rx>5) ? (1+proc->frame_rx)&1023 : proc->frame_rx;
    proc->frame_tx         = proc_rxtx->frame_tx;
    proc_rxtx->timestamp_tx = proc->timestamp_tx;
knopp's avatar
knopp committed
295

296
    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
297
    LOG_D(PHY,"eNB_top out %p (proc %p, CC_id %d), frame %d, subframe %d, instance_cnt_prach %d\n",
knopp's avatar
knopp committed
298
	  (void*)pthread_self(), proc, eNB->CC_id, proc->frame_rx,proc->subframe_rx,proc->instance_cnt_prach);
299
  }
knopp's avatar
knopp committed
300
301
302
}


303
304
305
306
307
308
309
int wakeup_rxtx(PHY_VARS_eNB *eNB,RU_t *ru) {

  eNB_proc_t *proc=&eNB->proc;

  eNB_rxtx_proc_t *proc_rxtx=&proc->proc_rxtx[proc->frame_rx&1];

  LTE_DL_FRAME_PARMS *fp = &eNB->frame_parms;
310
311
312
313

  int i;
  struct timespec wait;
  
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
  pthread_mutex_lock(&proc->mutex_RU);
  for (i=0;i<eNB->num_RU;i++) {
    if (ru == eNB->RU_list[i]) {
      if ((proc->RU_mask&(1<<i)) > 0)
	LOG_E(PHY,"eNB %d frame %d, subframe %d : previous information from RU %d (num_RU %d,mask %x) has not been served yet!\n",
	      eNB->Mod_id,proc->frame_rx,proc->subframe_rx,ru->idx,eNB->num_RU,proc->RU_mask);
      proc->RU_mask |= (1<<i);
    }
  }
  if (proc->RU_mask != (1<<eNB->num_RU)-1) {  // not all RUs have provided their information so return
    pthread_mutex_unlock(&proc->mutex_RU);
    return(0);
  }
  else { // all RUs have provided their information so continue on and wakeup eNB processing
    proc->RU_mask = 0;
    pthread_mutex_unlock(&proc->mutex_RU);
  }




335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
  wait.tv_sec=0;
  wait.tv_nsec=5000000L;

  /* accept some delay in processing - up to 5ms */
  for (i = 0; i < 10 && proc_rxtx->instance_cnt_rxtx == 0; i++) {
    LOG_W( PHY,"[eNB] Frame %d, eNB RXn-TXnp4 thread busy!! (cnt_rxtx %i)\n", proc_rxtx->frame_tx, proc_rxtx->instance_cnt_rxtx);
    usleep(500);
  }
  if (proc_rxtx->instance_cnt_rxtx == 0) {
    exit_fun( "TX thread busy" );
    return(-1);
  }

  // wake up TX for subframe n+4
  // lock the TX mutex and make sure the thread is ready
  if (pthread_mutex_timedlock(&proc_rxtx->mutex_rxtx,&wait) != 0) {
    LOG_E( PHY, "[eNB] ERROR pthread_mutex_lock for eNB RXTX thread %d (IC %d)\n", proc_rxtx->subframe_rx&1,proc_rxtx->instance_cnt_rxtx );
    exit_fun( "error locking mutex_rxtx" );
    return(-1);
  }
  
  ++proc_rxtx->instance_cnt_rxtx;
  
  // 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, 
knopp's avatar
knopp committed
362
363
  // we want to generate subframe (n+4), so TS_tx = TX_rx+4*samples_per_tti,
  // and proc->subframe_tx = proc->subframe_rx+4
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
  proc_rxtx->timestamp_tx = proc->timestamp_rx + (4*fp->samples_per_tti);
  proc_rxtx->frame_rx     = proc->frame_rx;
  proc_rxtx->subframe_rx  = proc->subframe_rx;
  proc_rxtx->frame_tx     = (proc_rxtx->subframe_rx > 5) ? (proc_rxtx->frame_rx+1)&1023 : proc_rxtx->frame_rx;
  proc_rxtx->subframe_tx  = (proc_rxtx->subframe_rx + 4)%10;
  
  // the thread can now be woken up
  if (pthread_cond_signal(&proc_rxtx->cond_rxtx) != 0) {
    LOG_E( PHY, "[eNB] ERROR pthread_cond_signal for eNB RXn-TXnp4 thread\n");
    exit_fun( "ERROR pthread_cond_signal" );
    return(-1);
  }
  
  pthread_mutex_unlock( &proc_rxtx->mutex_rxtx );

  return(0);
}

382
void wakeup_prach_eNB(PHY_VARS_eNB *eNB,RU_t *ru,int frame,int subframe) {
knopp's avatar
knopp committed
383
384
385

  eNB_proc_t *proc = &eNB->proc;
  LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms;
386
  int i;
knopp's avatar
knopp committed
387

388
389
390
391
  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
392
	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);
393
394
	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",
395
		eNB->Mod_id,frame,subframe,ru->idx,eNB->num_RU,proc->RU_mask_prach);
396
397
398
399
400
	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
401
      return;
402
403
404
405
406
407
408
    }
    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);
    }
  }
    
knopp's avatar
knopp committed
409
  // check if we have to detect PRACH first
410
  if (is_prach_subframe(fp,frame,subframe)>0) { 
411
    LOG_D(PHY,"Triggering prach processing, frame %d, subframe %d\n",frame,subframe);
knopp's avatar
knopp committed
412
    if (proc->instance_cnt_prach == 0) {
413
      LOG_W(PHY,"[eNB] Frame %d Subframe %d, dropping PRACH\n", frame,subframe);
knopp's avatar
knopp committed
414
415
416
417
418
419
420
421
422
423
424
425
      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
426
427
    proc->frame_prach = frame;
    proc->subframe_prach = subframe;
knopp's avatar
knopp committed
428
429
430
431
432
433
434
435
436
437
438
439
440
    
    // 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 );
  }

}

441
442
443
444
445
446
447
448
449
450
451
#ifdef Rel14
void wakeup_prach_eNB_br(PHY_VARS_eNB *eNB,RU_t *ru,int frame,int subframe) {

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

  if (ru!=NULL) {
    pthread_mutex_lock(&proc->mutex_RU_PRACH_br);
    for (i=0;i<eNB->num_RU;i++) {
      if (ru == eNB->RU_list[i]) {
knopp's avatar
knopp committed
452
	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);
453
454
455
456
457
458
459
460
	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
461
      return;
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
    }
    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

502
503
504
505
506
/*!
 * \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.
 */
Sandeep Kumar's avatar
Sandeep Kumar committed
507
static void* eNB_thread_prach( void* param ) {
508
509
  static int eNB_thread_prach_status;

510
511
512

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

514
515
516
  // set default return value
  eNB_thread_prach_status = 0;

517
  thread_top_init("eNB_thread_prach",1,500000L,1000000L,20000000L);
518

519

Sandeep Kumar's avatar
Sandeep Kumar committed
520
521
522
523
  while (!oai_exit) {
    
    if (oai_exit) break;

524
    
knopp's avatar
knopp committed
525
    if (wait_on_condition(&proc->mutex_prach,&proc->cond_prach,&proc->instance_cnt_prach,"eNB_prach_thread") < 0) break;
knopp's avatar
knopp committed
526
527

    LOG_D(PHY,"Running eNB prach procedures\n");
528
529
530
531
532
    prach_procedures(eNB
#ifdef Rel14
		     ,0
#endif
		     );
533
    
knopp's avatar
knopp committed
534
    if (release_thread(&proc->mutex_prach,&proc->instance_cnt_prach,"eNB_prach_thread") < 0) break;
Sandeep Kumar's avatar
Sandeep Kumar committed
535
  }
536

knopp's avatar
knopp committed
537
  LOG_I(PHY, "Exiting eNB thread PRACH\n");
Raymond Knopp's avatar
Raymond Knopp committed
538

539
540
  eNB_thread_prach_status = 0;
  return &eNB_thread_prach_status;
541
542
}

543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
#ifdef Rel14
/*!
 * \brief The prach receive thread of eNB for BL/CE UEs.
 * \param param is a \ref eNB_proc_t structure which contains the info what to process.
 * \returns a pointer to an int. The storage is not on the heap and must not be freed.
 */
static void* eNB_thread_prach_br( void* param ) {
  static int eNB_thread_prach_status;


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

  // set default return value
  eNB_thread_prach_status = 0;

  thread_top_init("eNB_thread_prach_br",1,500000L,1000000L,20000000L);

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

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

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

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

  eNB_thread_prach_status = 0;
  return &eNB_thread_prach_status;
}

#endif
knopp's avatar
knopp committed
581

knopp's avatar
knopp committed
582

knopp's avatar
knopp committed
583
584
extern void init_td_thread(PHY_VARS_eNB *, pthread_attr_t *);
extern void init_te_thread(PHY_VARS_eNB *, pthread_attr_t *);
585

586
void init_eNB_proc(int inst) {
Sandeep Kumar's avatar
Sandeep Kumar committed
587
  
Rohit Gupta's avatar
Rohit Gupta committed
588
  int i=0;
589
  int CC_id;
590
591
  PHY_VARS_eNB *eNB;
  eNB_proc_t *proc;
knopp's avatar
knopp committed
592
  eNB_rxtx_proc_t *proc_rxtx;
knopp's avatar
knopp committed
593
594
  pthread_attr_t *attr0=NULL,*attr1=NULL,*attr_prach=NULL;
    //*attr_td=NULL,*attr_te=NULL;
595
596
597
#ifdef Rel14
  pthread_attr_t *attr_prach_br=NULL;
#endif
knopp's avatar
knopp committed
598

knopp's avatar
knopp committed
599
  for (CC_id=0; CC_id<RC.nb_CC[inst]; CC_id++) {
600
    eNB = RC.eNB[inst][CC_id];
laurent's avatar
small2    
laurent committed
601
#ifndef OCP_FRAMEWORK
602
    LOG_I(PHY,"Initializing eNB processes %d CC_id %d \n",inst,CC_id);
laurent's avatar
small2    
laurent committed
603
#endif
604
    proc = &eNB->proc;
knopp's avatar
knopp committed
605

606
    proc_rxtx                      = proc->proc_rxtx;
607
608
    proc_rxtx[0].instance_cnt_rxtx = -1;
    proc_rxtx[1].instance_cnt_rxtx = -1;
609
    proc->instance_cnt_prach       = -1;
610
    proc->instance_cnt_asynch_rxtx = -1;
611
    proc->CC_id                    = CC_id;    
612

knopp's avatar
knopp committed
613
614
    proc->first_rx=1;
    proc->first_tx=1;
615
616
    proc->RU_mask=0;
    proc->RU_mask_prach=0;
knopp's avatar
knopp committed
617

618
    pthread_mutex_init( &eNB->UL_INFO_mutex, NULL);
619
620
621
622
    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
623
624
625

    pthread_mutex_init( &proc->mutex_prach, NULL);
    pthread_mutex_init( &proc->mutex_asynch_rxtx, NULL);
626
627
    pthread_mutex_init( &proc->mutex_RU,NULL);
    pthread_mutex_init( &proc->mutex_RU_PRACH,NULL);
knopp's avatar
knopp committed
628

629
    pthread_cond_init( &proc->cond_prach, NULL);
630
    pthread_cond_init( &proc->cond_asynch_rxtx, NULL);
631
632
633

    pthread_attr_init( &proc->attr_prach);
    pthread_attr_init( &proc->attr_asynch_rxtx);
knopp's avatar
knopp committed
634
635
    //    pthread_attr_init( &proc->attr_td);
    //    pthread_attr_init( &proc->attr_te);
636
637
    pthread_attr_init( &proc_rxtx[0].attr_rxtx);
    pthread_attr_init( &proc_rxtx[1].attr_rxtx);
638
639
640
641
642
643
644
645
#ifdef Rel14
    proc->instance_cnt_prach_br    = -1;
    proc->RU_mask_prach_br=0;
    pthread_mutex_init( &proc->mutex_prach_br, NULL);
    pthread_mutex_init( &proc->mutex_RU_PRACH_br,NULL);
    pthread_cond_init( &proc->cond_prach_br, NULL);
    pthread_attr_init( &proc->attr_prach_br);
#endif
646
#ifndef DEADLINE_SCHEDULER
knopp's avatar
knopp committed
647
648
649
    attr0       = &proc_rxtx[0].attr_rxtx;
    attr1       = &proc_rxtx[1].attr_rxtx;
    attr_prach  = &proc->attr_prach;
650
651
652
653
#ifdef Rel14
    attr_prach_br  = &proc->attr_prach_br;
#endif

knopp's avatar
knopp committed
654
655
    //    attr_td     = &proc->attr_td;
    //    attr_te     = &proc->attr_te; 
knopp's avatar
knopp committed
656
657
#endif

658
659
660
661
    if (eNB->single_thread_flag==0) {
      pthread_create( &proc_rxtx[0].pthread_rxtx, attr0, eNB_thread_rxtx, &proc_rxtx[0] );
      pthread_create( &proc_rxtx[1].pthread_rxtx, attr1, eNB_thread_rxtx, &proc_rxtx[1] );
    }
662
    pthread_create( &proc->pthread_prach, attr_prach, eNB_thread_prach, eNB );
663
664
665
#ifdef Rel14
    pthread_create( &proc->pthread_prach_br, attr_prach_br, eNB_thread_prach_br, eNB );
#endif
666
    char name[16];
667
668
669
670
671
672
    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 );
    }
knopp's avatar
knopp committed
673
674
675

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

676
    
677
  }
678

679
  //for multiple CCs: setup master and slaves
680
681
682
  /* 
     for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
     eNB = PHY_vars_eNB_g[inst][CC_id];
683

684
685
686
     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*));
687

688
689
690
691
692
693
694
     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);
     }
     }
     }
  */
695

696
697
698
699
  /* 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;
700
701
}

702

703

704
705
706
/*!
 * \brief Terminate eNB TX and RX threads.
 */
707
void kill_eNB_proc(int inst) {
Sandeep Kumar's avatar
Sandeep Kumar committed
708

709
  int *status;
710
711
  PHY_VARS_eNB *eNB;
  eNB_proc_t *proc;
knopp's avatar
knopp committed
712
  eNB_rxtx_proc_t *proc_rxtx;
713
  for (int CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
714
    eNB=RC.eNB[inst][CC_id];
715
716
    
    proc = &eNB->proc;
knopp's avatar
knopp committed
717
    proc_rxtx = &proc->proc_rxtx[0];
718
    
knopp's avatar
knopp committed
719
720

    LOG_I(PHY, "Killing TX CC_id %d inst %d\n", CC_id, inst );
721
722
723
724
725
726
727

    if (eNB->single_thread_flag==0) {
      proc_rxtx[0].instance_cnt_rxtx = 0; // FIXME data race!
      proc_rxtx[1].instance_cnt_rxtx = 0; // FIXME data race!
      pthread_cond_signal( &proc_rxtx[0].cond_rxtx );    
      pthread_cond_signal( &proc_rxtx[1].cond_rxtx );
    }
Raymond Knopp's avatar
Raymond Knopp committed
728
729
    proc->instance_cnt_prach = 0;
    pthread_cond_signal( &proc->cond_prach );
730

731
    pthread_cond_broadcast(&sync_phy_proc.cond_phy_proc_tx);
732
    pthread_join( proc->pthread_prach, (void**)&status );    
733

734
    LOG_I(PHY, "Destroying prach mutex/cond\n");
735
    pthread_mutex_destroy( &proc->mutex_prach );
736
737
    pthread_cond_destroy( &proc->cond_prach );
#ifdef Rel14
738
    proc->instance_cnt_prach_br = 0;
739
740
741
742
743
    pthread_cond_signal( &proc->cond_prach_br );
    pthread_join( proc->pthread_prach_br, (void**)&status );    
    pthread_mutex_destroy( &proc->mutex_prach_br );
    pthread_cond_destroy( &proc->cond_prach_br );
#endif         
744
    LOG_I(PHY, "Destroying UL_INFO mutex\n");
745
    pthread_mutex_destroy(&eNB->UL_INFO_mutex);
746
    int i;
747
748
    if (eNB->single_thread_flag==0) {
      for (i=0;i<2;i++) {
knopp's avatar
knopp committed
749
	LOG_I(PHY, "Joining rxtx[%d] mutex/cond\n",i);
750
	pthread_join( proc_rxtx[i].pthread_rxtx, (void**)&status );
knopp's avatar
knopp committed
751
	LOG_I(PHY, "Destroying rxtx[%d] mutex/cond\n",i);
752
753
754
	pthread_mutex_destroy( &proc_rxtx[i].mutex_rxtx );
	pthread_cond_destroy( &proc_rxtx[i].cond_rxtx );
      }
knopp's avatar
knopp committed
755
    }
756
  }
757
758
}

759

760
761
762


void reset_opp_meas(void) {
Sandeep Kumar's avatar
Sandeep Kumar committed
763

764
765
766
767
768
  int sfn;
  reset_meas(&softmodem_stats_mt);
  reset_meas(&softmodem_stats_hw);
  
  for (sfn=0; sfn < 10; sfn++) {
knopp's avatar
knopp committed
769
    reset_meas(&softmodem_stats_rxtx_sf);
770
    reset_meas(&softmodem_stats_rx_sf);
771
772
773
  }
}

Sandeep Kumar's avatar
Sandeep Kumar committed
774

775
776
777
778
779
780
781
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
782
    print_meas(&softmodem_stats_rxtx_sf,"[eNB][total_phy_proc_rxtx]",NULL, NULL);
783
    print_meas(&softmodem_stats_rx_sf,"[eNB][total_phy_proc_rx]",NULL,NULL);
784
785
  }
}
786

787
void init_transport(PHY_VARS_eNB *eNB) {
788

789
790
791
  int i;
  int j;
  LTE_DL_FRAME_PARMS *fp = &eNB->frame_parms;
knopp's avatar
knopp committed
792

793
794
795
796
797
798
  for (i=0; i<NUMBER_OF_UE_MAX; i++) {
    LOG_I(PHY,"Allocating Transport Channel Buffers for DLSCH, UE %d\n",i);
    for (j=0; j<2; j++) {
      eNB->dlsch[i][j] = new_eNB_dlsch(1,8,NSOFT,fp->N_RB_DL,0,fp);
      if (!eNB->dlsch[i][j]) {
	LOG_E(PHY,"Can't get eNB dlsch structures for UE %d \n", i);
knopp's avatar
knopp committed
799
	exit(-1);
800
801
802
      } else {
	LOG_D(PHY,"dlsch[%d][%d] => %p\n",i,j,eNB->dlsch[i][j]);
	eNB->dlsch[i][j]->rnti=0;
knopp's avatar
knopp committed
803
804
      }
    }
805
806
807
808
809
810
    
    LOG_I(PHY,"Allocating Transport Channel Buffer for ULSCH, UE %d\n",i);
    eNB->ulsch[1+i] = new_eNB_ulsch(MAX_TURBO_ITERATIONS,fp->N_RB_UL, 0);
    
    if (!eNB->ulsch[1+i]) {
      LOG_E(PHY,"Can't get eNB ulsch structures\n");
knopp's avatar
knopp committed
811
812
      exit(-1);
    }
813
814
815
816
    
    // 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
817
  }
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
  // 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
834
  
835
836
837
838
839
840
841
842
843
844
845
846
847
848
  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
849
850

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

852
853
  int inst,CC_id,ru_id,i,aa;
  PHY_VARS_eNB *eNB;
854
855


856
857
858
859
860
861
862
  for (inst=0;inst<RC.nb_inst;inst++) {
    for (CC_id=0;CC_id<RC.nb_CC[inst];CC_id++) {
      eNB                                  =  RC.eNB[inst][CC_id];
      phy_init_lte_eNB(eNB,0,0);
      // map antennas and PRACH signals to eNB RX
      AssertFatal(eNB->num_RU>0,"Number of RU attached to eNB %d is zero\n",eNB->Mod_id);
      LOG_I(PHY,"Mapping RX ports from %d RUs to eNB %d\n",eNB->num_RU,eNB->Mod_id);
863
      eNB->frame_parms.nb_antennas_rx       = 0;
knopp's avatar
knopp committed
864
      eNB->prach_vars.rxsigF[0] = (int16_t**)malloc16(64*sizeof(int16_t*));
865
866
#ifdef Rel14
      for (int ce_level=0;ce_level<4;ce_level++)
knopp's avatar
knopp committed
867
	eNB->prach_vars_br.rxsigF[ce_level] = (int16_t**)malloc16(64*sizeof(int16_t*));
868
#endif
869
870
      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;
871
872
873
874
875
876
877
878
879

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

880
881
	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);
knopp's avatar
knopp committed
882
883
884
885
886
	  eNB->prach_vars.rxsigF[0][aa]    =  eNB->RU_list[ru_id]->prach_rxsigF[i];
#ifdef Rel14
	  for (int ce_level=0;ce_level<4;ce_level++)
	    eNB->prach_vars_br.rxsigF[ce_level][aa] = eNB->RU_list[ru_id]->prach_rxsigF_br[ce_level][i];
#endif
887
888
889
	  eNB->common_vars.rxdataF[aa]     =  eNB->RU_list[ru_id]->common.rxdataF[i];
	}
      }
890
891
892
      AssertFatal(eNB->frame_parms.nb_antennas_rx >0,
		  "inst %d, CC_id %d : nb_antennas_rx %d\n",inst,CC_id,eNB->frame_parms.nb_antennas_rx);
      LOG_I(PHY,"inst %d, CC_id %d : nb_antennas_rx %d\n",inst,CC_id,eNB->frame_parms.nb_antennas_rx);
893
894

      init_transport(eNB);
knopp's avatar
knopp committed
895
      //init_precoding_weights(RC.eNB[inst][CC_id]);
896
897
898
    }
    init_eNB_proc(inst);
  }
knopp's avatar
knopp committed
899

900
  for (ru_id=0;ru_id<RC.nb_RU;ru_id++) {
901
902

    AssertFatal(RC.ru[ru_id]!=NULL,"ru_id %d is null\n",ru_id);
903
    
904
905
906
907
    RC.ru[ru_id]->wakeup_rxtx         = wakeup_rxtx;
    RC.ru[ru_id]->wakeup_prach_eNB    = wakeup_prach_eNB;
    RC.ru[ru_id]->wakeup_prach_eNB_br = wakeup_prach_eNB_br;
    RC.ru[ru_id]->eNB_top             = eNB_top;
908
909
  }
}
910

911
void init_eNB(int single_thread_flag,int wait_for_sync) {
912
  
913
  int CC_id;
914
  int inst;
915
  PHY_VARS_eNB *eNB;
knopp's avatar
knopp committed
916

917
918
  if (RC.eNB == NULL) RC.eNB = (PHY_VARS_eNB***) malloc(RC.nb_L1_inst*sizeof(PHY_VARS_eNB **));
  for (inst=0;inst<RC.nb_L1_inst;inst++) {
knopp's avatar
knopp committed
919
    if (RC.eNB[inst] == NULL) RC.eNB[inst] = (PHY_VARS_eNB**) malloc(RC.nb_CC[inst]*sizeof(PHY_VARS_eNB *));
920
    for (CC_id=0;CC_id<RC.nb_L1_CC[inst];CC_id++) {
921
922
      if (RC.eNB[inst][CC_id] == NULL) RC.eNB[inst][CC_id] = (PHY_VARS_eNB*) malloc(sizeof(PHY_VARS_eNB));
      eNB                     = RC.eNB[inst][CC_id]; 
923
      eNB->abstraction_flag   = 0;
knopp's avatar
knopp committed
924
      eNB->single_thread_flag = single_thread_flag;
925

926

laurent's avatar
small2    
laurent committed
927
#ifndef OCP_FRAMEWORK
928
      LOG_I(PHY,"Initializing eNB %d CC_id %d\n",inst,CC_id);
laurent's avatar
small2    
laurent committed
929
#endif
knopp's avatar
knopp committed
930
931


932
933
      eNB->td                   = ulsch_decoding_data;//(single_thread_flag==1) ? ulsch_decoding_data_2thread : ulsch_decoding_data;
      eNB->te                   = dlsch_encoding;//(single_thread_flag==1) ? dlsch_encoding_2threads : dlsch_encoding;
934

935
      
936
      LOG_I(PHY,"Registering with MAC interface module\n");
937
938
939
940
941
942
943
944
      AssertFatal((eNB->if_inst         = IF_Module_init(inst))!=NULL,"Cannot register interface");
      eNB->if_inst->schedule_response   = schedule_response;
      eNB->if_inst->PHY_config_req      = phy_config_request;
      memset((void*)&eNB->UL_INFO,0,sizeof(eNB->UL_INFO));
      memset((void*)&eNB->Sched_INFO,0,sizeof(eNB->Sched_INFO));
      LOG_I(PHY,"Setting indication lists\n");
      eNB->UL_INFO.rx_ind.rx_pdu_list   = eNB->rx_pdu_list;
      eNB->UL_INFO.crc_ind.crc_pdu_list = eNB->crc_pdu_list;
945
946
947
948
      eNB->UL_INFO.sr_ind.sr_pdu_list = eNB->sr_pdu_list;
      eNB->UL_INFO.harq_ind.harq_pdu_list = eNB->harq_pdu_list;
      eNB->UL_INFO.cqi_ind.cqi_pdu_list = eNB->cqi_pdu_list;
      eNB->UL_INFO.cqi_ind.cqi_raw_pdu_list = eNB->cqi_raw_pdu_list;
949
      eNB->prach_energy_counter = 0;
knopp's avatar
knopp committed
950
951
    }

952
  }
953

954

955
  LOG_I(PHY,"[lte-softmodem.c] eNB structure allocated\n");
956
  
957
958


959
960
961
}


962
void stop_eNB(int nb_inst) {
963

964
  for (int inst=0;inst<nb_inst;inst++) {
knopp's avatar
knopp committed
965
    LOG_I(PHY,"Killing eNB %d processing threads\n",inst);
966
967
    kill_eNB_proc(inst);
  }
968
}