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

/*! \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 39 40 41 42 43 44 45 46 47 48 49
#include <string.h>
#include <math.h>
#include <unistd.h>
#include <execinfo.h>
#include <signal.h>

#include "SIMULATION/TOOLS/defs.h"
#include "PHY/types.h"
#include "PHY/defs.h"
#include "PHY/vars.h"

#include "SCHED/defs.h"
#include "SCHED/vars.h"
#include "LAYER2/MAC/vars.h"

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

52 53
#include "unitary_defs.h"

54 55 56

#include "PHY/TOOLS/lte_phy_scope.h"

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


60

61 62
double cpuf;

63
int otg_enabled=0;
64 65 66 67 68 69 70
/*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 */
71

72 73
void handler(int sig)
{
74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93
  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;
94
#define CCCH_RB_ALLOC computeRIV(eNB->frame_parms.N_RB_UL,0,2)
95 96
//#define DLSCH_RB_ALLOC 0x1fbf // igore DC component,RB13
//#define DLSCH_RB_ALLOC 0x0001
97
void do_OFDM_mod_l(int32_t **txdataF, int32_t **txdata, uint16_t next_slot, LTE_DL_FRAME_PARMS *frame_parms)
98
{
99 100 101 102 103 104 105 106 107 108 109

  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
110
                   &txdata[aa][slot_offset],         // output
111
                   frame_parms->ofdm_symbol_size,
112 113 114
                   6,                 // number of symbols
                   frame_parms->nb_prefix_samples,               // number of prefix samples
                   CYCLIC_PREFIX);
115 116
    else {
      normal_prefix_mod(&txdataF[aa][slot_offset_F],
117 118 119
                        &txdata[aa][slot_offset],
                        7,
                        frame_parms);
120
    }
121

122 123

  }
124

125 126
}

knopp's avatar
knopp committed
127
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],
128
		double *s_re[2],double *s_im[2],double *r_re[2],double *r_im[2],FILE *csv_fd) {
129

130 131 132 133
  int i,u;
  int aa,aarx,aatx;
  double channelx,channely;
  double sigma2_dB,sigma2;
134 135
  double iqim=0.0;

136 137
  //    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
138
    for (aa=0; aa<ru->frame_parms.nb_antennas_tx; aa++) {
139
      if (awgn_flag == 0) {
knopp's avatar
knopp committed
140 141
	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]);
142 143 144
      } else {
	for (aarx=0; aarx<UE->frame_parms.nb_antennas_rx; aarx++) {
	  if (aa==0) {
knopp's avatar
knopp committed
145 146
	    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]);
147
	  } else {
knopp's avatar
knopp committed
148 149
	    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]);
150
	  }
151

152 153 154 155
	}
      }
    }
  }
156

157 158 159 160
  // 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);
161

162 163 164 165 166 167 168
    //      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);
      }
169

170 171 172 173 174 175 176 177 178
    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);
      /*
	write_output("channel.m","ch",eNB2UE[round]->ch[0],eNB2UE[round]->channel_length,1,8);
	write_output("channelF.m","chF",eNB2UE[round]->chF[0],12*UE->frame_parms.N_RB_DL + 1,1,8);
      */
    }
  }
179 180


181 182 183
  if(abstx) {
    if (trials==0 && round==0) {
      // calculate freq domain representation to compute SINR
knopp's avatar
knopp committed
184
      freq_channel(eNB2UE[0], ru->frame_parms.N_RB_DL,2*ru->frame_parms.N_RB_DL + 1);
185 186
      // snr=pow(10.0,.1*SNR);
      fprintf(csv_fd,"%f,",SNR);
187

knopp's avatar
knopp committed
188
      for (u=0; u<2*ru->frame_parms.N_RB_DL; u++) {
189 190 191 192 193 194 195
	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);
	  }
	}
196 197
      }

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

knopp's avatar
knopp committed
201
	for (u=0; u<2*ru->frame_parms.N_RB_DL; u++) {
202 203 204 205 206 207 208 209
	  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);
	    }
	  }
	}
210

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

knopp's avatar
knopp committed
213
	for (u=0; u<2*ru->frame_parms.N_RB_DL; u++) {
214 215 216 217 218 219 220 221
	  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);
	    }
	  }
	}
222

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

knopp's avatar
knopp committed
225
	for (u=0; u<2*ru->frame_parms.N_RB_DL; u++) {
226 227 228 229 230 231 232 233 234 235 236
	  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);
	    }
	  }
	}
      }
    }
  }
237

238
  //AWGN
239 240
  // 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
241
  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;
242 243 244
  sigma2 = pow(10,sigma2_dB/10);

  for (i=0; i<2*UE->frame_parms.samples_per_tti; i++) {
245
    for (aa=0; aa<UE->frame_parms.nb_antennas_rx; aa++) {
246 247 248 249 250 251 252 253
      //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));
    }
  }
}
254

knopp's avatar
knopp committed
255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 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
uint16_t
fill_tx_req(nfapi_tx_request_body_t *tx_req_body,
	    uint16_t                absSF, 
	    uint16_t                pdu_length,
	    uint16_t                pdu_index, 
	    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++;
}
334

335
void fill_DCI(PHY_VARS_eNB *eNB,
knopp's avatar
knopp committed
336
	      int frame,
337
	      int subframe,
knopp's avatar
knopp committed
338 339
	      Sched_Rsp_t *sched_resp,
	      uint8_t input_buffer[NUMBER_OF_UE_MAX][20000],
340 341 342
	      int n_rnti,
	      int n_users,
	      int transmission_mode,
knopp's avatar
knopp committed
343
	      int retrans,
344
	      int common_flag,
knopp's avatar
knopp committed
345
	      int NB_RB,
346 347 348 349 350 351
	      int DLSCH_RB_ALLOC,
	      int TPC,
	      int mcs1,
	      int mcs2,
	      int ndi,
	      int rv,
knopp's avatar
knopp committed
352
	      int pa,
353 354 355 356 357 358
	      int *num_common_dci,
	      int *num_ue_spec_dci,
	      int *num_dci) {

  int k;

knopp's avatar
knopp committed
359 360 361 362 363 364 365 366
  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;

367 368 369
  for(k=0; k<n_users; k++) {
    switch(transmission_mode) {
    case 1:
370

371
    case 2:
Xiwen JIANG's avatar
Xiwen JIANG committed
372 373

    case 7:
374
      if (common_flag == 0) {
375

knopp's avatar
knopp committed
376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436
	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
	
	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;


	fill_dlsch_config(dl_req, 
			  get_TBS_DL(mcs1,NB_RB), 
			  (retrans > 0) ? -1 : 0, /* retransmission, no pdu_index */
			  n_rnti, 
			  0,	// type 0 allocation from 7.1.6 in 36.213
			  0,	// virtual_resource_block_assignment_flag, unused here
			  DLSCH_RB_ALLOC,	// resource_block_coding, 
			  get_Qm(mcs1), 
			  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
			  pa,    // pa 
			  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,
		    get_TBS_DL(mcs1,NB_RB), 
		    0,
		    input_buffer[k]);
      }
      else {
437

knopp's avatar
knopp committed
438
      }
439

knopp's avatar
knopp committed
440
      break;
441

knopp's avatar
knopp committed
442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463
    case 3:
      if (common_flag == 0) {
	
	if (eNB->frame_parms.nb_antennas_tx == 2) {
	  
	  if (eNB->frame_parms.frame_type == TDD) {
	    
	  }
	  else {
	    
	  }
	}
      }
      break;
      
    case 4:
      if (common_flag == 0) {
	
	if (eNB->frame_parms.nb_antennas_tx == 2) {
	  
	  if (eNB->frame_parms.frame_type == TDD) {
	    
464

knopp's avatar
knopp committed
465
	  }
466

knopp's avatar
knopp committed
467
	  else {
468

knopp's avatar
knopp committed
469 470
	  }
	} else if (eNB->frame_parms.nb_antennas_tx == 4) {
471

knopp's avatar
knopp committed
472
	}
473

knopp's avatar
knopp committed
474 475
      }
      else {
476

477
        }
478

479
        break;
480

481 482
      case 5:
      case 6:
483

484
        break;
485

knopp's avatar
knopp committed
486 487 488 489
    default:
      printf("Unsupported Transmission Mode %d!!!\n",transmission_mode);
      exit(-1);
      break;
490
    }
knopp's avatar
knopp committed
491 492 493 494
  }
  *num_dci         = dl_req->number_dci;
  *num_ue_spec_dci = dl_req->number_dci;
  *num_common_dci  = 0;
495
}
496

497 498 499 500
int n_users = 1;
sub_frame_t subframe=7;
int num_common_dci=0,num_ue_spec_dci=0,num_dci=0,num_pdcch_symbols=1;
uint16_t n_rnti=0x1234;
knopp's avatar
knopp committed
501
  int nfapi_mode=0;
502

503 504
int main(int argc, char **argv)
{
505

506
  int c;
knopp's avatar
knopp committed
507
  int k,i,j,aa;
Xiwen JIANG's avatar
Xiwen JIANG committed
508
  int re;
509

510
  int s,Kr,Kr_bytes;
511

512
  double SNR,snr0=-2.0,snr1,rate = 0;
513
  double snr_step=1,input_snr_step=1, snr_int=30;
514

515
  LTE_DL_FRAME_PARMS *frame_parms;
516 517 518 519 520 521
  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};
522
  double forgetting_factor=0.0; //in [0,1] 0 means a new channel every time, 1 means keep the same channel
523

524

Xiwen JIANG's avatar
Xiwen JIANG committed
525
  uint8_t extended_prefix_flag=0,transmission_mode=1,n_tx_port=1,n_tx_phy=1,n_rx=2;
526
  uint16_t Nid_cell=0;
527

528 529 530 531 532
  int eNB_id = 0;
  unsigned char mcs1=0,mcs2=0,mcs_i=0,dual_stream_UE = 0,awgn_flag=0,round;
  unsigned char i_mod = 2;
  unsigned short NB_RB;
  uint16_t tdd_config=3;
533

534

535 536
  SCM_t channel_model=Rayleigh1;
  //  unsigned char *input_data,*decoded_output;
537

knopp's avatar
knopp committed
538 539
  DCI_ALLOC_t da;
  DCI_ALLOC_t *dci_alloc = &da;
540

541
  unsigned int ret;
542
  unsigned int coded_bits_per_codeword=0,nsymb; //,tbs=0;
543

knopp's avatar
knopp committed
544 545 546 547 548 549 550
  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));

551
  //int re_allocated;
552 553 554 555 556 557 558
  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];
559

560 561 562 563 564
  FILE *input_trch_fd=NULL;
  unsigned char input_trch_file=0;
  FILE *input_fd=NULL;
  unsigned char input_file=0;
  //  char input_val_str[50],input_val_str2[50];
565

566
  char input_trch_val[16];
knopp's avatar
knopp committed
567
  
568
  //  unsigned char pbch_pdu[6];
569 570


571 572


573
  //  FILE *rx_frame_file;
574

575 576 577
  int n_frames;
  int n_ch_rlz = 1;
  channel_desc_t *eNB2UE[4];
578
  //uint8_t num_pdcch_symbols_2=0;
579 580 581 582
  uint8_t rx_sample_offset = 0;
  //char stats_buffer[4096];
  //int len;
  uint8_t num_rounds = 4;//,fix_rounds=0;
583

584
  //int u;
585 586
  int n=0;
  int abstx=0;
587
  //int iii;
588

589
  int ch_realization;
590
  //int pmi_feedback=0;
591
  int hold_channel=0;
592

593 594 595
  // void *data;
  // int ii;
  //  int bler;
Cedric Roux's avatar
Cedric Roux committed
596
  double blerr[4],uncoded_ber=0; //,avg_ber;
597 598 599 600 601 602
  short *uncoded_ber_bit=NULL;
  uint8_t N_RB_DL=25,osf=1;
  frame_t frame_type = FDD;
  int xforms=0;
  FD_lte_phy_scope_ue *form_ue = NULL;
  char title[255];
603

604
  int numCCE=0;
605
  //int dci_length_bytes=0,dci_length=0;
606 607
  //double channel_bandwidth = 5.0, sampling_rate=7.68;
  int common_flag=0,TPC=0;
608

609 610 611 612 613 614
  double cpu_freq_GHz;
  //  time_stats_t ts;//,sts,usts;
  int avg_iter,iter_trials;
  int rballocset=0;
  int print_perf=0;
  int test_perf=0;
615
  int test_passed=0;
616
  int dump_table=0;
617

618 619
  double effective_rate=0.0;
  char channel_model_input[10]="I";
620

621 622
  int TB0_active = 1;
  uint32_t perfect_ce = 0;
623

624 625 626 627 628
  //  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;
629
  int sf;
630

631 632


633
  int CCE_table[800];
634

635
  int threequarter_fs=0;
636

knopp's avatar
knopp committed
637

638
  opp_enabled=1; // to enable the time meas
639

640 641
  FILE *csv_fd=NULL;
  char csv_fname[32];
642
  int dci_flag=0;
643
  int two_thread_flag=0;
644
  int DLSCH_RB_ALLOC = 0;
645

646
  int log_level = LOG_ERR;
647
  int dci_received;
knopp's avatar
knopp committed
648 649 650 651 652 653 654 655 656 657 658
  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;
  nfapi_dl_config_request_pdu_t dl_config_pdu_list[MAX_NUM_DL_PDU]; 
  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;
659

660 661 662
#if defined(__arm__)
  FILE    *proc_fd = NULL;
  char buf[64];
663

664 665 666 667 668 669
  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);
670
  }
671 672 673 674 675 676
  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
677 678 679 680 681 682 683 684 685 686 687 688
  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;
689

690 691
  cpuf = cpu_freq_GHz;

692 693
  //signal(SIGSEGV, handler);
  //signal(SIGABRT, handler);
694

695 696 697 698 699
  // default parameters
  n_frames = 1000;
  snr0 = 0;
  //  num_layers = 1;
  perfect_ce = 0;
700

701
  while ((c = getopt (argc, argv, "ahdpZDe:Em:n:o:s:f:t:c:g:r:F:x:q:y:z:AM:N:I:i:O:R:S:C:T:b:u:v:w:B:Pl:WXYL:")) != -1) {
702 703 704 705 706
    switch (c) {
    case 'a':
      awgn_flag = 1;
      channel_model = AWGN;
      break;
707

708 709 710
    case 'A':
      abstx = 1;
      break;
711

712 713 714
    case 'b':
      tdd_config=atoi(optarg);
      break;
715

716 717 718
    case 'B':
      N_RB_DL=atoi(optarg);
      break;
719

720 721 722
    case 'c':
      num_pdcch_symbols=atoi(optarg);
      break;
723

724 725 726
    case 'C':
      Nid_cell = atoi(optarg);
      break;
727

728 729 730
    case 'd':
      dci_flag = 1;
      break;
731

732 733 734
    case 'D':
      frame_type=TDD;
      break;
735

736 737 738 739 740
    case 'e':
      num_rounds=1;
      common_flag = 1;
      TPC = atoi(optarg);
      break;
741

742 743 744
    case 'E':
      threequarter_fs=1;
      break;
745

746 747 748
    case 'f':
      input_snr_step= atof(optarg);
      break;
749

750 751 752
    case 'F':
      forgetting_factor = atof(optarg);
      break;
753

754 755 756
    case 'i':
      input_fd = fopen(optarg,"r");
      input_file=1;
757
      dci_flag = 1;
758
      break;
759

760 761 762 763
    case 'I':
      input_trch_fd = fopen(optarg,"r");
      input_trch_file=1;
      break;
764

765 766 767
    case 'W':
      two_thread_flag = 1;
      break;
768 769 770
    case 'l':
      offset_mumimo_llr_drange_fix=atoi(optarg);
      break;
771

772 773 774
    case 'm':
      mcs1 = atoi(optarg);
      break;
775

776 777 778
    case 'M':
      mcs2 = atoi(optarg);
      break;
779

780 781 782 783
    case 'O':
      test_perf=atoi(optarg);
      //print_perf =1;
      break;
784

785 786 787 788
    case 't':
      mcs_i = atoi(optarg);
      i_mod = get_Qm(mcs_i);
      break;
789

790 791 792
    case 'n':
      n_frames = atoi(optarg);
      break;
793 794


795 796 797
    case 'o':
      rx_sample_offset = atoi(optarg);
      break;
798

799 800 801 802
    case 'r':
      DLSCH_RB_ALLOC = atoi(optarg);
      rballocset = 1;
      break;
803

804 805 806
    case 's':
      snr0 = atof(optarg);
      break;
807

808 809 810
    case 'w':
      snr_int = atof(optarg);
      break;
811 812


813 814 815
    case 'N':
      n_ch_rlz= atof(optarg);
      break;
816

817 818 819
    case 'p':
      extended_prefix_flag=1;
      break;
820

821 822
    case 'g':
      memcpy(channel_model_input,optarg,10);
823

824 825 826
      switch((char)*optarg) {
      case 'A':
        channel_model=SCM_A;
827 828
        break;

829 830 831
      case 'B':
        channel_model=SCM_B;
        break;
832

833 834 835
      case 'C':
        channel_model=SCM_C;
        break;
836

837 838 839
      case 'D':
        channel_model=SCM_D;
        break;
840

841 842 843
      case 'E':
        channel_model=EPA;
        break;
844

845 846 847
      case 'F':
        channel_model=EVA;
        break;
848

849 850 851
      case 'G':
        channel_model=ETU;
        break;
852

853 854 855
      case 'H':
        channel_model=Rayleigh8;
        break;
856

857 858 859
      case 'I':
        channel_model=Rayleigh1;
        break;
860

861 862 863
      case 'J':
        channel_model=Rayleigh1_corr;
        break;
864

865 866 867
      case 'K':
        channel_model=Rayleigh1_anticorr;
        break;
868

869 870 871
      case 'L':
        channel_model=Rice8;
        break;
872

873 874 875
      case 'M':
        channel_model=Rice1;
        break;
876

877 878 879 880
      case 'N':
        channel_model=AWGN;
        break;
      default:
knopp's avatar
knopp committed
881
        printf("Unsupported channel model!\n");
882 883
        exit(-1);
      }
884

885 886 887 888
      break;
    case 'R':
      num_rounds=atoi(optarg);
      break;
889

890 891 892
    case 'S':
      subframe=atoi(optarg);
      break;
893

894 895 896
    case 'T':
      n_rnti=atoi(optarg);
      break;
897

898 899 900
    case 'u':
      dual_stream_UE=1;
      UE->use_ia_receiver = 1;
901

Xiwen JIANG's avatar
Xiwen JIANG committed
902
      if ((n_tx_port!=2) || (transmission_mode!=5)) {
knopp's avatar
knopp committed
903
        printf("IA receiver only supported for TM5!");
904 905
        exit(-1);
      }
906

907
      break;
908

909 910
    case 'v':
      i_mod = atoi(optarg);
911

912
      if (i_mod!=2 && i_mod!=4 && i_mod!=6) {
knopp's avatar
knopp committed
913
        printf("Wrong i_mod %d, should be 2,4 or 6\n",i_mod);
914 915
        exit(-1);
      }
916

917
      break;
918

919 920 921
    case 'P':
      print_perf=1;
      break;
922

Xiwen JIANG's avatar
Xiwen JIANG committed
923 924 925 926
    case 'q':
      n_tx_port=atoi(optarg);

      if ((n_tx_port==0) || ((n_tx_port>2))) {
knopp's avatar
knopp committed
927
        printf("Unsupported number of cell specific antennas ports %d\n",n_tx_port);
Xiwen JIANG's avatar
Xiwen JIANG committed
928 929 930 931 932 933
        exit(-1);
      }

      break;


934 935
    case 'x':
      transmission_mode=atoi(optarg);
936

937 938 939 940 941
      if ((transmission_mode!=1) &&
          (transmission_mode!=2) &&
          (transmission_mode!=3) &&
          (transmission_mode!=4) &&
          (transmission_mode!=5) &&
Xiwen JIANG's avatar
Xiwen JIANG committed
942 943
          (transmission_mode!=6) &&
          (transmission_mode!=7)) {
knopp's avatar
knopp committed
944
        printf("Unsupported transmission mode %d\n",transmission_mode);
945 946
        exit(-1);
      }
947

Xiwen JIANG's avatar
Xiwen JIANG committed
948 949
      if (transmission_mode>1 && transmission_mode<7) {
        n_tx_port = 2;
950
      }
951

952
      break;
953

954
    case 'y':
Xiwen JIANG's avatar
Xiwen JIANG committed
955
      n_tx_phy=atoi(optarg);
956

Xiwen JIANG's avatar
Xiwen JIANG committed
957
      if (n_tx_phy < n_tx_port) {
knopp's avatar
knopp committed
958
        printf("n_tx_phy mush not be smaller than n_tx_port");
959 960
        exit(-1);
      }
961

Xiwen JIANG's avatar
Xiwen JIANG committed
962
      if ((transmission_mode>1 && transmission_mode<7) && n_tx_port<2) {
knopp's avatar
knopp committed
963
        printf("n_tx_port must be >1 for transmission_mode %d\n",transmission_mode);
Xiwen JIANG's avatar
Xiwen JIANG committed
964 965
        exit(-1);
      }
966

Xiwen JIANG's avatar
Xiwen JIANG committed
967
      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
968
        printf("Physical number of antennas not supported for TM7.\n");
969 970
        exit(-1);
      }
971