dlsim.c 44.9 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 102 103 104
void nr_rrc_ue_generate_RRCSetupRequest(module_id_t module_id, const uint8_t gNB_index)
{
  return;
}

105 106 107 108 109 110 111 112 113 114
int8_t nr_mac_rrc_data_req_ue(const module_id_t Mod_idP,
                              const int         CC_id,
                              const uint8_t     gNB_id,
                              const frame_t     frameP,
                              const rb_id_t     Srb_id,
                              uint8_t           *buffer_pP)
{
  return 0;
}

115 116
void
rrc_data_ind(
117
  const protocol_ctxt_t *const ctxt_pP,
118 119 120 121 122 123 124 125 126 127 128 129 130 131 132
  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;
}
133

134 135 136 137 138 139 140 141
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;
}
142

heshanyun's avatar
heshanyun committed
143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168
int
gtpv1u_create_ngu_tunnel(
  const instance_t instanceP,
  const gtpv1u_gnb_create_tunnel_req_t *  const create_tunnel_req_pP,
        gtpv1u_gnb_create_tunnel_resp_t * const create_tunnel_resp_pP){
  return 0;
}

int
gtpv1u_update_ngu_tunnel(
  const instance_t                              instanceP,
  const gtpv1u_gnb_create_tunnel_req_t *const  create_tunnel_req_pP,
  const rnti_t                                  prior_rnti
){
  return 0;
}

int
nr_rrc_gNB_process_GTPV1U_CREATE_TUNNEL_RESP(
  const protocol_ctxt_t *const ctxt_pP,
  const gtpv1u_gnb_create_tunnel_resp_t *const create_tunnel_resp_pP,
  uint8_t                         *inde_list
){
  return 0;
}

169 170
void config_common(int Mod_idP,
                   int pdsch_AntennaPorts, 
171
		   NR_ServingCellConfigCommon_t *scc
Raymond Knopp's avatar
Raymond Knopp committed
172
		   );
173

174 175 176 177 178 179 180 181 182
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;}
183

184
// Dummy function to avoid linking error at compilation of nr-dlsim
185 186 187 188 189
int is_x2ap_enabled(void)
{
  return 0;
}

Mahesh's avatar
Mahesh committed
190 191 192 193 194 195 196
//nFAPI P7 dummy functions

int oai_nfapi_dl_tti_req(nfapi_nr_dl_tti_request_t *dl_config_req) { return(0);  }
int oai_nfapi_tx_data_req(nfapi_nr_tx_data_request_t *tx_data_req){ return(0);  }
int oai_nfapi_ul_dci_req(nfapi_nr_ul_dci_request_t *ul_dci_req){ return(0);  }
int oai_nfapi_ul_tti_req(nfapi_nr_ul_tti_request_t *ul_tti_req){ return(0);  }

197
// needed for some functions
198
openair0_config_t openair0_cfg[MAX_CARDS];
199 200
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);
201

202 203
/* 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 */
204
int g_mcsIndex = -1, g_mcsTableIdx = 0, g_rbStart = -1, g_rbSize = -1;
205 206
void nr_dlsim_preprocessor(module_id_t module_id,
                           frame_t frame,
207
                           sub_frame_t slot) {
208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226
  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;

  sched_ctrl->rbStart = g_rbStart;
  sched_ctrl->rbSize = g_rbSize;
  sched_ctrl->mcs = g_mcsIndex;
  sched_ctrl->time_domain_allocation = 2;
227
  sched_ctrl->mcsTableIdx = g_mcsTableIdx;
228 229 230 231 232 233 234 235 236 237 238 239 240 241
  /* the simulator assumes the HARQ PID is equal to the slot number */
  sched_ctrl->dl_harq_pid = slot;
  /* The scheduler uses lists to track whether a HARQ process is
   * free/busy/awaiting retransmission, and updates the HARQ process states.
   * However, in the simulation, we never get ack or nack for any HARQ process,
   * thus the list and HARQ states don't match what the scheduler expects.
   * Therefore, below lines just "repair" everything so that the scheduler
   * won't remark that there is no HARQ feedback */
  sched_ctrl->feedback_dl_harq.head = -1; // always overwrite feedback HARQ process
  if (sched_ctrl->harq_processes[slot].round == 0) // depending on round set in simulation ...
    add_front_nr_list(&sched_ctrl->available_dl_harq, slot); // ... make PID available
  else
    add_front_nr_list(&sched_ctrl->retrans_dl_harq, slot);   // ... make PID retransmission
  sched_ctrl->harq_processes[slot].is_waiting = false;
242 243 244
  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);
245
  AssertFatal(sched_ctrl->mcsTableIdx >= 0 && sched_ctrl->mcsTableIdx <= 2, "invalid sched_ctrl->mcsTableIdx %d\n", sched_ctrl->mcsTableIdx);
246 247
  sched_ctrl->numDmrsCdmGrpsNoData = 1;
}
248 249


250 251 252
int main(int argc, char **argv)
{
  char c;
253
  int i,aa;//,l;
254
  double sigma2, sigma2_dB=10, SNR, snr0=-2.0, snr1=2.0;
255
  uint8_t snr1set=0;
256
  float roundStats[50];
257
  float effRate;
Francesco Mani's avatar
Francesco Mani committed
258
  //float psnr;
259
  float eff_tp_check = 0.7;
260
  uint8_t snrRun;
261
  uint32_t TBS;
262 263
  int **txdata;
  double **s_re,**s_im,**r_re,**r_im;
264 265
  //double iqim = 0.0;
  //unsigned char pbch_pdu[6];
266 267 268
  //  int sync_pos, sync_pos_slot;
  //  FILE *rx_frame_file;
  FILE *output_fd = NULL;
269
  //uint8_t write_output_file=0;
270
  //int result;
271
  //int freq_offset;
272
  //  int subframe_offset;
273
  //  char fname[40], vname[40];
Ahmed Hussein's avatar
Ahmed Hussein committed
274
  int trial, n_trials = 1, n_errors = 0, n_false_positive = 0;
275
  //int n_errors2, n_alamouti;
276
  uint8_t transmission_mode = 1,n_tx=1,n_rx=1;
277 278
  uint8_t round;
  uint8_t num_rounds = 4;
279 280

  channel_desc_t *gNB2UE;
281 282 283
  //uint32_t nsymb,tx_lev,tx_lev1 = 0,tx_lev2 = 0;
  //uint8_t extended_prefix_flag=0;
  //int8_t interf1=-21,interf2=-21;
284 285

  FILE *input_fd=NULL,*pbch_file_fd=NULL;
286
  //char input_val_str[50],input_val_str2[50];
287

288
  //uint8_t frame_mod4,num_pdcch_symbols = 0;
289 290 291

  SCM_t channel_model=AWGN;//Rayleigh1_anticorr;

Laurent's avatar
Laurent committed
292
  NB_UE_INST = 1;
293 294
  //double pbch_sinr;
  //int pbch_tx_ant;
Ahmed Hussein's avatar
Ahmed Hussein committed
295
  int N_RB_DL=106,mu=1;
296

297
  //unsigned char frame_type = 0;
298

299
  int frame=1,slot=1;
300
  int frame_length_complex_samples;
301
  //int frame_length_complex_samples_no_prefix;
302 303 304 305 306
  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;
307
  int cyclic_prefix_type = NFAPI_CP_NORMAL;
308
  int run_initial_sync=0;
309 310
  int pusch_tgt_snrx10 = 200;
  int pucch_tgt_snrx10 = 200;
Raymond Knopp's avatar
Raymond Knopp committed
311
  int loglvl=OAILOG_INFO;
312

313
  //float target_error_rate = 0.01;
314
  int css_flag=0;
315 316

  cpuf = get_cpu_freq_GHz();
317 318 319 320
  int8_t enable_ptrs = 0;
  int8_t modify_dmrs = 0;

  int8_t dmrs_arg[2] = {-1,-1};// Invalid values
321
  /* L_PTRS = ptrs_arg[0], K_PTRS = ptrs_arg[1] */
322 323
  int8_t ptrs_arg[2] = {-1,-1};// Invalid values

324 325 326 327 328 329
  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;
330
  uint8_t  dlsch_threads = 0;
331
  if ( load_configmodule(argc,argv,CONFIG_ENABLECMDLINEONLY) == 0) {
yilmazt's avatar
yilmazt committed
332
    exit_fun("[NR_DLSIM] Error, configuration module init failed\n");
333 334 335 336
  }

  randominit(0);

337
  int print_perf             = 0;
338

339 340
  FILE *scg_fd=NULL;
  
341
  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) {
342
    switch (c) {
343 344
    case 'f':
      scg_fd = fopen(optarg,"r");
345

346
      if (scg_fd==NULL) {
347 348 349
        printf("Error opening %s\n",optarg);
        exit(-1);
      }
350
      break;
351

352
    /*case 'd':
353
      frame_type = 1;
354
      break;*/
355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386

    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:
387
        printf("Unsupported channel model!\n");
388 389 390 391 392
        exit(-1);
      }

      break;

393
    /*case 'i':
394 395 396 397 398
      interf1=atoi(optarg);
      break;

    case 'j':
      interf2=atoi(optarg);
399
      break;*/
400 401 402 403 404 405 406

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

    case 's':
      snr0 = atof(optarg);
407
      printf("Setting SNR0 to %f\n",snr0);
408 409 410 411 412
      break;

    case 'S':
      snr1 = atof(optarg);
      snr1set=1;
413
      printf("Setting SNR1 to %f\n",snr1);
414 415 416 417 418 419 420
      break;

      /*
      case 't':
      Td= atof(optarg);
      break;
      */
421
    /*case 'p':
422
      extended_prefix_flag=1;
423
      break;*/
424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439

      /*
      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)) {
440
        printf("Unsupported transmission mode %d\n",transmission_mode);
441 442 443 444 445 446 447 448 449
        exit(-1);
      }

      break;

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

      if ((n_tx==0) || (n_tx>2)) {
450
        printf("Unsupported number of tx antennas %d\n",n_tx);
451 452 453 454 455 456 457 458 459
        exit(-1);
      }

      break;

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

      if ((n_rx==0) || (n_rx>2)) {
460
        printf("Unsupported number of rx antennas %d\n",n_rx);
461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480
        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':
481 482
      print_perf=1;
      opp_enabled=1;
483 484 485 486
      break;
      
    case 'I':
      run_initial_sync=1;
487
      //target_error_rate=0.1;
488
      slot = 0;
489 490 491 492 493 494
      break;

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

495

496 497 498
    case 'E':
	css_flag=1;
	break;
499

500

501
    case 'a':
502
      g_rbStart = atoi(optarg);
503 504 505
      break;

    case 'b':
506
      g_rbSize = atoi(optarg);
507
      break;
508 509 510
    case 'd':
      dlsch_threads = atoi(optarg);
      break;    
511
    case 'e':
512
      g_mcsIndex = atoi(optarg);
513 514
      break;

515 516 517 518 519
    case 'q':
      g_mcsTableIdx = 1;
      get_softmodem_params()->use_256qam_table = 1;
      break;

520 521 522
    case 'm':
      mu = atoi(optarg);
      break;
523

524 525 526 527
    case 't':
      eff_tp_check = (float)atoi(optarg)/100;
      break;

528 529 530
    case 'w':
      output_fd = fopen("txdata.dat", "w+");
      break;
Sakthivel Velumani's avatar
Sakthivel Velumani committed
531

532 533 534 535 536 537 538
    case 'T':
      enable_ptrs=1;
      for(i=0; i < atoi(optarg); i++) {
        ptrs_arg[i] = atoi(argv[optind++]);
      }
      break;

539 540
    case 'U':
      modify_dmrs = 1;
541
      for(i=0; i < atoi(optarg); i++) {
542 543 544
        dmrs_arg[i] = atoi(argv[optind++]);
      }
      break;
Sakthivel Velumani's avatar
Sakthivel Velumani committed
545

546 547 548 549 550
    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");
551 552
      //printf("-p Use extended prefix mode\n");
      //printf("-d Use TDD\n");
553 554 555 556 557
      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");
558
      printf("-y Number of TX antennas used in gNB\n");
559
      printf("-z Number of RX antennas used in UE\n");
560 561
      //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");
562 563 564
      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");
565
      //printf("-C Generate Calibration information for Abstraction (effective SNR adjustment to remove Pe bias w.r.t. AWGN)\n");
566
      printf("-f raw file containing RRC configuration (generated by gNB)\n");
567
      printf("-F Input filename (.txt format) for RX conformance testing\n");
568
      printf("-E used CSS scheduler\n");
569
      printf("-o CORESET offset\n");
570 571
      printf("-a Start PRB for PDSCH\n");
      printf("-b Number of PRB for PDSCH\n");
572 573
      printf("-c Start symbol for PDSCH (fixed for now)\n");
      printf("-j Number of symbols for PDSCH (fixed for now)\n");
574
      printf("-e MSC index\n");
575
      printf("-q Use 2nd MCS table (256 QAM table) for PDSCH\n");
576
      printf("-t Acceptable effective throughput (in percentage)\n");
577
      printf("-T Enable PTRS, arguments list L_PTRS{0,1,2} K_PTRS{2,4}, e.g. -T 2 0 2 \n");
578
      printf("-U Change DMRS Config, arguments list DMRS TYPE{0=A,1=B} DMRS AddPos{0:2}, e.g. -U 2 0 2 \n");
579
      printf("-P Print DLSCH performances\n");
Sakthivel Velumani's avatar
Sakthivel Velumani committed
580
      printf("-w Write txdata to binary file (one frame)\n");
581
      printf("-d number of dlsch threads, 0: no dlsch parallelization\n");
582 583 584 585
      exit (-1);
      break;
    }
  }
586

587 588 589
  logInit();
  set_glog(loglvl);
  T_stdout = 1;
590 591
  /* initialize the sin table */
  InitSinLUT();
592

593 594
  get_softmodem_params()->phy_test = 1;
  
595 596
  if (snr1set==0)
    snr1 = snr0+10;
597
  init_dlsch_tpool(dlsch_threads);
598 599


600 601 602
  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
603

604
  gNB = RC.gNB[0];
605 606 607 608 609 610
  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
611
  RC.nb_nr_macrlc_inst = 1;
cig's avatar
cig committed
612 613 614
  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
615 616
  mac_top_init_gNB();
  gNB_mac = RC.nrmac[0];
617
  gNB_mac->pre_processor_dl = nr_dlsim_preprocessor;
Raymond Knopp's avatar
Raymond Knopp committed
618
  gNB_RRC_INST rrc;
Raymond Knopp's avatar
Raymond Knopp committed
619
  memset((void*)&rrc,0,sizeof(rrc));
620

621
  /*
Raymond Knopp's avatar
Raymond Knopp committed
622
  // read in SCGroupConfig
Raymond Knopp's avatar
Raymond Knopp committed
623
  AssertFatal(scg_fd != NULL,"no reconfig.raw file\n");
Raymond Knopp's avatar
Raymond Knopp committed
624 625 626 627
  char buffer[1024];
  int msg_len=fread(buffer,1,1024,scg_fd);
  NR_RRCReconfiguration_t *NR_RRCReconfiguration;

Raymond Knopp's avatar
Raymond Knopp committed
628
  printf("Decoding NR_RRCReconfiguration (%d bytes)\n",msg_len);
Raymond Knopp's avatar
Raymond Knopp committed
629 630 631 632 633 634 635 636 637 638 639 640 641 642
  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
643 644
  AssertFatal(NR_RRCReconfiguration->criticalExtensions.present == NR_RRCReconfiguration__criticalExtensions_PR_rrcReconfiguration,"wrong NR_RRCReconfiguration->criticalExstions.present type\n");

Raymond Knopp's avatar
Raymond Knopp committed
645 646 647 648 649 650 651 652 653 654 655 656 657 658 659
  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);
  }      
  
660 661
  NR_ServingCellConfigCommon_t *scc = secondaryCellGroup->spCellConfig->reconfigurationWithSync->spCellConfigCommon;
  */
Raymond Knopp's avatar
Raymond Knopp committed
662

663 664 665 666 667 668 669 670 671

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

Francesco Mani's avatar
Francesco Mani committed
672 673
  fix_scc(scc,ssb_bitmap);

674 675 676 677 678 679 680
  fill_default_secondaryCellGroup(scc,
				  secondaryCellGroup,
				  0,
				  1,
				  n_tx,
				  0);

681
  /* -U option modify DMRS */
682
  if(modify_dmrs) {
683 684
    update_dmrs_config(secondaryCellGroup, NULL,dmrs_arg);
  }
685
  /* -T option enable PTRS */
686
  if(enable_ptrs) {
687
    update_ptrs_config(secondaryCellGroup, &rbSize, &mcsIndex, ptrs_arg);
688 689
  }

690

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

Raymond Knopp's avatar
Raymond Knopp committed
693 694
  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
695
  // common configuration
696
  rrc_mac_config_req_gNB(0,0,1,pusch_tgt_snrx10,pucch_tgt_snrx10,scc,0,0,NULL);
Raymond Knopp's avatar
Raymond Knopp committed
697
  // UE dedicated configuration
698
  rrc_mac_config_req_gNB(0,0,1,pusch_tgt_snrx10,pucch_tgt_snrx10,NULL,1,secondaryCellGroup->spCellConfig->reconfigurationWithSync->newUE_Identity,secondaryCellGroup);
Raymond Knopp's avatar
Raymond Knopp committed
699
  phy_init_nr_gNB(gNB,0,0);
700
  N_RB_DL = gNB->frame_parms.N_RB_DL;
701 702 703
  NR_UE_info_t *UE_info = &RC.nrmac[0]->UE_info;
  UE_info->num_UEs=1;

Raymond Knopp's avatar
Raymond Knopp committed
704
  // stub to configure frame_parms
Raymond Knopp's avatar
Raymond Knopp committed
705
  //  nr_phy_config_request_sim(gNB,N_RB_DL,N_RB_DL,mu,Nid_cell,SSB_positions);
Raymond Knopp's avatar
Raymond Knopp committed
706 707
  // call MAC to configure common parameters

708 709 710 711 712 713
  /* 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
714

715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732
  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;
  }
733 734 735 736
  else if (mu == 3 && N_RB_DL == 66) {
    fs = 122.88e6;
    bw = 100e6;
  }
737 738 739 740
  else if (mu == 3 && N_RB_DL == 32) {
    fs = 61.44e6;
    bw = 50e6;
  }
741 742 743 744 745
  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,
746 747
 				fs,
				bw,
748
				30e-9,
749 750 751 752 753
                                0,
                                0,
                                0);

  if (gNB2UE==NULL) {
754
    printf("Problem generating channel model. Exiting.\n");
755 756 757 758
    exit(-1);
  }

  frame_length_complex_samples = frame_parms->samples_per_subframe*NR_NUMBER_OF_SUBFRAMES_PER_FRAME;
759
  //frame_length_complex_samples_no_prefix = frame_parms->samples_per_subframe_wCP*NR_NUMBER_OF_SUBFRAMES_PER_FRAME;
760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780

  s_re = malloc(2*sizeof(double*));
  s_im = malloc(2*sizeof(double*));
  r_re = malloc(2*sizeof(double*));
  r_im = malloc(2*sizeof(double*));
  txdata = malloc(2*sizeof(int*));

  for (i=0; i<2; i++) {

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

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

    printf("Allocating %d samples for txdata\n",frame_length_complex_samples);
    txdata[i] = malloc(frame_length_complex_samples*sizeof(int));
781
    bzero(txdata[i],frame_length_complex_samples*sizeof(int));
782 783 784 785 786 787 788 789 790 791
  
  }

  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
792
  memset((void*)UE,0,sizeof(PHY_VARS_NR_UE));
793 794 795 796
  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));
Raymond Knopp's avatar
Raymond Knopp committed
797

798
  if (run_initial_sync==1)  UE->is_synchronized = 0;
799
  else                      {UE->is_synchronized = 1; UE->UE_mode[0]=PUSCH;}
800 801 802 803 804 805 806 807 808
                      
  UE->perfect_ce = 0;

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

809
  if(modify_dmrs) {
810 811
    update_dmrs_config( NULL,UE,dmrs_arg);
  }
812 813
  init_nr_ue_transport(UE,0);

814
  nr_gold_pbch(UE);
815
  nr_gold_pdcch(UE,0,2);
816

817
  nr_l2_init_ue(NULL);
818
  UE_mac = get_mac_inst(0);
819

820 821 822
  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;
823
  UE->if_inst->dl_indication = nr_ue_dl_indication;
824
  UE->if_inst->ul_indication = dummy_nr_ue_ul_indication;
825

826

827
  UE_mac->if_module = nr_ue_if_module_init(0);
828

829
  unsigned int available_bits=0;
Ahmed Hussein's avatar
Ahmed Hussein committed
830 831 832 833 834
  unsigned char *estimated_output_bit;
  unsigned char *test_input_bit;
  unsigned int errors_bit    = 0;
  uint32_t errors_scrambling = 0;

835

Ahmed Hussein's avatar
Ahmed Hussein committed
836 837
  test_input_bit       = (unsigned char *) malloc16(sizeof(unsigned char) * 16 * 68 * 384);
  estimated_output_bit = (unsigned char *) malloc16(sizeof(unsigned char) * 16 * 68 * 384);
838 839
  
  // generate signal
840 841 842
  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
843

844
  //Configure UE
845 846
  rrc.carrier.MIB = (uint8_t*) malloc(4);
  rrc.carrier.sizeof_MIB = do_MIB_NR(&rrc,0);
847

848
  nr_rrc_mac_config_req_ue(0,0,0,rrc.carrier.mib.message.choice.mib,secondaryCellGroup);
849

850 851 852 853 854 855 856 857

  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;
858
  
859 860 861 862 863 864 865
  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;
866
  scheduled_response.thread_id = UE_proc.thread_id;
Francesco Mani's avatar
Francesco Mani committed
867

868
  nr_ue_phy_config_request(&UE_mac->phy_config);
Francesco Mani's avatar
Francesco Mani committed
869
  //NR_COMMON_channels_t *cc = RC.nrmac[0]->common_channels;
870
  snrRun = 0;
871

872

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

875 876 877 878 879 880 881 882 883 884 885
    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);
886
    reset_meas(&gNB->toutput);
887

888 889
    clear_pdsch_stats(gNB);

890
    n_errors = 0;
891
    effRate = 0;
892 893
    //n_errors2 = 0;
    //n_alamouti = 0;
894
    errors_scrambling=0;
895
    n_false_positive = 0;
896 897
    if (n_trials== 1) num_rounds = 1;

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

900
      errors_bit = 0;
Ahmed Hussein's avatar
Ahmed Hussein committed
901
      //multipath channel
902
      //multipath_channel(gNB2UE,s_re,s_im,r_re,r_im,frame_length_complex_samples,0);
903

904
      UE->rx_offset=0;
905 906 907
      UE_proc.thread_id  = 0;
      UE_proc.frame_rx   = frame;
      UE_proc.nr_slot_rx = slot;
908 909 910
      
      dcireq.frame     = frame;
      dcireq.slot      = slot;
911

912
      NR_UE_DLSCH_t *dlsch0 = UE->dlsch[UE_proc.thread_id][0][0];
913

914
      int harq_pid = slot;
915 916 917
      NR_DL_UE_HARQ_t *UE_harq_process = dlsch0->harq_processes[harq_pid];

      NR_gNB_DLSCH_t *gNB_dlsch = gNB->dlsch[0][0];
918
      nfapi_nr_dl_tti_pdsch_pdu_rel15_t *rel15 = &gNB_dlsch->harq_process.pdsch_pdu.pdsch_pdu_rel15;
919
      
920 921
      UE_harq_process->harq_ack.ack = 0;
      round = 0;
922 923
      UE_harq_process->round = round;
      UE_harq_process->first_tx = 1;
924 925 926 927
        
      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));
928
        clear_nr_nfapi_information(RC.nrmac[0], 0, frame, slot);
929

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

932

933
        UE_info->UE_sched_ctrl[0].harq_processes[harq_pid].round = round;
Sakthivel Velumani's avatar
Sakthivel Velumani committed
934
        for (int i=0; i<MAX_NUM_CORESET; i++)
935
          gNB_mac->UE_info.num_pdcch_cand[0][i] = 0;
936
      
937
        if (css_flag == 0) {
938
          nr_schedule_ue_spec(0, frame, slot);
939 940 941
        } else {
          nr_schedule_css_dlsch_phytest(0,frame,slot);
        }
942 943 944 945 946
        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];
947
        Sched_INFO.UL_tti_req    = gNB_mac->UL_tti_req_ahead[slot];
948 949 950
        Sched_INFO.UL_dci_req  = NULL;
        Sched_INFO.TX_req    = &gNB_mac->TX_req[0];
        nr_schedule_response(&Sched_INFO);
951 952 953 954 955 956

        /* 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;
957
        if(pdu_bit_map & 0x1) {
958 959 960 961 962 963 964
          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);
965
          printf("[DLSIM] PTRS Symbols in a slot: %2u, RE per Symbol: %3u, RE in a slot %4d\n", ptrsSymbPerSlot,ptrsRePerSymb, ptrsSymbPerSlot*ptrsRePerSymb );
966
        }
967 968 969 970 971 972 973 974
        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) {
975
          LOG_M("txsigF0.m","txsF0", &gNB->common_vars.txdataF[0][txdataF_offset],frame_parms->samples_per_slot_wCP,1,1);
976
          if (gNB->frame_parms.nb_antennas_tx>1)
977
          LOG_M("txsigF1.m","txsF1", &gNB->common_vars.txdataF[1][txdataF_offset],frame_parms->samples_per_slot_wCP,1,1);
978 979
        }
        int tx_offset = frame_parms->get_samples_slot_timestamp(slot,frame_parms,0);
980
        if (n_trials==1) printf("tx_offset %d, txdataF_offset %d \n", tx_offset,txdataF_offset);
981

982 983 984
        //TODO: loop over slots
        for (aa=0; aa<gNB->frame_parms.nb_antennas_tx; aa++) {
    
985 986 987 988 989 990 991
          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);
992
          } else {
993 994 995 996 997
            nr_normal_prefix_mod(&gNB->common_vars.txdataF[aa][txdataF_offset],
                                 &txdata[aa][tx_offset],
                                 14,
                                 frame_parms);
          }
998 999 1000
        }
       
        if (n_trials==1) {
1001
          LOG_M("txsig0.m","txs0", &txdata[0][tx_offset],frame_parms->get_samples_slot_timestamp(slot,frame_parms,0),1,1);
1002
          if (gNB->frame_parms.nb_antennas_tx>1)
1003
            LOG_M("txsig1.m","txs1", &txdata[1][tx_offset],frame_parms->get_samples_slot_timestamp(slot,frame_parms,0),1,1);
1004
        }
Sakthivel Velumani's avatar
Sakthivel Velumani committed
1005 1006
        if (output_fd) {
          printf("writing txdata to binary file\n");
1007
          fwrite(txdata[0],sizeof(int32_t),frame_length_complex_samples,output_fd);
Sakthivel Velumani's avatar
Sakthivel Velumani committed
1008
        }
1009

1010
        int txlev = signal_energy(&txdata[0][frame_parms->get_samples_slot_timestamp(slot,frame_parms,0)+5*frame_parms->ofdm_symbol_size + 4*frame_parms->nb_prefix_samples + frame_parms->nb_prefix_samples0], frame_parms->ofdm_symbol_size + frame_parms->nb_prefix_samples);
1011 1012 1013 1014
        
        //  if (n_trials==1) printf("txlev %d (%f)\n",txlev,10*log10((double)txlev));
        
        for (i=(frame_parms->get_samples_slot_timestamp(slot,frame_parms,0)); 
1015 1016 1017 1018 1019 1020 1021
             i<(frame_parms->get_samples_slot_timestamp(slot+1,frame_parms,0)); 
             i++) {
    
          for (aa=0; aa<frame_parms->nb_antennas_tx; aa++) {
            r_re[aa][i] = ((double)(((short *)txdata[aa]))[(i<<1)]);
            r_im[aa][i] = ((double)(((short *)txdata[aa]))[(i<<1)+1]);
          }
1022
        }
1023
        double ts = 1.0/(frame_parms->subcarrier_spacing * frame_parms->ofdm_symbol_size); 
1024 1025 1026 1027 1028 1029
        //AWGN
        sigma2_dB = 10 * log10((double)txlev * ((double)UE->frame_parms.ofdm_symbol_size/(12*rel15->rbSize))) - SNR;
        sigma2    = pow(10, sigma2_dB/10);
        if (n_trials==1) printf("sigma2 %f (%f dB), txlev %f (factor %f)\n",sigma2,sigma2_dB,10*log10((double)txlev),(double)(double)UE->frame_parms.ofdm_symbol_size/(12*rel15->rbSize));
        
        for (i=frame_parms->get_samples_slot_timestamp(slot,frame_parms,0); 
1030 1031 1032 1033 1034 1035
             i<frame_parms->get_samples_slot_timestamp(slot+1,frame_parms,0);
             i++) {

          for (aa=0; aa<frame_parms->nb_antennas_rx; aa++) {
            ((short*) UE->common_vars.rxdata[aa])[2*i]   = (short) ((r_re[aa][i] + sqrt(sigma2/2)*gaussdouble(0.0,1.0)));
            ((short*) UE->common_vars.rxdata[aa])[2*i+1] = (short) ((r_im[aa][i] + sqrt(sigma2/2)*gaussdouble(0.0,1.0)));
1036
            /* Add phase noise if enabled */
1037
            if (pdu_bit_map & 0x1) {
1038 1039 1040
              phase_noise(ts, &((short*) UE->common_vars.rxdata[aa])[2*i],
                          &((short*) UE->common_vars.rxdata[aa])[2*i+1]);
            }
1041
          }
1042
        }
1043

1044 1045 1046 1047
        nr_ue_dcireq(&dcireq); //to be replaced with function pointer later
        nr_ue_scheduled_response(&scheduled_response);
        
        phy_procedures_nrUE_RX(UE,
1048 1049
                               &UE_proc,
                               0,
1050
                               dlsch_threads);
1051
        
1052
        //printf("dlsim round %d ends\n",round);
1053 1054
        round++;
      } // round
1055

1056 1057 1058
      //----------------------------------------------------------
      //---------------------- count errors ----------------------
      //----------------------------------------------------------
1059 1060 1061

      if (UE->dlsch[UE_proc.thread_id][0][0]->last_iteration_cnt >=
        UE->dlsch[UE_proc.thread_id][0][0]->max_ldpc_iterations+1)
1062
        n_errors++;
1063 1064

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

1067
      TBS                  = UE_harq_process->TBS;//rel15->TBSize[0];
1068
      uint16_t length_dmrs = get_num_dmrs(rel15->dlDmrsSymbPos);
1069 1070 1071 1072
      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;
1073

1074
      available_bits = nr_get_G(nb_rb, nb_symb_sch, nb_re_dmrs, length_dmrs, mod_order, rel15->nrOfLayers);
1075
      if(pdu_bit_map & 0x1) {
1076
        available_bits-= (ptrsSymbPerSlot * ptrsRePerSymb *rel15->nrOfLayers* 2);
1077
        printf("[DLSIM][PTRS] Available bits are: %5u, removed PTRS bits are: %5u \n",available_bits, (ptrsSymbPerSlot * ptrsRePerSymb *rel15->nrOfLayers* 2) );
1078
      }
1079 1080
      
      for (i = 0; i < available_bits; i++) {
Raymond Knopp's avatar
Raymond Knopp committed
1081
	
1082 1083
	if(((gNB_dlsch->harq_process.f[i] == 0) && (UE_llr[i] <= 0)) || 
	   ((gNB_dlsch->harq_process.f[i] == 1) && (UE_llr[i] >= 0)))
1084 1085 1086 1087
	  {
	    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
1088
	    }
1089
	    errors_scrambling++;
Raymond Knopp's avatar
Raymond Knopp committed
1090 1091
	  }
	
1092 1093
      }
      for (i = 0; i < TBS; i++) {
1094

1095
	estimated_output_bit[i] = (UE_harq_process->b[i/8] & (1 << (i & 7))) >> (i & 7);
1096
	test_input_bit[i]       = (gNB_dlsch->harq_process.b[i / 8] & (1 << (i & 7))) >> (i & 7); // Further correct for multiple segments
Raymond Knopp's avatar
Raymond Knopp committed
1097
	
1098 1099 1100 1101
	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
1102 1103
	}
	
1104 1105 1106 1107 1108 1109
      }
      
      ////////////////////////////////////////////////////////////
      
      if (errors_scrambling > 0) {
	if (n_trials == 1)
1110
	  printf("errors_scrambling = %u/%u (trial %d)\n", errors_scrambling, available_bits,trial);
1111 1112 1113 1114 1115 1116 1117
      }
      
      if (errors_bit > 0) {
	n_false_positive++;
	if (n_trials == 1)
	  printf("errors_bit = %u (trial %d)\n", errors_bit, trial);
      }
1118
      roundStats[snrRun]+=((float)round); 
1119
      if (UE_harq_process->harq_ack.ack==1) effRate += ((float)TBS)/round;
Ahmed Hussein's avatar
Ahmed Hussein committed
1120
    } // noise trials
1121

1122
    roundStats[snrRun]/=((float)n_trials);
1123
    effRate /= n_trials;
Ahmed Hussein's avatar
Ahmed Hussein committed
1124 1125
    printf("*****************************************\n");
    printf("SNR %f, (false positive %f)\n", SNR,
Sakthivel Velumani's avatar
Sakthivel Velumani committed
1126
           (float) n_errors / (float) n_trials);
Ahmed Hussein's avatar
Ahmed Hussein committed
1127 1128
    printf("*****************************************\n");
    printf("\n");
1129
    dump_pdsch_stats(gNB);
1130
    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
1131
    printf("\n");
1132

1133
    if (print_perf==1) {
1134
      printf("\ngNB TX function statistics (per %d us slot, NPRB %d, mcs %d, TBS %d, Kr %d (Zc %d))\n",
1135
	     1000>>*scc->ssbSubcarrierSpacing, g_rbSize, g_mcsIndex,
1136 1137 1138
	     gNB->dlsch[0][0]->harq_process.pdsch_pdu.pdsch_pdu_rel15.TBSize[0]<<3,
	     gNB->dlsch[0][0]->harq_process.K,
	     gNB->dlsch[0][0]->harq_process.K/((gNB->dlsch[0][0]->harq_process.pdsch_pdu.pdsch_pdu_rel15.TBSize[0]<<3)>3824?22:10));
1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166
      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",
1167 1168 1169
	     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,
1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182
	     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");
      */
    }
1183 1184 1185 1186 1187 1188 1189 1190

    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);
1191
      LOG_M("rxF_llr.m","rxFllr",UE->pdsch_vars[UE_proc.thread_id][0]->llr[0],available_bits,1,0);
1192 1193 1194 1195
      break;
    }

    //if ((float)n_errors/(float)n_trials <= target_error_rate) {
1196
    if (effRate > (eff_tp_check*TBS)) {
1197 1198 1199 1200
      printf("PDSCH test OK\n");
      break;
    }

1201
    snrRun++;
1202 1203
  } // NSR

1204
  /*if (n_trials>1) {
1205 1206 1207 1208 1209 1210
    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;
    }
1211
  }*/
1212

Ahmed Hussein's avatar
Ahmed Hussein committed
1213
  for (i = 0; i < 2; i++) {
1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225
    free(s_re[i]);
    free(s_im[i]);
    free(r_re[i]);
    free(r_im[i]);
    free(txdata[i]);
  }

  free(s_re);
  free(s_im);
  free(r_re);
  free(r_im);
  free(txdata);
Ahmed Hussein's avatar
Ahmed Hussein committed
1226 1227 1228
  free(test_input_bit);
  free(estimated_output_bit);
  
1229 1230 1231 1232 1233 1234
  if (output_fd)
    fclose(output_fd);

  if (input_fd)
    fclose(input_fd);

1235 1236
  if (scg_fd)
    fclose(scg_fd);
1237
  return(n_errors);
Raymond Knopp's avatar
Raymond Knopp committed
1238
  
1239
}
1240 1241


1242
void update_ptrs_config(NR_CellGroupConfig_t *secondaryCellGroup, uint16_t *rbSize, uint8_t *mcsIndex, int8_t *ptrs_arg)
1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255
{
  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;

1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267
  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 {
1268 1269 1270
    printf("[DLSIM] Wrong L_PTRS value, using default values 1\n");
  }
  /* L = 4 if Imcs < MCS4 */
1271 1272 1273 1274 1275 1276 1277 1278 1279 1280
  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");
  }
1281
  printf("[DLSIM] PTRS Enabled with L %d, K %d \n", 1<<ptrs_arg[0], ptrs_arg[1] );
1282 1283 1284 1285
  /* overwrite the values */
  rrc_config_dl_ptrs_params(bwp, ptrsFreqDenst, ptrsTimeDenst, &epre_Ratio, &reOffset);
}

1286 1287 1288 1289
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
1290
  if(dmrs_arg[0] == 0) {
1291 1292
    mapping_type = typeA;
  }
1293
  else if (dmrs_arg[0] == 1) {
1294 1295 1296
    mapping_type = typeB;
  }
  /* Additional DMRS positions 0 ,1 and 2 */
1297
  if(dmrs_arg[1] >= 0 && dmrs_arg[1] <3 ) {
1298 1299
    add_pos = dmrs_arg[1];
  }
1300

1301
  if(scg != NULL) {
1302 1303
    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;
1304
    for (int i=0;i<bwp->bwp_Common->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list.count;i++) {
1305 1306 1307
      bwp->bwp_Common->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list.array[i]->mappingType = mapping_type; 
    }
  }
1308 1309
  if(ue != NULL) {
    for (int i=0;i<MAX_NR_OF_DL_ALLOCATIONS;i++) {
1310 1311 1312 1313 1314 1315
      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] );
}