dlsim.c 85.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
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

/*! \file dlsim.c
 \brief Top-level DL simulator
 \author R. Knopp
25
 \date 2011 - 2014
26 27 28 29 30 31 32
 \version 0.1
 \company Eurecom
 \email: knopp@eurecom.fr
 \note
 \warning
*/

33 34 35 36 37 38
#include <string.h>
#include <math.h>
#include <unistd.h>
#include <execinfo.h>
#include <signal.h>

39
#include "SIMULATION/TOOLS/sim.h"
40
#include "PHY/types.h"
41 42 43
#include "PHY/defs_eNB.h"
#include "PHY/defs_UE.h"
#include "PHY/phy_vars.h"
44

45 46 47
#include "SCHED/sched_eNB.h"
#include "SCHED/sched_common_vars.h"
#include "LAYER2/MAC/mac_vars.h"
48 49

#include "OCG_vars.h"
50
#include "common/utils/LOG/log.h"
51
#include "UTIL/LISTS/list.h"
52

53 54
#include "unitary_defs.h"

55 56 57

#include "PHY/TOOLS/lte_phy_scope.h"

knopp's avatar
knopp committed
58 59
#include "dummy_functions.c"

60 61 62 63 64 65 66
#include "PHY/MODULATION/modulation_common.h"
#include "PHY/MODULATION/modulation_eNB.h"
#include "PHY/MODULATION/modulation_UE.h"
#include "PHY/LTE_TRANSPORT/transport_proto.h"
#include "PHY/LTE_UE_TRANSPORT/transport_proto_ue.h"
#include "SCHED/sched_eNB.h"
#include "SCHED_UE/sched_UE.h"
67 68 69
#include "common/config/config_load_configmodule.h"
#include "PHY/INIT/phy_init.h"

knopp's avatar
knopp committed
70

71 72
void feptx_ofdm(RU_t *ru);
void feptx_prec(RU_t *ru);
73

74
double cpuf;
75 76 77
#define inMicroS(a) (((double)(a))/(cpu_freq_GHz*1000.0))
//#define MCS_COUNT 23//added for PHY abstraction
#include <openair1/SIMULATION/LTE_PHY/common_sim.h>
78

79
int otg_enabled=0;
80 81 82 83 84 85 86
/*the following parameters are used to control the processing times calculations*/
double t_tx_max = -1000000000; /*!< \brief initial max process time for tx */
double t_rx_max = -1000000000; /*!< \brief initial max process time for rx */
double t_tx_min = 1000000000; /*!< \brief initial min process time for tx */
double t_rx_min = 1000000000; /*!< \brief initial min process time for rx */
int n_tx_dropped = 0; /*!< \brief initial max process time for tx */
int n_rx_dropped = 0; /*!< \brief initial max process time for rx */
87

88 89
char *parallel_config = NULL;
char *worker_config = NULL;
Wang Tsu-Han's avatar
Wang Tsu-Han committed
90
static THREAD_STRUCT thread_struct;
91
void set_parallel_conf(char *parallel_conf)
Wang Tsu-Han's avatar
Wang Tsu-Han committed
92
{
93 94 95 96
  if(strcmp(parallel_conf,"PARALLEL_SINGLE_THREAD")==0)           thread_struct.parallel_conf = PARALLEL_SINGLE_THREAD;
  else if(strcmp(parallel_conf,"PARALLEL_RU_L1_SPLIT")==0)        thread_struct.parallel_conf = PARALLEL_RU_L1_SPLIT;
  else if(strcmp(parallel_conf,"PARALLEL_RU_L1_TRX_SPLIT")==0)    thread_struct.parallel_conf = PARALLEL_RU_L1_TRX_SPLIT;
  printf("[CONFIG] parallel conf is set to %d\n",thread_struct.parallel_conf);
Wang Tsu-Han's avatar
Wang Tsu-Han committed
97
} 
98
void set_worker_conf(char *worker_conf)
Wang Tsu-Han's avatar
Wang Tsu-Han committed
99
{
100 101 102
  if(strcmp(worker_conf,"WORKER_DISABLE")==0)                     thread_struct.worker_conf = WORKER_DISABLE;
  else if(strcmp(worker_conf,"WORKER_ENABLE")==0)                 thread_struct.worker_conf = WORKER_ENABLE;
  printf("[CONFIG] worker conf is set to %d\n",thread_struct.worker_conf);
Wang Tsu-Han's avatar
Wang Tsu-Han committed
103 104 105 106 107 108 109 110 111
} 
PARALLEL_CONF_t get_thread_parallel_conf(void)
{
  return thread_struct.parallel_conf;
} 
WORKER_CONF_t get_thread_worker_conf(void)
{
  return thread_struct.worker_conf;
} 
Cedric Roux's avatar
Cedric Roux committed
112

knopp's avatar
knopp committed
113 114
int emulate_rf = 0;

115 116
void handler(int sig)
{
117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136
  void *array[10];
  size_t size;

  // get void*'s for all entries on the stack
  size = backtrace(array, 10);

  // print out all the frames to stderr
  fprintf(stderr, "Error: signal %d:\n", sig);
  backtrace_symbols_fd(array, size, 2);
  exit(1);
}



//DCI2_5MHz_2A_M10PRB_TDD_t DLSCH_alloc_pdu2_2A[2];

DCI1E_5MHz_2A_M10PRB_TDD_t  DLSCH_alloc_pdu2_1E[2];
uint64_t DLSCH_alloc_pdu_1[2];

#define UL_RB_ALLOC 0x1ff;
137
#define CCCH_RB_ALLOC computeRIV(eNB->frame_parms.N_RB_UL,0,2)
138 139
//#define DLSCH_RB_ALLOC 0x1fbf // igore DC component,RB13
//#define DLSCH_RB_ALLOC 0x0001
140
void do_OFDM_mod_l(int32_t **txdataF, int32_t **txdata, uint16_t next_slot, LTE_DL_FRAME_PARMS *frame_parms)
141
{
142 143 144 145 146 147 148 149 150 151 152

  int aa, slot_offset, slot_offset_F;

  slot_offset_F = (next_slot)*(frame_parms->ofdm_symbol_size)*((frame_parms->Ncp==1) ? 6 : 7);
  slot_offset = (next_slot)*(frame_parms->samples_per_tti>>1);

  for (aa=0; aa<frame_parms->nb_antennas_tx; aa++) {
    //    printf("Thread %d starting ... aa %d (%llu)\n",omp_get_thread_num(),aa,rdtsc());

    if (frame_parms->Ncp == 1)
      PHY_ofdm_mod(&txdataF[aa][slot_offset_F],        // input
153
                   &txdata[aa][slot_offset],         // output
154
                   frame_parms->ofdm_symbol_size,
155 156 157
                   6,                 // number of symbols
                   frame_parms->nb_prefix_samples,               // number of prefix samples
                   CYCLIC_PREFIX);
158 159
    else {
      normal_prefix_mod(&txdataF[aa][slot_offset_F],
160 161 162
                        &txdata[aa][slot_offset],
                        7,
                        frame_parms);
163
    }
164

165 166

  }
167

168 169
}

knopp's avatar
knopp committed
170
void DL_channel(RU_t *ru,PHY_VARS_UE *UE,uint subframe,int awgn_flag,double SNR, int tx_lev,int hold_channel,int abstx, int num_rounds, int trials, int round, channel_desc_t *eNB2UE[4],
171
		double *s_re[2],double *s_im[2],double *r_re[2],double *r_im[2],FILE *csv_fd) {
172

173 174 175 176
  int i,u;
  int aa,aarx,aatx;
  double channelx,channely;
  double sigma2_dB,sigma2;
177 178
  double iqim=0.0;

179 180
  //    printf("Copying tx ..., nsymb %d (n_tx %d), awgn %d\n",nsymb,eNB->frame_parms.nb_antennas_tx,awgn_flag);
  for (i=0; i<2*UE->frame_parms.samples_per_tti; i++) {
knopp's avatar
knopp committed
181
    for (aa=0; aa<ru->frame_parms.nb_antennas_tx; aa++) {
182
      if (awgn_flag == 0) {
knopp's avatar
knopp committed
183 184
	s_re[aa][i] = ((double)(((short *)ru->common.txdata[aa]))[(2*subframe*UE->frame_parms.samples_per_tti) + (i<<1)]);
	s_im[aa][i] = ((double)(((short *)ru->common.txdata[aa]))[(2*subframe*UE->frame_parms.samples_per_tti) +(i<<1)+1]);
185 186 187
      } else {
	for (aarx=0; aarx<UE->frame_parms.nb_antennas_rx; aarx++) {
	  if (aa==0) {
knopp's avatar
knopp committed
188 189
	    r_re[aarx][i] = ((double)(((short *)ru->common.txdata[aa]))[(2*subframe*UE->frame_parms.samples_per_tti) +(i<<1)]);
	    r_im[aarx][i] = ((double)(((short *)ru->common.txdata[aa]))[(2*subframe*UE->frame_parms.samples_per_tti) +(i<<1)+1]);
190
	  } else {
knopp's avatar
knopp committed
191 192
	    r_re[aarx][i] += ((double)(((short *)ru->common.txdata[aa]))[(2*subframe*UE->frame_parms.samples_per_tti) +(i<<1)]);
	    r_im[aarx][i] += ((double)(((short *)ru->common.txdata[aa]))[(2*subframe*UE->frame_parms.samples_per_tti) +(i<<1)+1]);
193
	  }
194

195 196 197 198
	}
      }
    }
  }
199

200 201 202 203
  // Multipath channel
  if (awgn_flag == 0) {
    multipath_channel(eNB2UE[round],s_re,s_im,r_re,r_im,
		      2*UE->frame_parms.samples_per_tti,hold_channel);
204

205 206 207 208 209 210 211
    //      printf("amc: ****************** eNB2UE[%d]->n_rx = %d,dd %d\n",round,eNB2UE[round]->nb_rx,eNB2UE[round]->channel_offset);
    if(abstx==1 && num_rounds>1)
      if(round==0 && hold_channel==0) {
	random_channel(eNB2UE[1],0);
	random_channel(eNB2UE[2],0);
	random_channel(eNB2UE[3],0);
      }
212

213 214 215 216
    if (UE->perfect_ce==1) {
      // fill in perfect channel estimates
      freq_channel(eNB2UE[round],UE->frame_parms.N_RB_DL,12*UE->frame_parms.N_RB_DL + 1);
      /*
Mongazon's avatar
Mongazon committed
217 218
	LOG_M("channel.m","ch",eNB2UE[round]->ch[0],eNB2UE[round]->channel_length,1,8);
	LOG_M("channelF.m","chF",eNB2UE[round]->chF[0],12*UE->frame_parms.N_RB_DL + 1,1,8);
219 220 221
      */
    }
  }
222 223


224 225 226
  if(abstx) {
    if (trials==0 && round==0) {
      // calculate freq domain representation to compute SINR
knopp's avatar
knopp committed
227
      freq_channel(eNB2UE[0], ru->frame_parms.N_RB_DL,2*ru->frame_parms.N_RB_DL + 1);
228 229
      // snr=pow(10.0,.1*SNR);
      fprintf(csv_fd,"%f,",SNR);
230

knopp's avatar
knopp committed
231
      for (u=0; u<2*ru->frame_parms.N_RB_DL; u++) {
232 233 234 235 236 237 238
	for (aarx=0; aarx<eNB2UE[0]->nb_rx; aarx++) {
	  for (aatx=0; aatx<eNB2UE[0]->nb_tx; aatx++) {
	    channelx = eNB2UE[0]->chF[aarx+(aatx*eNB2UE[0]->nb_rx)][u].x;
	    channely = eNB2UE[0]->chF[aarx+(aatx*eNB2UE[0]->nb_rx)][u].y;
	    fprintf(csv_fd,"%e+i*(%e),",channelx,channely);
	  }
	}
239 240
      }

241
      if(num_rounds>1) {
knopp's avatar
knopp committed
242
	freq_channel(eNB2UE[1], ru->frame_parms.N_RB_DL,2*ru->frame_parms.N_RB_DL + 1);
243

knopp's avatar
knopp committed
244
	for (u=0; u<2*ru->frame_parms.N_RB_DL; u++) {
245 246 247 248 249 250 251 252
	  for (aarx=0; aarx<eNB2UE[1]->nb_rx; aarx++) {
	    for (aatx=0; aatx<eNB2UE[1]->nb_tx; aatx++) {
	      channelx = eNB2UE[1]->chF[aarx+(aatx*eNB2UE[1]->nb_rx)][u].x;
	      channely = eNB2UE[1]->chF[aarx+(aatx*eNB2UE[1]->nb_rx)][u].y;
	      fprintf(csv_fd,"%e+i*(%e),",channelx,channely);
	    }
	  }
	}
253

knopp's avatar
knopp committed
254
	freq_channel(eNB2UE[2], ru->frame_parms.N_RB_DL,2*ru->frame_parms.N_RB_DL + 1);
255

knopp's avatar
knopp committed
256
	for (u=0; u<2*ru->frame_parms.N_RB_DL; u++) {
257 258 259 260 261 262 263 264
	  for (aarx=0; aarx<eNB2UE[2]->nb_rx; aarx++) {
	    for (aatx=0; aatx<eNB2UE[2]->nb_tx; aatx++) {
	      channelx = eNB2UE[2]->chF[aarx+(aatx*eNB2UE[2]->nb_rx)][u].x;
	      channely = eNB2UE[2]->chF[aarx+(aatx*eNB2UE[2]->nb_rx)][u].y;
	      fprintf(csv_fd,"%e+i*(%e),",channelx,channely);
	    }
	  }
	}
265

knopp's avatar
knopp committed
266
	freq_channel(eNB2UE[3], ru->frame_parms.N_RB_DL,2*ru->frame_parms.N_RB_DL + 1);
267

knopp's avatar
knopp committed
268
	for (u=0; u<2*ru->frame_parms.N_RB_DL; u++) {
269 270 271 272 273 274 275 276 277 278 279
	  for (aarx=0; aarx<eNB2UE[3]->nb_rx; aarx++) {
	    for (aatx=0; aatx<eNB2UE[3]->nb_tx; aatx++) {
	      channelx = eNB2UE[3]->chF[aarx+(aatx*eNB2UE[3]->nb_rx)][u].x;
	      channely = eNB2UE[3]->chF[aarx+(aatx*eNB2UE[3]->nb_rx)][u].y;
	      fprintf(csv_fd,"%e+i*(%e),",channelx,channely);
	    }
	  }
	}
      }
    }
  }
280

281
  //AWGN
282 283
  // tx_lev is the average energy over the whole subframe
  // but SNR should be better defined wrt the energy in the reference symbols
knopp's avatar
knopp committed
284
  sigma2_dB = 10*log10((double)tx_lev) +10*log10((double)ru->frame_parms.ofdm_symbol_size/(double)(ru->frame_parms.N_RB_DL*12)) - SNR;
285 286 287
  sigma2 = pow(10,sigma2_dB/10);

  for (i=0; i<2*UE->frame_parms.samples_per_tti; i++) {
288
    for (aa=0; aa<UE->frame_parms.nb_antennas_rx; aa++) {
289 290 291 292 293 294 295 296
      //printf("s_re[0][%d]=> %f , r_re[0][%d]=> %f\n",i,s_re[aa][i],i,r_re[aa][i]);
      ((short*) UE->common_vars.rxdata[aa])[(2*subframe*UE->frame_parms.samples_per_tti)+2*i] =
	(short) (r_re[aa][i] + sqrt(sigma2/2)*gaussdouble(0.0,1.0));
      ((short*) UE->common_vars.rxdata[aa])[(2*subframe*UE->frame_parms.samples_per_tti)+2*i+1] =
	(short) (r_im[aa][i] + (iqim*r_re[aa][i]) + sqrt(sigma2/2)*gaussdouble(0.0,1.0));
    }
  }
}
297

knopp's avatar
knopp committed
298 299
uint16_t
fill_tx_req(nfapi_tx_request_body_t *tx_req_body,
Cedric Roux's avatar
Cedric Roux committed
300
	    uint16_t                absSF,
knopp's avatar
knopp committed
301
	    uint16_t                pdu_length,
Cedric Roux's avatar
Cedric Roux committed
302
	    uint16_t                pdu_index,
knopp's avatar
knopp committed
303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 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 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376
	    uint8_t                 *pdu)
{
  nfapi_tx_request_pdu_t *TX_req = &tx_req_body->tx_pdu_list[tx_req_body->number_of_pdus];
  LOG_D(MAC, "Filling TX_req %d for pdu length %d\n",
	tx_req_body->number_of_pdus, pdu_length);

  TX_req->pdu_length                 = pdu_length;
  TX_req->pdu_index                  = pdu_index;
  TX_req->num_segments               = 1;
  TX_req->segments[0].segment_length = pdu_length;
  TX_req->segments[0].segment_data   = pdu;
  tx_req_body->tl.tag                = NFAPI_TX_REQUEST_BODY_TAG;
  tx_req_body->number_of_pdus++;

  return (((absSF / 10) << 4) + (absSF % 10));
}

void
fill_dlsch_config(nfapi_dl_config_request_body_t * dl_req,
		  uint16_t length,
		  uint16_t pdu_index,
		  uint16_t rnti,
		  uint8_t resource_allocation_type,
		  uint8_t virtual_resource_block_assignment_flag,
		  uint16_t resource_block_coding,
		  uint8_t modulation,
		  uint8_t redundancy_version,
		  uint8_t transport_blocks,
		  uint8_t transport_block_to_codeword_swap_flag,
		  uint8_t transmission_scheme,
		  uint8_t number_of_layers,
		  uint8_t number_of_subbands,
		  //                             uint8_t codebook_index,
		  uint8_t ue_category_capacity,
		  uint8_t pa,
		  uint8_t delta_power_offset_index,
		  uint8_t ngap,
		  uint8_t nprb,
		  uint8_t transmission_mode,
		  uint8_t num_bf_prb_per_subband,
		  uint8_t num_bf_vector)
{
  nfapi_dl_config_request_pdu_t *dl_config_pdu =
    &dl_req->dl_config_pdu_list[dl_req->number_pdu];
  memset((void *) dl_config_pdu, 0,
	 sizeof(nfapi_dl_config_request_pdu_t));

  dl_config_pdu->pdu_type                                                        = NFAPI_DL_CONFIG_DLSCH_PDU_TYPE;
  dl_config_pdu->pdu_size                                                        = (uint8_t) (2 + sizeof(nfapi_dl_config_dlsch_pdu));
  dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.tl.tag                                 = NFAPI_DL_CONFIG_REQUEST_DLSCH_PDU_REL8_TAG;
  dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.length                                 = length;
  dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.pdu_index                              = pdu_index;
  dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.rnti                                   = rnti;
  dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.resource_allocation_type               = resource_allocation_type;
  dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.virtual_resource_block_assignment_flag = virtual_resource_block_assignment_flag;
  dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.resource_block_coding                  = resource_block_coding;
  dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.modulation                             = modulation;
  dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.redundancy_version                     = redundancy_version;
  dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.transport_blocks                       = transport_blocks;
  dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.transport_block_to_codeword_swap_flag  = transport_block_to_codeword_swap_flag;
  dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.transmission_scheme                    = transmission_scheme;
  dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.number_of_layers                       = number_of_layers;
  dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.number_of_subbands                     = number_of_subbands;
  //  dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.codebook_index                         = codebook_index;
  dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.ue_category_capacity                   = ue_category_capacity;
  dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.pa                                     = pa;
  dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.delta_power_offset_index               = delta_power_offset_index;
  dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.ngap                                   = ngap;
  dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.nprb                                   = nprb;
  dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.transmission_mode                      = transmission_mode;
  dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.num_bf_prb_per_subband                 = num_bf_prb_per_subband;
  dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.num_bf_vector                          = num_bf_vector;
  dl_req->number_pdu++;
}
377

378
void fill_DCI(PHY_VARS_eNB *eNB,
knopp's avatar
knopp committed
379
	      int frame,
380
	      int subframe,
knopp's avatar
knopp committed
381 382
	      Sched_Rsp_t *sched_resp,
	      uint8_t input_buffer[NUMBER_OF_UE_MAX][20000],
383 384 385
	      int n_rnti,
	      int n_users,
	      int transmission_mode,
knopp's avatar
knopp committed
386
	      int retrans,
387
	      int common_flag,
knopp's avatar
knopp committed
388
	      int NB_RB,
389 390 391 392 393 394
	      int DLSCH_RB_ALLOC,
	      int TPC,
	      int mcs1,
	      int mcs2,
	      int ndi,
	      int rv,
knopp's avatar
knopp committed
395
	      int pa,
396 397 398 399 400 401
	      int *num_common_dci,
	      int *num_ue_spec_dci,
	      int *num_dci) {

  int k;

knopp's avatar
knopp committed
402 403 404 405 406 407 408 409
  nfapi_dl_config_request_body_t *dl_req=&sched_resp->DL_req->dl_config_request_body;
  nfapi_dl_config_request_pdu_t  *dl_config_pdu;
  nfapi_tx_request_body_t        *TX_req=&sched_resp->TX_req->tx_request_body;

  dl_req->number_dci=0;
  dl_req->number_pdu=0;
  TX_req->number_of_pdus=0;

410 411 412
  for(k=0; k<n_users; k++) {
    switch(transmission_mode) {
    case 1:
413

414
    case 2:
Xiwen JIANG's avatar
Xiwen JIANG committed
415 416

    case 7:
417
      if (common_flag == 0) {
418

knopp's avatar
knopp committed
419 420 421 422 423 424 425 426 427 428 429
	dl_config_pdu = &dl_req->dl_config_pdu_list[dl_req->number_pdu];
	memset((void *) dl_config_pdu, 0,
	       sizeof(nfapi_dl_config_request_pdu_t));
	dl_config_pdu->pdu_type = NFAPI_DL_CONFIG_DCI_DL_PDU_TYPE;
	dl_config_pdu->pdu_size = (uint8_t) (2 + sizeof(nfapi_dl_config_dci_dl_pdu));
	dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.dci_format = NFAPI_DL_DCI_FORMAT_1;
	dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.aggregation_level = 4;
	dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.tl.tag = NFAPI_DL_CONFIG_REQUEST_DCI_DL_PDU_REL8_TAG;
	dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.rnti = n_rnti+k;
	dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.rnti_type = 1;	// CRNTI : see Table 4-10 from SCF082 - nFAPI specifications
	dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.transmission_power = 6000;	// equal to RS power
Cedric Roux's avatar
Cedric Roux committed
430

knopp's avatar
knopp committed
431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448
	dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.harq_process = 0;
	dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.tpc = TPC;	// dont adjust power when retransmitting
	dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.new_data_indicator_1 = ndi;
	dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.mcs_1 = mcs1;
	dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.redundancy_version_1 = rv;
	dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.resource_block_coding = DLSCH_RB_ALLOC;
	//deactivate second codeword
	dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.mcs_2 = 0;
	dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.redundancy_version_2 = 1;

	dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.downlink_assignment_index = 0;
	dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.cce_idx = 0;

	dl_req->number_dci++;
	dl_req->number_pdu++;
	dl_req->tl.tag = NFAPI_DL_CONFIG_REQUEST_BODY_TAG;


Cedric Roux's avatar
Cedric Roux committed
449 450
	fill_dlsch_config(dl_req,
			  get_TBS_DL(mcs1,NB_RB),
knopp's avatar
knopp committed
451
			  (retrans > 0) ? -1 : 0, /* retransmission, no pdu_index */
Cedric Roux's avatar
Cedric Roux committed
452
			  n_rnti,
knopp's avatar
knopp committed
453 454
			  0,	// type 0 allocation from 7.1.6 in 36.213
			  0,	// virtual_resource_block_assignment_flag, unused here
Cedric Roux's avatar
Cedric Roux committed
455 456
			  DLSCH_RB_ALLOC,	// resource_block_coding,
			  get_Qm(mcs1),
knopp's avatar
knopp committed
457 458 459 460 461 462 463 464
			  rv,	// redundancy version
			  1,	// transport blocks
			  0,	// transport block to codeword swap flag
			  transmission_mode == 1 ? 0 : 1,	// transmission_scheme
			  1,	// number of layers
			  1,	// number of subbands
				//                      uint8_t codebook_index,
			  4,	// UE category capacity
Cedric Roux's avatar
Cedric Roux committed
465
			  pa,    // pa
knopp's avatar
knopp committed
466 467 468 469 470 471 472 473 474
			  0,	// delta_power_offset for TM5
			  0,	// ngap
			  0,	// nprb
			  transmission_mode,
			  0,	//number of PRBs treated as one subband, not used here
			  0	// number of beamforming vectors, not used here
			  );
	fill_tx_req(TX_req,
		    (frame * 10) + subframe,
Cedric Roux's avatar
Cedric Roux committed
475
		    get_TBS_DL(mcs1,NB_RB),
knopp's avatar
knopp committed
476 477 478 479
		    0,
		    input_buffer[k]);
      }
      else {
480

knopp's avatar
knopp committed
481
      }
482

knopp's avatar
knopp committed
483
      break;
484

knopp's avatar
knopp committed
485 486
    case 3:
      if (common_flag == 0) {
Cedric Roux's avatar
Cedric Roux committed
487

knopp's avatar
knopp committed
488
	if (eNB->frame_parms.nb_antennas_tx == 2) {
Cedric Roux's avatar
Cedric Roux committed
489

knopp's avatar
knopp committed
490
	  if (eNB->frame_parms.frame_type == TDD) {
Cedric Roux's avatar
Cedric Roux committed
491

knopp's avatar
knopp committed
492 493
	  }
	  else {
Cedric Roux's avatar
Cedric Roux committed
494

knopp's avatar
knopp committed
495 496 497 498
	  }
	}
      }
      break;
Cedric Roux's avatar
Cedric Roux committed
499

knopp's avatar
knopp committed
500 501
    case 4:
      if (common_flag == 0) {
Cedric Roux's avatar
Cedric Roux committed
502

knopp's avatar
knopp committed
503
	if (eNB->frame_parms.nb_antennas_tx == 2) {
Cedric Roux's avatar
Cedric Roux committed
504

knopp's avatar
knopp committed
505
	  if (eNB->frame_parms.frame_type == TDD) {
Cedric Roux's avatar
Cedric Roux committed
506

507

knopp's avatar
knopp committed
508
	  }
509

knopp's avatar
knopp committed
510
	  else {
511

knopp's avatar
knopp committed
512 513
	  }
	} else if (eNB->frame_parms.nb_antennas_tx == 4) {
514

knopp's avatar
knopp committed
515
	}
516

knopp's avatar
knopp committed
517 518
      }
      else {
519

520
        }
521

522
        break;
523

524 525
      case 5:
      case 6:
526

527
        break;
528

knopp's avatar
knopp committed
529 530 531 532
    default:
      printf("Unsupported Transmission Mode %d!!!\n",transmission_mode);
      exit(-1);
      break;
533
    }
knopp's avatar
knopp committed
534 535 536 537
  }
  *num_dci         = dl_req->number_dci;
  *num_ue_spec_dci = dl_req->number_dci;
  *num_common_dci  = 0;
538
}
539

540
int n_users = 1;
541
int subframe=7;
542 543
int num_common_dci=0,num_ue_spec_dci=0,num_dci=0,num_pdcch_symbols=1;
uint16_t n_rnti=0x1234;
544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567
int nfapi_mode=0;
int abstx=0;
int Nid_cell=0;
int N_RB_DL=25;
int tdd_config=3;
int dci_flag=0;
int threequarter_fs=0;
double snr_step=1,input_snr_step=1, snr_int=30;
double forgetting_factor=0.0; //in [0,1] 0 means a new channel every time, 1 means keep the same channel
int test_perf=0;
int n_frames;
int n_ch_rlz = 1;
int rx_sample_offset = 0;
int xforms=0;
int dump_table=0;
int loglvl=OAILOG_WARNING;
int mcs1=0,mcs2=0,mcs_i=0,dual_stream_UE = 0,awgn_flag=0;
int two_thread_flag=0;
int num_rounds = 4;//,fix_rounds=0;
int perfect_ce = 0;
int extended_prefix_flag=0;
int verbose=0, help=0;
double SNR,snr0=-2.0,snr1,rate = 0;
int print_perf=0;
568

569 570
int main(int argc, char **argv)
{
571

knopp's avatar
knopp committed
572
  int k,i,j,aa;
Xiwen JIANG's avatar
Xiwen JIANG committed
573
  int re;
574

575
  int s,Kr,Kr_bytes;
576 577


578
  LTE_DL_FRAME_PARMS *frame_parms;
579 580 581 582 583 584
  double s_re0[30720*2],s_im0[30720*2],r_re0[30720*2],r_im0[30720*2];
  double s_re1[30720*2],s_im1[30720*2],r_re1[30720*2],r_im1[30720*2];
  double *s_re[2]={s_re0,s_re1};
  double *s_im[2]={s_im0,s_im1};
  double *r_re[2]={r_re0,r_re1};
  double *r_im[2]={r_im0,r_im1};
585

586

587
  uint8_t transmission_mode=1,n_tx_port=1,n_tx_phy=1,n_rx=2;
588

589
  int eNB_id = 0;
590
  unsigned char round;
591 592
  unsigned char i_mod = 2;
  unsigned short NB_RB;
593

594

595 596
  SCM_t channel_model=Rayleigh1;
  //  unsigned char *input_data,*decoded_output;
597

knopp's avatar
knopp committed
598 599
  DCI_ALLOC_t da;
  DCI_ALLOC_t *dci_alloc = &da;
600

601
  unsigned int coded_bits_per_codeword=0,nsymb; //,tbs=0;
602

knopp's avatar
knopp committed
603 604 605 606 607 608 609
  unsigned int tx_lev=0,tx_lev_dB=0,trials;
  unsigned int errs[4],errs2[4],round_trials[4],dci_errors[4];//,num_layers;
  memset(errs,0,4*sizeof(unsigned int));
  memset(errs2,0,4*sizeof(unsigned int));
  memset(round_trials,0,4*sizeof(unsigned int));
  memset(dci_errors,0,4*sizeof(unsigned int));

610
  //int re_allocated;
611 612 613 614 615 616 617
  char fname[32],vname[32];
  FILE *bler_fd;
  char bler_fname[256];
  FILE *time_meas_fd;
  char time_meas_fname[256];
  //  FILE *tikz_fd;
  //  char tikz_fname[256];
618

619 620 621 622
  FILE *input_trch_fd=NULL;
  unsigned char input_trch_file=0;
  FILE *input_fd=NULL;
  unsigned char input_file=0;
623

624
  channel_desc_t *eNB2UE[4];
625
  //uint8_t num_pdcch_symbols_2=0;
626 627
  //char stats_buffer[4096];
  //int len;
628

629
  //int u;
630
  int n=0;
631
  //int iii;
632

633
  int ch_realization;
634
  //int pmi_feedback=0;
635
  int hold_channel=0;
636

637 638 639
  // void *data;
  // int ii;
  //  int bler;
640
  double blerr[4];
641
  short *uncoded_ber_bit=NULL;
642
  int osf=1;
643 644 645
  frame_t frame_type = FDD;
  FD_lte_phy_scope_ue *form_ue = NULL;
  char title[255];
646

647
  int numCCE=0;
648
  //int dci_length_bytes=0,dci_length=0;
649 650
  //double channel_bandwidth = 5.0, sampling_rate=7.68;
  int common_flag=0,TPC=0;
651

652 653 654 655
  double cpu_freq_GHz;
  //  time_stats_t ts;//,sts,usts;
  int avg_iter,iter_trials;
  int rballocset=0;
656
  int test_passed=0;
657

658 659
  double effective_rate=0.0;
  char channel_model_input[10]="I";
660

661
  int TB0_active = 1;
662

663 664 665 666 667
  //  LTE_DL_UE_HARQ_t *dlsch0_ue_harq;
  //  LTE_DL_eNB_HARQ_t *dlsch0_eNB_harq;
  uint8_t Kmimo;
  uint8_t ue_category=4;
  uint32_t Nsoft;
668
  int sf;
669 670
  int CCE_table[800];
  opp_enabled=1; // to enable the time meas
671

672
  FILE *csv_fd=NULL;
673
  char csv_fname[FILENAME_MAX];
674
  int DLSCH_RB_ALLOC = 0;
675

676
  int dci_received;
knopp's avatar
knopp committed
677 678 679 680 681 682
  PHY_VARS_eNB *eNB;
  RU_t *ru;
  PHY_VARS_UE *UE;
  nfapi_dl_config_request_t DL_req;
  nfapi_ul_config_request_t UL_req;
  nfapi_hi_dci0_request_t HI_DCI0_req;
Cedric Roux's avatar
Cedric Roux committed
683
  nfapi_dl_config_request_pdu_t dl_config_pdu_list[MAX_NUM_DL_PDU];
knopp's avatar
knopp committed
684 685 686 687
  nfapi_tx_request_pdu_t tx_pdu_list[MAX_NUM_TX_REQUEST_PDU];
  nfapi_tx_request_t TX_req;
  Sched_Rsp_t sched_resp;
  int pa=dB0;
688

689 690 691
#if defined(__arm__)
  FILE    *proc_fd = NULL;
  char buf[64];
692

693 694 695 696 697 698
  proc_fd = fopen("/sys/devices/system/cpu/cpu4/cpufreq/cpuinfo_cur_freq", "r");
  if(!proc_fd)
     printf("cannot open /sys/devices/system/cpu/cpu4/cpufreq/cpuinfo_cur_freq");
  else {
     while(fgets(buf, 63, proc_fd))
        printf("%s", buf);
699
  }
700 701 702 703 704 705
  fclose(proc_fd);
  cpu_freq_GHz = ((double)atof(buf))/1e6;
#else
  cpu_freq_GHz = get_cpu_freq_GHz();
#endif
  printf("Detected cpu_freq %f GHz\n",cpu_freq_GHz);
knopp's avatar
knopp committed
706 707 708 709 710 711 712 713 714 715 716 717
  memset((void*)&sched_resp,0,sizeof(sched_resp));
  sched_resp.DL_req = &DL_req;
  sched_resp.UL_req = &UL_req;
  sched_resp.HI_DCI0_req = &HI_DCI0_req;
  sched_resp.TX_req = &TX_req;
  memset((void*)&DL_req,0,sizeof(DL_req));
  memset((void*)&UL_req,0,sizeof(UL_req));
  memset((void*)&HI_DCI0_req,0,sizeof(HI_DCI0_req));
  memset((void*)&TX_req,0,sizeof(TX_req));

  DL_req.dl_config_request_body.dl_config_pdu_list = dl_config_pdu_list;
  TX_req.tx_request_body.tx_pdu_list = tx_pdu_list;
718

719 720
  cpuf = cpu_freq_GHz;

721 722
  //signal(SIGSEGV, handler);
  //signal(SIGABRT, handler);
723

724 725 726 727 728
  // default parameters
  n_frames = 1000;
  snr0 = 0;
  //  num_layers = 1;
  perfect_ce = 0;
729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775
  static paramdef_t options[] = {
    { "awgn", "Use AWGN channel and not multipath", PARAMFLAG_BOOL, strptr:NULL, defintval:0, TYPE_INT, 0, NULL, NULL },
    { "Abstx", "Turns on calibration mode for abstraction.", PARAMFLAG_BOOL, iptr:&abstx,  defintval:0, TYPE_INT, 0 },
    { "bTDD", "Set the tdd configuration mode",0, iptr:&tdd_config,  defintval:3, TYPE_INT, 0 },
    { "BnbRBs", "The LTE bandwith in RBs (100 is 20MHz)",0, iptr:&N_RB_DL,  defintval:25, TYPE_INT, 0 },
    { "cPdcch", "Number of PDCCH symbols",0, iptr:&num_pdcch_symbols,  defintval:1, TYPE_INT, 0 },
    { "CnidCell", "The cell id ",0, iptr:&Nid_cell,  defintval:0, TYPE_INT, 0 },
    { "dciFlag", "Transmit the DCI and compute its error statistics", PARAMFLAG_BOOL, iptr:&dci_flag,  defintval:0, TYPE_INT, 0 },
    { "Dtdd", "Enable tdd", PARAMFLAG_BOOL,  strptr:NULL, defintval:0, TYPE_INT, 0, NULL, NULL },
    { "eRounds", "Number of rounds",0, iptr:NULL,  defintval:25, TYPE_INT, 0 },
    { "EsubSampling","three quarters sub-sampling",PARAMFLAG_BOOL, iptr:&threequarter_fs, defintval:0, TYPE_INT, 0 },
    { "f_snr_step", "step size of SNR, default value is 1.",0, dblptr:&input_snr_step,  defdblval:1, TYPE_DOUBLE, 0 },
    { "Forgetting", "forgetting factor (0 new channel every trial, 1 channel constant)",0, dblptr:&forgetting_factor,  defdblval:0.0, TYPE_DOUBLE, 0 },
    { "input_file", "input IQ data file",0, iptr:NULL,  defintval:0, TYPE_INT, 0 },
    { "Input_file_trch", " Input filename for TrCH data (binary)",0, iptr:NULL,  defintval:0, TYPE_INT, 0 },
    { "WtwoThreads", "two_thread_flag", PARAMFLAG_BOOL, iptr:&two_thread_flag,  defintval:0, TYPE_INT, 0 },
    { "lMuMimo", "offset_mumimo_llr_drange_fix",0, u8ptr:&offset_mumimo_llr_drange_fix,  defintval:0, TYPE_UINT8, 0 },
    { "mcs1", "The MCS for TB 1", 0, iptr:&mcs1,  defintval:0, TYPE_INT, 0 },
    { "Mcs2", "The MCS for TB 2", 0, iptr:&mcs2,  defintval:0, TYPE_INT, 0 },
    { "Operf", "Set the percenatge of effective rate to testbench the modem performance (typically 30 and 70, range 1-100)",0, iptr:&test_perf,  defintval:0, TYPE_INT, 0 },
    { "tmcs_i", "MCS of interfering UE",0, iptr:NULL,  defintval:0, TYPE_INT, 0 },
    { "nb_frame", "number of frame in a test",0, iptr:&n_frames,  defintval:1, TYPE_INT, 0 },
    { "offsetRxSample", "Sample offset for receiver", 0, iptr:&rx_sample_offset,  defintval:0, TYPE_INT, 0 },
    { "rballocset", "ressource block allocation (see  section 7.1.6.3 in 36.213)",0, iptr:NULL,  defintval:0, TYPE_INT, 0 },
    { "snr", "Starting SNR, runs from SNR to SNR+%.1fdB in steps of %.1fdB. If n_frames is 1 then just SNR is simulated and MATLAB/OCTAVE output is generated", dblptr:&snr0,  defdblval:-2.0, TYPE_DOUBLE, 0 },
    { "wsnrInterrupt", "snr int ?", 0, dblptr:&snr_int,  defdblval:30, TYPE_DOUBLE, 0 },
    { "N_ch_rlzN0", "Determines the number of Channel Realizations in Abstraction mode. Default value is 1",0, iptr:&n_ch_rlz,  defintval:1, TYPE_INT, 0 },
    { "prefix_extended","Enable extended prefix", PARAMFLAG_BOOL, iptr:&extended_prefix_flag,  defintval:0, TYPE_INT, 0 },
    { "RNumRound", "Number of HARQ rounds (fixed)",0, iptr:&num_rounds,  defintval:4, TYPE_INT, 0 },
    { "Subframe", "subframe ",0, iptr:&subframe,  defintval:7, TYPE_INT, 0 },
    { "Trnti", "rnti",0, u16ptr:&n_rnti,  defuintval:0x1234, TYPE_UINT16, 0 },
    { "vi_mod", "i_mod",0, iptr:NULL,  defintval:0, TYPE_INT, 0 },
    { "Performance", "Display CPU perfomance of each L1 piece", PARAMFLAG_BOOL,  iptr:&print_perf,  defintval:0, TYPE_INT, 0 },
    { "q_tx_port", "Number of TX antennas ports used in eNB",0, iptr:NULL,  defintval:0, TYPE_INT, 0 },
    { "uEdual", "Enables the Interference Aware Receiver for TM5 (default is normal receiver)",0, iptr:NULL,  defintval:0, TYPE_INT, 0 },
    { "xTransmission","Transmission mode (1,2,6,7 for the moment)",0, iptr:NULL,  defintval:25, TYPE_INT, 0 },
    { "yn_tx_phy","Number of TX antennas used in eNB",0, iptr:NULL,  defintval:25, TYPE_INT, 0 },
    { "XForms", "Display the soft scope", PARAMFLAG_BOOL, iptr:&xforms,  defintval:0, TYPE_INT, 0 },
    { "Yperfect_ce","Perfect CE", PARAMFLAG_BOOL, iptr:&perfect_ce,  defintval:0, TYPE_INT, 0 },
    { "Zdump", "dump table",PARAMFLAG_BOOL,  iptr:&dump_table, defintval:0, TYPE_INT, 0 },
    { "Loglvl", "log level",0, iptr:&loglvl,  defintval:OAILOG_DEBUG, TYPE_INT, 0 },
    { "zn_rx", "Number of RX antennas used in UE",0, iptr:NULL,  defintval:2, TYPE_INT, 0 },
    { "gchannel", "[A:M] Use 3GPP 25.814 SCM-A/B/C/D('A','B','C','D') or 36-101 EPA('E'), EVA ('F'),ETU('G') models (ignores delay spread and Ricean factor), Rayghleigh8 ('H'), Rayleigh1('I'), Rayleigh1_corr('J'), Rayleigh1_anticorr ('K'),  Rice8('L'), Rice1('M')",0, strptr:NULL,  defstrval:NULL, TYPE_STRING, 0 },
    { "verbose", "display debug text", PARAMFLAG_BOOL,  iptr:&verbose, defintval:0, TYPE_INT, 0 },
    { "help", "display help and exit", PARAMFLAG_BOOL,  iptr:&help, defintval:0, TYPE_INT, 0 },
    { "", "",0,  iptr:NULL, defintval:0, TYPE_INT, 0 },
  };
776

777 778 779
  
  struct option * long_options = parse_oai_options(options); 
  
780

781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809
  int option_index;

  int res;

  while ((res=getopt_long_only(argc, argv, "", long_options, &option_index)) == 0) {
    if (options[option_index].voidptr != NULL ) {
      if (long_options[option_index].has_arg==no_argument)
        *(bool *)options[option_index].iptr=1;
      else switch (options[option_index].type) {
          case TYPE_INT:
            *(int *)options[option_index].iptr=atoi(optarg);
            break;

          case TYPE_DOUBLE:
            *(double *)options[option_index].dblptr=atof(optarg);
            break;
	    
	case TYPE_UINT8:
	  *(uint8_t *)options[option_index].dblptr=atoi(optarg);
	  break;
	  	    
	case TYPE_UINT16:
	  *(uint16_t *)options[option_index].dblptr=atoi(optarg);
	  break;
	  
	default:
            printf("not decoded type.\n");
            exit(1);
        }
810

811 812
      continue;
    }
813

814 815 816 817
    switch (long_options[option_index].name[0]) {
    case 'a':
      awgn_flag = 1;
      channel_model = AWGN;
818
      break;
819

820 821 822
    case 'D':
      frame_type=TDD;
      break;
823

824 825 826 827 828
    case 'e':
      num_rounds=1;
      common_flag = 1;
      TPC = atoi(optarg);
      break;
829

830 831 832
    case 'i':
      input_fd = fopen(optarg,"r");
      input_file=1;
833
      dci_flag = 1;
834
      break;
835

836 837 838 839
    case 'I':
      input_trch_fd = fopen(optarg,"r");
      input_trch_file=1;
      break;
840

841 842 843 844
    case 't':
      mcs_i = atoi(optarg);
      i_mod = get_Qm(mcs_i);
      break;
845

846 847 848 849
    case 'r':
      DLSCH_RB_ALLOC = atoi(optarg);
      rballocset = 1;
      break;
850

851
    case 'g':
852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881
    strncpy(channel_model_input,optarg,9);
    struct tmp {
      char opt;
      int m;
      int M;
    }
    tmp[]= {
      {'A',SCM_A,2},
          {'B',SCM_B,3},
          {'C',SCM_C,4},
          {'D',SCM_D,5},
          {'E',EPA,6},
          {'F',EVA,6},
          {'G',ETU,8},
          {'H',Rayleigh8,9},
          {'I',Rayleigh1,10},
          {'J',Rayleigh1_corr,11},
          {'K',Rayleigh1_anticorr,12},
          {'L',Rice8,13},
          {'M',Rice1,14},
          {'N',AWGN,1},
          {0,0,0}
        };
        struct tmp *ptr;

        for (ptr=tmp; ptr->opt!=0; ptr++)
          if ( ptr->opt == optarg[0] ) {
            channel_model=ptr->m;
            break;
          }
882

883
        AssertFatal(ptr->opt != 0, "Unsupported channel model: %s !\n", optarg );
884
        break;
885

886 887 888
    case 'u':
      dual_stream_UE=1;
      UE->use_ia_receiver = 1;
889

Xiwen JIANG's avatar
Xiwen JIANG committed
890
      if ((n_tx_port!=2) || (transmission_mode!=5)) {
knopp's avatar
knopp committed
891
        printf("IA receiver only supported for TM5!");
892 893
        exit(-1);
      }
894

895
      break;
896

897 898
    case 'v':
      i_mod = atoi(optarg);
899

900
      if (i_mod!=2 && i_mod!=4 && i_mod!=6) {
knopp's avatar
knopp committed
901
        printf("Wrong i_mod %d, should be 2,4 or 6\n",i_mod);
902 903
        exit(-1);
      }
904

905
      break;
906

Xiwen JIANG's avatar
Xiwen JIANG committed
907 908 909 910
    case 'q':
      n_tx_port=atoi(optarg);

      if ((n_tx_port==0) || ((n_tx_port>2))) {
knopp's avatar
knopp committed
911
        printf("Unsupported number of cell specific antennas ports %d\n",n_tx_port);
Xiwen JIANG's avatar
Xiwen JIANG committed
912 913 914 915 916 917
        exit(-1);
      }

      break;


918 919
    case 'x':
      transmission_mode=atoi(optarg);
920

921 922 923 924 925
      if ((transmission_mode!=1) &&
          (transmission_mode!=2) &&
          (transmission_mode!=3) &&
          (transmission_mode!=4) &&
          (transmission_mode!=5) &&
Xiwen JIANG's avatar
Xiwen JIANG committed
926 927
          (transmission_mode!=6) &&
          (transmission_mode!=7)) {
knopp's avatar
knopp committed
928
        printf("Unsupported transmission mode %d\n",transmission_mode);
929 930
        exit(-1);
      }
931

Xiwen JIANG's avatar
Xiwen JIANG committed
932 933
      if (transmission_mode>1 && transmission_mode<7) {
        n_tx_port = 2;
934
      }
935

936
      break;
937

938
    case 'y':
Xiwen JIANG's avatar
Xiwen JIANG committed
939
      n_tx_phy=atoi(optarg);
940

Xiwen JIANG's avatar
Xiwen JIANG committed
941
      if (n_tx_phy < n_tx_port) {
knopp's avatar
knopp committed
942
        printf("n_tx_phy mush not be smaller than n_tx_port");
943 944
        exit(-1);
      }
945

Xiwen JIANG's avatar
Xiwen JIANG committed
946
      if ((transmission_mode>1 && transmission_mode<7) && n_tx_port<2) {
knopp's avatar
knopp committed
947
        printf("n_tx_port must be >1 for transmission_mode %d\n",transmission_mode);
Xiwen JIANG's avatar
Xiwen JIANG committed
948 949
        exit(-1);
      }
950

Xiwen JIANG's avatar
Xiwen JIANG committed
951
      if (transmission_mode==7 && (n_tx_phy!=1 && n_tx_phy!=2 && n_tx_phy!=4 && n_tx_phy!=8 && n_tx_phy!=16 && n_tx_phy!=64 && n_tx_phy!=128)) {
knopp's avatar
knopp committed
952
        printf("Physical number of antennas not supported for TM7.\n");
953 954
        exit(-1);
      }
955

956
      break;
957

958 959
    case 'z':
      n_rx=atoi(optarg);
960

961
      if ((n_rx==0) || (n_rx>2)) {
knopp's avatar
knopp committed
962
        printf("Unsupported number of rx antennas %d\n",n_rx);
963 964
        exit(-1);
      }
965

966
      break;
967

968
    default:
969
      printf("Wrong option: %s\n",long_options[option_index].name);
970 971 972 973
      exit(1);
      break;
    }
  }
974 975 976 977 978 979 980 981 982 983 984

  if ( res != -1 ) {
    printf("A wrong option has been found\n");
    exit(1);
  }

  if (help || verbose )
     display_options_values(options, true);
  if (help)
    exit(0);
  
985 986
  set_parallel_conf("PARALLEL_RU_L1_TRX_SPLIT");
  set_worker_conf("WORKER_ENABLE");
987

knopp's avatar
knopp committed
988 989 990 991 992
  if (transmission_mode>1) pa=dBm3;
  printf("dlsim: tmode %d, pa %d\n",transmission_mode,pa);

  AssertFatal(load_configmodule(argc,argv) != NULL,
	      "cannot load configuration module, exiting\n");
993
  logInit();
994
  set_glog_onlinelog(true);
995
  // enable these lines if you need debug info
996
  set_glog(loglvl);
997
  SET_LOG_DEBUG(UE_TIMING);
998 999 1000 1001 1002 1003
  // moreover you need to init itti with the following line
  // however itti will catch all signals, so ctrl-c won't work anymore
  // alternatively you can disable ITTI completely in CMakeLists.txt
  //itti_init(TASK_MAX, THREAD_MAX, MESSAGES_ID_MAX, tasks_info, messages_info, messages_definition_xml, NULL);


1004 1005 1006 1007 1008 1009
  if (common_flag == 0) {
    switch (N_RB_DL) {
    case 6:
      if (rballocset==0) DLSCH_RB_ALLOC = 0x3f;
      num_pdcch_symbols = 3;
      break;
1010

1011 1012 1013
    case 25:
      if (rballocset==0) DLSCH_RB_ALLOC = 0x1fff;
      break;
1014

1015 1016 1017
    case 50:
      if (rballocset==0) DLSCH_RB_ALLOC = 0x1ffff;
      break;
1018

1019 1020 1021 1022
    case 100:
      if (rballocset==0) DLSCH_RB_ALLOC = 0x1ffffff;
      break;
    }
1023

1024 1025 1026
    NB_RB=conv_nprb(0,DLSCH_RB_ALLOC,N_RB_DL);
  } else
    NB_RB = 4;
1027

1028 1029 1030 1031 1032
  if (xforms==1) {
    fl_initialize (&argc, argv, NULL, 0, 0);
    form_ue = create_lte_phy_scope_ue();
    sprintf (title, "LTE PHY SCOPE eNB");
    fl_show_form (form_ue->lte_phy_scope_ue, FL_PLACE_HOTSPOT, FL_FULLBORDER, title);
1033

1034 1035 1036 1037 1038 1039 1040
    if (!dual_stream_UE==0) {
      UE->use_ia_receiver = 1;
      fl_set_button(form_ue->button_0,1);
      fl_set_object_label(form_ue->button_0, "IA Receiver ON");
      fl_set_object_color(form_ue->button_0, FL_GREEN, FL_GREEN);
    }
  }
1041

1042 1043 1044 1045
  if (transmission_mode==5) {
    n_users = 2;
    printf("dual_stream_UE=%d\n", dual_stream_UE);
  }
knopp's avatar
knopp committed
1046 1047
  RC.nb_L1_inst = 1;
  RC.nb_RU = 1;
1048

knopp's avatar
knopp committed
1049 1050
  lte_param_init(&eNB,&UE,&ru,
		 n_tx_port,
Xiwen JIANG's avatar
Xiwen JIANG committed
1051
		 n_tx_phy,
1052 1053
		 1,
                 n_rx,
1054 1055 1056 1057 1058 1059
		 transmission_mode,
		 extended_prefix_flag,
		 frame_type,
		 Nid_cell,
		 tdd_config,
		 N_RB_DL,
knopp's avatar
knopp committed
1060
		 pa,
1061 1062 1063
		 threequarter_fs,
		 osf,
		 perfect_ce);
knopp's avatar
knopp committed
1064 1065 1066 1067 1068 1069
  RC.eNB = (PHY_VARS_eNB ***)malloc(sizeof(PHY_VARS_eNB **));
  RC.eNB[0] = (PHY_VARS_eNB **)malloc(sizeof(PHY_VARS_eNB *));
  RC.ru = (RU_t **)malloc(sizeof(RC.ru));
  RC.eNB[0][0] = eNB;
  RC.ru[0] = ru;
  printf("lte_param_init done\n");
1070
  if ((transmission_mode==1) || (transmission_mode==7)) {
knopp's avatar
knopp committed
1071 1072 1073
    for (aa=0; aa<ru->nb_tx; aa++)
     for (re=0; re<ru->frame_parms.ofdm_symbol_size; re++)
       ru->beam_weights[0][0][aa][re] = 0x00007fff/eNB->frame_parms.nb_antennas_tx;
1074 1075
  }

1076
  if (transmission_mode<7)
knopp's avatar
knopp committed
1077
     ru->do_precoding=0;
1078
  else
knopp's avatar
knopp committed
1079
     ru->do_precoding=1;
1080

1081
  eNB->mac_enabled=1;
1082 1083 1084 1085 1086
  if (two_thread_flag == 0) {
    eNB->te = dlsch_encoding;
  }
  else {
    eNB->te = dlsch_encoding_2threads;
1087 1088 1089 1090
    extern void init_td_thread(PHY_VARS_eNB *);
    extern void init_te_thread(PHY_VARS_eNB *);
    init_td_thread(eNB);
    init_te_thread(eNB);
1091 1092
  }

1093 1094
  // callback functions required for phy_procedures_tx

1095
  //  eNB_id_i = UE->n_connected_eNB;
1096

1097 1098 1099 1100
  printf("Setting mcs1 = %d\n",mcs1);
  printf("Setting mcs2 = %d\n",mcs2);
  printf("NPRB = %d\n",NB_RB);
  printf("n_frames = %d\n",n_frames);
Xiwen JIANG's avatar
Xiwen JIANG committed
1101
  printf("Transmission mode %d with %dx%d antenna configuration, Extended Prefix %d\n",transmission_mode,n_tx_phy,n_rx,extended_prefix_flag);
1102

1103 1104
  snr1 = snr0+snr_int;
  printf("SNR0 %f, SNR1 %f\n",snr0,snr1);
1105

knopp's avatar
knopp committed
1106
  uint8_t input_buffer[NUMBER_OF_UE_MAX][20000];
1107

Cedric Roux's avatar
Cedric Roux committed
1108
  for (i=0;i<n_users;i++)