From 6fc6b7d120b6bd13671ba8f2a0ebbbc80efb6e97 Mon Sep 17 00:00:00 2001
From: Sakthivel Velumani <velumani@eurecom.fr>
Date: Mon, 6 Sep 2021 14:15:53 +0530
Subject: [PATCH] Updated nr_ulsim for multi antenna support

---
 openair1/SIMULATION/NR_PHY/ulsim.c            | 218 ++++++++++++++----
 .../LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c   |   1 +
 2 files changed, 172 insertions(+), 47 deletions(-)

diff --git a/openair1/SIMULATION/NR_PHY/ulsim.c b/openair1/SIMULATION/NR_PHY/ulsim.c
index 4604ad5fe9..e37f96a6b9 100644
--- a/openair1/SIMULATION/NR_PHY/ulsim.c
+++ b/openair1/SIMULATION/NR_PHY/ulsim.c
@@ -243,11 +243,6 @@ openair0_config_t openair0_cfg[MAX_CARDS];
 //const uint8_t nr_rv_round_map[4] = {0, 2, 1, 3}; 
 
 channel_desc_t *UE2gNB[NUMBER_OF_UE_MAX][NUMBER_OF_gNB_MAX];
-double s_re0[122880],s_im0[122880],r_re0[122880],r_im0[122880];
-double s_re1[122880],s_im1[122880],r_re1[122880],r_im1[122880];
-double r_re2[122880],r_im2[122880];
-double r_re3[122880],r_im3[122880];
-
 
 int main(int argc, char **argv)
 {
@@ -259,10 +254,7 @@ int main(int argc, char **argv)
   uint8_t snr1set = 0;
   int slot = 8, frame = 1;
   FILE *output_fd = NULL;
-  double *s_re[2]= {s_re0,s_re1};
-  double *s_im[2]= {s_im0,s_im1};
-  double *r_re[4]= {r_re0,r_re1,r_re2,r_re3};
-  double *r_im[4]= {r_im0,r_im1,r_im2,r_im3};
+  double **s_re,**s_im,**r_re,**r_im;
   //uint8_t write_output_file = 0;
   int trial, n_trials = 1, n_false_positive = 0, delay = 0;
   double maxDoppler = 0.0;
@@ -298,8 +290,9 @@ int main(int argc, char **argv)
   cpuf = get_cpu_freq_GHz();
   int msg3_flag = 0;
   int rv_index = 0;
-  float roundStats[50];
-  float effRate; 
+  float roundStats[100];
+  double effRate[100]; 
+  double effTP[100]; 
   //float eff_tp_check = 0.7;
   uint8_t snrRun;
   int prb_inter = 0;
@@ -314,8 +307,8 @@ int main(int argc, char **argv)
   uint16_t ptrsSymbPerSlot = 0;
   uint16_t ptrsRePerSymb = 0;
 
-  uint8_t transform_precoding = 1; // 0 - ENABLE, 1 - DISABLE
-  uint8_t num_dmrs_cdm_grps_no_data = 1;
+  uint8_t transform_precoding = transform_precoder_disabled; // 0 - ENABLE, 1 - DISABLE
+  uint8_t num_dmrs_cdm_grps_no_data = 2;
   uint8_t mcs_table = 0;
 
   UE_nr_rxtx_proc_t UE_proc;
@@ -502,7 +495,7 @@ int main(int argc, char **argv)
     case 'z':
       n_rx = atoi(optarg);
       
-      if ((n_rx == 0) || (n_rx > 2)) {
+      if ((n_rx == 0) || (n_rx > 8)) {
 	printf("Unsupported number of rx antennas %d\n", n_rx);
 	exit(-1);
       }
@@ -670,7 +663,7 @@ int main(int argc, char **argv)
   gNB->threadPool = (tpool_t*)malloc(sizeof(tpool_t));
   gNB->respDecode = (notifiedFIFO_t*) malloc(sizeof(notifiedFIFO_t));
   char tp_param[] = "n";
-  initTpool(tp_param, gNB->threadPool, true);
+  initTpool(tp_param, gNB->threadPool, false);
   initNotifiedFIFO(gNB->respDecode);
   //gNB_config = &gNB->gNB_config;
 
@@ -683,12 +676,14 @@ int main(int argc, char **argv)
   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_UL;
   frame_parms->Ncp = extended_prefix_flag ? EXTENDED : NORMAL;
 
+  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*));
 
   RC.nb_nr_macrlc_inst = 1;
   RC.nb_nr_mac_CC = (int*)malloc(RC.nb_nr_macrlc_inst*sizeof(int));
@@ -725,7 +720,13 @@ int main(int argc, char **argv)
   // common configuration
   rrc_mac_config_req_gNB(0,0, n_tx, n_rx, 0, scc, &rrc.carrier.mib,0, 0, NULL);
   // UE dedicated configuration
-  rrc_mac_config_req_gNB(0,0, n_tx, n_rx, 0, scc, &rrc.carrier.mib,1, secondaryCellGroup->spCellConfig->reconfigurationWithSync->newUE_Identity,secondaryCellGroup);
+  rrc_mac_config_req_gNB(0,0, n_tx, n_tx, scc, NULL, 1, secondaryCellGroup->spCellConfig->reconfigurationWithSync->newUE_Identity,secondaryCellGroup);
+  frame_parms->nb_antennas_tx = n_tx;
+  frame_parms->nb_antennas_rx = n_rx;
+  nfapi_nr_config_request_scf_t *cfg = &gNB->gNB_config;
+  cfg->carrier_config.num_tx_ant.value = n_tx;
+  cfg->carrier_config.num_rx_ant.value = n_rx;
+  nr_phy_config_request_sim(gNB,N_RB_DL,N_RB_DL,mu,0,0x01);
   phy_init_nr_gNB(gNB,0,1);
   N_RB_DL = gNB->frame_parms.N_RB_DL;
 
@@ -858,12 +859,13 @@ int main(int argc, char **argv)
     {
       add_pos = dmrs_arg[1];
     }
-    printf("NOTE: DMRS config is modified with Mapping Type %d , Additional Position %d \n", mapping_type, add_pos );
   }
+  printf("NOTE: DMRS config is modified with Mapping Type %d , Additional Position %d \n", mapping_type, add_pos );
 
   uint8_t  length_dmrs         = pusch_len1;
   uint16_t l_prime_mask        = get_l_prime(nb_symb_sch, mapping_type, add_pos, length_dmrs, start_symbol, NR_MIB__dmrs_TypeA_Position_pos2);
   uint16_t number_dmrs_symbols = get_dmrs_symbols_in_slot(l_prime_mask, nb_symb_sch);
+  printf("num dmrs sym %d\n",number_dmrs_symbols);
   uint8_t  nb_re_dmrs          = (dmrs_config_type == pusch_dmrs_type1) ? 6 : 4;
 
   // if transform precoding is enabled
@@ -875,11 +877,11 @@ int main(int argc, char **argv)
 	  AssertFatal(index >= 0, "Num RBs not configured according to 3GPP 38.211 section 6.3.1.4. For PUSCH with transform precoding, num RBs cannot be multiple of any other primenumber other than 2,3,5\n");
     
     dmrs_config_type = pusch_dmrs_type1;
-	  nb_re_dmrs   = nb_re_dmrs * num_dmrs_cdm_grps_no_data;
 
     printf("[ULSIM]: TRANSFORM PRECODING ENABLED. Num RBs: %d, index for DMRS_SEQ: %d\n", nb_rb, index);
   }
 
+  nb_re_dmrs   = nb_re_dmrs * num_dmrs_cdm_grps_no_data;
 
   unsigned int available_bits  = nr_get_G(nb_rb, nb_symb_sch, nb_re_dmrs, number_dmrs_symbols, mod_order, 1);
   unsigned int TBS             = nr_compute_tbs(mod_order, code_rate, nb_rb, nb_symb_sch, nb_re_dmrs * number_dmrs_symbols, 0, 0, precod_nbr_layers);
@@ -921,13 +923,24 @@ int main(int argc, char **argv)
     printf("NOTE: PTRS Enabled with L %d, K %d \n", ptrs_time_density, ptrs_freq_density );
   }
 
-  if (input_fd != NULL) max_rounds=1;
+  if (input_fd != NULL || n_trials == 1) max_rounds=1;
 
   if(1<<ptrs_time_density >= nb_symb_sch)
     pdu_bit_map &= ~PUSCH_PDU_BITMAP_PUSCH_PTRS; // disable PUSCH PTRS
 
   printf("\n");
 
+  int frame_length_complex_samples = frame_parms->samples_per_subframe*NR_NUMBER_OF_SUBFRAMES_PER_FRAME;
+  for (int aatx=0; aatx<n_tx; aatx++) {
+    s_re[aatx] = calloc(1,frame_length_complex_samples*sizeof(double));
+    s_im[aatx] = calloc(1,frame_length_complex_samples*sizeof(double));
+  }
+
+  for (int aarx=0; aarx<n_rx; aarx++) {
+    r_re[aarx] = calloc(1,frame_length_complex_samples*sizeof(double));
+    r_im[aarx] = calloc(1,frame_length_complex_samples*sizeof(double));
+  }
+
   //for (int i=0;i<16;i++) printf("%f\n",gaussdouble(0.0,1.0));
   snrRun = 0;
   int n_errs = 0;
@@ -969,7 +982,10 @@ int main(int argc, char **argv)
     sizeof(int16_t),
     slot_length<<1,
     input_fd);
-    if (read_errors==0) exit(1);
+    if (read_errors==0) {
+      printf("error reading file\n");
+      exit(1);
+    }
     for (int i=0;i<16;i+=2) printf("slot_offset %d : %d,%d\n",
 				   slot_offset,
 				   ((int16_t*)&gNB->common_vars.rxdata[0][slot_offset])[i],
@@ -979,14 +995,24 @@ int main(int argc, char **argv)
     code_rate = nr_get_code_rate_ul(Imcs, mcs_table);
   }
   
+  uint32_t errors_scrambling[4][100];
+  int n_errors[4][100];
+  int round_trials[4][100];
+  double blerStats[4][100];
+  double berStats[4][100];
+  double snrStats[100];
+  memset(errors_scrambling, 0, sizeof(uint32_t)*4*100);
+  memset(n_errors, 0, sizeof(int)*4*100);
+  memset(round_trials, 0, sizeof(int)*4*100);
+  memset(blerStats, 0, sizeof(double)*4*100);
+  memset(berStats, 0, sizeof(double)*4*100);
+  memset(snrStats, 0, sizeof(double)*100);
   for (SNR = snr0; SNR < snr1; SNR += snr_step) {
     varArray_t *table_rx=initVarArray(1000,sizeof(double));
     int error_flag = 0;
     n_false_positive = 0;
-    effRate = 0;
-    int n_errors[4] = {0,0,0,0};;
-    int round_trials[4]={0,0,0,0};
-    uint32_t errors_scrambling[4] = {0,0,0,0};
+    effRate[snrRun] = 0;
+    effTP[snrRun] = 0;
     reset_meas(&gNB->phy_proc_rx);
     reset_meas(&gNB->rx_pusch_stats);
     reset_meas(&gNB->ulsch_decoding_stats);
@@ -1011,7 +1037,7 @@ int main(int argc, char **argv)
     errors_decoding    = 0;
     memset((void*)roundStats,0,50*sizeof(roundStats[0]));
     while (round<max_rounds && crc_status) {
-      round_trials[round]++;
+      round_trials[round][snrRun]++;
       ulsch_ue[0]->harq_processes[harq_pid]->round = round;
       gNB->ulsch[0][0]->harq_processes[harq_pid]->round = round;
       rv_index = nr_rv_round_map[round];
@@ -1055,13 +1081,14 @@ int main(int argc, char **argv)
       pusch_pdu->qam_mod_order = mod_order;
       pusch_pdu->transform_precoding = transform_precoding;
       pusch_pdu->data_scrambling_id = *scc->physCellId;
+      printf("scram id %d\n",pusch_pdu->data_scrambling_id);
       pusch_pdu->nrOfLayers = 1;
       pusch_pdu->ul_dmrs_symb_pos = l_prime_mask;
       pusch_pdu->dmrs_config_type = dmrs_config_type;
       pusch_pdu->ul_dmrs_scrambling_id =  *scc->physCellId;
       pusch_pdu->scid = 0;
       pusch_pdu->dmrs_ports = 1;
-      pusch_pdu->num_dmrs_cdm_grps_no_data = msg3_flag == 0 ? 1 : 2;
+      pusch_pdu->num_dmrs_cdm_grps_no_data = num_dmrs_cdm_grps_no_data;
       pusch_pdu->resource_alloc = 1; 
       pusch_pdu->rb_start = start_rb;
       pusch_pdu->rb_size = nb_rb;
@@ -1124,7 +1151,7 @@ int main(int argc, char **argv)
       ul_config.ul_config_list[0].pusch_config_pdu.dmrs_config_type = dmrs_config_type;
       ul_config.ul_config_list[0].pusch_config_pdu.mcs_index = Imcs;
       ul_config.ul_config_list[0].pusch_config_pdu.mcs_table = mcs_table;
-      ul_config.ul_config_list[0].pusch_config_pdu.num_dmrs_cdm_grps_no_data = msg3_flag == 0 ? 1 : 2;
+      ul_config.ul_config_list[0].pusch_config_pdu.num_dmrs_cdm_grps_no_data = num_dmrs_cdm_grps_no_data;
       ul_config.ul_config_list[0].pusch_config_pdu.nrOfLayers = precod_nbr_layers;
       ul_config.ul_config_list[0].pusch_config_pdu.absolute_delta_PUSCH = 0;
 
@@ -1269,6 +1296,58 @@ int main(int argc, char **argv)
 		(nb_symb_sch-1)*(off+(NR_NB_SC_PER_RB * pusch_pdu->rb_size)),1,1);
 	  LOG_M("rxsigF0_comp.m","rxsF0_comp",
 		&gNB->pusch_vars[0]->rxdataF_comp[0][start_symbol*(off+(NR_NB_SC_PER_RB * pusch_pdu->rb_size))],nb_symb_sch*(off+(NR_NB_SC_PER_RB * pusch_pdu->rb_size)),1,1);
+    LOG_M("chmagF0.m","chmF0",
+    &gNB->pusch_vars[0]->ul_ch_mag[0][start_symbol*(off+(NR_NB_SC_PER_RB * pusch_pdu->rb_size))],nb_symb_sch*(off+(NR_NB_SC_PER_RB * pusch_pdu->rb_size)),1,1);
+    LOG_M("chmagbF0.m","chmbF0",
+    &gNB->pusch_vars[0]->ul_ch_magb[0][start_symbol*(off+(NR_NB_SC_PER_RB * pusch_pdu->rb_size))],nb_symb_sch*(off+(NR_NB_SC_PER_RB * pusch_pdu->rb_size)),1,1);
+    if (n_rx == 2) {
+      LOG_MM("rxsigF0_comp.m","rxsF1_comp",
+      &gNB->pusch_vars[0]->rxdataF_comp[1][start_symbol*(off+(NR_NB_SC_PER_RB * pusch_pdu->rb_size))],nb_symb_sch*(off+(NR_NB_SC_PER_RB * pusch_pdu->rb_size)),1,1);
+      LOG_MM("rxsigF0_ext.m","rxsF1_ext",
+      &gNB->pusch_vars[0]->rxdataF_ext[1][start_symbol*NR_NB_SC_PER_RB * pusch_pdu->rb_size],nb_symb_sch*(off+(NR_NB_SC_PER_RB * pusch_pdu->rb_size)),1,1);
+      LOG_MM("chestF0_ext.m","chF1_ext",
+      &gNB->pusch_vars[0]->ul_ch_estimates_ext[1][(start_symbol+1)*(off+(NR_NB_SC_PER_RB * pusch_pdu->rb_size))],
+      (nb_symb_sch-1)*(off+(NR_NB_SC_PER_RB * pusch_pdu->rb_size)),1,1);
+      LOG_MM("chmagF0.m","chmF1",
+      &gNB->pusch_vars[0]->ul_ch_mag[1][start_symbol*(off+(NR_NB_SC_PER_RB * pusch_pdu->rb_size))],nb_symb_sch*(off+(NR_NB_SC_PER_RB * pusch_pdu->rb_size)),1,1);
+      LOG_MM("chmagbF0.m","chmbF1",
+      &gNB->pusch_vars[0]->ul_ch_magb[1][start_symbol*(off+(NR_NB_SC_PER_RB * pusch_pdu->rb_size))],nb_symb_sch*(off+(NR_NB_SC_PER_RB * pusch_pdu->rb_size)),1,1);
+    } else if (n_rx == 4) {
+      LOG_MM("rxsigF0_comp.m","rxsF1_comp",
+      &gNB->pusch_vars[0]->rxdataF_comp[1][start_symbol*(off+(NR_NB_SC_PER_RB * pusch_pdu->rb_size))],nb_symb_sch*(off+(NR_NB_SC_PER_RB * pusch_pdu->rb_size)),1,1);
+      LOG_MM("rxsigF0_comp.m","rxsF2_comp",
+      &gNB->pusch_vars[0]->rxdataF_comp[2][start_symbol*(off+(NR_NB_SC_PER_RB * pusch_pdu->rb_size))],nb_symb_sch*(off+(NR_NB_SC_PER_RB * pusch_pdu->rb_size)),1,1);
+      LOG_MM("rxsigF0_comp.m","rxsF3_comp",
+      &gNB->pusch_vars[0]->rxdataF_comp[3][start_symbol*(off+(NR_NB_SC_PER_RB * pusch_pdu->rb_size))],nb_symb_sch*(off+(NR_NB_SC_PER_RB * pusch_pdu->rb_size)),1,1);
+      LOG_MM("rxsigF0_ext.m","rxsF1_ext",
+      &gNB->pusch_vars[0]->rxdataF_ext[1][start_symbol*NR_NB_SC_PER_RB * pusch_pdu->rb_size],nb_symb_sch*(off+(NR_NB_SC_PER_RB * pusch_pdu->rb_size)),1,1);
+      LOG_MM("rxsigF0_ext.m","rxsF2_ext",
+      &gNB->pusch_vars[0]->rxdataF_ext[2][start_symbol*NR_NB_SC_PER_RB * pusch_pdu->rb_size],nb_symb_sch*(off+(NR_NB_SC_PER_RB * pusch_pdu->rb_size)),1,1);
+      LOG_MM("rxsigF0_ext.m","rxsF3_ext",
+      &gNB->pusch_vars[0]->rxdataF_ext[3][start_symbol*NR_NB_SC_PER_RB * pusch_pdu->rb_size],nb_symb_sch*(off+(NR_NB_SC_PER_RB * pusch_pdu->rb_size)),1,1);
+      LOG_MM("chestF0_ext.m","chF1_ext",
+      &gNB->pusch_vars[0]->ul_ch_estimates_ext[1][(start_symbol+1)*(off+(NR_NB_SC_PER_RB * pusch_pdu->rb_size))],
+      (nb_symb_sch-1)*(off+(NR_NB_SC_PER_RB * pusch_pdu->rb_size)),1,1);
+      LOG_MM("chestF0_ext.m","chF2_ext",
+      &gNB->pusch_vars[0]->ul_ch_estimates_ext[2][(start_symbol+1)*(off+(NR_NB_SC_PER_RB * pusch_pdu->rb_size))],
+      (nb_symb_sch-1)*(off+(NR_NB_SC_PER_RB * pusch_pdu->rb_size)),1,1);
+      LOG_MM("chestF0_ext.m","chF3_ext",
+      &gNB->pusch_vars[0]->ul_ch_estimates_ext[3][(start_symbol+1)*(off+(NR_NB_SC_PER_RB * pusch_pdu->rb_size))],
+      (nb_symb_sch-1)*(off+(NR_NB_SC_PER_RB * pusch_pdu->rb_size)),1,1);
+      LOG_MM("chmagF0.m","chmF1",
+      &gNB->pusch_vars[0]->ul_ch_mag[1][start_symbol*(off+(NR_NB_SC_PER_RB * pusch_pdu->rb_size))],nb_symb_sch*(off+(NR_NB_SC_PER_RB * pusch_pdu->rb_size)),1,1);
+      LOG_MM("chmagF0.m","chmF2",
+      &gNB->pusch_vars[0]->ul_ch_mag[2][start_symbol*(off+(NR_NB_SC_PER_RB * pusch_pdu->rb_size))],nb_symb_sch*(off+(NR_NB_SC_PER_RB * pusch_pdu->rb_size)),1,1);
+      LOG_MM("chmagF0.m","chmF3",
+      &gNB->pusch_vars[0]->ul_ch_mag[3][start_symbol*(off+(NR_NB_SC_PER_RB * pusch_pdu->rb_size))],nb_symb_sch*(off+(NR_NB_SC_PER_RB * pusch_pdu->rb_size)),1,1);
+      LOG_MM("chmagbF0.m","chmbF1",
+      &gNB->pusch_vars[0]->ul_ch_magb[1][start_symbol*(off+(NR_NB_SC_PER_RB * pusch_pdu->rb_size))],nb_symb_sch*(off+(NR_NB_SC_PER_RB * pusch_pdu->rb_size)),1,1);
+      LOG_MM("chmagbF0.m","chmbF2",
+      &gNB->pusch_vars[0]->ul_ch_magb[2][start_symbol*(off+(NR_NB_SC_PER_RB * pusch_pdu->rb_size))],nb_symb_sch*(off+(NR_NB_SC_PER_RB * pusch_pdu->rb_size)),1,1);
+      LOG_MM("chmagbF0.m","chmbF3",
+      &gNB->pusch_vars[0]->ul_ch_magb[3][start_symbol*(off+(NR_NB_SC_PER_RB * pusch_pdu->rb_size))],nb_symb_sch*(off+(NR_NB_SC_PER_RB * pusch_pdu->rb_size)),1,1);
+    }
+
 	  LOG_M("rxsigF0_llr.m","rxsF0_llr",
 		&gNB->pusch_vars[0]->llr[0],(nb_symb_sch-1)*NR_NB_SC_PER_RB * pusch_pdu->rb_size * mod_order,1,0);
 	}
@@ -1277,7 +1356,7 @@ int main(int argc, char **argv)
 	if ((gNB->ulsch[0][0]->last_iteration_cnt >=
 	    gNB->ulsch[0][0]->max_ldpc_iterations+1) || ul_proc_error == 1) {
 	  error_flag = 1; 
-	  n_errors[round]++;
+	  n_errors[round][snrRun]++;
 	  crc_status = 1;
 	} else {
 	  crc_status = 0;
@@ -1303,13 +1382,19 @@ int main(int argc, char **argv)
 	  if(((ulsch_ue[0]->g[i] == 0) && (gNB->pusch_vars[UE_id]->llr[i] <= 0)) ||
 	     ((ulsch_ue[0]->g[i] == 1) && (gNB->pusch_vars[UE_id]->llr[i] >= 0)))
 	    {
-	      errors_scrambling[round]++;
+	      /*if(errors_scrambling == 0)
+		printf("\x1B[34m" "[frame %d][trial %d]\t1st bit in error in unscrambling = %d\n" "\x1B[0m", frame, trial, i);*/
+	      errors_scrambling[round][snrRun]++;
 	    }
 	}
 	round++;
 
     } // round
     
+    if (n_trials == 1 && errors_scrambling[0][snrRun] > 0) {
+      printf("\x1B[31m""[frame %d][trial %d]\tnumber of errors in unscrambling = %u\n" "\x1B[0m", frame, trial, errors_scrambling[0][snrRun]);
+    }
+    
     for (i = 0; i < TBS; i++) {
       
       estimated_output_bit[i] = (ulsch_gNB->harq_processes[harq_pid]->b[i/8] & (1 << (i & 7))) >> (i & 7);
@@ -1323,7 +1408,7 @@ int main(int argc, char **argv)
     }
     if (n_trials == 1) {
       for (int r=0;r<ulsch_ue[0]->harq_processes[harq_pid]->C;r++) 
-	for (int i=0;i<ulsch_ue[0]->harq_processes[harq_pid]->K>>3;i++) {
+	for (int i=0;i<10;i++) {
 	  if ((ulsch_ue[0]->harq_processes[harq_pid]->c[r][i]^ulsch_gNB->harq_processes[harq_pid]->c[r][i]) != 0) printf("************");
 	    printf("r %d: in[%d] %x, out[%d] %x (%x)\n",r,
 	    i,ulsch_ue[0]->harq_processes[harq_pid]->c[r][i],
@@ -1337,26 +1422,36 @@ int main(int argc, char **argv)
 	printf("\x1B[31m""[frame %d][trial %d]\tnumber of errors in decoding     = %u\n" "\x1B[0m", frame, trial, errors_decoding);
     } 
     roundStats[snrRun] += ((float)round);
-    if (!crc_status) effRate += ((float)TBS)/round;
+    if (!crc_status) effRate[snrRun] += ((double)TBS)/(double)round;
     } // trial loop
     
     roundStats[snrRun]/=((float)n_trials);
-    effRate /= n_trials;
+    effRate[snrRun] /= (double)n_trials;
     
     printf("*****************************************\n");
-    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], round_trials[0],n_errors[1], round_trials[1],n_errors[2], round_trials[2],n_errors[3], round_trials[3], n_false_positive, n_trials, errors_scrambling[0],available_bits*n_trials,errors_scrambling[1],available_bits*n_trials,errors_scrambling[2],available_bits*n_trials,errors_scrambling[3],available_bits*n_trials);
+    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*n_trials,errors_scrambling[1][snrRun],available_bits*n_trials,errors_scrambling[2][snrRun],available_bits*n_trials,errors_scrambling[3][snrRun],available_bits*n_trials);
     printf("\n");
+    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];
+    effTP[snrRun] = effRate[snrRun]/(double)TBS*(double)100;
     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,
-	   (double)n_errors[0]/round_trials[0],
-	   (double)n_errors[1]/round_trials[0],
-	   (double)n_errors[2]/round_trials[0],
-	   (double)n_errors[3]/round_trials[0],
-	   (double)errors_scrambling[0]/available_bits/round_trials[0],
-	   (double)errors_scrambling[1]/available_bits/round_trials[0],
-	   (double)errors_scrambling[2]/available_bits/round_trials[0],
-	   (double)errors_scrambling[3]/available_bits/round_trials[0],
-	   roundStats[snrRun],effRate,effRate/TBS*100,TBS);
+     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[snrRun],effTP[snrRun],TBS);
 
     FILE *fd=fopen("nr_ulsim.log","w");
     dump_pusch_stats(fd,gNB);
@@ -1389,18 +1484,47 @@ int main(int argc, char **argv)
     if(n_trials==1)
       break;
 
-    if ((float)n_errors[0]/(float)n_trials <= target_error_rate) {
+    if ((float)n_errors[0][snrRun]/(float)n_trials <= target_error_rate) {
       printf("*************\n");
       printf("PUSCH test OK\n");
       printf("*************\n");
-      break;
+      //break;
     }
 
+    snrStats[snrRun] = SNR;
     snrRun++;
-    n_errs = n_errors[0];
+    n_errs = n_errors[0][snrRun];
   } // SNR loop
   printf("\n");
 
+  printf( "Num RB:\t%d\n"
+          "Num symbols:\t%d\n"
+          "MCS:\t%d\n"
+          "DMRS config type:\t%d\n"
+          "DMRS add pos:\t%d\n"
+          "PUSCH mapping type:\t%d\n"
+          "DMRS length:\t%d\n"
+          "DMRS CDM gr w/o data:\t%d\n",
+          nb_rb,
+          nb_symb_sch,
+          Imcs,
+          dmrs_config_type,
+          add_pos,
+          mapping_type,
+          length_dmrs,
+          num_dmrs_cdm_grps_no_data);
+              
+  LOG_M("ulsimStats.m","SNR",snrStats,snrRun,1,7);
+  LOG_MM("ulsimStats.m","BLER_round0",blerStats[0],snrRun,1,7);
+  LOG_MM("ulsimStats.m","BLER_round1",blerStats[1],snrRun,1,7);
+  LOG_MM("ulsimStats.m","BLER_round2",blerStats[2],snrRun,1,7);
+  LOG_MM("ulsimStats.m","BLER_round3",blerStats[3],snrRun,1,7);
+  LOG_MM("ulsimStats.m","BER_round0",berStats[0],snrRun,1,7);
+  LOG_MM("ulsimStats.m","BER_round1",berStats[1],snrRun,1,7);
+  LOG_MM("ulsimStats.m","BER_round2",berStats[2],snrRun,1,7);
+  LOG_MM("ulsimStats.m","BER_round3",berStats[3],snrRun,1,7);
+  LOG_MM("ulsimStats.m","EffRate",effRate,snrRun,1,7);
+  LOG_MM("ulsimStats.m","EffTP",effTP,snrRun,1,7);
   free(test_input_bit);
   free(estimated_output_bit);
 
diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c
index 1b8330599b..8b2ff306ed 100644
--- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c
+++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c
@@ -922,6 +922,7 @@ bool allocate_ul_retransmission(module_id_t module_id,
   const uint8_t num_dmrs_cdm_grps_no_data = (sched_ctrl->active_bwp || ubwpd) ? 1 : 2;
   const int tda = sched_ctrl->active_ubwp ? RC.nrmac[module_id]->preferred_ul_tda[sched_ctrl->active_ubwp->bwp_Id][slot] : 0;
   LOG_D(NR_MAC,"retInfo->time_domain_allocation = %d, tda = %d\n", retInfo->time_domain_allocation, tda);
+  printf("num_dmrs_cdm_grps_no_data %d, tbs %d\n",num_dmrs_cdm_grps_no_data,retInfo->tb_size);
   if (tda == retInfo->time_domain_allocation) {
     /* Check the resource is enough for retransmission */
     while (rbStart < bwpSize && !rballoc_mask[rbStart])
-- 
2.26.2