ulsim.c 64.8 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
/*
* 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>
28
#include "common/ran_context.h"
29 30
#include "common/config/config_userapi.h"
#include "common/utils/LOG/log.h"
31
#include "common/utils/nr/nr_common.h"
32
#include "PHY/defs_gNB.h"
33 34
#include "PHY/defs_nr_common.h"
#include "PHY/defs_nr_UE.h"
35
#include "PHY/phy_vars_nr_ue.h"
36
#include "PHY/types.h"
37 38
#include "PHY/INIT/phy_init.h"
#include "PHY/MODULATION/modulation_UE.h"
39 40 41
#include "PHY/MODULATION/nr_modulation.h"
#include "PHY/NR_REFSIG/dmrs_nr.h"
#include "PHY/NR_REFSIG/refsig_defs_ue.h"
42
#include "PHY/NR_TRANSPORT/nr_dlsch.h"
43 44
#include "PHY/NR_TRANSPORT/nr_sch_dmrs.h"
#include "PHY/NR_TRANSPORT/nr_transport_proto.h"
45 46
#include "PHY/NR_TRANSPORT/nr_ulsch.h"
#include "PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h"
47
#include "PHY/TOOLS/tools_defs.h"
Francesco Mani's avatar
Francesco Mani committed
48
#include "SCHED_NR/fapi_nr_l1.h"
49
#include "SCHED_NR/sched_nr.h"
50
#include "SCHED_NR_UE/defs.h"
51
#include "SCHED_NR_UE/fapi_nr_ue_l1.h"
52 53 54
#include "openair1/SIMULATION/TOOLS/sim.h"
#include "openair1/SIMULATION/RF/rf.h"
#include "openair1/SIMULATION/NR_PHY/nr_unitary_defs.h"
Francesco Mani's avatar
Francesco Mani committed
55
#include "openair2/RRC/NR/MESSAGES/asn1_msg.h"
Raymond Knopp's avatar
Raymond Knopp committed
56
//#include "openair1/SIMULATION/NR_PHY/nr_dummy_functions.c"
57
#include "openair2/LAYER2/NR_MAC_UE/mac_proto.h"
58
#include "openair2/LAYER2/NR_MAC_gNB/mac_proto.h"
Sakthivel Velumani's avatar
Sakthivel Velumani committed
59
#include "common/utils/threadPool/thread-pool.h"
60
#include "PHY/NR_REFSIG/ptrs_nr.h"
61
#define inMicroS(a) (((double)(a))/(get_cpu_freq_GHz()*1000.0))
62
#include "SIMULATION/LTE_PHY/common_sim.h"
63

Laurent's avatar
Laurent committed
64 65 66
#include <openair2/LAYER2/MAC/mac_vars.h>
#include <openair2/RRC/LTE/rrc_vars.h>

Raymond Knopp's avatar
Raymond Knopp committed
67
#include <executables/softmodem-common.h>
dir's avatar
dir committed
68
#include "PHY/NR_REFSIG/ul_ref_seq_nr.h"
69
#include <openair3/ocp-gtpu/gtp_itf.h>
70
#include "executables/nr-uesoftmodem.h"
71
//#define DEBUG_ULSIM
72

73 74 75 76 77 78
const char *__asan_default_options()
{
  /* don't do leak checking in nr_ulsim, not finished yet */
  return "detect_leaks=0";
}

79 80 81
LCHAN_DESC DCCH_LCHAN_DESC,DTCH_DL_LCHAN_DESC,DTCH_UL_LCHAN_DESC;
rlc_info_t Rlc_info_um,Rlc_info_am_config;

82 83 84
PHY_VARS_gNB *gNB;
PHY_VARS_NR_UE *UE;
RAN_CONTEXT_t RC;
85
char *uecap_file;
86 87
int32_t uplink_frequency_offset[MAX_NUM_CCs][4];

Laurent THOMAS's avatar
Laurent THOMAS committed
88
uint16_t sf_ahead=4 ;
Aniq's avatar
Aniq committed
89
int slot_ahead=6 ;
Laurent THOMAS's avatar
Laurent THOMAS committed
90
uint16_t sl_ahead=0;
91
double cpuf;
92
//uint8_t nfapi_mode = 0;
93
uint64_t downlink_frequency[MAX_NUM_CCs][4];
94 95
THREAD_STRUCT thread_struct;
nfapi_ue_release_request_body_t release_rntis;
96

97 98 99
//Fixme: Uniq dirty DU instance, by global var, datamodel need better management
instance_t DUuniqInstance=0;
instance_t CUuniqInstance=0;
100 101 102 103 104 105 106 107 108 109 110
teid_t newGtpuCreateTunnel(instance_t instance,
                           rnti_t rnti,
                           int incoming_bearer_id,
                           int outgoing_bearer_id,
                           teid_t outgoing_teid,
                           int qfi,
                           transport_layer_addr_t remoteAddr,
                           int port,
                           gtpCallback callBack,
                           gtpCallbackSDAP callBackSDAP) {
  return 0;
111
}
112 113 114 115 116

int newGtpuDeleteAllTunnels(instance_t instance, rnti_t rnti) {
  return 0;
}

117
extern void fix_scd(NR_ServingCellConfig_t *scd);// forward declaration
118

119 120 121 122 123 124 125 126 127 128 129 130
int8_t nr_mac_rrc_data_ind_ue(const module_id_t module_id,
                              const int CC_id,
                              const uint8_t gNB_index,
                              const frame_t frame,
                              const sub_frame_t sub_frame,
                              const rnti_t rnti,
                              const channel_t channel,
                              const uint8_t* pduP,
                              const sdu_size_t pdu_len)
{
  return 0;
}
131

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

void
rrc_data_ind(
144
  const protocol_ctxt_t *const ctxt_pP,
145 146 147 148 149 150
  const rb_id_t                Srb_id,
  const sdu_size_t             sdu_sizeP,
  const uint8_t   *const       buffer_pP
)
{
}
151

rmagueta's avatar
rmagueta committed
152

153 154 155 156 157 158 159 160
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;
}
161

Laurent THOMAS's avatar
Laurent THOMAS committed
162 163 164 165 166 167
int gtpv1u_delete_s1u_tunnel(const instance_t instance, const gtpv1u_enb_delete_tunnel_req_t *const req_pP) {
  return 0;
}

int gtpv1u_delete_ngu_tunnel( const instance_t instance,
			      gtpv1u_gnb_delete_tunnel_req_t *req) {
rmagueta's avatar
rmagueta committed
168 169 170
  return 0;
}

171 172 173 174 175 176 177 178
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;
}
179

heshanyun's avatar
heshanyun committed
180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205
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;
}

206
// Dummy function to avoid linking error at compilation of nr-ulsim
207 208 209 210 211
int is_x2ap_enabled(void)
{
  return 0;
}

212 213 214 215 216
void nr_rrc_ue_generate_RRCSetupRequest(module_id_t module_id, const uint8_t gNB_index)
{
  return;
}

217 218 219 220 221 222 223
int8_t nr_mac_rrc_data_req_ue(const module_id_t Mod_idP,
                              const int         CC_id,
                              const uint8_t     gNB_id,
                              const frame_t     frameP,
                              const rb_id_t     Srb_id,
                              uint8_t           *buffer_pP)
{
rmagueta's avatar
rmagueta committed
224 225 226
  return 0;
}

rmagueta's avatar
rmagueta committed
227 228 229 230 231 232 233 234 235 236 237
int DU_send_INITIAL_UL_RRC_MESSAGE_TRANSFER(module_id_t     module_idP,
                                            int             CC_idP,
                                            int             UE_id,
                                            rnti_t          rntiP,
                                            const uint8_t   *sduP,
                                            sdu_size_t      sdu_lenP,
                                            const uint8_t   *sdu2P,
                                            sdu_size_t      sdu2_lenP) {
  return 0;
}

Robert Schmidt's avatar
Robert Schmidt committed
238 239
nr_bler_struct nr_bler_data[NR_NUM_MCS];

240
//nFAPI P7 dummy functions
Mahesh's avatar
Mahesh committed
241 242 243 244 245

int oai_nfapi_dl_tti_req(nfapi_nr_dl_tti_request_t *dl_config_req) { return(0);  }
int oai_nfapi_tx_data_req(nfapi_nr_tx_data_request_t *tx_data_req){ return(0);  }
int oai_nfapi_ul_dci_req(nfapi_nr_ul_dci_request_t *ul_dci_req){ return(0);  }
int oai_nfapi_ul_tti_req(nfapi_nr_ul_tti_request_t *ul_tti_req){ return(0);  }
Mahesh's avatar
Mahesh committed
246 247 248 249 250
int oai_nfapi_nr_rx_data_indication(nfapi_nr_rx_data_indication_t *ind) { return(0);  }
int oai_nfapi_nr_crc_indication(nfapi_nr_crc_indication_t *ind) { return(0);  }
int oai_nfapi_nr_srs_indication(nfapi_nr_srs_indication_t *ind) { return(0);  }
int oai_nfapi_nr_uci_indication(nfapi_nr_uci_indication_t *ind) { return(0);  }
int oai_nfapi_nr_rach_indication(nfapi_nr_rach_indication_t *ind) { return(0);  }
Mahesh's avatar
Mahesh committed
251

252 253 254
int nr_derive_key(int alg_type, uint8_t alg_id,
               const uint8_t key[32], uint8_t **out)
{
rmagueta's avatar
rmagueta committed
255 256 257
  return 0;
}

258 259
void processSlotTX(void *arg) {}

Sakthivel Velumani's avatar
Sakthivel Velumani committed
260 261 262 263 264
nrUE_params_t nrUE_params;

nrUE_params_t *get_nrUE_params(void) {
  return &nrUE_params;
}
265 266 267 268
// needed for some functions
uint16_t n_rnti = 0x1234;
openair0_config_t openair0_cfg[MAX_CARDS];

269
channel_desc_t *UE2gNB[NUMBER_OF_UE_MAX][NUMBER_OF_gNB_MAX];
270

271 272
int main(int argc, char **argv)
{
273

274
  char c;
laurent's avatar
laurent committed
275
  int i;
276 277
  double SNR, snr0 = -2.0, snr1 = 2.0;
  double sigma, sigma_dB;
278
  double snr_step = .2;
279
  uint8_t snr1set = 0;
Raymond Knopp's avatar
Raymond Knopp committed
280
  int slot = 8, frame = 1;
281
  FILE *output_fd = NULL;
282
  double **s_re,**s_im,**r_re,**r_im;
283
  //uint8_t write_output_file = 0;
284
  int trial, n_trials = 1, n_false_positive = 0, delay = 0;
285
  double maxDoppler = 0.0;
286
  uint8_t n_tx = 1, n_rx = 1;
287
  //uint8_t transmission_mode = 1;
288
  //uint16_t Nid_cell = 0;
289
  channel_desc_t *UE2gNB;
290 291
  uint8_t extended_prefix_flag = 0;
  //int8_t interf1 = -21, interf2 = -21;
292
  FILE *input_fd = NULL;
293
  SCM_t channel_model = AWGN;  //Rayleigh1_anticorr;
294
  corr_level_t corr_level = CORR_LEVEL_LOW;
295
  uint16_t N_RB_DL = 106, N_RB_UL = 106, mu = 1;
296

Laurent's avatar
Laurent committed
297
  NB_UE_INST = 1;
298

299 300
  //unsigned char frame_type = 0;
  NR_DL_FRAME_PARMS *frame_parms;
301
  int loglvl = OAILOG_WARNING;
302
  uint16_t nb_symb_sch = 12;
303
  int start_symbol = 0;
304
  uint16_t nb_rb = 50;
305
  int Imcs = 9;
306
  uint8_t precod_nbr_layers = 1;
307
  int gNB_id = 0;
Khalid Ahmed's avatar
Khalid Ahmed committed
308
  int tx_offset;
309
  int32_t txlev_sum = 0, atxlev[4];
Ahmed Hussein's avatar
Ahmed Hussein committed
310
  int start_rb = 0;
311
  int UE_id =0; // [hna] only works for UE_id = 0 because NUMBER_OF_NR_UE_MAX is set to 1 (phy_init_nr_gNB causes segmentation fault)
312
  int print_perf = 0;
313
  cpuf = get_cpu_freq_GHz();
314
  int msg3_flag = 0;
315
  int rv_index = 0;
316 317 318
  float roundStats;
  double effRate;
  double effTP;
319
  float eff_tp_check = 100;
320
  int ldpc_offload_flag = 0;
321
  uint8_t max_rounds = 4;
322
  int chest_type[2] = {0};
323

324
  int enable_ptrs = 0;
325 326 327
  int modify_dmrs = 0;
  /* L_PTRS = ptrs_arg[0], K_PTRS = ptrs_arg[1] */
  int ptrs_arg[2] = {-1,-1};// Invalid values
328
  int dmrs_arg[4] = {-1,-1,-1,-1};// Invalid values
329 330 331
  uint16_t ptrsSymPos = 0;
  uint16_t ptrsSymbPerSlot = 0;
  uint16_t ptrsRePerSymb = 0;
332

333
  uint8_t transform_precoding = transformPrecoder_disabled; // 0 - ENABLE, 1 - DISABLE
dir's avatar
dir committed
334 335
  uint8_t num_dmrs_cdm_grps_no_data = 1;
  uint8_t mcs_table = 0;
336
  int ilbrm = 0;
dir's avatar
dir committed
337

338
  UE_nr_rxtx_proc_t UE_proc;
339
  FILE *scg_fd=NULL;
340
  int file_offset = 0;
341

342
  double DS_TDL = .03;
Francesco Mani's avatar
Francesco Mani committed
343
  int ibwps=24;
344
  int ibwp_rboffset=41;
345
  int params_from_file = 0;
346
  int threadCnt=0;
347
  int max_ldpc_iterations = 5;
yilmazt's avatar
yilmazt committed
348
  if ( load_configmodule(argc,argv,CONFIG_ENABLECMDLINEONLY) == 0 ) {
yilmazt's avatar
yilmazt committed
349
    exit_fun("[NR_ULSIM] Error, configuration module init failed\n");
350
  }
351
  int ul_proc_error = 0; // uplink processing checking status flag
352 353 354
  //logInit();
  randominit(0);

355 356 357
  /* initialize the sin-cos table */
   InitSinLUT();

Hongzhi Wang's avatar
Hongzhi Wang committed
358
  while ((c = getopt(argc, argv, "a:b:c:d:ef:g:h:i:kl:m:n:op:q:r:s:t:u:v:w:y:z:C:F:G:H:I:M:N:PR:S:T:U:L:ZW:")) != -1) {
359
    printf("handling optarg %c\n",c);
360
    switch (c) {
361 362 363 364 365

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

366 367 368 369 370 371 372 373 374
    case 'a':
      start_symbol = atoi(optarg);
      AssertFatal(start_symbol >= 0 && start_symbol < 13,"start_symbol %d is not in 0..12\n",start_symbol);
      break;

    case 'b':
      nb_symb_sch = atoi(optarg);
      AssertFatal(nb_symb_sch > 0 && nb_symb_sch < 15,"start_symbol %d is not in 1..14\n",nb_symb_sch);
      break;
375

376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392
    case 'c':
      n_rnti = atoi(optarg);
      AssertFatal(n_rnti > 0 && n_rnti<=65535,"Illegal n_rnti %x\n",n_rnti);
      break;

    case 'd':
      delay = atoi(optarg);
      break;
      
    case 'e':
      msg3_flag = 1;
      break;
      
    case 'f':
      scg_fd = fopen(optarg, "r");
      
      if (scg_fd == NULL) {
393 394
        printf("Error opening %s\n", optarg);
        exit(-1);
395
      }
396

397 398 399
      break;
      
    case 'g':
400

401
      switch ((char) *optarg) {
402 403
        case 'A':
          channel_model = TDL_A;
404
          DS_TDL = 0.030; // 30 ns
405 406
          printf("Channel model: TDLA30\n");
          break;
407
        case 'B':
408
          channel_model = TDL_B;
409
          DS_TDL = 0.100; // 100ns
410 411
          printf("Channel model: TDLB100\n");
          break;
412
        case 'C':
413 414 415 416 417 418 419
          channel_model = TDL_C;
          DS_TDL = 0.300; // 300 ns
          printf("Channel model: TDLC300\n");
          break;
        default:
          printf("Unsupported channel model!\n");
          exit(-1);
420
      }
421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437

      if (optarg[1] == ',') {
        switch (optarg[2]) {
          case 'l':
            corr_level = CORR_LEVEL_LOW;
            break;
          case 'm':
            corr_level = CORR_LEVEL_MEDIUM;
            break;
          case 'h':
            corr_level = CORR_LEVEL_HIGH;
            break;
          default:
            printf("Invalid correlation level!\n");
        }
      }

438 439
      break;
      
440
    case 'i':
441 442 443 444 445
      i=0;
      do {
        chest_type[i>>1] = atoi(&optarg[i]);
        i+=2;
      } while (optarg[i-1] == ',');
446
      break;
447 448 449 450 451
	
    case 'k':
      printf("Setting threequarter_fs_flag\n");
      openair0_cfg[0].threequarter_fs= 1;
      break;
452

453 454 455 456 457 458 459
    case 'l':
      nb_symb_sch = atoi(optarg);
      break;
      
    case 'm':
      Imcs = atoi(optarg);
      break;
460 461 462 463

    case 'W':
      precod_nbr_layers = atoi(optarg);
      break;
464

465 466 467
    case 'n':
      n_trials = atoi(optarg);
      break;
468 469

    case 'o':
Hongzhi Wang's avatar
Hongzhi Wang committed
470
      ldpc_offload_flag = 1;
471
      break;
472 473 474 475
      
    case 'p':
      extended_prefix_flag = 1;
      break;
476 477 478 479

    case 'q':
      mcs_table = atoi(optarg);
      break;
480

481 482 483 484 485 486 487 488
    case 'r':
      nb_rb = atoi(optarg);
      break;
      
    case 's':
      snr0 = atof(optarg);
      printf("Setting SNR0 to %f\n", snr0);
      break;
489

490
    case 'C':
491 492
      threadCnt = atoi(optarg);
      break;
493

Sakthivel Velumani's avatar
Sakthivel Velumani committed
494 495 496 497
    case 'u':
      mu = atoi(optarg);
      break;

Hongzhi Wang's avatar
Hongzhi Wang committed
498 499
    case 'v':
      max_rounds = atoi(optarg);
500
      AssertFatal(max_rounds > 0 && max_rounds < 16, "Unsupported number of rounds %d, should be in [1,16]\n", max_rounds);
Hongzhi Wang's avatar
Hongzhi Wang committed
501 502
      break;

Sakthivel Velumani's avatar
Sakthivel Velumani committed
503 504 505 506
    case 'w':
      start_rb = atoi(optarg);
      break;

507
    case 't':
508
      eff_tp_check = atof(optarg);
509
      break;
510

511
      /*
512 513 514 515 516 517 518 519 520
	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;
      */
      
521 522 523
      /*case 'x':
        transmission_mode = atoi(optarg);
        break;*/
524 525 526
      
    case 'y':
      n_tx = atoi(optarg);
527
      if ((n_tx == 0) || (n_tx > 4)) {
francescomani's avatar
francescomani committed
528 529
        printf("Unsupported number of tx antennas %d\n", n_tx);
        exit(-1);
530 531 532 533 534
      }
      break;
      
    case 'z':
      n_rx = atoi(optarg);
535
      if ((n_rx == 0) || (n_rx > 8)) {
francescomani's avatar
francescomani committed
536 537
        printf("Unsupported number of rx antennas %d\n", n_rx);
        exit(-1);
538 539
      }
      break;
540

541 542 543
    case 'F':
      input_fd = fopen(optarg, "r");
      if (input_fd == NULL) {
francescomani's avatar
francescomani committed
544 545
        printf("Problem with filename %s\n", optarg);
        exit(-1);
546 547
      }
      break;
548 549 550 551 552 553 554 555 556

    case 'G':
      file_offset = atoi(optarg);
      break;

    case 'H':
      slot = atoi(optarg);
      break;

557 558 559 560
    case 'I':
      max_ldpc_iterations = atoi(optarg);
      break;

561
    case 'M':
562
      ilbrm = atoi(optarg);
563 564 565
      break;
      
    case 'N':
Francesco Mani's avatar
Francesco Mani committed
566
     // Nid_cell = atoi(optarg);
567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587
      break;
      
    case 'R':
      N_RB_DL = atoi(optarg);
      N_RB_UL = N_RB_DL;
      break;
      
    case 'S':
      snr1 = atof(optarg);
      snr1set = 1;
      printf("Setting SNR1 to %f\n", snr1);
      break;
      
    case 'P':
      print_perf=1;
      opp_enabled=1;
      break;
      
    case 'L':
      loglvl = atoi(optarg);
      break;
588 589 590

   case 'T':
      enable_ptrs=1;
591 592 593 594 595
      i=0;
      do {
        ptrs_arg[i>>1] = atoi(&optarg[i]);
        i+=2;
      } while (optarg[i-1] == ',');
596 597 598 599
      break;

    case 'U':
      modify_dmrs = 1;
600 601 602 603 604
      i=0;
      do {
        dmrs_arg[i>>1] = atoi(&optarg[i]);
        i+=2;
      } while (optarg[i-1] == ',');
605
      break;
606

607 608 609 610
    case 'Q':
      params_from_file = 1;
      break;

dir's avatar
dir committed
611
    case 'Z':
612
      transform_precoding = transformPrecoder_enabled;
dir's avatar
dir committed
613 614
      num_dmrs_cdm_grps_no_data = 2;
      mcs_table = 3;
615
      printf("NOTE: TRANSFORM PRECODING (SC-FDMA) is ENABLED in UPLINK (0 - ENABLE, 1 - DISABLE) : %d \n", transform_precoding);
dir's avatar
dir committed
616 617
      break;

618 619
    default:
    case 'h':
620
      printf("%s -h(elp) -p(extended_prefix) -N cell_id -f output_filename -F input_filename -g channel_model -i Intefrence0 -j Interference1 -n n_frames -s snr0 -S snr1 -t Delayspread -x transmission_mode -y TXant -z RXant -A interpolation_file -C(alibration offset dB) -N CellId -Z Enable SC-FDMA in Uplink \n", argv[0]);
621 622 623
      //printf("-d Use TDD\n");
      printf("-d Introduce delay in terms of number of samples\n");
      printf("-f Number of frames to simulate\n");
624
      printf("-g Channel model configuration. Arguments list: Number of arguments = 2, {Channel model: [A] TDLA30, [B] TDLB100, [C] TDLC300}, {Correlation: [l] Low, [m] Medium, [h] High}, e.g. -g A,l\n");
625
      printf("-h This message\n");
626
      printf("-i Change channel estimation technique. Arguments list: Number of arguments=2, Frequency domain {0:Linear interpolation, 1:PRB based averaging}, Time domain {0:Estimates of last DMRS symbol, 1:Average of DMRS symbols}. e.g. -i 1,0\n");
627 628
      //printf("-j Relative strength of second intefering eNB (in dB) - cell_id mod 3 = 2\n");
      printf("-s Starting SNR, runs from SNR0 to SNR0 + 10 dB if ending SNR isn't given\n");
629
      printf("-S Ending SNR, runs from SNR0 to SNR1\n");
630 631
      printf("-m MCS value\n");
      printf("-n Number of trials to simulate\n");
632
      printf("-o ldpc offload flag\n");
633
      printf("-p Use extended prefix mode\n");
634
      printf("-q MCS table\n");
Arash's avatar
Arash committed
635
      printf("-r Number of allocated resource blocks for PUSCH\n");
Sakthivel Velumani's avatar
Sakthivel Velumani committed
636 637
      printf("-u Set the numerology\n");
      printf("-w Start PRB for PUSCH\n");
638
      //printf("-x Transmission mode (1,2,6 for the moment)\n");
639 640
      printf("-y Number of TX antennas used at UE\n");
      printf("-z Number of RX antennas used at gNB\n");
Hongzhi Wang's avatar
Hongzhi Wang committed
641
      printf("-v Set the max rounds\n");
642 643 644
      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 Input filename (.txt format) for RX conformance testing\n");
645
      printf("-G Offset of samples to read from file (0 default)\n");
646
      printf("-L <log level, 0(errors), 1(warning), 2(info) 3(debug) 4 (trace)>\n");
647
      printf("-I Maximum LDPC decoder iterations\n");
648
      printf("-M Use limited buffer rate-matching\n");
649 650
      printf("-N Nid_cell\n");
      printf("-O oversampling factor (1,2,4,8,16)\n");
Arash's avatar
Arash committed
651
      printf("-R Maximum number of available resorce blocks (N_RB_DL)\n");
652
      printf("-t Acceptable effective throughput (in percentage)\n");
653
      printf("-P Print ULSCH performances\n");
654 655
      printf("-T Enable PTRS, arguments list: Number of arguments=2 L_PTRS{0,1,2} K_PTRS{2,4}, e.g. -T 0,2 \n");
      printf("-U Change DMRS Config, arguments list: Number of arguments=4, DMRS Mapping Type{0=A,1=B}, DMRS AddPos{0:3}, DMRS Config Type{1,2}, Number of CDM groups without data{1,2,3} e.g. -U 0,2,0,1 \n");
656
      printf("-Q If -F used, read parameters from file\n");
dir's avatar
dir committed
657
      printf("-Z If -Z is used, SC-FDMA or transform precoding is enabled in Uplink \n");
francescomani's avatar
francescomani committed
658
      printf("-W Num of layer for PUSCH\n");
659 660
      exit(-1);
      break;
661

662 663
    }
  }
664
  
665 666 667 668
  logInit();
  set_glog(loglvl);
  T_stdout = 1;

669
  get_softmodem_params()->phy_test = 1;
670
  get_softmodem_params()->do_ra = 0;
Francesco Mani's avatar
Francesco Mani committed
671 672
  get_softmodem_params()->usim_test = 1;

673 674
  if (snr1set == 0)
    snr1 = snr0 + 10;
675

676 677 678 679 680 681 682 683 684
  double sampling_frequency, tx_bandwidth, rx_bandwidth;
  uint32_t samples;
  get_samplerate_and_bw(mu,
                        N_RB_DL,
                        openair0_cfg[0].threequarter_fs,
                        &sampling_frequency,
                        &samples,
                        &tx_bandwidth,
                        &rx_bandwidth);
685

686
  LOG_I( PHY,"++++++++++++++++++++++++++++++++++++++++++++++%i+++++++++++++++++++++++++++++++++++++++++",loglvl);  
687

688 689
  UE2gNB = new_channel_desc_scm(n_tx,
                                n_rx, channel_model,
690 691
                                sampling_frequency/1e6,
                                tx_bandwidth,
692
                                DS_TDL,
693 694 695 696 697
                                corr_level,
                                0,
                                0,
                                0,
                                0);
698

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

704 705
  UE2gNB->max_Doppler = maxDoppler;

706
  RC.gNB = (PHY_VARS_gNB **) malloc(sizeof(PHY_VARS_gNB *));
707
  RC.gNB[0] = calloc(1,sizeof(PHY_VARS_gNB));
708
  gNB = RC.gNB[0];
709
  gNB->ofdm_offset_divisor = UINT_MAX;
710
  initNotifiedFIFO(&gNB->respDecode);
711

712
  initFloatingCoresTpool(threadCnt, &gNB->threadPool, false, "gNB-tpool");
713 714 715 716 717
  initNotifiedFIFO(&gNB->respDecode);
  initNotifiedFIFO(&gNB->L1_tx_free);
  initNotifiedFIFO(&gNB->L1_tx_filled);
  initNotifiedFIFO(&gNB->L1_tx_out);
  notifiedFIFO_elt_t *msgL1Tx = newNotifiedFIFO_elt(sizeof(processingData_L1tx_t), 0, &gNB->L1_tx_free, NULL);
Sakthivel Velumani's avatar
Sakthivel Velumani committed
718 719
  processingData_L1tx_t *msgDataTx = (processingData_L1tx_t *)NotifiedFifoData(msgL1Tx);
  msgDataTx->slot = -1;
720
  //gNB_config = &gNB->gNB_config;
721

722
  //memset((void *)&gNB->UL_INFO,0,sizeof(gNB->UL_INFO));
Francesco Mani's avatar
Francesco Mani committed
723 724 725 726
  gNB->UL_INFO.rx_ind.pdu_list = (nfapi_nr_rx_data_pdu_t *)malloc(NB_UE_INST*sizeof(nfapi_nr_rx_data_pdu_t));
  gNB->UL_INFO.crc_ind.crc_list = (nfapi_nr_crc_t *)malloc(NB_UE_INST*sizeof(nfapi_nr_crc_t));
  gNB->UL_INFO.rx_ind.number_of_pdus = 0;
  gNB->UL_INFO.crc_ind.number_crcs = 0;
727
  gNB->max_ldpc_iterations = max_ldpc_iterations;
728
  gNB->pusch_thres = -20;
729
  frame_parms = &gNB->frame_parms; //to be initialized I suppose (maybe not necessary for PBCH)
730

731 732 733 734
  frame_parms->N_RB_DL = N_RB_DL;
  frame_parms->N_RB_UL = N_RB_UL;
  frame_parms->Ncp = extended_prefix_flag ? EXTENDED : NORMAL;

735 736 737 738
  s_re = malloc(n_tx*sizeof(double*));
  s_im = malloc(n_tx*sizeof(double*));
  r_re = malloc(n_rx*sizeof(double*));
  r_im = malloc(n_rx*sizeof(double*));
739

740 741 742 743
  RC.nb_nr_macrlc_inst = 1;
  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;
744
  mac_top_init_gNB(ngran_gNB);
laurent's avatar
laurent committed
745
  //gNB_MAC_INST* gNB_mac = RC.nrmac[0];
746 747 748
  gNB_RRC_INST rrc;
  memset((void*)&rrc,0,sizeof(rrc));

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

  NR_ServingCellConfigCommon_t *scc = rrc.carrier.servingcellconfigcommon;
752
  NR_ServingCellConfig_t *scd = calloc(1,sizeof(NR_ServingCellConfig_t));
753 754 755
  NR_CellGroupConfig_t *secondaryCellGroup=calloc(1,sizeof(*secondaryCellGroup));
  prepare_scc(rrc.carrier.servingcellconfigcommon);
  uint64_t ssb_bitmap;
756
  fill_scc_sim(rrc.carrier.servingcellconfigcommon,&ssb_bitmap,N_RB_DL,N_RB_DL,mu,mu);
757

Francesco Mani's avatar
Francesco Mani committed
758 759
  fix_scc(scc,ssb_bitmap);

760 761
  prepare_scd(scd);

762
  // TODO do a UECAP for phy-sim
763
  const gNB_RrcConfigurationReq conf = {
764
    .pdsch_AntennaPorts = { .N1 = 1, .N2 = 1, .XP = 1 },
765
    .pusch_AntennaPorts = n_rx,
766 767 768 769 770 771
    .minRXTXTIME = 0,
    .do_CSIRS = 0,
    .do_SRS = 0,
    .force_256qam_off = false
  };
  fill_default_secondaryCellGroup(scc, scd, secondaryCellGroup, NULL, 0, 1, &conf, 0);
772

773
  // xer_fprint(stdout, &asn_DEF_NR_CellGroupConfig, (const void*)secondaryCellGroup);
774

775 776 777
  /* RRC parameter validation for secondaryCellGroup */
  fix_scd(scd);

778
  AssertFatal((gNB->if_inst = NR_IF_Module_init(0))!=NULL,"Cannot register interface");
779

780
  gNB->if_inst->NR_PHY_config_req = nr_phy_config_request;
781
  // common configuration
782
  rrc_mac_config_req_gNB(0, conf.pdsch_AntennaPorts, n_rx, 0, 6, scc, &rrc.carrier.mib, rrc.carrier.siblock1, 0, 0, NULL);
783
  // UE dedicated configuration
784
  rrc_mac_config_req_gNB(0, conf.pdsch_AntennaPorts, n_rx, 0, 6, scc, &rrc.carrier.mib, rrc.carrier.siblock1, 1,
785
                         secondaryCellGroup->spCellConfig->reconfigurationWithSync->newUE_Identity, secondaryCellGroup);
786
  frame_parms->nb_antennas_tx = 1;
787 788
  frame_parms->nb_antennas_rx = n_rx;
  nfapi_nr_config_request_scf_t *cfg = &gNB->gNB_config;
789
  cfg->carrier_config.num_tx_ant.value = 1;
790
  cfg->carrier_config.num_rx_ant.value = n_rx;
791

Raymond Knopp's avatar
Raymond Knopp committed
792
//  nr_phy_config_request_sim(gNB,N_RB_DL,N_RB_DL,mu,0,0x01);
793
  gNB->ldpc_offload_flag = ldpc_offload_flag;
794 795
  gNB->chest_freq = chest_type[0];
  gNB->chest_time = chest_type[1];
Hongzhi Wang's avatar
Hongzhi Wang committed
796

797
  phy_init_nr_gNB(gNB,0,1);
798 799 800 801
  /* RU handles rxdataF, and gNB just has a pointer. Here, we don't have an RU,
   * so we need to allocate that memory as well. */
  for (i = 0; i < n_rx; i++)
    gNB->common_vars.rxdataF[i] = malloc16_clear(gNB->frame_parms.samples_per_frame_wCP*sizeof(int32_t));
802
  N_RB_DL = gNB->frame_parms.N_RB_DL;
803

804 805 806 807 808
  /* no RU: need to have rxdata */
  c16_t **rxdata;
  rxdata = malloc(n_rx * sizeof(*rxdata));
  for (int i = 0; i < n_rx; ++i)
    rxdata[i] = malloc(gNB->frame_parms.samples_per_frame * sizeof(**rxdata));
809 810 811

  NR_BWP_Uplink_t *ubwp=secondaryCellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->uplinkBWP_ToAddModList->list.array[0];

812 813 814

  //configure UE
  UE = malloc(sizeof(PHY_VARS_NR_UE));
Florian Kaltenberger's avatar
Florian Kaltenberger committed
815 816 817 818
  memset((void*)UE,0,sizeof(PHY_VARS_NR_UE));
  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;
819
  memcpy(&UE->frame_parms, frame_parms, sizeof(NR_DL_FRAME_PARMS));
820
  UE->frame_parms.nb_antennas_tx = n_tx;
821
  UE->frame_parms.nb_antennas_rx = 0;
822

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

828
  init_nr_ue_transport(UE);
829

francescomani's avatar
francescomani committed
830 831 832 833
  for(int n_scid = 0; n_scid<2; n_scid++) {
    UE->scramblingID_ulsch[n_scid] = frame_parms->Nid_cell;
    nr_init_pusch_dmrs(UE, frame_parms->Nid_cell, n_scid);
  }
834 835 836 837 838 839 840 841 842 843

  //Configure UE
  NR_UE_RRC_INST_t rrcue;
  memset(&rrcue,0,sizeof(NR_UE_RRC_INST_t));
  rrc.carrier.MIB = (uint8_t*) malloc(4);
  rrc.carrier.sizeof_MIB = do_MIB_NR(&rrc,0);
  rrcue.mib = rrc.carrier.mib.message.choice.mib;
  rrcue.scell_group_config=secondaryCellGroup;
  nr_l2_init_ue(&rrcue);

844 845 846 847 848 849 850 851 852 853
  NR_UE_MAC_INST_t* UE_mac = get_mac_inst(0);
  
  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;
  UE->if_inst->dl_indication = nr_ue_dl_indication;
  UE->if_inst->ul_indication = nr_ue_ul_indication;
  
  UE_mac->if_module = nr_ue_if_module_init(0);

854
//  nr_rrc_mac_config_req_ue(0,0,0,rrc.carrier.mib.message.choice.mib, NULL, NULL, secondaryCellGroup);
855 856 857

  nr_ue_phy_config_request(&UE_mac->phy_config);

858

859
  unsigned char harq_pid = 0;
860

861
  NR_gNB_ULSCH_t *ulsch_gNB = gNB->ulsch[UE_id];
Hongzhi Wang's avatar
Hongzhi Wang committed
862

863
  //nfapi_nr_ul_config_ulsch_pdu *rel15_ul = &ulsch_gNB->harq_processes[harq_pid]->ulsch_pdu;
864 865 866 867 868
  nfapi_nr_ul_tti_request_t     *UL_tti_req  = malloc(sizeof(*UL_tti_req));
  NR_Sched_Rsp_t *Sched_INFO = malloc(sizeof(*Sched_INFO));
  memset((void*)Sched_INFO,0,sizeof(*Sched_INFO));
  Sched_INFO->UL_tti_req=UL_tti_req;

869 870
  nfapi_nr_pusch_pdu_t  *pusch_pdu = &UL_tti_req->pdus_list[0].pusch_pdu;

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

873 874
  unsigned char *estimated_output_bit;
  unsigned char *test_input_bit;
875
  uint32_t errors_decoding = 0;
876
  
877

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

Ahmed Hussein's avatar
Ahmed Hussein committed
881 882
  nr_scheduled_response_t scheduled_response;
  fapi_nr_ul_config_request_t ul_config;
883
  fapi_nr_tx_request_t tx_req;
884 885 886 887 888

  memset(&scheduled_response, 0, sizeof(scheduled_response));
  memset(&ul_config, 0, sizeof(ul_config));
  memset(&tx_req, 0, sizeof(tx_req));

889 890 891 892 893
  uint8_t ptrs_mcs1 = 2;
  uint8_t ptrs_mcs2 = 4;
  uint8_t ptrs_mcs3 = 10;
  uint16_t n_rb0 = 25;
  uint16_t n_rb1 = 75;
dir's avatar
dir committed
894
  
895
  uint16_t pdu_bit_map = PUSCH_PDU_BITMAP_PUSCH_DATA; // | PUSCH_PDU_BITMAP_PUSCH_PTRS;
896
  uint8_t crc_status = 0;
897

dir's avatar
dir committed
898 899
  unsigned char mod_order = nr_get_Qm_ul(Imcs, mcs_table);
  uint16_t      code_rate = nr_get_code_rate_ul(Imcs, mcs_table);
900 901 902 903 904

  uint8_t mapping_type = typeB; // Default Values
  pusch_dmrs_type_t dmrs_config_type = pusch_dmrs_type1; // Default Values
  pusch_dmrs_AdditionalPosition_t add_pos = pusch_dmrs_pos0; // Default Values

905 906
  /* validate parameters othwerwise default values are used */
  /* -U flag can be used to set DMRS parameters*/
907
  if(modify_dmrs) {
908
    if(dmrs_arg[0] == 0)
909
      mapping_type = typeA;
910
    else if (dmrs_arg[0] == 1)
911
      mapping_type = typeB;
912 913 914
    /* Additional DMRS positions */
    if(dmrs_arg[1] >= 0 && dmrs_arg[1] <=3 )
      add_pos = dmrs_arg[1];
915
    /* DMRS Conf Type 1 or 2 */
916
    if(dmrs_arg[2] == 1)
917
      dmrs_config_type = pusch_dmrs_type1;
918
    else if(dmrs_arg[2] == 2)
919
      dmrs_config_type = pusch_dmrs_type2;
920
    num_dmrs_cdm_grps_no_data = dmrs_arg[3];
921 922 923
  }

  uint8_t  length_dmrs         = pusch_len1;
924
  uint16_t l_prime_mask        = get_l_prime(nb_symb_sch, mapping_type, add_pos, length_dmrs, start_symbol, NR_MIB__dmrs_TypeA_Position_pos2);
925
  uint16_t number_dmrs_symbols = get_dmrs_symbols_in_slot(l_prime_mask, nb_symb_sch);
926
  printf("num dmrs sym %d\n",number_dmrs_symbols);
927
  uint8_t  nb_re_dmrs          = (dmrs_config_type == pusch_dmrs_type1) ? 6 : 4;
dir's avatar
dir committed
928

929 930 931 932 933 934
  uint32_t tbslbrm = 0;
  if (ilbrm)
    tbslbrm = nr_compute_tbslbrm(mcs_table,
                                 N_RB_UL,
                                 precod_nbr_layers);

935
  if ((UE->frame_parms.nb_antennas_tx==4)&&(precod_nbr_layers==4))
936
    num_dmrs_cdm_grps_no_data = 2;
937

938
  if (transform_precoding == transformPrecoder_enabled) {
dir's avatar
dir committed
939 940 941 942

    AssertFatal(enable_ptrs == 0, "PTRS NOT SUPPORTED IF TRANSFORM PRECODING IS ENABLED\n");

    int8_t index = get_index_for_dmrs_lowpapr_seq((NR_NB_SC_PER_RB/2) * nb_rb);
943
    AssertFatal(index >= 0, "Num RBs not configured according to 3GPP 38.211 section 6.3.1.4. For PUSCH with transform precoding, num RBs cannot be multiple of any other primenumber other than 2,3,5\n");
dir's avatar
dir committed
944 945
    
    dmrs_config_type = pusch_dmrs_type1;
946
    nb_re_dmrs       = 6;
dir's avatar
dir committed
947 948 949 950

    printf("[ULSIM]: TRANSFORM PRECODING ENABLED. Num RBs: %d, index for DMRS_SEQ: %d\n", nb_rb, index);
  }

951
  nb_re_dmrs = nb_re_dmrs * num_dmrs_cdm_grps_no_data;
dir's avatar
dir committed
952

953
  unsigned int available_bits  = nr_get_G(nb_rb, nb_symb_sch, nb_re_dmrs, number_dmrs_symbols, mod_order, precod_nbr_layers);
954 955
  unsigned int TBS             = nr_compute_tbs(mod_order, code_rate, nb_rb, nb_symb_sch, nb_re_dmrs * number_dmrs_symbols, 0, 0, precod_nbr_layers);

dir's avatar
dir committed
956
  
957 958 959 960
  printf("[ULSIM]: length_dmrs: %u, l_prime_mask: %u	number_dmrs_symbols: %u, mapping_type: %u add_pos: %d \n", length_dmrs, l_prime_mask, number_dmrs_symbols, mapping_type, add_pos);
  printf("[ULSIM]: CDM groups: %u, dmrs_config_type: %d, num_rbs: %u, nb_symb_sch: %u\n", num_dmrs_cdm_grps_no_data, dmrs_config_type, nb_rb, nb_symb_sch);
  printf("[ULSIM]: MCS: %d, mod order: %u, code_rate: %u\n", Imcs, mod_order, code_rate);
  printf("[ULSIM]: VALUE OF G: %u, TBS: %u\n", available_bits, TBS);
dir's avatar
dir committed
961 962 963
  

  
964 965 966 967 968
  uint8_t ulsch_input_buffer[TBS/8];

  ulsch_input_buffer[0] = 0x31;
  for (i = 1; i < TBS/8; i++) {
    ulsch_input_buffer[i] = (unsigned char) rand();
969 970
  }

971
  uint8_t ptrs_time_density = get_L_ptrs(ptrs_mcs1, ptrs_mcs2, ptrs_mcs3, Imcs, mcs_table);
972
  uint8_t ptrs_freq_density = get_K_ptrs(n_rb0, n_rb1, nb_rb);
973 974
  int     ptrs_symbols      = 0; // to calculate total PTRS RE's in a slot

975 976
  double ts = 1.0/(frame_parms->subcarrier_spacing * frame_parms->ofdm_symbol_size);

977
  /* -T option enable PTRS */
978
  if(enable_ptrs) {
979 980 981 982 983 984
    /* validate parameters othwerwise default values are used */
    if(ptrs_arg[0] == 0 || ptrs_arg[0] == 1 || ptrs_arg[0] == 2 )
      ptrs_time_density = ptrs_arg[0];
    if(ptrs_arg[1] == 2 || ptrs_arg[1] == 4 )
      ptrs_freq_density = ptrs_arg[1];
    pdu_bit_map |= PUSCH_PDU_BITMAP_PUSCH_PTRS;
985
    printf("NOTE: PTRS Enabled with L %d, K %d \n", ptrs_time_density, ptrs_freq_density );
986
  }
987

988
  if (input_fd != NULL || n_trials == 1) max_rounds=1;
989

990
  if(1<<ptrs_time_density >= nb_symb_sch)
991
    pdu_bit_map &= ~PUSCH_PDU_BITMAP_PUSCH_PTRS; // disable PUSCH PTRS
992

993
  printf("\n");
994

995 996 997 998 999 1000 1001 1002 1003 1004 1005
  int frame_length_complex_samples = frame_parms->samples_per_subframe*NR_NUMBER_OF_SUBFRAMES_PER_FRAME;
  for (int aatx=0; aatx<n_tx; aatx++) {
    s_re[aatx] = calloc(1,frame_length_complex_samples*sizeof(double));
    s_im[aatx] = calloc(1,frame_length_complex_samples*sizeof(double));
  }

  for (int aarx=0; aarx<n_rx; aarx++) {
    r_re[aarx] = calloc(1,frame_length_complex_samples*sizeof(double));
    r_im[aarx] = calloc(1,frame_length_complex_samples*sizeof(double));
  }

Sakthivel Velumani's avatar
Sakthivel Velumani committed
1006
  //for (int i=0;i<16;i++) printf("%f\n",gaussdouble(0.0,1.0));
1007
  int read_errors=0;
1008

1009
  int slot_offset = frame_parms->get_samples_slot_timestamp(slot,frame_parms,0);
1010 1011 1012 1013 1014 1015
  int slot_length = slot_offset - frame_parms->get_samples_slot_timestamp(slot-1,frame_parms,0);

  if (input_fd != NULL)	{
    // 800 samples is N_TA_OFFSET for FR1 @ 30.72 Ms/s,
    AssertFatal(frame_parms->subcarrier_spacing==30000,"only 30 kHz for file input for now (%d)\n",frame_parms->subcarrier_spacing);
  
1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039
    if (params_from_file) {
      fseek(input_fd,file_offset*((slot_length<<2)+4000+16),SEEK_SET);
      read_errors+=fread((void*)&n_rnti,sizeof(int16_t),1,input_fd);
      printf("rnti %x\n",n_rnti);
      read_errors+=fread((void*)&nb_rb,sizeof(int16_t),1,input_fd);
      printf("nb_rb %d\n",nb_rb);
      int16_t dummy;
      read_errors+=fread((void*)&start_rb,sizeof(int16_t),1,input_fd);
      //fread((void*)&dummy,sizeof(int16_t),1,input_fd);
      printf("rb_start %d\n",start_rb);
      read_errors+=fread((void*)&nb_symb_sch,sizeof(int16_t),1,input_fd);
      //fread((void*)&dummy,sizeof(int16_t),1,input_fd);
      printf("nb_symb_sch %d\n",nb_symb_sch);
      read_errors+=fread((void*)&start_symbol,sizeof(int16_t),1,input_fd);
      printf("start_symbol %d\n",start_symbol);
      read_errors+=fread((void*)&Imcs,sizeof(int16_t),1,input_fd);
      printf("mcs %d\n",Imcs);
      read_errors+=fread((void*)&rv_index,sizeof(int16_t),1,input_fd);
      printf("rv_index %d\n",rv_index);
      //    fread((void*)&harq_pid,sizeof(int16_t),1,input_fd);
      read_errors+=fread((void*)&dummy,sizeof(int16_t),1,input_fd);
      printf("harq_pid %d\n",harq_pid);
    }
    fseek(input_fd,file_offset*sizeof(int16_t)*2,SEEK_SET);
1040 1041
    for (int irx=0; irx<frame_parms->nb_antennas_rx; irx++) {
      fseek(input_fd,irx*(slot_length+15)*sizeof(int16_t)*2,SEEK_SET); // matlab adds samlples to the end to emulate channel delay
1042
      read_errors += fread((void *)&rxdata[irx][slot_offset-delay], sizeof(int16_t), slot_length<<1, input_fd);
1043 1044 1045 1046
      if (read_errors==0) {
        printf("error reading file\n");
        exit(1);
      }
1047 1048 1049 1050 1051
      for (int i=0;i<16;i+=2)
        printf("slot_offset %d : %d,%d\n",
               slot_offset,
               rxdata[irx][slot_offset].r,
               rxdata[irx][slot_offset].i);
1052
    }
Raymond Knopp's avatar
Raymond Knopp committed
1053

1054 1055
    mod_order = nr_get_Qm_ul(Imcs, mcs_table);
    code_rate = nr_get_code_rate_ul(Imcs, mcs_table);
1056
  }
1057 1058

  int ret = 1;
1059
  for (SNR = snr0; SNR < snr1; SNR += snr_step) {
Sakthivel Velumani's avatar
Sakthivel Velumani committed
1060
    varArray_t *table_rx=initVarArray(1000,sizeof(double));
1061 1062
    int error_flag = 0;
    n_false_positive = 0;
1063 1064 1065
    effRate = 0;
    effTP = 0;
    roundStats = 0;
Sakthivel Velumani's avatar
fixes  
Sakthivel Velumani committed
1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076
    reset_meas(&gNB->phy_proc_rx);
    reset_meas(&gNB->rx_pusch_stats);
    reset_meas(&gNB->ulsch_decoding_stats);
    reset_meas(&gNB->ulsch_deinterleaving_stats);
    reset_meas(&gNB->ulsch_rate_unmatching_stats);
    reset_meas(&gNB->ulsch_ldpc_decoding_stats);
    reset_meas(&gNB->ulsch_unscrambling_stats);
    reset_meas(&gNB->ulsch_channel_estimation_stats);
    reset_meas(&gNB->ulsch_llr_stats);
    reset_meas(&gNB->ulsch_channel_compensation_stats);
    reset_meas(&gNB->ulsch_rbs_extraction_stats);
1077 1078 1079 1080
    reset_meas(&UE->ulsch_ldpc_encoding_stats);
    reset_meas(&UE->ulsch_rate_matching_stats);
    reset_meas(&UE->ulsch_interleaving_stats);
    reset_meas(&UE->ulsch_encoding_stats);
1081

1082 1083 1084 1085 1086 1087
    uint32_t errors_scrambling[16] = {0};
    int n_errors[16] = {0};
    int round_trials[16] = {0};
    double blerStats[16] = {0};
    double berStats[16] = {0};

Raymond Knopp's avatar
Raymond Knopp committed
1088
    clear_pusch_stats(gNB);
Sakthivel Velumani's avatar
Sakthivel Velumani committed
1089
    for (trial = 0; trial < n_trials; trial++) {
1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123
      uint8_t round = 0;
      crc_status = 1;
      errors_decoding = 0;
      while (round < max_rounds && crc_status) {
        round_trials[round]++;
        ulsch_ue->harq_processes[harq_pid]->round = round;
        rv_index = nr_rv_round_map[round % 4];

        UE_proc.nr_slot_tx = slot;
        UE_proc.frame_tx = frame;

        UL_tti_req->SFN = frame;
        UL_tti_req->Slot = slot;
        UL_tti_req->n_pdus = 1;
        UL_tti_req->pdus_list[0].pdu_type = NFAPI_NR_UL_CONFIG_PUSCH_PDU_TYPE;
        UL_tti_req->pdus_list[0].pdu_size = sizeof(nfapi_nr_pusch_pdu_t);
        memset(pusch_pdu, 0, sizeof(nfapi_nr_pusch_pdu_t));

        int abwp_size = NRRIV2BW(ubwp->bwp_Common->genericParameters.locationAndBandwidth, 275);
        int abwp_start = NRRIV2PRBOFFSET(ubwp->bwp_Common->genericParameters.locationAndBandwidth, 275);
        int ibwp_size = ibwps;
        int ibwp_start = ibwp_rboffset;
        if (msg3_flag == 1) {
          if ((ibwp_start < abwp_start) || (ibwp_size > abwp_size))
            pusch_pdu->bwp_start = abwp_start;
          else
            pusch_pdu->bwp_start = ibwp_start;
          pusch_pdu->bwp_size = ibwp_size;
          start_rb = (ibwp_start - abwp_start);
          printf("msg3: ibwp_size %d, abwp_size %d, ibwp_start %d, abwp_start %d\n", ibwp_size, abwp_size, ibwp_start, abwp_start);
        } else {
          pusch_pdu->bwp_start = abwp_start;
          pusch_pdu->bwp_size = abwp_size;
        }
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 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165
        pusch_pdu->pusch_data.tb_size = TBS >> 3;
        pusch_pdu->pdu_bit_map = pdu_bit_map;
        pusch_pdu->rnti = n_rnti;
        pusch_pdu->mcs_index = Imcs;
        pusch_pdu->mcs_table = mcs_table;
        pusch_pdu->target_code_rate = code_rate;
        pusch_pdu->qam_mod_order = mod_order;
        pusch_pdu->transform_precoding = transform_precoding;
        pusch_pdu->data_scrambling_id = *scc->physCellId;
        pusch_pdu->nrOfLayers = precod_nbr_layers;
        pusch_pdu->ul_dmrs_symb_pos = l_prime_mask;
        pusch_pdu->dmrs_config_type = dmrs_config_type;
        pusch_pdu->ul_dmrs_scrambling_id = *scc->physCellId;
        pusch_pdu->scid = 0;
        pusch_pdu->dmrs_ports = ((1 << precod_nbr_layers) - 1);
        pusch_pdu->num_dmrs_cdm_grps_no_data = num_dmrs_cdm_grps_no_data;
        pusch_pdu->resource_alloc = 1;
        pusch_pdu->rb_start = start_rb;
        pusch_pdu->rb_size = nb_rb;
        pusch_pdu->vrb_to_prb_mapping = 0;
        pusch_pdu->frequency_hopping = 0;
        pusch_pdu->uplink_frequency_shift_7p5khz = 0;
        pusch_pdu->start_symbol_index = start_symbol;
        pusch_pdu->nr_of_symbols = nb_symb_sch;
        pusch_pdu->maintenance_parms_v3.tbSizeLbrmBytes = tbslbrm;
        pusch_pdu->pusch_data.rv_index = rv_index;
        pusch_pdu->pusch_data.harq_process_id = 0;
        pusch_pdu->pusch_data.new_data_indicator = trial & 0x1;
        pusch_pdu->pusch_data.num_cb = 0;
        pusch_pdu->pusch_ptrs.ptrs_time_density = ptrs_time_density;
        pusch_pdu->pusch_ptrs.ptrs_freq_density = ptrs_freq_density;
        pusch_pdu->pusch_ptrs.ptrs_ports_list = (nfapi_nr_ptrs_ports_t *)malloc(2 * sizeof(nfapi_nr_ptrs_ports_t));
        pusch_pdu->pusch_ptrs.ptrs_ports_list[0].ptrs_re_offset = 0;
        pusch_pdu->maintenance_parms_v3.ldpcBaseGraph = get_BG(TBS, code_rate);

        // if transform precoding is enabled
        if (transform_precoding == transformPrecoder_enabled) {
          pusch_pdu->dfts_ofdm.low_papr_group_number = *scc->physCellId % 30; // U as defined in 38.211 section 6.4.1.1.1.2
          pusch_pdu->dfts_ofdm.low_papr_sequence_number = 0; // V as defined in 38.211 section 6.4.1.1.1.2
          pusch_pdu->num_dmrs_cdm_grps_no_data = num_dmrs_cdm_grps_no_data;
        }
1166

1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203
        // prepare ULSCH/PUSCH reception
        pushNotifiedFIFO(&gNB->L1_tx_free, msgL1Tx); // to unblock the process in the beginning
        nr_schedule_response(Sched_INFO);

        // --------- setting parameters for UE --------

        scheduled_response.module_id = 0;
        scheduled_response.CC_id = 0;
        scheduled_response.frame = frame;
        scheduled_response.slot = slot;
        scheduled_response.dl_config = NULL;
        scheduled_response.ul_config = &ul_config;
        scheduled_response.tx_request = &tx_req;

        // Config UL TX PDU
        tx_req.slot = slot;
        tx_req.sfn = frame;
        // tx_req->tx_config // TbD
        tx_req.number_of_pdus = 1;
        tx_req.tx_request_body[0].pdu_length = TBS / 8;
        tx_req.tx_request_body[0].pdu_index = 0;
        tx_req.tx_request_body[0].pdu = &ulsch_input_buffer[0];

        ul_config.slot = slot;
        ul_config.number_pdus = 1;
        ul_config.ul_config_list[0].pdu_type = FAPI_NR_UL_CONFIG_TYPE_PUSCH;
        ul_config.ul_config_list[0].pusch_config_pdu.rnti = n_rnti;
        ul_config.ul_config_list[0].pusch_config_pdu.pdu_bit_map = pdu_bit_map;
        ul_config.ul_config_list[0].pusch_config_pdu.qam_mod_order = mod_order;
        ul_config.ul_config_list[0].pusch_config_pdu.rb_size = nb_rb;
        ul_config.ul_config_list[0].pusch_config_pdu.rb_start = start_rb;
        ul_config.ul_config_list[0].pusch_config_pdu.nr_of_symbols = nb_symb_sch;
        ul_config.ul_config_list[0].pusch_config_pdu.start_symbol_index = start_symbol;
        ul_config.ul_config_list[0].pusch_config_pdu.ul_dmrs_symb_pos = l_prime_mask;
        ul_config.ul_config_list[0].pusch_config_pdu.dmrs_config_type = dmrs_config_type;
        ul_config.ul_config_list[0].pusch_config_pdu.mcs_index = Imcs;
        ul_config.ul_config_list[0].pusch_config_pdu.mcs_table = mcs_table;
dir's avatar
dir committed
1204
        ul_config.ul_config_list[0].pusch_config_pdu.num_dmrs_cdm_grps_no_data = num_dmrs_cdm_grps_no_data;
1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229
        ul_config.ul_config_list[0].pusch_config_pdu.nrOfLayers = precod_nbr_layers;
        ul_config.ul_config_list[0].pusch_config_pdu.dmrs_ports = ((1 << precod_nbr_layers) - 1);
        ul_config.ul_config_list[0].pusch_config_pdu.absolute_delta_PUSCH = 0;
        ul_config.ul_config_list[0].pusch_config_pdu.target_code_rate = code_rate;
        ul_config.ul_config_list[0].pusch_config_pdu.tbslbrm = tbslbrm;

        ul_config.ul_config_list[0].pusch_config_pdu.pusch_data.tb_size = TBS / 8;
        ul_config.ul_config_list[0].pusch_config_pdu.pusch_data.new_data_indicator = trial & 0x1;
        ul_config.ul_config_list[0].pusch_config_pdu.pusch_data.rv_index = rv_index;
        ul_config.ul_config_list[0].pusch_config_pdu.pusch_data.harq_process_id = harq_pid;

        ul_config.ul_config_list[0].pusch_config_pdu.pusch_ptrs.ptrs_time_density = ptrs_time_density;
        ul_config.ul_config_list[0].pusch_config_pdu.pusch_ptrs.ptrs_freq_density = ptrs_freq_density;
        ul_config.ul_config_list[0].pusch_config_pdu.pusch_ptrs.ptrs_ports_list = (nfapi_nr_ue_ptrs_ports_t *)malloc(2 * sizeof(nfapi_nr_ue_ptrs_ports_t));
        ul_config.ul_config_list[0].pusch_config_pdu.pusch_ptrs.ptrs_ports_list[0].ptrs_re_offset = 0;

        ul_config.ul_config_list[0].pusch_config_pdu.transform_precoding = transform_precoding;

        // if transform precoding is enabled
        if (transform_precoding == transformPrecoder_enabled) {
          ul_config.ul_config_list[0].pusch_config_pdu.dfts_ofdm.low_papr_group_number = *scc->physCellId % 30; // U as defined in 38.211 section 6.4.1.1.1.2
          ul_config.ul_config_list[0].pusch_config_pdu.dfts_ofdm.low_papr_sequence_number = 0; // V as defined in 38.211 section 6.4.1.1.1.2
          // ul_config.ul_config_list[0].pusch_config_pdu.pdu_bit_map |= PUSCH_PDU_BITMAP_DFTS_OFDM;
          ul_config.ul_config_list[0].pusch_config_pdu.num_dmrs_cdm_grps_no_data = num_dmrs_cdm_grps_no_data;
        }
dir's avatar
dir committed
1230

1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259
        // nr_fill_ulsch(gNB,frame,slot,pusch_pdu); // Not needed as its its already filled as apart of "nr_schedule_response(Sched_INFO);"

        for (int i = 0; i < (TBS / 8); i++)
          ulsch_ue->harq_processes[harq_pid]->a[i] = i & 0xff;
        if (input_fd == NULL) {
          // set FAPI parameters for UE, put them in the scheduled response and call
          nr_ue_scheduled_response(&scheduled_response);

          /////////////////////////phy_procedures_nr_ue_TX///////////////////////
          ///////////

          phy_procedures_nrUE_TX(UE, &UE_proc, gNB_id);

          /* We need to call common sending function to send signal */
          LOG_D(PHY, "Sending Uplink data \n");
          nr_ue_pusch_common_procedures(UE, slot, &UE->frame_parms, UE->frame_parms.nb_antennas_tx);

          if (n_trials == 1) {
            LOG_M("txsig0.m", "txs0", &UE->common_vars.txdata[0][slot_offset], slot_length, 1, 1);
            LOG_M("txsig0F.m", "txs0F", UE->common_vars.txdataF[0], frame_parms->ofdm_symbol_size * 14, 1, 1);
            if (precod_nbr_layers > 1) {
              LOG_M("txsig1.m", "txs1", &UE->common_vars.txdata[1][slot_offset], slot_length, 1, 1);
              LOG_M("txsig1F.m", "txs1F", UE->common_vars.txdataF[1], frame_parms->ofdm_symbol_size * 14, 1, 1);
              if (precod_nbr_layers == 4) {
                LOG_M("txsig2.m", "txs2", &UE->common_vars.txdata[2][slot_offset], slot_length, 1, 1);
                LOG_M("txsig3.m", "txs3", &UE->common_vars.txdata[3][slot_offset], slot_length, 1, 1);
                LOG_M("txsig2F.m", "txs2F", UE->common_vars.txdataF[2], frame_parms->ofdm_symbol_size * 14, 1, 1);
                LOG_M("txsig3F.m", "txs3F", UE->common_vars.txdataF[3], frame_parms->ofdm_symbol_size * 14, 1, 1);
              }
1260 1261
            }
          }
1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292
          ///////////
          ////////////////////////////////////////////////////
          tx_offset = frame_parms->get_samples_slot_timestamp(slot, frame_parms, 0);
          txlev_sum = 0;
          for (int aa = 0; aa < UE->frame_parms.nb_antennas_tx; aa++) {
            atxlev[aa] = signal_energy(&UE->common_vars.txdata[aa][tx_offset + 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);

            txlev_sum += atxlev[aa];

            if (n_trials == 1)
              printf("txlev[%d] = %d (%f dB) txlev_sum %d\n", aa, atxlev[aa], 10 * log10((double)atxlev[aa]), txlev_sum);
          }
        } else
          n_trials = 1;

        if (input_fd == NULL) {
          // Justification of division by precod_nbr_layers:
          // When the channel is the identity matrix, the results in terms of SNR should be almost equal for 2x2 and 4x4.
          sigma_dB = 10 * log10((double)txlev_sum / precod_nbr_layers * ((double)frame_parms->ofdm_symbol_size / (12 * nb_rb))) - SNR;
          ;
          sigma = pow(10, sigma_dB / 10);

          if (n_trials == 1)
            printf("sigma %f (%f dB), txlev_sum %f (factor %f)\n", sigma, sigma_dB, 10 * log10((double)txlev_sum), (double)(double)frame_parms->ofdm_symbol_size / (12 * nb_rb));

          for (i = 0; i < slot_length; i++) {
            for (int aa = 0; aa < UE->frame_parms.nb_antennas_tx; aa++) {
              s_re[aa][i] = ((double)(((short *)&UE->common_vars.txdata[aa][slot_offset]))[(i << 1)]);
              s_im[aa][i] = ((double)(((short *)&UE->common_vars.txdata[aa][slot_offset]))[(i << 1) + 1]);
            }
1293
          }
1294

1295 1296 1297 1298 1299 1300
          if (UE2gNB->max_Doppler == 0) {
            multipath_channel(UE2gNB, s_re, s_im, r_re, r_im, slot_length, 0, (n_trials==1)?1:0);
          } else {
            multipath_tv_channel(UE2gNB, s_re, s_im, r_re, r_im, 2*slot_length, 0);
          }
          add_noise(rxdata, (const double **) r_re, (const double **) r_im, sigma, slot_length, slot_offset, ts, delay, pdu_bit_map, frame_parms->nb_antennas_rx);
1301

1302
        } /*End input_fd */
1303

1304 1305 1306 1307 1308 1309
        if (pusch_pdu->pdu_bit_map & PUSCH_PDU_BITMAP_PUSCH_PTRS) {
          set_ptrs_symb_idx(&ptrsSymPos, pusch_pdu->nr_of_symbols, pusch_pdu->start_symbol_index, 1 << ptrs_time_density, pusch_pdu->ul_dmrs_symb_pos);
          ptrsSymbPerSlot = get_ptrs_symbols_in_slot(ptrsSymPos, pusch_pdu->start_symbol_index, pusch_pdu->nr_of_symbols);
          ptrsRePerSymb = ((pusch_pdu->rb_size + ptrs_freq_density - 1) / ptrs_freq_density);
          LOG_D(PHY, "[ULSIM] PTRS Symbols in a slot: %2u, RE per Symbol: %3u, RE in a slot %4d\n", ptrsSymbPerSlot, ptrsRePerSymb, ptrsSymbPerSlot * ptrsRePerSymb);
        }
1310

1311 1312 1313 1314 1315
        //----------------------------------------------------------
        //------------------- gNB phy procedures -------------------
        //----------------------------------------------------------
        gNB->UL_INFO.rx_ind.number_of_pdus = 0;
        gNB->UL_INFO.crc_ind.number_crcs = 0;
1316

1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331
        for(uint8_t symbol = 0; symbol < (gNB->frame_parms.Ncp == EXTENDED ? 12 : 14); symbol++) {
          for (int aa = 0; aa < gNB->frame_parms.nb_antennas_rx; aa++)
            nr_slot_fep_ul(&gNB->frame_parms,
                           (int32_t*) rxdata[aa],
                           gNB->common_vars.rxdataF[aa],
                           symbol,
                           slot,
                           0);
        }

        for (int aa = 0; aa < gNB->frame_parms.nb_antennas_rx; aa++)  {
          apply_nr_rotation_ul(&gNB->frame_parms,
                               gNB->common_vars.rxdataF[aa],
                               slot,
                               0,
1332
                               gNB->frame_parms.Ncp == EXTENDED ? 12 : 14);
1333
        }
1334

1335
        ul_proc_error = phy_procedures_gNB_uespec_RX(gNB, frame, slot);
1336

1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349
        if (n_trials == 1 && round == 0) {
          LOG_M("rxsig0.m", "rx0", &rxdata[0][slot_offset], slot_length, 1, 1);
          LOG_M("rxsigF0.m", "rxsF0", gNB->common_vars.rxdataF[0], 14 * frame_parms->ofdm_symbol_size, 1, 1);
          if (precod_nbr_layers > 1) {
            LOG_M("rxsig1.m", "rx1", &rxdata[1][slot_offset], slot_length, 1, 1);
            LOG_M("rxsigF1.m", "rxsF1", gNB->common_vars.rxdataF[1], 14 * frame_parms->ofdm_symbol_size, 1, 1);
            if (precod_nbr_layers == 4) {
              LOG_M("rxsig2.m", "rx2", &rxdata[2][slot_offset], slot_length, 1, 1);
              LOG_M("rxsig3.m", "rx3", &rxdata[3][slot_offset], slot_length, 1, 1);
              LOG_M("rxsigF2.m", "rxsF2", gNB->common_vars.rxdataF[2], 14 * frame_parms->ofdm_symbol_size, 1, 1);
              LOG_M("rxsigF3.m", "rxsF3", gNB->common_vars.rxdataF[3], 14 * frame_parms->ofdm_symbol_size, 1, 1);
            }
          }
1350
        }
1351

1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414
        if (n_trials == 1 && round == 0) {
          __attribute__((unused)) int off = ((nb_rb & 1) == 1) ? 4 : 0;

          LOG_M("rxsigF0_ext.m",
                "rxsF0_ext",
                &gNB->pusch_vars[0]->rxdataF_ext[0][start_symbol * NR_NB_SC_PER_RB * pusch_pdu->rb_size],
                nb_symb_sch * (off + (NR_NB_SC_PER_RB * pusch_pdu->rb_size)),
                1,
                1);
          LOG_M("chestF0.m", "chF0", &gNB->pusch_vars[0]->ul_ch_estimates[0][start_symbol * frame_parms->ofdm_symbol_size], frame_parms->ofdm_symbol_size, 1, 1);
          LOG_M("chestT0.m", "chT0", &gNB->pusch_vars[0]->ul_ch_estimates_time[0][0], frame_parms->ofdm_symbol_size, 1, 1);
          LOG_M("chestF0_ext.m",
                "chF0_ext",
                &gNB->pusch_vars[0]->ul_ch_estimates_ext[0][(start_symbol + 1) * (off + (NR_NB_SC_PER_RB * pusch_pdu->rb_size))],
                (nb_symb_sch - 1) * (off + (NR_NB_SC_PER_RB * pusch_pdu->rb_size)),
                1,
                1);
          LOG_M("rxsigF0_comp.m",
                "rxsF0_comp",
                &gNB->pusch_vars[0]->rxdataF_comp[0][start_symbol * (off + (NR_NB_SC_PER_RB * pusch_pdu->rb_size))],
                nb_symb_sch * (off + (NR_NB_SC_PER_RB * pusch_pdu->rb_size)),
                1,
                1);
          LOG_M("chmagF0.m",
                "chmF0",
                &gNB->pusch_vars[0]->ul_ch_mag[0][start_symbol * (off + (NR_NB_SC_PER_RB * pusch_pdu->rb_size))],
                nb_symb_sch * (off + (NR_NB_SC_PER_RB * pusch_pdu->rb_size)),
                1,
                1);
          LOG_M("chmagbF0.m",
                "chmbF0",
                &gNB->pusch_vars[0]->ul_ch_magb[0][start_symbol * (off + (NR_NB_SC_PER_RB * pusch_pdu->rb_size))],
                nb_symb_sch * (off + (NR_NB_SC_PER_RB * pusch_pdu->rb_size)),
                1,
                1);
          LOG_M("rxsigF0_llrlayers0.m", "rxsF0_llrlayers0", &gNB->pusch_vars[0]->llr_layers[0][0], (nb_symb_sch - 1) * NR_NB_SC_PER_RB * pusch_pdu->rb_size * mod_order, 1, 0);

          if (precod_nbr_layers == 2) {
            LOG_M("rxsigF1_ext.m",
                  "rxsF1_ext",
                  &gNB->pusch_vars[0]->rxdataF_ext[1][start_symbol * NR_NB_SC_PER_RB * pusch_pdu->rb_size],
                  nb_symb_sch * (off + (NR_NB_SC_PER_RB * pusch_pdu->rb_size)),
                  1,
                  1);

            LOG_M("chestF3.m", "chF3", &gNB->pusch_vars[0]->ul_ch_estimates[3][start_symbol * frame_parms->ofdm_symbol_size], frame_parms->ofdm_symbol_size, 1, 1);

            LOG_M("chestF3_ext.m",
                  "chF3_ext",
                  &gNB->pusch_vars[0]->ul_ch_estimates_ext[3][(start_symbol + 1) * (off + (NR_NB_SC_PER_RB * pusch_pdu->rb_size))],
                  (nb_symb_sch - 1) * (off + (NR_NB_SC_PER_RB * pusch_pdu->rb_size)),
                  1,
                  1);

            LOG_M("rxsigF2_comp.m",
                  "rxsF2_comp",
                  &gNB->pusch_vars[0]->rxdataF_comp[2][start_symbol * (off + (NR_NB_SC_PER_RB * pusch_pdu->rb_size))],
                  nb_symb_sch * (off + (NR_NB_SC_PER_RB * pusch_pdu->rb_size)),
                  1,
                  1);

            LOG_M("rxsigF0_llrlayers1.m", "rxsF0_llrlayers1", &gNB->pusch_vars[0]->llr_layers[1][0], (nb_symb_sch - 1) * NR_NB_SC_PER_RB * pusch_pdu->rb_size * mod_order, 1, 0);
          }
1415

1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480
          if (precod_nbr_layers == 4) {
            LOG_M("rxsigF1_ext.m",
                  "rxsF1_ext",
                  &gNB->pusch_vars[0]->rxdataF_ext[1][start_symbol * NR_NB_SC_PER_RB * pusch_pdu->rb_size],
                  nb_symb_sch * (off + (NR_NB_SC_PER_RB * pusch_pdu->rb_size)),
                  1,
                  1);
            LOG_M("rxsigF2_ext.m",
                  "rxsF2_ext",
                  &gNB->pusch_vars[0]->rxdataF_ext[2][start_symbol * NR_NB_SC_PER_RB * pusch_pdu->rb_size],
                  nb_symb_sch * (off + (NR_NB_SC_PER_RB * pusch_pdu->rb_size)),
                  1,
                  1);
            LOG_M("rxsigF3_ext.m",
                  "rxsF3_ext",
                  &gNB->pusch_vars[0]->rxdataF_ext[3][start_symbol * NR_NB_SC_PER_RB * pusch_pdu->rb_size],
                  nb_symb_sch * (off + (NR_NB_SC_PER_RB * pusch_pdu->rb_size)),
                  1,
                  1);

            LOG_M("chestF5.m", "chF5", &gNB->pusch_vars[0]->ul_ch_estimates[5][start_symbol * frame_parms->ofdm_symbol_size], frame_parms->ofdm_symbol_size, 1, 1);
            LOG_M("chestF10.m", "chF10", &gNB->pusch_vars[0]->ul_ch_estimates[10][start_symbol * frame_parms->ofdm_symbol_size], frame_parms->ofdm_symbol_size, 1, 1);
            LOG_M("chestF15.m", "chF15", &gNB->pusch_vars[0]->ul_ch_estimates[15][start_symbol * frame_parms->ofdm_symbol_size], frame_parms->ofdm_symbol_size, 1, 1);

            LOG_M("chestF5_ext.m",
                  "chF5_ext",
                  &gNB->pusch_vars[0]->ul_ch_estimates_ext[5][(start_symbol + 1) * (off + (NR_NB_SC_PER_RB * pusch_pdu->rb_size))],
                  (nb_symb_sch - 1) * (off + (NR_NB_SC_PER_RB * pusch_pdu->rb_size)),
                  1,
                  1);
            LOG_M("chestF10_ext.m",
                  "chF10_ext",
                  &gNB->pusch_vars[0]->ul_ch_estimates_ext[10][(start_symbol + 1) * (off + (NR_NB_SC_PER_RB * pusch_pdu->rb_size))],
                  (nb_symb_sch - 1) * (off + (NR_NB_SC_PER_RB * pusch_pdu->rb_size)),
                  1,
                  1);
            LOG_M("chestF15_ext.m",
                  "chF15_ext",
                  &gNB->pusch_vars[0]->ul_ch_estimates_ext[15][(start_symbol + 1) * (off + (NR_NB_SC_PER_RB * pusch_pdu->rb_size))],
                  (nb_symb_sch - 1) * (off + (NR_NB_SC_PER_RB * pusch_pdu->rb_size)),
                  1,
                  1);

            LOG_M("rxsigF4_comp.m",
                  "rxsF4_comp",
                  &gNB->pusch_vars[0]->rxdataF_comp[4][start_symbol * (off + (NR_NB_SC_PER_RB * pusch_pdu->rb_size))],
                  nb_symb_sch * (off + (NR_NB_SC_PER_RB * pusch_pdu->rb_size)),
                  1,
                  1);
            LOG_M("rxsigF8_comp.m",
                  "rxsF8_comp",
                  &gNB->pusch_vars[0]->rxdataF_comp[8][start_symbol * (off + (NR_NB_SC_PER_RB * pusch_pdu->rb_size))],
                  nb_symb_sch * (off + (NR_NB_SC_PER_RB * pusch_pdu->rb_size)),
                  1,
                  1);
            LOG_M("rxsigF12_comp.m",
                  "rxsF12_comp",
                  &gNB->pusch_vars[0]->rxdataF_comp[12][start_symbol * (off + (NR_NB_SC_PER_RB * pusch_pdu->rb_size))],
                  nb_symb_sch * (off + (NR_NB_SC_PER_RB * pusch_pdu->rb_size)),
                  1,
                  1);
            LOG_M("rxsigF0_llrlayers1.m", "rxsF0_llrlayers1", &gNB->pusch_vars[0]->llr_layers[1][0], (nb_symb_sch - 1) * NR_NB_SC_PER_RB * pusch_pdu->rb_size * mod_order, 1, 0);
            LOG_M("rxsigF0_llrlayers2.m", "rxsF0_llrlayers2", &gNB->pusch_vars[0]->llr_layers[2][0], (nb_symb_sch - 1) * NR_NB_SC_PER_RB * pusch_pdu->rb_size * mod_order, 1, 0);
            LOG_M("rxsigF0_llrlayers3.m", "rxsF0_llrlayers3", &gNB->pusch_vars[0]->llr_layers[3][0], (nb_symb_sch - 1) * NR_NB_SC_PER_RB * pusch_pdu->rb_size * mod_order, 1, 0);
          }
1481

1482 1483
          LOG_M("rxsigF0_llr.m", "rxsF0_llr", &gNB->pusch_vars[0]->llr[0], precod_nbr_layers * (nb_symb_sch - 1) * NR_NB_SC_PER_RB * pusch_pdu->rb_size * mod_order, 1, 0);
        }
1484

1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506
        if ((gNB->ulsch[0]->last_iteration_cnt >= gNB->ulsch[0]->max_ldpc_iterations + 1) || ul_proc_error == 1) {
          error_flag = 1;
          n_errors[round]++;
          crc_status = 1;
        } else
          crc_status = 0;
        if (n_trials == 1)
          printf("end of round %d rv_index %d\n", round, rv_index);

        //----------------------------------------------------------
        //----------------- count and print errors -----------------
        //----------------------------------------------------------

        if ((pusch_pdu->pdu_bit_map & PUSCH_PDU_BITMAP_PUSCH_PTRS) && (SNR == snr0) && (trial == 0) && (round == 0)) {
          ptrs_symbols = 0;
          for (int i = pusch_pdu->start_symbol_index; i < pusch_pdu->start_symbol_index + pusch_pdu->nr_of_symbols; i++)
            ptrs_symbols += ((gNB->pusch_vars[UE_id]->ptrs_symbols) >> i) & 1;

          /*  2*5*(50/2), for RB = 50,K = 2 for 5 OFDM PTRS symbols */
          available_bits -= 2 * ptrs_symbols * ((nb_rb + ptrs_freq_density - 1) / ptrs_freq_density);
          printf("[ULSIM][PTRS] Available bits are: %5u, removed PTRS bits are: %5d \n", available_bits, (ptrsSymbPerSlot * ptrsRePerSymb * 2));
        }
1507

1508 1509 1510 1511 1512 1513 1514 1515 1516 1517
        for (i = 0; i < available_bits; i++) {
          if (((ulsch_ue->harq_processes[harq_pid]->f[i] == 0) && (gNB->pusch_vars[UE_id]->llr[i] <= 0))
              || ((ulsch_ue->harq_processes[harq_pid]->f[i] == 1) && (gNB->pusch_vars[UE_id]->llr[i] >= 0))) {
            /*if(errors_scrambling == 0)
              printf("\x1B[34m" "[frame %d][trial %d]\t1st bit in error in unscrambling = %d\n" "\x1B[0m", frame, trial, i);*/
            errors_scrambling[round]++;
          }
        }
        round++;
      } // round
1518

1519 1520
      if (n_trials == 1 && errors_scrambling[0] > 0) {
        printf("\x1B[31m""[frame %d][trial %d]\tnumber of errors in unscrambling = %u\n" "\x1B[0m", frame, trial, errors_scrambling[0]);
1521
      }
1522

1523
      for (i = 0; i < TBS; i++) {
1524
      
1525 1526
        estimated_output_bit[i] = (ulsch_gNB->harq_processes[harq_pid]->b[i / 8] & (1 << (i & 7))) >> (i & 7);
        test_input_bit[i] = (ulsch_ue->harq_processes[harq_pid]->b[i / 8] & (1 << (i & 7))) >> (i & 7);
1527
      
1528 1529 1530 1531 1532
        if (estimated_output_bit[i] != test_input_bit[i]) {
          /*if(errors_decoding == 0)
              printf("\x1B[34m""[frame %d][trial %d]\t1st bit in error in decoding     = %d\n" "\x1B[0m", frame, trial, i);*/
          errors_decoding++;
        }
1533
      }
1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552
      if (n_trials == 1) {
        for (int r = 0; r < ulsch_ue->harq_processes[harq_pid]->C; r++)
          for (int i = 0; i < ulsch_ue->harq_processes[harq_pid]->K >> 3; i++) {
            if ((ulsch_ue->harq_processes[harq_pid]->c[r][i] ^ ulsch_gNB->harq_processes[harq_pid]->c[r][i]) != 0)
              printf("************");
            /*printf("r %d: in[%d] %x, out[%d] %x (%x)\n",r,
              i,ulsch_ue->harq_processes[harq_pid]->c[r][i],
              i,ulsch_gNB->harq_processes[harq_pid]->c[r][i],
              ulsch_ue->harq_processes[harq_pid]->c[r][i]^ulsch_gNB->harq_processes[harq_pid]->c[r][i]);*/
          }
      }
      if (errors_decoding > 0 && error_flag == 0) {
        n_false_positive++;
        if (n_trials==1)
	  printf("\x1B[31m""[frame %d][trial %d]\tnumber of errors in decoding     = %u\n" "\x1B[0m", frame, trial, errors_decoding);
      } 
      roundStats += ((float)round);
      if (!crc_status)
        effRate += ((double)TBS) / (double)round;
1553
    } // trial loop
1554 1555 1556

    roundStats/=((float)n_trials);
    effRate /= (double)n_trials;
1557 1558
    
    printf("*****************************************\n");
1559
    printf("SNR %f: n_errors (%d/%d", SNR, n_errors[0], round_trials[0]);
1560
    for (int r = 1; r < max_rounds; r++)
1561
      printf(",%d/%d", n_errors[r], round_trials[r]);
1562
    printf(") (negative CRC), false_positive %d/%d, errors_scrambling (%u/%u",
1563
           n_false_positive, n_trials, errors_scrambling[0], available_bits * n_trials);
1564
    for (int r = 1; r < max_rounds; r++)
1565
      printf(",%u/%u", errors_scrambling[r], available_bits * n_trials);
1566
    printf(")\n");
1567
    printf("\n");
1568 1569

    for (int r = 0; r < max_rounds; r++) {
1570 1571
      blerStats[r] = (double)n_errors[r] / round_trials[r];
      berStats[r] = (double)errors_scrambling[r] / available_bits/round_trials[r];
1572
    }
1573 1574
    effTP = effRate/(double)TBS * (double)100;
    printf("SNR %f: Channel BLER (%e", SNR, blerStats[0]);
1575
    for (int r = 1; r < max_rounds; r++)
1576 1577
      printf(",%e", blerStats[r]);
    printf(" Channel BER (%e", berStats[0]);
1578
    for (int r = 1; r < max_rounds; r++)
1579 1580
      printf(",%e", berStats[r]);
    printf(") Avg round %.2f, Eff Rate %.4f bits/slot, Eff Throughput %.2f, TBS %u bits/slot\n", roundStats,effRate,effTP,TBS);
Raymond Knopp's avatar
Raymond Knopp committed
1581

rmagueta's avatar
rmagueta committed
1582
    FILE *fd=fopen("nr_ulsim.log","w");
1583 1584 1585 1586
    if (fd == NULL) {
      printf("Problem with filename %s\n", "nr_ulsim.log");
      exit(-1);
    }
rmagueta's avatar
rmagueta committed
1587
    dump_pusch_stats(fd,gNB);
1588
    fclose(fd);
Raymond Knopp's avatar
Raymond Knopp committed
1589

1590 1591 1592 1593 1594
    printf("*****************************************\n");
    printf("\n");
    
    if (print_perf==1) {
      printDistribution(&gNB->phy_proc_rx,table_rx,"Total PHY proc rx");
1595 1596
      printStatIndent(&gNB->rx_pusch_stats,"RX PUSCH time");
      printStatIndent2(&gNB->ulsch_channel_estimation_stats,"ULSCH channel estimation time");
1597
      printStatIndent2(&gNB->ulsch_ptrs_processing_stats,"ULSCH PTRS Processing time");
1598 1599
      printStatIndent2(&gNB->ulsch_rbs_extraction_stats,"ULSCH rbs extraction time");
      printStatIndent2(&gNB->ulsch_channel_compensation_stats,"ULSCH channel compensation time");
1600
      printStatIndent2(&gNB->ulsch_mrc_stats,"ULSCH mrc computation");
1601
      printStatIndent2(&gNB->ulsch_llr_stats,"ULSCH llr computation");
1602 1603
      printStatIndent(&gNB->ulsch_unscrambling_stats,"ULSCH unscrambling");
      printStatIndent(&gNB->ulsch_decoding_stats,"ULSCH total decoding time");
1604 1605 1606 1607 1608
      printStatIndent(&UE->ulsch_encoding_stats,"ULSCH total encoding time");
      printStatIndent2(&UE->ulsch_segmentation_stats,"ULSCH segmentation time");
      printStatIndent2(&UE->ulsch_ldpc_encoding_stats,"ULSCH LDPC encoder time");
      printStatIndent2(&UE->ulsch_rate_matching_stats,"ULSCH rate-matching time");
      printStatIndent2(&UE->ulsch_interleaving_stats,"ULSCH interleaving time");
Sakthivel Velumani's avatar
Sakthivel Velumani committed
1609 1610 1611
      //printStatIndent2(&gNB->ulsch_deinterleaving_stats,"ULSCH deinterleaving");
      //printStatIndent2(&gNB->ulsch_rate_unmatching_stats,"ULSCH rate matching rx");
      //printStatIndent2(&gNB->ulsch_ldpc_decoding_stats,"ULSCH ldpc decoding");
1612
      printf("\n");
1613
    }
1614

1615 1616
    if(n_trials==1)
      break;
1617

1618
    if ((float)effTP >= eff_tp_check) {
1619 1620 1621
      printf("*************\n");
      printf("PUSCH test OK\n");
      printf("*************\n");
1622
      ret = 0;
1623 1624
      break;
    }
1625
  } // SNR loop
1626

1627
  printf("\n");
1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644
  printf( "Num RB:\t%d\n"
          "Num symbols:\t%d\n"
          "MCS:\t%d\n"
          "DMRS config type:\t%d\n"
          "DMRS add pos:\t%d\n"
          "PUSCH mapping type:\t%d\n"
          "DMRS length:\t%d\n"
          "DMRS CDM gr w/o data:\t%d\n",
          nb_rb,
          nb_symb_sch,
          Imcs,
          dmrs_config_type,
          add_pos,
          mapping_type,
          length_dmrs,
          num_dmrs_cdm_grps_no_data);
              
Ahmed Hussein's avatar
Ahmed Hussein committed
1645 1646
  free(test_input_bit);
  free(estimated_output_bit);
1647 1648
  if (gNB->ldpc_offload_flag)
    free_nrLDPClib_offload();
Ahmed Hussein's avatar
Ahmed Hussein committed
1649

1650 1651 1652 1653 1654 1655
  if (output_fd)
    fclose(output_fd);

  if (input_fd)
    fclose(input_fd);

1656 1657 1658
  if (scg_fd)
    fclose(scg_fd);

1659
  return ret;
1660
}