dlsim.c 55.7 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 30
#include "common/config/config_userapi.h"
#include "common/utils/LOG/log.h"
31 32 33
#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"
34
#include "PHY/defs_gNB.h"
35 36
#include "PHY/defs_nr_common.h"
#include "PHY/defs_nr_UE.h"
37
#include "PHY/phy_vars_nr_ue.h"
38 39
#include "PHY/types.h"
#include "PHY/INIT/phy_init.h"
40
#include "PHY/MODULATION/modulation_eNB.h"
41
#include "PHY/MODULATION/nr_modulation.h"
42
#include "PHY/MODULATION/modulation_UE.h"
43
#include "PHY/NR_REFSIG/refsig_defs_ue.h"
44
#include "PHY/NR_TRANSPORT/nr_dlsch.h"
cig's avatar
cig committed
45
#include "PHY/NR_TRANSPORT/nr_transport_proto.h"
46
#include "PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h"
47
#include "SCHED_NR/fapi_nr_l1.h"
48
#include "SCHED_NR/sched_nr.h"
49
#include "SCHED_NR_UE/defs.h"
50 51 52 53
#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"

54
#include "LAYER2/NR_MAC_UE/mac_proto.h"
yilmazt's avatar
yilmazt committed
55 56
//#include "LAYER2/NR_MAC_gNB/mac_proto.h"
//#include "openair2/LAYER2/NR_MAC_UE/mac_proto.h"
57
#include "LAYER2/NR_MAC_gNB/mac_proto.h"
58
#include "NR_asn_constant.h"
59
#include "RRC/NR/MESSAGES/asn1_msg.h"
60 61 62
#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
63
//#include "openair1/SIMULATION/NR_PHY/nr_dummy_functions.c"
64
#include "PHY/NR_REFSIG/ptrs_nr.h"
Raymond Knopp's avatar
Raymond Knopp committed
65
#include "NR_RRCReconfiguration.h"
66
#define inMicroS(a) (((double)(a))/(get_cpu_freq_GHz()*1000.0))
67 68
#include "SIMULATION/LTE_PHY/common_sim.h"

Laurent's avatar
Laurent committed
69 70
#include <openair2/LAYER2/MAC/mac_vars.h>
#include <openair2/RRC/LTE/rrc_vars.h>
71

Raymond Knopp's avatar
Raymond Knopp committed
72 73
#include <executables/softmodem-common.h>

74 75
LCHAN_DESC DCCH_LCHAN_DESC,DTCH_DL_LCHAN_DESC,DTCH_UL_LCHAN_DESC;
rlc_info_t Rlc_info_um,Rlc_info_am_config;
Raymond Knopp's avatar
Raymond Knopp committed
76

77 78 79
PHY_VARS_gNB *gNB;
PHY_VARS_NR_UE *UE;
RAN_CONTEXT_t RC;
80 81
int32_t uplink_frequency_offset[MAX_NUM_CCs][4];

82
double cpuf;
83

Laurent THOMAS's avatar
Laurent THOMAS committed
84 85
uint16_t sf_ahead=4 ;
uint16_t sl_ahead=0;
86
//uint8_t nfapi_mode = 0;
87
uint64_t downlink_frequency[MAX_NUM_CCs][4];
88 89
THREAD_STRUCT thread_struct;
nfapi_ue_release_request_body_t release_rntis;
rmagueta's avatar
rmagueta committed
90
uint32_t N_RB_DL = 106;
91 92

// dummy functions
Raymond Knopp's avatar
Raymond Knopp committed
93 94
int dummy_nr_ue_ul_indication(nr_uplink_indication_t *ul_info)              { return(0);  }

95 96 97 98 99 100 101 102 103
int8_t nr_mac_rrc_data_ind_ue(const module_id_t module_id,
                              const int CC_id,
                              const uint8_t gNB_index,
                              const frame_t frame,
                              const sub_frame_t sub_frame,
                              const rnti_t rnti,
                              const channel_t channel,
                              const uint8_t* pduP,
                              const sdu_size_t pdu_len)
104 105 106 107
{
  return 0;
}

108 109 110 111 112
void nr_rrc_ue_generate_RRCSetupRequest(module_id_t module_id, const uint8_t gNB_index)
{
  return;
}

113 114 115 116 117 118 119 120 121 122
int8_t nr_mac_rrc_data_req_ue(const module_id_t Mod_idP,
                              const int         CC_id,
                              const uint8_t     gNB_id,
                              const frame_t     frameP,
                              const rb_id_t     Srb_id,
                              uint8_t           *buffer_pP)
{
  return 0;
}

123 124
void
rrc_data_ind(
125
  const protocol_ctxt_t *const ctxt_pP,
126 127 128 129 130 131 132
  const rb_id_t                Srb_id,
  const sdu_size_t             sdu_sizeP,
  const uint8_t   *const       buffer_pP
)
{
}

rmagueta's avatar
rmagueta committed
133 134 135 136 137 138
int ocp_gtpv1u_create_s1u_tunnel(instance_t instance,
                                 const gtpv1u_enb_create_tunnel_req_t  *create_tunnel_req,
                                 gtpv1u_enb_create_tunnel_resp_t *create_tunnel_resp) {
    return 0;
}

139 140 141 142 143 144 145 146
int
gtpv1u_create_s1u_tunnel(
  const instance_t                              instanceP,
  const gtpv1u_enb_create_tunnel_req_t *const  create_tunnel_req_pP,
  gtpv1u_enb_create_tunnel_resp_t *const create_tunnel_resp_pP
) {
  return 0;
}
147

148 149 150 151 152 153 154 155
int
rrc_gNB_process_GTPV1U_CREATE_TUNNEL_RESP(
  const protocol_ctxt_t *const ctxt_pP,
  const gtpv1u_enb_create_tunnel_resp_t *const create_tunnel_resp_pP,
  uint8_t                         *inde_list
) {
  return 0;
}
156

heshanyun's avatar
heshanyun committed
157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173
int
gtpv1u_create_ngu_tunnel(
  const instance_t instanceP,
  const gtpv1u_gnb_create_tunnel_req_t *  const create_tunnel_req_pP,
        gtpv1u_gnb_create_tunnel_resp_t * const create_tunnel_resp_pP){
  return 0;
}

int
gtpv1u_update_ngu_tunnel(
  const instance_t                              instanceP,
  const gtpv1u_gnb_create_tunnel_req_t *const  create_tunnel_req_pP,
  const rnti_t                                  prior_rnti
){
  return 0;
}

rmagueta's avatar
rmagueta committed
174 175 176 177
int ocp_gtpv1u_delete_s1u_tunnel(const instance_t instance, const gtpv1u_enb_delete_tunnel_req_t *const req_pP) {
  return 0;
}

heshanyun's avatar
heshanyun committed
178 179 180 181 182 183 184 185 186
int
nr_rrc_gNB_process_GTPV1U_CREATE_TUNNEL_RESP(
  const protocol_ctxt_t *const ctxt_pP,
  const gtpv1u_gnb_create_tunnel_resp_t *const create_tunnel_resp_pP,
  uint8_t                         *inde_list
){
  return 0;
}

187 188 189 190 191 192
int nr_derive_key(int alg_type, uint8_t alg_id,
               const uint8_t key[32], uint8_t **out)
{
  return 0;
}

193
void config_common(int Mod_idP,
194
                   int ssb_SubcarrierOffset,
195 196
                   int pdsch_AntennaPorts,
                   int pusch_AntennaPorts,
197
		   NR_ServingCellConfigCommon_t *scc
Raymond Knopp's avatar
Raymond Knopp committed
198
		   );
199

200 201 202 203 204 205 206 207 208
int generate_dlsch_header(unsigned char *mac_header,
                          unsigned char num_sdus,
                          unsigned short *sdu_lengths,
                          unsigned char *sdu_lcids,
                          unsigned char drx_cmd,
                          unsigned short timing_advance_cmd,
                          unsigned char *ue_cont_res_id,
                          unsigned char short_padding,
                          unsigned short post_padding){return 0;}
209

210
// Dummy function to avoid linking error at compilation of nr-dlsim
211 212 213 214 215
int is_x2ap_enabled(void)
{
  return 0;
}

rmagueta's avatar
rmagueta committed
216 217 218 219 220 221 222 223 224 225 226
int DU_send_INITIAL_UL_RRC_MESSAGE_TRANSFER(module_id_t     module_idP,
                                            int             CC_idP,
                                            int             UE_id,
                                            rnti_t          rntiP,
                                            const uint8_t   *sduP,
                                            sdu_size_t      sdu_lenP,
                                            const uint8_t   *sdu2P,
                                            sdu_size_t      sdu2_lenP) {
  return 0;
}

227 228
void processSlotTX(void *arg) {}

Mahesh's avatar
Mahesh committed
229
//nFAPI P7 dummy functions to avoid linking errors 
Mahesh's avatar
Mahesh committed
230 231 232 233 234

int oai_nfapi_dl_tti_req(nfapi_nr_dl_tti_request_t *dl_config_req) { return(0);  }
int oai_nfapi_tx_data_req(nfapi_nr_tx_data_request_t *tx_data_req){ return(0);  }
int oai_nfapi_ul_dci_req(nfapi_nr_ul_dci_request_t *ul_dci_req){ return(0);  }
int oai_nfapi_ul_tti_req(nfapi_nr_ul_tti_request_t *ul_tti_req){ return(0);  }
Mahesh's avatar
Mahesh committed
235 236 237 238 239
int oai_nfapi_nr_rx_data_indication(nfapi_nr_rx_data_indication_t *ind) { return(0);  }
int oai_nfapi_nr_crc_indication(nfapi_nr_crc_indication_t *ind) { return(0);  }
int oai_nfapi_nr_srs_indication(nfapi_nr_srs_indication_t *ind) { return(0);  }
int oai_nfapi_nr_uci_indication(nfapi_nr_uci_indication_t *ind) { return(0);  }
int oai_nfapi_nr_rach_indication(nfapi_nr_rach_indication_t *ind) { return(0);  }
rmagueta's avatar
rmagueta committed
240

241
// needed for some functions
242
openair0_config_t openair0_cfg[MAX_CARDS];
243
void update_ptrs_config(NR_CellGroupConfig_t *secondaryCellGroup, uint16_t *rbSize, uint8_t *mcsIndex,int8_t *ptrs_arg);
244
void update_dmrs_config(NR_CellGroupConfig_t *scg, int8_t* dmrs_arg);
rmagueta's avatar
rmagueta committed
245
extern void fix_scd(NR_ServingCellConfig_t *scd);// forward declaration
246

247
/* specific dlsim DL preprocessor: uses rbStart/rbSize/mcs/nrOfLayers from command line of
248
   dlsim, does not search for CCE/PUCCH occasion but simply sets to 0 */
249
int g_mcsIndex = -1, g_mcsTableIdx = 0, g_rbStart = -1, g_rbSize = -1, g_nrOfLayers = 1;
250 251
void nr_dlsim_preprocessor(module_id_t module_id,
                           frame_t frame,
252
                           sub_frame_t slot) {
253 254 255
  NR_UE_info_t *UE_info = &RC.nrmac[module_id]->UE_info;
  AssertFatal(UE_info->num_UEs == 1, "can have only a single UE\n");
  NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl[0];
rmagueta's avatar
rmagueta committed
256
  NR_ServingCellConfigCommon_t *scc = RC.nrmac[0]->common_channels[0].ServingCellConfigCommon;
257 258 259

  /* manually set free CCE to 0 */
  const int target_ss = NR_SearchSpace__searchSpaceType_PR_ue_Specific;
rmagueta's avatar
rmagueta committed
260
  sched_ctrl->search_space = get_searchspace(scc, sched_ctrl->active_bwp ? sched_ctrl->active_bwp->bwp_Dedicated : NULL, target_ss);
261 262 263
  uint8_t nr_of_candidates;
  find_aggregation_candidates(&sched_ctrl->aggregation_level,
                              &nr_of_candidates,
Eurecom's avatar
Eurecom committed
264 265
                              sched_ctrl->search_space,4);
  sched_ctrl->coreset = get_coreset(scc, sched_ctrl->active_bwp->bwp_Dedicated, sched_ctrl->search_space, target_ss);
266 267
  sched_ctrl->cce_index = 0;

268
  NR_pdsch_semi_static_t *ps = &sched_ctrl->pdsch_semi_static;
rmagueta's avatar
rmagueta committed
269

270 271
  ps->nrOfLayers = g_nrOfLayers;

272
  nr_set_pdsch_semi_static(scc,
rmagueta's avatar
rmagueta committed
273
                           UE_info->CellGroup[0],
274
                           sched_ctrl->active_bwp,
rmagueta's avatar
rmagueta committed
275
                           NULL,
276
                           /* tda = */ 2,
rmagueta's avatar
rmagueta committed
277
                           /* dci_format = */ 0,
278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296
                           ps);

  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;
  /* the following might override the table that is mandated by RRC
   * configuration */
  ps->mcsTableIdx = g_mcsTableIdx;

  sched_pdsch->Qm = nr_get_Qm_dl(sched_pdsch->mcs, ps->mcsTableIdx);
  sched_pdsch->R = nr_get_code_rate_dl(sched_pdsch->mcs, ps->mcsTableIdx);
  sched_pdsch->tb_size = nr_compute_tbs(sched_pdsch->Qm,
                                        sched_pdsch->R,
                                        sched_pdsch->rbSize,
                                        ps->nrOfSymbols,
                                        ps->N_PRB_DMRS * ps->N_DMRS_SLOT,
                                        0 /* N_PRB_oh, 0 for initialBWP */,
                                        0 /* tb_scaling */,
297
                                        ps->nrOfLayers)
298 299
                         >> 3;

300
  /* the simulator assumes the HARQ PID is equal to the slot number */
301 302
  sched_pdsch->dl_harq_pid = slot;

303 304 305 306 307 308 309 310 311 312 313 314
  /* 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;
315 316 317 318
  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);
  AssertFatal(ps->mcsTableIdx >= 0 && ps->mcsTableIdx <= 2, "invalid mcsTableIdx %d\n", ps->mcsTableIdx);
319
}
320

Sakthivel Velumani's avatar
Sakthivel Velumani committed
321 322 323
typedef struct {
  uint64_t       optmask;   //mask to store boolean config options
  uint8_t        nr_dlsch_parallel; // number of threads for dlsch decoding, 0 means no parallelization
324
  tpool_t        Tpool;             // thread pool
Sakthivel Velumani's avatar
Sakthivel Velumani committed
325 326 327 328 329 330 331
} nrUE_params_t;

nrUE_params_t nrUE_params;

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

Sakthivel Velumani's avatar
Sakthivel Velumani committed
333 334
void do_nothing(void *args) {
}
335

336 337 338
int main(int argc, char **argv)
{
  char c;
339
  int i,aa;//,l;
340
  double sigma2, sigma2_dB=10, SNR, snr0=-2.0, snr1=2.0;
341
  uint8_t snr1set=0;
342 343 344 345
  double roundStats[500] = {0};
  double blerStats[500] = {0};
  double berStats[500] = {0};
  double snrStats[500] = {0};
346
  float effRate;
Francesco Mani's avatar
Francesco Mani committed
347
  //float psnr;
348
  float eff_tp_check = 0.7;
349
  uint8_t snrRun;
350
  uint32_t TBS = 0;
351 352
  int **txdata;
  double **s_re,**s_im,**r_re,**r_im;
353 354
  //double iqim = 0.0;
  //unsigned char pbch_pdu[6];
355 356 357
  //  int sync_pos, sync_pos_slot;
  //  FILE *rx_frame_file;
  FILE *output_fd = NULL;
358
  //uint8_t write_output_file=0;
359
  //int result;
360
  //int freq_offset;
361
  //  int subframe_offset;
362
  //  char fname[40], vname[40];
Ahmed Hussein's avatar
Ahmed Hussein committed
363
  int trial, n_trials = 1, n_errors = 0, n_false_positive = 0;
364
  //int n_errors2, n_alamouti;
365
  uint8_t n_tx=1,n_rx=1;
366 367
  uint8_t round;
  uint8_t num_rounds = 4;
368 369

  channel_desc_t *gNB2UE;
370 371 372
  //uint32_t nsymb,tx_lev,tx_lev1 = 0,tx_lev2 = 0;
  //uint8_t extended_prefix_flag=0;
  //int8_t interf1=-21,interf2=-21;
373 374

  FILE *input_fd=NULL,*pbch_file_fd=NULL;
375
  //char input_val_str[50],input_val_str2[50];
376

377
  //uint8_t frame_mod4,num_pdcch_symbols = 0;
378

379
  SCM_t channel_model = AWGN; // AWGN Rayleigh1 Rayleigh1_anticorr;
380

Laurent's avatar
Laurent committed
381
  NB_UE_INST = 1;
382 383
  //double pbch_sinr;
  //int pbch_tx_ant;
Ahmed Hussein's avatar
Ahmed Hussein committed
384
  int N_RB_DL=106,mu=1;
385

386
  //unsigned char frame_type = 0;
387

388
  int frame=1,slot=1;
389
  int frame_length_complex_samples;
390
  //int frame_length_complex_samples_no_prefix;
391 392 393 394 395
  NR_DL_FRAME_PARMS *frame_parms;
  UE_nr_rxtx_proc_t UE_proc;
  NR_Sched_Rsp_t Sched_INFO;
  gNB_MAC_INST *gNB_mac;
  NR_UE_MAC_INST_t *UE_mac;
396
  int cyclic_prefix_type = NFAPI_CP_NORMAL;
397
  int run_initial_sync=0;
Raymond Knopp's avatar
Raymond Knopp committed
398
  int loglvl=OAILOG_INFO;
399

400
  //float target_error_rate = 0.01;
401
  int css_flag=0;
402 403

  cpuf = get_cpu_freq_GHz();
404 405 406
  int8_t enable_ptrs = 0;
  int8_t modify_dmrs = 0;

407
  int8_t dmrs_arg[3] = {-1,-1,-1};// Invalid values
408
  /* L_PTRS = ptrs_arg[0], K_PTRS = ptrs_arg[1] */
409 410
  int8_t ptrs_arg[2] = {-1,-1};// Invalid values

411 412 413 414 415 416
  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;
417
  uint8_t  dlsch_threads = 0;
418
  int      prb_inter = 0;
419
  if ( load_configmodule(argc,argv,CONFIG_ENABLECMDLINEONLY) == 0) {
yilmazt's avatar
yilmazt committed
420
    exit_fun("[NR_DLSIM] Error, configuration module init failed\n");
421 422 423 424
  }

  randominit(0);

425
  int print_perf             = 0;
426

427 428
  FILE *scg_fd=NULL;
  
429
  while ((c = getopt (argc, argv, "f:hA:pf:g:in:s:S:t:x:y:z:M:N:F:GR:dPIL:Ea:b:d:e:m:w:T:U:q")) != -1) {
430
    switch (c) {
431 432
    case 'f':
      scg_fd = fopen(optarg,"r");
433

434
      if (scg_fd==NULL) {
435 436 437
        printf("Error opening %s\n",optarg);
        exit(-1);
      }
438
      break;
439

440
    /*case 'd':
441
      frame_type = 1;
442
      break;*/
443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473

    case 'g':
      switch((char)*optarg) {
      case 'A':
        channel_model=SCM_A;
        break;

      case 'B':
        channel_model=SCM_B;
        break;

      case 'C':
        channel_model=SCM_C;
        break;

      case 'D':
        channel_model=SCM_D;
        break;

      case 'E':
        channel_model=EPA;
        break;

      case 'F':
        channel_model=EVA;
        break;

      case 'G':
        channel_model=ETU;
        break;

sfn's avatar
sfn committed
474 475 476 477
      case 'R':
        channel_model=Rayleigh1;
        break;

478
      default:
479
        printf("Unsupported channel model!\n");
480 481 482 483 484
        exit(-1);
      }

      break;

485
    case 'i':
486
      prb_inter=1;
487 488 489 490 491 492 493 494
      break;

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

    case 's':
      snr0 = atof(optarg);
495
      printf("Setting SNR0 to %f\n",snr0);
496 497 498 499 500
      break;

    case 'S':
      snr1 = atof(optarg);
      snr1set=1;
501
      printf("Setting SNR1 to %f\n",snr1);
502 503 504 505 506 507 508
      break;

      /*
      case 't':
      Td= atof(optarg);
      break;
      */
509
    /*case 'p':
510
      extended_prefix_flag=1;
511
      break;*/
512 513 514 515 516 517 518 519 520 521 522

      /*
      case 'r':
      ricean_factor = pow(10,-.1*atof(optarg));
      if (ricean_factor>1) {
        printf("Ricean factor must be between 0 and 1\n");
        exit(-1);
      }
      break;
      */
    case 'x':
523
      g_nrOfLayers=atoi(optarg);
524

525 526 527
      if ((g_nrOfLayers!=1) &&
          (g_nrOfLayers!=2)) {
        printf("Unsupported nr Of Layers %d\n",g_nrOfLayers);
528 529 530 531 532 533 534 535
        exit(-1);
      }

      break;

    case 'y':
      n_tx=atoi(optarg);

536
      if ((n_tx==0) || (n_tx>4)) {//extend gNB to support n_tx = 4
537
        printf("Unsupported number of tx antennas %d\n",n_tx);
538 539 540 541 542 543 544 545
        exit(-1);
      }

      break;

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

546
      if ((n_rx==0) || (n_rx>4)) {//extend UE to support n_tx = 4
547
        printf("Unsupported number of rx antennas %d\n",n_rx);
548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567
        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':
568 569
      print_perf=1;
      opp_enabled=1;
570 571 572 573
      break;
      
    case 'I':
      run_initial_sync=1;
574
      //target_error_rate=0.1;
575
      slot = 0;
576 577 578 579 580 581
      break;

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

582

583 584 585
    case 'E':
	css_flag=1;
	break;
586

587

588
    case 'a':
589
      g_rbStart = atoi(optarg);
590 591 592
      break;

    case 'b':
593
      g_rbSize = atoi(optarg);
594
      break;
595 596 597
    case 'd':
      dlsch_threads = atoi(optarg);
      break;    
598
    case 'e':
599
      g_mcsIndex = atoi(optarg);
600 601
      break;

602 603 604 605 606
    case 'q':
      g_mcsTableIdx = 1;
      get_softmodem_params()->use_256qam_table = 1;
      break;

607 608 609
    case 'm':
      mu = atoi(optarg);
      break;
610

611 612 613 614
    case 't':
      eff_tp_check = (float)atoi(optarg)/100;
      break;

615 616 617
    case 'w':
      output_fd = fopen("txdata.dat", "w+");
      break;
Sakthivel Velumani's avatar
Sakthivel Velumani committed
618

619 620 621 622 623 624 625
    case 'T':
      enable_ptrs=1;
      for(i=0; i < atoi(optarg); i++) {
        ptrs_arg[i] = atoi(argv[optind++]);
      }
      break;

626 627
    case 'U':
      modify_dmrs = 1;
628
      for(i=0; i < atoi(optarg); i++) {
629 630 631
        dmrs_arg[i] = atoi(argv[optind++]);
      }
      break;
Sakthivel Velumani's avatar
Sakthivel Velumani committed
632

633 634 635 636 637
    default:
    case 'h':
      printf("%s -h(elp) -p(extended_prefix) -N cell_id -f output_filename -F input_filename -g channel_model -n n_frames -t Delayspread -s snr0 -S snr1 -x transmission_mode -y TXant -z RXant -i Intefrence0 -j Interference1 -A interpolation_file -C(alibration offset dB) -N CellId\n",
             argv[0]);
      printf("-h This message\n");
638 639
      //printf("-p Use extended prefix mode\n");
      //printf("-d Use TDD\n");
640 641 642 643
      printf("-n Number of frames to simulate\n");
      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");
      printf("-t Delay spread for multipath channel\n");
sfn's avatar
sfn committed
644
      printf("-g [A,B,C,D,E,F,G,R] Use 3GPP SCM (A,B,C,D) or 36-101 (E-EPA,F-EVA,G-ETU) models or R for MIMO model (ignores delay spread and Ricean factor)\n");
645
      printf("-y Number of TX antennas used in gNB\n");
646
      printf("-z Number of RX antennas used in UE\n");
647
      printf("-i Activate PRB based averaging for channel estimation. Frequncy domain interpolation by default.\n");
648
      //printf("-j Relative strength of second intefering gNB (in dB) - cell_id mod 3 = 2\n");
649 650 651
      printf("-R N_RB_DL\n");
      printf("-O oversampling factor (1,2,4,8,16)\n");
      printf("-A Interpolation_filname Run with Abstraction to generate Scatter plot using interpolation polynomial in file\n");
652
      //printf("-C Generate Calibration information for Abstraction (effective SNR adjustment to remove Pe bias w.r.t. AWGN)\n");
653
      printf("-f raw file containing RRC configuration (generated by gNB)\n");
654
      printf("-F Input filename (.txt format) for RX conformance testing\n");
655
      printf("-E used CSS scheduler\n");
656
      printf("-o CORESET offset\n");
657 658
      printf("-a Start PRB for PDSCH\n");
      printf("-b Number of PRB for PDSCH\n");
659 660
      printf("-c Start symbol for PDSCH (fixed for now)\n");
      printf("-j Number of symbols for PDSCH (fixed for now)\n");
661
      printf("-e MSC index\n");
662
      printf("-q Use 2nd MCS table (256 QAM table) for PDSCH\n");
663
      printf("-t Acceptable effective throughput (in percentage)\n");
664
      printf("-T Enable PTRS, arguments list L_PTRS{0,1,2} K_PTRS{2,4}, e.g. -T 2 0 2 \n");
665
      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");
666
      printf("-P Print DLSCH performances\n");
Sakthivel Velumani's avatar
Sakthivel Velumani committed
667
      printf("-w Write txdata to binary file (one frame)\n");
668
      printf("-d number of dlsch threads, 0: no dlsch parallelization\n");
669 670 671 672
      exit (-1);
      break;
    }
  }
673

674 675 676
  logInit();
  set_glog(loglvl);
  T_stdout = 1;
677 678
  /* initialize the sin table */
  InitSinLUT();
679

680
  get_softmodem_params()->phy_test = 1;
681 682
  get_softmodem_params()->do_ra = 0;

683 684
  if (snr1set==0)
    snr1 = snr0+10;
685
  init_dlsch_tpool(dlsch_threads);
686 687


688 689 690
  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
691

692
  gNB = RC.gNB[0];
693
  gNB->ofdm_offset_divisor = UINT_MAX;
694 695 696 697 698 699
  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;

Raymond Knopp's avatar
Raymond Knopp committed
700
  RC.nb_nr_macrlc_inst = 1;
cig's avatar
cig committed
701 702 703
  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;
Raymond Knopp's avatar
Raymond Knopp committed
704 705 706
  mac_top_init_gNB();
  gNB_mac = RC.nrmac[0];
  gNB_RRC_INST rrc;
Raymond Knopp's avatar
Raymond Knopp committed
707
  memset((void*)&rrc,0,sizeof(rrc));
708

709
  /*
Raymond Knopp's avatar
Raymond Knopp committed
710
  // read in SCGroupConfig
Raymond Knopp's avatar
Raymond Knopp committed
711
  AssertFatal(scg_fd != NULL,"no reconfig.raw file\n");
Raymond Knopp's avatar
Raymond Knopp committed
712 713 714 715
  char buffer[1024];
  int msg_len=fread(buffer,1,1024,scg_fd);
  NR_RRCReconfiguration_t *NR_RRCReconfiguration;

Raymond Knopp's avatar
Raymond Knopp committed
716
  printf("Decoding NR_RRCReconfiguration (%d bytes)\n",msg_len);
Raymond Knopp's avatar
Raymond Knopp committed
717 718 719 720 721 722 723 724 725 726 727 728 729 730
  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);
  }      
  fclose(scg_fd);

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

Raymond Knopp's avatar
Raymond Knopp committed
733 734 735 736 737 738 739 740 741 742 743 744 745 746 747
  NR_RRCReconfiguration_IEs_t *reconfig_ies = NR_RRCReconfiguration->criticalExtensions.choice.rrcReconfiguration;
  NR_CellGroupConfig_t *secondaryCellGroup;
  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);
  }      
  
748 749
  NR_ServingCellConfigCommon_t *scc = secondaryCellGroup->spCellConfig->reconfigurationWithSync->spCellConfigCommon;
  */
Raymond Knopp's avatar
Raymond Knopp committed
750

751 752 753 754

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

  NR_ServingCellConfigCommon_t *scc = rrc.carrier.servingcellconfigcommon;
755
  NR_ServingCellConfig_t *scd = calloc(1,sizeof(NR_ServingCellConfig_t));
756 757
  NR_CellGroupConfig_t *secondaryCellGroup=calloc(1,sizeof(*secondaryCellGroup));
  prepare_scc(rrc.carrier.servingcellconfigcommon);
758
  uint64_t ssb_bitmap = 1;
759
  fill_scc(rrc.carrier.servingcellconfigcommon,&ssb_bitmap,N_RB_DL,N_RB_DL,mu,mu);
760
  ssb_bitmap = 1;// Enable only first SSB with index ssb_indx=0
Francesco Mani's avatar
Francesco Mani committed
761 762
  fix_scc(scc,ssb_bitmap);

763
  prepare_scd(scd);
764

765
  fill_default_secondaryCellGroup(scc, scd, secondaryCellGroup, 0, 1, n_tx, 0, 0, 0);
766

767 768
  /* RRC parameter validation for secondaryCellGroup */
  fix_scd(scd);
769
  /* -U option modify DMRS */
770
  if(modify_dmrs) {
771
    update_dmrs_config(secondaryCellGroup, dmrs_arg);
772
  }
773
  /* -T option enable PTRS */
774
  if(enable_ptrs) {
775
    update_ptrs_config(secondaryCellGroup, &rbSize, &mcsIndex, ptrs_arg);
776 777
  }

778

779
  //xer_fprint(stdout, &asn_DEF_NR_CellGroupConfig, (const void*)secondaryCellGroup);
Raymond Knopp's avatar
Raymond Knopp committed
780

Raymond Knopp's avatar
Raymond Knopp committed
781 782
  AssertFatal((gNB->if_inst         = NR_IF_Module_init(0))!=NULL,"Cannot register interface");
  gNB->if_inst->NR_PHY_config_req      = nr_phy_config_request;
Raymond Knopp's avatar
Raymond Knopp committed
783
  // common configuration
Eurecom's avatar
Eurecom committed
784
  rrc_mac_config_req_gNB(0,0, n_tx, n_tx, 0, scc, NULL, 0, 0, NULL);
Raymond Knopp's avatar
Raymond Knopp committed
785
  // UE dedicated configuration
Eurecom's avatar
Eurecom committed
786
  rrc_mac_config_req_gNB(0,0, n_tx, n_tx, 0, scc, NULL, 1, secondaryCellGroup->spCellConfig->reconfigurationWithSync->newUE_Identity,secondaryCellGroup);
787 788 789
  // reset preprocessor to the one of DLSIM after it has been set during
  // rrc_mac_config_req_gNB
  gNB_mac->pre_processor_dl = nr_dlsim_preprocessor;
790
  phy_init_nr_gNB(gNB,0,1);
791
  N_RB_DL = gNB->frame_parms.N_RB_DL;
792 793 794
  NR_UE_info_t *UE_info = &RC.nrmac[0]->UE_info;
  UE_info->num_UEs=1;

Raymond Knopp's avatar
Raymond Knopp committed
795
  // stub to configure frame_parms
Raymond Knopp's avatar
Raymond Knopp committed
796
  //  nr_phy_config_request_sim(gNB,N_RB_DL,N_RB_DL,mu,Nid_cell,SSB_positions);
Raymond Knopp's avatar
Raymond Knopp committed
797 798
  // call MAC to configure common parameters

799 800 801 802 803 804
  /* rrc_mac_config_req_gNB() has created one user, so set the scheduling
   * 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
805

806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823
  double fs,bw;

  if (mu == 1 && N_RB_DL == 217) { 
    fs = 122.88e6;
    bw = 80e6;
  }					       
  else if (mu == 1 && N_RB_DL == 245) {
    fs = 122.88e6;
    bw = 90e6;
  }
  else if (mu == 1 && N_RB_DL == 273) {
    fs = 122.88e6;
    bw = 100e6;
  }
  else if (mu == 1 && N_RB_DL == 106) { 
    fs = 61.44e6;
    bw = 40e6;
  }
824 825 826 827
  else if (mu == 3 && N_RB_DL == 66) {
    fs = 122.88e6;
    bw = 100e6;
  }
828 829 830 831
  else if (mu == 3 && N_RB_DL == 32) {
    fs = 61.44e6;
    bw = 50e6;
  }
832 833 834 835 836
  else AssertFatal(1==0,"Unsupported numerology for mu %d, N_RB %d\n",mu, N_RB_DL);

  gNB2UE = new_channel_desc_scm(n_tx,
                                n_rx,
                                channel_model,
837
                                fs/1e6,//sampling frequency in MHz
838
				bw,
839
				30e-9,
840 841
                                0,
                                0,
842
                                0, 0);
843 844

  if (gNB2UE==NULL) {
845
    printf("Problem generating channel model. Exiting.\n");
846 847 848 849
    exit(-1);
  }

  frame_length_complex_samples = frame_parms->samples_per_subframe*NR_NUMBER_OF_SUBFRAMES_PER_FRAME;
850
  //frame_length_complex_samples_no_prefix = frame_parms->samples_per_subframe_wCP*NR_NUMBER_OF_SUBFRAMES_PER_FRAME;
851

852 853 854 855 856
  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*));
857

858
  for (i=0; i<n_tx; i++) {
859 860 861 862 863
    s_re[i] = malloc(frame_length_complex_samples*sizeof(double));
    bzero(s_re[i],frame_length_complex_samples*sizeof(double));
    s_im[i] = malloc(frame_length_complex_samples*sizeof(double));
    bzero(s_im[i],frame_length_complex_samples*sizeof(double));

864 865 866 867 868 869
    printf("Allocating %d samples for txdata\n",frame_length_complex_samples);
    txdata[i] = malloc(frame_length_complex_samples*sizeof(int));
    bzero(txdata[i],frame_length_complex_samples*sizeof(int));
  }

  for (i=0; i<n_rx; i++) {
870 871 872 873 874 875 876 877 878 879 880 881 882
    r_re[i] = malloc(frame_length_complex_samples*sizeof(double));
    bzero(r_re[i],frame_length_complex_samples*sizeof(double));
    r_im[i] = malloc(frame_length_complex_samples*sizeof(double));
    bzero(r_im[i],frame_length_complex_samples*sizeof(double));
  }

  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
883
  memset((void*)UE,0,sizeof(PHY_VARS_NR_UE));
884 885 886 887
  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));
888
  UE->frame_parms.nb_antennas_rx = n_rx;
Raymond Knopp's avatar
Raymond Knopp committed
889

890
  if (run_initial_sync==1)  UE->is_synchronized = 0;
891
  else                      {UE->is_synchronized = 1; UE->UE_mode[0]=PUSCH;}
892 893 894 895 896 897 898 899 900
                      
  UE->perfect_ce = 0;

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

901 902
  init_nr_ue_transport(UE,0);

903
  nr_gold_pbch(UE);
francescomani's avatar
francescomani committed
904
  nr_gold_pdcch(UE,0);
905

906
  nr_l2_init_ue(NULL);
907
  UE_mac = get_mac_inst(0);
908

909 910 911
  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;
912
  UE->if_inst->dl_indication = nr_ue_dl_indication;
913
  UE->if_inst->ul_indication = dummy_nr_ue_ul_indication;
914
  UE->prb_interpolation = prb_inter;
915

916

917
  UE_mac->if_module = nr_ue_if_module_init(0);
918

919
  unsigned int available_bits=0;
Ahmed Hussein's avatar
Ahmed Hussein committed
920 921 922 923 924
  unsigned char *estimated_output_bit;
  unsigned char *test_input_bit;
  unsigned int errors_bit    = 0;
  uint32_t errors_scrambling = 0;

Sakthivel Velumani's avatar
Sakthivel Velumani committed
925
  initTpool("N", &(nrUE_params.Tpool), false);
926

Ahmed Hussein's avatar
Ahmed Hussein committed
927 928
  test_input_bit       = (unsigned char *) malloc16(sizeof(unsigned char) * 16 * 68 * 384);
  estimated_output_bit = (unsigned char *) malloc16(sizeof(unsigned char) * 16 * 68 * 384);
929 930
  
  // generate signal
931 932
  AssertFatal(input_fd==NULL,"Not ready for input signal file\n");
  gNB->pbch_configured = 1;
933 934
  gNB->ssb[0].ssb_pdu.ssb_pdu_rel15.bchPayload=0x001234;
  gNB->ssb[0].ssb_pdu.ssb_pdu_rel15.SsbBlockIndex = 0;
Raymond Knopp's avatar
Raymond Knopp committed
935

936
  //Configure UE
937 938
  rrc.carrier.MIB = (uint8_t*) malloc(4);
  rrc.carrier.sizeof_MIB = do_MIB_NR(&rrc,0);
939

rmagueta's avatar
rmagueta committed
940
  nr_rrc_mac_config_req_ue(0,0,0,rrc.carrier.mib.message.choice.mib, NULL, NULL, secondaryCellGroup);
941

942 943 944 945 946 947 948 949

  nr_dcireq_t dcireq;
  nr_scheduled_response_t scheduled_response;
  memset((void*)&dcireq,0,sizeof(dcireq));
  memset((void*)&scheduled_response,0,sizeof(scheduled_response));
  dcireq.module_id = 0;
  dcireq.gNB_index = 0;
  dcireq.cc_id     = 0;
950
  
951 952 953 954 955 956 957
  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;
  scheduled_response.CC_id     = 0;
  scheduled_response.frame = frame;
  scheduled_response.slot  = slot;
958
  scheduled_response.thread_id = 0;
Francesco Mani's avatar
Francesco Mani committed
959

960
  nr_ue_phy_config_request(&UE_mac->phy_config);
Francesco Mani's avatar
Francesco Mani committed
961
  //NR_COMMON_channels_t *cc = RC.nrmac[0]->common_channels;
962
  snrRun = 0;
963

964

Ahmed Hussein's avatar
Ahmed Hussein committed
965
  for (SNR = snr0; SNR < snr1; SNR += .2) {
966

967 968 969 970 971 972 973 974 975 976 977
    varArray_t *table_tx=initVarArray(1000,sizeof(double));
    reset_meas(&gNB->phy_proc_tx); // total gNB tx
    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);
978
    reset_meas(&gNB->toutput);
979

980 981
    clear_pdsch_stats(gNB);

982
    n_errors = 0;
983
    effRate = 0;
984 985
    //n_errors2 = 0;
    //n_alamouti = 0;
986
    errors_scrambling=0;
987
    n_false_positive = 0;
988 989
    if (n_trials== 1) num_rounds = 1;

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

992
      errors_bit = 0;
Ahmed Hussein's avatar
Ahmed Hussein committed
993
      //multipath channel
994
      //multipath_channel(gNB2UE,s_re,s_im,r_re,r_im,frame_length_complex_samples,0);
995

996
      UE->rx_offset=0;
997 998 999
      UE_proc.thread_id  = 0;
      UE_proc.frame_rx   = frame;
      UE_proc.nr_slot_rx = slot;
1000 1001 1002
      
      dcireq.frame     = frame;
      dcireq.slot      = slot;
1003

1004
      NR_UE_DLSCH_t *dlsch0 = UE->dlsch[UE_proc.thread_id][0][0];
1005

1006
      int harq_pid = slot;
1007 1008 1009
      NR_DL_UE_HARQ_t *UE_harq_process = dlsch0->harq_processes[harq_pid];

      NR_gNB_DLSCH_t *gNB_dlsch = gNB->dlsch[0][0];
1010
      nfapi_nr_dl_tti_pdsch_pdu_rel15_t *rel15 = &gNB_dlsch->harq_process.pdsch_pdu.pdsch_pdu_rel15;
1011
      
1012
      UE_harq_process->ack = 0;
1013
      round = 0;
1014
      UE_harq_process->round = round;
francescomani's avatar
fixes  
francescomani committed
1015
      UE_harq_process->first_rx = 1;
1016
        
1017
      while ((round<num_rounds) && (UE_harq_process->ack==0)) {
francescomani's avatar
fixes  
francescomani committed
1018

1019 1020
        memset(RC.nrmac[0]->cce_list[1][0],0,MAX_NUM_CCE*sizeof(int));
        memset(RC.nrmac[0]->cce_list[1][1],0,MAX_NUM_CCE*sizeof(int));
1021
        clear_nr_nfapi_information(RC.nrmac[0], 0, frame, slot);
1022

1023
        UE_info->UE_sched_ctrl[0].harq_processes[harq_pid].ndi = !(trial&1);
1024

1025

1026
        UE_info->UE_sched_ctrl[0].harq_processes[harq_pid].round = round;
Sakthivel Velumani's avatar
Sakthivel Velumani committed
1027
        for (int i=0; i<MAX_NUM_CORESET; i++)
1028
          gNB_mac->UE_info.num_pdcch_cand[0][i] = 0;
1029
      
1030
        if (css_flag == 0) {
1031
          nr_schedule_ue_spec(0, frame, slot);
1032 1033 1034
        } else {
          nr_schedule_css_dlsch_phytest(0,frame,slot);
        }
1035 1036 1037 1038 1039
        Sched_INFO.module_id = 0;
        Sched_INFO.CC_id     = 0;
        Sched_INFO.frame     = frame;
        Sched_INFO.slot      = slot;
        Sched_INFO.DL_req    = &gNB_mac->DL_req[0];
1040
        Sched_INFO.UL_tti_req    = gNB_mac->UL_tti_req_ahead[slot];
1041 1042 1043
        Sched_INFO.UL_dci_req  = NULL;
        Sched_INFO.TX_req    = &gNB_mac->TX_req[0];
        nr_schedule_response(&Sched_INFO);
1044 1045 1046 1047 1048 1049

        /* PTRS values for DLSIM calculations   */
        nfapi_nr_dl_tti_request_body_t *dl_req = &gNB_mac->DL_req[Sched_INFO.CC_id].dl_tti_request_body;
        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;
1050
        if(pdu_bit_map & 0x1) {
1051 1052 1053 1054 1055 1056 1057
          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);
1058
          printf("[DLSIM] PTRS Symbols in a slot: %2u, RE per Symbol: %3u, RE in a slot %4d\n", ptrsSymbPerSlot,ptrsRePerSymb, ptrsSymbPerSlot*ptrsRePerSymb );
1059
        }
1060
        if (run_initial_sync)
1061
          nr_common_signal_procedures(gNB,frame,slot,gNB->ssb[0].ssb_pdu);
1062
        else
1063
          phy_procedures_gNB_TX(gNB,frame,slot,1);
1064 1065 1066 1067
            
        int txdataF_offset = (slot%2) * frame_parms->samples_per_slot_wCP;
        
        if (n_trials==1) {
1068
          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);
1069
          if (gNB->frame_parms.nb_antennas_tx>1)
1070
            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);
1071 1072
        }
        int tx_offset = frame_parms->get_samples_slot_timestamp(slot,frame_parms,0);
1073
        if (n_trials==1) printf("tx_offset %d, txdataF_offset %d \n", tx_offset,txdataF_offset);
1074

1075 1076 1077
        //TODO: loop over slots
        for (aa=0; aa<gNB->frame_parms.nb_antennas_tx; aa++) {
    
1078 1079 1080 1081 1082 1083 1084
          if (cyclic_prefix_type == 1) {
            PHY_ofdm_mod(&gNB->common_vars.txdataF[aa][txdataF_offset],
                         &txdata[aa][tx_offset],
                         frame_parms->ofdm_symbol_size,
                         12,
                         frame_parms->nb_prefix_samples,
                         CYCLIC_PREFIX);
1085
          } else {
1086 1087 1088
            nr_normal_prefix_mod(&gNB->common_vars.txdataF[aa][txdataF_offset],
                                 &txdata[aa][tx_offset],
                                 14,
1089 1090
                                 frame_parms,
                                 slot);
1091
          }
1092 1093 1094
        }
       
        if (n_trials==1) {
1095 1096 1097 1098 1099
          char filename[100];//LOG_M
          for (aa=0;aa<n_tx;aa++) {
            sprintf(filename,"txsig%d.m", aa);//LOG_M
            LOG_M(filename,"txs", &txdata[aa][tx_offset+frame_parms->ofdm_symbol_size+frame_parms->nb_prefix_samples0],6*(frame_parms->ofdm_symbol_size+frame_parms->nb_prefix_samples),1,1);
          }
1100
        }
Sakthivel Velumani's avatar
Sakthivel Velumani committed
1101 1102
        if (output_fd) {
          printf("writing txdata to binary file\n");
1103
          fwrite(txdata[0],sizeof(int32_t),frame_length_complex_samples,output_fd);
Sakthivel Velumani's avatar
Sakthivel Velumani committed
1104
        }
1105

1106 1107 1108 1109 1110 1111 1112 1113 1114
        int txlev[n_tx];
        int txlev_sum = 0;
        int l_ofdm = 6;
        for (aa=0; aa<n_tx; aa++) {
          txlev[aa] = signal_energy(&txdata[aa][tx_offset+l_ofdm*frame_parms->ofdm_symbol_size + (l_ofdm-1)*frame_parms->nb_prefix_samples + frame_parms->nb_prefix_samples0],
          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);
        }
1115 1116
        
        for (i=(frame_parms->get_samples_slot_timestamp(slot,frame_parms,0)); 
1117 1118 1119 1120
             i<(frame_parms->get_samples_slot_timestamp(slot+1,frame_parms,0)); 
             i++) {
    
          for (aa=0; aa<frame_parms->nb_antennas_tx; aa++) {
1121 1122
            s_re[aa][i] = ((double)(((short *)txdata[aa]))[(i<<1)]);
            s_im[aa][i] = ((double)(((short *)txdata[aa]))[(i<<1)+1]);
1123
          }
1124
        }
1125

1126
        double ts = 1.0/(frame_parms->subcarrier_spacing * frame_parms->ofdm_symbol_size); 
1127
        //Compute AWGN variance
1128
        sigma2_dB = 10 * log10((double)txlev_sum * ((double)UE->frame_parms.ofdm_symbol_size/(12*rel15->rbSize))) - SNR;
1129
        sigma2    = pow(10, sigma2_dB/10);
1130
        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));
1131

1132 1133 1134 1135
        for (aa=0; aa<n_rx; aa++) {
          bzero(r_re[aa],frame_length_complex_samples*sizeof(double));
          bzero(r_im[aa],frame_length_complex_samples*sizeof(double));
        }
1136
        
1137 1138 1139 1140 1141 1142 1143 1144 1145
        // Apply MIMO Channel
        if (channel_model != AWGN) multipath_tv_channel(gNB2UE,
                             s_re,
                             s_im,
                             r_re,
                             r_im,
                             frame_length_complex_samples,
                             0);

1146 1147 1148 1149 1150
        double H_awgn_mimo[4][4] ={{1.0, 0.5, 0.25, 0.125},//rx 0
                                   {0.5, 1.0, 0.5, 0.25},  //rx 1
                                   {0.25, 0.5, 1.0, 0.5},  //rx 2
                                   {0.125, 0.25, 0.5, 1.0}};//rx 3

1151
        for (i=frame_parms->get_samples_slot_timestamp(slot,frame_parms,0); 
1152 1153 1154
             i<frame_parms->get_samples_slot_timestamp(slot+1,frame_parms,0);
             i++) {

1155
          for (int aa_rx=0; aa_rx<n_rx; aa_rx++) {
1156 1157 1158 1159 1160

            if (channel_model == AWGN) {
              // sum up signals from different Tx antennas
              r_re[aa_rx][i] = 0;
              r_im[aa_rx][i] = 0;
1161 1162 1163
             for (aa=0; aa<n_tx; aa++) {
                r_re[aa_rx][i] += s_re[aa][i]*H_awgn_mimo[aa_rx][aa];
                r_im[aa_rx][i] += s_im[aa][i]*H_awgn_mimo[aa_rx][aa];
1164
              }
1165
            }
1166
            // Add Gaussian noise
1167 1168
            ((short*) UE->common_vars.rxdata[aa_rx])[2*i]   = (short) ((r_re[aa_rx][i] + sqrt(sigma2/2)*gaussdouble(0.0,1.0)));
            ((short*) UE->common_vars.rxdata[aa_rx])[2*i+1] = (short) ((r_im[aa_rx][i] + sqrt(sigma2/2)*gaussdouble(0.0,1.0)));
1169
            /* Add phase noise if enabled */
1170
            if (pdu_bit_map & 0x1) {
1171 1172
              phase_noise(ts, &((short*) UE->common_vars.rxdata[aa_rx])[2*i],
                          &((short*) UE->common_vars.rxdata[aa_rx])[2*i+1]);
1173
            }
1174
          }
1175
        }
1176

1177 1178 1179 1180
        nr_ue_dcireq(&dcireq); //to be replaced with function pointer later
        nr_ue_scheduled_response(&scheduled_response);
        
        phy_procedures_nrUE_RX(UE,
1181 1182
                               &UE_proc,
                               0,
1183 1184
                               dlsch_threads,
                               NULL);
1185
        
1186
        //printf("dlsim round %d ends\n",round);
1187 1188
        round++;
      } // round
1189

1190 1191 1192
      //----------------------------------------------------------
      //---------------------- count errors ----------------------
      //----------------------------------------------------------
1193 1194 1195

      if (UE->dlsch[UE_proc.thread_id][0][0]->last_iteration_cnt >=
        UE->dlsch[UE_proc.thread_id][0][0]->max_ldpc_iterations+1)
1196
        n_errors++;
1197 1198

      NR_UE_PDSCH **pdsch_vars = UE->pdsch_vars[UE_proc.thread_id];
1199
      int16_t *UE_llr = pdsch_vars[0]->llr[0];
1200

1201
      TBS                  = UE_harq_process->TBS;//rel15->TBSize[0];
1202
      uint16_t length_dmrs = get_num_dmrs(rel15->dlDmrsSymbPos);
1203 1204 1205 1206
      uint16_t nb_rb       = rel15->rbSize;
      uint8_t  nb_re_dmrs  = rel15->dmrsConfigType == NFAPI_NR_DMRS_TYPE1 ? 6 : 4;
      uint8_t  mod_order   = rel15->qamModOrder[0];
      uint8_t  nb_symb_sch = rel15->NrOfSymbols;
1207

1208
      available_bits = nr_get_G(nb_rb, nb_symb_sch, nb_re_dmrs, length_dmrs, mod_order, rel15->nrOfLayers);
1209
      if(pdu_bit_map & 0x1) {
1210
        available_bits-= (ptrsSymbPerSlot * ptrsRePerSymb *rel15->nrOfLayers* 2);
1211
        printf("[DLSIM][PTRS] Available bits are: %5u, removed PTRS bits are: %5u \n",available_bits, (ptrsSymbPerSlot * ptrsRePerSymb *rel15->nrOfLayers* 2) );
1212
      }
1213

1214
      for (i = 0; i < available_bits; i++) {
1215 1216

	if(((gNB_dlsch->harq_process.f[i] == 0) && (UE_llr[i] <= 0)) ||
1217
	   ((gNB_dlsch->harq_process.f[i] == 1) && (UE_llr[i] >= 0)))
1218 1219 1220 1221
	  {
	    if(errors_scrambling == 0) {
	      LOG_D(PHY,"\n");
	      LOG_D(PHY,"First bit in error in unscrambling = %d\n",i);
Raymond Knopp's avatar
Raymond Knopp committed
1222
	    }
1223
	    errors_scrambling++;
Raymond Knopp's avatar
Raymond Knopp committed
1224
	  }
1225

1226 1227
      }
      for (i = 0; i < TBS; i++) {
1228

1229
	estimated_output_bit[i] = (UE_harq_process->b[i/8] & (1 << (i & 7))) >> (i & 7);
1230
	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
1231
	
1232 1233 1234 1235
	if (estimated_output_bit[i] != test_input_bit[i]) {
	  if(errors_bit == 0)
	    LOG_D(PHY,"First bit in error in decoding = %d (errors scrambling %d)\n",i,errors_scrambling);
	  errors_bit++;
Raymond Knopp's avatar
Raymond Knopp committed
1236 1237
	}
	
1238 1239 1240 1241 1242 1243
      }
      
      ////////////////////////////////////////////////////////////
      
      if (errors_scrambling > 0) {
	if (n_trials == 1)
1244
	  printf("errors_scrambling = %u/%u (trial %d)\n", errors_scrambling, available_bits,trial);
1245 1246 1247 1248 1249 1250 1251
      }
      
      if (errors_bit > 0) {
	n_false_positive++;
	if (n_trials == 1)
	  printf("errors_bit = %u (trial %d)\n", errors_bit, trial);
      }
1252
      roundStats[snrRun]+=((float)round); 
1253
      if (UE_harq_process->ack==1) effRate += ((float)TBS)/round;
Ahmed Hussein's avatar
Ahmed Hussein committed
1254
    } // noise trials
1255

1256
    blerStats[snrRun] = (float) n_errors / (float) n_trials;
1257
    roundStats[snrRun]/=((float)n_trials);
1258
    berStats[snrRun] = (double)errors_scrambling/available_bits/n_trials;
1259
    effRate /= n_trials;
Ahmed Hussein's avatar
Ahmed Hussein committed
1260 1261
    printf("*****************************************\n");
    printf("SNR %f, (false positive %f)\n", SNR,
Sakthivel Velumani's avatar
Sakthivel Velumani committed
1262
           (float) n_errors / (float) n_trials);
Ahmed Hussein's avatar
Ahmed Hussein committed
1263 1264
    printf("*****************************************\n");
    printf("\n");
Raymond Knopp's avatar
Raymond Knopp committed
1265
    dump_pdsch_stats(stdout,gNB);
1266
    printf("SNR %f : n_errors (negative CRC) = %d/%d, Avg round %.2f, Channel BER %e, BLER %.2f, Eff Rate %.4f bits/slot, Eff Throughput %.2f, TBS %u bits/slot\n", SNR, n_errors, n_trials,roundStats[snrRun],berStats[snrRun],blerStats[snrRun],effRate,effRate/TBS*100,TBS);
Ahmed Hussein's avatar
Ahmed Hussein committed
1267
    printf("\n");
1268

1269
    if (print_perf==1) {
1270
      printf("\ngNB TX function statistics (per %d us slot, NPRB %d, mcs %d, TBS %d, Kr %d (Zc %d))\n",
1271
	     1000>>*scc->ssbSubcarrierSpacing, g_rbSize, g_mcsIndex,
1272 1273 1274
	     gNB->dlsch[0][0]->harq_process.pdsch_pdu.pdsch_pdu_rel15.TBSize[0]<<3,
	     gNB->dlsch[0][0]->harq_process.K,
	     gNB->dlsch[0][0]->harq_process.K/((gNB->dlsch[0][0]->harq_process.pdsch_pdu.pdsch_pdu_rel15.TBSize[0]<<3)>3824?22:10));
1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302
      printDistribution(&gNB->phy_proc_tx,table_tx,"PHY proc tx");
      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");


      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",
1303 1304 1305
	     UE->dlsch[UE_proc.thread_id][0][0]->harq_processes[0]->Cminus ?
	     UE->dlsch[UE_proc.thread_id][0][0]->harq_processes[0]->Kminus :
	     UE->dlsch[UE_proc.thread_id][0][0]->harq_processes[0]->Kplus,
1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318
	     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");
      */
    }
1319 1320 1321 1322 1323 1324

    if (n_trials == 1) {
      
      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);
1325
      LOG_M("chestF0.m","chF0",&UE->pdsch_vars[0][0]->dl_ch_estimates_ext[0][0],g_rbSize*12*14,1,1);
1326
      write_output("rxF_comp.m","rxFc",&UE->pdsch_vars[0][0]->rxdataF_comp0[0][0],N_RB_DL*12*14,1,1);
1327
      LOG_M("rxF_llr.m","rxFllr",UE->pdsch_vars[UE_proc.thread_id][0]->llr[0],available_bits,1,0);
Eurecom's avatar
Eurecom committed
1328 1329
      LOG_M("pdcch_rxFcomp.m","pdcch_rxFcomp",&UE->pdcch_vars[0][0]->rxdataF_comp[0][0],96*12,1,1);
      LOG_M("pdcch_rxFllr.m","pdcch_rxFllr",UE->pdcch_vars[0][0]->llr,96*12,1,1);
1330 1331 1332
      break;
    }

1333
    if (effRate > (eff_tp_check*TBS)) {
1334 1335 1336 1337
      printf("PDSCH test OK\n");
      break;
    }

1338
    snrStats[snrRun] = SNR;
1339
    snrRun++;
1340 1341
  } // NSR

1342 1343 1344 1345
  LOG_M("dlsimStats.m","SNR",snrStats,snrRun,1,7);
  LOG_MM("dlsimStats.m","BLER",blerStats,snrRun,1,7);
  LOG_MM("dlsimStats.m","BER",berStats,snrRun,1,7);
  LOG_MM("dlsimStats.m","rounds",roundStats,snrRun,1,7);
1346
  /*if (n_trials>1) {
1347 1348 1349 1350 1351 1352
    printf("HARQ stats:\nSNR\tRounds\n");
    psnr = snr0;
    for (uint8_t i=0; i<snrRun; i++) {
      printf("%.1f\t%.2f\n",psnr,roundStats[i]);
      psnr+=0.2;
    }
1353
  }*/
1354

1355 1356
  free_channel_desc_scm(gNB2UE);

1357
  for (i = 0; i < n_tx; i++) {
1358 1359
    free(s_re[i]);
    free(s_im[i]);
1360 1361 1362
    free(txdata[i]);
  }
  for (i = 0; i < n_rx; i++) {
1363 1364 1365 1366 1367 1368 1369 1370 1371
    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
1372 1373 1374
  free(test_input_bit);
  free(estimated_output_bit);
  
1375 1376 1377 1378 1379 1380
  if (output_fd)
    fclose(output_fd);

  if (input_fd)
    fclose(input_fd);

1381 1382
  if (scg_fd)
    fclose(scg_fd);
1383
  return(n_errors);
Raymond Knopp's avatar
Raymond Knopp committed
1384
  
1385
}
1386 1387


1388
void update_ptrs_config(NR_CellGroupConfig_t *secondaryCellGroup, uint16_t *rbSize, uint8_t *mcsIndex, int8_t *ptrs_arg)
1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401
{
  NR_BWP_Downlink_t *bwp=secondaryCellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.array[0];
  int *ptrsFreqDenst = calloc(2, sizeof(long));
  ptrsFreqDenst[0]= 25;
  ptrsFreqDenst[1]= 115;
  int *ptrsTimeDenst = calloc(3, sizeof(long));
  ptrsTimeDenst[0]= 2;
  ptrsTimeDenst[1]= 4;
  ptrsTimeDenst[2]= 10;

  int epre_Ratio = 0;
  int reOffset = 0;

1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413
  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 {
1414 1415 1416
    printf("[DLSIM] Wrong L_PTRS value, using default values 1\n");
  }
  /* L = 4 if Imcs < MCS4 */
1417 1418 1419 1420 1421 1422 1423 1424 1425 1426
  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");
  }
1427
  printf("[DLSIM] PTRS Enabled with L %d, K %d \n", 1<<ptrs_arg[0], ptrs_arg[1] );
1428 1429 1430 1431
  /* overwrite the values */
  rrc_config_dl_ptrs_params(bwp, ptrsFreqDenst, ptrsTimeDenst, &epre_Ratio, &reOffset);
}

1432
void update_dmrs_config(NR_CellGroupConfig_t *scg, int8_t* dmrs_arg)
1433 1434 1435
{
  int8_t  mapping_type = typeA;//default value
  int8_t  add_pos = pdsch_dmrs_pos0;//default value
1436 1437
  int8_t  dmrs_config_type = NFAPI_NR_DMRS_TYPE1;//default value

1438
  if(dmrs_arg[0] == 0) {
1439 1440
    mapping_type = typeA;
  }
1441
  else if (dmrs_arg[0] == 1) {
1442
    mapping_type = typeB;
1443 1444
  } else {
    AssertFatal(1==0,"Incorrect Mappingtype, valid options 0-typeA, 1-typeB\n");
1445
  }
1446 1447 1448

  /* Additional DMRS positions 0 ,1 ,2 and 3 */
  if(dmrs_arg[1] >= 0 && dmrs_arg[1] <4 ) {
1449
    add_pos = dmrs_arg[1];
1450 1451
  } else {
    AssertFatal(1==0,"Incorrect Additional Position, valid options 0-pos1, 1-pos1, 2-pos2, 3-pos3\n");
1452
  }
1453

1454
  /* DMRS Conf Type 1 or 2 */
1455 1456 1457 1458
  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;
1459
  }
1460

1461
  NR_BWP_Downlink_t *bwp = scg->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.array[0];
1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479

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

1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495
  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");
  }
1496

1497 1498
  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;
1499 1500


1501 1502 1503 1504 1505
  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));
1506
    }
1507 1508 1509 1510
    *dmrs_config->dmrs_AdditionalPosition = add_pos;
  } else { // if NULL, Value pos2
    free(dmrs_config->dmrs_AdditionalPosition);
    dmrs_config->dmrs_AdditionalPosition = NULL;
1511
  }
1512

1513
  for (int i=0;i<bwp->bwp_Common->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list.count;i++) {
1514
    bwp->bwp_Common->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list.array[i]->mappingType = mapping_type;
1515
  }
1516

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