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

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

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
125
uint16_t sf_ahead=2;

126
//pthread_t                       main_eNB_thread;
127
128
129

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

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

143
144
extern double cpuf;

145
146
void exit_fun(const char* s);

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


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

156
extern uint8_t nfapi_mode;
157
158
extern void oai_subframe_ind(uint16_t sfn, uint16_t sf);
extern void add_subframe(uint16_t *frameP, uint16_t *subframeP, int offset);
159

knopp's avatar
knopp committed
160
161
162
static inline int rxtx(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc, char *thread_name) {

  start_meas(&softmodem_stats_rxtx_sf);
163

164
165
  // *******************************************************************

166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
  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);
    oai_subframe_ind(frame, subframe);

    LOG_D(PHY, "UL_info[rx_ind:%d number_of_harqs:%d number_of_crcs:%d number_of_cqis:%d number_of_preambles:%d]\n", 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.cqi_ind.number_of_cqis, eNB->UL_INFO.rach_ind.rach_indication_body.number_of_preambles);
  }

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

knopp's avatar
knopp committed
187
188
  // ****************************************
  // Common RX procedures subframe n
189

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

192
  // if this is IF5 or 3GPP_eNB
193
  if (eNB && eNB->RU_list && eNB->RU_list[0] && eNB->RU_list[0]->function < NGFI_RAU_IF4p5) {
194
    //LOG_D(PHY,"%s:%s() %u/%u Before wakeup_prach_eNB() proc->instance_cnt_rxtx:%d\n", thread_name, __FUNCTION__, proc->frame_tx, proc->subframe_tx, proc->instance_cnt_rxtx);
195
    wakeup_prach_eNB(eNB,NULL,proc->frame_rx,proc->subframe_rx);
196
    //LOG_D(PHY,"%s:%s() %u/%u Before wakeup_prach_eNB_br() proc->instance_cnt_rxtx:%d\n", thread_name, __FUNCTION__, proc->frame_tx, proc->subframe_tx, proc->instance_cnt_rxtx);
197
198
#ifdef Rel14
    wakeup_prach_eNB_br(eNB,NULL,proc->frame_rx,proc->subframe_rx);
199
    //LOG_D(PHY,"%s:%s() %u/%u proc->instance_cnt_rxtx:%d\n", thread_name, __FUNCTION__, proc->frame_tx, proc->subframe_tx, proc->instance_cnt_rxtx);
200
201
#endif
  }
202

203
  LOG_D(PHY, "RX_IND:SFN/SF:%d proc:SFN/SF:%d/%d [rx_ind:num_pdus:%d] TX:%d/%d eNB->pdcch_vars[subframe&1].num_pdcch_symbols:%d\n", NFAPI_SFNSF2DEC(eNB->UL_INFO.rx_ind.sfn_sf), proc->frame_rx, proc->subframe_rx, eNB->UL_INFO.rx_ind.rx_indication_body.number_of_pdus, proc->frame_tx, proc->subframe_tx, eNB->pdcch_vars[proc->subframe_tx&1].num_pdcch_symbols);
204
205
206
207
208
209

  if (eNB->UL_INFO.rx_ind.sfn_sf == (proc->frame_rx<<4|proc->subframe_rx) && eNB->UL_INFO.rx_ind.rx_indication_body.number_of_pdus>0)
  {
    // Fix me here, these should be locked
    for (int i=0; i<eNB->UL_INFO.rx_ind.rx_indication_body.number_of_pdus; i++)
    {
210
      LOG_E(PHY, "SFN/SF(RX):%d/%d eNB->UL_INFO.rx_ind.number_of_pdus:%d NOT ZEROING!\n\n\n\n\n", proc->frame_rx, proc->subframe_rx, eNB->UL_INFO.rx_ind.rx_indication_body.number_of_pdus);
211
212
213
214
215
216
217
218
      //eNB->UL_INFO.rx_ind[proc->subframe_rx&1].number_of_pdus  = 0;
    }
  }

  if (eNB->UL_INFO.crc_ind.sfn_sf == (proc->frame_rx<<4|proc->subframe_rx))
  {
    for (int i=0; i<eNB->UL_INFO.crc_ind.crc_indication_body.number_of_crcs; i++)
    {
219
      LOG_E(PHY, "SFN/SF(RX):%d/%d eNB->UL_INFO.crc_ind.number_of_crcs:%d NOT ZEROING!\n\n\n\n\n", proc->frame_rx, proc->subframe_rx, eNB->UL_INFO.crc_ind.crc_indication_body.number_of_crcs);
220
221
222
223
      //eNB->UL_INFO.crc_ind.number_of_crcs = 0;
    }
  }

knopp's avatar
knopp committed
224
  // UE-specific RX processing for subframe n
225
226
227
  if (nfapi_mode == 0 || nfapi_mode == 1) {
    phy_procedures_eNB_uespec_RX(eNB, proc, no_relay );
  }
228
229

  pthread_mutex_lock(&eNB->UL_INFO_mutex);
230

231
232
233
234
  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;
235

236
  eNB->if_inst->UL_indication(&eNB->UL_INFO);
237

238
  pthread_mutex_unlock(&eNB->UL_INFO_mutex);
239

knopp's avatar
knopp committed
240
  // *****************************************
241
  // TX processing for subframe n+sf_ahead
knopp's avatar
knopp committed
242
243
244
  // 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)
  // *****************************************
245
  //if (wait_CCs(proc)<0) return(-1);
knopp's avatar
knopp committed
246
247
248
  
  if (oai_exit) return(-1);
  
249
250
  if (nfapi_mode == 0 || nfapi_mode == 1)
    phy_procedures_eNB_TX(eNB, proc, no_relay, NULL, 1);
251

knopp's avatar
knopp committed
252
253
254
255
256
  stop_meas( &softmodem_stats_rxtx_sf );
  
  return(0);
}

257

258
/*!
knopp's avatar
knopp committed
259
 * \brief The RX UE-specific and TX thread of eNB.
260
261
262
 * \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.
 */
263

Sandeep Kumar's avatar
Sandeep Kumar committed
264
265
static void* eNB_thread_rxtx( void* param ) {

knopp's avatar
knopp committed
266
  static int eNB_thread_rxtx_status;
267

knopp's avatar
knopp committed
268
  eNB_rxtx_proc_t *proc = (eNB_rxtx_proc_t*)param;
269
  PHY_VARS_eNB *eNB = RC.eNB[0][proc->CC_id];
270

knopp's avatar
knopp committed
271
272
  char thread_name[100];

273
  //LOG_D(PHY,"%s()\n", __FUNCTION__);
274

275
  // set default return value
knopp's avatar
knopp committed
276
  eNB_thread_rxtx_status = 0;
277
278


279
  sprintf(thread_name,"RXn_TXnp4_%d",&eNB->proc.proc_rxtx[0] == proc ? 0 : 1);
280
  thread_top_init(thread_name,1,850000L,1000000L,2000000L);
281

282
283
  //LOG_D(PHY,"%s() thread_name:%s\n", __FUNCTION__, thread_name);

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

287
    //LOG_D(PHY,"%s:%s() TX:%u/%u About to wait on proc->instance_cnt_rxtx:%d\n", thread_name, __FUNCTION__, proc->frame_tx, proc->subframe_tx, proc->instance_cnt_rxtx);
knopp's avatar
knopp committed
288
    if (wait_on_condition(&proc->mutex_rxtx,&proc->cond_rxtx,&proc->instance_cnt_rxtx,thread_name)<0) break;
289

290
    //LOG_D(PHY,"%s:%s() TX:%u/%u - WOKEN on proc->instance_cnt_rxtx proc->instance_cnt_rxtx:%d \n", thread_name, __FUNCTION__, proc->frame_tx, proc->subframe_tx, proc->instance_cnt_rxtx);
291

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

294
295
    if (oai_exit) break;

296
    //LOG_D(PHY,"%s:%s() TX:%u/%u About to rxtx()\n", thread_name, __FUNCTION__, proc->frame_tx, proc->subframe_tx);
297
298
    if (eNB->CC_id==0)
      if (rxtx(eNB,proc,thread_name) < 0) break;
299

300
    //LOG_D(PHY,"%s:%s() TX:%u/%u DONE rxtx()\n", thread_name, __FUNCTION__, proc->frame_tx, proc->subframe_tx);
301

302
303
    if (release_thread(&proc->mutex_rxtx,&proc->instance_cnt_rxtx,thread_name)<0) break;

knopp's avatar
knopp committed
304
  } // while !oai_exit
305

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

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

knopp's avatar
knopp committed
310
311
  eNB_thread_rxtx_status = 0;
  return &eNB_thread_rxtx_status;
312
313
}

314

knopp's avatar
knopp committed
315
316
#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
317
318
static void wait_system_ready (char *message, volatile int *start_flag) {
  
319
  static char *indicator[] = {".    ", "..   ", "...  ", ".... ", ".....",
Sandeep Kumar's avatar
Sandeep Kumar committed
320
			      " ....", "  ...", "   ..", "    .", "     "};
321
322
323
324
325
326
327
  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);
328
  }
329
330
  
  LOG_D(EMU,"\n");
331
332
}
#endif
333

knopp's avatar
knopp committed
334
335


knopp's avatar
knopp committed
336

knopp's avatar
knopp committed
337

Cedric Roux's avatar
Cedric Roux committed
338
339
void eNB_top(PHY_VARS_eNB *eNB, int frame_rx, int subframe_rx, char *string)
{
340
341
  eNB_proc_t *proc           = &eNB->proc;
  eNB_rxtx_proc_t *proc_rxtx = &proc->proc_rxtx[0];
342

343
344
  proc->frame_rx    = frame_rx;
  proc->subframe_rx = subframe_rx;
knopp's avatar
knopp committed
345

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

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

352
353
    proc_rxtx->subframe_rx = proc->subframe_rx;
    proc_rxtx->frame_rx    = proc->frame_rx;
354
355
    proc_rxtx->subframe_tx = (proc->subframe_rx+sf_ahead)%10;
    proc_rxtx->frame_tx    = (proc->subframe_rx>(9-sf_ahead)) ? (1+proc->frame_rx)&1023 : proc->frame_rx;
356
357
    proc->frame_tx         = proc_rxtx->frame_tx;
    proc_rxtx->timestamp_tx = proc->timestamp_tx;
knopp's avatar
knopp committed
358

359
    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);
360
    //LOG_D(PHY,"eNB_top out %p (proc %p, CC_id %d), frame %d, subframe %d, instance_cnt_prach %d\n", (void*)pthread_self(), proc, eNB->CC_id, proc->frame_rx,proc->subframe_rx,proc->instance_cnt_prach);
361
  }
knopp's avatar
knopp committed
362
363
364
}


365
366
367
368
369
370
371
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;
372
373
374
375

  int i;
  struct timespec wait;
  
376
377
  LOG_D(PHY,"About to wake RUs\n");

378
  pthread_mutex_lock(&proc->mutex_RU);
379
  LOG_D(PHY,"eNB->num_RU:%d\n", eNB->num_RU);
380
  for (i=0;i<eNB->num_RU;i++) {
381
    LOG_D(PHY,"eNB->RU_list[%d]:%p\n",i,eNB->RU_list[i]);
382
    if (ru == eNB->RU_list[i]) {
383
      LOG_D(PHY,"proc->RU_mask:%02x\n", proc->RU_mask);
384
385
386
387
388
389
390
      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
391
    LOG_E(PHY,"Not all RUs have provided their info\n");
392
393
394
395
396
397
398
399
400
401
402
    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);
  }




403
404
405
  wait.tv_sec=0;
  wait.tv_nsec=5000000L;

406
#if 0
407
408
  /* accept some delay in processing - up to 5ms */
  for (i = 0; i < 10 && proc_rxtx->instance_cnt_rxtx == 0; i++) {
409
    LOG_W( PHY,"[eNB] Frame %d Subframe %d, eNB RXn-TXnp4 thread busy!! (cnt_rxtx %i)\n", proc_rxtx->frame_tx, proc_rxtx->subframe_tx, proc_rxtx->instance_cnt_rxtx);
410
411
412
    usleep(500);
  }
  if (proc_rxtx->instance_cnt_rxtx == 0) {
413
    //exit_fun( "TX thread busy" ); - DJP - this is commented out just whilst I work out what has gone wrong
414
415
    return(-1);
  }
416
#endif
417

418
  // wake up TX for subframe n+2
419
420
421
422
423
424
425
426
  // 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;
427
  LOG_D(PHY,"%s() %u/%u Just incremented proc->instance_cnt_rxtx:%d\n", __FUNCTION__, proc_rxtx->frame_tx, proc_rxtx->subframe_tx, proc_rxtx->instance_cnt_rxtx);
428
429
430
431
432
  
  // 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, 
433
434
435
  // 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
  proc_rxtx->timestamp_tx = proc->timestamp_rx + (sf_ahead*fp->samples_per_tti);
436
437
  proc_rxtx->frame_rx     = proc->frame_rx;
  proc_rxtx->subframe_rx  = proc->subframe_rx;
438
439
  proc_rxtx->frame_tx     = (proc_rxtx->subframe_rx > (9-sf_ahead)) ? (proc_rxtx->frame_rx+1)&1023 : proc_rxtx->frame_rx;
  proc_rxtx->subframe_tx  = (proc_rxtx->subframe_rx + sf_ahead)%10;
440
  
441
442
  LOG_D(PHY,"Signal &proc_rxtx->cond_rxtx\n");

443
444
445
446
447
448
449
450
451
452
453
454
  // 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);
}

455
void wakeup_prach_eNB(PHY_VARS_eNB *eNB,RU_t *ru,int frame,int subframe) {
knopp's avatar
knopp committed
456
457
458

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

461
462
463
464
  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
465
	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);
466
467
	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",
468
		eNB->Mod_id,frame,subframe,ru->idx,eNB->num_RU,proc->RU_mask_prach);
469
470
471
472
473
	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
474
      return;
475
476
477
478
479
480
481
    }
    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
482
  // check if we have to detect PRACH first
483
  if (is_prach_subframe(fp,frame,subframe)>0) { 
484
    LOG_D(PHY,"Triggering prach processing, frame %d, subframe %d\n",frame,subframe);
knopp's avatar
knopp committed
485
    if (proc->instance_cnt_prach == 0) {
486
      LOG_W(PHY,"[eNB] Frame %d Subframe %d, dropping PRACH\n", frame,subframe);
knopp's avatar
knopp committed
487
488
489
490
491
492
493
494
495
496
497
498
      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
499
500
    proc->frame_prach = frame;
    proc->subframe_prach = subframe;
knopp's avatar
knopp committed
501
502
503
504
505
506
507
508
509
510
511
512
513
    
    // 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 );
  }

}

514
515
516
517
518
519
520
521
522
523
524
#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
525
	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);
526
527
528
529
530
531
532
533
	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
534
      return;
535
536
537
538
539
540
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
    }
    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

575
576
577
578
579
/*!
 * \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
580
static void* eNB_thread_prach( void* param ) {
581
582
  static int eNB_thread_prach_status;

583
584
585

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

587
588
589
  // set default return value
  eNB_thread_prach_status = 0;

590
  thread_top_init("eNB_thread_prach",1,500000L,1000000L,20000000L);
591

592

Sandeep Kumar's avatar
Sandeep Kumar committed
593
594
595
596
  while (!oai_exit) {
    
    if (oai_exit) break;

597
    
knopp's avatar
knopp committed
598
    if (wait_on_condition(&proc->mutex_prach,&proc->cond_prach,&proc->instance_cnt_prach,"eNB_prach_thread") < 0) break;
knopp's avatar
knopp committed
599
600

    LOG_D(PHY,"Running eNB prach procedures\n");
601
602
603
604
605
    prach_procedures(eNB
#ifdef Rel14
		     ,0
#endif
		     );
606
    
knopp's avatar
knopp committed
607
    if (release_thread(&proc->mutex_prach,&proc->instance_cnt_prach,"eNB_prach_thread") < 0) break;
Sandeep Kumar's avatar
Sandeep Kumar committed
608
  }
609

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

612
613
  eNB_thread_prach_status = 0;
  return &eNB_thread_prach_status;
614
615
}

616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
#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
654

knopp's avatar
knopp committed
655

656
extern void init_fep_thread(PHY_VARS_eNB *, pthread_attr_t *);
knopp's avatar
knopp committed
657
658
extern void init_td_thread(PHY_VARS_eNB *, pthread_attr_t *);
extern void init_te_thread(PHY_VARS_eNB *, pthread_attr_t *);
659

660
void init_eNB_proc(int inst) {
Sandeep Kumar's avatar
Sandeep Kumar committed
661
  
Rohit Gupta's avatar
Rohit Gupta committed
662
  int i=0;
663
  int CC_id;
664
665
  PHY_VARS_eNB *eNB;
  eNB_proc_t *proc;
knopp's avatar
knopp committed
666
  eNB_rxtx_proc_t *proc_rxtx;
knopp's avatar
knopp committed
667
668
  pthread_attr_t *attr0=NULL,*attr1=NULL,*attr_prach=NULL;
    //*attr_td=NULL,*attr_te=NULL;
669
670
671
#ifdef Rel14
  pthread_attr_t *attr_prach_br=NULL;
#endif
knopp's avatar
knopp committed
672

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

knopp's avatar
knopp committed
675
  for (CC_id=0; CC_id<RC.nb_CC[inst]; CC_id++) {
676
    eNB = RC.eNB[inst][CC_id];
laurent's avatar
small2    
laurent committed
677
#ifndef OCP_FRAMEWORK
678
    LOG_I(PHY,"Initializing eNB processes instance:%d CC_id %d \n",inst,CC_id);
laurent's avatar
small2    
laurent committed
679
#endif
680
    proc = &eNB->proc;
knopp's avatar
knopp committed
681

682
    proc_rxtx                      = proc->proc_rxtx;
683
684
    proc_rxtx[0].instance_cnt_rxtx = -1;
    proc_rxtx[1].instance_cnt_rxtx = -1;
685
    proc->instance_cnt_prach       = -1;
686
    proc->instance_cnt_asynch_rxtx = -1;
687
    proc->CC_id                    = CC_id;    
688

knopp's avatar
knopp committed
689
690
    proc->first_rx=1;
    proc->first_tx=1;
691
692
    proc->RU_mask=0;
    proc->RU_mask_prach=0;
knopp's avatar
knopp committed
693

694
    pthread_mutex_init( &eNB->UL_INFO_mutex, NULL);
695
696
697
698
    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
699
700
701

    pthread_mutex_init( &proc->mutex_prach, NULL);
    pthread_mutex_init( &proc->mutex_asynch_rxtx, NULL);
702
703
    pthread_mutex_init( &proc->mutex_RU,NULL);
    pthread_mutex_init( &proc->mutex_RU_PRACH,NULL);
knopp's avatar
knopp committed
704

705
    pthread_cond_init( &proc->cond_prach, NULL);
706
    pthread_cond_init( &proc->cond_asynch_rxtx, NULL);
707
708
709

    pthread_attr_init( &proc->attr_prach);
    pthread_attr_init( &proc->attr_asynch_rxtx);
knopp's avatar
knopp committed
710
711
    //    pthread_attr_init( &proc->attr_td);
    //    pthread_attr_init( &proc->attr_te);
712
713
    pthread_attr_init( &proc_rxtx[0].attr_rxtx);
    pthread_attr_init( &proc_rxtx[1].attr_rxtx);
714
715
716
717
718
719
720
721
#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
722
#ifndef DEADLINE_SCHEDULER
knopp's avatar
knopp committed
723
724
725
    attr0       = &proc_rxtx[0].attr_rxtx;
    attr1       = &proc_rxtx[1].attr_rxtx;
    attr_prach  = &proc->attr_prach;
726
727
728
729
#ifdef Rel14
    attr_prach_br  = &proc->attr_prach_br;
#endif

knopp's avatar
knopp committed
730
731
    //    attr_td     = &proc->attr_td;
    //    attr_te     = &proc->attr_te; 
knopp's avatar
knopp committed
732
733
#endif

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

736
737
738
739
    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] );
    }
740
    pthread_create( &proc->pthread_prach, attr_prach, eNB_thread_prach, eNB );
741
742
743
#ifdef Rel14
    pthread_create( &proc->pthread_prach_br, attr_prach_br, eNB_thread_prach_br, eNB );
#endif
744
    char name[16];
745
746
747
748
749
750
    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
751
752
753

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

754
    
755
  }
756

757
  //for multiple CCs: setup master and slaves
758
759
760
  /* 
     for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
     eNB = PHY_vars_eNB_g[inst][CC_id];
761

762
763
764
     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*));
765

766
767
768
769
770
771
772
     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);
     }
     }
     }
  */
773

774
775
776
777
  /* 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;
778
779
}

780

781

782
783
784
/*!
 * \brief Terminate eNB TX and RX threads.
 */
785
void kill_eNB_proc(int inst) {
Sandeep Kumar's avatar
Sandeep Kumar committed
786

787
  int *status;
788
789
  PHY_VARS_eNB *eNB;
  eNB_proc_t *proc;
knopp's avatar
knopp committed
790
  eNB_rxtx_proc_t *proc_rxtx;
791
  for (int CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
792
    eNB=RC.eNB[inst][CC_id];
793
794
    
    proc = &eNB->proc;
knopp's avatar
knopp committed
795
    proc_rxtx = &proc->proc_rxtx[0];
796
    
knopp's avatar
knopp committed
797
798

    LOG_I(PHY, "Killing TX CC_id %d inst %d\n", CC_id, inst );
799
800
801
802
803
804
805

    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
806
807
    proc->instance_cnt_prach = 0;
    pthread_cond_signal( &proc->cond_prach );
808

809
    pthread_cond_broadcast(&sync_phy_proc.cond_phy_proc_tx);
810
    pthread_join( proc->pthread_prach, (void**)&status );    
811

812
    LOG_I(PHY, "Destroying prach mutex/cond\n");
813
    pthread_mutex_destroy( &proc->mutex_prach );
814
815
    pthread_cond_destroy( &proc->cond_prach );
#ifdef Rel14
816
    proc->instance_cnt_prach_br = 0;
817
818
819
820
821
    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         
822
    LOG_I(PHY, "Destroying UL_INFO mutex\n");
823
    pthread_mutex_destroy(&eNB->UL_INFO_mutex);
824
    int i;
825
826
    if (eNB->single_thread_flag==0) {
      for (i=0;i<2;i++) {
knopp's avatar
knopp committed
827
	LOG_I(PHY, "Joining rxtx[%d] mutex/cond\n",i);
828
	pthread_join( proc_rxtx[i].pthread_rxtx, (void**)&status );
knopp's avatar
knopp committed
829
	LOG_I(PHY, "Destroying rxtx[%d] mutex/cond\n",i);
830
831
832
	pthread_mutex_destroy( &proc_rxtx[i].mutex_rxtx );
	pthread_cond_destroy( &proc_rxtx[i].cond_rxtx );
      }
knopp's avatar
knopp committed
833
    }
834
  }
835
836
}

837

838
839
840


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

842
843
844
845
846
  int sfn;
  reset_meas(&softmodem_stats_mt);
  reset_meas(&softmodem_stats_hw);
  
  for (sfn=0; sfn < 10; sfn++) {
knopp's avatar
knopp committed
847
    reset_meas(&softmodem_stats_rxtx_sf);
848
    reset_meas(&softmodem_stats_rx_sf);
849
850
851
  }
}

Sandeep Kumar's avatar
Sandeep Kumar committed
852

853
854
855
856
857
858
859
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
860
    print_meas(&softmodem_stats_rxtx_sf,"[eNB][total_phy_proc_rxtx]",NULL, NULL);
861
    print_meas(&softmodem_stats_rx_sf,"[eNB][total_phy_proc_rx]",NULL,NULL);
862
863
  }
}
864

865
void init_transport(PHY_VARS_eNB *eNB) {
866

867
868
869
  int i;
  int j;
  LTE_DL_FRAME_PARMS *fp = &eNB->frame_parms;
knopp's avatar
knopp committed
870

871
872
  LOG_E(PHY, "Initialise transport\n");

873
874
875
876
877
878
  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
879
	exit(-1);
880
881
      } else {
	eNB->dlsch[i][j]->rnti=0;
882
	LOG_D(PHY,"dlsch[%d][%d] => %p rnti:%d\n",i,j,eNB->dlsch[i][j], eNB->dlsch[i][j]->rnti);
knopp's avatar
knopp committed
883
884
      }
    }
885
886
887
888
889
890
    
    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
891
892
      exit(-1);
    }
893
894
895
896
    
    // 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
897
  }
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
  // 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
914
  
915
916
917
918
919
920
921
922
923
924
925
926
927
928
  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
929

930
void init_eNB_afterRU(void) {
knopp's avatar
knopp committed
931

932
933
  int inst,CC_id,ru_id,i,aa;
  PHY_VARS_eNB *eNB;
934

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

937
  for (inst=0;inst<RC.nb_inst;inst++) {
938
    LOG_I(PHY,"RC.nb_CC[inst]:%d\n", RC.nb_CC[inst]);
939
    for (CC_id=0;CC_id<RC.nb_CC[inst];CC_id++) {
940

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

943
944
945
      eNB                                  =  RC.eNB[inst][CC_id];
      phy_init_lte_eNB(eNB,0,0);
      // map antennas and PRACH signals to eNB RX
946
      if (0) AssertFatal(eNB->num_RU>0,"Number of RU attached to eNB %d is zero\n",eNB->Mod_id);
947
      LOG_I(PHY,"Mapping RX ports from %d RUs to eNB %d\n",eNB->num_RU,eNB->Mod_id);
948
      eNB->frame_parms.nb_antennas_rx       = 0;
949
950
951

      LOG_E(PHY,"Overwriting eNB->prach_vars.rxsigF[0]:%p\n", eNB->prach_vars.rxsigF[0]);

knopp's avatar
knopp committed
952
      eNB->prach_vars.rxsigF[0] = (int16_t**)malloc16(64*sizeof(int16_t*));
953
#ifdef Rel14
954
955
956
957
      for (int ce_level=0;ce_level<4;ce_level++) {
        LOG_E(PHY,"Overwriting eNB->prach_vars_br.rxsigF.rxsigF[0]:%p\n", eNB->prach_vars_br.rxsigF[ce_level]);
        eNB->prach_vars_br.rxsigF[ce_level] = (int16_t**)malloc16(64*sizeof(int16_t*));
      }
958
#endif
959
960
961

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

962
963
      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;
964
965
966
967
968
969
970
971
972

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

973
974
	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
975
976
977
978
979
	  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
980
981
982
	  eNB->common_vars.rxdataF[aa]     =  eNB->RU_list[ru_id]->common.rxdataF[i];
	}
      }
983
984
985
986
987
988
989
990
991




      if (eNB->frame_parms.nb_antennas_rx < 1)
      {
        LOG_I(PHY, "%s() ************* DJP ***** eNB->frame_parms.nb_antennas_rx:%d - GOING TO HARD CODE TO 1", __FUNCTION__, eNB->frame_parms.nb_antennas_rx);
        eNB->frame_parms.nb_antennas_rx = 1;
      }
992
993
994
995
      else
      {
        LOG_I(PHY," Delete code\n");
      }
996
997
998
999
1000
1001

      if (eNB->frame_parms.nb_antennas_tx < 1)
      {
        LOG_I(PHY, "%s() ************* DJP ***** eNB->frame_parms.nb_antennas_tx:%d - GOING TO HARD CODE TO 1", __FUNCTION__, eNB->frame_parms.nb_antennas_tx);
        eNB->frame_parms.nb_antennas_tx = 1;
      }
1002
1003
1004
1005
      else
      {
        LOG_I(PHY," Delete code\n");
      }
1006
1007
1008
1009




1010
1011
1012
      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);
1013
1014

      init_transport(eNB);
knopp's avatar
knopp committed
1015
      //init_precoding_weights(RC.eNB[inst][CC_id]);
1016
    }
1017
    printf("RC.nb_CC[inst:%d]:%d CC_id:%d AFTER LOOP - About to init_eNB_proc\n", inst, RC.nb_CC[inst], CC_id);
1018
1019
    init_eNB_proc(inst);
  }
1020
  printf("%s() RC.nb_inst:%d AFTER LOOP\n", __FUNCTION__, RC.nb_inst);
knopp's avatar
knopp committed
1021

1022
  printf("%s:%d RC.nb_RU:%d\n", __FILE__, __LINE__, RC.nb_RU);
1023
  for (ru_id=0;ru_id<RC.nb_RU;ru_id++) {
1024
1025

    AssertFatal(RC.ru[ru_id]!=NULL,"ru_id %d is null\n",ru_id);
1026
    
1027
1028
1029
    RC.ru[ru_id]->wakeup_rxtx         = wakeup_rxtx;
    RC.