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

heshanyun's avatar
heshanyun committed
128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153
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;
}

154 155
void config_common(int Mod_idP,
                   int pdsch_AntennaPorts, 
156
		   NR_ServingCellConfigCommon_t *scc
Raymond Knopp's avatar
Raymond Knopp committed
157
		   );
158

159 160 161 162 163 164 165 166 167
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;}
168

169
// Dummy function to avoid linking error at compilation of nr-dlsim
170 171 172 173 174
int is_x2ap_enabled(void)
{
  return 0;
}

rmagueta's avatar
rmagueta committed
175 176 177 178
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;
}

179
// needed for some functions
180
openair0_config_t openair0_cfg[MAX_CARDS];
181 182
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);
183

184 185
/* 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 */
186
int g_mcsIndex = -1, g_mcsTableIdx = 0, g_rbStart = -1, g_rbSize = -1;
187 188
void nr_dlsim_preprocessor(module_id_t module_id,
                           frame_t frame,
189
                           sub_frame_t slot) {
190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208
  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;
209
  sched_ctrl->mcsTableIdx = g_mcsTableIdx;
210 211 212 213 214 215 216 217 218 219 220 221 222 223
  /* 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;
224 225 226
  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);
227
  AssertFatal(sched_ctrl->mcsTableIdx >= 0 && sched_ctrl->mcsTableIdx <= 2, "invalid sched_ctrl->mcsTableIdx %d\n", sched_ctrl->mcsTableIdx);
228 229
  sched_ctrl->numDmrsCdmGrpsNoData = 1;
}
230 231


232 233 234
int main(int argc, char **argv)
{
  char c;
235
  int i,aa;//,l;
236
  double sigma2, sigma2_dB=10, SNR, snr0=-2.0, snr1=2.0;
237
  uint8_t snr1set=0;
238
  float roundStats[50];
239
  float effRate;
Francesco Mani's avatar
Francesco Mani committed
240
  //float psnr;
241
  float eff_tp_check = 0.7;
242
  uint8_t snrRun;
243
  uint32_t TBS;
244 245
  int **txdata;
  double **s_re,**s_im,**r_re,**r_im;
246 247
  //double iqim = 0.0;
  //unsigned char pbch_pdu[6];
248 249 250
  //  int sync_pos, sync_pos_slot;
  //  FILE *rx_frame_file;
  FILE *output_fd = NULL;
251
  //uint8_t write_output_file=0;
252
  //int result;
253
  //int freq_offset;
254
  //  int subframe_offset;
255
  //  char fname[40], vname[40];
Ahmed Hussein's avatar
Ahmed Hussein committed
256
  int trial, n_trials = 1, n_errors = 0, n_false_positive = 0;
257
  //int n_errors2, n_alamouti;
258
  uint8_t transmission_mode = 1,n_tx=1,n_rx=1;
259 260
  uint8_t round;
  uint8_t num_rounds = 4;
261 262

  channel_desc_t *gNB2UE;
263 264 265
  //uint32_t nsymb,tx_lev,tx_lev1 = 0,tx_lev2 = 0;
  //uint8_t extended_prefix_flag=0;
  //int8_t interf1=-21,interf2=-21;
266 267

  FILE *input_fd=NULL,*pbch_file_fd=NULL;
268
  //char input_val_str[50],input_val_str2[50];
269

270
  //uint8_t frame_mod4,num_pdcch_symbols = 0;
271 272 273

  SCM_t channel_model=AWGN;//Rayleigh1_anticorr;

Laurent's avatar
Laurent committed
274
  NB_UE_INST = 1;
275 276
  //double pbch_sinr;
  //int pbch_tx_ant;
Ahmed Hussein's avatar
Ahmed Hussein committed
277
  int N_RB_DL=106,mu=1;
278

279
  //unsigned char frame_type = 0;
280

281
  int frame=1,slot=1;
282
  int frame_length_complex_samples;
283
  //int frame_length_complex_samples_no_prefix;
284 285 286 287 288
  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;
289
  int cyclic_prefix_type = NFAPI_CP_NORMAL;
290
  int run_initial_sync=0;
291 292
  int pusch_tgt_snrx10 = 200;
  int pucch_tgt_snrx10 = 200;
Raymond Knopp's avatar
Raymond Knopp committed
293
  int loglvl=OAILOG_INFO;
294

295
  //float target_error_rate = 0.01;
296
  int css_flag=0;
297 298

  cpuf = get_cpu_freq_GHz();
299 300 301 302
  int8_t enable_ptrs = 0;
  int8_t modify_dmrs = 0;

  int8_t dmrs_arg[2] = {-1,-1};// Invalid values
303
  /* L_PTRS = ptrs_arg[0], K_PTRS = ptrs_arg[1] */
304 305
  int8_t ptrs_arg[2] = {-1,-1};// Invalid values

306 307 308 309 310 311
  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;
312
  uint8_t  dlsch_threads = 0;
313
  if ( load_configmodule(argc,argv,CONFIG_ENABLECMDLINEONLY) == 0) {
yilmazt's avatar
yilmazt committed
314
    exit_fun("[NR_DLSIM] Error, configuration module init failed\n");
315 316 317 318
  }

  randominit(0);

319
  int print_perf             = 0;
320

321 322
  FILE *scg_fd=NULL;
  
323
  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) {
324
    switch (c) {
325 326
    case 'f':
      scg_fd = fopen(optarg,"r");
327

328
      if (scg_fd==NULL) {
329 330 331
        printf("Error opening %s\n",optarg);
        exit(-1);
      }
332
      break;
333

334
    /*case 'd':
335
      frame_type = 1;
336
      break;*/
337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368

    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:
369
        printf("Unsupported channel model!\n");
370 371 372 373 374
        exit(-1);
      }

      break;

375
    /*case 'i':
376 377 378 379 380
      interf1=atoi(optarg);
      break;

    case 'j':
      interf2=atoi(optarg);
381
      break;*/
382 383 384 385 386 387 388

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

    case 's':
      snr0 = atof(optarg);
389
      printf("Setting SNR0 to %f\n",snr0);
390 391 392 393 394
      break;

    case 'S':
      snr1 = atof(optarg);
      snr1set=1;
395
      printf("Setting SNR1 to %f\n",snr1);
396 397 398 399 400 401 402
      break;

      /*
      case 't':
      Td= atof(optarg);
      break;
      */
403
    /*case 'p':
404
      extended_prefix_flag=1;
405
      break;*/
406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421

      /*
      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)) {
422
        printf("Unsupported transmission mode %d\n",transmission_mode);
423 424 425 426 427 428 429 430 431
        exit(-1);
      }

      break;

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

      if ((n_tx==0) || (n_tx>2)) {
432
        printf("Unsupported number of tx antennas %d\n",n_tx);
433 434 435 436 437 438 439 440 441
        exit(-1);
      }

      break;

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

      if ((n_rx==0) || (n_rx>2)) {
442
        printf("Unsupported number of rx antennas %d\n",n_rx);
443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462
        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':
463 464
      print_perf=1;
      opp_enabled=1;
465 466 467 468
      break;
      
    case 'I':
      run_initial_sync=1;
469
      //target_error_rate=0.1;
470
      slot = 0;
471 472 473 474 475 476
      break;

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

477

478 479 480
    case 'E':
	css_flag=1;
	break;
481

482

483
    case 'a':
484
      g_rbStart = atoi(optarg);
485 486 487
      break;

    case 'b':
488
      g_rbSize = atoi(optarg);
489
      break;
490 491 492
    case 'd':
      dlsch_threads = atoi(optarg);
      break;    
493
    case 'e':
494
      g_mcsIndex = atoi(optarg);
495 496
      break;

497 498 499 500 501
    case 'q':
      g_mcsTableIdx = 1;
      get_softmodem_params()->use_256qam_table = 1;
      break;

502 503 504
    case 'm':
      mu = atoi(optarg);
      break;
505

506 507 508 509
    case 't':
      eff_tp_check = (float)atoi(optarg)/100;
      break;

510 511 512
    case 'w':
      output_fd = fopen("txdata.dat", "w+");
      break;
Sakthivel Velumani's avatar
Sakthivel Velumani committed
513

514 515 516 517 518 519 520
    case 'T':
      enable_ptrs=1;
      for(i=0; i < atoi(optarg); i++) {
        ptrs_arg[i] = atoi(argv[optind++]);
      }
      break;

521 522
    case 'U':
      modify_dmrs = 1;
523
      for(i=0; i < atoi(optarg); i++) {
524 525 526
        dmrs_arg[i] = atoi(argv[optind++]);
      }
      break;
Sakthivel Velumani's avatar
Sakthivel Velumani committed
527

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

569 570 571
  logInit();
  set_glog(loglvl);
  T_stdout = 1;
572 573
  /* initialize the sin table */
  InitSinLUT();
574

575 576
  get_softmodem_params()->phy_test = 1;
  
577 578
  if (snr1set==0)
    snr1 = snr0+10;
579
  init_dlsch_tpool(dlsch_threads);
580 581


582 583 584
  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
585

586
  gNB = RC.gNB[0];
587 588 589 590 591 592
  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
593
  RC.nb_nr_macrlc_inst = 1;
cig's avatar
cig committed
594 595 596
  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
597 598
  mac_top_init_gNB();
  gNB_mac = RC.nrmac[0];
599
  gNB_mac->pre_processor_dl = nr_dlsim_preprocessor;
Raymond Knopp's avatar
Raymond Knopp committed
600
  gNB_RRC_INST rrc;
Raymond Knopp's avatar
Raymond Knopp committed
601
  memset((void*)&rrc,0,sizeof(rrc));
602

603
  /*
Raymond Knopp's avatar
Raymond Knopp committed
604
  // read in SCGroupConfig
Raymond Knopp's avatar
Raymond Knopp committed
605
  AssertFatal(scg_fd != NULL,"no reconfig.raw file\n");
Raymond Knopp's avatar
Raymond Knopp committed
606 607 608 609
  char buffer[1024];
  int msg_len=fread(buffer,1,1024,scg_fd);
  NR_RRCReconfiguration_t *NR_RRCReconfiguration;

Raymond Knopp's avatar
Raymond Knopp committed
610
  printf("Decoding NR_RRCReconfiguration (%d bytes)\n",msg_len);
Raymond Knopp's avatar
Raymond Knopp committed
611 612 613 614 615 616 617 618 619 620 621 622 623 624
  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
625 626
  AssertFatal(NR_RRCReconfiguration->criticalExtensions.present == NR_RRCReconfiguration__criticalExtensions_PR_rrcReconfiguration,"wrong NR_RRCReconfiguration->criticalExstions.present type\n");

Raymond Knopp's avatar
Raymond Knopp committed
627 628 629 630 631 632 633 634 635 636 637 638 639 640 641
  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);
  }      
  
642 643
  NR_ServingCellConfigCommon_t *scc = secondaryCellGroup->spCellConfig->reconfigurationWithSync->spCellConfigCommon;
  */
Raymond Knopp's avatar
Raymond Knopp committed
644

645 646 647 648 649 650 651 652 653

  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
654 655
  fix_scc(scc,ssb_bitmap);

656 657 658 659 660 661 662
  fill_default_secondaryCellGroup(scc,
				  secondaryCellGroup,
				  0,
				  1,
				  n_tx,
				  0);

663
  /* -U option modify DMRS */
664
  if(modify_dmrs) {
665 666
    update_dmrs_config(secondaryCellGroup, NULL,dmrs_arg);
  }
667
  /* -T option enable PTRS */
668
  if(enable_ptrs) {
669
    update_ptrs_config(secondaryCellGroup, &rbSize, &mcsIndex, ptrs_arg);
670 671
  }

672

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

Raymond Knopp's avatar
Raymond Knopp committed
675 676
  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
677
  // common configuration
678
  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
679
  // UE dedicated configuration
680
  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
681
  phy_init_nr_gNB(gNB,0,0);
682
  N_RB_DL = gNB->frame_parms.N_RB_DL;
683 684 685
  NR_UE_info_t *UE_info = &RC.nrmac[0]->UE_info;
  UE_info->num_UEs=1;

Raymond Knopp's avatar
Raymond Knopp committed
686
  // stub to configure frame_parms
Raymond Knopp's avatar
Raymond Knopp committed
687
  //  nr_phy_config_request_sim(gNB,N_RB_DL,N_RB_DL,mu,Nid_cell,SSB_positions);
Raymond Knopp's avatar
Raymond Knopp committed
688 689
  // call MAC to configure common parameters

690 691 692 693 694 695
  /* 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
696

697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714
  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;
  }
715 716 717 718
  else if (mu == 3 && N_RB_DL == 66) {
    fs = 122.88e6;
    bw = 100e6;
  }
719 720 721 722
  else if (mu == 3 && N_RB_DL == 32) {
    fs = 61.44e6;
    bw = 50e6;
  }
723 724 725 726 727
  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,
728 729
 				fs,
				bw,
730
				30e-9,
731 732 733 734 735
                                0,
                                0,
                                0);

  if (gNB2UE==NULL) {
736
    printf("Problem generating channel model. Exiting.\n");
737 738 739 740
    exit(-1);
  }

  frame_length_complex_samples = frame_parms->samples_per_subframe*NR_NUMBER_OF_SUBFRAMES_PER_FRAME;
741
  //frame_length_complex_samples_no_prefix = frame_parms->samples_per_subframe_wCP*NR_NUMBER_OF_SUBFRAMES_PER_FRAME;
742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762

  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));
763
    bzero(txdata[i],frame_length_complex_samples*sizeof(int));
764 765 766 767 768 769 770 771 772 773
  
  }

  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
774
  memset((void*)UE,0,sizeof(PHY_VARS_NR_UE));
775 776 777 778
  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
779

780
  if (run_initial_sync==1)  UE->is_synchronized = 0;
781
  else                      {UE->is_synchronized = 1; UE->UE_mode[0]=PUSCH;}
782 783 784 785 786 787 788 789 790
                      
  UE->perfect_ce = 0;

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

791
  if(modify_dmrs) {
792 793
    update_dmrs_config( NULL,UE,dmrs_arg);
  }
794 795
  init_nr_ue_transport(UE,0);

796
  nr_gold_pbch(UE);
797
  nr_gold_pdcch(UE,0,2);
798

799
  nr_l2_init_ue(NULL);
800
  UE_mac = get_mac_inst(0);
801

802 803 804
  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;
805
  UE->if_inst->dl_indication = nr_ue_dl_indication;
806
  UE->if_inst->ul_indication = dummy_nr_ue_ul_indication;
807

808

809
  UE_mac->if_module = nr_ue_if_module_init(0);
810

811
  unsigned int available_bits=0;
Ahmed Hussein's avatar
Ahmed Hussein committed
812 813 814 815 816
  unsigned char *estimated_output_bit;
  unsigned char *test_input_bit;
  unsigned int errors_bit    = 0;
  uint32_t errors_scrambling = 0;

817

Ahmed Hussein's avatar
Ahmed Hussein committed
818 819
  test_input_bit       = (unsigned char *) malloc16(sizeof(unsigned char) * 16 * 68 * 384);
  estimated_output_bit = (unsigned char *) malloc16(sizeof(unsigned char) * 16 * 68 * 384);
820 821
  
  // generate signal
822 823 824
  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
825

826
  //Configure UE
827 828
  rrc.carrier.MIB = (uint8_t*) malloc(4);
  rrc.carrier.sizeof_MIB = do_MIB_NR(&rrc,0);
829

830
  nr_rrc_mac_config_req_ue(0,0,0,rrc.carrier.mib.message.choice.mib,secondaryCellGroup);
831

832 833 834 835 836 837 838 839

  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;
840
  
841 842 843 844 845 846 847
  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;
848
  scheduled_response.thread_id = UE_proc.thread_id;
Francesco Mani's avatar
Francesco Mani committed
849

850
  nr_ue_phy_config_request(&UE_mac->phy_config);
Francesco Mani's avatar
Francesco Mani committed
851
  //NR_COMMON_channels_t *cc = RC.nrmac[0]->common_channels;
852
  snrRun = 0;
853

854

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

857 858 859 860 861 862 863 864 865 866 867
    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);
868
    reset_meas(&gNB->toutput);
869

870 871
    clear_pdsch_stats(gNB);

872
    n_errors = 0;
873
    effRate = 0;
874 875
    //n_errors2 = 0;
    //n_alamouti = 0;
876
    errors_scrambling=0;
877
    n_false_positive = 0;
878 879
    if (n_trials== 1) num_rounds = 1;

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

882
      errors_bit = 0;
Ahmed Hussein's avatar
Ahmed Hussein committed
883
      //multipath channel
884
      //multipath_channel(gNB2UE,s_re,s_im,r_re,r_im,frame_length_complex_samples,0);
885

886
      UE->rx_offset=0;
887 888 889
      UE_proc.thread_id  = 0;
      UE_proc.frame_rx   = frame;
      UE_proc.nr_slot_rx = slot;
890 891 892
      
      dcireq.frame     = frame;
      dcireq.slot      = slot;
893

894
      NR_UE_DLSCH_t *dlsch0 = UE->dlsch[UE_proc.thread_id][0][0];
895

896
      int harq_pid = slot;
897 898 899
      NR_DL_UE_HARQ_t *UE_harq_process = dlsch0->harq_processes[harq_pid];

      NR_gNB_DLSCH_t *gNB_dlsch = gNB->dlsch[0][0];
900
      nfapi_nr_dl_tti_pdsch_pdu_rel15_t *rel15 = &gNB_dlsch->harq_process.pdsch_pdu.pdsch_pdu_rel15;
901
      
902 903
      UE_harq_process->harq_ack.ack = 0;
      round = 0;
904 905
      UE_harq_process->round = round;
      UE_harq_process->first_tx = 1;
906 907 908 909
        
      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));
910
        clear_nr_nfapi_information(RC.nrmac[0], 0, frame, slot);
911

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

914

915
        UE_info->UE_sched_ctrl[0].harq_processes[harq_pid].round = round;
Sakthivel Velumani's avatar
Sakthivel Velumani committed
916
        for (int i=0; i<MAX_NUM_CORESET; i++)
917
          gNB_mac->UE_info.num_pdcch_cand[0][i] = 0;
918
      
919
        if (css_flag == 0) {
920
          nr_schedule_ue_spec(0, frame, slot);
921 922 923
        } else {
          nr_schedule_css_dlsch_phytest(0,frame,slot);
        }
924 925 926 927 928
        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];
929
        Sched_INFO.UL_tti_req    = gNB_mac->UL_tti_req_ahead[slot];
930 931 932
        Sched_INFO.UL_dci_req  = NULL;
        Sched_INFO.TX_req    = &gNB_mac->TX_req[0];
        nr_schedule_response(&Sched_INFO);
933 934 935 936 937 938

        /* 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;
939
        if(pdu_bit_map & 0x1) {
940 941 942 943 944 945 946
          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);
947
          printf("[DLSIM] PTRS Symbols in a slot: %2u, RE per Symbol: %3u, RE in a slot %4d\n", ptrsSymbPerSlot,ptrsRePerSymb, ptrsSymbPerSlot*ptrsRePerSymb );
948
        }
949 950 951 952 953 954 955 956
        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) {
957
          LOG_M("txsigF0.m","txsF0", &gNB->common_vars.txdataF[0][txdataF_offset],frame_parms->samples_per_slot_wCP,1,1);
958
          if (gNB->frame_parms.nb_antennas_tx>1)
959
          LOG_M("txsigF1.m","txsF1", &gNB->common_vars.txdataF[1][txdataF_offset],frame_parms->samples_per_slot_wCP,1,1);
960 961
        }
        int tx_offset = frame_parms->get_samples_slot_timestamp(slot,frame_parms,0);
962
        if (n_trials==1) printf("tx_offset %d, txdataF_offset %d \n", tx_offset,txdataF_offset);
963

964 965 966
        //TODO: loop over slots
        for (aa=0; aa<gNB->frame_parms.nb_antennas_tx; aa++) {
    
967 968 969 970 971 972 973
          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);
974
          } else {
975 976 977 978 979
            nr_normal_prefix_mod(&gNB->common_vars.txdataF[aa][txdataF_offset],
                                 &txdata[aa][tx_offset],
                                 14,
                                 frame_parms);
          }
980 981 982
        }
       
        if (n_trials==1) {
983
          LOG_M("txsig0.m","txs0", &txdata[0][tx_offset],frame_parms->get_samples_slot_timestamp(slot,frame_parms,0),1,1);
984
          if (gNB->frame_parms.nb_antennas_tx>1)
985
            LOG_M("txsig1.m","txs1", &txdata[1][tx_offset],frame_parms->get_samples_slot_timestamp(slot,frame_parms,0),1,1);
986
        }
Sakthivel Velumani's avatar
Sakthivel Velumani committed
987 988
        if (output_fd) {
          printf("writing txdata to binary file\n");
989
          fwrite(txdata[0],sizeof(int32_t),frame_length_complex_samples,output_fd);
Sakthivel Velumani's avatar
Sakthivel Velumani committed
990
        }
991

992
        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);
993 994 995 996
        
        //  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)); 
997 998 999 1000 1001 1002 1003
             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]);
          }
1004
        }
1005
        double ts = 1.0/(frame_parms->subcarrier_spacing * frame_parms->ofdm_symbol_size); 
1006 1007 1008 1009 1010 1011
        //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); 
1012 1013 1014 1015 1016 1017
             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)));
1018
            /* Add phase noise if enabled */
1019
            if (pdu_bit_map & 0x1) {
1020 1021 1022
              phase_noise(ts, &((short*) UE->common_vars.rxdata[aa])[2*i],
                          &((short*) UE->common_vars.rxdata[aa])[2*i+1]);
            }
1023
          }
1024
        }
1025

1026 1027 1028 1029
        nr_ue_dcireq(&dcireq); //to be replaced with function pointer later
        nr_ue_scheduled_response(&scheduled_response);
        
        phy_procedures_nrUE_RX(UE,
1030 1031
                               &UE_proc,
                               0,
1032
                               dlsch_threads);
1033
        
1034
        //printf("dlsim round %d ends\n",round);
1035 1036
        round++;
      } // round
1037

1038 1039 1040
      //----------------------------------------------------------
      //---------------------- count errors ----------------------
      //----------------------------------------------------------
1041 1042 1043

      if (UE->dlsch[UE_proc.thread_id][0][0]->last_iteration_cnt >=
        UE->dlsch[UE_proc.thread_id][0][0]->max_ldpc_iterations+1)
1044
        n_errors++;
1045 1046

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

1049
      TBS                  = UE_harq_process->TBS;//rel15->TBSize[0];
1050
      uint16_t length_dmrs = get_num_dmrs(rel15->dlDmrsSymbPos);
1051 1052 1053 1054
      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;
1055

1056
      available_bits = nr_get_G(nb_rb, nb_symb_sch, nb_re_dmrs, length_dmrs, mod_order, rel15->nrOfLayers);
1057
      if(pdu_bit_map & 0x1) {
1058
        available_bits-= (ptrsSymbPerSlot * ptrsRePerSymb *rel15->nrOfLayers* 2);
1059
        printf("[DLSIM][PTRS] Available bits are: %5u, removed PTRS bits are: %5u \n",available_bits, (ptrsSymbPerSlot * ptrsRePerSymb *rel15->nrOfLayers* 2) );
1060
      }
1061 1062
      
      for (i = 0; i < available_bits; i++) {
Raymond Knopp's avatar
Raymond Knopp committed
1063
	
1064 1065
	if(((gNB_dlsch->harq_process.f[i] == 0) && (UE_llr[i] <= 0)) || 
	   ((gNB_dlsch->harq_process.f[i] == 1) && (UE_llr[i] >= 0)))
1066 1067 1068 1069
	  {
	    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
1070
	    }
1071
	    errors_scrambling++;
Raymond Knopp's avatar
Raymond Knopp committed
1072 1073
	  }
	
1074 1075
      }
      for (i = 0; i < TBS; i++) {
1076

1077
	estimated_output_bit[i] = (UE_harq_process->b[i/8] & (1 << (i & 7))) >> (i & 7);
1078
	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
1079
	
1080 1081 1082 1083
	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
1084 1085
	}
	
1086 1087 1088 1089 1090 1091
      }
      
      ////////////////////////////////////////////////////////////
      
      if (errors_scrambling > 0) {
	if (n_trials == 1)
1092
	  printf("errors_scrambling = %u/%u (trial %d)\n", errors_scrambling, available_bits,trial);
1093 1094 1095 1096 1097 1098 1099
      }
      
      if (errors_bit > 0) {
	n_false_positive++;
	if (n_trials == 1)
	  printf("errors_bit = %u (trial %d)\n", errors_bit, trial);
      }
1100
      roundStats[snrRun]+=((float)round); 
1101
      if (UE_harq_process->harq_ack.ack==1) effRate += ((float)TBS)/round;
Ahmed Hussein's avatar
Ahmed Hussein committed
1102
    } // noise trials
1103

1104
    roundStats[snrRun]/=((float)n_trials);
1105
    effRate /= n_trials;
Ahmed Hussein's avatar
Ahmed Hussein committed
1106 1107
    printf("*****************************************\n");
    printf("SNR %f, (false positive %f)\n", SNR,
Sakthivel Velumani's avatar
Sakthivel Velumani committed
1108
           (float) n_errors / (float) n_trials);
Ahmed Hussein's avatar
Ahmed Hussein committed
1109 1110
    printf("*****************************************\n");
    printf("\n");
1111
    dump_pdsch_stats(gNB);
1112
    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
1113
    printf("\n");
1114

1115
    if (print_perf==1) {
1116
      printf("\ngNB TX function statistics (per %d us slot, NPRB %d, mcs %d, TBS %d, Kr %d (Zc %d))\n",
1117
	     1000>>*scc->ssbSubcarrierSpacing, g_rbSize, g_mcsIndex,
1118 1119 1120
	     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));
1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148
      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",
1149 1150 1151
	     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,
1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164
	     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");
      */
    }
1165 1166 1167 1168 1169 1170 1171 1172

    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);
1173
      LOG_M("rxF_llr.m","rxFllr",UE->pdsch_vars[UE_proc.thread_id][0]->llr[0],available_bits,1,0);
1174 1175 1176 1177
      break;
    }

    //if ((float)n_errors/(float)n_trials <= target_error_rate) {
1178
    if (effRate > (eff_tp_check*TBS)) {
1179 1180 1181 1182
      printf("PDSCH test OK\n");
      break;
    }

1183
    snrRun++;
1184 1185
  } // NSR

1186
  /*if (n_trials>1) {
1187 1188 1189 1190 1191 1192
    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;
    }
1193
  }*/
1194

Ahmed Hussein's avatar
Ahmed Hussein committed
1195
  for (i = 0; i < 2; i++) {
1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207
    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
1208 1209 1210
  free(test_input_bit);
  free(estimated_output_bit);
  
1211 1212 1213 1214 1215 1216
  if (output_fd)
    fclose(output_fd);

  if (input_fd)
    fclose(input_fd);

1217 1218
  if (scg_fd)
    fclose(scg_fd);
1219
  return(n_errors);
Raymond Knopp's avatar
Raymond Knopp committed
1220
  
1221
}
1222 1223


1224
void update_ptrs_config(NR_CellGroupConfig_t *secondaryCellGroup, uint16_t *rbSize, uint8_t *mcsIndex, int8_t *ptrs_arg)
1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237
{
  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;

1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249
  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 {
1250 1251 1252
    printf("[DLSIM] Wrong L_PTRS value, using default values 1\n");
  }
  /* L = 4 if Imcs < MCS4 */
1253 1254 1255 1256 1257 1258 1259 1260 1261 1262
  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");
  }
1263
  printf("[DLSIM] PTRS Enabled with L %d, K %d \n", 1<<ptrs_arg[0], ptrs_arg[1] );
1264 1265 1266 1267
  /* overwrite the values */
  rrc_config_dl_ptrs_params(bwp, ptrsFreqDenst, ptrsTimeDenst, &epre_Ratio, &reOffset);
}

1268 1269 1270 1271
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
1272
  if(dmrs_arg[0] == 0) {
1273 1274
    mapping_type = typeA;
  }
1275
  else if (dmrs_arg[0] == 1) {
1276 1277 1278
    mapping_type = typeB;
  }
  /* Additional DMRS positions 0 ,1 and 2 */
1279
  if(dmrs_arg[1] >= 0 && dmrs_arg[1] <3 ) {
1280 1281
    add_pos = dmrs_arg[1];
  }
1282

1283
  if(scg != NULL) {
1284 1285
    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;
1286
    for (int i=0;i<bwp->bwp_Common->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list.count;i++) {
1287 1288 1289
      bwp->bwp_Common->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list.array[i]->mappingType = mapping_type; 
    }
  }
1290 1291
  if(ue != NULL) {
    for (int i=0;i<MAX_NR_OF_DL_ALLOCATIONS;i++) {
1292 1293 1294 1295 1296 1297
      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] );
}