dlsim.c 56.2 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
/*
 * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The OpenAirInterface Software Alliance licenses this file to You under
 * the OAI Public License, Version 1.1  (the "License"); you may not use this file
 * except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.openairinterface.org/?page_id=698
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *-------------------------------------------------------------------------------
 * For more information about the OpenAirInterface (OAI) Software Alliance:
 *      contact@openairinterface.org
 */

#include <fcntl.h>
23 24
#include <math.h>
#include <string.h>
25 26
#include <sys/ioctl.h>
#include <sys/mman.h>
27 28
#include <unistd.h>
#include "common/ran_context.h"
29
#include "common/config/config_userapi.h"
francescomani's avatar
francescomani committed
30
#include "common/utils/nr/nr_common.h"
Robert Schmidt's avatar
Robert Schmidt committed
31
#include "common/utils/var_array.h"
32
#include "common/utils/LOG/log.h"
33 34 35
#include "LAYER2/NR_MAC_gNB/nr_mac_gNB.h"
#include "LAYER2/NR_MAC_UE/mac_defs.h"
#include "LAYER2/NR_MAC_UE/mac_extern.h"
36
#include "PHY/defs_gNB.h"
37 38
#include "PHY/defs_nr_common.h"
#include "PHY/defs_nr_UE.h"
39
#include "PHY/phy_vars_nr_ue.h"
40
#include "PHY/types.h"
41
#include "PHY/INIT/nr_phy_init.h"
42
#include "PHY/MODULATION/modulation_eNB.h"
43
#include "PHY/MODULATION/nr_modulation.h"
44
#include "PHY/MODULATION/modulation_UE.h"
45
#include "PHY/NR_REFSIG/refsig_defs_ue.h"
46
#include "PHY/NR_TRANSPORT/nr_dlsch.h"
cig's avatar
cig committed
47
#include "PHY/NR_TRANSPORT/nr_transport_proto.h"
48
#include "PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h"
49
#include "SCHED_NR/fapi_nr_l1.h"
50
#include "SCHED_NR/sched_nr.h"
51
#include "SCHED_NR_UE/defs.h"
52 53 54 55
#include "SCHED_NR_UE/fapi_nr_ue_l1.h"
#include "NR_PHY_INTERFACE/NR_IF_Module.h"
#include "NR_UE_PHY_INTERFACE/NR_IF_Module.h"

56
#include "LAYER2/NR_MAC_UE/mac_proto.h"
yilmazt's avatar
yilmazt committed
57 58
//#include "LAYER2/NR_MAC_gNB/mac_proto.h"
//#include "openair2/LAYER2/NR_MAC_UE/mac_proto.h"
59
#include "LAYER2/NR_MAC_gNB/mac_proto.h"
60
#include "NR_asn_constant.h"
Robert Schmidt's avatar
Robert Schmidt committed
61
#include "RRC/NR/nr_rrc_config.h"
62 63 64
#include "openair1/SIMULATION/RF/rf.h"
#include "openair1/SIMULATION/TOOLS/sim.h"
#include "openair1/SIMULATION/NR_PHY/nr_unitary_defs.h"
Raymond Knopp's avatar
Raymond Knopp committed
65
//#include "openair1/SIMULATION/NR_PHY/nr_dummy_functions.c"
66
#include "PHY/NR_REFSIG/ptrs_nr.h"
Raymond Knopp's avatar
Raymond Knopp committed
67
#include "NR_RRCReconfiguration.h"
68
#define inMicroS(a) (((double)(a))/(get_cpu_freq_GHz()*1000.0))
69
#include "SIMULATION/LTE_PHY/common_sim.h"
70
#include "PHY/NR_REFSIG/dmrs_nr.h"
71

Laurent's avatar
Laurent committed
72
#include <openair2/RRC/LTE/rrc_vars.h>
73

Raymond Knopp's avatar
Raymond Knopp committed
74
#include <executables/softmodem-common.h>
75
#include <openair3/ocp-gtpu/gtp_itf.h>
76
#include <executables/nr-uesoftmodem.h>
Raymond Knopp's avatar
Raymond Knopp committed
77

78 79 80 81 82 83
const char *__asan_default_options()
{
  /* don't do leak checking in nr_ulsim, not finished yet */
  return "detect_leaks=0";
}

84 85 86
PHY_VARS_gNB *gNB;
PHY_VARS_NR_UE *UE;
RAN_CONTEXT_t RC;
87
int32_t uplink_frequency_offset[MAX_NUM_CCs][4];
88
double cpuf;
89
char *uecap_file;
90

Laurent THOMAS's avatar
Laurent THOMAS committed
91
uint16_t sl_ahead=0;
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
//Fixme: Uniq dirty DU instance, by global var, datamodel need better management
instance_t DUuniqInstance=0;
instance_t CUuniqInstance=0;
99

mir's avatar
mir committed
100
void nr_derive_key_ng_ran_star(uint16_t pci, uint64_t nr_arfcn_dl, const uint8_t key[32], uint8_t *key_ng_ran_star)
101 102 103
{
}

104
int dummy_nr_ue_ul_indication(nr_uplink_indication_t *ul_info) { return(0);  }
105

106
void e1_bearer_context_setup(const e1ap_bearer_setup_req_t *req) { abort(); }
107
void e1_bearer_context_modif(const e1ap_bearer_setup_req_t *req) { abort(); }
108
void e1_bearer_release_cmd(const e1ap_bearer_release_cmd_t *cmd) { abort(); }
109

110 111 112 113
int8_t nr_rrc_RA_succeeded(const module_id_t mod_id, const uint8_t gNB_index) {
  return 0;
}

mir's avatar
mir committed
114
void nr_derive_key(int alg_type, uint8_t alg_id, const uint8_t key[32], uint8_t out[16])
115
{
mir's avatar
mir committed
116
  (void)alg_type;
117 118
}

119 120
void processSlotTX(void *arg) {}

Robert Schmidt's avatar
Robert Schmidt committed
121
nr_bler_struct nr_bler_data[NR_NUM_MCS];
rmagueta's avatar
rmagueta committed
122

123
// needed for some functions
124
openair0_config_t openair0_cfg[MAX_CARDS];
125
void update_ptrs_config(NR_CellGroupConfig_t *secondaryCellGroup, uint16_t *rbSize, uint8_t *mcsIndex,int8_t *ptrs_arg);
126
void update_dmrs_config(NR_CellGroupConfig_t *scg, int8_t* dmrs_arg);
rmagueta's avatar
rmagueta committed
127
extern void fix_scd(NR_ServingCellConfig_t *scd);// forward declaration
128

129
/* specific dlsim DL preprocessor: uses rbStart/rbSize/mcs/nrOfLayers from command line of dlsim */
130
int g_mcsIndex = -1, g_mcsTableIdx = 0, g_rbStart = -1, g_rbSize = -1, g_nrOfLayers = 1, g_pmi = 0;
131 132
void nr_dlsim_preprocessor(module_id_t module_id,
                           frame_t frame,
133
                           sub_frame_t slot) {
134

Laurent THOMAS's avatar
Laurent THOMAS committed
135 136 137
  NR_UE_info_t *UE_info = RC.nrmac[module_id]->UE_info.list[0];
  AssertFatal(RC.nrmac[module_id]->UE_info.list[1]==NULL, "can have only a single UE\n");
  NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl;
francescomani's avatar
francescomani committed
138
  NR_UE_DL_BWP_t *current_BWP = &UE_info->current_DL_BWP;
rmagueta's avatar
rmagueta committed
139
  NR_ServingCellConfigCommon_t *scc = RC.nrmac[0]->common_channels[0].ServingCellConfigCommon;
140

141 142 143 144 145 146 147
  //TODO better implementation needed
  //for now artificially set candidates for the required aggregation levels
  sched_ctrl->search_space->nrofCandidates->aggregationLevel1 = NR_SearchSpace__nrofCandidates__aggregationLevel1_n0;
  sched_ctrl->search_space->nrofCandidates->aggregationLevel2 = NR_SearchSpace__nrofCandidates__aggregationLevel2_n0;
  sched_ctrl->search_space->nrofCandidates->aggregationLevel4 = NR_SearchSpace__nrofCandidates__aggregationLevel4_n1;
  sched_ctrl->search_space->nrofCandidates->aggregationLevel8 = NR_SearchSpace__nrofCandidates__aggregationLevel8_n1;
  sched_ctrl->search_space->nrofCandidates->aggregationLevel16 = NR_SearchSpace__nrofCandidates__aggregationLevel16_n0;
148

149
  uint8_t nr_of_candidates = 0;
150 151 152 153 154 155 156 157 158 159
  if (g_mcsIndex < 4) {
    find_aggregation_candidates(&sched_ctrl->aggregation_level,
                                &nr_of_candidates,
                                sched_ctrl->search_space,8);
  }
  if (nr_of_candidates == 0) {
    find_aggregation_candidates(&sched_ctrl->aggregation_level,
                                &nr_of_candidates,
                                sched_ctrl->search_space,4);
  }
francescomani's avatar
francescomani committed
160
  uint32_t Y = get_Y(sched_ctrl->search_space, slot, UE_info->rnti);
161 162 163 164 165 166 167
  int CCEIndex = find_pdcch_candidate(RC.nrmac[module_id],
                                      /* CC_id = */ 0,
                                      sched_ctrl->aggregation_level,
                                      nr_of_candidates,
                                      &sched_ctrl->sched_pdcch,
                                      sched_ctrl->coreset,
                                      Y);
francescomani's avatar
francescomani committed
168
  AssertFatal(CCEIndex>=0, "%4d.%2d could not find CCE for DL DCI UE %d/RNTI %04x\n", frame, slot, 0, UE_info->rnti);
169
  sched_ctrl->cce_index = CCEIndex;
170

171 172 173 174
  NR_sched_pdsch_t *sched_pdsch = &sched_ctrl->sched_pdsch;
  sched_pdsch->rbStart = g_rbStart;
  sched_pdsch->rbSize = g_rbSize;
  sched_pdsch->mcs = g_mcsIndex;
francescomani's avatar
francescomani committed
175
  sched_pdsch->nrOfLayers = g_nrOfLayers;
176
  sched_pdsch->pm_index = g_pmi;
177 178
  /* the following might override the table that is mandated by RRC
   * configuration */
francescomani's avatar
francescomani committed
179
  current_BWP->mcsTableIdx = g_mcsTableIdx;
francescomani's avatar
francescomani committed
180
  sched_pdsch->time_domain_allocation = get_dl_tda(RC.nrmac[module_id], scc, slot);
181
  AssertFatal(sched_pdsch->time_domain_allocation >= 0,"Unable to find PDSCH time domain allocation in list\n");
francescomani's avatar
francescomani committed
182

183 184
  sched_pdsch->tda_info = get_dl_tda_info(current_BWP, sched_ctrl->search_space->searchSpaceType->present, sched_pdsch->time_domain_allocation,
                                          NR_MIB__dmrs_TypeA_Position_pos2, 1, NR_RNTI_C, sched_ctrl->coreset->controlResourceSetId, false);
francescomani's avatar
francescomani committed
185 186 187 188 189

  sched_pdsch->dmrs_parms = get_dl_dmrs_params(scc,
                                               current_BWP,
                                               &sched_pdsch->tda_info,
                                               sched_pdsch->nrOfLayers);
francescomani's avatar
francescomani committed
190

francescomani's avatar
francescomani committed
191 192
  sched_pdsch->Qm = nr_get_Qm_dl(sched_pdsch->mcs, current_BWP->mcsTableIdx);
  sched_pdsch->R = nr_get_code_rate_dl(sched_pdsch->mcs, current_BWP->mcsTableIdx);
193 194 195
  sched_pdsch->tb_size = nr_compute_tbs(sched_pdsch->Qm,
                                        sched_pdsch->R,
                                        sched_pdsch->rbSize,
francescomani's avatar
francescomani committed
196
                                        sched_pdsch->tda_info.nrOfSymbols,
francescomani's avatar
francescomani committed
197
                                        sched_pdsch->dmrs_parms.N_PRB_DMRS * sched_pdsch->dmrs_parms.N_DMRS_SLOT,
198 199
                                        0 /* N_PRB_oh, 0 for initialBWP */,
                                        0 /* tb_scaling */,
francescomani's avatar
francescomani committed
200
                                        sched_pdsch->nrOfLayers) >> 3;
201

202
  /* the simulator assumes the HARQ PID is equal to the slot number */
203 204
  sched_pdsch->dl_harq_pid = slot;

205 206 207 208 209 210 211 212 213 214 215 216
  /* The scheduler uses lists to track whether a HARQ process is
   * free/busy/awaiting retransmission, and updates the HARQ process states.
   * However, in the simulation, we never get ack or nack for any HARQ process,
   * thus the list and HARQ states don't match what the scheduler expects.
   * Therefore, below lines just "repair" everything so that the scheduler
   * won't remark that there is no HARQ feedback */
  sched_ctrl->feedback_dl_harq.head = -1; // always overwrite feedback HARQ process
  if (sched_ctrl->harq_processes[slot].round == 0) // depending on round set in simulation ...
    add_front_nr_list(&sched_ctrl->available_dl_harq, slot); // ... make PID available
  else
    add_front_nr_list(&sched_ctrl->retrans_dl_harq, slot);   // ... make PID retransmission
  sched_ctrl->harq_processes[slot].is_waiting = false;
217 218 219
  AssertFatal(sched_pdsch->rbStart >= 0, "invalid rbStart %d\n", sched_pdsch->rbStart);
  AssertFatal(sched_pdsch->rbSize > 0, "invalid rbSize %d\n", sched_pdsch->rbSize);
  AssertFatal(sched_pdsch->mcs >= 0, "invalid mcs %d\n", sched_pdsch->mcs);
francescomani's avatar
francescomani committed
220
  AssertFatal(current_BWP->mcsTableIdx >= 0 && current_BWP->mcsTableIdx <= 2, "invalid mcsTableIdx %d\n", current_BWP->mcsTableIdx);
221
}
222

Sakthivel Velumani's avatar
Sakthivel Velumani committed
223 224 225 226 227
nrUE_params_t nrUE_params;

nrUE_params_t *get_nrUE_params(void) {
  return &nrUE_params;
}
228

229

230
void validate_input_pmi(nr_pdsch_AntennaPorts_t pdsch_AntennaPorts, int nrOfLayers, int pmi)
231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258
{
  if (pmi == 0)
    return;

  int num_antenna_ports = pdsch_AntennaPorts.N1 * pdsch_AntennaPorts.N2 * pdsch_AntennaPorts.XP;
  int N1 = pdsch_AntennaPorts.N1;
  int N2 = pdsch_AntennaPorts.N2;
  int O1 = N1 > 1 ? 4 : 1;
  int O2 = N2 > 1 ? 4 : 1;
  int K1, K2;
  if (num_antenna_ports > 2)
    get_K1_K2(N1, N2, &K1, &K2);
  else {
    K1 = 1; K2 = 1;
  }
  int num_pmi = 1; // pmi = 0 is the identity matrix
  switch (nrOfLayers) {
    case 1 :
      num_pmi += N1 * O1 * N2 * O2 * 4;
      AssertFatal(pmi < num_pmi, "Input PMI index %d exceeds the limit of configured matrices %d for %d layers\n", pmi, num_pmi, nrOfLayers);
      return;
    case 2 :
      num_pmi += N1 * O1 * N2 * O2 * K1 * K2 * 2;
      AssertFatal(pmi < num_pmi, "Input PMI index %d exceeds the limit of conigured matrices %d for %d layers\n", pmi, num_pmi, nrOfLayers);
      break;
    default :
      AssertFatal(false, "Precoding with more than 2 nrOfLayers not yet supported\n");
  }
Sakthivel Velumani's avatar
Sakthivel Velumani committed
259
}
260 261


laurent's avatar
laurent committed
262
int NB_UE_INST = 1;
263
configmodule_interface_t *uniqCfg = NULL;
264 265
int main(int argc, char **argv)
{
266 267
  FILE *csv_file = NULL;
  char *filename_csv = NULL;
268
  setbuf(stdout, NULL);
269
  int c;
270
  int i,aa;//,l;
271
  double sigma2, sigma2_dB=10, SNR, snr0=-2.0, snr1=2.0;
272
  uint8_t snr1set=0;
273
  float effRate;
Francesco Mani's avatar
Francesco Mani committed
274
  //float psnr;
275
  float eff_tp_check = 0.7;
276
  uint32_t TBS = 0;
277
  c16_t **txdata;
278
  double **s_re,**s_im,**r_re,**r_im;
279 280
  //double iqim = 0.0;
  //unsigned char pbch_pdu[6];
281 282 283
  //  int sync_pos, sync_pos_slot;
  //  FILE *rx_frame_file;
  FILE *output_fd = NULL;
284
  //uint8_t write_output_file=0;
285
  //int result;
286
  //int freq_offset;
287
  //  int subframe_offset;
288
  //  char fname[40], vname[40];
289
  int trial, n_trials = 1, n_false_positive = 0;
290
  //int n_errors2, n_alamouti;
291
  uint8_t n_tx=1,n_rx=1;
292 293
  uint8_t round;
  uint8_t num_rounds = 4;
294
  char gNBthreads[128]="n";
295 296

  channel_desc_t *gNB2UE;
297 298 299
  //uint32_t nsymb,tx_lev,tx_lev1 = 0,tx_lev2 = 0;
  //uint8_t extended_prefix_flag=0;
  //int8_t interf1=-21,interf2=-21;
300 301

  FILE *input_fd=NULL,*pbch_file_fd=NULL;
302
  //char input_val_str[50],input_val_str2[50];
303

304
  //uint8_t frame_mod4,num_pdcch_symbols = 0;
305

306
  SCM_t channel_model = AWGN; // AWGN Rayleigh1 Rayleigh1_anticorr;
307
  double DS_TDL = .03;
308
  int delay = 0;
309

310 311
  //double pbch_sinr;
  //int pbch_tx_ant;
Ahmed Hussein's avatar
Ahmed Hussein committed
312
  int N_RB_DL=106,mu=1;
313

314
  //unsigned char frame_type = 0;
315

316
  int frame=1,slot=1;
317
  int frame_length_complex_samples;
318
  //int frame_length_complex_samples_no_prefix;
319 320
  NR_DL_FRAME_PARMS *frame_parms;
  UE_nr_rxtx_proc_t UE_proc;
321
  NR_Sched_Rsp_t *Sched_INFO;
322 323
  gNB_MAC_INST *gNB_mac;
  NR_UE_MAC_INST_t *UE_mac;
324
  int cyclic_prefix_type = NFAPI_CP_NORMAL;
325
  int run_initial_sync=0;
326
  int loglvl=OAILOG_WARNING;
327

328
  //float target_error_rate = 0.01;
329
  cpuf = get_cpu_freq_GHz();
330 331 332
  int8_t enable_ptrs = 0;
  int8_t modify_dmrs = 0;

333
  int8_t dmrs_arg[3] = {-1,-1,-1};// Invalid values
334
  /* L_PTRS = ptrs_arg[0], K_PTRS = ptrs_arg[1] */
335 336
  int8_t ptrs_arg[2] = {-1,-1};// Invalid values

337 338 339 340 341 342
  uint16_t ptrsRePerSymb = 0;
  uint16_t pdu_bit_map = 0x0;
  uint16_t dlPtrsSymPos = 0;
  uint16_t ptrsSymbPerSlot = 0;
  uint16_t rbSize = 106;
  uint8_t  mcsIndex = 9;
343
  uint8_t  dlsch_threads = 0;
344
  int chest_type[2] = {0};
345
  uint8_t  max_ldpc_iterations = 5;
346
  if ((uniqCfg = load_configmodule(argc, argv, CONFIG_ENABLECMDLINEONLY)) == 0) {
yilmazt's avatar
yilmazt committed
347
    exit_fun("[NR_DLSIM] Error, configuration module init failed\n");
348 349 350 351
  }

  randominit(0);

352
  int print_perf = 0;
353

354
  FILE *scg_fd=NULL;
355

356
  while ((c = getopt(argc, argv, "f:hA:p:f:g:i:n:s:S:t:v:x:y:z:o:M:N:F:GR:d:PI:L:a:b:e:m:w:T:U:q:X:Y:Z:")) != -1) {
357
    switch (c) {
358 359
    case 'f':
      scg_fd = fopen(optarg,"r");
360

361
      if (scg_fd==NULL) {
362 363 364
        printf("Error opening %s\n",optarg);
        exit(-1);
      }
365
      break;
366 367

    case 'g':
368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386
      switch ((char)*optarg) {
        case 'A':
          channel_model = TDL_A;
          DS_TDL = 0.030; // 30 ns
          printf("Channel model: TDLA30\n");
          break;
        case 'B':
          channel_model = TDL_B;
          DS_TDL = 0.100; // 100ns
          printf("Channel model: TDLB100\n");
          break;
        case 'C':
          channel_model = TDL_C;
          DS_TDL = 0.300; // 300 ns
          printf("Channel model: TDLC300\n");
          break;
        default:
          printf("Unsupported channel model!\n");
          exit(-1);
387 388 389 390
      }

      break;

391
    case 'i':
392 393 394
      for(i=0; i < atoi(optarg); i++){
        chest_type[i] = atoi(argv[optind++]);
      }
395 396 397 398 399 400 401 402
      break;

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

    case 's':
      snr0 = atof(optarg);
403
      printf("Setting SNR0 to %f\n",snr0);
404 405 406 407 408
      break;

    case 'S':
      snr1 = atof(optarg);
      snr1set=1;
409
      printf("Setting SNR1 to %f\n",snr1);
410 411 412
      break;

    case 'x':
413
      g_nrOfLayers = atoi(optarg);
414

415 416
      if ((g_nrOfLayers == 0) || (g_nrOfLayers > 4)) {
        printf("Unsupported nr Of Layers %d\n", g_nrOfLayers);
417 418 419 420
        exit(-1);
      }
      break;

421 422 423 424
    case 'p':
     g_pmi = atoi(optarg);
     break;

425
    case 'v':
426
      num_rounds = atoi(optarg);
427

428
      AssertFatal(num_rounds > 0 && num_rounds < 16, "Unsupported number of rounds %d, should be in [1,16]\n", num_rounds);
429 430
      break;

431 432 433
    case 'y':
      n_tx=atoi(optarg);

434
      if ((n_tx==0) || (n_tx>4)) {//extend gNB to support n_tx = 4
435
        printf("Unsupported number of tx antennas %d\n",n_tx);
436 437 438 439 440 441 442 443
        exit(-1);
      }

      break;

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

444
      if ((n_rx==0) || (n_rx>4)) {//extend UE to support n_tx = 4
445
        printf("Unsupported number of rx antennas %d\n",n_rx);
446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465
        exit(-1);
      }

      break;

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

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

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

      break;

    case 'P':
466 467
      print_perf=1;
      opp_enabled=1;
468 469 470
      break;
      
    case 'I':
471
      max_ldpc_iterations = atoi(optarg);
472 473 474 475 476 477
      break;

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

478
    case 'a':
479
      g_rbStart = atoi(optarg);
480 481 482
      break;

    case 'b':
483
      g_rbSize = atoi(optarg);
484
      break;
485

486
    case 'd':
487
      dlsch_threads = atoi(optarg);
488 489
      break;

490
    case 'e':
491
      g_mcsIndex = atoi(optarg);
492 493
      break;

494
    case 'q':
495
      g_mcsTableIdx = atoi(optarg);
496 497
      break;

498 499 500
    case 'm':
      mu = atoi(optarg);
      break;
501

502 503 504 505
    case 't':
      eff_tp_check = (float)atoi(optarg)/100;
      break;

506 507 508
    case 'w':
      output_fd = fopen("txdata.dat", "w+");
      break;
Sakthivel Velumani's avatar
Sakthivel Velumani committed
509

510 511 512 513 514 515 516
    case 'T':
      enable_ptrs=1;
      for(i=0; i < atoi(optarg); i++) {
        ptrs_arg[i] = atoi(argv[optind++]);
      }
      break;

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

524
    case 'X':
525
      strncpy(gNBthreads, optarg, sizeof(gNBthreads)-1);
526 527
      gNBthreads[sizeof(gNBthreads)-1]=0;
      break;
528

529 530 531 532 533
    case 'Y':
      run_initial_sync=1;
      //target_error_rate=0.1;
      slot = 0;
      break;
534 535 536 537
    case 'Z' :
      filename_csv = strdup(optarg);
      AssertFatal(filename_csv != NULL, "strdup() error: errno %d\n", errno);
      break;
538

539 540 541 542
    case 'o':
      delay = atoi(optarg);
      break;

543 544
    default:
    case 'h':
545 546 547 548 549 550 551
      printf("%s -h(elp)\n", argv[0]);
      printf("-a Start PRB for PDSCH\n");
      printf("-b Number of PRB for PDSCH\n");
      printf("-d number of dlsch threads, 0: no dlsch parallelization\n");
      printf("-e MSC index\n");
      printf("-f raw file containing RRC configuration (generated by gNB)\n");
      printf("-g Channel model: [A] TDLA30, [B] TDLB100, [C] TDLC300, e.g. -g A\n");
552
      printf("-h This message\n");
553 554
      printf("-i Change channel estimation technique. Arguments list: Frequency domain {0:Linear interpolation, 1:PRB based averaging}, Time domain {0:Estimates of last DMRS symbol, 1:Average of DMRS symbols}\n");
      printf("-m Numerology\n");
555
      printf("-n Number of frames to simulate\n");
556 557 558
      printf("-o Introduce delay in terms of number of samples\n");
      printf("-p Precoding matrix index\n");
      printf("-q MCS Table index\n");
559 560
      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");
561 562 563 564
      printf("-t Acceptable effective throughput (in percentage)\n");
      printf("-v Maximum number of rounds\n");
      printf("-w Write txdata to binary file (one frame)\n");
      printf("-x Num of layer for PDSCH\n");
565
      printf("-y Number of TX antennas used in gNB\n");
566 567
      printf("-z Number of RX antennas used in UE\n");
      printf("-F Input filename (.txt format) for RX conformance testing\n");
568
      printf("-I Maximum LDPC decoder iterations\n");
569 570 571
      printf("-L <log level, 0(errors), 1(warning), 2(analysis), 3(info), 4(debug), 5(trace)>\n");
      printf("-P Print DLSCH performances\n");
      printf("-R N_RB_DL\n");
572
      printf("-T Enable PTRS, arguments list L_PTRS{0,1,2} K_PTRS{2,4}, e.g. -T 2 0 2 \n");
573
      printf("-U Change DMRS Config, arguments list DMRS TYPE{0=A,1=B} DMRS AddPos{0:2} DMRS ConfType{1:2}, e.g. -U 3 0 2 1 \n");
574 575
      printf("-X gNB thread pool configuration, n => no threads\n");
      printf("-Y Run initial sync in UE\n");
576
      printf("-Z Output filename (.csv format) for stats\n");
577 578 579 580
      exit (-1);
      break;
    }
  }
581

582 583
  logInit();
  set_glog(loglvl);
584 585
  /* initialize the sin table */
  InitSinLUT();
586

587
  get_softmodem_params()->phy_test = 1;
588
  get_softmodem_params()->do_ra = 0;
589
  set_softmodem_optmask(SOFTMODEM_DLSIM_BIT);
590

591 592 593
  if (snr1set==0)
    snr1 = snr0+10;

594 595 596
  RC.gNB = (PHY_VARS_gNB**) malloc(sizeof(PHY_VARS_gNB *));
  RC.gNB[0] = (PHY_VARS_gNB*) malloc(sizeof(PHY_VARS_gNB ));
  memset(RC.gNB[0],0,sizeof(PHY_VARS_gNB));
Raymond Knopp's avatar
Raymond Knopp committed
597

598
  gNB = RC.gNB[0];
599
  gNB->ofdm_offset_divisor = UINT_MAX;
600 601 602 603 604 605
  frame_parms = &gNB->frame_parms; //to be initialized I suppose (maybe not necessary for PBCH)
  frame_parms->nb_antennas_tx = n_tx;
  frame_parms->nb_antennas_rx = n_rx;
  frame_parms->N_RB_DL = N_RB_DL;
  frame_parms->N_RB_UL = N_RB_DL;

606 607 608
  AssertFatal((gNB->if_inst = NR_IF_Module_init(0)) != NULL, "Cannot register interface");
  gNB->if_inst->NR_PHY_config_req = nr_phy_config_request;

609 610 611 612 613 614
  NR_ServingCellConfigCommon_t *scc = calloc(1,sizeof(*scc));;
  prepare_scc(scc);
  uint64_t ssb_bitmap = 1; // Enable only first SSB with index ssb_indx=0
  fill_scc_sim(scc, &ssb_bitmap, N_RB_DL, N_RB_DL, mu, mu);
  fix_scc(scc, ssb_bitmap);

615 616 617 618 619 620 621 622 623 624 625 626
  // TODO do a UECAP for phy-sim
  nr_pdsch_AntennaPorts_t pdsch_AntennaPorts = {0};
  pdsch_AntennaPorts.N1 = n_tx > 1 ? n_tx >> 1 : 1;
  pdsch_AntennaPorts.N2 = 1;
  pdsch_AntennaPorts.XP = n_tx > 1 ? 2 : 1;
  const nr_mac_config_t conf = {.pdsch_AntennaPorts = pdsch_AntennaPorts,
                                .pusch_AntennaPorts = n_tx,
                                .minRXTXTIME = 6,
                                .do_CSIRS = 0,
                                .do_SRS = 0,
                                .force_256qam_off = false};

Raymond Knopp's avatar
Raymond Knopp committed
627
  RC.nb_nr_macrlc_inst = 1;
cig's avatar
cig committed
628 629 630
  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;
631
  mac_top_init_gNB(ngran_gNB, scc, NULL, &conf);
Raymond Knopp's avatar
Raymond Knopp committed
632
  gNB_mac = RC.nrmac[0];
633

634 635
  gNB_mac->dl_bler.harq_round_max = num_rounds;

636
  /*
Raymond Knopp's avatar
Raymond Knopp committed
637
  // read in SCGroupConfig
Raymond Knopp's avatar
Raymond Knopp committed
638
  AssertFatal(scg_fd != NULL,"no reconfig.raw file\n");
Raymond Knopp's avatar
Raymond Knopp committed
639 640
  char buffer[1024];
  int msg_len=fread(buffer,1,1024,scg_fd);
641
  NR_RRCReconfiguration_t *NR_RRCReconfiguration = NULL;
Raymond Knopp's avatar
Raymond Knopp committed
642

Raymond Knopp's avatar
Raymond Knopp committed
643
  printf("Decoding NR_RRCReconfiguration (%d bytes)\n",msg_len);
Raymond Knopp's avatar
Raymond Knopp committed
644 645 646 647 648 649 650 651 652 653 654
  asn_dec_rval_t dec_rval = uper_decode_complete( NULL,
						  &asn_DEF_NR_RRCReconfiguration,
						  (void **)&NR_RRCReconfiguration,
						  (uint8_t *)buffer,
						  msg_len); 
  
  if ((dec_rval.code != RC_OK) && (dec_rval.consumed == 0)) {
    AssertFatal(1==0,"NR_RRCReConfiguration decode error\n");
    // free the memory
    SEQUENCE_free( &asn_DEF_NR_RRCReconfiguration, NR_RRCReconfiguration, 1 );
    exit(-1);
655
  }
Raymond Knopp's avatar
Raymond Knopp committed
656 657
  fclose(scg_fd);

Raymond Knopp's avatar
Raymond Knopp committed
658 659
  AssertFatal(NR_RRCReconfiguration->criticalExtensions.present == NR_RRCReconfiguration__criticalExtensions_PR_rrcReconfiguration,"wrong NR_RRCReconfiguration->criticalExstions.present type\n");

Raymond Knopp's avatar
Raymond Knopp committed
660
  NR_RRCReconfiguration_IEs_t *reconfig_ies = NR_RRCReconfiguration->criticalExtensions.choice.rrcReconfiguration;
661
  NR_CellGroupConfig_t *secondaryCellGroup = NULL;
Raymond Knopp's avatar
Raymond Knopp committed
662 663 664 665 666 667 668 669 670 671 672
  dec_rval = uper_decode_complete( NULL,
				   &asn_DEF_NR_CellGroupConfig,
				   (void **)&secondaryCellGroup,
				   (uint8_t *)reconfig_ies->secondaryCellGroup->buf,
				   reconfig_ies->secondaryCellGroup->size); 
  
  if ((dec_rval.code != RC_OK) && (dec_rval.consumed == 0)) {
    AssertFatal(1==0,"NR_CellGroupConfig decode error\n");
    // free the memory
    SEQUENCE_free( &asn_DEF_NR_CellGroupConfig, secondaryCellGroup, 1 );
    exit(-1);
673
  }
Raymond Knopp's avatar
Raymond Knopp committed
674
  
675 676
  NR_ServingCellConfigCommon_t *scc = secondaryCellGroup->spCellConfig->reconfigurationWithSync->spCellConfigCommon;
  */
Raymond Knopp's avatar
Raymond Knopp committed
677

Robert Schmidt's avatar
Robert Schmidt committed
678
  NR_ServingCellConfig_t *scd = calloc(1,sizeof(*scd));
679
  prepare_scd(scd);
680

francescomani's avatar
francescomani committed
681 682 683
  gNB->ap_N1 = pdsch_AntennaPorts.N1;
  gNB->ap_N2 = pdsch_AntennaPorts.N2;
  gNB->ap_XP = pdsch_AntennaPorts.XP;
684

685 686
  validate_input_pmi(pdsch_AntennaPorts, g_nrOfLayers, g_pmi);

687 688
  NR_UE_NR_Capability_t* UE_Capability_nr = CALLOC(1,sizeof(NR_UE_NR_Capability_t));
  prepare_sim_uecap(UE_Capability_nr,scc,mu,
689
                    N_RB_DL,g_mcsTableIdx,0);
690

691
  NR_CellGroupConfig_t *secondaryCellGroup = get_default_secondaryCellGroup(scc, scd, UE_Capability_nr, 0, 1, &conf, 0);
692

693 694
  /* RRC parameter validation for secondaryCellGroup */
  fix_scd(scd);
Robert Schmidt's avatar
Robert Schmidt committed
695

696
  /* -U option modify DMRS */
697
  if(modify_dmrs) {
698
    update_dmrs_config(secondaryCellGroup, dmrs_arg);
699
  }
700
  /* -T option enable PTRS */
701
  if(enable_ptrs) {
702
    update_ptrs_config(secondaryCellGroup, &rbSize, &mcsIndex, ptrs_arg);
703 704
  }

705

706
  //xer_fprint(stdout, &asn_DEF_NR_CellGroupConfig, (const void*)secondaryCellGroup);
Raymond Knopp's avatar
Raymond Knopp committed
707 708

  // UE dedicated configuration
709
  nr_mac_add_test_ue(RC.nrmac[0], secondaryCellGroup->spCellConfig->reconfigurationWithSync->newUE_Identity, secondaryCellGroup);
710
  // reset preprocessor to the one of DLSIM after it has been set during
711
  // nr_mac_config_scc()
712
  gNB_mac->pre_processor_dl = nr_dlsim_preprocessor;
713
  phy_init_nr_gNB(gNB);
714
  N_RB_DL = gNB->frame_parms.N_RB_DL;
Laurent THOMAS's avatar
Laurent THOMAS committed
715
  NR_UE_info_t *UE_info = RC.nrmac[0]->UE_info.list[0];
716

717
  configure_UE_BWP(RC.nrmac[0], scc, &UE_info->UE_sched_ctrl, NULL, UE_info, -1, -1);
francescomani's avatar
francescomani committed
718

Raymond Knopp's avatar
Raymond Knopp committed
719
  // stub to configure frame_parms
Raymond Knopp's avatar
Raymond Knopp committed
720
  //  nr_phy_config_request_sim(gNB,N_RB_DL,N_RB_DL,mu,Nid_cell,SSB_positions);
Raymond Knopp's avatar
Raymond Knopp committed
721 722
  // call MAC to configure common parameters

723
  /* nr_mac_add_test_ue() has created one user, so set the scheduling
724 725 726 727 728
   * parameters from command line in global variables that will be picked up by
   * scheduling preprocessor */
  if (g_mcsIndex < 0) g_mcsIndex = 9;
  if (g_rbStart < 0) g_rbStart=0;
  if (g_rbSize < 0) g_rbSize = N_RB_DL - g_rbStart;
Raymond Knopp's avatar
Raymond Knopp committed
729

730 731
  double fs,txbw,rxbw;
  uint32_t samples;
732

733 734 735 736 737 738 739
  get_samplerate_and_bw(mu,
                        N_RB_DL,
                        frame_parms->threequarter_fs,
                        &fs,
                        &samples,
                        &txbw,
                        &rxbw);
740 741 742 743

  gNB2UE = new_channel_desc_scm(n_tx,
                                n_rx,
                                channel_model,
744
                                fs/1e6,//sampling frequency in MHz
745
                                0,
746
                                txbw,
747
                                DS_TDL,
748
                                0.0,
749
                                CORR_LEVEL_LOW,
750
                                0,
751
                                delay,
752 753
                                0,
                                0);
754 755

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

  frame_length_complex_samples = frame_parms->samples_per_subframe*NR_NUMBER_OF_SUBFRAMES_PER_FRAME;
761
  //frame_length_complex_samples_no_prefix = frame_parms->samples_per_subframe_wCP*NR_NUMBER_OF_SUBFRAMES_PER_FRAME;
762 763
  int slot_offset = frame_parms->get_samples_slot_timestamp(slot,frame_parms,0);
  int slot_length = slot_offset - frame_parms->get_samples_slot_timestamp(slot-1,frame_parms,0);
764

765 766 767 768 769
  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*));
  txdata = malloc(n_tx*sizeof(int*));
770

771 772 773
  for (i = 0; i < n_tx; i++) {
    s_re[i] = calloc(1, slot_length * sizeof(double));
    s_im[i] = calloc(1, slot_length * sizeof(double));
774

775 776
    printf("Allocating %d samples for txdata\n", frame_length_complex_samples);
    txdata[i] = calloc(1, frame_length_complex_samples * sizeof(int));
777 778
  }

779 780 781
  for (i = 0; i < n_rx; i++) {
    r_re[i] = calloc(1, slot_length * sizeof(double));
    r_im[i] = calloc(1, slot_length * sizeof(double));
782 783 784 785 786 787 788 789 790
  }

  if (pbch_file_fd!=NULL) {
    load_pbch_desc(pbch_file_fd);
  }


  //configure UE
  UE = malloc(sizeof(PHY_VARS_NR_UE));
Raymond Knopp's avatar
Raymond Knopp committed
791
  memset((void*)UE,0,sizeof(PHY_VARS_NR_UE));
792 793 794 795
  PHY_vars_UE_g = malloc(sizeof(PHY_VARS_NR_UE**));
  PHY_vars_UE_g[0] = malloc(sizeof(PHY_VARS_NR_UE*));
  PHY_vars_UE_g[0][0] = UE;
  memcpy(&UE->frame_parms,frame_parms,sizeof(NR_DL_FRAME_PARMS));
796
  UE->frame_parms.nb_antennas_rx = n_rx;
laurent's avatar
laurent committed
797
  UE->frame_parms.nb_antenna_ports_gNB = n_tx;
798
  UE->max_ldpc_iterations = max_ldpc_iterations;
Raymond Knopp's avatar
Raymond Knopp committed
799

francescomani's avatar
francescomani committed
800 801 802 803
  if (run_initial_sync==1)
    UE->is_synchronized = 0;
  else
    UE->is_synchronized = 1;
804

805
  if (init_nr_ue_signal(UE, 1) != 0)
806 807 808 809 810
  {
    printf("Error at UE NR initialisation\n");
    exit(-1);
  }

811
  init_nr_ue_transport(UE);
812

813
  nr_gold_pbch(UE);
814 815 816 817 818 819

  // compute the scramblingID_pdcch and the gold pdcch
  UE->scramblingID_pdcch = frame_parms->Nid_cell;
  nr_gold_pdcch(UE, frame_parms->Nid_cell);

  // compute the scrambling IDs for PDSCH DMRS
francescomani's avatar
francescomani committed
820 821 822 823
  for (int i = 0; i < 2; i++) {
    UE->scramblingID_dlsch[i] = frame_parms->Nid_cell;
    nr_gold_pdsch(UE, i, UE->scramblingID_dlsch[i]);
  }
824

825
  nr_l2_init_ue(NULL);
826
  UE_mac = get_mac_inst(0);
francescomani's avatar
francescomani committed
827
  ue_init_config_request(UE_mac, mu);
828

829 830 831
  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;
832
  UE->if_inst->dl_indication = nr_ue_dl_indication;
833
  UE->if_inst->ul_indication = dummy_nr_ue_ul_indication;
834 835
  UE->chest_freq = chest_type[0];
  UE->chest_time = chest_type[1];
836

837
  UE_mac->if_module = nr_ue_if_module_init(0);
francescomani's avatar
francescomani committed
838
  UE_mac->state = UE_CONNECTED;
839

840
  unsigned int available_bits=0;
Ahmed Hussein's avatar
Ahmed Hussein committed
841 842
  unsigned char *estimated_output_bit;
  unsigned char *test_input_bit;
843
  unsigned int errors_bit = 0;
Ahmed Hussein's avatar
Ahmed Hussein committed
844

845
  initFloatingCoresTpool(dlsch_threads, &nrUE_params.Tpool, false, "UE-tpool");
846

847
  test_input_bit = (unsigned char *) malloc16(sizeof(unsigned char) * 16 * 68 * 384);
Ahmed Hussein's avatar
Ahmed Hussein committed
848
  estimated_output_bit = (unsigned char *) malloc16(sizeof(unsigned char) * 16 * 68 * 384);
849 850
  
  // generate signal
851
  AssertFatal(input_fd==NULL,"Not ready for input signal file\n");
Raymond Knopp's avatar
Raymond Knopp committed
852

853
  //Configure UE
Robert Schmidt's avatar
Robert Schmidt committed
854
  NR_BCCH_BCH_Message_t *mib = get_new_MIB_NR(scc);
francescomani's avatar
francescomani committed
855 856
  nr_rrc_mac_config_req_mib(0, 0, mib->message.choice.mib, false);
  nr_rrc_mac_config_req_scg(0, 0, secondaryCellGroup);
857 858 859

  nr_dcireq_t dcireq;
  nr_scheduled_response_t scheduled_response;
860
  nr_phy_data_t phy_data = {0};
861

862 863 864 865
  memset((void*)&dcireq,0,sizeof(dcireq));
  memset((void*)&scheduled_response,0,sizeof(scheduled_response));
  dcireq.module_id = 0;
  dcireq.gNB_index = 0;
866
  dcireq.cc_id = 0;
867
  
868 869 870 871
  scheduled_response.dl_config = &dcireq.dl_config_req;
  scheduled_response.ul_config = &dcireq.ul_config_req;
  scheduled_response.tx_request = NULL;
  scheduled_response.module_id = 0;
872
  scheduled_response.CC_id = 0;
873 874
  scheduled_response.frame = frame;
  scheduled_response.slot  = slot;
875
  scheduled_response.phy_data = &phy_data;
Francesco Mani's avatar
Francesco Mani committed
876

877
  nr_ue_phy_config_request(&UE_mac->phy_config);
Francesco Mani's avatar
Francesco Mani committed
878
  //NR_COMMON_channels_t *cc = RC.nrmac[0]->common_channels;
879
  int n_errs = 0;
880

881
  initNamedTpool(gNBthreads, &gNB->threadPool, true, "gNB-tpool");
882 883 884
  initNotifiedFIFO(&gNB->L1_tx_free);
  initNotifiedFIFO(&gNB->L1_tx_filled);
  initNotifiedFIFO(&gNB->L1_tx_out);
Sakthivel Velumani's avatar
Sakthivel Velumani committed
885
  // we create 2 threads for L1 tx processing
886
  notifiedFIFO_elt_t *msgL1Tx = newNotifiedFIFO_elt(sizeof(processingData_L1tx_t),0,&gNB->L1_tx_free,processSlotTX);
Sakthivel Velumani's avatar
Sakthivel Velumani committed
887 888 889 890 891
  processingData_L1tx_t *msgDataTx = (processingData_L1tx_t *)NotifiedFifoData(msgL1Tx);
  init_DLSCH_struct(gNB, msgDataTx);
  msgDataTx->slot = slot;
  msgDataTx->frame = frame;
  memset(msgDataTx->ssb, 0, 64*sizeof(NR_gNB_SSB_t));
892

893
  // Buffers to store internal memory of slot process
894 895 896 897 898 899 900
  int rx_size = (((14 * frame_parms->N_RB_DL * 12 * sizeof(int32_t)) + 15) >> 4) << 4;
  UE->phy_sim_rxdataF = calloc(sizeof(int32_t *) * frame_parms->nb_antennas_rx * g_nrOfLayers, frame_parms->samples_per_slot_wCP * sizeof(int32_t));
  UE->phy_sim_pdsch_llr = calloc(1, (8 * (3 * 8 * 8448)) * sizeof(int16_t)); // Max length
  UE->phy_sim_pdsch_rxdataF_ext = calloc(sizeof(int32_t *) * frame_parms->nb_antennas_rx * g_nrOfLayers, rx_size);
  UE->phy_sim_pdsch_rxdataF_comp = calloc(sizeof(int32_t *) * frame_parms->nb_antennas_rx * g_nrOfLayers, rx_size);
  UE->phy_sim_pdsch_dl_ch_estimates = calloc(sizeof(int32_t *) * frame_parms->nb_antennas_rx * g_nrOfLayers, rx_size);
  UE->phy_sim_pdsch_dl_ch_estimates_ext = calloc(sizeof(int32_t *) * frame_parms->nb_antennas_rx * g_nrOfLayers, rx_size);
901 902 903 904 905 906 907
  int a_segments = MAX_NUM_NR_DLSCH_SEGMENTS_PER_LAYER*NR_MAX_NB_LAYERS;  //number of segments to be allocated
  if (g_rbSize != 273) {
    a_segments = a_segments*g_rbSize;
    a_segments = (a_segments/273)+1;
  }
  uint32_t dlsch_bytes = a_segments*1056;  // allocated bytes per segment
  UE->phy_sim_dlsch_b = calloc(1, dlsch_bytes);
908

909 910 911 912 913 914 915 916 917 918 919 920 921 922
  // csv file
  if (filename_csv != NULL) {
    csv_file = fopen(filename_csv, "a");
    if (csv_file == NULL) {
      printf("Can't open file \"%s\", errno %d\n", filename_csv, errno);
      return 1;
    }
    // adding name of parameters into file
    fprintf(csv_file,"SNR,false_positive,");
    for (int r = 0; r < num_rounds; r++)
      fprintf(csv_file,"n_errors_%d,errors_scrambling_%d,channel_bler_%d,channel_ber_%d,",r,r,r,r);
    fprintf(csv_file,"avg_round,eff_rate,eff_throughput,TBS\n");
  }
  //---------------
Ahmed Hussein's avatar
Ahmed Hussein committed
923
  for (SNR = snr0; SNR < snr1; SNR += .2) {
924

925 926 927 928 929 930 931 932 933 934
    varArray_t *table_tx=initVarArray(1000,sizeof(double));
    reset_meas(&gNB->dlsch_scrambling_stats);
    reset_meas(&gNB->dlsch_interleaving_stats);
    reset_meas(&gNB->dlsch_rate_matching_stats);
    reset_meas(&gNB->dlsch_segmentation_stats);
    reset_meas(&gNB->dlsch_modulation_stats);
    reset_meas(&gNB->dlsch_encoding_stats);
    reset_meas(&gNB->tinput);
    reset_meas(&gNB->tprep);
    reset_meas(&gNB->tparity);
935
    reset_meas(&gNB->toutput);
936

937 938 939 940 941 942 943
    uint32_t errors_scrambling[16] = {0};
    int n_errors[16] = {0};
    int round_trials[16] = {0};
    double roundStats = {0};
    double blerStats[16] = {0};
    double berStats[16] = {0};

944
    effRate = 0;
945 946
    //n_errors2 = 0;
    //n_alamouti = 0;
947
    n_false_positive = 0;
948 949
    if (n_trials== 1) num_rounds = 1;

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

952
      errors_bit = 0;
Ahmed Hussein's avatar
Ahmed Hussein committed
953
      //multipath channel
954
      //multipath_channel(gNB2UE,s_re,s_im,r_re,r_im,frame_length_complex_samples,0);
955

956
      UE->rx_offset=0;
957
      UE_proc.frame_rx = frame;
958
      UE_proc.nr_slot_rx = slot;
959
      UE_proc.gNB_id = 0;
960
      
961 962
      dcireq.frame = frame;
      dcireq.slot = slot;
963

964
      NR_UE_DLSCH_t *dlsch0 = &phy_data.dlsch[0];
965

966
      int harq_pid = slot;
967
      NR_DL_UE_HARQ_t *UE_harq_process = &UE->dl_harq_processes[0][harq_pid];
968

francescomani's avatar
francescomani committed
969
      NR_gNB_DLSCH_t *gNB_dlsch = &msgDataTx->dlsch[0][0];
970
      nfapi_nr_dl_tti_pdsch_pdu_rel15_t *rel15 = &gNB_dlsch->harq_process.pdsch_pdu.pdsch_pdu_rel15;
971
      
972
      UE_harq_process->ack = 0;
973
      round = 0;
974
      UE_harq_process->DLround = round;
francescomani's avatar
fixes  
francescomani committed
975
      UE_harq_process->first_rx = 1;
976 977 978 979 980 981 982 983 984

      Sched_INFO = malloc(sizeof(*Sched_INFO));
      if (Sched_INFO == NULL) {
        LOG_E(PHY, "out of memory\n");
        exit(1);
      }
      memset(Sched_INFO, 0, sizeof(*Sched_INFO));
      Sched_INFO->sched_response_id = -1;

985
      while ((round<num_rounds) && (UE_harq_process->ack==0)) {
986
        round_trials[round]++;
francescomani's avatar
fixes  
francescomani committed
987

988
        clear_nr_nfapi_information(RC.nrmac[0], 0, frame, slot, &Sched_INFO->DL_req, &Sched_INFO->TX_req, &Sched_INFO->UL_dci_req);
Laurent THOMAS's avatar
Laurent THOMAS committed
989 990
        UE_info->UE_sched_ctrl.harq_processes[harq_pid].ndi = !(trial&1);
        UE_info->UE_sched_ctrl.harq_processes[harq_pid].round = round;
991

992 993
        // nr_schedule_ue_spec() requires the mutex to be locked
        NR_SCHED_LOCK(&gNB_mac->sched_lock);
994
        nr_schedule_ue_spec(0, frame, slot, &Sched_INFO->DL_req, &Sched_INFO->TX_req);
995
        NR_SCHED_UNLOCK(&gNB_mac->sched_lock);
996 997 998 999 1000
        Sched_INFO->module_id = 0;
        Sched_INFO->CC_id = 0;
        Sched_INFO->frame = frame;
        Sched_INFO->slot = slot;
        Sched_INFO->UL_dci_req.numPdus = 0;
1001
        pushNotifiedFIFO(&gNB->L1_tx_free,msgL1Tx);
1002
        nr_schedule_response(Sched_INFO);
1003 1004

        /* PTRS values for DLSIM calculations   */
1005
        nfapi_nr_dl_tti_request_body_t *dl_req = &Sched_INFO->DL_req.dl_tti_request_body;
1006 1007 1008
        nfapi_nr_dl_tti_request_pdu_t  *dl_tti_pdsch_pdu = &dl_req->dl_tti_pdu_list[1];
        nfapi_nr_dl_tti_pdsch_pdu_rel15_t *pdsch_pdu_rel15 = &dl_tti_pdsch_pdu->pdsch_pdu.pdsch_pdu_rel15;
        pdu_bit_map = pdsch_pdu_rel15->pduBitmap;
1009
        if(pdu_bit_map & 0x1) {
1010 1011 1012 1013 1014 1015
          set_ptrs_symb_idx(&dlPtrsSymPos,
                            pdsch_pdu_rel15->NrOfSymbols,
                            pdsch_pdu_rel15->StartSymbolIndex,
                            1<<pdsch_pdu_rel15->PTRSTimeDensity,
                            pdsch_pdu_rel15->dlDmrsSymbPos);
          ptrsSymbPerSlot = get_ptrs_symbols_in_slot(dlPtrsSymPos, pdsch_pdu_rel15->StartSymbolIndex, pdsch_pdu_rel15->NrOfSymbols);
1016 1017
          ptrsRePerSymb = ((rel15->rbSize + rel15->PTRSFreqDensity - 1) / rel15->PTRSFreqDensity);
          LOG_D(PHY,"[DLSIM] PTRS Symbols in a slot: %2u, RE per Symbol: %3u, RE in a slot %4d\n", ptrsSymbPerSlot, ptrsRePerSymb, ptrsSymbPerSlot * ptrsRePerSymb);
1018
        }
Sakthivel Velumani's avatar
Sakthivel Velumani committed
1019 1020 1021 1022

        msgDataTx->ssb[0].ssb_pdu.ssb_pdu_rel15.bchPayload=0x001234;
        msgDataTx->ssb[0].ssb_pdu.ssb_pdu_rel15.SsbBlockIndex = 0;
        msgDataTx->gNB = gNB;
1023
        if (run_initial_sync)
Sakthivel Velumani's avatar
Sakthivel Velumani committed
1024
          nr_common_signal_procedures(gNB,frame,slot,msgDataTx->ssb[0].ssb_pdu);
1025
        else
Sakthivel Velumani's avatar
Sakthivel Velumani committed
1026
          phy_procedures_gNB_TX(msgDataTx,frame,slot,1);
1027
            
1028
        int txdataF_offset = slot * frame_parms->samples_per_slot_wCP;
1029 1030
        
        if (n_trials==1) {
1031
          LOG_M("txsigF0.m","txsF0=", &gNB->common_vars.txdataF[0][txdataF_offset+2*frame_parms->ofdm_symbol_size],frame_parms->ofdm_symbol_size,1,1);
1032
          if (gNB->frame_parms.nb_antennas_tx>1)
1033
            LOG_M("txsigF1.m","txsF1=", &gNB->common_vars.txdataF[1][txdataF_offset+2*frame_parms->ofdm_symbol_size],frame_parms->ofdm_symbol_size,1,1);
1034
        }
1035
        if (n_trials == 1) printf("slot_offset %d, txdataF_offset %d \n", slot_offset, txdataF_offset);
1036

1037 1038
        //TODO: loop over slots
        for (aa=0; aa<gNB->frame_parms.nb_antennas_tx; aa++) {
1039

1040
          if (cyclic_prefix_type == 1) {
1041
            PHY_ofdm_mod((int *)&gNB->common_vars.txdataF[aa][txdataF_offset],
1042
                         (int *)&txdata[aa][slot_offset],
1043 1044 1045 1046
                         frame_parms->ofdm_symbol_size,
                         12,
                         frame_parms->nb_prefix_samples,
                         CYCLIC_PREFIX);
1047
          } else {
1048
            nr_normal_prefix_mod(&gNB->common_vars.txdataF[aa][txdataF_offset],
1049
                                 &txdata[aa][slot_offset],
1050
                                 14,
1051 1052
                                 frame_parms,
                                 slot);
1053
          }
1054 1055
        }
        if (n_trials==1) {
1056 1057 1058
          char filename[100];//LOG_M
          for (aa=0;aa<n_tx;aa++) {
            sprintf(filename,"txsig%d.m", aa);//LOG_M
1059
            LOG_M(filename,"txs", &txdata[aa][slot_offset +frame_parms->ofdm_symbol_size+frame_parms->nb_prefix_samples0],6*(frame_parms->ofdm_symbol_size+frame_parms->nb_prefix_samples),1,1);
1060
          }
1061
        }
Sakthivel Velumani's avatar
Sakthivel Velumani committed
1062 1063
        if (output_fd) {
          printf("writing txdata to binary file\n");
1064
          fwrite(txdata[0],sizeof(int32_t),frame_length_complex_samples,output_fd);
Sakthivel Velumani's avatar
Sakthivel Velumani committed
1065
        }
1066

1067 1068 1069 1070
        int txlev[n_tx];
        int txlev_sum = 0;
        int l_ofdm = 6;
        for (aa=0; aa<n_tx; aa++) {
1071
          txlev[aa] = signal_energy((int32_t *)&txdata[aa][slot_offset +l_ofdm*frame_parms->ofdm_symbol_size + (l_ofdm-1)*frame_parms->nb_prefix_samples + frame_parms->nb_prefix_samples0],
1072 1073 1074 1075
          frame_parms->ofdm_symbol_size + frame_parms->nb_prefix_samples);
          txlev_sum += txlev[aa];
          if (n_trials==1) printf("txlev[%d] = %d (%f dB) txlev_sum %d\n",aa,txlev[aa],10*log10((double)txlev[aa]),txlev_sum);
        }
1076 1077

        for (i = 0; i < slot_length; i++) {
1078
          for (aa=0; aa<frame_parms->nb_antennas_tx; aa++) {
1079 1080
            s_re[aa][i] = ((double)(((short *)&txdata[aa][slot_offset]))[(i << 1)]);
            s_im[aa][i] = ((double)(((short *)&txdata[aa][slot_offset]))[(i << 1) + 1]);
1081
          }
1082
        }
1083

1084
        double ts = 1.0/(frame_parms->subcarrier_spacing * frame_parms->ofdm_symbol_size); 
1085
        //Compute AWGN variance
1086
        sigma2_dB = 10 * log10((double)txlev_sum * ((double)UE->frame_parms.ofdm_symbol_size/(12*rel15->rbSize))) - SNR;
1087
        sigma2    = pow(10, sigma2_dB/10);
1088
        if (n_trials==1) printf("sigma2 %f (%f dB), txlev_sum %f (factor %f)\n",sigma2,sigma2_dB,10*log10((double)txlev_sum),(double)(double)UE->frame_parms.ofdm_symbol_size/(12*rel15->rbSize));
1089

1090 1091 1092
        for (aa = 0; aa < n_rx; aa++) {
          bzero(r_re[aa], slot_length * sizeof(double));
          bzero(r_im[aa], slot_length * sizeof(double));
1093
        }
1094

1095
        // Apply MIMO Channel
1096
        multipath_channel(gNB2UE, s_re, s_im, r_re, r_im, slot_length, 0, (n_trials == 1) ? 1 : 0);
1097
        add_noise(UE->common_vars.rxdata, (const double **) r_re, (const double **) r_im, sigma2, slot_length, slot_offset, ts, delay, pdu_bit_map, 0x1, frame_parms->nb_antennas_rx);
1098

1099 1100
        nr_ue_dcireq(&dcireq); //to be replaced with function pointer later
        nr_ue_scheduled_response(&scheduled_response);
1101

1102 1103 1104 1105 1106 1107
        pbch_pdcch_processing(UE,
                              &UE_proc,
                              &phy_data);
        pdsch_processing(UE,
                         &UE_proc,
                         &phy_data);
1108 1109 1110
        //----------------------------------------------------------
        //---------------------- count errors ----------------------
        //----------------------------------------------------------
1111

1112
        if (dlsch0->last_iteration_cnt >= dlsch0->max_ldpc_iterations+1)
1113
          n_errors[round]++;
1114

1115
        int16_t *UE_llr = (int16_t*)UE->phy_sim_pdsch_llr;
1116

1117
        TBS                  = dlsch0->dlsch_config.TBS;//rel15->TBSize[0];
1118 1119
        uint16_t length_dmrs = get_num_dmrs(rel15->dlDmrsSymbPos);
        uint16_t nb_rb       = rel15->rbSize;
1120
        uint8_t  nb_re_dmrs  = rel15->dmrsConfigType == NFAPI_NR_DMRS_TYPE1 ? 6*dlsch0->dlsch_config.n_dmrs_cdm_groups : 4*dlsch0->dlsch_config.n_dmrs_cdm_groups;
1121 1122
        uint8_t  mod_order   = rel15->qamModOrder[0];
        uint8_t  nb_symb_sch = rel15->NrOfSymbols;
1123 1124
        uint32_t unav_res = ptrsSymbPerSlot * ptrsRePerSymb;
        available_bits = nr_get_G(nb_rb, nb_symb_sch, nb_re_dmrs, length_dmrs, unav_res, mod_order, rel15->nrOfLayers);
1125 1126
        if (pdu_bit_map & 0x1) {
          if (trial == 0 && round == 0) {
1127
            printf("[DLSIM][PTRS] Available bits are: %5u, removed PTRS bits are: %5u \n", available_bits, (ptrsSymbPerSlot * ptrsRePerSymb * rel15->nrOfLayers * mod_order));
1128
          }
1129
        }
1130

1131 1132 1133 1134
        for (i = 0; i < available_bits; i++) {
          if(((gNB_dlsch->harq_process.f[i] == 0) && (UE_llr[i] <= 0)) ||
             ((gNB_dlsch->harq_process.f[i] == 1) && (UE_llr[i] >= 0)))
          {
1135
            if (errors_scrambling[round] == 0) {
1136 1137
              LOG_D(PHY,"First bit in error in unscrambling = %d\n",i);
            }
1138
            errors_scrambling[round]++;
1139 1140
          }
        }
1141

1142 1143 1144
        //printf("dlsim round %d ends\n",round);
        round++;
      } // round
1145

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

1148
	estimated_output_bit[i] = (UE->phy_sim_dlsch_b[i/8] & (1 << (i & 7))) >> (i & 7);
1149
	test_input_bit[i]       = (gNB_dlsch->harq_process.b[i / 8] & (1 << (i & 7))) >> (i & 7); // Further correct for multiple segments
Raymond Knopp's avatar
Raymond Knopp committed
1150
	
1151 1152
	if (estimated_output_bit[i] != test_input_bit[i]) {
	  if(errors_bit == 0)
1153
	    LOG_D(PHY,"First bit in error in decoding = %d\n",i);
1154
	  errors_bit++;
Raymond Knopp's avatar
Raymond Knopp committed
1155 1156
	}
	
1157 1158
      }
      ////////////////////////////////////////////////////////////
1159

1160 1161 1162 1163 1164
      if (errors_bit > 0) {
	n_false_positive++;
	if (n_trials == 1)
	  printf("errors_bit = %u (trial %d)\n", errors_bit, trial);
      }
1165
      roundStats += ((float)round);
1166
      if (UE_harq_process->ack==1) effRate += ((float)TBS)/round;
Ahmed Hussein's avatar
Ahmed Hussein committed
1167
    } // noise trials
1168

1169
    roundStats /= ((float)n_trials);
1170

1171
    for (int r = 0; r < num_rounds; r++) {
1172 1173
      blerStats[r] = (double)n_errors[r] / round_trials[r];
      berStats[r] = (double)errors_scrambling[r] / available_bits / round_trials[r];
1174
    }
1175

1176
    effRate /= n_trials;
Ahmed Hussein's avatar
Ahmed Hussein committed
1177
    printf("*****************************************\n");
1178
    printf("SNR %f: n_errors (%d/%d", SNR, n_errors[0], round_trials[0]);
1179
    for (int r = 1; r < num_rounds; r++)
1180 1181
      printf(",%d/%d", n_errors[r], round_trials[r]);
    printf(") (negative CRC), false_positive %d/%d, errors_scrambling (%u/%u", n_false_positive, n_trials, errors_scrambling[0], available_bits * round_trials[0]);
1182
    for (int r = 1; r < num_rounds; r++)
1183
      printf(",%u/%u", errors_scrambling[r], available_bits * round_trials[r]);
1184
    printf(")\n\n");
Raymond Knopp's avatar
Raymond Knopp committed
1185
    dump_pdsch_stats(stdout,gNB);
1186
    printf("SNR %f: Channel BLER (%e", SNR, blerStats[0]);
1187
    for (int r = 1; r < num_rounds; r++)
1188 1189
      printf(",%e", blerStats[r]);
    printf("), Channel BER (%e", berStats[0]);
1190
    for (int r = 1; r < num_rounds; r++)
1191 1192
      printf(",%e", berStats[r]);
    printf(") Avg round %.2f, Eff Rate %.4f bits/slot, Eff Throughput %.2f, TBS %u bits/slot\n", roundStats, effRate, effRate / TBS * 100, TBS);
1193
    printf("*****************************************\n");
Ahmed Hussein's avatar
Ahmed Hussein committed
1194
    printf("\n");
1195 1196 1197 1198 1199 1200 1201
    // writing to csv file
    if (filename_csv != NULL) { // means we are asked to print stats to CSV
      fprintf(csv_file,"%f,%d/%d,",SNR,n_false_positive,n_trials);
      for (int r = 0; r < num_rounds; r++)
        fprintf(csv_file,"%d/%d,%u/%u,%f,%e,",n_errors[r], round_trials[r], errors_scrambling[r], available_bits * round_trials[r],blerStats[r],berStats[r]);
      fprintf(csv_file,"%.2f,%.4f,%.2f,%u\n", roundStats, effRate, effRate / TBS * 100, TBS);
    }
1202
    if (print_perf==1) {
1203
      printf("\ngNB TX function statistics (per %d us slot, NPRB %d, mcs %d, block %d)\n",
francescomani's avatar
francescomani committed
1204 1205 1206 1207
             1000 >> *scc->ssbSubcarrierSpacing,
             g_rbSize,
             g_mcsIndex,
             msgDataTx->dlsch[0][0].harq_process.pdsch_pdu.pdsch_pdu_rel15.TBSize[0] << 3);
Robert Schmidt's avatar
Robert Schmidt committed
1208
      printDistribution(&gNB->phy_proc_tx,table_tx,"PHY proc tx");
1209 1210 1211 1212 1213 1214 1215 1216 1217 1218
      printStatIndent2(&gNB->dlsch_encoding_stats,"DLSCH encoding time");
      printStatIndent3(&gNB->dlsch_segmentation_stats,"DLSCH segmentation time");
      printStatIndent3(&gNB->tinput,"DLSCH LDPC input processing time");
      printStatIndent3(&gNB->tprep,"DLSCH LDPC input preparation time");
      printStatIndent3(&gNB->tparity,"DLSCH LDPC parity generation time");
      printStatIndent3(&gNB->toutput,"DLSCH LDPC output generation time");
      printStatIndent3(&gNB->dlsch_rate_matching_stats,"DLSCH Rate Mataching time");
      printStatIndent3(&gNB->dlsch_interleaving_stats,  "DLSCH Interleaving time");
      printStatIndent2(&gNB->dlsch_modulation_stats,"DLSCH modulation time");
      printStatIndent2(&gNB->dlsch_scrambling_stats,  "DLSCH scrambling time");
1219 1220 1221
      printStatIndent2(&gNB->dlsch_layer_mapping_stats, "DLSCH Layer Mapping time");
      printStatIndent2(&gNB->dlsch_resource_mapping_stats, "DLSCH Resource Mapping time");
      printStatIndent2(&gNB->dlsch_precoding_stats,"DLSCH Layer Precoding time");
1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237

      printf("\nUE RX function statistics (per %d us slot)\n",1000>>*scc->ssbSubcarrierSpacing);
      /*
      printDistribution(&phy_proc_rx_tot, table_rx,"Total PHY proc rx");
      printStatIndent(&ue_front_end_tot,"Front end processing");
      printStatIndent(&dlsch_llr_tot,"rx_pdsch processing");
      printStatIndent2(&pdsch_procedures_tot,"pdsch processing");
      printStatIndent2(&dlsch_procedures_tot,"dlsch processing");
      printStatIndent2(&UE->crnti_procedures_stats,"C-RNTI processing");
      printStatIndent(&UE->ofdm_demod_stats,"ofdm demodulation");
      printStatIndent(&UE->dlsch_channel_estimation_stats,"DLSCH channel estimation time");
      printStatIndent(&UE->dlsch_freq_offset_estimation_stats,"DLSCH frequency offset estimation time");
      printStatIndent(&dlsch_decoding_tot, "DLSCH Decoding time ");
      printStatIndent(&UE->dlsch_unscrambling_stats,"DLSCH unscrambling time");
      printStatIndent(&UE->dlsch_rate_unmatching_stats,"DLSCH Rate Unmatching");
      printf("|__ DLSCH Turbo Decoding(%d bits), avg iterations: %.1f       %.2f us (%d cycles, %d trials)\n",
1238 1239 1240
	     UE->dlsch[0][0]->harq_processes[0]->Cminus ?
	     UE->dlsch[0][0]->harq_processes[0]->Kminus :
	     UE->dlsch[0][0]->harq_processes[0]->Kplus,
1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253
	     UE->dlsch_tc_intl1_stats.trials/(double)UE->dlsch_tc_init_stats.trials,
	     (double)UE->dlsch_turbo_decoding_stats.diff/UE->dlsch_turbo_decoding_stats.trials*timeBase,
	     (int)((double)UE->dlsch_turbo_decoding_stats.diff/UE->dlsch_turbo_decoding_stats.trials),
	     UE->dlsch_turbo_decoding_stats.trials);
      printStatIndent2(&UE->dlsch_tc_init_stats,"init");
      printStatIndent2(&UE->dlsch_tc_alpha_stats,"alpha");
      printStatIndent2(&UE->dlsch_tc_beta_stats,"beta");
      printStatIndent2(&UE->dlsch_tc_gamma_stats,"gamma");
      printStatIndent2(&UE->dlsch_tc_ext_stats,"ext");
      printStatIndent2(&UE->dlsch_tc_intl1_stats,"turbo internal interleaver");
      printStatIndent2(&UE->dlsch_tc_intl2_stats,"intl2+HardDecode+CRC");
      */
    }
1254 1255

    if (n_trials == 1) {
1256

1257 1258 1259
      LOG_M("rxsig0.m","rxs0", UE->common_vars.rxdata[0], frame_length_complex_samples, 1, 1);
      if (UE->frame_parms.nb_antennas_rx>1)
	LOG_M("rxsig1.m","rxs1", UE->common_vars.rxdata[1], frame_length_complex_samples, 1, 1);
1260 1261 1262 1263 1264
      LOG_M("rxF0.m","rxF0", UE->phy_sim_rxdataF, frame_parms->samples_per_slot_wCP, 1, 1);
      LOG_M("rxF_ext.m","rxFe",UE->phy_sim_pdsch_rxdataF_ext,g_rbSize*12*14,1,1);
      LOG_M("chestF0.m","chF0",UE->phy_sim_pdsch_dl_ch_estimates_ext,g_rbSize*12*14,1,1);
      write_output("rxF_comp.m","rxFc",UE->phy_sim_pdsch_rxdataF_comp,N_RB_DL*12*14,1,1);
      LOG_M("rxF_llr.m","rxFllr",UE->phy_sim_pdsch_llr,available_bits,1,0);
1265 1266 1267
      break;
    }

1268
    if (effRate > (eff_tp_check*TBS)) {
1269 1270 1271 1272
      printf("PDSCH test OK\n");
      break;
    }

1273
    n_errs = n_errors[0];
1274 1275
  } // NSR

1276 1277
  free_channel_desc_scm(gNB2UE);

1278
  for (i = 0; i < n_tx; i++) {
1279 1280
    free(s_re[i]);
    free(s_im[i]);
1281 1282 1283
    free(txdata[i]);
  }
  for (i = 0; i < n_rx; i++) {
1284 1285 1286 1287 1288 1289 1290 1291 1292
    free(r_re[i]);
    free(r_im[i]);
  }

  free(s_re);
  free(s_im);
  free(r_re);
  free(r_im);
  free(txdata);
Ahmed Hussein's avatar
Ahmed Hussein committed
1293 1294
  free(test_input_bit);
  free(estimated_output_bit);
1295 1296 1297 1298 1299 1300
  free(UE->phy_sim_rxdataF);
  free(UE->phy_sim_pdsch_llr);
  free(UE->phy_sim_pdsch_rxdataF_ext);
  free(UE->phy_sim_pdsch_rxdataF_comp);
  free(UE->phy_sim_pdsch_dl_ch_estimates);
  free(UE->phy_sim_pdsch_dl_ch_estimates_ext);
1301
  free(UE->phy_sim_dlsch_b);
Ahmed Hussein's avatar
Ahmed Hussein committed
1302
  
1303 1304 1305 1306 1307 1308
  if (output_fd)
    fclose(output_fd);

  if (input_fd)
    fclose(input_fd);

1309 1310
  if (scg_fd)
    fclose(scg_fd);
1311

1312 1313 1314 1315 1316 1317
  // closing csv file
  if (filename_csv != NULL) { // means we are asked to print stats to CSV
    fclose(csv_file);
    free(filename_csv);
  }

1318
  return n_errs;
1319
}
1320 1321


1322
void update_ptrs_config(NR_CellGroupConfig_t *secondaryCellGroup, uint16_t *rbSize, uint8_t *mcsIndex, int8_t *ptrs_arg)
1323 1324
{
  NR_BWP_Downlink_t *bwp=secondaryCellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.array[0];
laurent's avatar
laurent committed
1325 1326 1327 1328 1329
  long ptrsFreqDenst[] = {25, 115};
  long ptrsTimeDenst[] = {2, 4, 10};

  long epre_Ratio = 0;
  long reOffset = 0;
1330

1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342
  if(ptrs_arg[0] ==0) {
    ptrsTimeDenst[2]= *mcsIndex -1;
  }
  else if(ptrs_arg[0] == 1) {
    ptrsTimeDenst[1]= *mcsIndex - 1;
    ptrsTimeDenst[2]= *mcsIndex + 1;
  }
  else if(ptrs_arg[0] ==2) {
    ptrsTimeDenst[0]= *mcsIndex - 1;
    ptrsTimeDenst[1]= *mcsIndex + 1;
  }
  else {
1343 1344 1345
    printf("[DLSIM] Wrong L_PTRS value, using default values 1\n");
  }
  /* L = 4 if Imcs < MCS4 */
1346 1347 1348 1349 1350 1351 1352 1353 1354 1355
  if(ptrs_arg[1] ==2) {
    ptrsFreqDenst[0]= *rbSize - 1;
    ptrsFreqDenst[1]= *rbSize + 1;
  }
  else if(ptrs_arg[1] == 4) {
    ptrsFreqDenst[1]= *rbSize - 1;
  }
  else {
    printf("[DLSIM] Wrong K_PTRS value, using default values 2\n");
  }
1356
  printf("[DLSIM] PTRS Enabled with L %d, K %d \n", 1<<ptrs_arg[0], ptrs_arg[1] );
1357 1358 1359 1360
  /* overwrite the values */
  rrc_config_dl_ptrs_params(bwp, ptrsFreqDenst, ptrsTimeDenst, &epre_Ratio, &reOffset);
}

1361
void update_dmrs_config(NR_CellGroupConfig_t *scg, int8_t* dmrs_arg)
1362 1363 1364
{
  int8_t  mapping_type = typeA;//default value
  int8_t  add_pos = pdsch_dmrs_pos0;//default value
1365 1366
  int8_t  dmrs_config_type = NFAPI_NR_DMRS_TYPE1;//default value

1367
  if(dmrs_arg[0] == 0) {
1368 1369
    mapping_type = typeA;
  }
1370
  else if (dmrs_arg[0] == 1) {
1371
    mapping_type = typeB;
1372 1373
  } else {
    AssertFatal(1==0,"Incorrect Mappingtype, valid options 0-typeA, 1-typeB\n");
1374
  }
1375 1376 1377

  /* Additional DMRS positions 0 ,1 ,2 and 3 */
  if(dmrs_arg[1] >= 0 && dmrs_arg[1] <4 ) {
1378
    add_pos = dmrs_arg[1];
1379 1380
  } else {
    AssertFatal(1==0,"Incorrect Additional Position, valid options 0-pos1, 1-pos1, 2-pos2, 3-pos3\n");
1381
  }
1382

1383
  /* DMRS Conf Type 1 or 2 */
1384 1385 1386 1387
  if(dmrs_arg[2] == 1) {
    dmrs_config_type = NFAPI_NR_DMRS_TYPE1;
  } else if(dmrs_arg[2] == 2) {
    dmrs_config_type = NFAPI_NR_DMRS_TYPE2;
1388
  }
1389

1390
  NR_BWP_Downlink_t *bwp = scg->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.array[0];
1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408

  AssertFatal((bwp->bwp_Dedicated->pdsch_Config != NULL && bwp->bwp_Dedicated->pdsch_Config->choice.setup != NULL), "Base RRC reconfig structures are not allocated.\n");

  if(mapping_type == typeA) {
    bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA = calloc(1,sizeof(*bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA));
    bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->present= NR_SetupRelease_DMRS_DownlinkConfig_PR_setup;
    bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup = calloc(1,sizeof(*bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup));
    if (dmrs_config_type == NFAPI_NR_DMRS_TYPE2)
      bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->dmrs_Type = calloc(1,sizeof(*bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->dmrs_Type));
    else
      bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->dmrs_Type = NULL;
    bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->maxLength=NULL;
    bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->scramblingID0=NULL;
    bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->scramblingID1=NULL;
    bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS=NULL;
    bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->dmrs_AdditionalPosition = NULL;
    printf("DLSIM: Allocated Mapping TypeA in RRC reconfig message\n");
  }
1409

1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424
  if(mapping_type == typeB) {
    bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeB = calloc(1,sizeof(*bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeB));
    bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeB->present= NR_SetupRelease_DMRS_DownlinkConfig_PR_setup;
    bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeB->choice.setup = calloc(1,sizeof(*bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeB->choice.setup));
    if (dmrs_config_type == NFAPI_NR_DMRS_TYPE2)
      bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeB->choice.setup->dmrs_Type = calloc(1,sizeof(*bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeB->choice.setup->dmrs_Type));
    else
      bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeB->choice.setup->dmrs_Type = NULL;
    bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeB->choice.setup->maxLength=NULL;
    bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeB->choice.setup->scramblingID0=NULL;
    bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeB->choice.setup->scramblingID1=NULL;
    bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeB->choice.setup->phaseTrackingRS=NULL;
    bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeB->choice.setup->dmrs_AdditionalPosition = NULL;
    printf("DLSIM: Allocated Mapping TypeB in RRC reconfig message\n");
  }
1425

1426 1427
  struct NR_SetupRelease_DMRS_DownlinkConfig	*dmrs_MappingtypeA = bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA;
  struct NR_SetupRelease_DMRS_DownlinkConfig	*dmrs_MappingtypeB = bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeB;
1428 1429


1430 1431 1432 1433 1434
  NR_DMRS_DownlinkConfig_t *dmrs_config = (mapping_type == typeA) ? dmrs_MappingtypeA->choice.setup : dmrs_MappingtypeB->choice.setup;

  if (add_pos != 2) { // pos0,pos1,pos3
    if (dmrs_config->dmrs_AdditionalPosition == NULL) {
      dmrs_config->dmrs_AdditionalPosition = calloc(1,sizeof(*dmrs_MappingtypeA->choice.setup->dmrs_AdditionalPosition));
1435
    }
1436 1437 1438 1439
    *dmrs_config->dmrs_AdditionalPosition = add_pos;
  } else { // if NULL, Value pos2
    free(dmrs_config->dmrs_AdditionalPosition);
    dmrs_config->dmrs_AdditionalPosition = NULL;
1440
  }
1441

1442
  for (int i=0;i<bwp->bwp_Common->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list.count;i++) {
1443
    bwp->bwp_Common->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list.array[i]->mappingType = mapping_type;
1444
  }
1445

1446
  printf("[DLSIM] DMRS Config is modified with Mapping Type %d, Additional Positions %d Config. Type %d \n", mapping_type, add_pos, dmrs_config_type);
1447
}