ulschsim.c 17.1 KB
Newer Older
1
/*
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
* 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
*/
21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41

#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 "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"
#include "PHY/MODULATION/modulation_eNB.h"
#include "PHY/MODULATION/modulation_UE.h"
#include "PHY/NR_TRANSPORT/nr_transport.h"
#include "PHY/NR_TRANSPORT/nr_dlsch.h"
42
#include "PHY/NR_TRANSPORT/nr_ulsch.h"
43 44
#include "PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h"
#include "SCHED_NR/sched_nr.h"
45 46 47 48
#include "openair1/SIMULATION/TOOLS/sim.h"
#include "openair1/SIMULATION/RF/rf.h"
#include "openair1/SIMULATION/NR_PHY/nr_unitary_defs.h"
#include "openair1/SIMULATION/NR_PHY/nr_dummy_functions.c"
49

50
//#define DEBUG_NR_ULSCHSIM
51 52 53 54

PHY_VARS_gNB *gNB;
PHY_VARS_NR_UE *UE;
RAN_CONTEXT_t RC;
55 56
int32_t uplink_frequency_offset[MAX_NUM_CCs][4];

57 58
double cpuf;
int nfapi_mode = 0;
yilmazt's avatar
yilmazt committed
59
uint16_t NB_UE_INST = 1;
60 61 62 63

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

66 67
int main(int argc, char **argv)
{
68
  char c;
69
  int i,sf;
70
  double SNR, snr0 = -2.0, snr1 = 2.0, SNR_lin;
71 72 73
  double snr_step = 0.1;
  uint8_t snr1set = 0;
  FILE *output_fd = NULL;
74
  //uint8_t write_output_file = 0;
75
  int trial, n_trials = 1, n_errors = 0, n_false_positive = 0;
Khalid Ahmed's avatar
Khalid Ahmed committed
76
  uint8_t n_tx = 1, n_rx = 1, nb_codewords = 1;
77
  //uint8_t transmission_mode = 1;
78 79 80
  uint16_t Nid_cell = 0;
  channel_desc_t *gNB2UE;
  uint8_t extended_prefix_flag = 0;
81
  //int8_t interf1 = -21, interf2 = -21;
82
  FILE *input_fd = NULL;
83
  SCM_t channel_model = AWGN;  //Rayleigh1_anticorr;
84
  uint16_t N_RB_DL = 106, N_RB_UL = 106, mu = 1;
85
  //unsigned char frame_type = 0;
86
  //unsigned char pbch_phase = 0;
87 88
  int frame = 0, subframe = 0;
  NR_DL_FRAME_PARMS *frame_parms;
89
  double sigma;
90 91 92
  unsigned char qbits = 8;
  int ret;
  int loglvl = OAILOG_WARNING;
93
  uint64_t SSB_positions=0x01;
94 95 96 97 98 99
  uint16_t nb_symb_sch = 12;
  uint16_t nb_rb = 50;
  uint8_t Imcs = 9;

  cpuf = get_cpu_freq_GHz();

100
  if (load_configmodule(argc, argv, CONFIG_ENABLECMDLINEONLY) == 0) {
yilmazt's avatar
yilmazt committed
101
    exit_fun("[NR_ULSCHSIM] Error, configuration module init failed\n");
102 103 104 105 106
  }

  //logInit();
  randominit(0);

107 108
  //while ((c = getopt(argc, argv, "df:hpg:i:j:n:l:m:r:s:S:y:z:M:N:F:R:P:")) != -1) {
  while ((c = getopt(argc, argv, "hg:n:s:S:py:z:M:N:R:F:m:l:r:")) != -1) {
109
    switch (c) {
110
      /*case 'f':
111 112 113 114 115 116 117 118
         write_output_file = 1;
         output_fd = fopen(optarg, "w");

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

119
         break;*/
120

121
      /*case 'd':
122
        frame_type = 1;
123
        break;*/
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

      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:
156
            printf("Unsupported channel model! Exiting.\n");
157 158 159 160 161
            exit(-1);
        }

        break;

162
      /*case 'i':
163 164 165 166 167
        interf1 = atoi(optarg);
        break;

      case 'j':
        interf2 = atoi(optarg);
168
        break;*/
169 170 171

      case 'n':
        n_trials = atoi(optarg);
172 173 174
#ifdef DEBUG_NR_ULSCHSIM
        printf("n_trials (-n) = %d\n", n_trials);
#endif
175 176 177 178
        break;

      case 's':
        snr0 = atof(optarg);
179 180 181
#ifdef DEBUG_NR_ULSCHSIM
        printf("Setting SNR0 to %f\n", snr0);
#endif
182 183 184 185 186
        break;

      case 'S':
        snr1 = atof(optarg);
        snr1set = 1;
187 188 189
#ifdef DEBUG_NR_ULSCHSIM
        printf("Setting SNR1 to %f\n", snr1);
#endif
190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209
        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)) {
210
          printf("Unsupported number of TX antennas %d. Exiting.\n", n_tx);
211 212 213 214 215 216 217 218 219
          exit(-1);
        }

        break;

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

        if ((n_rx == 0) || (n_rx > 2)) {
220
          printf("Unsupported number of RX antennas %d. Exiting.\n", n_rx);
221 222 223 224 225
          exit(-1);
        }

        break;

226 227 228 229
      case 'M':
        SSB_positions = atoi(optarg);
        break;

230 231 232 233 234 235
      case 'N':
        Nid_cell = atoi(optarg);
        break;

      case 'R':
        N_RB_DL = atoi(optarg);
236 237 238
#ifdef DEBUG_NR_ULSCHSIM
        printf("N_RB_DL (-R) = %d\n", N_RB_DL);
#endif
239 240 241 242 243 244
        break;

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

        if (input_fd == NULL) {
245
            printf("Problem with filename %s. Exiting.\n", optarg);
246 247 248 249 250
            exit(-1);
        }

        break;

251
      /*case 'P':
252 253 254
        pbch_phase = atoi(optarg);
        if (pbch_phase > 3)
          printf("Illegal PBCH phase (0-3) got %d\n", pbch_phase);
255
        break;*/
256 257 258

      case 'm':
        Imcs = atoi(optarg);
259 260 261
#ifdef DEBUG_NR_ULSCHSIM
        printf("Imcs (-m) = %d\n", Imcs);
#endif
262 263 264 265 266 267 268 269 270 271
        break;

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

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

272
      /*case 'x':
273
        transmission_mode = atoi(optarg);
274
        break;*/
275 276 277

      default:
        case 'h':
278 279
          printf("%s -h(elp) -g channel_model -n n_frames -s snr0 -S snr1 -p(extended_prefix) -y TXant -z RXant -M -N cell_id -R -F input_filename -m -l -r\n", argv[0]);
          //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]);
280
          printf("-h This message\n");
281
          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");
282
          printf("-n Number of frames to simulate\n");
283
          //printf("-d Use TDD\n");
284 285
          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");
286 287
          printf("-p Use extended prefix mode\n");
          //printf("-t Delay spread for multipath channel\n");
288
          //printf("-x Transmission mode (1,2,6 for the moment)\n");
289 290
          printf("-y Number of TX antennas used in eNB\n");
          printf("-z Number of RX antennas used in UE\n");
291 292
          //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");
293
          printf("-M Multiple SSB positions in burst\n");
294 295
          printf("-N Nid_cell\n");
          printf("-R N_RB_DL\n");
296 297 298 299 300 301
          printf("-F Input filename (.txt format) for RX conformance testing\n");
          printf("-m\n");
          printf("-l\n");
          printf("-r\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");
302 303
          //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");
304 305 306 307 308 309 310 311 312 313 314 315
          exit(-1);
          break;
    }
  }

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

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

316 317 318
  gNB2UE = new_channel_desc_scm(n_tx,
		                        n_rx,
								channel_model,
319
                                61.44e6, //N_RB2sampling_rate(N_RB_DL),
320
                                40e6, //N_RB2channel_bandwidth(N_RB_DL),
321 322 323
                                0,
								0,
								0);
324 325

  if (gNB2UE == NULL) {
326
    printf("Problem generating channel model. Exiting.\n");
327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343
    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];

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

344
  nr_phy_config_request_sim(gNB, N_RB_DL, N_RB_DL, mu, Nid_cell, SSB_positions);
345 346 347 348 349 350 351 352 353

  phy_init_nr_gNB(gNB, 0, 0);

  //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) {
354
    printf("Error at UE NR initialisation.\n");
355 356 357 358 359 360 361 362 363
    exit(-1);
  }

  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]) {
364
          printf("Can't get ue ulsch structures.\n");
365 366 367 368 369 370
          exit(-1);
        }

    }
  }

371
  unsigned char harq_pid = 0;
372
  uint8_t is_crnti = 0;
373 374 375
  unsigned int TBS = 8424;
  unsigned int available_bits;
  uint8_t nb_re_dmrs = 6;
376
  uint8_t length_dmrs = 1;
Khalid Ahmed's avatar
Khalid Ahmed committed
377
  uint8_t N_PRB_oh;
378
  uint16_t N_RE_prime,code_rate;
379 380 381
  unsigned char mod_order;
  uint8_t Nl = 1;
  uint8_t rvidx = 0;
382
  uint8_t UE_id = 0;
383

384
  NR_gNB_ULSCH_t *ulsch_gNB = gNB->ulsch[UE_id][0];
385 386
  NR_UL_gNB_HARQ_t *harq_process_gNB = ulsch_gNB->harq_processes[harq_pid];
  nfapi_nr_ul_config_ulsch_pdu_rel15_t *rel15_ul = &harq_process_gNB->ulsch_pdu.ulsch_pdu_rel15;
387 388 389

  NR_UE_ULSCH_t *ulsch_ue = UE->ulsch[0][0][0];

390 391
  mod_order = nr_get_Qm_ul(Imcs, 0);
  code_rate = nr_get_code_rate_ul(Imcs, 0);
392
  available_bits = nr_get_G(nb_rb, nb_symb_sch, nb_re_dmrs, length_dmrs, mod_order, 1);
393
  TBS = nr_compute_tbs(mod_order,code_rate, nb_rb, nb_symb_sch, nb_re_dmrs*length_dmrs, 0, Nl);
yilmazt's avatar
yilmazt committed
394 395

  printf("\nAvailable bits %u TBS %u mod_order %d\n", available_bits, TBS, mod_order);
396 397 398 399 400 401 402 403

  /////////// setting rel15_ul parameters ///////////
  rel15_ul->number_rbs     = nb_rb;
  rel15_ul->number_symbols = nb_symb_sch;
  rel15_ul->Qm             = mod_order;
  rel15_ul->mcs            = Imcs;
  rel15_ul->rv             = rvidx;
  rel15_ul->n_layers       = Nl;
404
  rel15_ul->length_dmrs    = length_dmrs;
405
  rel15_ul->R              = code_rate;
406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425
  ///////////////////////////////////////////////////

  double *modulated_input = malloc16(sizeof(double) * 16 * 68 * 384); // [hna] 16 segments, 68*Zc
  short *channel_output_fixed = malloc16(sizeof(short) * 16 * 68 * 384);
  short *channel_output_uncoded = malloc16(sizeof(unsigned short) * 16 * 68 * 384);
  unsigned int errors_bit_uncoded = 0;
  unsigned char *estimated_output_bit;
  unsigned char *test_input_bit;
  unsigned int errors_bit = 0;

  test_input_bit = (unsigned char *) malloc16(sizeof(unsigned char) * 16 * 68 * 384);
  estimated_output_bit = (unsigned char *) malloc16(sizeof(unsigned char) * 16 * 68 * 384);

  unsigned char *test_input;
  test_input = (unsigned char *) malloc16(sizeof(unsigned char) * TBS / 8);

  for (i = 0; i < TBS / 8; i++)
    test_input[i] = (unsigned char) rand();


Khalid Ahmed's avatar
Khalid Ahmed committed
426 427 428 429 430 431 432
  /////////////////////////[adk] preparing NR_UE_ULSCH_t parameters///////////////////////// A HOT FIX until creating nfapi_nr_ul_config_ulsch_pdu_rel15_t
  ///////////
  ulsch_ue->nb_re_dmrs = nb_re_dmrs;
  ulsch_ue->length_dmrs =  length_dmrs;
  ulsch_ue->rnti = n_rnti;
  ///////////
  ////////////////////////////////////////////////////////////////////////////////////////////
433 434 435 436 437

  /////////////////////////[adk] preparing UL harq_process parameters/////////////////////////
  ///////////
  NR_UL_UE_HARQ_t *harq_process_ul_ue = ulsch_ue->harq_processes[harq_pid];

438
  N_PRB_oh   = 0; // higher layer (RRC) parameter xOverhead in PUSCH-ServingCellConfig
Khalid Ahmed's avatar
Khalid Ahmed committed
439 440
  N_RE_prime = NR_NB_SC_PER_RB*nb_symb_sch - nb_re_dmrs - N_PRB_oh;

441 442 443 444 445
  if (harq_process_ul_ue) {

    harq_process_ul_ue->mcs = Imcs;
    harq_process_ul_ue->Nl = Nl;
    harq_process_ul_ue->nb_rb = nb_rb;
Khalid Ahmed's avatar
Khalid Ahmed committed
446 447
    harq_process_ul_ue->number_of_symbols = nb_symb_sch;
    harq_process_ul_ue->num_of_mod_symbols = N_RE_prime*nb_rb*nb_codewords;
448 449 450 451 452 453 454
    harq_process_ul_ue->rvidx = rvidx;
    harq_process_ul_ue->TBS = TBS;
    harq_process_ul_ue->a = &test_input[0];

  }
  ///////////
  ////////////////////////////////////////////////////////////////////////////////////////////
455

456
#ifdef DEBUG_NR_ULSCHSIM
yilmazt's avatar
yilmazt committed
457
  for (i = 0; i < TBS / 8; i++) printf("test_input[i]=%hhu \n",test_input[i]);
458 459
#endif

Khalid Ahmed's avatar
Khalid Ahmed committed
460
  /////////////////////////ULSCH coding/////////////////////////
461 462 463 464 465
  ///////////

  if (input_fd == NULL) {
    nr_ulsch_encoding(ulsch_ue, frame_parms, harq_pid);
  }
466 467
  
  printf("\n");
468

469 470
  ///////////
  ////////////////////////////////////////////////////////////////////
471

472 473 474
  for (SNR = snr0; SNR < snr1; SNR += snr_step) {
    n_errors = 0;
    n_false_positive = 0;
475

476 477 478 479 480
    for (trial = 0; trial < n_trials; trial++) {

      errors_bit_uncoded = 0;

      for (i = 0; i < available_bits; i++) {
481 482

#ifdef DEBUG_CODER
483 484
        if ((i&0xf)==0)
          printf("\ne %d..%d:    ",i,i+15);
485
#endif
486 487 488 489 490 491
        /*
            if (i<16){
               printf("ulsch_encoder output f[%d] = %d\n",i,ulsch_ue->harq_processes[0]->f[i]);
            }
        */

492
        if (ulsch_ue->g[i] == 0)
493 494 495 496 497 498
          modulated_input[i] = 1.0;        ///sqrt(2);  //QPSK
        else
          modulated_input[i] = -1.0;        ///sqrt(2);
  
        //if (i<16) printf("modulated_input[%d] = %d\n",i,modulated_input[i]);

499 500 501 502 503 504 505
#if 1
        SNR_lin = pow(10, SNR / 10.0);
        sigma = 1.0 / sqrt(2 * SNR_lin);
        channel_output_fixed[i] = (short) quantize(sigma / 4.0 / 4.0,
                                                   modulated_input[i] + sigma * gaussdouble(0.0, 1.0),
                                                   qbits);
#else
506
        channel_output_fixed[i] = (short) quantize(0.01, modulated_input[i], qbits);
507
#endif
508
        //printf("channel_output_fixed[%d]: %d\n",i,channel_output_fixed[i]);
509

510 511 512 513 514
        //Uncoded BER
        if (channel_output_fixed[i] < 0)
          channel_output_uncoded[i] = 1;  //QPSK demod
        else
          channel_output_uncoded[i] = 0;
515

516 517 518 519 520
        if (channel_output_uncoded[i] != ulsch_ue->harq_processes[harq_pid]->f[i])
          errors_bit_uncoded = errors_bit_uncoded + 1;
      }

      printf("errors bits uncoded %u\n", errors_bit_uncoded);
521
      printf("\n");
522
#ifdef DEBUG_CODER
523 524
      printf("\n");
      exit(-1);
525
#endif
526 527

      ret = nr_ulsch_decoding(gNB, UE_id, channel_output_fixed, frame_parms,
528
                              frame, nb_symb_sch, nb_re_dmrs, subframe, harq_pid, is_crnti);
529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547

      if (ret > ulsch_gNB->max_ldpc_iterations)
        n_errors++;

      //count errors
      errors_bit = 0;

      for (i = 0; i < TBS; i++) {
        estimated_output_bit[i] = (ulsch_gNB->harq_processes[harq_pid]->b[i/8] & (1 << (i & 7))) >> (i & 7);
        test_input_bit[i] = (test_input[i / 8] & (1 << (i & 7))) >> (i & 7); // Further correct for multiple segments

        if (estimated_output_bit[i] != test_input_bit[i]) {
          errors_bit++;
        }
      }

      if (errors_bit > 0) {
        n_false_positive++;
        if (n_trials == 1)
yilmazt's avatar
yilmazt committed
548
          printf("errors_bit %u (trial %d)\n", errors_bit, trial);
549
      }
550
      printf("\n");
551 552 553 554 555 556 557
    }
    
    printf("*****************************************\n");
    printf("SNR %f, BLER %f (false positive %f)\n", SNR,
           (float) n_errors / (float) n_trials,
           (float) n_false_positive / (float) n_trials);
    printf("*****************************************\n");
558
    printf("\n");
559

560
    if (errors_bit == 0) {
561
      printf("PUSCH test OK\n");
562
      printf("\n");
563
      break;
564
    }
565
    printf("\n");
566 567 568 569 570 571 572 573 574
  }

  if (output_fd)
    fclose(output_fd);

  if (input_fd)
    fclose(input_fd);

  return (n_errors);
575 576
}