ulsim.c 21.1 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 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
/*
* 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 <string.h>
#include <math.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/mman.h>

#include "common/config/config_userapi.h"
#include "common/utils/LOG/log.h"
#include "common/ran_context.h"

#include "SIMULATION/TOOLS/sim.h"
#include "SIMULATION/RF/rf.h"

#include "PHY/types.h"
#include "PHY/defs_nr_common.h"
#include "PHY/defs_nr_UE.h"
#include "PHY/defs_gNB.h"
#include "PHY/INIT/phy_init.h"
#include "PHY/NR_REFSIG/refsig_defs_ue.h"
#include "PHY/NR_REFSIG/nr_mod_table.h"
43
#include "PHY/MODULATION/nr_modulation.h"
44 45 46 47
#include "PHY/MODULATION/modulation_UE.h"
#include "PHY/NR_TRANSPORT/nr_transport.h"
#include "PHY/NR_TRANSPORT/nr_dlsch.h"
#include "PHY/NR_TRANSPORT/nr_ulsch.h"
48
#include "PHY/NR_REFSIG/dmrs_nr.h"
49
#include "PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h"
50
#include "PHY/NR_TRANSPORT/nr_transport_proto.h"
51
#include "SCHED_NR/sched_nr.h"
52
#include "PHY/TOOLS/tools_defs.h"
53
#include "PHY/NR_TRANSPORT/nr_sch_dmrs.h"
54

55 56 57 58 59
//#include "PHY/MODULATION/modulation_common.h"
//#include "common/config/config_load_configmodule.h"
//#include "UTIL/LISTS/list.h"
//#include "common/ran_context.h"

60
//#define DEBUG_ULSIM
61 62 63 64 65 66
PHY_VARS_gNB *gNB;
PHY_VARS_NR_UE *UE;
RAN_CONTEXT_t RC;

double cpuf;

67 68 69 70 71 72 73 74 75 76 77 78 79 80 81
typedef struct ulsim_params_s {
  uint16_t  Nid_cell;
  uint8_t   nb_codewords;
  uint8_t   Imcs;
  uint16_t  nb_symb_sch;
  int       eNB_id;
  int       nb_rb;
  int       first_rb;
  uint8_t   length_dmrs;
  uint8_t   Nl;
  uint8_t   rvidx;
  uint8_t   UE_id;
  uint16_t  n_rnti;
} ulsim_params_t;

82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114
// dummy functions
int nfapi_mode = 0;
int oai_nfapi_hi_dci0_req(nfapi_hi_dci0_request_t *hi_dci0_req) {
  return (0);
}
int oai_nfapi_tx_req(nfapi_tx_request_t *tx_req) {
  return (0);
}

int oai_nfapi_dl_config_req(nfapi_dl_config_request_t *dl_config_req) {
  return (0);
}

int oai_nfapi_ul_config_req(nfapi_ul_config_request_t *ul_config_req) {
  return (0);
}

int oai_nfapi_nr_dl_config_req(nfapi_nr_dl_config_request_t *dl_config_req) {
  return (0);
}

uint32_t from_nrarfcn(int nr_bandP, uint32_t dl_earfcn) {
  return (0);
}
int32_t get_uldl_offset(int eutra_bandP) {
  return (0);
}

NR_IF_Module_t *
NR_IF_Module_init(int Mod_id) {
  return (NULL);
}

115 116 117 118 119 120 121 122 123 124 125 126 127 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 154 155 156 157 158 159 160 161 162 163 164 165
int generate_ue_ulsch_params(PHY_VARS_NR_UE *UE,
                             ulsim_params_t *ulsim_params,
                             uint8_t thread_id,
                             unsigned char harq_pid,
                             unsigned char *test_input){

  int N_PRB_oh, N_RE_prime, cwd_idx;

  NR_UE_ULSCH_t *ulsch_ue;
  NR_UL_UE_HARQ_t *harq_process_ul_ue;

  for (cwd_idx = 0;cwd_idx < 1;cwd_idx++){

    ulsch_ue = UE->ulsch[thread_id][ulsim_params->eNB_id][cwd_idx];
    harq_process_ul_ue = ulsch_ue->harq_processes[harq_pid];

    ulsch_ue->length_dmrs = ulsim_params->length_dmrs;
    ulsch_ue->rnti        = ulsim_params->n_rnti;
    ulsch_ue->Nid_cell    = ulsim_params->Nid_cell;
    ulsch_ue->Nsc_pusch   = ulsim_params->nb_rb*NR_NB_SC_PER_RB;
    ulsch_ue->Nsymb_pusch = ulsim_params->nb_symb_sch;
    ulsch_ue->nb_re_dmrs  = UE->dmrs_UplinkConfig.pusch_maxLength*(UE->dmrs_UplinkConfig.pusch_dmrs_type == pusch_dmrs_type1)?6:4;


    N_PRB_oh   = 0; // higher layer (RRC) parameter xOverhead in PUSCH-ServingCellConfig
    N_RE_prime = NR_NB_SC_PER_RB*ulsim_params->nb_symb_sch - ulsch_ue->nb_re_dmrs - N_PRB_oh;

    if (harq_process_ul_ue) {

      harq_process_ul_ue->mcs                = ulsim_params->Imcs;
      harq_process_ul_ue->Nl                 = ulsim_params->Nl;
      harq_process_ul_ue->nb_rb              = ulsim_params->nb_rb;
      harq_process_ul_ue->first_rb           = ulsim_params->first_rb;
      harq_process_ul_ue->number_of_symbols  = ulsim_params->nb_symb_sch;
      harq_process_ul_ue->num_of_mod_symbols = N_RE_prime*ulsim_params->nb_rb*ulsim_params->nb_codewords;
      harq_process_ul_ue->rvidx              = ulsim_params->rvidx;
      harq_process_ul_ue->a                  = test_input;
      harq_process_ul_ue->TBS                = nr_compute_tbs(ulsim_params->Imcs,
                                                              ulsim_params->nb_rb,
                                                              ulsim_params->nb_symb_sch,
                                                              ulsch_ue->nb_re_dmrs,
                                                              ulsim_params->length_dmrs,
                                                              ulsim_params->Nl);

    }

  }

  return 0;
}

166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195
void exit_function(const char *file, const char *function, const int line, const char *s) {
  const char *msg = s == NULL ? "no comment" : s;
  printf("Exiting at: %s:%d %s(), %s\n", file, line, function, msg);
  exit(-1);
}

// needed for some functions
PHY_VARS_NR_UE *PHY_vars_UE_g[1][1] = { { NULL } };
uint16_t n_rnti = 0x1234;
openair0_config_t openair0_cfg[MAX_CARDS];

char quantize(double D, double x, unsigned char B) {
  double qxd;
  short maxlev;
  qxd = floor(x / D);
  maxlev = 1 << (B - 1); //(char)(pow(2,B-1));

  //printf("x=%f,qxd=%f,maxlev=%d\n",x,qxd, maxlev);

  if (qxd <= -maxlev)
    qxd = -maxlev;
  else if (qxd >= maxlev)
    qxd = maxlev - 1;

  return ((char) qxd);
}

int main(int argc, char **argv) {

  char c;
196
  int i,sf;
197 198
  double SNR, snr0 = -2.0, snr1 = 2.0;
  double sigma, sigma_dB;
199 200
  double snr_step = 0.1;
  uint8_t snr1set = 0;
Khalid Ahmed's avatar
Khalid Ahmed committed
201
  int slot = 0;
202 203 204
  FILE *output_fd = NULL;
  //uint8_t write_output_file = 0;
  int trial, n_trials = 1, n_errors = 0, n_false_positive = 0;
205
  uint8_t n_tx = 1, n_rx = 1, nb_codewords = 1;
206 207 208 209 210
  //uint8_t transmission_mode = 1;
  uint16_t Nid_cell = 0;
  channel_desc_t *gNB2UE;
  uint8_t extended_prefix_flag = 0;
  //int8_t interf1 = -21, interf2 = -21;
211
  FILE *input_fd = NULL;
212
  SCM_t channel_model = AWGN;  //Rayleigh1_anticorr;
213 214
  ulsim_params_t ulsim_params;
  uint16_t N_RB_DL = 106, N_RB_UL = 106, mu = 1;
215
  //unsigned char frame_type = 0;
216
  int frame = 0;
217 218 219 220 221
  int frame_length_complex_samples;
  NR_DL_FRAME_PARMS *frame_parms;
  int loglvl = OAILOG_WARNING;
  uint64_t SSB_positions=0x01;
  uint16_t nb_symb_sch = 12;
222
  int start_symbol = NR_SYMBOLS_PER_SLOT - nb_symb_sch;
223 224
  uint16_t nb_rb = 50;
  uint8_t Imcs = 9;
225
  int eNB_id = 0;
Khalid Ahmed's avatar
Khalid Ahmed committed
226
  int ap;
Khalid Ahmed's avatar
Khalid Ahmed committed
227
  int tx_offset;
228
  double txlev;
229
  int start_rb = 30;
230 231 232

  cpuf = get_cpu_freq_GHz();

233

234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441
  if (load_configmodule(argc, argv) == 0) {
    exit_fun("[SOFTMODEM] Error, configuration module init failed\n");
  }

  //logInit();
  randominit(0);

  while ((c = getopt(argc, argv, "df:hpg:i:j:n:l:m:r:s:S:y:z:M:N:F:R:P:")) != -1) {
    switch (c) {
      /*case 'f':
         write_output_file = 1;
         output_fd = fopen(optarg, "w");

         if (output_fd == NULL) {
             printf("Error opening %s\n", optarg);
             exit(-1);
         }

         break;*/

      /*case 'd':
        frame_type = 1;
        break;*/

      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:
            msg("Unsupported channel model!\n");
            exit(-1);
        }

        break;

      /*case 'i':
        interf1 = atoi(optarg);
        break;

      case 'j':
        interf2 = atoi(optarg);
        break;*/

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

      case 's':
        snr0 = atof(optarg);
        msg("Setting SNR0 to %f\n", snr0);
        break;

      case 'S':
        snr1 = atof(optarg);
        snr1set = 1;
        msg("Setting SNR1 to %f\n", snr1);
        break;

      case 'p':
        extended_prefix_flag = 1;
        break;

      /*
       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 'y':
        n_tx = atoi(optarg);

        if ((n_tx == 0) || (n_tx > 2)) {
          msg("Unsupported number of tx antennas %d\n", n_tx);
          exit(-1);
        }

        break;

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

        if ((n_rx == 0) || (n_rx > 2)) {
          msg("Unsupported number of rx antennas %d\n", n_rx);
          exit(-1);
        }

        break;

      case 'M':
        SSB_positions = atoi(optarg);
        break;

      case 'N':
        Nid_cell = atoi(optarg);
        break;

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

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

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

        break;

      case 'm':
        Imcs = atoi(optarg);
        break;

      case 'l':
        nb_symb_sch = atoi(optarg);
        break;

      case 'r':
        nb_rb = atoi(optarg);
        break;

      /*case 'x':
        transmission_mode = atoi(optarg);
        break;*/

      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");
          printf("-p Use extended prefix mode\n");
          //printf("-d Use TDD\n");
          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");
          //printf("-x Transmission mode (1,2,6 for the moment)\n");
          printf("-y Number of TX antennas used in eNB\n");
          printf("-z Number of RX antennas used in UE\n");
          //printf("-i Relative strength of first intefering eNB (in dB) - cell_id mod 3 = 1\n");
          //printf("-j Relative strength of second intefering eNB (in dB) - cell_id mod 3 = 2\n");
          printf("-M Multiple SSB positions in burst\n");
          printf("-N Nid_cell\n");
          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");
          //printf("-C Generate Calibration information for Abstraction (effective SNR adjustment to remove Pe bias w.r.t. AWGN)\n");
          //printf("-f Output filename (.txt format) for Pe/SNR results\n");
          printf("-F Input filename (.txt format) for RX conformance testing\n");
          exit(-1);
          break;
    }
  }

  logInit();
  set_glog(loglvl);
  T_stdout = 1;

  if (snr1set == 0)
    snr1 = snr0 + 10;

  gNB2UE = new_channel_desc_scm(n_tx, n_rx, channel_model,
                                61.44e6, //N_RB2sampling_rate(N_RB_DL),
                                40e6, //N_RB2channel_bandwidth(N_RB_DL),
                                0, 0, 0);

  if (gNB2UE == NULL) {
    msg("Problem generating channel model. Exiting.\n");
    exit(-1);
  }

  RC.gNB = (PHY_VARS_gNB ** *) malloc(sizeof(PHY_VARS_gNB **));
  RC.gNB[0] = (PHY_VARS_gNB **) malloc(sizeof(PHY_VARS_gNB *));
  RC.gNB[0][0] = malloc(sizeof(PHY_VARS_gNB));
  gNB = RC.gNB[0][0];
  //gNB_config = &gNB->gNB_config;
442 443 444 445
  gNB_L1_rxtx_proc_t gNB_proc;

  gNB_proc.frame_rx = frame;
  gNB_proc.slot_rx  = slot;
446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488

  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_UL;
  frame_parms->Ncp = extended_prefix_flag ? EXTENDED : NORMAL;

  crcTableInit();

  nr_phy_config_request_sim(gNB, N_RB_DL, N_RB_DL, mu, Nid_cell, SSB_positions);

  phy_init_nr_gNB(gNB, 0, 0);
  //init_eNB_afterRU();

  frame_length_complex_samples = frame_parms->samples_per_subframe;
  //frame_length_complex_samples_no_prefix = frame_parms->samples_per_subframe_wCP;

  //configure UE
  UE = malloc(sizeof(PHY_VARS_NR_UE));
  memcpy(&UE->frame_parms, frame_parms, sizeof(NR_DL_FRAME_PARMS));

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

  //nr_init_frame_parms_ue(&UE->frame_parms);
  //init_nr_ue_transport(UE, 0);
  for (sf = 0; sf < 2; sf++) {
    for (i = 0; i < 2; i++) {

        UE->ulsch[sf][0][i] = new_nr_ue_ulsch(N_RB_UL, 8, 0);

        if (!UE->ulsch[sf][0][i]) {
          printf("Can't get ue ulsch structures\n");
          exit(-1);
        }

    }
  }

489 490 491 492 493 494 495 496 497 498 499 500 501
  ulsim_params.Nid_cell = Nid_cell;
  ulsim_params.nb_codewords = nb_codewords;
  ulsim_params.Imcs = Imcs;
  ulsim_params.nb_symb_sch = nb_symb_sch;
  ulsim_params.eNB_id = eNB_id;
  ulsim_params.nb_rb = nb_rb;
  ulsim_params.first_rb = start_rb;
  ulsim_params.length_dmrs = 1;
  ulsim_params.Nl = 1;
  ulsim_params.rvidx = 0;
  ulsim_params.UE_id = 0;
  ulsim_params.n_rnti = n_rnti;

502
  unsigned char harq_pid = 0;
503 504
  unsigned int TBS = 8424;
  unsigned int available_bits;
Khalid Ahmed's avatar
Khalid Ahmed committed
505
  uint8_t  nb_re_dmrs  = UE->dmrs_UplinkConfig.pusch_maxLength*(UE->dmrs_UplinkConfig.pusch_dmrs_type == pusch_dmrs_type1)?6:4;
506 507
  uint16_t length_dmrs = 1;
  unsigned char mod_order;
Khalid Ahmed's avatar
Khalid Ahmed committed
508

509
  mod_order      = nr_get_Qm(Imcs, 1);
510
  available_bits = nr_get_G(nb_rb, nb_symb_sch, nb_re_dmrs, length_dmrs, mod_order, 1);
511
  TBS            = nr_compute_tbs(Imcs, nb_rb, nb_symb_sch, nb_re_dmrs, length_dmrs, ulsim_params.Nl);
512

513 514 515 516 517
  NR_gNB_ULSCH_t *ulsch_gNB = gNB->ulsch[ulsim_params.UE_id+1][0];
  ulsch_gNB->harq_processes[harq_pid]->G = available_bits; // [hna] temp until length_dmrs and nb_re_dmrs are signaled
  nfapi_nr_ul_config_ulsch_pdu *rel15_ul = &ulsch_gNB->harq_processes[harq_pid]->ulsch_pdu;
  
  NR_UE_ULSCH_t **ulsch_ue = UE->ulsch[0][0];
518

519 520 521 522 523 524 525 526 527 528
  // --------- setting rel15_ul parameters ----------
  rel15_ul->rnti                           = n_rnti;
  rel15_ul->ulsch_pdu_rel15.start_rb       = start_rb;
  rel15_ul->ulsch_pdu_rel15.number_rbs     = nb_rb;
  rel15_ul->ulsch_pdu_rel15.start_symbol   = start_symbol;
  rel15_ul->ulsch_pdu_rel15.number_symbols = nb_symb_sch;
  rel15_ul->ulsch_pdu_rel15.Qm             = mod_order;
  rel15_ul->ulsch_pdu_rel15.mcs            = Imcs;
  rel15_ul->ulsch_pdu_rel15.rv             = ulsim_params.rvidx;
  rel15_ul->ulsch_pdu_rel15.n_layers       = ulsim_params.Nl;
529 530 531 532
  ///////////////////////////////////////////////////

  unsigned char *estimated_output_bit;
  unsigned char *test_input_bit;
533
  unsigned char *test_input;
534 535
  unsigned int errors_bit = 0;
  uint32_t errors_scrambling = 0;
536

537 538 539
  test_input           = (unsigned char *) malloc16(sizeof(unsigned char) * TBS / 8);
  test_input_bit       = (unsigned char *) malloc16(sizeof(unsigned char) * 16 * 68 * 384);
  estimated_output_bit = (unsigned char *) malloc16(sizeof(unsigned char) * 16 * 68 * 384);
540

541
  int UE_id = ulsim_params.UE_id; // [hna] only works for UE_id = 0 because NUMBER_OF_NR_UE_MAX is set to 1 (phy_init_nr_gNB causes segmentation fault)
542

543
  /////////////////////////phy_procedures_nr_ue_TX///////////////////////
Khalid Ahmed's avatar
Khalid Ahmed committed
544 545
  ///////////

546 547
  for (i = 0; i < TBS / 8; i++)
    test_input[i] = (unsigned char) rand();
Khalid Ahmed's avatar
Khalid Ahmed committed
548

549 550
  generate_ue_ulsch_params(UE,
                           &ulsim_params,
551
                           0,
552 553
                           harq_pid,
                           test_input);
554

555 556 557 558 559 560 561 562 563 564
  nr_ue_ulsch_procedures(UE,
                         harq_pid,
                         slot,
                         0,
                         eNB_id);

  nr_ue_pusch_common_procedures(UE,
                                slot,
                                ulsim_params.Nl,
                                &UE->frame_parms);
Khalid Ahmed's avatar
Khalid Ahmed committed
565

566 567
    ///////////
    ////////////////////////////////////////////////////
Khalid Ahmed's avatar
Khalid Ahmed committed
568
  tx_offset = slot*frame_parms->samples_per_slot;
569

570
  txlev = (double) signal_energy_amp_shift(&UE->common_vars.txdata[0][tx_offset + 5*frame_parms->ofdm_symbol_size + 4*frame_parms->nb_prefix_samples + frame_parms->nb_prefix_samples0],
571 572
          frame_parms->ofdm_symbol_size + frame_parms->nb_prefix_samples);

573
  txlev = txlev/(double)AMP; // output of signal_energy is fixed point representation
574 575
  
  printf("\n");
576

577
  for (SNR = snr0; SNR < snr1; SNR += snr_step) {
578

579 580
    n_errors = 0;
    n_false_positive = 0;
581

582
    //AWGN
583 584
    sigma_dB = 10*log10((double)txlev)-SNR;
    sigma    = pow(10,sigma_dB/10);
585
    
586 587
    for (trial = 0; trial < n_trials; trial++) {

588 589
      errors_scrambling  = 0;
      errors_bit         = 0;
590

591 592
      for (i=0; i<frame_length_complex_samples; i++) {
        for (ap=0; ap<frame_parms->nb_antennas_rx; ap++) {
593

594 595 596
          // [hna] doesn't work with noise in case of mod_order = 6
          ((short*) gNB->common_vars.rxdata[ap])[2*i]   = (((int16_t *)UE->common_vars.txdata[ap])[(i<<1)]);// + (int16_t)(sqrt(sigma/2)*gaussdouble(0.0,1.0)*(double)AMP)); // convert to fixed point
          ((short*) gNB->common_vars.rxdata[ap])[2*i+1] = (((int16_t *)UE->common_vars.txdata[ap])[(i<<1)+1]);// + (int16_t)(sqrt(sigma/2)*gaussdouble(0.0,1.0)*(double)AMP));
597 598
        }
      }
599

600
      
601
      phy_procedures_gNB_common_RX(gNB, &gNB_proc);
602

603
      phy_procedures_gNB_uespec_RX(gNB, &gNB_proc, rel15_ul->ulsch_pdu_rel15.start_symbol, rel15_ul->ulsch_pdu_rel15.start_symbol + rel15_ul->ulsch_pdu_rel15.number_symbols);
604 605


606 607
      //----------------------------------------------------------
      //---------------------- count errors ----------------------
608
      //----------------------------------------------------------
609

610
      for (i = 0; i < available_bits; i++) {
611
        
612 613 614
        if(((ulsch_ue[0]->g[i] == 0) && (gNB->pusch_vars[UE_id]->llr[i] <= 0)) || 
           ((ulsch_ue[0]->g[i] == 1) && (gNB->pusch_vars[UE_id]->llr[i] >= 0)))
        {
615
          if(errors_scrambling == 0)
616
            printf("First bit in error in unscrambling = %d\n",i);
617
          errors_scrambling++;
618 619
        }

620 621 622 623
      }

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

624
        estimated_output_bit[i] = (ulsch_gNB->harq_processes[harq_pid]->b[i/8] & (1 << (i & 7))) >> (i & 7);
625
        test_input_bit[i]       = (test_input[i / 8] & (1 << (i & 7))) >> (i & 7); // Further correct for multiple segments
626 627

        if (estimated_output_bit[i] != test_input_bit[i]) {
628 629
          if(errors_bit == 0)
            printf("First bit in error in decoding = %d\n",i);
630 631
          errors_bit++;
        }
632
        
633 634
      }

635 636
      ////////////////////////////////////////////////////////////

637 638 639 640 641
      if (errors_scrambling > 0) {
        if (n_trials == 1)
          printf("errors_scrambling %d (trial %d)\n", errors_scrambling, trial);
      }

642 643 644 645 646
      if (errors_bit > 0) {
        n_false_positive++;
        if (n_trials == 1)
          printf("errors_bit %d (trial %d)\n", errors_bit, trial);
      }
647
      printf("\n");
648
    } // [hna] for (trial = 0; trial < n_trials; trial++)
649 650
    
    printf("*****************************************\n");
651
    printf("SNR %f, (false positive %f)\n", SNR,
652 653
           (float) n_false_positive / (float) n_trials);
    printf("*****************************************\n");
654
    printf("\n");
655

656
    if (errors_bit == 0) {
657
      printf("PUSCH test OK\n");
658
      printf("\n");
659 660
      break;
    }
661
    printf("\n");
662 663
  } // [hna] for (SNR = snr0; SNR < snr1; SNR += snr_step)

664 665 666 667 668 669 670 671 672 673 674

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

    printf("----------------------\n");
    printf("freeing codeword %d\n", i);
    printf("----------------------\n");

    printf("gNB ulsch[0][%d]\n", i); // [hna] ulsch[0] is for RA

    free_gNB_ulsch(gNB->ulsch[0][i]);

675
    printf("gNB ulsch[%d][%d]\n",UE_id+1, i);
676

677
    free_gNB_ulsch(gNB->ulsch[UE_id+1][i]); // "+1" because first element in ulsch is for RA
678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697

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

      printf("UE  ulsch[%d][0][%d]\n", sf, i);

      if (UE->ulsch[sf][0][i])
        free_nr_ue_ulsch(UE->ulsch[sf][0][i]);
    }

    printf("\n");
  }

  if (output_fd)
    fclose(output_fd);

  if (input_fd)
    fclose(input_fd);

  return (n_errors);
}