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

#include <fcntl.h>
23 24
#include <math.h>
#include <string.h>
25 26
#include <sys/ioctl.h>
#include <sys/mman.h>
27 28
#include <unistd.h>
#include "common/ran_context.h"
29
#include "common/config/config_userapi.h"
francescomani's avatar
francescomani committed
30
#include "common/utils/nr/nr_common.h"
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
  NR_pdsch_semi_static_t *ps = &sched_ctrl->pdsch_semi_static;
rmagueta's avatar
rmagueta committed
318

francescomani's avatar
francescomani committed
319
  nr_set_pdsch_semi_static(current_BWP,
320
                           scc,
321
                           /* tda = */ 0,
322 323
                           g_nrOfLayers,
                           sched_ctrl,
324 325 326 327 328 329
                           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;
francescomani's avatar
francescomani committed
330
  sched_pdsch->nrOfLayers = g_nrOfLayers;
331 332
  /* the following might override the table that is mandated by RRC
   * configuration */
francescomani's avatar
francescomani committed
333
  current_BWP->mcsTableIdx = g_mcsTableIdx;
334

francescomani's avatar
francescomani committed
335 336
  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);
337 338 339 340 341 342 343
  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 */,
344
                                        ps->nrOfLayers) >> 3;
345

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

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

Sakthivel Velumani's avatar
Sakthivel Velumani committed
367 368 369 370 371
nrUE_params_t nrUE_params;

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

Sakthivel Velumani's avatar
Sakthivel Velumani committed
373 374
void do_nothing(void *args) {
}
375

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

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

  FILE *input_fd=NULL,*pbch_file_fd=NULL;
419
  //char input_val_str[50],input_val_str2[50];
420

421
  //uint8_t frame_mod4,num_pdcch_symbols = 0;
422

423
  SCM_t channel_model = AWGN; // AWGN Rayleigh1 Rayleigh1_anticorr;
424

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

430
  //unsigned char frame_type = 0;
431

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

444
  //float target_error_rate = 0.01;
445
  int css_flag=0;
446 447

  cpuf = get_cpu_freq_GHz();
448 449 450
  int8_t enable_ptrs = 0;
  int8_t modify_dmrs = 0;

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

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

  randominit(0);

470
  int print_perf             = 0;
471

472 473
  FILE *scg_fd=NULL;
  
474
  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) {
475
    switch (c) {
476 477
    case 'f':
      scg_fd = fopen(optarg,"r");
478

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

485
    /*case 'd':
486
      frame_type = 1;
487
      break;*/
488 489 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

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

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

      break;

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

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

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

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

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

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

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

      break;

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

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

      break;

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

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

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

627

628 629 630
    case 'E':
	css_flag=1;
	break;
631

632

633
    case 'a':
634
      g_rbStart = atoi(optarg);
635 636 637
      break;

    case 'b':
638
      g_rbSize = atoi(optarg);
639
      break;
640

641
    case 'd':
642
      dlsch_threads = atoi(optarg);
643 644
      break;

645
    case 'e':
646
      g_mcsIndex = atoi(optarg);
647 648
      break;

649
    case 'q':
650
      g_mcsTableIdx = atoi(optarg);
651 652
      break;

653 654 655
    case 'm':
      mu = atoi(optarg);
      break;
656

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

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

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

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

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

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

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

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

741
  get_softmodem_params()->phy_test = 1;
742
  get_softmodem_params()->do_ra = 0;
743
  set_softmodem_optmask(SOFTMODEM_DLSIM_BIT);
744

745 746 747
  if (snr1set==0)
    snr1 = snr0+10;

748 749 750
  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
751

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

769 770
  gNB_mac->dl_bler.harq_round_max = num_rounds;

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

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

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

813 814 815 816

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

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

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

834 835 836
  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);
837

838
  // TODO do a UECAP for phy-sim
839
  const gNB_RrcConfigurationReq conf = {
840
    .pdsch_AntennaPorts = pdsch_AntennaPorts,
841 842 843 844 845 846
    .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);
847

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

859

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

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

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

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

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

882 883 884 885 886 887
  /* 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
888

889 890
  double fs,txbw,rxbw;
  uint32_t samples;
891

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

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

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

  frame_length_complex_samples = frame_parms->samples_per_subframe*NR_NUMBER_OF_SUBFRAMES_PER_FRAME;
916
  //frame_length_complex_samples_no_prefix = frame_parms->samples_per_subframe_wCP*NR_NUMBER_OF_SUBFRAMES_PER_FRAME;
917

918 919 920 921 922
  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*));
923

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

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

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

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

966
  init_nr_ue_transport(UE);
967

968
  nr_gold_pbch(UE);
969 970 971 972 973 974

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

980
  nr_l2_init_ue(NULL);
981
  UE_mac = get_mac_inst(0);
982

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

991
  UE_mac->if_module = nr_ue_if_module_init(0);
992

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

998
  initFloatingCoresTpool(dlsch_threads, &nrUE_params.Tpool, false, "UE-tpool");
999

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

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

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

1013 1014 1015

  nr_dcireq_t dcireq;
  nr_scheduled_response_t scheduled_response;
1016 1017
  NR_UE_PDCCH_CONFIG phy_pdcch_config={0};

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

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

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

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

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

1065 1066
    clear_pdsch_stats(gNB);

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

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

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

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

1087
      NR_UE_DLSCH_t *dlsch0 = UE->dlsch[UE_proc.thread_id][0][0];
1088

1089
      int harq_pid = slot;
1090 1091
      NR_DL_UE_HARQ_t *UE_harq_process = dlsch0->harq_processes[harq_pid];

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

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

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

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

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

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

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

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

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

1228 1229 1230 1231
        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
1232

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

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

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

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

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

1272 1273 1274
        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]++;
1275

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

1279 1280 1281 1282 1283 1284
        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;
1285

1286 1287 1288 1289 1290
        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) );
        }
1291

1292 1293 1294 1295 1296 1297 1298 1299 1300 1301
        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]++;
          }
        }
1302

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

1307
      for (i = 0; i < TBS; i++) {
1308

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

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

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

    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];

1343
    effRate /= n_trials;
Ahmed Hussein's avatar
Ahmed Hussein committed
1344
    printf("*****************************************\n");
1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355
    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
1356
    printf("\n");
Raymond Knopp's avatar
Raymond Knopp committed
1357
    dump_pdsch_stats(stdout,gNB);
1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372
    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
1373
    printf("\n");
1374

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


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

    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);
1432
      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);
1433
      LOG_M("chestF0.m","chF0",&UE->pdsch_vars[0][0]->dl_ch_estimates_ext[0][0],g_rbSize*12*14,1,1);
1434
      write_output("rxF_comp.m","rxFc",&UE->pdsch_vars[0][0]->rxdataF_comp0[0][0],N_RB_DL*12*14,1,1);
1435
      LOG_M("rxF_llr.m","rxFllr",UE->pdsch_vars[UE_proc.thread_id][0]->llr[0],available_bits,1,0);
1436 1437 1438
      break;
    }

1439
    if (effRate > (eff_tp_check*TBS)) {
1440 1441 1442 1443
      printf("PDSCH test OK\n");
      break;
    }

1444
    snrStats[snrRun] = SNR;
1445
    snrRun++;
1446
    n_errs = n_errors[0][snrRun];
1447 1448
  } // NSR

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

1462 1463
  free_channel_desc_scm(gNB2UE);

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

  if (input_fd)
    fclose(input_fd);

1488 1489
  if (scg_fd)
    fclose(scg_fd);
1490 1491

  return n_errs;
1492
}
1493 1494


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

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

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

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

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

1561
  /* DMRS Conf Type 1 or 2 */
1562 1563 1564 1565
  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;
1566
  }
1567

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

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

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

1604 1605
  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;
1606 1607


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

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

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