dlsim.c 56.1 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
/*
 * 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 107 108 109 110
void nr_rrc_ue_generate_RRCSetupRequest(module_id_t module_id, const uint8_t gNB_index)
{
  return;
}

111
void e1_bearer_context_setup(const e1ap_bearer_setup_req_t *req) { abort(); }
112
void e1_bearer_context_modif(const e1ap_bearer_setup_req_t *req) { abort(); }
113

114 115 116 117
int8_t nr_rrc_RA_succeeded(const module_id_t mod_id, const uint8_t gNB_index) {
  return 0;
}

mir's avatar
mir committed
118
void nr_derive_key(int alg_type, uint8_t alg_id, const uint8_t key[32], uint8_t out[16])
119
{
mir's avatar
mir committed
120
  (void)alg_type;
121 122
}

123 124
void processSlotTX(void *arg) {}

Robert Schmidt's avatar
Robert Schmidt committed
125
nr_bler_struct nr_bler_data[NR_NUM_MCS];
rmagueta's avatar
rmagueta committed
126

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

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

Laurent THOMAS's avatar
Laurent THOMAS committed
139 140 141
  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
142
  NR_UE_DL_BWP_t *current_BWP = &UE_info->current_DL_BWP;
rmagueta's avatar
rmagueta committed
143
  NR_ServingCellConfigCommon_t *scc = RC.nrmac[0]->common_channels[0].ServingCellConfigCommon;
144

145 146 147 148 149 150 151
  //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;
152

153
  uint8_t nr_of_candidates = 0;
154 155 156 157 158 159 160 161 162 163
  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
164
  uint32_t Y = get_Y(sched_ctrl->search_space, slot, UE_info->rnti);
165 166 167 168 169 170 171
  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
172
  AssertFatal(CCEIndex>=0, "%4d.%2d could not find CCE for DL DCI UE %d/RNTI %04x\n", frame, slot, 0, UE_info->rnti);
173
  sched_ctrl->cce_index = CCEIndex;
174

175 176 177 178
  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
179
  sched_pdsch->nrOfLayers = g_nrOfLayers;
180
  sched_pdsch->pm_index = g_pmi;
181 182
  /* the following might override the table that is mandated by RRC
   * configuration */
francescomani's avatar
francescomani committed
183
  current_BWP->mcsTableIdx = g_mcsTableIdx;
francescomani's avatar
francescomani committed
184
  sched_pdsch->time_domain_allocation = get_dl_tda(RC.nrmac[module_id], scc, slot);
185
  AssertFatal(sched_pdsch->time_domain_allocation >= 0,"Unable to find PDSCH time domain allocation in list\n");
francescomani's avatar
francescomani committed
186

187 188
  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
189 190 191 192 193

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

francescomani's avatar
francescomani committed
195 196
  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);
197 198 199
  sched_pdsch->tb_size = nr_compute_tbs(sched_pdsch->Qm,
                                        sched_pdsch->R,
                                        sched_pdsch->rbSize,
francescomani's avatar
francescomani committed
200
                                        sched_pdsch->tda_info.nrOfSymbols,
francescomani's avatar
francescomani committed
201
                                        sched_pdsch->dmrs_parms.N_PRB_DMRS * sched_pdsch->dmrs_parms.N_DMRS_SLOT,
202 203
                                        0 /* N_PRB_oh, 0 for initialBWP */,
                                        0 /* tb_scaling */,
francescomani's avatar
francescomani committed
204
                                        sched_pdsch->nrOfLayers) >> 3;
205

206
  /* the simulator assumes the HARQ PID is equal to the slot number */
207 208
  sched_pdsch->dl_harq_pid = slot;

209 210 211 212 213 214 215 216 217 218 219 220
  /* 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;
221 222 223
  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
224
  AssertFatal(current_BWP->mcsTableIdx >= 0 && current_BWP->mcsTableIdx <= 2, "invalid mcsTableIdx %d\n", current_BWP->mcsTableIdx);
225
}
226

Sakthivel Velumani's avatar
Sakthivel Velumani committed
227 228 229 230 231
nrUE_params_t nrUE_params;

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

233

234
void validate_input_pmi(nr_pdsch_AntennaPorts_t pdsch_AntennaPorts, int nrOfLayers, int pmi)
235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262
{
  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
263
}
264 265


laurent's avatar
laurent committed
266
int NB_UE_INST = 1;
267

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

  channel_desc_t *gNB2UE;
301 302 303
  //uint32_t nsymb,tx_lev,tx_lev1 = 0,tx_lev2 = 0;
  //uint8_t extended_prefix_flag=0;
  //int8_t interf1=-21,interf2=-21;
304 305

  FILE *input_fd=NULL,*pbch_file_fd=NULL;
306
  //char input_val_str[50],input_val_str2[50];
307

308
  //uint8_t frame_mod4,num_pdcch_symbols = 0;
309

310
  SCM_t channel_model = AWGN; // AWGN Rayleigh1 Rayleigh1_anticorr;
311
  double DS_TDL = .03;
312
  int delay = 0;
313

314 315
  //double pbch_sinr;
  //int pbch_tx_ant;
Ahmed Hussein's avatar
Ahmed Hussein committed
316
  int N_RB_DL=106,mu=1;
317

318
  //unsigned char frame_type = 0;
319

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

332
  //float target_error_rate = 0.01;
333
  cpuf = get_cpu_freq_GHz();
334 335 336
  int8_t enable_ptrs = 0;
  int8_t modify_dmrs = 0;

337
  int8_t dmrs_arg[3] = {-1,-1,-1};// Invalid values
338
  /* L_PTRS = ptrs_arg[0], K_PTRS = ptrs_arg[1] */
339 340
  int8_t ptrs_arg[2] = {-1,-1};// Invalid values

341 342 343 344 345 346
  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;
347
  uint8_t  dlsch_threads = 0;
348
  int chest_type[2] = {0};
349
  uint8_t  max_ldpc_iterations = 5;
350
  if ( load_configmodule(argc,argv,CONFIG_ENABLECMDLINEONLY) == 0) {
yilmazt's avatar
yilmazt committed
351
    exit_fun("[NR_DLSIM] Error, configuration module init failed\n");
352 353 354 355
  }

  randominit(0);

356
  int print_perf = 0;
357

358
  FILE *scg_fd=NULL;
359

360
  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) {
361
    switch (c) {
362 363
    case 'f':
      scg_fd = fopen(optarg,"r");
364

365
      if (scg_fd==NULL) {
366 367 368
        printf("Error opening %s\n",optarg);
        exit(-1);
      }
369
      break;
370 371

    case 'g':
372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390
      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);
391 392 393 394
      }

      break;

395
    case 'i':
396 397 398
      for(i=0; i < atoi(optarg); i++){
        chest_type[i] = atoi(argv[optind++]);
      }
399 400 401 402 403 404 405 406
      break;

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

    case 's':
      snr0 = atof(optarg);
407
      printf("Setting SNR0 to %f\n",snr0);
408 409 410 411 412
      break;

    case 'S':
      snr1 = atof(optarg);
      snr1set=1;
413
      printf("Setting SNR1 to %f\n",snr1);
414 415 416
      break;

    case 'x':
417
      g_nrOfLayers = atoi(optarg);
418

419 420
      if ((g_nrOfLayers == 0) || (g_nrOfLayers > 4)) {
        printf("Unsupported nr Of Layers %d\n", g_nrOfLayers);
421 422 423 424
        exit(-1);
      }
      break;

425 426 427 428
    case 'p':
     g_pmi = atoi(optarg);
     break;

429
    case 'v':
430
      num_rounds = atoi(optarg);
431

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

435 436 437
    case 'y':
      n_tx=atoi(optarg);

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

      break;

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

448
      if ((n_rx==0) || (n_rx>4)) {//extend UE to support n_tx = 4
449
        printf("Unsupported number of rx antennas %d\n",n_rx);
450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469
        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':
470 471
      print_perf=1;
      opp_enabled=1;
472 473 474
      break;
      
    case 'I':
475
      max_ldpc_iterations = atoi(optarg);
476 477 478 479 480 481
      break;

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

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

    case 'b':
487
      g_rbSize = atoi(optarg);
488
      break;
489

490
    case 'd':
491
      dlsch_threads = atoi(optarg);
492 493
      break;

494
    case 'e':
495
      g_mcsIndex = atoi(optarg);
496 497
      break;

498
    case 'q':
499
      g_mcsTableIdx = atoi(optarg);
500 501
      break;

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

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

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

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

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

528
    case 'X':
529
      strncpy(gNBthreads, optarg, sizeof(gNBthreads)-1);
530 531
      gNBthreads[sizeof(gNBthreads)-1]=0;
      break;
532

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

543 544 545 546
    case 'o':
      delay = atoi(optarg);
      break;

547 548
    default:
    case 'h':
549 550 551 552 553 554 555
      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");
556
      printf("-h This message\n");
557 558
      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");
559
      printf("-n Number of frames to simulate\n");
560 561 562
      printf("-o Introduce delay in terms of number of samples\n");
      printf("-p Precoding matrix index\n");
      printf("-q MCS Table index\n");
563 564
      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");
565 566 567 568
      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");
569
      printf("-y Number of TX antennas used in gNB\n");
570 571
      printf("-z Number of RX antennas used in UE\n");
      printf("-F Input filename (.txt format) for RX conformance testing\n");
572
      printf("-I Maximum LDPC decoder iterations\n");
573 574 575
      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");
576
      printf("-T Enable PTRS, arguments list L_PTRS{0,1,2} K_PTRS{2,4}, e.g. -T 2 0 2 \n");
577
      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");
578 579
      printf("-X gNB thread pool configuration, n => no threads\n");
      printf("-Y Run initial sync in UE\n");
580
      printf("-Z Output filename (.csv format) for stats\n");
581 582 583 584
      exit (-1);
      break;
    }
  }
585

586 587
  logInit();
  set_glog(loglvl);
588 589
  /* initialize the sin table */
  InitSinLUT();
590

591
  get_softmodem_params()->phy_test = 1;
592
  get_softmodem_params()->do_ra = 0;
593
  set_softmodem_optmask(SOFTMODEM_DLSIM_BIT);
594

595 596 597
  if (snr1set==0)
    snr1 = snr0+10;

598 599 600
  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
601

602
  gNB = RC.gNB[0];
603
  gNB->ofdm_offset_divisor = UINT_MAX;
604 605 606 607 608 609
  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;

610 611 612
  AssertFatal((gNB->if_inst = NR_IF_Module_init(0)) != NULL, "Cannot register interface");
  gNB->if_inst->NR_PHY_config_req = nr_phy_config_request;

613 614 615 616 617 618
  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);

619 620 621 622 623 624 625 626 627 628 629 630
  // 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
631
  RC.nb_nr_macrlc_inst = 1;
cig's avatar
cig committed
632 633 634
  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;
635
  mac_top_init_gNB(ngran_gNB, scc, NULL, &conf);
Raymond Knopp's avatar
Raymond Knopp committed
636
  gNB_mac = RC.nrmac[0];
637

638 639
  gNB_mac->dl_bler.harq_round_max = num_rounds;

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

Raymond Knopp's avatar
Raymond Knopp committed
647
  printf("Decoding NR_RRCReconfiguration (%d bytes)\n",msg_len);
Raymond Knopp's avatar
Raymond Knopp committed
648 649 650 651 652 653 654 655 656 657 658
  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);
659
  }
Raymond Knopp's avatar
Raymond Knopp committed
660 661
  fclose(scg_fd);

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

Raymond Knopp's avatar
Raymond Knopp committed
664
  NR_RRCReconfiguration_IEs_t *reconfig_ies = NR_RRCReconfiguration->criticalExtensions.choice.rrcReconfiguration;
665
  NR_CellGroupConfig_t *secondaryCellGroup = NULL;
Raymond Knopp's avatar
Raymond Knopp committed
666 667 668 669 670 671 672 673 674 675 676
  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);
677
  }
Raymond Knopp's avatar
Raymond Knopp committed
678
  
679 680
  NR_ServingCellConfigCommon_t *scc = secondaryCellGroup->spCellConfig->reconfigurationWithSync->spCellConfigCommon;
  */
Raymond Knopp's avatar
Raymond Knopp committed
681

Robert Schmidt's avatar
Robert Schmidt committed
682
  NR_ServingCellConfig_t *scd = calloc(1,sizeof(*scd));
683
  prepare_scd(scd);
684

francescomani's avatar
francescomani committed
685 686 687
  gNB->ap_N1 = pdsch_AntennaPorts.N1;
  gNB->ap_N2 = pdsch_AntennaPorts.N2;
  gNB->ap_XP = pdsch_AntennaPorts.XP;
688

689 690
  validate_input_pmi(pdsch_AntennaPorts, g_nrOfLayers, g_pmi);

691 692
  NR_UE_NR_Capability_t* UE_Capability_nr = CALLOC(1,sizeof(NR_UE_NR_Capability_t));
  prepare_sim_uecap(UE_Capability_nr,scc,mu,
693
                    N_RB_DL,g_mcsTableIdx,0);
694

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

697 698
  /* RRC parameter validation for secondaryCellGroup */
  fix_scd(scd);
Robert Schmidt's avatar
Robert Schmidt committed
699

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

709

710
  //xer_fprint(stdout, &asn_DEF_NR_CellGroupConfig, (const void*)secondaryCellGroup);
Raymond Knopp's avatar
Raymond Knopp committed
711 712

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

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

Raymond Knopp's avatar
Raymond Knopp committed
723
  // stub to configure frame_parms
Raymond Knopp's avatar
Raymond Knopp committed
724
  //  nr_phy_config_request_sim(gNB,N_RB_DL,N_RB_DL,mu,Nid_cell,SSB_positions);
Raymond Knopp's avatar
Raymond Knopp committed
725 726
  // call MAC to configure common parameters

727
  /* nr_mac_add_test_ue() has created one user, so set the scheduling
728 729 730 731 732
   * 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
733

734 735
  double fs,txbw,rxbw;
  uint32_t samples;
736

737 738 739 740 741 742 743
  get_samplerate_and_bw(mu,
                        N_RB_DL,
                        frame_parms->threequarter_fs,
                        &fs,
                        &samples,
                        &txbw,
                        &rxbw);
744 745 746 747

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

  if (gNB2UE==NULL) {
760
    printf("Problem generating channel model. Exiting.\n");
761 762 763 764
    exit(-1);
  }

  frame_length_complex_samples = frame_parms->samples_per_subframe*NR_NUMBER_OF_SUBFRAMES_PER_FRAME;
765
  //frame_length_complex_samples_no_prefix = frame_parms->samples_per_subframe_wCP*NR_NUMBER_OF_SUBFRAMES_PER_FRAME;
766 767
  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);
768

769 770 771 772 773
  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*));
774

775 776 777
  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));
778

779 780
    printf("Allocating %d samples for txdata\n", frame_length_complex_samples);
    txdata[i] = calloc(1, frame_length_complex_samples * sizeof(int));
781 782
  }

783 784 785
  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));
786 787 788 789 790 791 792 793 794
  }

  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
795
  memset((void*)UE,0,sizeof(PHY_VARS_NR_UE));
796 797 798 799
  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));
800
  UE->frame_parms.nb_antennas_rx = n_rx;
laurent's avatar
laurent committed
801
  UE->frame_parms.nb_antenna_ports_gNB = n_tx;
802
  UE->max_ldpc_iterations = max_ldpc_iterations;
Raymond Knopp's avatar
Raymond Knopp committed
803

francescomani's avatar
francescomani committed
804 805 806 807
  if (run_initial_sync==1)
    UE->is_synchronized = 0;
  else
    UE->is_synchronized = 1;
808

809
  if (init_nr_ue_signal(UE, 1) != 0)
810 811 812 813 814
  {
    printf("Error at UE NR initialisation\n");
    exit(-1);
  }

815
  init_nr_ue_transport(UE);
816

817
  nr_gold_pbch(UE);
818 819 820 821 822 823

  // 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
824 825 826 827
  for (int i = 0; i < 2; i++) {
    UE->scramblingID_dlsch[i] = frame_parms->Nid_cell;
    nr_gold_pdsch(UE, i, UE->scramblingID_dlsch[i]);
  }
828

829
  nr_l2_init_ue(NULL);
830
  UE_mac = get_mac_inst(0);
francescomani's avatar
francescomani committed
831
  ue_init_config_request(UE_mac, mu);
832

833 834 835
  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;
836
  UE->if_inst->dl_indication = nr_ue_dl_indication;
837
  UE->if_inst->ul_indication = dummy_nr_ue_ul_indication;
838 839
  UE->chest_freq = chest_type[0];
  UE->chest_time = chest_type[1];
840

841
  UE_mac->if_module = nr_ue_if_module_init(0);
francescomani's avatar
francescomani committed
842
  UE_mac->state = UE_CONNECTED;
843

844
  unsigned int available_bits=0;
Ahmed Hussein's avatar
Ahmed Hussein committed
845 846
  unsigned char *estimated_output_bit;
  unsigned char *test_input_bit;
847
  unsigned int errors_bit = 0;
Ahmed Hussein's avatar
Ahmed Hussein committed
848

849
  initFloatingCoresTpool(dlsch_threads, &nrUE_params.Tpool, false, "UE-tpool");
850

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

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

  nr_dcireq_t dcireq;
  nr_scheduled_response_t scheduled_response;
864
  nr_phy_data_t phy_data = {0};
865

866 867 868 869
  memset((void*)&dcireq,0,sizeof(dcireq));
  memset((void*)&scheduled_response,0,sizeof(scheduled_response));
  dcireq.module_id = 0;
  dcireq.gNB_index = 0;
870
  dcireq.cc_id = 0;
871
  
872 873 874 875
  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;
876
  scheduled_response.CC_id = 0;
877 878
  scheduled_response.frame = frame;
  scheduled_response.slot  = slot;
879
  scheduled_response.phy_data = &phy_data;
Francesco Mani's avatar
Francesco Mani committed
880

881
  nr_ue_phy_config_request(&UE_mac->phy_config);
Francesco Mani's avatar
Francesco Mani committed
882
  //NR_COMMON_channels_t *cc = RC.nrmac[0]->common_channels;
883
  int n_errs = 0;
884

885
  initNamedTpool(gNBthreads, &gNB->threadPool, true, "gNB-tpool");
886 887 888
  initNotifiedFIFO(&gNB->L1_tx_free);
  initNotifiedFIFO(&gNB->L1_tx_filled);
  initNotifiedFIFO(&gNB->L1_tx_out);
Sakthivel Velumani's avatar
Sakthivel Velumani committed
889
  // we create 2 threads for L1 tx processing
890
  notifiedFIFO_elt_t *msgL1Tx = newNotifiedFIFO_elt(sizeof(processingData_L1tx_t),0,&gNB->L1_tx_free,processSlotTX);
Sakthivel Velumani's avatar
Sakthivel Velumani committed
891 892 893 894 895
  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));
896

897
  // Buffers to store internal memory of slot process
898 899 900 901 902 903 904
  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);
905 906 907 908 909 910 911
  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);
912

913 914 915 916 917 918 919 920 921 922 923 924 925 926
  // 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
927
  for (SNR = snr0; SNR < snr1; SNR += .2) {
928

929 930 931 932 933 934 935 936 937 938
    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);
939
    reset_meas(&gNB->toutput);
940

941 942 943 944 945 946 947
    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};

948
    effRate = 0;
949 950
    //n_errors2 = 0;
    //n_alamouti = 0;
951
    n_false_positive = 0;
952 953
    if (n_trials== 1) num_rounds = 1;

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

956
      errors_bit = 0;
Ahmed Hussein's avatar
Ahmed Hussein committed
957
      //multipath channel
958
      //multipath_channel(gNB2UE,s_re,s_im,r_re,r_im,frame_length_complex_samples,0);
959

960
      UE->rx_offset=0;
961
      UE_proc.frame_rx = frame;
962
      UE_proc.nr_slot_rx = slot;
963
      UE_proc.gNB_id = 0;
964
      
965 966
      dcireq.frame = frame;
      dcireq.slot = slot;
967

968
      NR_UE_DLSCH_t *dlsch0 = &phy_data.dlsch[0];
969

970
      int harq_pid = slot;
971
      NR_DL_UE_HARQ_t *UE_harq_process = &UE->dl_harq_processes[0][harq_pid];
972

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

      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;

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

992
        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
993 994
        UE_info->UE_sched_ctrl.harq_processes[harq_pid].ndi = !(trial&1);
        UE_info->UE_sched_ctrl.harq_processes[harq_pid].round = round;
995

996 997
        // nr_schedule_ue_spec() requires the mutex to be locked
        NR_SCHED_LOCK(&gNB_mac->sched_lock);
998
        nr_schedule_ue_spec(0, frame, slot, &Sched_INFO->DL_req, &Sched_INFO->TX_req);
999
        NR_SCHED_UNLOCK(&gNB_mac->sched_lock);
1000 1001 1002 1003 1004
        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;
1005
        pushNotifiedFIFO(&gNB->L1_tx_free,msgL1Tx);
1006
        nr_schedule_response(Sched_INFO);
1007 1008

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

        msgDataTx->ssb[0].ssb_pdu.ssb_pdu_rel15.bchPayload=0x001234;
        msgDataTx->ssb[0].ssb_pdu.ssb_pdu_rel15.SsbBlockIndex = 0;
        msgDataTx->gNB = gNB;
1027
        if (run_initial_sync)
Sakthivel Velumani's avatar
Sakthivel Velumani committed
1028
          nr_common_signal_procedures(gNB,frame,slot,msgDataTx->ssb[0].ssb_pdu);
1029
        else
Sakthivel Velumani's avatar
Sakthivel Velumani committed
1030
          phy_procedures_gNB_TX(msgDataTx,frame,slot,1);
1031
            
1032
        int txdataF_offset = slot * frame_parms->samples_per_slot_wCP;
1033 1034
        
        if (n_trials==1) {
1035
          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);
1036
          if (gNB->frame_parms.nb_antennas_tx>1)
1037
            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);
1038
        }
1039
        if (n_trials == 1) printf("slot_offset %d, txdataF_offset %d \n", slot_offset, txdataF_offset);
1040

1041 1042
        //TODO: loop over slots
        for (aa=0; aa<gNB->frame_parms.nb_antennas_tx; aa++) {
1043

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

1071 1072 1073 1074
        int txlev[n_tx];
        int txlev_sum = 0;
        int l_ofdm = 6;
        for (aa=0; aa<n_tx; aa++) {
1075
          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],
1076 1077 1078 1079
          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);
        }
1080 1081

        for (i = 0; i < slot_length; i++) {
1082
          for (aa=0; aa<frame_parms->nb_antennas_tx; aa++) {
1083 1084
            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]);
1085
          }
1086
        }
1087

1088
        double ts = 1.0/(frame_parms->subcarrier_spacing * frame_parms->ofdm_symbol_size); 
1089
        //Compute AWGN variance
1090
        sigma2_dB = 10 * log10((double)txlev_sum * ((double)UE->frame_parms.ofdm_symbol_size/(12*rel15->rbSize))) - SNR;
1091
        sigma2    = pow(10, sigma2_dB/10);
1092
        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));
1093

1094 1095 1096
        for (aa = 0; aa < n_rx; aa++) {
          bzero(r_re[aa], slot_length * sizeof(double));
          bzero(r_im[aa], slot_length * sizeof(double));
1097
        }
1098

1099
        // Apply MIMO Channel
1100
        multipath_channel(gNB2UE, s_re, s_im, r_re, r_im, slot_length, 0, (n_trials == 1) ? 1 : 0);
1101
        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);
1102

1103 1104
        nr_ue_dcireq(&dcireq); //to be replaced with function pointer later
        nr_ue_scheduled_response(&scheduled_response);
1105

1106 1107 1108 1109 1110 1111
        pbch_pdcch_processing(UE,
                              &UE_proc,
                              &phy_data);
        pdsch_processing(UE,
                         &UE_proc,
                         &phy_data);
1112 1113 1114
        //----------------------------------------------------------
        //---------------------- count errors ----------------------
        //----------------------------------------------------------
1115

1116
        if (dlsch0->last_iteration_cnt >= dlsch0->max_ldpc_iterations+1)
1117
          n_errors[round]++;
1118

1119
        int16_t *UE_llr = (int16_t*)UE->phy_sim_pdsch_llr;
1120

1121
        TBS                  = dlsch0->dlsch_config.TBS;//rel15->TBSize[0];
1122 1123
        uint16_t length_dmrs = get_num_dmrs(rel15->dlDmrsSymbPos);
        uint16_t nb_rb       = rel15->rbSize;
1124
        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;
1125 1126
        uint8_t  mod_order   = rel15->qamModOrder[0];
        uint8_t  nb_symb_sch = rel15->NrOfSymbols;
1127

1128
        available_bits = nr_get_G(nb_rb, nb_symb_sch, nb_re_dmrs, length_dmrs, mod_order, rel15->nrOfLayers);
1129 1130 1131 1132 1133
        if (pdu_bit_map & 0x1) {
          available_bits -= (ptrsSymbPerSlot * ptrsRePerSymb * rel15->nrOfLayers * 2);
          if (trial == 0 && round == 0) {
            printf("[DLSIM][PTRS] Available bits are: %5u, removed PTRS bits are: %5u \n", available_bits, (ptrsSymbPerSlot * ptrsRePerSymb * rel15->nrOfLayers * 2));
          }
1134
        }
1135

1136 1137 1138 1139
        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)))
          {
1140
            if (errors_scrambling[round] == 0) {
1141 1142
              LOG_D(PHY,"First bit in error in unscrambling = %d\n",i);
            }
1143
            errors_scrambling[round]++;
1144 1145
          }
        }
1146

1147 1148 1149
        //printf("dlsim round %d ends\n",round);
        round++;
      } // round
1150

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

1153
	estimated_output_bit[i] = (UE->phy_sim_dlsch_b[i/8] & (1 << (i & 7))) >> (i & 7);
1154
	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
1155
	
1156 1157
	if (estimated_output_bit[i] != test_input_bit[i]) {
	  if(errors_bit == 0)
1158
	    LOG_D(PHY,"First bit in error in decoding = %d\n",i);
1159
	  errors_bit++;
Raymond Knopp's avatar
Raymond Knopp committed
1160 1161
	}
	
1162 1163
      }
      ////////////////////////////////////////////////////////////
1164

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

1174
    roundStats /= ((float)n_trials);
1175

1176
    for (int r = 0; r < num_rounds; r++) {
1177 1178
      blerStats[r] = (double)n_errors[r] / round_trials[r];
      berStats[r] = (double)errors_scrambling[r] / available_bits / round_trials[r];
1179
    }
1180

1181
    effRate /= n_trials;
Ahmed Hussein's avatar
Ahmed Hussein committed
1182
    printf("*****************************************\n");
1183
    printf("SNR %f: n_errors (%d/%d", SNR, n_errors[0], round_trials[0]);
1184
    for (int r = 1; r < num_rounds; r++)
1185 1186
      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]);
1187
    for (int r = 1; r < num_rounds; r++)
1188
      printf(",%u/%u", errors_scrambling[r], available_bits * round_trials[r]);
1189
    printf(")\n\n");
Raymond Knopp's avatar
Raymond Knopp committed
1190
    dump_pdsch_stats(stdout,gNB);
1191
    printf("SNR %f: Channel BLER (%e", SNR, blerStats[0]);
1192
    for (int r = 1; r < num_rounds; r++)
1193 1194
      printf(",%e", blerStats[r]);
    printf("), Channel BER (%e", berStats[0]);
1195
    for (int r = 1; r < num_rounds; r++)
1196 1197
      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);
1198
    printf("*****************************************\n");
Ahmed Hussein's avatar
Ahmed Hussein committed
1199
    printf("\n");
1200 1201 1202 1203 1204 1205 1206
    // 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);
    }
1207
    if (print_perf==1) {
1208
      printf("\ngNB TX function statistics (per %d us slot, NPRB %d, mcs %d, block %d)\n",
francescomani's avatar
francescomani committed
1209 1210 1211 1212
             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
1213
      printDistribution(&gNB->phy_proc_tx,table_tx,"PHY proc tx");
1214 1215 1216 1217 1218 1219 1220 1221 1222 1223
      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");
1224 1225 1226
      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");
1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242

      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",
1243 1244 1245
	     UE->dlsch[0][0]->harq_processes[0]->Cminus ?
	     UE->dlsch[0][0]->harq_processes[0]->Kminus :
	     UE->dlsch[0][0]->harq_processes[0]->Kplus,
1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258
	     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");
      */
    }
1259 1260

    if (n_trials == 1) {
1261

1262 1263 1264
      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);
1265 1266 1267 1268 1269
      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);
1270 1271 1272
      break;
    }

1273
    if (effRate > (eff_tp_check*TBS)) {
1274 1275 1276 1277
      printf("PDSCH test OK\n");
      break;
    }

1278
    n_errs = n_errors[0];
1279 1280
  } // NSR

1281 1282
  free_channel_desc_scm(gNB2UE);

1283
  for (i = 0; i < n_tx; i++) {
1284 1285
    free(s_re[i]);
    free(s_im[i]);
1286 1287 1288
    free(txdata[i]);
  }
  for (i = 0; i < n_rx; i++) {
1289 1290 1291 1292 1293 1294 1295 1296 1297
    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
1298 1299
  free(test_input_bit);
  free(estimated_output_bit);
1300 1301 1302 1303 1304 1305
  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);
1306
  free(UE->phy_sim_dlsch_b);
Ahmed Hussein's avatar
Ahmed Hussein committed
1307
  
1308 1309 1310 1311 1312 1313
  if (output_fd)
    fclose(output_fd);

  if (input_fd)
    fclose(input_fd);

1314 1315
  if (scg_fd)
    fclose(scg_fd);
1316

1317 1318 1319 1320 1321 1322
  // closing csv file
  if (filename_csv != NULL) { // means we are asked to print stats to CSV
    fclose(csv_file);
    free(filename_csv);
  }

1323
  return n_errs;
1324
}
1325 1326


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

  long epre_Ratio = 0;
  long reOffset = 0;
1335

1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347
  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 {
1348 1349 1350
    printf("[DLSIM] Wrong L_PTRS value, using default values 1\n");
  }
  /* L = 4 if Imcs < MCS4 */
1351 1352 1353 1354 1355 1356 1357 1358 1359 1360
  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");
  }
1361
  printf("[DLSIM] PTRS Enabled with L %d, K %d \n", 1<<ptrs_arg[0], ptrs_arg[1] );
1362 1363 1364 1365
  /* overwrite the values */
  rrc_config_dl_ptrs_params(bwp, ptrsFreqDenst, ptrsTimeDenst, &epre_Ratio, &reOffset);
}

1366
void update_dmrs_config(NR_CellGroupConfig_t *scg, int8_t* dmrs_arg)
1367 1368 1369
{
  int8_t  mapping_type = typeA;//default value
  int8_t  add_pos = pdsch_dmrs_pos0;//default value
1370 1371
  int8_t  dmrs_config_type = NFAPI_NR_DMRS_TYPE1;//default value

1372
  if(dmrs_arg[0] == 0) {
1373 1374
    mapping_type = typeA;
  }
1375
  else if (dmrs_arg[0] == 1) {
1376
    mapping_type = typeB;
1377 1378
  } else {
    AssertFatal(1==0,"Incorrect Mappingtype, valid options 0-typeA, 1-typeB\n");
1379
  }
1380 1381 1382

  /* Additional DMRS positions 0 ,1 ,2 and 3 */
  if(dmrs_arg[1] >= 0 && dmrs_arg[1] <4 ) {
1383
    add_pos = dmrs_arg[1];
1384 1385
  } else {
    AssertFatal(1==0,"Incorrect Additional Position, valid options 0-pos1, 1-pos1, 2-pos2, 3-pos3\n");
1386
  }
1387

1388
  /* DMRS Conf Type 1 or 2 */
1389 1390 1391 1392
  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;
1393
  }
1394

1395
  NR_BWP_Downlink_t *bwp = scg->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.array[0];
1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413

  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");
  }
1414

1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429
  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");
  }
1430

1431 1432
  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;
1433 1434


1435 1436 1437 1438 1439
  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));
1440
    }
1441 1442 1443 1444
    *dmrs_config->dmrs_AdditionalPosition = add_pos;
  } else { // if NULL, Value pos2
    free(dmrs_config->dmrs_AdditionalPosition);
    dmrs_config->dmrs_AdditionalPosition = NULL;
1445
  }
1446

1447
  for (int i=0;i<bwp->bwp_Common->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list.count;i++) {
1448
    bwp->bwp_Common->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list.array[i]->mappingType = mapping_type;
1449
  }
1450

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