dlsim.c 44.3 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
/*
 * 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.1  (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
 */

#include <fcntl.h>
23 24
#include <math.h>
#include <string.h>
25 26
#include <sys/ioctl.h>
#include <sys/mman.h>
27 28
#include <unistd.h>
#include "common/ran_context.h"
29 30
#include "common/config/config_userapi.h"
#include "common/utils/LOG/log.h"
31 32 33
#include "LAYER2/NR_MAC_gNB/nr_mac_gNB.h"
#include "LAYER2/NR_MAC_UE/mac_defs.h"
#include "LAYER2/NR_MAC_UE/mac_extern.h"
34
#include "PHY/defs_gNB.h"
35 36
#include "PHY/defs_nr_common.h"
#include "PHY/defs_nr_UE.h"
37
#include "PHY/phy_vars_nr_ue.h"
38 39
#include "PHY/types.h"
#include "PHY/INIT/phy_init.h"
40
#include "PHY/MODULATION/modulation_eNB.h"
41
#include "PHY/MODULATION/nr_modulation.h"
42
#include "PHY/MODULATION/modulation_UE.h"
43
#include "PHY/NR_REFSIG/refsig_defs_ue.h"
44
#include "PHY/NR_TRANSPORT/nr_dlsch.h"
cig's avatar
cig committed
45
#include "PHY/NR_TRANSPORT/nr_transport_proto.h"
46
#include "PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h"
47
#include "SCHED_NR/fapi_nr_l1.h"
48
#include "SCHED_NR/sched_nr.h"
49
#include "SCHED_NR_UE/defs.h"
50 51 52 53
#include "SCHED_NR_UE/fapi_nr_ue_l1.h"
#include "NR_PHY_INTERFACE/NR_IF_Module.h"
#include "NR_UE_PHY_INTERFACE/NR_IF_Module.h"

54
#include "LAYER2/NR_MAC_UE/mac_proto.h"
yilmazt's avatar
yilmazt committed
55 56
//#include "LAYER2/NR_MAC_gNB/mac_proto.h"
//#include "openair2/LAYER2/NR_MAC_UE/mac_proto.h"
57
#include "LAYER2/NR_MAC_gNB/mac_proto.h"
58
#include "NR_asn_constant.h"
59
#include "RRC/NR/MESSAGES/asn1_msg.h"
60 61 62
#include "openair1/SIMULATION/RF/rf.h"
#include "openair1/SIMULATION/TOOLS/sim.h"
#include "openair1/SIMULATION/NR_PHY/nr_unitary_defs.h"
Raymond Knopp's avatar
Raymond Knopp committed
63
//#include "openair1/SIMULATION/NR_PHY/nr_dummy_functions.c"
64
#include "PHY/NR_REFSIG/ptrs_nr.h"
Raymond Knopp's avatar
Raymond Knopp committed
65
#include "NR_RRCReconfiguration.h"
66 67 68
#define inMicroS(a) (((double)(a))/(cpu_freq_GHz*1000.0))
#include "SIMULATION/LTE_PHY/common_sim.h"

Laurent's avatar
Laurent committed
69 70
#include <openair2/LAYER2/MAC/mac_vars.h>
#include <openair2/RRC/LTE/rrc_vars.h>
71

72 73
LCHAN_DESC DCCH_LCHAN_DESC,DTCH_DL_LCHAN_DESC,DTCH_UL_LCHAN_DESC;
rlc_info_t Rlc_info_um,Rlc_info_am_config;
Raymond Knopp's avatar
Raymond Knopp committed
74

75 76 77
PHY_VARS_gNB *gNB;
PHY_VARS_NR_UE *UE;
RAN_CONTEXT_t RC;
78 79
int32_t uplink_frequency_offset[MAX_NUM_CCs][4];

80
double cpuf;
81

82
int sf_ahead=4 ;
83
int sl_ahead=0;
84
uint8_t nfapi_mode = 0;
85
uint64_t downlink_frequency[MAX_NUM_CCs][4];
86 87

// dummy functions
Raymond Knopp's avatar
Raymond Knopp committed
88 89
int dummy_nr_ue_ul_indication(nr_uplink_indication_t *ul_info)              { return(0);  }

90 91 92 93 94 95
int8_t nr_mac_rrc_data_ind_ue(const module_id_t     module_id,
			      const int             CC_id,
			      const uint8_t         gNB_index,
			      const int8_t          channel,
			      const uint8_t*        pduP,
			      const sdu_size_t      pdu_len)
96 97 98 99
{
  return 0;
}

100 101
void
rrc_data_ind(
102
  const protocol_ctxt_t *const ctxt_pP,
103 104 105 106 107 108 109 110 111 112 113 114 115 116 117
  const rb_id_t                Srb_id,
  const sdu_size_t             sdu_sizeP,
  const uint8_t   *const       buffer_pP
)
{
}

int
gtpv1u_create_s1u_tunnel(
  const instance_t                              instanceP,
  const gtpv1u_enb_create_tunnel_req_t *const  create_tunnel_req_pP,
  gtpv1u_enb_create_tunnel_resp_t *const create_tunnel_resp_pP
) {
  return 0;
}
118

119 120 121 122 123 124 125 126
int
rrc_gNB_process_GTPV1U_CREATE_TUNNEL_RESP(
  const protocol_ctxt_t *const ctxt_pP,
  const gtpv1u_enb_create_tunnel_resp_t *const create_tunnel_resp_pP,
  uint8_t                         *inde_list
) {
  return 0;
}
127

128 129
void config_common(int Mod_idP,
                   int pdsch_AntennaPorts, 
130
		   NR_ServingCellConfigCommon_t *scc
Raymond Knopp's avatar
Raymond Knopp committed
131
		   );
132

133 134 135 136 137 138 139 140 141
int generate_dlsch_header(unsigned char *mac_header,
                          unsigned char num_sdus,
                          unsigned short *sdu_lengths,
                          unsigned char *sdu_lcids,
                          unsigned char drx_cmd,
                          unsigned short timing_advance_cmd,
                          unsigned char *ue_cont_res_id,
                          unsigned char short_padding,
                          unsigned short post_padding){return 0;}
142

143
// Dummy function to avoid linking error at compilation of nr-dlsim
144 145 146 147 148
int is_x2ap_enabled(void)
{
  return 0;
}

rmagueta's avatar
rmagueta committed
149 150 151 152
int8_t nr_rrc_ue_decode_NR_SIB1_Message(module_id_t module_id, uint8_t gNB_index, uint8_t *const bufferP, const uint8_t buffer_len) {
  return 0;
}

153
// needed for some functions
154
openair0_config_t openair0_cfg[MAX_CARDS];
155 156
void update_ptrs_config(NR_CellGroupConfig_t *secondaryCellGroup, uint16_t *rbSize, uint8_t *mcsIndex,int8_t *ptrs_arg);
void update_dmrs_config(NR_CellGroupConfig_t *scg,PHY_VARS_NR_UE *ue, int8_t* dmrs_arg);
157

158 159
/* specific dlsim DL preprocessor: uses rbStart/rbSize/mcs from command line of
   dlsim, does not search for CCE/PUCCH occasion but simply sets to 0 */
160
int g_mcsIndex = -1, g_mcsTableIdx = 0, g_rbStart = -1, g_rbSize = -1;
161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187
void nr_dlsim_preprocessor(module_id_t module_id,
                           frame_t frame,
                           sub_frame_t slot,
                           int num_slots_per_tdd) {
  NR_UE_info_t *UE_info = &RC.nrmac[module_id]->UE_info;
  AssertFatal(UE_info->num_UEs == 1, "can have only a single UE\n");
  NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl[0];

  /* manually set free CCE to 0 */
  const int target_ss = NR_SearchSpace__searchSpaceType_PR_ue_Specific;
  sched_ctrl->search_space = get_searchspace(sched_ctrl->active_bwp, target_ss);
  uint8_t nr_of_candidates;
  find_aggregation_candidates(&sched_ctrl->aggregation_level,
                              &nr_of_candidates,
                              sched_ctrl->search_space);
  sched_ctrl->coreset = get_coreset(
      sched_ctrl->active_bwp, sched_ctrl->search_space, 1 /* dedicated */);
  sched_ctrl->cce_index = 0;

  /* set "any" value for PUCCH (simulator evaluates PDSCH only) */
  sched_ctrl->pucch_sched_idx = 0;
  sched_ctrl->pucch_occ_idx = 0;

  sched_ctrl->rbStart = g_rbStart;
  sched_ctrl->rbSize = g_rbSize;
  sched_ctrl->mcs = g_mcsIndex;
  sched_ctrl->time_domain_allocation = 2;
188
  sched_ctrl->mcsTableIdx = g_mcsTableIdx;
189 190 191
  AssertFatal(sched_ctrl->rbStart >= 0, "invalid rbStart %d\n", sched_ctrl->rbStart);
  AssertFatal(sched_ctrl->rbSize > 0, "invalid rbSize %d\n", sched_ctrl->rbSize);
  AssertFatal(sched_ctrl->mcs >= 0, "invalid sched_ctrl->mcs %d\n", sched_ctrl->mcs);
192
  AssertFatal(sched_ctrl->mcsTableIdx >= 0 && sched_ctrl->mcsTableIdx <= 2, "invalid sched_ctrl->mcsTableIdx %d\n", sched_ctrl->mcsTableIdx);
193 194
  sched_ctrl->numDmrsCdmGrpsNoData = 1;
}
195 196


197 198 199
int main(int argc, char **argv)
{
  char c;
200
  int i,aa;//,l;
201
  double sigma2, sigma2_dB=10, SNR, snr0=-2.0, snr1=2.0;
202
  uint8_t snr1set=0;
203
  float roundStats[50];
204
  float effRate;
Francesco Mani's avatar
Francesco Mani committed
205
  //float psnr;
206
  float eff_tp_check = 0.7;
207
  uint8_t snrRun;
208
  uint32_t TBS;
209 210
  int **txdata;
  double **s_re,**s_im,**r_re,**r_im;
211 212
  //double iqim = 0.0;
  //unsigned char pbch_pdu[6];
213 214 215
  //  int sync_pos, sync_pos_slot;
  //  FILE *rx_frame_file;
  FILE *output_fd = NULL;
216
  //uint8_t write_output_file=0;
217
  //int result;
218
  //int freq_offset;
219
  //  int subframe_offset;
220
  //  char fname[40], vname[40];
Ahmed Hussein's avatar
Ahmed Hussein committed
221
  int trial, n_trials = 1, n_errors = 0, n_false_positive = 0;
222
  //int n_errors2, n_alamouti;
223
  uint8_t transmission_mode = 1,n_tx=1,n_rx=1;
224 225
  uint8_t round;
  uint8_t num_rounds = 4;
226 227

  channel_desc_t *gNB2UE;
228 229 230
  //uint32_t nsymb,tx_lev,tx_lev1 = 0,tx_lev2 = 0;
  //uint8_t extended_prefix_flag=0;
  //int8_t interf1=-21,interf2=-21;
231 232

  FILE *input_fd=NULL,*pbch_file_fd=NULL;
233
  //char input_val_str[50],input_val_str2[50];
234

235
  //uint8_t frame_mod4,num_pdcch_symbols = 0;
236 237 238

  SCM_t channel_model=AWGN;//Rayleigh1_anticorr;

Laurent's avatar
Laurent committed
239
  NB_UE_INST = 1;
240 241
  //double pbch_sinr;
  //int pbch_tx_ant;
Ahmed Hussein's avatar
Ahmed Hussein committed
242
  int N_RB_DL=106,mu=1;
243

244
  //unsigned char frame_type = 0;
245

246
  int frame=1,slot=1;
247
  int frame_length_complex_samples;
248
  //int frame_length_complex_samples_no_prefix;
249 250 251 252 253
  NR_DL_FRAME_PARMS *frame_parms;
  UE_nr_rxtx_proc_t UE_proc;
  NR_Sched_Rsp_t Sched_INFO;
  gNB_MAC_INST *gNB_mac;
  NR_UE_MAC_INST_t *UE_mac;
254
  int cyclic_prefix_type = NFAPI_CP_NORMAL;
255
  int run_initial_sync=0;
256 257
  int pusch_tgt_snrx10 = 200;
  int pucch_tgt_snrx10 = 200;
Raymond Knopp's avatar
Raymond Knopp committed
258
  int loglvl=OAILOG_INFO;
259

260
  //float target_error_rate = 0.01;
261
  int css_flag=0;
262 263

  cpuf = get_cpu_freq_GHz();
264 265 266 267
  int8_t enable_ptrs = 0;
  int8_t modify_dmrs = 0;

  int8_t dmrs_arg[2] = {-1,-1};// Invalid values
268
  /* L_PTRS = ptrs_arg[0], K_PTRS = ptrs_arg[1] */
269 270
  int8_t ptrs_arg[2] = {-1,-1};// Invalid values

271 272 273 274 275 276
  uint16_t ptrsRePerSymb = 0;
  uint16_t pdu_bit_map = 0x0;
  uint16_t dlPtrsSymPos = 0;
  uint16_t ptrsSymbPerSlot = 0;
  uint16_t rbSize = 106;
  uint8_t  mcsIndex = 9;
277
  uint8_t  dlsch_threads = 0;
278
  if ( load_configmodule(argc,argv,CONFIG_ENABLECMDLINEONLY) == 0) {
yilmazt's avatar
yilmazt committed
279
    exit_fun("[NR_DLSIM] Error, configuration module init failed\n");
280 281 282 283
  }

  randominit(0);

284
  int print_perf             = 0;
285

286 287
  FILE *scg_fd=NULL;
  
288
  while ((c = getopt (argc, argv, "f:hA:pf:g:i:j:n:s:S:t:x:y:z:M:N:F:GR:dPIL:Ea:b:d:e:m:w:T:U:q")) != -1) {
289
    switch (c) {
290 291
    case 'f':
      scg_fd = fopen(optarg,"r");
292

293
      if (scg_fd==NULL) {
294 295 296
        printf("Error opening %s\n",optarg);
        exit(-1);
      }
297
      break;
298

299
    /*case 'd':
300
      frame_type = 1;
301
      break;*/
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

    case 'g':
      switch((char)*optarg) {
      case 'A':
        channel_model=SCM_A;
        break;

      case 'B':
        channel_model=SCM_B;
        break;

      case 'C':
        channel_model=SCM_C;
        break;

      case 'D':
        channel_model=SCM_D;
        break;

      case 'E':
        channel_model=EPA;
        break;

      case 'F':
        channel_model=EVA;
        break;

      case 'G':
        channel_model=ETU;
        break;

      default:
334
        printf("Unsupported channel model!\n");
335 336 337 338 339
        exit(-1);
      }

      break;

340
    /*case 'i':
341 342 343 344 345
      interf1=atoi(optarg);
      break;

    case 'j':
      interf2=atoi(optarg);
346
      break;*/
347 348 349 350 351 352 353

    case 'n':
      n_trials = atoi(optarg);
      break;

    case 's':
      snr0 = atof(optarg);
354
      printf("Setting SNR0 to %f\n",snr0);
355 356 357 358 359
      break;

    case 'S':
      snr1 = atof(optarg);
      snr1set=1;
360
      printf("Setting SNR1 to %f\n",snr1);
361 362 363 364 365 366 367
      break;

      /*
      case 't':
      Td= atof(optarg);
      break;
      */
368
    /*case 'p':
369
      extended_prefix_flag=1;
370
      break;*/
371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386

      /*
      case 'r':
      ricean_factor = pow(10,-.1*atof(optarg));
      if (ricean_factor>1) {
        printf("Ricean factor must be between 0 and 1\n");
        exit(-1);
      }
      break;
      */
    case 'x':
      transmission_mode=atoi(optarg);

      if ((transmission_mode!=1) &&
          (transmission_mode!=2) &&
          (transmission_mode!=6)) {
387
        printf("Unsupported transmission mode %d\n",transmission_mode);
388 389 390 391 392 393 394 395
        exit(-1);
      }

      break;

    case 'y':
      n_tx=atoi(optarg);

396
      if ((n_tx==0) || (n_tx>4)) {//extend gNB to support n_tx = 4
397
        printf("Unsupported number of tx antennas %d\n",n_tx);
398 399 400 401 402 403 404 405
        exit(-1);
      }

      break;

    case 'z':
      n_rx=atoi(optarg);

406
      if ((n_rx==0) || (n_rx>4)) {//extend UE to support n_tx = 4
407
        printf("Unsupported number of rx antennas %d\n",n_rx);
408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427
        exit(-1);
      }

      break;

    case 'R':
      N_RB_DL = atoi(optarg);
      break;

    case 'F':
      input_fd = fopen(optarg,"r");

      if (input_fd==NULL) {
        printf("Problem with filename %s\n",optarg);
        exit(-1);
      }

      break;

    case 'P':
428 429
      print_perf=1;
      opp_enabled=1;
430 431 432 433
      break;
      
    case 'I':
      run_initial_sync=1;
434
      //target_error_rate=0.1;
435
      slot = 0;
436 437 438 439 440 441
      break;

    case 'L':
      loglvl = atoi(optarg);
      break;

442

443 444 445
    case 'E':
	css_flag=1;
	break;
446

447

448
    case 'a':
449
      g_rbStart = atoi(optarg);
450 451 452
      break;

    case 'b':
453
      g_rbSize = atoi(optarg);
454
      break;
455 456 457
    case 'd':
      dlsch_threads = atoi(optarg);
      break;    
458
    case 'e':
459
      g_mcsIndex = atoi(optarg);
460 461
      break;

462 463 464 465 466
    case 'q':
      g_mcsTableIdx = 1;
      get_softmodem_params()->use_256qam_table = 1;
      break;

467 468 469
    case 'm':
      mu = atoi(optarg);
      break;
470

471 472 473 474
    case 't':
      eff_tp_check = (float)atoi(optarg)/100;
      break;

475 476 477
    case 'w':
      output_fd = fopen("txdata.dat", "w+");
      break;
Sakthivel Velumani's avatar
Sakthivel Velumani committed
478

479 480 481 482 483 484 485
    case 'T':
      enable_ptrs=1;
      for(i=0; i < atoi(optarg); i++) {
        ptrs_arg[i] = atoi(argv[optind++]);
      }
      break;

486 487
    case 'U':
      modify_dmrs = 1;
488
      for(i=0; i < atoi(optarg); i++) {
489 490 491
        dmrs_arg[i] = atoi(argv[optind++]);
      }
      break;
Sakthivel Velumani's avatar
Sakthivel Velumani committed
492

493 494 495 496 497
    default:
    case 'h':
      printf("%s -h(elp) -p(extended_prefix) -N cell_id -f output_filename -F input_filename -g channel_model -n n_frames -t Delayspread -s snr0 -S snr1 -x transmission_mode -y TXant -z RXant -i Intefrence0 -j Interference1 -A interpolation_file -C(alibration offset dB) -N CellId\n",
             argv[0]);
      printf("-h This message\n");
498 499
      //printf("-p Use extended prefix mode\n");
      //printf("-d Use TDD\n");
500 501 502 503 504
      printf("-n Number of frames to simulate\n");
      printf("-s Starting SNR, runs from SNR0 to SNR0 + 5 dB.  If n_frames is 1 then just SNR is simulated\n");
      printf("-S Ending SNR, runs from SNR0 to SNR1\n");
      printf("-t Delay spread for multipath channel\n");
      printf("-g [A,B,C,D,E,F,G] Use 3GPP SCM (A,B,C,D) or 36-101 (E-EPA,F-EVA,G-ETU) models (ignores delay spread and Ricean factor)\n");
505
      printf("-y Number of TX antennas used in gNB\n");
506
      printf("-z Number of RX antennas used in UE\n");
507 508
      //printf("-i Relative strength of first intefering gNB (in dB) - cell_id mod 3 = 1\n");
      //printf("-j Relative strength of second intefering gNB (in dB) - cell_id mod 3 = 2\n");
509 510 511
      printf("-R N_RB_DL\n");
      printf("-O oversampling factor (1,2,4,8,16)\n");
      printf("-A Interpolation_filname Run with Abstraction to generate Scatter plot using interpolation polynomial in file\n");
512
      //printf("-C Generate Calibration information for Abstraction (effective SNR adjustment to remove Pe bias w.r.t. AWGN)\n");
513
      printf("-f raw file containing RRC configuration (generated by gNB)\n");
514
      printf("-F Input filename (.txt format) for RX conformance testing\n");
515
      printf("-E used CSS scheduler\n");
516
      printf("-o CORESET offset\n");
517 518
      printf("-a Start PRB for PDSCH\n");
      printf("-b Number of PRB for PDSCH\n");
519 520
      printf("-c Start symbol for PDSCH (fixed for now)\n");
      printf("-j Number of symbols for PDSCH (fixed for now)\n");
521
      printf("-e MSC index\n");
522
      printf("-q Use 2nd MCS table (256 QAM table) for PDSCH\n");
523
      printf("-t Acceptable effective throughput (in percentage)\n");
524
      printf("-T Enable PTRS, arguments list L_PTRS{0,1,2} K_PTRS{2,4}, e.g. -T 2 0 2 \n");
525
      printf("-U Change DMRS Config, arguments list DMRS TYPE{0=A,1=B} DMRS AddPos{0:2}, e.g. -U 2 0 2 \n");
526
      printf("-P Print DLSCH performances\n");
Sakthivel Velumani's avatar
Sakthivel Velumani committed
527
      printf("-w Write txdata to binary file (one frame)\n");
528
      printf("-d number of dlsch threads, 0: no dlsch parallelization\n");
529 530 531 532
      exit (-1);
      break;
    }
  }
533

534 535 536
  logInit();
  set_glog(loglvl);
  T_stdout = 1;
537 538
  /* initialize the sin table */
  InitSinLUT();
539

540 541
  get_softmodem_params()->phy_test = 1;
  
542 543
  if (snr1set==0)
    snr1 = snr0+10;
544
  init_dlsch_tpool(dlsch_threads);
545 546


547 548 549
  RC.gNB = (PHY_VARS_gNB**) malloc(sizeof(PHY_VARS_gNB *));
  RC.gNB[0] = (PHY_VARS_gNB*) malloc(sizeof(PHY_VARS_gNB ));
  memset(RC.gNB[0],0,sizeof(PHY_VARS_gNB));
Raymond Knopp's avatar
Raymond Knopp committed
550

551
  gNB = RC.gNB[0];
552 553 554 555 556 557
  frame_parms = &gNB->frame_parms; //to be initialized I suppose (maybe not necessary for PBCH)
  frame_parms->nb_antennas_tx = n_tx;
  frame_parms->nb_antennas_rx = n_rx;
  frame_parms->N_RB_DL = N_RB_DL;
  frame_parms->N_RB_UL = N_RB_DL;

Raymond Knopp's avatar
Raymond Knopp committed
558
  RC.nb_nr_macrlc_inst = 1;
cig's avatar
cig committed
559 560 561
  RC.nb_nr_mac_CC = (int*)malloc(RC.nb_nr_macrlc_inst*sizeof(int));
  for (i = 0; i < RC.nb_nr_macrlc_inst; i++)
    RC.nb_nr_mac_CC[i] = 1;
Raymond Knopp's avatar
Raymond Knopp committed
562 563
  mac_top_init_gNB();
  gNB_mac = RC.nrmac[0];
564
  gNB_mac->pre_processor_dl = nr_dlsim_preprocessor;
Raymond Knopp's avatar
Raymond Knopp committed
565
  gNB_RRC_INST rrc;
Raymond Knopp's avatar
Raymond Knopp committed
566
  memset((void*)&rrc,0,sizeof(rrc));
567

568
  /*
Raymond Knopp's avatar
Raymond Knopp committed
569
  // read in SCGroupConfig
Raymond Knopp's avatar
Raymond Knopp committed
570
  AssertFatal(scg_fd != NULL,"no reconfig.raw file\n");
Raymond Knopp's avatar
Raymond Knopp committed
571 572 573 574
  char buffer[1024];
  int msg_len=fread(buffer,1,1024,scg_fd);
  NR_RRCReconfiguration_t *NR_RRCReconfiguration;

Raymond Knopp's avatar
Raymond Knopp committed
575
  printf("Decoding NR_RRCReconfiguration (%d bytes)\n",msg_len);
Raymond Knopp's avatar
Raymond Knopp committed
576 577 578 579 580 581 582 583 584 585 586 587 588 589
  asn_dec_rval_t dec_rval = uper_decode_complete( NULL,
						  &asn_DEF_NR_RRCReconfiguration,
						  (void **)&NR_RRCReconfiguration,
						  (uint8_t *)buffer,
						  msg_len); 
  
  if ((dec_rval.code != RC_OK) && (dec_rval.consumed == 0)) {
    AssertFatal(1==0,"NR_RRCReConfiguration decode error\n");
    // free the memory
    SEQUENCE_free( &asn_DEF_NR_RRCReconfiguration, NR_RRCReconfiguration, 1 );
    exit(-1);
  }      
  fclose(scg_fd);

Raymond Knopp's avatar
Raymond Knopp committed
590 591
  AssertFatal(NR_RRCReconfiguration->criticalExtensions.present == NR_RRCReconfiguration__criticalExtensions_PR_rrcReconfiguration,"wrong NR_RRCReconfiguration->criticalExstions.present type\n");

Raymond Knopp's avatar
Raymond Knopp committed
592 593 594 595 596 597 598 599 600 601 602 603 604 605 606
  NR_RRCReconfiguration_IEs_t *reconfig_ies = NR_RRCReconfiguration->criticalExtensions.choice.rrcReconfiguration;
  NR_CellGroupConfig_t *secondaryCellGroup;
  dec_rval = uper_decode_complete( NULL,
				   &asn_DEF_NR_CellGroupConfig,
				   (void **)&secondaryCellGroup,
				   (uint8_t *)reconfig_ies->secondaryCellGroup->buf,
				   reconfig_ies->secondaryCellGroup->size); 
  
  if ((dec_rval.code != RC_OK) && (dec_rval.consumed == 0)) {
    AssertFatal(1==0,"NR_CellGroupConfig decode error\n");
    // free the memory
    SEQUENCE_free( &asn_DEF_NR_CellGroupConfig, secondaryCellGroup, 1 );
    exit(-1);
  }      
  
607 608
  NR_ServingCellConfigCommon_t *scc = secondaryCellGroup->spCellConfig->reconfigurationWithSync->spCellConfigCommon;
  */
Raymond Knopp's avatar
Raymond Knopp committed
609

610 611 612 613 614 615 616 617

  rrc.carrier.servingcellconfigcommon = calloc(1,sizeof(*rrc.carrier.servingcellconfigcommon));

  NR_ServingCellConfigCommon_t *scc = rrc.carrier.servingcellconfigcommon;
  NR_CellGroupConfig_t *secondaryCellGroup=calloc(1,sizeof(*secondaryCellGroup));
  prepare_scc(rrc.carrier.servingcellconfigcommon);
  uint64_t ssb_bitmap;
  fill_scc(rrc.carrier.servingcellconfigcommon,&ssb_bitmap,N_RB_DL,N_RB_DL,mu,mu);
618
  ssb_bitmap = 1;// Enable only first SSB with index ssb_indx=0
Francesco Mani's avatar
Francesco Mani committed
619 620
  fix_scc(scc,ssb_bitmap);

621 622 623 624 625 626 627
  fill_default_secondaryCellGroup(scc,
				  secondaryCellGroup,
				  0,
				  1,
				  n_tx,
				  0);

628
  /* -U option modify DMRS */
629
  if(modify_dmrs) {
630 631
    update_dmrs_config(secondaryCellGroup, NULL,dmrs_arg);
  }
632
  /* -T option enable PTRS */
633
  if(enable_ptrs) {
634
    update_ptrs_config(secondaryCellGroup, &rbSize, &mcsIndex, ptrs_arg);
635 636
  }

637

638
  //xer_fprint(stdout, &asn_DEF_NR_CellGroupConfig, (const void*)secondaryCellGroup);
Raymond Knopp's avatar
Raymond Knopp committed
639

Raymond Knopp's avatar
Raymond Knopp committed
640 641
  AssertFatal((gNB->if_inst         = NR_IF_Module_init(0))!=NULL,"Cannot register interface");
  gNB->if_inst->NR_PHY_config_req      = nr_phy_config_request;
Raymond Knopp's avatar
Raymond Knopp committed
642
  // common configuration
643
  rrc_mac_config_req_gNB(0,0,n_tx,pusch_tgt_snrx10,pucch_tgt_snrx10,scc,0,0,NULL);
Raymond Knopp's avatar
Raymond Knopp committed
644
  // UE dedicated configuration
645
  rrc_mac_config_req_gNB(0,0,n_tx,pusch_tgt_snrx10,pucch_tgt_snrx10,NULL,1,secondaryCellGroup->spCellConfig->reconfigurationWithSync->newUE_Identity,secondaryCellGroup);
Raymond Knopp's avatar
Raymond Knopp committed
646
  phy_init_nr_gNB(gNB,0,0);
647
  N_RB_DL = gNB->frame_parms.N_RB_DL;
Raymond Knopp's avatar
Raymond Knopp committed
648
  // stub to configure frame_parms
Raymond Knopp's avatar
Raymond Knopp committed
649
  //  nr_phy_config_request_sim(gNB,N_RB_DL,N_RB_DL,mu,Nid_cell,SSB_positions);
Raymond Knopp's avatar
Raymond Knopp committed
650 651
  // call MAC to configure common parameters

652 653 654 655 656 657
  /* rrc_mac_config_req_gNB() has created one user, so set the scheduling
   * parameters from command line in global variables that will be picked up by
   * scheduling preprocessor */
  if (g_mcsIndex < 0) g_mcsIndex = 9;
  if (g_rbStart < 0) g_rbStart=0;
  if (g_rbSize < 0) g_rbSize = N_RB_DL - g_rbStart;
Raymond Knopp's avatar
Raymond Knopp committed
658

659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676
  double fs,bw;

  if (mu == 1 && N_RB_DL == 217) { 
    fs = 122.88e6;
    bw = 80e6;
  }					       
  else if (mu == 1 && N_RB_DL == 245) {
    fs = 122.88e6;
    bw = 90e6;
  }
  else if (mu == 1 && N_RB_DL == 273) {
    fs = 122.88e6;
    bw = 100e6;
  }
  else if (mu == 1 && N_RB_DL == 106) { 
    fs = 61.44e6;
    bw = 40e6;
  }
677 678 679 680
  else if (mu == 3 && N_RB_DL == 66) {
    fs = 122.88e6;
    bw = 100e6;
  }
681 682 683 684
  else if (mu == 3 && N_RB_DL == 32) {
    fs = 61.44e6;
    bw = 50e6;
  }
685 686 687 688 689
  else AssertFatal(1==0,"Unsupported numerology for mu %d, N_RB %d\n",mu, N_RB_DL);

  gNB2UE = new_channel_desc_scm(n_tx,
                                n_rx,
                                channel_model,
690 691
 				fs,
				bw,
692
				30e-9,
693 694 695 696 697
                                0,
                                0,
                                0);

  if (gNB2UE==NULL) {
698
    printf("Problem generating channel model. Exiting.\n");
699 700 701 702
    exit(-1);
  }

  frame_length_complex_samples = frame_parms->samples_per_subframe*NR_NUMBER_OF_SUBFRAMES_PER_FRAME;
703
  //frame_length_complex_samples_no_prefix = frame_parms->samples_per_subframe_wCP*NR_NUMBER_OF_SUBFRAMES_PER_FRAME;
704

705 706 707 708 709
  s_re = malloc(n_tx*sizeof(double*));
  s_im = malloc(n_tx*sizeof(double*));
  r_re = malloc(n_rx*sizeof(double*));
  r_im = malloc(n_rx*sizeof(double*));
  txdata = malloc(n_tx*sizeof(int*));
710

711
  for (i=0; i<n_tx; i++) {
712 713 714 715 716
    s_re[i] = malloc(frame_length_complex_samples*sizeof(double));
    bzero(s_re[i],frame_length_complex_samples*sizeof(double));
    s_im[i] = malloc(frame_length_complex_samples*sizeof(double));
    bzero(s_im[i],frame_length_complex_samples*sizeof(double));

717 718 719 720 721 722
    printf("Allocating %d samples for txdata\n",frame_length_complex_samples);
    txdata[i] = malloc(frame_length_complex_samples*sizeof(int));
    bzero(txdata[i],frame_length_complex_samples*sizeof(int));
  }

  for (i=0; i<n_rx; i++) {
723 724 725 726 727 728 729 730 731 732 733 734 735
    r_re[i] = malloc(frame_length_complex_samples*sizeof(double));
    bzero(r_re[i],frame_length_complex_samples*sizeof(double));
    r_im[i] = malloc(frame_length_complex_samples*sizeof(double));
    bzero(r_im[i],frame_length_complex_samples*sizeof(double));
  }

  if (pbch_file_fd!=NULL) {
    load_pbch_desc(pbch_file_fd);
  }


  //configure UE
  UE = malloc(sizeof(PHY_VARS_NR_UE));
Raymond Knopp's avatar
Raymond Knopp committed
736
  memset((void*)UE,0,sizeof(PHY_VARS_NR_UE));
737 738 739 740
  PHY_vars_UE_g = malloc(sizeof(PHY_VARS_NR_UE**));
  PHY_vars_UE_g[0] = malloc(sizeof(PHY_VARS_NR_UE*));
  PHY_vars_UE_g[0][0] = UE;
  memcpy(&UE->frame_parms,frame_parms,sizeof(NR_DL_FRAME_PARMS));
741
  UE->frame_parms.nb_antennas_rx = n_rx;
Raymond Knopp's avatar
Raymond Knopp committed
742

743
  if (run_initial_sync==1)  UE->is_synchronized = 0;
744
  else                      {UE->is_synchronized = 1; UE->UE_mode[0]=PUSCH;}
745 746 747 748 749 750 751 752 753
                      
  UE->perfect_ce = 0;

  if (init_nr_ue_signal(UE, 1, 0) != 0)
  {
    printf("Error at UE NR initialisation\n");
    exit(-1);
  }

754
  if(modify_dmrs) {
755 756
    update_dmrs_config( NULL,UE,dmrs_arg);
  }
757 758
  init_nr_ue_transport(UE,0);

759
  nr_gold_pbch(UE);
760
  nr_gold_pdcch(UE,0,2);
761

762
  nr_l2_init_ue(NULL);
763
  UE_mac = get_mac_inst(0);
764

765 766 767
  UE->if_inst = nr_ue_if_module_init(0);
  UE->if_inst->scheduled_response = nr_ue_scheduled_response;
  UE->if_inst->phy_config_request = nr_ue_phy_config_request;
768
  UE->if_inst->dl_indication = nr_ue_dl_indication;
769
  UE->if_inst->ul_indication = dummy_nr_ue_ul_indication;
770

771

772
  UE_mac->if_module = nr_ue_if_module_init(0);
773

774
  unsigned int available_bits=0;
Ahmed Hussein's avatar
Ahmed Hussein committed
775 776 777 778 779
  unsigned char *estimated_output_bit;
  unsigned char *test_input_bit;
  unsigned int errors_bit    = 0;
  uint32_t errors_scrambling = 0;

780

Ahmed Hussein's avatar
Ahmed Hussein committed
781 782
  test_input_bit       = (unsigned char *) malloc16(sizeof(unsigned char) * 16 * 68 * 384);
  estimated_output_bit = (unsigned char *) malloc16(sizeof(unsigned char) * 16 * 68 * 384);
783 784
  
  // generate signal
785 786 787
  AssertFatal(input_fd==NULL,"Not ready for input signal file\n");
  gNB->pbch_configured = 1;
  gNB->ssb_pdu.ssb_pdu_rel15.bchPayload=0x001234;
Raymond Knopp's avatar
Raymond Knopp committed
788

789
  //Configure UE
790 791
  rrc.carrier.MIB = (uint8_t*) malloc(4);
  rrc.carrier.sizeof_MIB = do_MIB_NR(&rrc,0);
792

793
  nr_rrc_mac_config_req_ue(0,0,0,rrc.carrier.mib.message.choice.mib,secondaryCellGroup);
794

795 796 797 798 799 800 801 802

  nr_dcireq_t dcireq;
  nr_scheduled_response_t scheduled_response;
  memset((void*)&dcireq,0,sizeof(dcireq));
  memset((void*)&scheduled_response,0,sizeof(scheduled_response));
  dcireq.module_id = 0;
  dcireq.gNB_index = 0;
  dcireq.cc_id     = 0;
803
  
804 805 806 807 808 809 810
  scheduled_response.dl_config = &dcireq.dl_config_req;
  scheduled_response.ul_config = &dcireq.ul_config_req;
  scheduled_response.tx_request = NULL;
  scheduled_response.module_id = 0;
  scheduled_response.CC_id     = 0;
  scheduled_response.frame = frame;
  scheduled_response.slot  = slot;
811
  scheduled_response.thread_id = UE_proc.thread_id;
Francesco Mani's avatar
Francesco Mani committed
812

813
  nr_ue_phy_config_request(&UE_mac->phy_config);
814
  NR_UE_info_t *UE_info = &RC.nrmac[0]->UE_info;
Francesco Mani's avatar
Francesco Mani committed
815
  //NR_COMMON_channels_t *cc = RC.nrmac[0]->common_channels;
816
  snrRun = 0;
817

Ahmed Hussein's avatar
Ahmed Hussein committed
818
  for (SNR = snr0; SNR < snr1; SNR += .2) {
819

820 821 822 823 824 825 826 827 828 829 830
    varArray_t *table_tx=initVarArray(1000,sizeof(double));
    reset_meas(&gNB->phy_proc_tx); // total gNB tx
    reset_meas(&gNB->dlsch_scrambling_stats);
    reset_meas(&gNB->dlsch_interleaving_stats);
    reset_meas(&gNB->dlsch_rate_matching_stats);
    reset_meas(&gNB->dlsch_segmentation_stats);
    reset_meas(&gNB->dlsch_modulation_stats);
    reset_meas(&gNB->dlsch_encoding_stats);
    reset_meas(&gNB->tinput);
    reset_meas(&gNB->tprep);
    reset_meas(&gNB->tparity);
831
    reset_meas(&gNB->toutput);
832

833 834
    clear_pdsch_stats(gNB);

835
    n_errors = 0;
836
    effRate = 0;
837 838
    //n_errors2 = 0;
    //n_alamouti = 0;
839
    errors_scrambling=0;
840
    n_false_positive = 0;
841 842
    if (n_trials== 1) num_rounds = 1;

Ahmed Hussein's avatar
Ahmed Hussein committed
843
    for (trial = 0; trial < n_trials; trial++) {
844

845
      errors_bit = 0;
Ahmed Hussein's avatar
Ahmed Hussein committed
846
      //multipath channel
847
      //multipath_channel(gNB2UE,s_re,s_im,r_re,r_im,frame_length_complex_samples,0);
848

849
      UE->rx_offset=0;
850 851 852
      UE_proc.thread_id  = 0;
      UE_proc.frame_rx   = frame;
      UE_proc.nr_slot_rx = slot;
853 854 855
      
      dcireq.frame     = frame;
      dcireq.slot      = slot;
856

857
      NR_UE_DLSCH_t *dlsch0 = UE->dlsch[UE_proc.thread_id][0][0];
858

859
      int harq_pid = slot;
860 861 862
      NR_DL_UE_HARQ_t *UE_harq_process = dlsch0->harq_processes[harq_pid];

      NR_gNB_DLSCH_t *gNB_dlsch = gNB->dlsch[0][0];
Sakthivel Velumani's avatar
Sakthivel Velumani committed
863
      nfapi_nr_dl_tti_pdsch_pdu_rel15_t *rel15 = &gNB_dlsch->harq_processes[slot]->pdsch_pdu.pdsch_pdu_rel15;
864
      
865 866
      UE_harq_process->harq_ack.ack = 0;
      round = 0;
867 868
      UE_harq_process->round = round;
      UE_harq_process->first_tx = 1;
869 870 871 872
        
      while ((round<num_rounds) && (UE_harq_process->harq_ack.ack==0)) {
        memset(RC.nrmac[0]->cce_list[1][0],0,MAX_NUM_CCE*sizeof(int));
        memset(RC.nrmac[0]->cce_list[1][1],0,MAX_NUM_CCE*sizeof(int));
873
        clear_nr_nfapi_information(RC.nrmac[0], 0, frame, slot);
874

875
        UE_info->UE_sched_ctrl[0].harq_processes[harq_pid].ndi = !(trial&1);
876

877

878
        UE_info->UE_sched_ctrl[0].harq_processes[harq_pid].round = round;
879
        gNB->dlsch[0][0]->harq_processes[harq_pid]->round = round;
Sakthivel Velumani's avatar
Sakthivel Velumani committed
880
        for (int i=0; i<MAX_NUM_CORESET; i++)
881
          gNB_mac->UE_info.num_pdcch_cand[0][i] = 0;
882
      
883 884 885 886 887 888 889 890
        if (css_flag == 0) {
          const uint8_t slots_per_frame[5] = {10, 20, 40, 80, 160};
          const NR_TDD_UL_DL_Pattern_t *tdd_pattern = &scc->tdd_UL_DL_ConfigurationCommon->pattern1;
          const int num_slots_per_tdd = slots_per_frame[*scc->ssbSubcarrierSpacing] >> (7 - tdd_pattern->dl_UL_TransmissionPeriodicity);
          nr_schedule_ue_spec(0, frame, slot, num_slots_per_tdd);
        } else {
          nr_schedule_css_dlsch_phytest(0,frame,slot);
        }
891 892 893 894 895
        Sched_INFO.module_id = 0;
        Sched_INFO.CC_id     = 0;
        Sched_INFO.frame     = frame;
        Sched_INFO.slot      = slot;
        Sched_INFO.DL_req    = &gNB_mac->DL_req[0];
896
        Sched_INFO.UL_tti_req    = gNB_mac->UL_tti_req_ahead[slot];
897 898 899
        Sched_INFO.UL_dci_req  = NULL;
        Sched_INFO.TX_req    = &gNB_mac->TX_req[0];
        nr_schedule_response(&Sched_INFO);
900 901 902 903 904 905

        /* PTRS values for DLSIM calculations   */
        nfapi_nr_dl_tti_request_body_t *dl_req = &gNB_mac->DL_req[Sched_INFO.CC_id].dl_tti_request_body;
        nfapi_nr_dl_tti_request_pdu_t  *dl_tti_pdsch_pdu = &dl_req->dl_tti_pdu_list[1];
        nfapi_nr_dl_tti_pdsch_pdu_rel15_t *pdsch_pdu_rel15 = &dl_tti_pdsch_pdu->pdsch_pdu.pdsch_pdu_rel15;
        pdu_bit_map = pdsch_pdu_rel15->pduBitmap;
906
        if(pdu_bit_map & 0x1) {
907 908 909 910 911 912 913
          set_ptrs_symb_idx(&dlPtrsSymPos,
                            pdsch_pdu_rel15->NrOfSymbols,
                            pdsch_pdu_rel15->StartSymbolIndex,
                            1<<pdsch_pdu_rel15->PTRSTimeDensity,
                            pdsch_pdu_rel15->dlDmrsSymbPos);
          ptrsSymbPerSlot = get_ptrs_symbols_in_slot(dlPtrsSymPos, pdsch_pdu_rel15->StartSymbolIndex, pdsch_pdu_rel15->NrOfSymbols);
          ptrsRePerSymb = ((rel15->rbSize + rel15->PTRSFreqDensity - 1)/rel15->PTRSFreqDensity);
914
          printf("[DLSIM] PTRS Symbols in a slot: %2u, RE per Symbol: %3u, RE in a slot %4d\n", ptrsSymbPerSlot,ptrsRePerSymb, ptrsSymbPerSlot*ptrsRePerSymb );
915
        }
916 917 918 919 920 921 922 923
        if (run_initial_sync)
          nr_common_signal_procedures(gNB,frame,slot);
        else
          phy_procedures_gNB_TX(gNB,frame,slot,0);
            
        int txdataF_offset = (slot%2) * frame_parms->samples_per_slot_wCP;
        
        if (n_trials==1) {
924
          LOG_M("txsigF0.m","txsF0=", &gNB->common_vars.txdataF[0][txdataF_offset+2*frame_parms->ofdm_symbol_size],frame_parms->ofdm_symbol_size,1,1);
925
          if (gNB->frame_parms.nb_antennas_tx>1)
926
            LOG_M("txsigF1.m","txsF1=", &gNB->common_vars.txdataF[1][txdataF_offset+2*frame_parms->ofdm_symbol_size],frame_parms->ofdm_symbol_size,1,1);
927 928
        }
        int tx_offset = frame_parms->get_samples_slot_timestamp(slot,frame_parms,0);
929
        if (n_trials==1) printf("tx_offset %d, txdataF_offset %d \n", tx_offset,txdataF_offset);
930

931 932 933
        //TODO: loop over slots
        for (aa=0; aa<gNB->frame_parms.nb_antennas_tx; aa++) {
    
934 935 936 937 938 939 940
          if (cyclic_prefix_type == 1) {
            PHY_ofdm_mod(&gNB->common_vars.txdataF[aa][txdataF_offset],
                         &txdata[aa][tx_offset],
                         frame_parms->ofdm_symbol_size,
                         12,
                         frame_parms->nb_prefix_samples,
                         CYCLIC_PREFIX);
941
          } else {
942 943 944 945 946
            nr_normal_prefix_mod(&gNB->common_vars.txdataF[aa][txdataF_offset],
                                 &txdata[aa][tx_offset],
                                 14,
                                 frame_parms);
          }
947 948 949
        }
       
        if (n_trials==1) {
950 951 952 953 954
          char filename[100];//LOG_M
          for (aa=0;aa<n_tx;aa++) {
            sprintf(filename,"txsig%d.m", aa);//LOG_M
            LOG_M(filename,"txs", &txdata[aa][tx_offset+frame_parms->ofdm_symbol_size+frame_parms->nb_prefix_samples0],6*(frame_parms->ofdm_symbol_size+frame_parms->nb_prefix_samples),1,1);
          }
955
        }
Sakthivel Velumani's avatar
Sakthivel Velumani committed
956 957
        if (output_fd) {
          printf("writing txdata to binary file\n");
958
          fwrite(txdata[0],sizeof(int32_t),frame_length_complex_samples,output_fd);
Sakthivel Velumani's avatar
Sakthivel Velumani committed
959
        }
960

961 962 963 964 965 966 967 968 969
        int txlev[n_tx];
        int txlev_sum = 0;
        int l_ofdm = 6;
        for (aa=0; aa<n_tx; aa++) {
          txlev[aa] = signal_energy(&txdata[aa][tx_offset+l_ofdm*frame_parms->ofdm_symbol_size + (l_ofdm-1)*frame_parms->nb_prefix_samples + frame_parms->nb_prefix_samples0],
          frame_parms->ofdm_symbol_size + frame_parms->nb_prefix_samples);
          txlev_sum += txlev[aa];
          if (n_trials==1) printf("txlev[%d] = %d (%f dB) txlev_sum %d\n",aa,txlev[aa],10*log10((double)txlev[aa]),txlev_sum);
        }
970 971 972
        
        
        for (i=(frame_parms->get_samples_slot_timestamp(slot,frame_parms,0)); 
973 974 975 976
             i<(frame_parms->get_samples_slot_timestamp(slot+1,frame_parms,0)); 
             i++) {
    
          for (aa=0; aa<frame_parms->nb_antennas_tx; aa++) {
977 978
            s_re[aa][i] = ((double)(((short *)txdata[aa]))[(i<<1)]);
            s_im[aa][i] = ((double)(((short *)txdata[aa]))[(i<<1)+1]);
979
          }
980
        }
981
        double ts = 1.0/(frame_parms->subcarrier_spacing * frame_parms->ofdm_symbol_size); 
982
        //AWGN
983
        sigma2_dB = 10 * log10((double)txlev_sum * ((double)UE->frame_parms.ofdm_symbol_size/(12*rel15->rbSize))) - SNR;
984
        sigma2    = pow(10, sigma2_dB/10);
985 986 987 988 989
        if (n_trials==1) printf("sigma2 %f (%f dB), txlev_sum %f (factor %f)\n",sigma2,sigma2_dB,10*log10((double)txlev_sum),(double)(double)UE->frame_parms.ofdm_symbol_size/(12*rel15->rbSize));
        for (aa=0; aa<n_rx; aa++) {
          bzero(r_re[aa],frame_length_complex_samples*sizeof(double));
          bzero(r_im[aa],frame_length_complex_samples*sizeof(double));
        }
990 991
        
        for (i=frame_parms->get_samples_slot_timestamp(slot,frame_parms,0); 
992 993 994
             i<frame_parms->get_samples_slot_timestamp(slot+1,frame_parms,0);
             i++) {

995 996 997 998 999 1000 1001 1002 1003
          for (int aa_rx=0; aa_rx<n_rx; aa_rx++) {
            // Apply MIMO Channel and then add noise
            // sum up signals from different Tx antennas
            for (aa=0; aa<n_tx; aa++) {
              r_re[aa_rx][i] += s_re[aa][i];
              r_im[aa_rx][i] += s_im[aa][i];
            }
            ((short*) UE->common_vars.rxdata[aa_rx])[2*i]   = (short) ((r_re[aa_rx][i] + sqrt(sigma2/2)*gaussdouble(0.0,1.0)));
            ((short*) UE->common_vars.rxdata[aa_rx])[2*i+1] = (short) ((r_im[aa_rx][i] + sqrt(sigma2/2)*gaussdouble(0.0,1.0)));
1004
            /* Add phase noise if enabled */
1005
            if (pdu_bit_map & 0x1) {
1006 1007
              phase_noise(ts, &((short*) UE->common_vars.rxdata[aa_rx])[2*i],
                          &((short*) UE->common_vars.rxdata[aa_rx])[2*i+1]);
1008
            }
1009
          }
1010
        }
1011

1012 1013 1014 1015
        nr_ue_dcireq(&dcireq); //to be replaced with function pointer later
        nr_ue_scheduled_response(&scheduled_response);
        
        phy_procedures_nrUE_RX(UE,
1016 1017
                               &UE_proc,
                               0,
1018 1019
                               normal_txrx,
                               dlsch_threads);
1020
        
1021
        //printf("dlsim round %d ends\n",round);
1022 1023
        round++;
      } // round
1024

1025 1026 1027
      //----------------------------------------------------------
      //---------------------- count errors ----------------------
      //----------------------------------------------------------
1028 1029 1030

      if (UE->dlsch[UE_proc.thread_id][0][0]->last_iteration_cnt >=
        UE->dlsch[UE_proc.thread_id][0][0]->max_ldpc_iterations+1)
1031
        n_errors++;
1032 1033

      NR_UE_PDSCH **pdsch_vars = UE->pdsch_vars[UE_proc.thread_id];
1034
      int16_t *UE_llr = pdsch_vars[0]->llr[0];
1035

1036
      TBS                  = UE_harq_process->TBS;//rel15->TBSize[0];
1037
      uint16_t length_dmrs = get_num_dmrs(rel15->dlDmrsSymbPos);
1038 1039 1040 1041
      uint16_t nb_rb       = rel15->rbSize;
      uint8_t  nb_re_dmrs  = rel15->dmrsConfigType == NFAPI_NR_DMRS_TYPE1 ? 6 : 4;
      uint8_t  mod_order   = rel15->qamModOrder[0];
      uint8_t  nb_symb_sch = rel15->NrOfSymbols;
1042

1043
      available_bits = nr_get_G(nb_rb, nb_symb_sch, nb_re_dmrs, length_dmrs, mod_order, rel15->nrOfLayers);
1044
      if(pdu_bit_map & 0x1) {
1045
        available_bits-= (ptrsSymbPerSlot * ptrsRePerSymb *rel15->nrOfLayers* 2);
1046
        printf("[DLSIM][PTRS] Available bits are: %5u, removed PTRS bits are: %5u \n",available_bits, (ptrsSymbPerSlot * ptrsRePerSymb *rel15->nrOfLayers* 2) );
1047
      }
1048 1049
      
      for (i = 0; i < available_bits; i++) {
Raymond Knopp's avatar
Raymond Knopp committed
1050
	
1051 1052 1053 1054 1055 1056
	if(((gNB_dlsch->harq_processes[harq_pid]->f[i] == 0) && (UE_llr[i] <= 0)) || 
	   ((gNB_dlsch->harq_processes[harq_pid]->f[i] == 1) && (UE_llr[i] >= 0)))
	  {
	    if(errors_scrambling == 0) {
	      LOG_D(PHY,"\n");
	      LOG_D(PHY,"First bit in error in unscrambling = %d\n",i);
Raymond Knopp's avatar
Raymond Knopp committed
1057
	    }
1058
	    errors_scrambling++;
Raymond Knopp's avatar
Raymond Knopp committed
1059 1060
	  }
	
1061 1062
      }
      for (i = 0; i < TBS; i++) {
1063

1064 1065
	estimated_output_bit[i] = (UE_harq_process->b[i/8] & (1 << (i & 7))) >> (i & 7);
	test_input_bit[i]       = (gNB_dlsch->harq_processes[harq_pid]->b[i / 8] & (1 << (i & 7))) >> (i & 7); // Further correct for multiple segments
Raymond Knopp's avatar
Raymond Knopp committed
1066
	
1067 1068 1069 1070
	if (estimated_output_bit[i] != test_input_bit[i]) {
	  if(errors_bit == 0)
	    LOG_D(PHY,"First bit in error in decoding = %d (errors scrambling %d)\n",i,errors_scrambling);
	  errors_bit++;
Raymond Knopp's avatar
Raymond Knopp committed
1071 1072
	}
	
1073 1074 1075 1076 1077 1078
      }
      
      ////////////////////////////////////////////////////////////
      
      if (errors_scrambling > 0) {
	if (n_trials == 1)
1079
	  printf("errors_scrambling = %u/%u (trial %d)\n", errors_scrambling, available_bits,trial);
1080 1081 1082 1083 1084 1085 1086
      }
      
      if (errors_bit > 0) {
	n_false_positive++;
	if (n_trials == 1)
	  printf("errors_bit = %u (trial %d)\n", errors_bit, trial);
      }
1087
      roundStats[snrRun]+=((float)round); 
1088
      if (UE_harq_process->harq_ack.ack==1) effRate += ((float)TBS)/round;
Ahmed Hussein's avatar
Ahmed Hussein committed
1089
    } // noise trials
1090

1091
    roundStats[snrRun]/=((float)n_trials);
1092
    effRate /= n_trials;
Ahmed Hussein's avatar
Ahmed Hussein committed
1093 1094
    printf("*****************************************\n");
    printf("SNR %f, (false positive %f)\n", SNR,
Sakthivel Velumani's avatar
Sakthivel Velumani committed
1095
           (float) n_errors / (float) n_trials);
Ahmed Hussein's avatar
Ahmed Hussein committed
1096 1097
    printf("*****************************************\n");
    printf("\n");
1098
    dump_pdsch_stats(gNB);
1099
    printf("SNR %f : n_errors (negative CRC) = %d/%d, Avg round %.2f, Channel BER %e, Eff Rate %.4f bits/slot, Eff Throughput %.2f, TBS %u bits/slot\n", SNR, n_errors, n_trials,roundStats[snrRun],(double)errors_scrambling/available_bits/n_trials,effRate,effRate/TBS*100,TBS);
Ahmed Hussein's avatar
Ahmed Hussein committed
1100
    printf("\n");
1101

1102
    if (print_perf==1) {
1103
      printf("\ngNB TX function statistics (per %d us slot, NPRB %d, mcs %d, TBS %d, Kr %d (Zc %d))\n",
1104
	     1000>>*scc->ssbSubcarrierSpacing, g_rbSize, g_mcsIndex,
1105 1106 1107
	     gNB->dlsch[0][0]->harq_processes[0]->pdsch_pdu.pdsch_pdu_rel15.TBSize[0]<<3,
	     gNB->dlsch[0][0]->harq_processes[0]->K,
	     gNB->dlsch[0][0]->harq_processes[0]->K/((gNB->dlsch[0][0]->harq_processes[0]->pdsch_pdu.pdsch_pdu_rel15.TBSize[0]<<3)>3824?22:10));
1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135
      printDistribution(&gNB->phy_proc_tx,table_tx,"PHY proc tx");
      printStatIndent2(&gNB->dlsch_encoding_stats,"DLSCH encoding time");
      printStatIndent3(&gNB->dlsch_segmentation_stats,"DLSCH segmentation time");
      printStatIndent3(&gNB->tinput,"DLSCH LDPC input processing time");
      printStatIndent3(&gNB->tprep,"DLSCH LDPC input preparation time");
      printStatIndent3(&gNB->tparity,"DLSCH LDPC parity generation time");
      printStatIndent3(&gNB->toutput,"DLSCH LDPC output generation time");
      printStatIndent3(&gNB->dlsch_rate_matching_stats,"DLSCH Rate Mataching time");
      printStatIndent3(&gNB->dlsch_interleaving_stats,  "DLSCH Interleaving time");
      printStatIndent2(&gNB->dlsch_modulation_stats,"DLSCH modulation time");
      printStatIndent2(&gNB->dlsch_scrambling_stats,  "DLSCH scrambling time");


      printf("\nUE RX function statistics (per %d us slot)\n",1000>>*scc->ssbSubcarrierSpacing);
      /*
      printDistribution(&phy_proc_rx_tot, table_rx,"Total PHY proc rx");
      printStatIndent(&ue_front_end_tot,"Front end processing");
      printStatIndent(&dlsch_llr_tot,"rx_pdsch processing");
      printStatIndent2(&pdsch_procedures_tot,"pdsch processing");
      printStatIndent2(&dlsch_procedures_tot,"dlsch processing");
      printStatIndent2(&UE->crnti_procedures_stats,"C-RNTI processing");
      printStatIndent(&UE->ofdm_demod_stats,"ofdm demodulation");
      printStatIndent(&UE->dlsch_channel_estimation_stats,"DLSCH channel estimation time");
      printStatIndent(&UE->dlsch_freq_offset_estimation_stats,"DLSCH frequency offset estimation time");
      printStatIndent(&dlsch_decoding_tot, "DLSCH Decoding time ");
      printStatIndent(&UE->dlsch_unscrambling_stats,"DLSCH unscrambling time");
      printStatIndent(&UE->dlsch_rate_unmatching_stats,"DLSCH Rate Unmatching");
      printf("|__ DLSCH Turbo Decoding(%d bits), avg iterations: %.1f       %.2f us (%d cycles, %d trials)\n",
1136 1137 1138
	     UE->dlsch[UE_proc.thread_id][0][0]->harq_processes[0]->Cminus ?
	     UE->dlsch[UE_proc.thread_id][0][0]->harq_processes[0]->Kminus :
	     UE->dlsch[UE_proc.thread_id][0][0]->harq_processes[0]->Kplus,
1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151
	     UE->dlsch_tc_intl1_stats.trials/(double)UE->dlsch_tc_init_stats.trials,
	     (double)UE->dlsch_turbo_decoding_stats.diff/UE->dlsch_turbo_decoding_stats.trials*timeBase,
	     (int)((double)UE->dlsch_turbo_decoding_stats.diff/UE->dlsch_turbo_decoding_stats.trials),
	     UE->dlsch_turbo_decoding_stats.trials);
      printStatIndent2(&UE->dlsch_tc_init_stats,"init");
      printStatIndent2(&UE->dlsch_tc_alpha_stats,"alpha");
      printStatIndent2(&UE->dlsch_tc_beta_stats,"beta");
      printStatIndent2(&UE->dlsch_tc_gamma_stats,"gamma");
      printStatIndent2(&UE->dlsch_tc_ext_stats,"ext");
      printStatIndent2(&UE->dlsch_tc_intl1_stats,"turbo internal interleaver");
      printStatIndent2(&UE->dlsch_tc_intl2_stats,"intl2+HardDecode+CRC");
      */
    }
1152 1153 1154 1155 1156 1157 1158 1159

    if (n_trials == 1) {
      
      LOG_M("rxsig0.m","rxs0", UE->common_vars.rxdata[0], frame_length_complex_samples, 1, 1);
      if (UE->frame_parms.nb_antennas_rx>1)
	LOG_M("rxsig1.m","rxs1", UE->common_vars.rxdata[1], frame_length_complex_samples, 1, 1);
      LOG_M("chestF0.m","chF0",UE->pdsch_vars[0][0]->dl_ch_estimates_ext,N_RB_DL*12*14,1,1);
      write_output("rxF_comp.m","rxFc",&UE->pdsch_vars[0][0]->rxdataF_comp0[0][0],N_RB_DL*12*14,1,1);
1160
      LOG_M("rxF_llr.m","rxFllr",UE->pdsch_vars[UE_proc.thread_id][0]->llr[0],available_bits,1,0);
1161 1162 1163 1164
      break;
    }

    //if ((float)n_errors/(float)n_trials <= target_error_rate) {
1165
    if (effRate > (eff_tp_check*TBS)) {
1166 1167 1168 1169
      printf("PDSCH test OK\n");
      break;
    }

1170
    snrRun++;
1171 1172
  } // NSR

1173
  /*if (n_trials>1) {
1174 1175 1176 1177 1178 1179
    printf("HARQ stats:\nSNR\tRounds\n");
    psnr = snr0;
    for (uint8_t i=0; i<snrRun; i++) {
      printf("%.1f\t%.2f\n",psnr,roundStats[i]);
      psnr+=0.2;
    }
1180
  }*/
1181

1182
  for (i = 0; i < n_tx; i++) {
1183 1184
    free(s_re[i]);
    free(s_im[i]);
1185 1186 1187
    free(txdata[i]);
  }
  for (i = 0; i < n_rx; i++) {
1188 1189 1190 1191 1192 1193 1194 1195 1196
    free(r_re[i]);
    free(r_im[i]);
  }

  free(s_re);
  free(s_im);
  free(r_re);
  free(r_im);
  free(txdata);
Ahmed Hussein's avatar
Ahmed Hussein committed
1197 1198 1199
  free(test_input_bit);
  free(estimated_output_bit);
  
1200 1201 1202 1203 1204 1205
  if (output_fd)
    fclose(output_fd);

  if (input_fd)
    fclose(input_fd);

1206 1207
  if (scg_fd)
    fclose(scg_fd);
1208
  return(n_errors);
Raymond Knopp's avatar
Raymond Knopp committed
1209
  
1210
}
1211 1212


1213
void update_ptrs_config(NR_CellGroupConfig_t *secondaryCellGroup, uint16_t *rbSize, uint8_t *mcsIndex, int8_t *ptrs_arg)
1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226
{
  NR_BWP_Downlink_t *bwp=secondaryCellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.array[0];
  int *ptrsFreqDenst = calloc(2, sizeof(long));
  ptrsFreqDenst[0]= 25;
  ptrsFreqDenst[1]= 115;
  int *ptrsTimeDenst = calloc(3, sizeof(long));
  ptrsTimeDenst[0]= 2;
  ptrsTimeDenst[1]= 4;
  ptrsTimeDenst[2]= 10;

  int epre_Ratio = 0;
  int reOffset = 0;

1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238
  if(ptrs_arg[0] ==0) {
    ptrsTimeDenst[2]= *mcsIndex -1;
  }
  else if(ptrs_arg[0] == 1) {
    ptrsTimeDenst[1]= *mcsIndex - 1;
    ptrsTimeDenst[2]= *mcsIndex + 1;
  }
  else if(ptrs_arg[0] ==2) {
    ptrsTimeDenst[0]= *mcsIndex - 1;
    ptrsTimeDenst[1]= *mcsIndex + 1;
  }
  else {
1239 1240 1241
    printf("[DLSIM] Wrong L_PTRS value, using default values 1\n");
  }
  /* L = 4 if Imcs < MCS4 */
1242 1243 1244 1245 1246 1247 1248 1249 1250 1251
  if(ptrs_arg[1] ==2) {
    ptrsFreqDenst[0]= *rbSize - 1;
    ptrsFreqDenst[1]= *rbSize + 1;
  }
  else if(ptrs_arg[1] == 4) {
    ptrsFreqDenst[1]= *rbSize - 1;
  }
  else {
    printf("[DLSIM] Wrong K_PTRS value, using default values 2\n");
  }
1252
  printf("[DLSIM] PTRS Enabled with L %d, K %d \n", 1<<ptrs_arg[0], ptrs_arg[1] );
1253 1254 1255 1256
  /* overwrite the values */
  rrc_config_dl_ptrs_params(bwp, ptrsFreqDenst, ptrsTimeDenst, &epre_Ratio, &reOffset);
}

1257 1258 1259 1260
void update_dmrs_config(NR_CellGroupConfig_t *scg,PHY_VARS_NR_UE *ue, int8_t* dmrs_arg)
{
  int8_t  mapping_type = typeA;//default value
  int8_t  add_pos = pdsch_dmrs_pos0;//default value
1261
  if(dmrs_arg[0] == 0) {
1262 1263
    mapping_type = typeA;
  }
1264
  else if (dmrs_arg[0] == 1) {
1265 1266 1267
    mapping_type = typeB;
  }
  /* Additional DMRS positions 0 ,1 and 2 */
1268
  if(dmrs_arg[1] >= 0 && dmrs_arg[1] <3 ) {
1269 1270
    add_pos = dmrs_arg[1];
  }
1271

1272
  if(scg != NULL) {
1273 1274
    NR_BWP_Downlink_t *bwp = scg->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.array[0];
    *bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->dmrs_AdditionalPosition = add_pos;
1275
    for (int i=0;i<bwp->bwp_Common->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list.count;i++) {
1276 1277 1278
      bwp->bwp_Common->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list.array[i]->mappingType = mapping_type; 
    }
  }
1279 1280
  if(ue != NULL) {
    for (int i=0;i<MAX_NR_OF_DL_ALLOCATIONS;i++) {
1281 1282 1283 1284 1285 1286
      ue->PDSCH_Config.pdsch_TimeDomainResourceAllocation[i]->mappingType = mapping_type;
    }
    ue->dmrs_DownlinkConfig.pdsch_dmrs_AdditionalPosition = add_pos;
  }
  printf("[DLSIM] DMRS Config is modified with Mapping Type %d, Additional Positions %d \n", dmrs_arg[0], dmrs_arg[1] );
}