dlsim.c 56 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 112 113 114
int8_t nr_rrc_RA_succeeded(const module_id_t mod_id, const uint8_t gNB_index) {
  return 0;
}

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

120 121
void processSlotTX(void *arg) {}

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

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

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

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

142 143 144 145 146 147 148
  //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;
149

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

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

184 185
  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
186 187 188 189 190

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

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

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

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

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

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

230

231
void validate_input_pmi(nr_pdsch_AntennaPorts_t pdsch_AntennaPorts, int nrOfLayers, int pmi)
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 259
{
  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
260
}
261 262


laurent's avatar
laurent committed
263
int NB_UE_INST = 1;
264

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

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

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

305
  //uint8_t frame_mod4,num_pdcch_symbols = 0;
306

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

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

315
  //unsigned char frame_type = 0;
316

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

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

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

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

  randominit(0);

353
  int print_perf = 0;
354

355
  FILE *scg_fd=NULL;
356

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

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

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

      break;

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

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

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

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

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

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

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

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

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

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

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

      break;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

595 596 597
  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
598

599
  gNB = RC.gNB[0];
600
  gNB->ofdm_offset_divisor = UINT_MAX;
601 602 603 604 605 606
  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;

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

610 611 612 613 614 615
  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);

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

635 636
  gNB_mac->dl_bler.harq_round_max = num_rounds;

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

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

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

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

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

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

686 687
  validate_input_pmi(pdsch_AntennaPorts, g_nrOfLayers, g_pmi);

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

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

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

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

706

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

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

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

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

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

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

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

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

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

  frame_length_complex_samples = frame_parms->samples_per_subframe*NR_NUMBER_OF_SUBFRAMES_PER_FRAME;
762
  //frame_length_complex_samples_no_prefix = frame_parms->samples_per_subframe_wCP*NR_NUMBER_OF_SUBFRAMES_PER_FRAME;
763 764
  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);
765

766 767 768 769 770
  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*));
771

772 773 774
  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));
775

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

780 781 782
  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));
783 784 785 786 787 788 789 790 791
  }

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

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

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

812
  init_nr_ue_transport(UE);
813

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

938 939 940 941 942 943 944
    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};

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

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

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

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

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

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

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

      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;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

1125
        available_bits = nr_get_G(nb_rb, nb_symb_sch, nb_re_dmrs, length_dmrs, mod_order, rel15->nrOfLayers);
1126 1127 1128 1129 1130
        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));
          }
1131
        }
1132

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

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

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

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

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

1171
    roundStats /= ((float)n_trials);
1172

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

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

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

    if (n_trials == 1) {
1258

1259 1260 1261
      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);
1262 1263 1264 1265 1266
      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);
1267 1268 1269
      break;
    }

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

1275
    n_errs = n_errors[0];
1276 1277
  } // NSR

1278 1279
  free_channel_desc_scm(gNB2UE);

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

  if (input_fd)
    fclose(input_fd);

1311 1312
  if (scg_fd)
    fclose(scg_fd);
1313

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

1320
  return n_errs;
1321
}
1322 1323


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

  long epre_Ratio = 0;
  long reOffset = 0;
1332

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

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

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

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

1385
  /* DMRS Conf Type 1 or 2 */
1386 1387 1388 1389
  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;
1390
  }
1391

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

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

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

1428 1429
  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;
1430 1431


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

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

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