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

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

Laurent's avatar
Laurent committed
71 72
#include <openair2/LAYER2/MAC/mac_vars.h>
#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
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
86

87 88 89
PHY_VARS_gNB *gNB;
PHY_VARS_NR_UE *UE;
RAN_CONTEXT_t RC;
90 91
int32_t uplink_frequency_offset[MAX_NUM_CCs][4];

92
double cpuf;
93
char *uecap_file;
94

Laurent THOMAS's avatar
Laurent THOMAS committed
95 96
uint16_t sf_ahead=4 ;
uint16_t sl_ahead=0;
97
//uint8_t nfapi_mode = 0;
98
uint64_t downlink_frequency[MAX_NUM_CCs][4];
99 100
THREAD_STRUCT thread_struct;
nfapi_ue_release_request_body_t release_rntis;
101 102 103
//Fixme: Uniq dirty DU instance, by global var, datamodel need better management
instance_t DUuniqInstance=0;
instance_t CUuniqInstance=0;
104 105 106 107 108 109 110 111 112 113 114
teid_t newGtpuCreateTunnel(instance_t instance,
                           rnti_t rnti,
                           int incoming_bearer_id,
                           int outgoing_bearer_id,
                           teid_t outgoing_teid,
                           int qfi,
                           transport_layer_addr_t remoteAddr,
                           int port,
                           gtpCallback callBack,
                           gtpCallbackSDAP callBackSDAP) {
  return 0;
115
}
116

117 118 119 120
int newGtpuDeleteAllTunnels(instance_t instance, rnti_t rnti) {
  return 0;
}

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

124 125 126 127 128 129 130 131 132
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)
133 134 135 136
{
  return 0;
}

137 138 139 140 141
void nr_rrc_ue_generate_RRCSetupRequest(module_id_t module_id, const uint8_t gNB_index)
{
  return;
}

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

152 153
void
rrc_data_ind(
154
  const protocol_ctxt_t *const ctxt_pP,
155 156 157 158 159 160 161 162 163 164 165 166 167 168 169
  const rb_id_t                Srb_id,
  const sdu_size_t             sdu_sizeP,
  const uint8_t   *const       buffer_pP
)
{
}

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;
}
170

171 172 173 174 175 176 177 178
int
rrc_gNB_process_GTPV1U_CREATE_TUNNEL_RESP(
  const protocol_ctxt_t *const ctxt_pP,
  const gtpv1u_enb_create_tunnel_resp_t *const create_tunnel_resp_pP,
  uint8_t                         *inde_list
) {
  return 0;
}
179

heshanyun's avatar
heshanyun committed
180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196
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;
}

Laurent THOMAS's avatar
Laurent THOMAS committed
197 198 199 200 201 202
int gtpv1u_delete_s1u_tunnel(const instance_t instance, const gtpv1u_enb_delete_tunnel_req_t *const req_pP) {
  return 0;
}

int gtpv1u_delete_ngu_tunnel( const instance_t instance,
			      gtpv1u_gnb_delete_tunnel_req_t *req) {
rmagueta's avatar
rmagueta committed
203 204 205
  return 0;
}

heshanyun's avatar
heshanyun committed
206 207 208 209 210 211 212 213 214
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;
}

215 216 217 218 219 220
int nr_derive_key(int alg_type, uint8_t alg_id,
               const uint8_t key[32], uint8_t **out)
{
  return 0;
}

221
void config_common(int Mod_idP,
222
                   int pdsch_AntennaPorts,
223
                   int pusch_AntennaPorts,
francescomani's avatar
francescomani committed
224
                   NR_ServingCellConfigCommon_t *scc);
225

226 227 228 229 230 231 232 233 234
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;}
235

236
// Dummy function to avoid linking error at compilation of nr-dlsim
237 238 239 240 241
int is_x2ap_enabled(void)
{
  return 0;
}

rmagueta's avatar
rmagueta committed
242 243 244 245 246 247 248 249 250 251 252
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;
}

253 254
void processSlotTX(void *arg) {}

Robert Schmidt's avatar
Robert Schmidt committed
255 256
nr_bler_struct nr_bler_data[NR_NUM_MCS];

Mahesh's avatar
Mahesh committed
257
//nFAPI P7 dummy functions to avoid linking errors 
Mahesh's avatar
Mahesh committed
258 259 260 261 262

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
263 264 265 266 267
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
268

269
// needed for some functions
270
openair0_config_t openair0_cfg[MAX_CARDS];
271
void update_ptrs_config(NR_CellGroupConfig_t *secondaryCellGroup, uint16_t *rbSize, uint8_t *mcsIndex,int8_t *ptrs_arg);
272
void update_dmrs_config(NR_CellGroupConfig_t *scg, int8_t* dmrs_arg);
rmagueta's avatar
rmagueta committed
273
extern void fix_scd(NR_ServingCellConfig_t *scd);// forward declaration
274

275
/* specific dlsim DL preprocessor: uses rbStart/rbSize/mcs/nrOfLayers from command line of dlsim */
276
int g_mcsIndex = -1, g_mcsTableIdx = 0, g_rbStart = -1, g_rbSize = -1, g_nrOfLayers = 1;
277 278
void nr_dlsim_preprocessor(module_id_t module_id,
                           frame_t frame,
279
                           sub_frame_t slot) {
280

Laurent THOMAS's avatar
Laurent THOMAS committed
281 282 283
  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
284
  NR_UE_DL_BWP_t *current_BWP = &UE_info->current_DL_BWP;
rmagueta's avatar
rmagueta committed
285
  NR_ServingCellConfigCommon_t *scc = RC.nrmac[0]->common_channels[0].ServingCellConfigCommon;
286

287 288 289 290 291 292 293
  //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;
294

295
  uint8_t nr_of_candidates = 0;
296 297 298 299 300 301 302 303 304 305
  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
306
  uint32_t Y = get_Y(sched_ctrl->search_space, slot, UE_info->rnti);
307 308 309 310 311 312 313
  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
314
  AssertFatal(CCEIndex>=0, "%4d.%2d could not find CCE for DL DCI UE %d/RNTI %04x\n", frame, slot, 0, UE_info->rnti);
315
  sched_ctrl->cce_index = CCEIndex;
316

317 318 319 320
  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
321
  sched_pdsch->nrOfLayers = g_nrOfLayers;
322 323
  /* the following might override the table that is mandated by RRC
   * configuration */
francescomani's avatar
francescomani committed
324
  current_BWP->mcsTableIdx = g_mcsTableIdx;
325

francescomani's avatar
francescomani committed
326 327 328 329 330 331 332 333 334 335 336
  sched_pdsch->time_domain_allocation = get_dl_tda(RC.nrmac[module_id], scc, slot);
  AssertFatal(sched_pdsch->time_domain_allocation>=0,"Unable to find PDSCH time domain allocation in list\n");
  NR_pdsch_tda_info_t *tda_info = &sched_pdsch->tda_info;
  nr_get_pdsch_tda_info(current_BWP, sched_pdsch->time_domain_allocation, tda_info);

  set_dl_dmrs_params(&sched_pdsch->dmrs_parms,
                     scc,
                     current_BWP,
                     tda_info,
                     sched_pdsch->nrOfLayers);

francescomani's avatar
francescomani committed
337 338
  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);
339 340 341
  sched_pdsch->tb_size = nr_compute_tbs(sched_pdsch->Qm,
                                        sched_pdsch->R,
                                        sched_pdsch->rbSize,
francescomani's avatar
francescomani committed
342 343
                                        tda_info->nrOfSymbols,
                                        sched_pdsch->dmrs_parms.N_PRB_DMRS * sched_pdsch->dmrs_parms.N_DMRS_SLOT,
344 345
                                        0 /* N_PRB_oh, 0 for initialBWP */,
                                        0 /* tb_scaling */,
francescomani's avatar
francescomani committed
346
                                        sched_pdsch->nrOfLayers) >> 3;
347

348
  /* the simulator assumes the HARQ PID is equal to the slot number */
349 350
  sched_pdsch->dl_harq_pid = slot;

351 352 353 354 355 356 357 358 359 360 361 362
  /* 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;
363 364 365
  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
366
  AssertFatal(current_BWP->mcsTableIdx >= 0 && current_BWP->mcsTableIdx <= 2, "invalid mcsTableIdx %d\n", current_BWP->mcsTableIdx);
367
}
368

Sakthivel Velumani's avatar
Sakthivel Velumani committed
369 370 371 372 373
nrUE_params_t nrUE_params;

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

Sakthivel Velumani's avatar
Sakthivel Velumani committed
375 376
void do_nothing(void *args) {
}
377

378 379 380
int main(int argc, char **argv)
{
  char c;
381
  int i,aa;//,l;
382
  double sigma2, sigma2_dB=10, SNR, snr0=-2.0, snr1=2.0;
383
  uint8_t snr1set=0;
384 385 386 387 388 389 390
  uint32_t errors_scrambling[4][100] = {{0}};
  int      n_errors[4][100]          = {{0}};
  int      round_trials[4][100]      = {{0}};
  double   roundStats[100]           = {0};
  double   blerStats[4][100]         = {{0}};
  double   berStats[4][100]          = {{0}};
  double   snrStats[100]             = {0};
391
  float effRate;
Francesco Mani's avatar
Francesco Mani committed
392
  //float psnr;
393
  float eff_tp_check = 0.7;
394
  uint8_t snrRun;
395
  uint32_t TBS = 0;
396 397
  int **txdata;
  double **s_re,**s_im,**r_re,**r_im;
398 399
  //double iqim = 0.0;
  //unsigned char pbch_pdu[6];
400 401 402
  //  int sync_pos, sync_pos_slot;
  //  FILE *rx_frame_file;
  FILE *output_fd = NULL;
403
  //uint8_t write_output_file=0;
404
  //int result;
405
  //int freq_offset;
406
  //  int subframe_offset;
407
  //  char fname[40], vname[40];
408
  int trial, n_trials = 1, n_false_positive = 0;
409
  //int n_errors2, n_alamouti;
410
  uint8_t n_tx=1,n_rx=1;
411 412
  uint8_t round;
  uint8_t num_rounds = 4;
413
  char gNBthreads[128]="n";
414 415

  channel_desc_t *gNB2UE;
416 417 418
  //uint32_t nsymb,tx_lev,tx_lev1 = 0,tx_lev2 = 0;
  //uint8_t extended_prefix_flag=0;
  //int8_t interf1=-21,interf2=-21;
419 420

  FILE *input_fd=NULL,*pbch_file_fd=NULL;
421
  //char input_val_str[50],input_val_str2[50];
422

423
  //uint8_t frame_mod4,num_pdcch_symbols = 0;
424

425
  SCM_t channel_model = AWGN; // AWGN Rayleigh1 Rayleigh1_anticorr;
426

Laurent's avatar
Laurent committed
427
  NB_UE_INST = 1;
428 429
  //double pbch_sinr;
  //int pbch_tx_ant;
Ahmed Hussein's avatar
Ahmed Hussein committed
430
  int N_RB_DL=106,mu=1;
431

432
  //unsigned char frame_type = 0;
433

434
  int frame=1,slot=1;
435
  int frame_length_complex_samples;
436
  //int frame_length_complex_samples_no_prefix;
437 438 439 440 441
  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;
442
  int cyclic_prefix_type = NFAPI_CP_NORMAL;
443
  int run_initial_sync=0;
444
  int loglvl=OAILOG_WARNING;
445

446
  //float target_error_rate = 0.01;
447
  int css_flag=0;
448 449

  cpuf = get_cpu_freq_GHz();
450 451 452
  int8_t enable_ptrs = 0;
  int8_t modify_dmrs = 0;

453
  int8_t dmrs_arg[3] = {-1,-1,-1};// Invalid values
454
  /* L_PTRS = ptrs_arg[0], K_PTRS = ptrs_arg[1] */
455 456
  int8_t ptrs_arg[2] = {-1,-1};// Invalid values

457 458 459 460 461 462
  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;
463
  uint8_t  dlsch_threads = 0;
464
  int      chest_type[2] = {0};
465
  uint8_t  max_ldpc_iterations = 5;
466
  if ( load_configmodule(argc,argv,CONFIG_ENABLECMDLINEONLY) == 0) {
yilmazt's avatar
yilmazt committed
467
    exit_fun("[NR_DLSIM] Error, configuration module init failed\n");
468 469 470 471
  }

  randominit(0);

472
  int print_perf             = 0;
473

474 475
  FILE *scg_fd=NULL;
  
476
  while ((c = getopt (argc, argv, "f:hA:pf:g:i:n:s:S:t:x:y:z:M:N:F:GR:d:PI:L:Ea:b:e:m:w:T:U:q:X:Y")) != -1) {
477
    switch (c) {
478 479
    case 'f':
      scg_fd = fopen(optarg,"r");
480

481
      if (scg_fd==NULL) {
482 483 484
        printf("Error opening %s\n",optarg);
        exit(-1);
      }
485
      break;
486

487
    /*case 'd':
488
      frame_type = 1;
489
      break;*/
490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520

    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
521 522 523 524
      case 'R':
        channel_model=Rayleigh1;
        break;

525
      default:
526
        printf("Unsupported channel model!\n");
527 528 529 530 531
        exit(-1);
      }

      break;

532
    case 'i':
533 534 535
      for(i=0; i < atoi(optarg); i++){
        chest_type[i] = atoi(argv[optind++]);
      }
536 537 538 539 540 541 542 543
      break;

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

    case 's':
      snr0 = atof(optarg);
544
      printf("Setting SNR0 to %f\n",snr0);
545 546 547 548 549
      break;

    case 'S':
      snr1 = atof(optarg);
      snr1set=1;
550
      printf("Setting SNR1 to %f\n",snr1);
551 552 553 554 555 556 557
      break;

      /*
      case 't':
      Td= atof(optarg);
      break;
      */
558
    /*case 'p':
559
      extended_prefix_flag=1;
560
      break;*/
561 562 563 564 565 566 567 568 569 570 571

      /*
      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':
572
      g_nrOfLayers=atoi(optarg);
573

574 575
      if ((g_nrOfLayers==0) ||
          (g_nrOfLayers>4)) {
576
        printf("Unsupported nr Of Layers %d\n",g_nrOfLayers);
577 578 579 580 581 582 583 584
        exit(-1);
      }

      break;

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

585
      if ((n_tx==0) || (n_tx>4)) {//extend gNB to support n_tx = 4
586
        printf("Unsupported number of tx antennas %d\n",n_tx);
587 588 589 590 591 592 593 594
        exit(-1);
      }

      break;

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

595
      if ((n_rx==0) || (n_rx>4)) {//extend UE to support n_tx = 4
596
        printf("Unsupported number of rx antennas %d\n",n_rx);
597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616
        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':
617 618
      print_perf=1;
      opp_enabled=1;
619 620 621
      break;
      
    case 'I':
622
      max_ldpc_iterations = atoi(optarg);
623 624 625 626 627 628
      break;

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

629

630 631 632
    case 'E':
	css_flag=1;
	break;
633

634

635
    case 'a':
636
      g_rbStart = atoi(optarg);
637 638 639
      break;

    case 'b':
640
      g_rbSize = atoi(optarg);
641
      break;
642

643
    case 'd':
644
      dlsch_threads = atoi(optarg);
645 646
      break;

647
    case 'e':
648
      g_mcsIndex = atoi(optarg);
649 650
      break;

651
    case 'q':
652
      g_mcsTableIdx = atoi(optarg);
653 654
      break;

655 656 657
    case 'm':
      mu = atoi(optarg);
      break;
658

659 660 661 662
    case 't':
      eff_tp_check = (float)atoi(optarg)/100;
      break;

663 664 665
    case 'w':
      output_fd = fopen("txdata.dat", "w+");
      break;
Sakthivel Velumani's avatar
Sakthivel Velumani committed
666

667 668 669 670 671 672 673
    case 'T':
      enable_ptrs=1;
      for(i=0; i < atoi(optarg); i++) {
        ptrs_arg[i] = atoi(argv[optind++]);
      }
      break;

674 675
    case 'U':
      modify_dmrs = 1;
676
      for(i=0; i < atoi(optarg); i++) {
677 678 679
        dmrs_arg[i] = atoi(argv[optind++]);
      }
      break;
Sakthivel Velumani's avatar
Sakthivel Velumani committed
680

681
    case 'X':
682
      strncpy(gNBthreads, optarg, sizeof(gNBthreads)-1);
683 684
      gNBthreads[sizeof(gNBthreads)-1]=0;
      break;
685

686 687 688 689 690
    case 'Y':
      run_initial_sync=1;
      //target_error_rate=0.1;
      slot = 0;
      break;
691

692 693
    default:
    case 'h':
694
      printf("%s -h(elp) -p(extended_prefix) -N cell_id -f output_filename -F input_filename -g channel_model -n n_frames -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",
695 696
             argv[0]);
      printf("-h This message\n");
francescomani's avatar
francescomani committed
697
      printf("-L <log level, 0(errors), 1(warning), 2(analysis), 3(info), 4(debug), 5(trace)>\n");
698 699
      //printf("-p Use extended prefix mode\n");
      //printf("-d Use TDD\n");
700 701 702
      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");
703
      //printf("-t Delay spread for multipath channel\n");
sfn's avatar
sfn committed
704
      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");
705
      printf("-y Number of TX antennas used in gNB\n");
706
      printf("-z Number of RX antennas used in UE\n");
707
      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");
708
      //printf("-j Relative strength of second intefering gNB (in dB) - cell_id mod 3 = 2\n");
709 710 711
      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");
712
      //printf("-C Generate Calibration information for Abstraction (effective SNR adjustment to remove Pe bias w.r.t. AWGN)\n");
713
      printf("-f raw file containing RRC configuration (generated by gNB)\n");
714
      printf("-F Input filename (.txt format) for RX conformance testing\n");
715
      printf("-E used CSS scheduler\n");
716
      printf("-o CORESET offset\n");
717 718
      printf("-a Start PRB for PDSCH\n");
      printf("-b Number of PRB for PDSCH\n");
719 720
      printf("-c Start symbol for PDSCH (fixed for now)\n");
      printf("-j Number of symbols for PDSCH (fixed for now)\n");
721
      printf("-e MSC index\n");
722
      printf("-q MCS Table index\n");
723
      printf("-t Acceptable effective throughput (in percentage)\n");
724
      printf("-I Maximum LDPC decoder iterations\n");
725
      printf("-T Enable PTRS, arguments list L_PTRS{0,1,2} K_PTRS{2,4}, e.g. -T 2 0 2 \n");
726
      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");
727
      printf("-P Print DLSCH performances\n");
Sakthivel Velumani's avatar
Sakthivel Velumani committed
728
      printf("-w Write txdata to binary file (one frame)\n");
729
      printf("-d number of dlsch threads, 0: no dlsch parallelization\n");
730 731
      printf("-X gNB thread pool configuration, n => no threads\n");
      printf("-Y Run initial sync in UE\n");
732 733 734 735
      exit (-1);
      break;
    }
  }
736

737 738 739
  logInit();
  set_glog(loglvl);
  T_stdout = 1;
740 741
  /* initialize the sin table */
  InitSinLUT();
742

743
  get_softmodem_params()->phy_test = 1;
744
  get_softmodem_params()->do_ra = 0;
745
  set_softmodem_optmask(SOFTMODEM_DLSIM_BIT);
746

747 748 749
  if (snr1set==0)
    snr1 = snr0+10;

750 751 752
  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
753

754
  gNB = RC.gNB[0];
755
  gNB->ofdm_offset_divisor = UINT_MAX;
756 757 758 759 760 761
  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
762
  RC.nb_nr_macrlc_inst = 1;
cig's avatar
cig committed
763 764 765
  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;
766
  mac_top_init_gNB(ngran_gNB);
Raymond Knopp's avatar
Raymond Knopp committed
767 768
  gNB_mac = RC.nrmac[0];
  gNB_RRC_INST rrc;
Raymond Knopp's avatar
Raymond Knopp committed
769
  memset((void*)&rrc,0,sizeof(rrc));
770

771 772
  gNB_mac->dl_bler.harq_round_max = num_rounds;

773
  /*
Raymond Knopp's avatar
Raymond Knopp committed
774
  // read in SCGroupConfig
Raymond Knopp's avatar
Raymond Knopp committed
775
  AssertFatal(scg_fd != NULL,"no reconfig.raw file\n");
Raymond Knopp's avatar
Raymond Knopp committed
776 777 778 779
  char buffer[1024];
  int msg_len=fread(buffer,1,1024,scg_fd);
  NR_RRCReconfiguration_t *NR_RRCReconfiguration;

Raymond Knopp's avatar
Raymond Knopp committed
780
  printf("Decoding NR_RRCReconfiguration (%d bytes)\n",msg_len);
Raymond Knopp's avatar
Raymond Knopp committed
781 782 783 784 785 786 787 788 789 790 791 792 793 794
  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
795 796
  AssertFatal(NR_RRCReconfiguration->criticalExtensions.present == NR_RRCReconfiguration__criticalExtensions_PR_rrcReconfiguration,"wrong NR_RRCReconfiguration->criticalExstions.present type\n");

Raymond Knopp's avatar
Raymond Knopp committed
797 798 799 800 801 802 803 804 805 806 807 808 809 810 811
  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);
  }      
  
812 813
  NR_ServingCellConfigCommon_t *scc = secondaryCellGroup->spCellConfig->reconfigurationWithSync->spCellConfigCommon;
  */
Raymond Knopp's avatar
Raymond Knopp committed
814

815 816 817 818

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

  NR_ServingCellConfigCommon_t *scc = rrc.carrier.servingcellconfigcommon;
819
  NR_ServingCellConfig_t *scd = calloc(1,sizeof(NR_ServingCellConfig_t));
820 821
  NR_CellGroupConfig_t *secondaryCellGroup=calloc(1,sizeof(*secondaryCellGroup));
  prepare_scc(rrc.carrier.servingcellconfigcommon);
822
  uint64_t ssb_bitmap = 1;
823
  fill_scc_sim(rrc.carrier.servingcellconfigcommon,&ssb_bitmap,N_RB_DL,N_RB_DL,mu,mu);
824
  ssb_bitmap = 1;// Enable only first SSB with index ssb_indx=0
Francesco Mani's avatar
Francesco Mani committed
825
  fix_scc(scc,ssb_bitmap);
826
  prepare_scd(scd);
827

828
  rrc_pdsch_AntennaPorts_t pdsch_AntennaPorts;
829
  pdsch_AntennaPorts.N1 = n_tx>1 ? n_tx>>1 : 1;
830
  pdsch_AntennaPorts.N2 = 1;
831
  pdsch_AntennaPorts.XP = n_tx>1 ? 2 : 1;
francescomani's avatar
francescomani committed
832 833 834
  gNB->ap_N1 = pdsch_AntennaPorts.N1;
  gNB->ap_N2 = pdsch_AntennaPorts.N2;
  gNB->ap_XP = pdsch_AntennaPorts.XP;
835

836 837 838
  NR_UE_NR_Capability_t* UE_Capability_nr = CALLOC(1,sizeof(NR_UE_NR_Capability_t));
  prepare_sim_uecap(UE_Capability_nr,scc,mu,
                    N_RB_DL,g_mcsTableIdx);
839

840
  // TODO do a UECAP for phy-sim
841
  const gNB_RrcConfigurationReq conf = {
842
    .pdsch_AntennaPorts = pdsch_AntennaPorts,
843 844 845 846 847 848
    .minRXTXTIME = 6,
    .do_CSIRS = 0,
    .do_SRS = 0,
    .force_256qam_off = false
  };
  fill_default_secondaryCellGroup(scc, scd, secondaryCellGroup, UE_Capability_nr, 0, 1, &conf, 0);
849

850 851
  /* RRC parameter validation for secondaryCellGroup */
  fix_scd(scd);
852
  /* -U option modify DMRS */
853
  if(modify_dmrs) {
854
    update_dmrs_config(secondaryCellGroup, dmrs_arg);
855
  }
856
  /* -T option enable PTRS */
857
  if(enable_ptrs) {
858
    update_ptrs_config(secondaryCellGroup, &rbSize, &mcsIndex, ptrs_arg);
859 860
  }

861

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

Raymond Knopp's avatar
Raymond Knopp committed
864 865
  AssertFatal((gNB->if_inst         = NR_IF_Module_init(0))!=NULL,"Cannot register interface");
  gNB->if_inst->NR_PHY_config_req      = nr_phy_config_request;
866

Raymond Knopp's avatar
Raymond Knopp committed
867
  // common configuration
868
  rrc_mac_config_req_gNB(0, pdsch_AntennaPorts, n_tx, 0, 6, scc, NULL, NULL, 0, 0, NULL);
Raymond Knopp's avatar
Raymond Knopp committed
869
  // UE dedicated configuration
870
  rrc_mac_config_req_gNB(0, pdsch_AntennaPorts, n_tx, 0, 6, scc, NULL, NULL, 1, secondaryCellGroup->spCellConfig->reconfigurationWithSync->newUE_Identity,secondaryCellGroup);
871 872 873
  // 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;
874
  phy_init_nr_gNB(gNB,0,1);
875
  N_RB_DL = gNB->frame_parms.N_RB_DL;
Laurent THOMAS's avatar
Laurent THOMAS committed
876
  NR_UE_info_t *UE_info = RC.nrmac[0]->UE_info.list[0];
877

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

Raymond Knopp's avatar
Raymond Knopp committed
880
  // stub to configure frame_parms
Raymond Knopp's avatar
Raymond Knopp committed
881
  //  nr_phy_config_request_sim(gNB,N_RB_DL,N_RB_DL,mu,Nid_cell,SSB_positions);
Raymond Knopp's avatar
Raymond Knopp committed
882 883
  // call MAC to configure common parameters

884 885 886 887 888 889
  /* 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
890

891 892
  double fs,txbw,rxbw;
  uint32_t samples;
893

894 895 896 897 898 899 900
  get_samplerate_and_bw(mu,
                        N_RB_DL,
                        frame_parms->threequarter_fs,
                        &fs,
                        &samples,
                        &txbw,
                        &rxbw);
901 902 903 904

  gNB2UE = new_channel_desc_scm(n_tx,
                                n_rx,
                                channel_model,
905
                                fs/1e6,//sampling frequency in MHz
906
				txbw,
907
				30e-9,
908 909
                                0,
                                0,
910
                                0, 0);
911 912

  if (gNB2UE==NULL) {
913
    printf("Problem generating channel model. Exiting.\n");
914 915 916 917
    exit(-1);
  }

  frame_length_complex_samples = frame_parms->samples_per_subframe*NR_NUMBER_OF_SUBFRAMES_PER_FRAME;
918
  //frame_length_complex_samples_no_prefix = frame_parms->samples_per_subframe_wCP*NR_NUMBER_OF_SUBFRAMES_PER_FRAME;
919

920 921 922 923 924
  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*));
925

926
  for (i=0; i<n_tx; i++) {
927 928 929 930 931
    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));

932 933 934 935 936 937
    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++) {
938 939 940 941 942 943 944 945 946 947 948 949 950
    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
951
  memset((void*)UE,0,sizeof(PHY_VARS_NR_UE));
952 953 954 955
  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));
956
  UE->frame_parms.nb_antennas_rx = n_rx;
957
  UE->max_ldpc_iterations = max_ldpc_iterations;
Raymond Knopp's avatar
Raymond Knopp committed
958

959
  if (run_initial_sync==1)  UE->is_synchronized = 0;
960
  else                      {UE->is_synchronized = 1; UE->UE_mode[0]=PUSCH;}
961

962
  if (init_nr_ue_signal(UE, 1) != 0)
963 964 965 966 967
  {
    printf("Error at UE NR initialisation\n");
    exit(-1);
  }

968
  init_nr_ue_transport(UE);
969

970
  nr_gold_pbch(UE);
971 972 973 974 975 976

  // 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
977 978 979 980
  for (int i = 0; i < 2; i++) {
    UE->scramblingID_dlsch[i] = frame_parms->Nid_cell;
    nr_gold_pdsch(UE, i, UE->scramblingID_dlsch[i]);
  }
981

982
  nr_l2_init_ue(NULL);
983
  UE_mac = get_mac_inst(0);
984

985 986 987
  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;
988
  UE->if_inst->dl_indication = nr_ue_dl_indication;
989
  UE->if_inst->ul_indication = dummy_nr_ue_ul_indication;
990 991
  UE->chest_freq = chest_type[0];
  UE->chest_time = chest_type[1];
992

993
  UE_mac->if_module = nr_ue_if_module_init(0);
994

995
  unsigned int available_bits=0;
Ahmed Hussein's avatar
Ahmed Hussein committed
996 997 998 999
  unsigned char *estimated_output_bit;
  unsigned char *test_input_bit;
  unsigned int errors_bit    = 0;

1000
  initFloatingCoresTpool(dlsch_threads, &nrUE_params.Tpool, false, "UE-tpool");
1001

Ahmed Hussein's avatar
Ahmed Hussein committed
1002 1003
  test_input_bit       = (unsigned char *) malloc16(sizeof(unsigned char) * 16 * 68 * 384);
  estimated_output_bit = (unsigned char *) malloc16(sizeof(unsigned char) * 16 * 68 * 384);
1004 1005
  
  // generate signal
1006 1007
  AssertFatal(input_fd==NULL,"Not ready for input signal file\n");
  gNB->pbch_configured = 1;
Raymond Knopp's avatar
Raymond Knopp committed
1008

1009
  //Configure UE
1010 1011
  rrc.carrier.MIB = (uint8_t*) malloc(4);
  rrc.carrier.sizeof_MIB = do_MIB_NR(&rrc,0);
1012

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

1015 1016 1017

  nr_dcireq_t dcireq;
  nr_scheduled_response_t scheduled_response;
1018 1019
  NR_UE_PDCCH_CONFIG phy_pdcch_config={0};

1020 1021 1022 1023 1024
  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;
1025
  
1026 1027 1028 1029 1030 1031 1032
  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;
1033
  scheduled_response.thread_id = 0;
1034
  scheduled_response.phy_data = &phy_pdcch_config;
Francesco Mani's avatar
Francesco Mani committed
1035

1036
  nr_ue_phy_config_request(&UE_mac->phy_config);
Francesco Mani's avatar
Francesco Mani committed
1037
  //NR_COMMON_channels_t *cc = RC.nrmac[0]->common_channels;
1038
  snrRun = 0;
1039
  int n_errs = 0;
1040

1041
  initNamedTpool(gNBthreads, &gNB->threadPool, true, "gNB-tpool");
1042 1043 1044
  initNotifiedFIFO(&gNB->L1_tx_free);
  initNotifiedFIFO(&gNB->L1_tx_filled);
  initNotifiedFIFO(&gNB->L1_tx_out);
Sakthivel Velumani's avatar
Sakthivel Velumani committed
1045
  // we create 2 threads for L1 tx processing
1046
  notifiedFIFO_elt_t *msgL1Tx = newNotifiedFIFO_elt(sizeof(processingData_L1tx_t),0,&gNB->L1_tx_free,processSlotTX);
Sakthivel Velumani's avatar
Sakthivel Velumani committed
1047 1048 1049 1050 1051
  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));
1052

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

1055 1056 1057 1058 1059 1060 1061 1062 1063 1064
    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);
1065
    reset_meas(&gNB->toutput);
1066

1067 1068
    clear_pdsch_stats(gNB);

1069
    effRate = 0;
1070 1071
    //n_errors2 = 0;
    //n_alamouti = 0;
1072
    n_false_positive = 0;
1073 1074
    if (n_trials== 1) num_rounds = 1;

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

1077
      errors_bit = 0;
Ahmed Hussein's avatar
Ahmed Hussein committed
1078
      //multipath channel
1079
      //multipath_channel(gNB2UE,s_re,s_im,r_re,r_im,frame_length_complex_samples,0);
1080

1081
      UE->rx_offset=0;
1082 1083 1084
      UE_proc.thread_id  = 0;
      UE_proc.frame_rx   = frame;
      UE_proc.nr_slot_rx = slot;
1085 1086 1087
      
      dcireq.frame     = frame;
      dcireq.slot      = slot;
1088

1089
      NR_UE_DLSCH_t *dlsch0 = UE->dlsch[UE_proc.thread_id][0][0];
1090

1091
      int harq_pid = slot;
1092 1093
      NR_DL_UE_HARQ_t *UE_harq_process = dlsch0->harq_processes[harq_pid];

Sakthivel Velumani's avatar
Sakthivel Velumani committed
1094
      NR_gNB_DLSCH_t *gNB_dlsch = msgDataTx->dlsch[0][0];
1095
      nfapi_nr_dl_tti_pdsch_pdu_rel15_t *rel15 = &gNB_dlsch->harq_process.pdsch_pdu.pdsch_pdu_rel15;
1096
      
1097
      UE_harq_process->ack = 0;
1098
      round = 0;
1099
      UE_harq_process->DLround = round;
francescomani's avatar
fixes  
francescomani committed
1100
      UE_harq_process->first_rx = 1;
1101
        
1102
      while ((round<num_rounds) && (UE_harq_process->ack==0)) {
1103
        round_trials[round][snrRun]++;
francescomani's avatar
fixes  
francescomani committed
1104

1105
        clear_nr_nfapi_information(RC.nrmac[0], 0, frame, slot);
Laurent THOMAS's avatar
Laurent THOMAS committed
1106 1107
        UE_info->UE_sched_ctrl.harq_processes[harq_pid].ndi = !(trial&1);
        UE_info->UE_sched_ctrl.harq_processes[harq_pid].round = round;
1108

1109
        if (css_flag == 0) {
1110
          nr_schedule_ue_spec(0, frame, slot);
1111 1112 1113
        } else {
          nr_schedule_css_dlsch_phytest(0,frame,slot);
        }
1114 1115 1116 1117 1118
        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];
laurent's avatar
laurent committed
1119
        Sched_INFO.UL_tti_req    = gNB_mac->UL_tti_req_ahead[0];
1120 1121
        Sched_INFO.UL_dci_req  = NULL;
        Sched_INFO.TX_req    = &gNB_mac->TX_req[0];
1122
        pushNotifiedFIFO(&gNB->L1_tx_free,msgL1Tx);
1123
        nr_schedule_response(&Sched_INFO);
1124 1125 1126 1127 1128 1129

        /* 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;
1130
        if(pdu_bit_map & 0x1) {
1131 1132 1133 1134 1135 1136 1137
          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);
1138
          LOG_D(PHY,"[DLSIM] PTRS Symbols in a slot: %2u, RE per Symbol: %3u, RE in a slot %4d\n", ptrsSymbPerSlot,ptrsRePerSymb, ptrsSymbPerSlot*ptrsRePerSymb );
1139
        }
Sakthivel Velumani's avatar
Sakthivel Velumani committed
1140 1141 1142 1143

        msgDataTx->ssb[0].ssb_pdu.ssb_pdu_rel15.bchPayload=0x001234;
        msgDataTx->ssb[0].ssb_pdu.ssb_pdu_rel15.SsbBlockIndex = 0;
        msgDataTx->gNB = gNB;
1144
        if (run_initial_sync)
Sakthivel Velumani's avatar
Sakthivel Velumani committed
1145
          nr_common_signal_procedures(gNB,frame,slot,msgDataTx->ssb[0].ssb_pdu);
1146
        else
Sakthivel Velumani's avatar
Sakthivel Velumani committed
1147
          phy_procedures_gNB_TX(msgDataTx,frame,slot,1);
1148
            
1149
        int txdataF_offset = slot * frame_parms->samples_per_slot_wCP;
1150 1151
        
        if (n_trials==1) {
1152
          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);
1153
          if (gNB->frame_parms.nb_antennas_tx>1)
1154
            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);
1155 1156
        }
        int tx_offset = frame_parms->get_samples_slot_timestamp(slot,frame_parms,0);
1157
        if (n_trials==1) printf("tx_offset %d, txdataF_offset %d \n", tx_offset,txdataF_offset);
1158

1159 1160 1161
        //TODO: loop over slots
        for (aa=0; aa<gNB->frame_parms.nb_antennas_tx; aa++) {
    
1162 1163 1164 1165 1166 1167 1168
          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);
1169
          } else {
1170 1171 1172
            nr_normal_prefix_mod(&gNB->common_vars.txdataF[aa][txdataF_offset],
                                 &txdata[aa][tx_offset],
                                 14,
1173 1174
                                 frame_parms,
                                 slot);
1175
          }
1176 1177 1178
        }
       
        if (n_trials==1) {
1179 1180 1181 1182 1183
          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);
          }
1184
        }
Sakthivel Velumani's avatar
Sakthivel Velumani committed
1185 1186
        if (output_fd) {
          printf("writing txdata to binary file\n");
1187
          fwrite(txdata[0],sizeof(int32_t),frame_length_complex_samples,output_fd);
Sakthivel Velumani's avatar
Sakthivel Velumani committed
1188
        }
1189

1190 1191 1192 1193 1194 1195 1196 1197 1198
        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);
        }
1199 1200
        
        for (i=(frame_parms->get_samples_slot_timestamp(slot,frame_parms,0)); 
1201 1202 1203 1204
             i<(frame_parms->get_samples_slot_timestamp(slot+1,frame_parms,0)); 
             i++) {
    
          for (aa=0; aa<frame_parms->nb_antennas_tx; aa++) {
1205 1206
            s_re[aa][i] = ((double)(((short *)txdata[aa]))[(i<<1)]);
            s_im[aa][i] = ((double)(((short *)txdata[aa]))[(i<<1)+1]);
1207
          }
1208
        }
1209

1210
        double ts = 1.0/(frame_parms->subcarrier_spacing * frame_parms->ofdm_symbol_size); 
1211
        //Compute AWGN variance
1212
        sigma2_dB = 10 * log10((double)txlev_sum * ((double)UE->frame_parms.ofdm_symbol_size/(12*rel15->rbSize))) - SNR;
1213
        sigma2    = pow(10, sigma2_dB/10);
1214
        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));
1215

1216 1217 1218 1219
        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));
        }
1220
        
1221 1222 1223 1224 1225 1226 1227 1228 1229
        // Apply MIMO Channel
        if (channel_model != AWGN) multipath_tv_channel(gNB2UE,
                             s_re,
                             s_im,
                             r_re,
                             r_im,
                             frame_length_complex_samples,
                             0);

1230 1231 1232 1233
        double H_awgn_mimo[4][4] ={{1.0, 0.2, 0.1, 0.05}, //rx 0
                                   {0.2, 1.0, 0.2, 0.1}, //rx 1
                                   {0.1, 0.2, 1.0, 0.2}, //rx 2
                                   {0.05, 0.1, 0.2, 1.0}};//rx 3
1234

1235
        for (i=frame_parms->get_samples_slot_timestamp(slot,frame_parms,0); 
1236 1237 1238
             i<frame_parms->get_samples_slot_timestamp(slot+1,frame_parms,0);
             i++) {

1239
          for (int aa_rx=0; aa_rx<n_rx; aa_rx++) {
1240 1241 1242 1243 1244

            if (channel_model == AWGN) {
              // sum up signals from different Tx antennas
              r_re[aa_rx][i] = 0;
              r_im[aa_rx][i] = 0;
1245 1246 1247
             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];
1248
              }
1249
            }
1250
            // Add Gaussian noise
1251 1252
            ((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)));
1253
            /* Add phase noise if enabled */
1254
            if (pdu_bit_map & 0x1) {
1255 1256
              phase_noise(ts, &((short*) UE->common_vars.rxdata[aa_rx])[2*i],
                          &((short*) UE->common_vars.rxdata[aa_rx])[2*i+1]);
1257
            }
1258
          }
1259
        }
1260

1261 1262
        nr_ue_dcireq(&dcireq); //to be replaced with function pointer later
        nr_ue_scheduled_response(&scheduled_response);
1263

1264
        phy_procedures_nrUE_RX(UE,
1265 1266
                               &UE_proc,
                               0,
1267
                               &phy_pdcch_config,
1268
                               NULL);
1269
        
1270 1271 1272
        //----------------------------------------------------------
        //---------------------- count errors ----------------------
        //----------------------------------------------------------
1273

1274 1275 1276
        if (UE->dlsch[UE_proc.thread_id][0][0]->last_iteration_cnt >=
          UE->dlsch[UE_proc.thread_id][0][0]->max_ldpc_iterations+1)
          n_errors[round][snrRun]++;
1277

1278 1279
        NR_UE_PDSCH **pdsch_vars = UE->pdsch_vars[UE_proc.thread_id];
        int16_t *UE_llr = pdsch_vars[0]->llr[0];
1280

1281 1282 1283 1284 1285 1286
        TBS                  = UE_harq_process->TBS;//rel15->TBSize[0];
        uint16_t length_dmrs = get_num_dmrs(rel15->dlDmrsSymbPos);
        uint16_t nb_rb       = rel15->rbSize;
        uint8_t  nb_re_dmrs  = rel15->dmrsConfigType == NFAPI_NR_DMRS_TYPE1 ? 6*UE_harq_process->n_dmrs_cdm_groups : 4*UE_harq_process->n_dmrs_cdm_groups;
        uint8_t  mod_order   = rel15->qamModOrder[0];
        uint8_t  nb_symb_sch = rel15->NrOfSymbols;
1287

1288 1289 1290 1291 1292
        available_bits = nr_get_G(nb_rb, nb_symb_sch, nb_re_dmrs, length_dmrs, mod_order, rel15->nrOfLayers);
        if(pdu_bit_map & 0x1) {
          available_bits-= (ptrsSymbPerSlot * ptrsRePerSymb *rel15->nrOfLayers* 2);
          printf("[DLSIM][PTRS] Available bits are: %5u, removed PTRS bits are: %5u \n",available_bits, (ptrsSymbPerSlot * ptrsRePerSymb *rel15->nrOfLayers* 2) );
        }
1293

1294 1295 1296 1297 1298 1299 1300 1301 1302 1303
        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)))
          {
            if(errors_scrambling[round][snrRun] == 0) {
              LOG_D(PHY,"First bit in error in unscrambling = %d\n",i);
            }
            errors_scrambling[round][snrRun]++;
          }
        }
1304

1305 1306 1307
        //printf("dlsim round %d ends\n",round);
        round++;
      } // round
1308

1309
      for (i = 0; i < TBS; i++) {
1310

1311
	estimated_output_bit[i] = (UE_harq_process->b[i/8] & (1 << (i & 7))) >> (i & 7);
1312
	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
1313
	
1314 1315
	if (estimated_output_bit[i] != test_input_bit[i]) {
	  if(errors_bit == 0)
1316
	    LOG_D(PHY,"First bit in error in decoding = %d\n",i);
1317
	  errors_bit++;
Raymond Knopp's avatar
Raymond Knopp committed
1318 1319
	}
	
1320 1321 1322
      }
      
      ////////////////////////////////////////////////////////////
1323

1324 1325 1326 1327 1328
      if (errors_bit > 0) {
	n_false_positive++;
	if (n_trials == 1)
	  printf("errors_bit = %u (trial %d)\n", errors_bit, trial);
      }
1329
      roundStats[snrRun]+=((float)round); 
1330
      if (UE_harq_process->ack==1) effRate += ((float)TBS)/round;
Ahmed Hussein's avatar
Ahmed Hussein committed
1331
    } // noise trials
1332

1333
    roundStats[snrRun]/=((float)n_trials);
1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344

    blerStats[0][snrRun] = (double)n_errors[0][snrRun]/round_trials[0][snrRun];
    blerStats[1][snrRun] = (double)n_errors[1][snrRun]/round_trials[1][snrRun];
    blerStats[2][snrRun] = (double)n_errors[2][snrRun]/round_trials[2][snrRun];
    blerStats[3][snrRun] = (double)n_errors[3][snrRun]/round_trials[3][snrRun];

    berStats[0][snrRun] = (double)errors_scrambling[0][snrRun]/available_bits/round_trials[0][snrRun];
    berStats[1][snrRun] = (double)errors_scrambling[1][snrRun]/available_bits/round_trials[1][snrRun];
    berStats[2][snrRun] = (double)errors_scrambling[2][snrRun]/available_bits/round_trials[2][snrRun];
    berStats[3][snrRun] = (double)errors_scrambling[3][snrRun]/available_bits/round_trials[3][snrRun];

1345
    effRate /= n_trials;
Ahmed Hussein's avatar
Ahmed Hussein committed
1346
    printf("*****************************************\n");
1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357
    printf("SNR %f: n_errors (%d/%d,%d/%d,%d/%d,%d/%d) (negative CRC), false_positive %d/%d, errors_scrambling (%u/%u,%u/%u,%u/%u,%u/%u\n",
           SNR,
           n_errors[0][snrRun], round_trials[0][snrRun],
           n_errors[1][snrRun], round_trials[1][snrRun],
           n_errors[2][snrRun], round_trials[2][snrRun],
           n_errors[3][snrRun], round_trials[3][snrRun],
           n_false_positive, n_trials,
           errors_scrambling[0][snrRun], available_bits*round_trials[0][snrRun],
           errors_scrambling[1][snrRun], available_bits*round_trials[1][snrRun],
           errors_scrambling[2][snrRun], available_bits*round_trials[2][snrRun],
           errors_scrambling[3][snrRun], available_bits*round_trials[3][snrRun]);
Ahmed Hussein's avatar
Ahmed Hussein committed
1358
    printf("\n");
Raymond Knopp's avatar
Raymond Knopp committed
1359
    dump_pdsch_stats(stdout,gNB);
1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374
    printf("SNR %f: Channel BLER (%e,%e,%e,%e), Channel BER (%e,%e,%e,%e) Avg round %.2f, Eff Rate %.4f bits/slot, Eff Throughput %.2f, TBS %u bits/slot\n",
           SNR,
           blerStats[0][snrRun],
           blerStats[1][snrRun],
           blerStats[2][snrRun],
           blerStats[3][snrRun],
           berStats[0][snrRun],
           berStats[1][snrRun],
           berStats[2][snrRun],
           berStats[3][snrRun],
           roundStats[snrRun],
           effRate,
           effRate/TBS*100,
           TBS);
    printf("*****************************************\n");
Ahmed Hussein's avatar
Ahmed Hussein committed
1375
    printf("\n");
1376

1377
    if (print_perf==1) {
1378
      printf("\ngNB TX function statistics (per %d us slot, NPRB %d, mcs %d, block %d)\n",
1379
	     1000>>*scc->ssbSubcarrierSpacing, g_rbSize, g_mcsIndex,
1380
	     msgDataTx->dlsch[0][0]->harq_process.pdsch_pdu.pdsch_pdu_rel15.TBSize[0]<<3);
Robert Schmidt's avatar
Robert Schmidt committed
1381
      printDistribution(&gNB->phy_proc_tx,table_tx,"PHY proc tx");
1382 1383 1384 1385 1386 1387 1388 1389 1390 1391
      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");
1392 1393 1394
      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");
1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411


      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",
1412 1413 1414
	     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,
1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427
	     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");
      */
    }
1428 1429 1430 1431 1432 1433

    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);
1434
      LOG_M("rxF0.m","rxF0", UE->common_vars.common_vars_rx_data_per_thread[UE_proc.thread_id].rxdataF[0], frame_parms->samples_per_slot_wCP, 1, 1);
1435
      LOG_M("rxF_ext.m","rxFe",&UE->pdsch_vars[0][0]->rxdataF_ext[0][0],g_rbSize*12*14,1,1);
1436
      LOG_M("chestF0.m","chF0",&UE->pdsch_vars[0][0]->dl_ch_estimates_ext[0][0],g_rbSize*12*14,1,1);
1437
      write_output("rxF_comp.m","rxFc",&UE->pdsch_vars[0][0]->rxdataF_comp0[0][0],N_RB_DL*12*14,1,1);
1438
      LOG_M("rxF_llr.m","rxFllr",UE->pdsch_vars[UE_proc.thread_id][0]->llr[0],available_bits,1,0);
1439 1440 1441
      break;
    }

1442
    if (effRate > (eff_tp_check*TBS)) {
1443 1444 1445 1446
      printf("PDSCH test OK\n");
      break;
    }

1447
    snrStats[snrRun] = SNR;
1448
    snrRun++;
1449
    n_errs = n_errors[0][snrRun];
1450 1451
  } // NSR

1452 1453 1454 1455
  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);
1456
  /*if (n_trials>1) {
1457 1458 1459 1460 1461 1462
    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;
    }
1463
  }*/
1464

1465 1466
  free_channel_desc_scm(gNB2UE);

1467
  for (i = 0; i < n_tx; i++) {
1468 1469
    free(s_re[i]);
    free(s_im[i]);
1470 1471 1472
    free(txdata[i]);
  }
  for (i = 0; i < n_rx; i++) {
1473 1474 1475 1476 1477 1478 1479 1480 1481
    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
1482 1483 1484
  free(test_input_bit);
  free(estimated_output_bit);
  
1485 1486 1487 1488 1489 1490
  if (output_fd)
    fclose(output_fd);

  if (input_fd)
    fclose(input_fd);

1491 1492
  if (scg_fd)
    fclose(scg_fd);
1493 1494

  return n_errs;
1495
}
1496 1497


1498
void update_ptrs_config(NR_CellGroupConfig_t *secondaryCellGroup, uint16_t *rbSize, uint8_t *mcsIndex, int8_t *ptrs_arg)
1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511
{
  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;

1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523
  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 {
1524 1525 1526
    printf("[DLSIM] Wrong L_PTRS value, using default values 1\n");
  }
  /* L = 4 if Imcs < MCS4 */
1527 1528 1529 1530 1531 1532 1533 1534 1535 1536
  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");
  }
1537
  printf("[DLSIM] PTRS Enabled with L %d, K %d \n", 1<<ptrs_arg[0], ptrs_arg[1] );
1538 1539 1540 1541
  /* overwrite the values */
  rrc_config_dl_ptrs_params(bwp, ptrsFreqDenst, ptrsTimeDenst, &epre_Ratio, &reOffset);
}

1542
void update_dmrs_config(NR_CellGroupConfig_t *scg, int8_t* dmrs_arg)
1543 1544 1545
{
  int8_t  mapping_type = typeA;//default value
  int8_t  add_pos = pdsch_dmrs_pos0;//default value
1546 1547
  int8_t  dmrs_config_type = NFAPI_NR_DMRS_TYPE1;//default value

1548
  if(dmrs_arg[0] == 0) {
1549 1550
    mapping_type = typeA;
  }
1551
  else if (dmrs_arg[0] == 1) {
1552
    mapping_type = typeB;
1553 1554
  } else {
    AssertFatal(1==0,"Incorrect Mappingtype, valid options 0-typeA, 1-typeB\n");
1555
  }
1556 1557 1558

  /* Additional DMRS positions 0 ,1 ,2 and 3 */
  if(dmrs_arg[1] >= 0 && dmrs_arg[1] <4 ) {
1559
    add_pos = dmrs_arg[1];
1560 1561
  } else {
    AssertFatal(1==0,"Incorrect Additional Position, valid options 0-pos1, 1-pos1, 2-pos2, 3-pos3\n");
1562
  }
1563

1564
  /* DMRS Conf Type 1 or 2 */
1565 1566 1567 1568
  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;
1569
  }
1570

1571
  NR_BWP_Downlink_t *bwp = scg->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.array[0];
1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589

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

1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605
  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");
  }
1606

1607 1608
  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;
1609 1610


1611 1612 1613 1614 1615
  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));
1616
    }
1617 1618 1619 1620
    *dmrs_config->dmrs_AdditionalPosition = add_pos;
  } else { // if NULL, Value pos2
    free(dmrs_config->dmrs_AdditionalPosition);
    dmrs_config->dmrs_AdditionalPosition = NULL;
1621
  }
1622

1623
  for (int i=0;i<bwp->bwp_Common->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list.count;i++) {
1624
    bwp->bwp_Common->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list.array[i]->mappingType = mapping_type;
1625
  }
1626

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