From bd1c609ca89b551ee0805525fd085b75c459be21 Mon Sep 17 00:00:00 2001
From: laurent <laurent.thomas@open-cells.com>
Date: Fri, 12 Oct 2018 18:17:57 +0200
Subject: [PATCH] issue 359 dlsim CPU measurements

---
 cmake_targets/lte-simulators/CMakeLists.txt |   1 +
 openair1/PHY/defs_UE.h                      |   1 +
 openair1/PHY/defs_eNB.h                     |   2 +-
 openair1/SCHED/phy_procedures_lte_eNb.c     |   2 +
 openair1/SCHED_UE/phy_procedures_lte_ue.c   |  54 +-
 openair1/SIMULATION/LTE_PHY/common_sim.h    | 164 ++++
 openair1/SIMULATION/LTE_PHY/dlsim.c         | 791 +++++++-------------
 openair1/SIMULATION/LTE_PHY/ulsim.c         | 356 ++++-----
 8 files changed, 614 insertions(+), 757 deletions(-)
 create mode 100644 openair1/SIMULATION/LTE_PHY/common_sim.h

diff --git a/cmake_targets/lte-simulators/CMakeLists.txt b/cmake_targets/lte-simulators/CMakeLists.txt
index b7e83a92a03..1bfac2b20d6 100644
--- a/cmake_targets/lte-simulators/CMakeLists.txt
+++ b/cmake_targets/lte-simulators/CMakeLists.txt
@@ -9,4 +9,5 @@ set(MU_RECIEVER False)
 set(NAS_UE False)
 set(MESSAGE_CHART_GENERATOR False)
 set(RRC_ASN1_VERSION "Rel14")
+set (UE_TIMING_TRACE True)
 include(${CMAKE_CURRENT_SOURCE_DIR}/../CMakeLists.txt)
diff --git a/openair1/PHY/defs_UE.h b/openair1/PHY/defs_UE.h
index 55f8c9639ab..a303902b079 100644
--- a/openair1/PHY/defs_UE.h
+++ b/openair1/PHY/defs_UE.h
@@ -847,6 +847,7 @@ typedef struct {
   time_stats_t pdsch_procedures_stat[RX_NB_TH];
   time_stats_t pdsch_procedures_per_slot_stat[RX_NB_TH][LTE_SLOTS_PER_SUBFRAME];
   time_stats_t dlsch_procedures_stat[RX_NB_TH];
+  time_stats_t crnti_procedures_stats;
 
   time_stats_t ofdm_demod_stats;
   time_stats_t dlsch_rx_pdcch_stats;
diff --git a/openair1/PHY/defs_eNB.h b/openair1/PHY/defs_eNB.h
index f23485cad84..e62c4d766fc 100644
--- a/openair1/PHY/defs_eNB.h
+++ b/openair1/PHY/defs_eNB.h
@@ -1074,12 +1074,12 @@ typedef struct PHY_VARS_eNB_s {
 
   int hw_timing_advance;
 
-  time_stats_t phy_proc;
   time_stats_t phy_proc_tx;
   time_stats_t phy_proc_rx;
   time_stats_t rx_prach;
 
   time_stats_t ofdm_mod_stats;
+  time_stats_t dlsch_common_and_dci;
   time_stats_t dlsch_encoding_stats;
   time_stats_t dlsch_modulation_stats;
   time_stats_t dlsch_scrambling_stats;
diff --git a/openair1/SCHED/phy_procedures_lte_eNb.c b/openair1/SCHED/phy_procedures_lte_eNb.c
index 276006ec3be..f5d5334850e 100644
--- a/openair1/SCHED/phy_procedures_lte_eNb.c
+++ b/openair1/SCHED/phy_procedures_lte_eNb.c
@@ -484,6 +484,7 @@ void phy_procedures_eNB_TX(PHY_VARS_eNB *eNB,
 
   VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_TX+(eNB->CC_id),1);
   if (do_meas==1) start_meas(&eNB->phy_proc_tx);
+  if (do_meas==1) start_meas(&eNB->dlsch_common_and_dci);
 
   // clear the transmit data array for the current subframe
   for (aa=0; aa<fp->nb_antenna_ports_eNB; aa++) {      
@@ -578,6 +579,7 @@ void phy_procedures_eNB_TX(PHY_VARS_eNB *eNB,
         subframe);
   }
 
+  if (do_meas==1) stop_meas(&eNB->dlsch_common_and_dci);
 
   VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_PDCCH_TX,0);
 
diff --git a/openair1/SCHED_UE/phy_procedures_lte_ue.c b/openair1/SCHED_UE/phy_procedures_lte_ue.c
index b7d05ba0062..3b4d60230c6 100644
--- a/openair1/SCHED_UE/phy_procedures_lte_ue.c
+++ b/openair1/SCHED_UE/phy_procedures_lte_ue.c
@@ -1715,7 +1715,7 @@ void ue_ulsch_uespec_procedures(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB
       
     if ( LOG_DEBUGFLAG(UE_TIMING)) {
       stop_meas(&ue->phy_proc_tx);
-      LOG_UI(PHY,"------FULL TX PROC : %5.2f ------\n",ue->phy_proc_tx.p_time/(cpuf*1000.0));
+      LOG_I(PHY,"------FULL TX PROC : %5.2f ------\n",ue->phy_proc_tx.p_time/(cpuf*1000.0));
       stop_meas(&ue->ulsch_encoding_stats);
     }
 
@@ -3369,7 +3369,7 @@ void ue_pdsch_procedures(PHY_VARS_UE *ue, UE_rxtx_proc_t *proc, int eNB_id, PDSC
   	if(m >= ue->frame_parms.symbols_per_tti>>1)
   	  slot = 1;
   	stop_meas(&ue->dlsch_llr_stats_parallelization[ue->current_thread_id[subframe_rx]][slot]);
-  	LOG_UI(PHY, "[AbsSFN %d.%d] LLR Computation Symbol %d %5.2f \n",proc->frame_rx,subframe_rx,m,ue->dlsch_llr_stats_parallelization[ue->current_thread_id[subframe_rx]][slot].p_time/(cpuf*1000.0));
+  	LOG_I(PHY, "[AbsSFN %d.%d] LLR Computation Symbol %d %5.2f \n",proc->frame_rx,subframe_rx,m,ue->dlsch_llr_stats_parallelization[ue->current_thread_id[subframe_rx]][slot].p_time/(cpuf*1000.0));
       }
 
 
@@ -3604,9 +3604,9 @@ void ue_dlsch_procedures(PHY_VARS_UE *ue,
       
       if (LOG_DEBUGFLAG(UE_TIMING)) {
         stop_meas(&ue->dlsch_decoding_stats[ue->current_thread_id[subframe_rx]]);
-        LOG_UI(PHY, " --> Unscrambling for CW0 %5.3f\n",
+        LOG_I(PHY, " --> Unscrambling for CW0 %5.3f\n",
 	      (ue->dlsch_unscrambling_stats.p_time)/(cpuf*1000.0));
-        LOG_UI(PHY, "AbsSubframe %d.%d --> Turbo Decoding for CW0 %5.3f\n",
+        LOG_I(PHY, "AbsSubframe %d.%d --> Turbo Decoding for CW0 %5.3f\n",
 	      frame_rx%1024, subframe_rx,(ue->dlsch_decoding_stats[ue->current_thread_id[subframe_rx]].p_time)/(cpuf*1000.0));
       
       }
@@ -3661,9 +3661,9 @@ void ue_dlsch_procedures(PHY_VARS_UE *ue,
 	  
           if (LOG_DEBUGFLAG(UE_TIMING)) {
             stop_meas(&ue->dlsch_decoding_stats[ue->current_thread_id[subframe_rx]]);
-            LOG_UI(PHY, " --> Unscrambling for CW1 %5.3f\n",
+            LOG_I(PHY, " --> Unscrambling for CW1 %5.3f\n",
 		  (ue->dlsch_unscrambling_stats.p_time)/(cpuf*1000.0));
-            LOG_UI(PHY, "AbsSubframe %d.%d --> Turbo Decoding for CW1 %5.3f\n",
+            LOG_I(PHY, "AbsSubframe %d.%d --> Turbo Decoding for CW1 %5.3f\n",
 		  frame_rx%1024, subframe_rx,(ue->dlsch_decoding_stats[ue->current_thread_id[subframe_rx]].p_time)/(cpuf*1000.0));
           }
 
@@ -4005,7 +4005,7 @@ void *UE_thread_slot1_dl_processing(void *arg) {
 
         if ( LOG_DEBUGFLAG(UE_TIMING)) {
           stop_meas(&ue->ue_front_end_per_slot_stat[ue->current_thread_id[subframe_rx]][1]);
-          LOG_UI(PHY, "[AbsSFN %d.%d] Slot1: FFT + Channel Estimate + Pdsch Proc Slot0 %5.2f \n",frame_rx,subframe_rx,ue->ue_front_end_per_slot_stat[ue->current_thread_id[subframe_rx]][1].p_time/(cpuf*1000.0));
+          LOG_I(PHY, "[AbsSFN %d.%d] Slot1: FFT + Channel Estimate + Pdsch Proc Slot0 %5.2f \n",frame_rx,subframe_rx,ue->ue_front_end_per_slot_stat[ue->current_thread_id[subframe_rx]][1].p_time/(cpuf*1000.0));
         }
 
 
@@ -4099,7 +4099,7 @@ void *UE_thread_slot1_dl_processing(void *arg) {
 
     if ( LOG_DEBUGFLAG(UE_TIMING)) {
       stop_meas(&ue->pdsch_procedures_per_slot_stat[ue->current_thread_id[subframe_rx]][1]);
-      LOG_UI(PHY, "[AbsSFN %d.%d] Slot1: LLR Computation %5.2f \n",frame_rx,subframe_rx,ue->pdsch_procedures_per_slot_stat[ue->current_thread_id[subframe_rx]][1].p_time/(cpuf*1000.0));
+      LOG_I(PHY, "[AbsSFN %d.%d] Slot1: LLR Computation %5.2f \n",frame_rx,subframe_rx,ue->pdsch_procedures_per_slot_stat[ue->current_thread_id[subframe_rx]][1].p_time/(cpuf*1000.0));
     }
 
 
@@ -4319,7 +4319,7 @@ int phy_procedures_slot_parallelization_UE_RX(PHY_VARS_UE *ue,UE_rxtx_proc_t *pr
         if (ue_pdcch_procedures(eNB_id,ue,proc,abstraction_flag) == -1) {
             LOG_E(PHY,"[UE  %d] Frame %d, subframe %d: Error in pdcch procedures\n",ue->Mod_id,frame_rx,subframe_rx);
           if (LOG_DEBUGFLAG(UE_TIMING)) {
-            LOG_UI(PHY, "[AbsSFN %d.%d] Slot0: PDCCH %5.2f \n",frame_rx,subframe_rx,ue->pdcch_procedures_stat[ue->current_thread_id[subframe_rx]].p_time/(cpuf*1000.0));
+            LOG_I(PHY, "[AbsSFN %d.%d] Slot0: PDCCH %5.2f \n",frame_rx,subframe_rx,ue->pdcch_procedures_stat[ue->current_thread_id[subframe_rx]].p_time/(cpuf*1000.0));
         }
 
             //proc->dci_slot0_available = 1;
@@ -4328,7 +4328,7 @@ int phy_procedures_slot_parallelization_UE_RX(PHY_VARS_UE *ue,UE_rxtx_proc_t *pr
         //proc->dci_slot0_available=1;
         if (LOG_DEBUGFLAG(UE_TIMING)) {
           stop_meas(&ue->pdcch_procedures_stat[ue->current_thread_id[subframe_rx]]);
-          LOG_UI(PHY, "[AbsSFN %d.%d] Slot0: PDCCH %5.2f \n",frame_rx,subframe_rx,ue->pdcch_procedures_stat[ue->current_thread_id[subframe_rx]].p_time/(cpuf*1000.0));
+          LOG_I(PHY, "[AbsSFN %d.%d] Slot0: PDCCH %5.2f \n",frame_rx,subframe_rx,ue->pdcch_procedures_stat[ue->current_thread_id[subframe_rx]].p_time/(cpuf*1000.0));
         }
     }
 
@@ -4337,7 +4337,7 @@ int phy_procedures_slot_parallelization_UE_RX(PHY_VARS_UE *ue,UE_rxtx_proc_t *pr
     // first slot has been processed (FFTs + Channel Estimation, PCFICH/PHICH/PDCCH)
     if (LOG_DEBUGFLAG(UE_TIMING)) {
       stop_meas(&ue->ue_front_end_per_slot_stat[ue->current_thread_id[subframe_rx]][0]);
-      LOG_UI(PHY, "[AbsSFN %d.%d] Slot0: FFT + Channel Estimate + PCFICH/PHICH/PDCCH %5.2f \n",frame_rx,subframe_rx,ue->ue_front_end_per_slot_stat[ue->current_thread_id[subframe_rx]][0].p_time/(cpuf*1000.0));
+      LOG_I(PHY, "[AbsSFN %d.%d] Slot0: FFT + Channel Estimate + PCFICH/PHICH/PDCCH %5.2f \n",frame_rx,subframe_rx,ue->ue_front_end_per_slot_stat[ue->current_thread_id[subframe_rx]][0].p_time/(cpuf*1000.0));
     }
 
     //wait until slot1 FE is done
@@ -4350,7 +4350,7 @@ int phy_procedures_slot_parallelization_UE_RX(PHY_VARS_UE *ue,UE_rxtx_proc_t *pr
 
     if (LOG_DEBUGFLAG(UE_TIMING)) {
       stop_meas(&ue->ue_front_end_stat[ue->current_thread_id[subframe_rx]]);
-      LOG_UI(PHY, "[AbsSFN %d.%d] FULL FE Processing %5.2f \n",frame_rx,subframe_rx,ue->ue_front_end_per_slot_stat[ue->current_thread_id[subframe_rx]][0].p_time/(cpuf*1000.0));
+      LOG_I(PHY, "[AbsSFN %d.%d] FULL FE Processing %5.2f \n",frame_rx,subframe_rx,ue->ue_front_end_per_slot_stat[ue->current_thread_id[subframe_rx]][0].p_time/(cpuf*1000.0));
     }
     /**** End Subframe FE Processing ****/
 
@@ -4439,7 +4439,7 @@ int phy_procedures_slot_parallelization_UE_RX(PHY_VARS_UE *ue,UE_rxtx_proc_t *pr
 
     if (LOG_DEBUGFLAG(UE_TIMING)){
       stop_meas(&ue->pdsch_procedures_per_slot_stat[ue->current_thread_id[subframe_rx]][0]);
-      LOG_UI(PHY, "[AbsSFN %d.%d] Slot0: LLR Computation %5.2f \n",frame_rx,subframe_rx,ue->pdsch_procedures_per_slot_stat[ue->current_thread_id[subframe_rx]][0].p_time/(cpuf*1000.0));
+      LOG_I(PHY, "[AbsSFN %d.%d] Slot0: LLR Computation %5.2f \n",frame_rx,subframe_rx,ue->pdsch_procedures_per_slot_stat[ue->current_thread_id[subframe_rx]][0].p_time/(cpuf*1000.0));
     }
 
 
@@ -4455,7 +4455,7 @@ int phy_procedures_slot_parallelization_UE_RX(PHY_VARS_UE *ue,UE_rxtx_proc_t *pr
 
     if (LOG_DEBUGFLAG(UE_TIMING)){
       stop_meas(&ue->pdsch_procedures_stat[ue->current_thread_id[subframe_rx]]);
-      LOG_UI(PHY, "[AbsSFN %d.%d] Full LLR Computation %5.2f \n",frame_rx,subframe_rx,ue->pdsch_procedures_stat[ue->current_thread_id[subframe_rx]].p_time/(cpuf*1000.0));
+      LOG_I(PHY, "[AbsSFN %d.%d] Full LLR Computation %5.2f \n",frame_rx,subframe_rx,ue->pdsch_procedures_stat[ue->current_thread_id[subframe_rx]].p_time/(cpuf*1000.0));
     }
 
 
@@ -4526,7 +4526,7 @@ int phy_procedures_slot_parallelization_UE_RX(PHY_VARS_UE *ue,UE_rxtx_proc_t *pr
 
     if (LOG_DEBUGFLAG(UE_TIMING)
       stop_meas(&ue->dlsch_procedures_stat[ue->current_thread_id[subframe_rx]]);
-      LOG_UI(PHY, "[AbsSFN %d.%d] Channel Decoder: %5.2f \n",frame_rx,subframe_rx,ue->dlsch_procedures_stat[ue->current_thread_id[subframe_rx]].p_time/(cpuf*1000.0));
+      LOG_I(PHY, "[AbsSFN %d.%d] Channel Decoder: %5.2f \n",frame_rx,subframe_rx,ue->dlsch_procedures_stat[ue->current_thread_id[subframe_rx]].p_time/(cpuf*1000.0));
     }
 
         // duplicate harq structure
@@ -4589,7 +4589,7 @@ int phy_procedures_slot_parallelization_UE_RX(PHY_VARS_UE *ue,UE_rxtx_proc_t *pr
 
     if (LOG_DEBUGFLAG(UE_TIMING)){
     stop_meas(&ue->phy_proc_rx[ue->current_thread_id[subframe_rx]]);
-    LOG_UI(PHY, "------FULL RX PROC [AbsSFN %d.%d]: %5.2f ------\n",frame_rx,subframe_rx,ue->phy_proc_rx[ue->current_thread_id[subframe_rx]].p_time/(cpuf*1000.0));
+    LOG_I(PHY, "------FULL RX PROC [AbsSFN %d.%d]: %5.2f ------\n",frame_rx,subframe_rx,ue->phy_proc_rx[ue->current_thread_id[subframe_rx]].p_time/(cpuf*1000.0));
     }
 
     LOG_D(PHY," ****** end RX-Chain  for AbsSubframe %d.%d ******  \n", frame_rx%1024, subframe_rx);
@@ -4632,7 +4632,7 @@ int phy_procedures_UE_RX(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,
 
   if(LOG_DEBUGFLAG(UE_TIMING)) {
     start_meas(&ue->phy_proc_rx[ue->current_thread_id[subframe_rx]]);
-    start_meas(&ue->generic_stat);
+    start_meas(&ue->ue_front_end_stat[ue->current_thread_id[subframe_rx]]);
   }
 
   pmch_flag = is_pmch_subframe(frame_rx,subframe_rx,&ue->frame_parms) ? 1 : 0;
@@ -4757,15 +4757,17 @@ int phy_procedures_UE_RX(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,
 
   // first slot has been processed (FFTs + Channel Estimation, PCFICH/PHICH/PDCCH)
   if (LOG_DEBUGFLAG(UE_TIMING)) {
-    stop_meas(&ue->generic_stat);
-    LOG_UI(PHY, "[SFN %d] Slot0: FFT + Channel Estimate + PCFICH/PHICH/PDCCH %5.2f \n",subframe_rx,ue->generic_stat.p_time/(cpuf*1000.0));
+    stop_meas(&ue->ue_front_end_stat[ue->current_thread_id[subframe_rx]]);
+    LOG_I(PHY, "[SFN %d] Slot0: FFT + Channel Estimate + PCFICH/PHICH/PDCCH %5.2f \n",subframe_rx,ue->ue_front_end_stat[ue->current_thread_id[subframe_rx]].p_time/(cpuf*1000.0));
   }
 
 
   LOG_D(PHY," ------ --> PDSCH ChannelComp/LLR slot 0: AbsSubframe %d.%d ------  \n", frame_rx%1024, subframe_rx);
   if (LOG_DEBUGFLAG(UE_TIMING)) {
     start_meas(&ue->generic_stat);
+    start_meas(&ue->crnti_procedures_stats);
   }
+
   // do procedures for C-RNTI
   if (ue->dlsch[ue->current_thread_id[subframe_rx]][eNB_id][0]->active == 1) {
     VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDSCH_PROC, VCD_FUNCTION_IN);
@@ -4782,12 +4784,14 @@ int phy_procedures_UE_RX(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,
     VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDSCH_PROC, VCD_FUNCTION_OUT);
   }
 
+  if (LOG_DEBUGFLAG(UE_TIMING)) {
+    stop_meas(&ue->crnti_procedures_stats);
+  }
   LOG_D(PHY," ------ end PDSCH ChannelComp/LLR slot 0: AbsSubframe %d.%d ------  \n", frame_rx%1024, subframe_rx);
   // do procedures for SI-RNTI
   if ((ue->dlsch_SI[eNB_id]) && (ue->dlsch_SI[eNB_id]->active == 1)) {
     VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDSCH_PROC_SI, VCD_FUNCTION_IN);
     ue_pdsch_procedures(ue,
-
 			proc,
 			eNB_id,
 			SI_PDSCH,
@@ -4870,7 +4874,7 @@ int phy_procedures_UE_RX(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,
   } // not an S-subframe
   if(LOG_DEBUGFLAG(UE_TIMING)) {
     stop_meas(&ue->generic_stat);
-    LOG_UI(PHY, "[SFN %d] Slot1: FFT + Channel Estimate + Pdsch Proc Slot0 %5.2f \n",subframe_rx,ue->generic_stat.p_time/(cpuf*1000.0));
+    LOG_I(PHY, "[SFN %d] Slot1: FFT + Channel Estimate + Pdsch Proc Slot0 %5.2f \n",subframe_rx,ue->generic_stat.p_time/(cpuf*1000.0));
   }
 
   LOG_D(PHY," ------  end FFT/ChannelEst/PDCCH slot 1: AbsSubframe %d.%d ------  \n", frame_rx%1024, subframe_rx);
@@ -4915,8 +4919,8 @@ int phy_procedures_UE_RX(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,
 			abstraction_flag);
     if (LOG_DEBUGFLAG(UE_TIMING)) { 
       stop_meas(&ue->dlsch_procedures_stat[ue->current_thread_id[subframe_rx]]);
-      LOG_UI(PHY, "[SFN %d] Slot1:       Pdsch Proc %5.2f\n",subframe_rx,ue->pdsch_procedures_stat[ue->current_thread_id[subframe_rx]].p_time/(cpuf*1000.0));
-      LOG_UI(PHY, "[SFN %d] Slot0 Slot1: Dlsch Proc %5.2f\n",subframe_rx,ue->dlsch_procedures_stat[ue->current_thread_id[subframe_rx]].p_time/(cpuf*1000.0));
+      LOG_I(PHY, "[SFN %d] Slot1:       Pdsch Proc %5.2f\n",subframe_rx,ue->pdsch_procedures_stat[ue->current_thread_id[subframe_rx]].p_time/(cpuf*1000.0));
+      LOG_I(PHY, "[SFN %d] Slot0 Slot1: Dlsch Proc %5.2f\n",subframe_rx,ue->dlsch_procedures_stat[ue->current_thread_id[subframe_rx]].p_time/(cpuf*1000.0));
     }
 
     VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDSCH_PROC, VCD_FUNCTION_OUT);
@@ -5059,14 +5063,14 @@ int phy_procedures_UE_RX(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,
 
   if ( LOG_DEBUGFLAG(UE_TIMING)) {
     stop_meas(&ue->generic_stat);
-    LOG_UI(PHY,"after tubo until end of Rx %5.2f \n",ue->generic_stat.p_time/(cpuf*1000.0));
+    LOG_I(PHY,"after tubo until end of Rx %5.2f \n",ue->generic_stat.p_time/(cpuf*1000.0));
   }
 
   VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_RX, VCD_FUNCTION_OUT);
 
   if ( LOG_DEBUGFLAG(UE_TIMING) ) {
     stop_meas(&ue->phy_proc_rx[ue->current_thread_id[subframe_rx]]);
-    LOG_UI(PHY, "------FULL RX PROC [SFN %d]: %5.2f ------\n",subframe_rx,ue->phy_proc_rx[ue->current_thread_id[subframe_rx]].p_time/(cpuf*1000.0));
+    LOG_I(PHY, "------FULL RX PROC [SFN %d]: %5.2f ------\n",subframe_rx,ue->phy_proc_rx[ue->current_thread_id[subframe_rx]].p_time/(cpuf*1000.0));
   }
 
   LOG_D(PHY," ****** end RX-Chain  for AbsSubframe %d.%d ******  \n", frame_rx%1024, subframe_rx);
diff --git a/openair1/SIMULATION/LTE_PHY/common_sim.h b/openair1/SIMULATION/LTE_PHY/common_sim.h
new file mode 100644
index 00000000000..46f4cdf1611
--- /dev/null
+++ b/openair1/SIMULATION/LTE_PHY/common_sim.h
@@ -0,0 +1,164 @@
+
+static int cmpdouble(const void *p1, const void *p2) {
+  return *(double *)p1 > *(double *)p2;
+}
+
+double median(varArray_t *input) {
+  return *(double *)((uint8_t *)(input+1)+(input->size/2)*input->atomSize);
+}
+
+double q1(varArray_t *input) {
+  return *(double *)((uint8_t *)(input+1)+(input->size/4)*input->atomSize);
+}
+
+double q3(varArray_t *input) {
+  return *(double *)((uint8_t *)(input+1)+(3*input->size/4)*input->atomSize);
+}
+
+void dumpVarArray(varArray_t *input) {
+  double *ptr=dataArray(input);
+  printf("dumping size=%ld\n", input->size);
+
+  for (int i=0; i < input->size; i++)
+    printf("%.1f:", *ptr++);
+
+  printf("\n");
+}
+void sumUpStats(time_stats_t * res, time_stats_t * src, int lastActive) {
+  	reset_meas(res);
+	for (int i=0; i<RX_NB_TH; i++) {
+	  res->diff+=src[i].diff;
+	  res->diff_square+=src[i].diff_square;
+	  res->trials+=src[i].trials;
+	  if (src[i].max > res->max)
+	    res->max=src[i].max;
+	}
+	res->p_time=src[lastActive].p_time;
+}
+void sumUpStatsSlot(time_stats_t *res, time_stats_t src[RX_NB_TH][2], int lastActive) {
+  	reset_meas(res);
+	for (int i=0; i<RX_NB_TH; i++) {
+	  res->diff+=src[i][0].diff+src[i][1].diff;
+	  res->diff_square+=src[i][0].diff_square+src[i][1].diff_square;
+	  res->trials+=src[i][0].trials+src[i][1].trials;
+	  if (src[i][0].max > res->max)
+	    res->max=src[i][0].max;
+	  if (src[i][1].max > res->max)
+	    res->max=src[i][1].max;}
+	int last=src[lastActive][0].in < src[lastActive][1].in? 1 : 0 ;
+	res->p_time=src[lastActive][last].p_time;
+}
+
+void printStatIndent(time_stats_t *ptr, char *txt) {
+  printf("|__ %-50s %.2f us (%d trials)\n",
+         txt,
+         ptr->trials?inMicroS(ptr->diff/ptr->trials):0,
+         ptr->trials);
+}
+
+void printStatIndent2(time_stats_t *ptr, char *txt, int turbo_iter) {
+  double timeBase=1/(1000*cpu_freq_GHz);
+  printf("    |__ %-45s %.2f us (cycles/block %ld, %5d trials)\n",
+         txt,
+         ptr->trials?((double)ptr->diff)/ptr->trials*timeBase:0,
+         turbo_iter?(uint64_t)round(((double)ptr->diff)/turbo_iter):0,
+         ptr->trials);
+}
+
+double squareRoot(time_stats_t *ptr) {
+  double timeBase=1/(1000*cpu_freq_GHz);
+  return sqrt((double)ptr->diff_square*pow(timeBase,2)/ptr->trials -
+              pow((double)ptr->diff/ptr->trials*timeBase,2));
+}
+
+void printDistribution(time_stats_t *ptr, varArray_t *sortedList, char *txt) {
+  double timeBase=1/(1000*cpu_freq_GHz);
+  printf("%-50s             :%.2f us (%d trials)\n",
+         txt,
+         (double)ptr->diff/ptr->trials*timeBase,
+         ptr->trials);
+  printf("|__ Statistics std=%.2f, median=%.2f, q1=%.2f, q3=%.2f µs (on %ld trials)\n",
+         squareRoot(ptr), median(sortedList),q1(sortedList),q3(sortedList), sortedList->size);
+}
+
+void logDistribution(FILE* fd, time_stats_t *ptr, varArray_t *sortedList, int dropped) {
+  fprintf(fd,"%f;%f;%f;%f;%f;%f;%d;",
+	  squareRoot(ptr),
+	  (double)ptr->max, *(double*)dataArray(sortedList),
+	  median(sortedList),q1(sortedList),q3(sortedList),
+	  dropped); 
+}
+
+struct option * parse_oai_options(paramdef_t *options) {
+  int l;
+
+  for(l=0; options[l].optname[0]!=0; l++) {};
+
+  struct option *long_options=calloc(sizeof(struct option),l);
+
+  for(int i=0; options[i].optname[0]!=0; i++) {
+    long_options[i].name=options[i].optname;
+    long_options[i].has_arg=options[i].paramflags==PARAMFLAG_BOOL?no_argument:required_argument;
+
+    if ( options[i].voidptr)
+      switch (options[i].type) {
+      case TYPE_INT:
+	*options[i].iptr=options[i].defintval;
+	break;
+
+      case TYPE_DOUBLE:
+	*options[i].dblptr=options[i].defdblval;
+	break;
+
+      case TYPE_UINT8:
+	*options[i].u8ptr=options[i].defintval;
+	break;
+
+      case TYPE_UINT16:
+	*options[i].u16ptr=options[i].defintval;
+	break;
+	
+      default:
+	printf("not parsed type for default value %s\n", options[i].optname );
+	exit(1);
+      }
+
+    continue;
+  };
+  return long_options;
+}
+
+void display_options_values(paramdef_t *options, int verbose) {
+  for(paramdef_t * ptr=options; ptr->optname[0]!=0; ptr++) {
+    char varText[256]="need specific display";
+
+    if (ptr->voidptr != NULL) {
+      if ( (ptr->paramflags & PARAMFLAG_BOOL) )
+        strcpy(varText, *(bool *)ptr->iptr ? "True": "False" );
+      else  switch (ptr->type) {
+          case TYPE_INT:
+            sprintf(varText,"%d",*ptr->iptr);
+            break;
+
+          case TYPE_DOUBLE:
+            sprintf(varText,"%.2f",*ptr->dblptr);
+            break;
+
+	case TYPE_UINT8:
+	  sprintf(varText,"%d",(int)*ptr->u8ptr);
+	  break;
+	  
+	case TYPE_UINT16:
+	  sprintf(varText,"%d",(int)*ptr->u16ptr);
+	  break;
+	  
+	default:
+	  printf("not decoded type\n");
+	  exit(1);
+        }
+    }
+
+    printf("--%-20s set to %s\n",ptr->optname, varText);
+    if (verbose) printf("%s\n",ptr->helpstr);
+  }
+}
diff --git a/openair1/SIMULATION/LTE_PHY/dlsim.c b/openair1/SIMULATION/LTE_PHY/dlsim.c
index 3583c0f25ea..0f4655eb2c7 100644
--- a/openair1/SIMULATION/LTE_PHY/dlsim.c
+++ b/openair1/SIMULATION/LTE_PHY/dlsim.c
@@ -72,6 +72,9 @@ void feptx_ofdm(RU_t *ru);
 void feptx_prec(RU_t *ru);
 
 double cpuf;
+#define inMicroS(a) (((double)(a))/(cpu_freq_GHz*1000.0))
+//#define MCS_COUNT 23//added for PHY abstraction
+#include <openair1/SIMULATION/LTE_PHY/common_sim.h>
 
 int otg_enabled=0;
 /*the following parameters are used to control the processing times calculations*/
@@ -535,23 +538,42 @@ void fill_DCI(PHY_VARS_eNB *eNB,
 }
 
 int n_users = 1;
-sub_frame_t subframe=7;
+int subframe=7;
 int num_common_dci=0,num_ue_spec_dci=0,num_dci=0,num_pdcch_symbols=1;
 uint16_t n_rnti=0x1234;
-  int nfapi_mode=0;
+int nfapi_mode=0;
+int abstx=0;
+int Nid_cell=0;
+int N_RB_DL=25;
+int tdd_config=3;
+int dci_flag=0;
+int threequarter_fs=0;
+double snr_step=1,input_snr_step=1, snr_int=30;
+double forgetting_factor=0.0; //in [0,1] 0 means a new channel every time, 1 means keep the same channel
+int test_perf=0;
+int n_frames;
+int n_ch_rlz = 1;
+int rx_sample_offset = 0;
+int xforms=0;
+int dump_table=0;
+int loglvl=OAILOG_WARNING;
+int mcs1=0,mcs2=0,mcs_i=0,dual_stream_UE = 0,awgn_flag=0;
+int two_thread_flag=0;
+int num_rounds = 4;//,fix_rounds=0;
+int perfect_ce = 0;
+int extended_prefix_flag=0;
+int verbose=0, help=0;
+double SNR,snr0=-2.0,snr1,rate = 0;
+int print_perf=0;
 
 int main(int argc, char **argv)
 {
 
-  int c;
   int k,i,j,aa;
   int re;
-  int loglvl=OAILOG_DEBUG;
 
   int s,Kr,Kr_bytes;
 
-  double SNR,snr0=-2.0,snr1,rate = 0;
-  double snr_step=1,input_snr_step=1, snr_int=30;
 
   LTE_DL_FRAME_PARMS *frame_parms;
   double s_re0[30720*2],s_im0[30720*2],r_re0[30720*2],r_im0[30720*2];
@@ -560,17 +582,14 @@ int main(int argc, char **argv)
   double *s_im[2]={s_im0,s_im1};
   double *r_re[2]={r_re0,r_re1};
   double *r_im[2]={r_im0,r_im1};
-  double forgetting_factor=0.0; //in [0,1] 0 means a new channel every time, 1 means keep the same channel
 
 
-  uint8_t extended_prefix_flag=0,transmission_mode=1,n_tx_port=1,n_tx_phy=1,n_rx=2;
-  uint16_t Nid_cell=0;
+  uint8_t transmission_mode=1,n_tx_port=1,n_tx_phy=1,n_rx=2;
 
   int eNB_id = 0;
-  unsigned char mcs1=0,mcs2=0,mcs_i=0,dual_stream_UE = 0,awgn_flag=0,round;
+  unsigned char round;
   unsigned char i_mod = 2;
   unsigned short NB_RB;
-  uint16_t tdd_config=3;
 
 
   SCM_t channel_model=Rayleigh1;
@@ -602,18 +621,13 @@ int main(int argc, char **argv)
   FILE *input_fd=NULL;
   unsigned char input_file=0;
 
-  int n_frames;
-  int n_ch_rlz = 1;
   channel_desc_t *eNB2UE[4];
   //uint8_t num_pdcch_symbols_2=0;
-  uint8_t rx_sample_offset = 0;
   //char stats_buffer[4096];
   //int len;
-  uint8_t num_rounds = 4;//,fix_rounds=0;
 
   //int u;
   int n=0;
-  int abstx=0;
   //int iii;
 
   int ch_realization;
@@ -625,9 +639,8 @@ int main(int argc, char **argv)
   //  int bler;
   double blerr[4];
   short *uncoded_ber_bit=NULL;
-  uint8_t N_RB_DL=25,osf=1;
+  int osf=1;
   frame_t frame_type = FDD;
-  int xforms=0;
   FD_lte_phy_scope_ue *form_ue = NULL;
   char title[255];
 
@@ -640,16 +653,12 @@ int main(int argc, char **argv)
   //  time_stats_t ts;//,sts,usts;
   int avg_iter,iter_trials;
   int rballocset=0;
-  int print_perf=0;
-  int test_perf=0;
   int test_passed=0;
-  int dump_table=0;
 
   double effective_rate=0.0;
   char channel_model_input[10]="I";
 
   int TB0_active = 1;
-  uint32_t perfect_ce = 0;
 
   //  LTE_DL_UE_HARQ_t *dlsch0_ue_harq;
   //  LTE_DL_eNB_HARQ_t *dlsch0_eNB_harq;
@@ -657,20 +666,11 @@ int main(int argc, char **argv)
   uint8_t ue_category=4;
   uint32_t Nsoft;
   int sf;
-
-
-
   int CCE_table[800];
-
-  int threequarter_fs=0;
-
-
   opp_enabled=1; // to enable the time meas
 
   FILE *csv_fd=NULL;
-  char csv_fname[32];
-  int dci_flag=0;
-  int two_thread_flag=0;
+  char csv_fname[FILENAME_MAX];
   int DLSCH_RB_ALLOC = 0;
 
   int dci_received;
@@ -726,36 +726,95 @@ int main(int argc, char **argv)
   snr0 = 0;
   //  num_layers = 1;
   perfect_ce = 0;
+  static paramdef_t options[] = {
+    { "awgn", "Use AWGN channel and not multipath", PARAMFLAG_BOOL, strptr:NULL, defintval:0, TYPE_INT, 0, NULL, NULL },
+    { "Abstx", "Turns on calibration mode for abstraction.", PARAMFLAG_BOOL, iptr:&abstx,  defintval:0, TYPE_INT, 0 },
+    { "bTDD", "Set the tdd configuration mode",0, iptr:&tdd_config,  defintval:3, TYPE_INT, 0 },
+    { "BnbRBs", "The LTE bandwith in RBs (100 is 20MHz)",0, iptr:&N_RB_DL,  defintval:25, TYPE_INT, 0 },
+    { "cPdcch", "Number of PDCCH symbols",0, iptr:&num_pdcch_symbols,  defintval:1, TYPE_INT, 0 },
+    { "CnidCell", "The cell id ",0, iptr:&Nid_cell,  defintval:0, TYPE_INT, 0 },
+    { "dciFlag", "Transmit the DCI and compute its error statistics", PARAMFLAG_BOOL, iptr:&dci_flag,  defintval:0, TYPE_INT, 0 },
+    { "Dtdd", "Enable tdd", PARAMFLAG_BOOL,  strptr:NULL, defintval:0, TYPE_INT, 0, NULL, NULL },
+    { "eRounds", "Number of rounds",0, iptr:NULL,  defintval:25, TYPE_INT, 0 },
+    { "EsubSampling","three quarters sub-sampling",PARAMFLAG_BOOL, iptr:&threequarter_fs, defintval:0, TYPE_INT, 0 },
+    { "f_snr_step", "step size of SNR, default value is 1.",0, dblptr:&input_snr_step,  defdblval:1, TYPE_DOUBLE, 0 },
+    { "Forgetting", "forgetting factor (0 new channel every trial, 1 channel constant)",0, dblptr:&forgetting_factor,  defdblval:0.0, TYPE_DOUBLE, 0 },
+    { "input_file", "input IQ data file",0, iptr:NULL,  defintval:0, TYPE_INT, 0 },
+    { "Input_file_trch", " Input filename for TrCH data (binary)",0, iptr:NULL,  defintval:0, TYPE_INT, 0 },
+    { "WtwoThreads", "two_thread_flag", PARAMFLAG_BOOL, iptr:&two_thread_flag,  defintval:0, TYPE_INT, 0 },
+    { "lMuMimo", "offset_mumimo_llr_drange_fix",0, u8ptr:&offset_mumimo_llr_drange_fix,  defintval:0, TYPE_UINT8, 0 },
+    { "mcs1", "The MCS for TB 1", 0, iptr:&mcs1,  defintval:0, TYPE_INT, 0 },
+    { "Mcs2", "The MCS for TB 2", 0, iptr:&mcs2,  defintval:0, TYPE_INT, 0 },
+    { "Operf", "Set the percenatge of effective rate to testbench the modem performance (typically 30 and 70, range 1-100)",0, iptr:&test_perf,  defintval:0, TYPE_INT, 0 },
+    { "tmcs_i", "MCS of interfering UE",0, iptr:NULL,  defintval:0, TYPE_INT, 0 },
+    { "nb_frame", "number of frame in a test",0, iptr:&n_frames,  defintval:1, TYPE_INT, 0 },
+    { "offsetRxSample", "Sample offset for receiver", 0, iptr:&rx_sample_offset,  defintval:0, TYPE_INT, 0 },
+    { "rballocset", "ressource block allocation (see  section 7.1.6.3 in 36.213)",0, iptr:NULL,  defintval:0, TYPE_INT, 0 },
+    { "snr", "Starting SNR, runs from SNR to SNR+%.1fdB in steps of %.1fdB. If n_frames is 1 then just SNR is simulated and MATLAB/OCTAVE output is generated", dblptr:&snr0,  defdblval:-2.0, TYPE_DOUBLE, 0 },
+    { "wsnrInterrupt", "snr int ?", 0, dblptr:&snr_int,  defdblval:30, TYPE_DOUBLE, 0 },
+    { "N_ch_rlzN0", "Determines the number of Channel Realizations in Abstraction mode. Default value is 1",0, iptr:&n_ch_rlz,  defintval:1, TYPE_INT, 0 },
+    { "prefix_extended","Enable extended prefix", PARAMFLAG_BOOL, iptr:&extended_prefix_flag,  defintval:0, TYPE_INT, 0 },
+    { "RNumRound", "Number of HARQ rounds (fixed)",0, iptr:&num_rounds,  defintval:4, TYPE_INT, 0 },
+    { "Subframe", "subframe ",0, iptr:&subframe,  defintval:7, TYPE_INT, 0 },
+    { "Trnti", "rnti",0, u16ptr:&n_rnti,  defuintval:0x1234, TYPE_UINT16, 0 },
+    { "vi_mod", "i_mod",0, iptr:NULL,  defintval:0, TYPE_INT, 0 },
+    { "Performance", "Display CPU perfomance of each L1 piece", PARAMFLAG_BOOL,  iptr:&print_perf,  defintval:0, TYPE_INT, 0 },
+    { "q_tx_port", "Number of TX antennas ports used in eNB",0, iptr:NULL,  defintval:0, TYPE_INT, 0 },
+    { "uEdual", "Enables the Interference Aware Receiver for TM5 (default is normal receiver)",0, iptr:NULL,  defintval:0, TYPE_INT, 0 },
+    { "xTransmission","Transmission mode (1,2,6,7 for the moment)",0, iptr:NULL,  defintval:25, TYPE_INT, 0 },
+    { "yn_tx_phy","Number of TX antennas used in eNB",0, iptr:NULL,  defintval:25, TYPE_INT, 0 },
+    { "XForms", "Display the soft scope", PARAMFLAG_BOOL, iptr:&xforms,  defintval:0, TYPE_INT, 0 },
+    { "Yperfect_ce","Perfect CE", PARAMFLAG_BOOL, iptr:&perfect_ce,  defintval:0, TYPE_INT, 0 },
+    { "Zdump", "dump table",PARAMFLAG_BOOL,  iptr:&dump_table, defintval:0, TYPE_INT, 0 },
+    { "Loglvl", "log level",0, iptr:&loglvl,  defintval:OAILOG_DEBUG, TYPE_INT, 0 },
+    { "zn_rx", "Number of RX antennas used in UE",0, iptr:NULL,  defintval:2, TYPE_INT, 0 },
+    { "gchannel", "[A:M] Use 3GPP 25.814 SCM-A/B/C/D('A','B','C','D') or 36-101 EPA('E'), EVA ('F'),ETU('G') models (ignores delay spread and Ricean factor), Rayghleigh8 ('H'), Rayleigh1('I'), Rayleigh1_corr('J'), Rayleigh1_anticorr ('K'),  Rice8('L'), Rice1('M')",0, strptr:NULL,  defstrval:NULL, TYPE_STRING, 0 },
+    { "verbose", "display debug text", PARAMFLAG_BOOL,  iptr:&verbose, defintval:0, TYPE_INT, 0 },
+    { "help", "display help and exit", PARAMFLAG_BOOL,  iptr:&help, defintval:0, TYPE_INT, 0 },
+    { "", "",0,  iptr:NULL, defintval:0, TYPE_INT, 0 },
+  };
 
-  while ((c = getopt (argc, argv, "ahdpZDe:Em:n:o:s:f:t:c:g:r:F:x:q:y:z:AM:N:I:i:O:R:S:C:T:b:u:v:w:B:Pl:WXYL:")) != -1) {
-    switch (c) {
-    case 'a':
-      awgn_flag = 1;
-      channel_model = AWGN;
-      break;
-
-    case 'A':
-      abstx = 1;
-      break;
-
-    case 'b':
-      tdd_config=atoi(optarg);
-      break;
-
-    case 'B':
-      N_RB_DL=atoi(optarg);
-      break;
+  
+  struct option * long_options = parse_oai_options(options); 
+  
 
-    case 'c':
-      num_pdcch_symbols=atoi(optarg);
-      break;
+  int option_index;
+
+  int res;
+
+  while ((res=getopt_long_only(argc, argv, "", long_options, &option_index)) == 0) {
+    if (options[option_index].voidptr != NULL ) {
+      if (long_options[option_index].has_arg==no_argument)
+        *(bool *)options[option_index].iptr=1;
+      else switch (options[option_index].type) {
+          case TYPE_INT:
+            *(int *)options[option_index].iptr=atoi(optarg);
+            break;
+
+          case TYPE_DOUBLE:
+            *(double *)options[option_index].dblptr=atof(optarg);
+            break;
+	    
+	case TYPE_UINT8:
+	  *(uint8_t *)options[option_index].dblptr=atoi(optarg);
+	  break;
+	  	    
+	case TYPE_UINT16:
+	  *(uint16_t *)options[option_index].dblptr=atoi(optarg);
+	  break;
+	  
+	default:
+            printf("not decoded type.\n");
+            exit(1);
+        }
 
-    case 'C':
-      Nid_cell = atoi(optarg);
-      break;
+      continue;
+    }
 
-    case 'd':
-      dci_flag = 1;
+    switch (long_options[option_index].name[0]) {
+    case 'a':
+      awgn_flag = 1;
+      channel_model = AWGN;
       break;
 
     case 'D':
@@ -768,18 +827,6 @@ int main(int argc, char **argv)
       TPC = atoi(optarg);
       break;
 
-    case 'E':
-      threequarter_fs=1;
-      break;
-
-    case 'f':
-      input_snr_step= atof(optarg);
-      break;
-
-    case 'F':
-      forgetting_factor = atof(optarg);
-      break;
-
     case 'i':
       input_fd = fopen(optarg,"r");
       input_file=1;
@@ -791,138 +838,50 @@ int main(int argc, char **argv)
       input_trch_file=1;
       break;
 
-    case 'W':
-      two_thread_flag = 1;
-      break;
-    case 'l':
-      offset_mumimo_llr_drange_fix=atoi(optarg);
-      break;
-
-    case 'm':
-      mcs1 = atoi(optarg);
-      break;
-
-    case 'M':
-      mcs2 = atoi(optarg);
-      break;
-
-    case 'O':
-      test_perf=atoi(optarg);
-      //print_perf =1;
-      break;
-
     case 't':
       mcs_i = atoi(optarg);
       i_mod = get_Qm(mcs_i);
       break;
 
-    case 'n':
-      n_frames = atoi(optarg);
-      break;
-
-
-    case 'o':
-      rx_sample_offset = atoi(optarg);
-      break;
-
     case 'r':
       DLSCH_RB_ALLOC = atoi(optarg);
       rballocset = 1;
       break;
 
-    case 's':
-      snr0 = atof(optarg);
-      break;
-
-    case 'w':
-      snr_int = atof(optarg);
-      break;
-
-
-    case 'N':
-      n_ch_rlz= atof(optarg);
-      break;
-
-    case 'p':
-      extended_prefix_flag=1;
-      break;
-
     case 'g':
-      memcpy(channel_model_input,optarg,10);
-
-      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;
-
-      case 'H':
-        channel_model=Rayleigh8;
-        break;
-
-      case 'I':
-        channel_model=Rayleigh1;
-        break;
-
-      case 'J':
-        channel_model=Rayleigh1_corr;
-        break;
-
-      case 'K':
-        channel_model=Rayleigh1_anticorr;
-        break;
-
-      case 'L':
-        channel_model=Rice8;
-        break;
-
-      case 'M':
-        channel_model=Rice1;
-        break;
+    strncpy(channel_model_input,optarg,9);
+    struct tmp {
+      char opt;
+      int m;
+      int M;
+    }
+    tmp[]= {
+      {'A',SCM_A,2},
+          {'B',SCM_B,3},
+          {'C',SCM_C,4},
+          {'D',SCM_D,5},
+          {'E',EPA,6},
+          {'F',EVA,6},
+          {'G',ETU,8},
+          {'H',Rayleigh8,9},
+          {'I',Rayleigh1,10},
+          {'J',Rayleigh1_corr,11},
+          {'K',Rayleigh1_anticorr,12},
+          {'L',Rice8,13},
+          {'M',Rice1,14},
+          {'N',AWGN,1},
+          {0,0,0}
+        };
+        struct tmp *ptr;
+
+        for (ptr=tmp; ptr->opt!=0; ptr++)
+          if ( ptr->opt == optarg[0] ) {
+            channel_model=ptr->m;
+            break;
+          }
 
-      case 'N':
-        channel_model=AWGN;
+        AssertFatal(ptr->opt != 0, "Unsupported channel model: %s !\n", optarg );
         break;
-      default:
-        printf("Unsupported channel model!\n");
-        exit(-1);
-      }
-
-      break;
-    case 'R':
-      num_rounds=atoi(optarg);
-      break;
-
-    case 'S':
-      subframe=atoi(optarg);
-      break;
-
-    case 'T':
-      n_rnti=atoi(optarg);
-      break;
 
     case 'u':
       dual_stream_UE=1;
@@ -945,10 +904,6 @@ int main(int argc, char **argv)
 
       break;
 
-    case 'P':
-      print_perf=1;
-      break;
-
     case 'q':
       n_tx_port=atoi(optarg);
 
@@ -999,15 +954,6 @@ int main(int argc, char **argv)
       }
 
       break;
-      break;
-
-    case 'X':
-      xforms=1;
-      break;
-
-    case 'Y':
-      perfect_ce=1;
-      break;
 
     case 'z':
       n_rx=atoi(optarg);
@@ -1019,51 +965,23 @@ int main(int argc, char **argv)
 
       break;
 
-    case 'Z':
-      dump_table=1;
-      break;
-
-    case 'L':
-      loglvl = atoi(optarg);
-      break;
-
-    case 'h':
     default:
-      printf("%s -h(elp) -a(wgn on) -d(ci decoding on) -p(extended prefix on) -m mcs1 -M mcs2 -n n_frames -s snr0 -x transmission mode (1,2,5,6,7) -y TXant -z RXant -I trch_file\n",argv[0]);
-      printf("-h This message\n");
-      printf("-a Use AWGN channel and not multipath\n");
-      printf("-c Number of PDCCH symbols\n");
-      printf("-m MCS1 for TB 1\n");
-      printf("-M MCS2 for TB 2\n");
-      printf("-d Transmit the DCI and compute its error statistics\n");
-      printf("-p Use extended prefix mode\n");
-      printf("-n Number of frames to simulate\n");
-      printf("-o Sample offset for receiver\n");
-      printf("-s Starting SNR, runs from SNR to SNR+%.1fdB in steps of %.1fdB. If n_frames is 1 then just SNR is simulated and MATLAB/OCTAVE output is generated\n", snr_int, snr_step);
-      printf("-f step size of SNR, default value is 1.\n");
-      printf("-C cell id\n");
-      printf("-S subframe\n");
-      printf("-D use TDD mode\n");
-      printf("-b TDD config\n");
-      printf("-B bandwidth configuration (in number of ressource blocks): 6, 25, 50, 100\n");
-      printf("-r ressource block allocation (see  section 7.1.6.3 in 36.213\n");
-      printf("-g [A:M] Use 3GPP 25.814 SCM-A/B/C/D('A','B','C','D') or 36-101 EPA('E'), EVA ('F'),ETU('G') models (ignores delay spread and Ricean factor), Rayghleigh8 ('H'), Rayleigh1('I'), Rayleigh1_corr('J'), Rayleigh1_anticorr ('K'), Rice8('L'), Rice1('M')\n");
-      printf("-F forgetting factor (0 new channel every trial, 1 channel constant\n");
-      printf("-x Transmission mode (1,2,6,7 for the moment)\n");
-      printf("-q Number of TX antennas ports used in eNB\n");
-      printf("-y Number of TX antennas used in eNB\n");
-      printf("-z Number of RX antennas used in UE\n");
-      printf("-t MCS of interfering UE\n");
-      printf("-R Number of HARQ rounds (fixed)\n");
-      printf("-A Turns on calibration mode for abstraction.\n");
-      printf("-N Determines the number of Channel Realizations in Abstraction mode. Default value is 1. \n");
-      printf("-O Set the percenatge of effective rate to testbench the modem performance (typically 30 and 70, range 1-100) \n");
-      printf("-I Input filename for TrCH data (binary)\n");
-      printf("-u Enables the Interference Aware Receiver for TM5 (default is normal receiver)\n");
+      printf("Wrong option: %s\n",long_options[option_index].name);
       exit(1);
       break;
     }
   }
+
+  if ( res != -1 ) {
+    printf("A wrong option has been found\n");
+    exit(1);
+  }
+
+  if (help || verbose )
+     display_options_values(options, true);
+  if (help)
+    exit(0);
+  
   set_parallel_conf("PARALLEL_RU_L1_TRX_SPLIT");
   set_worker_conf("WORKER_ENABLE");
 
@@ -1073,8 +991,10 @@ int main(int argc, char **argv)
   AssertFatal(load_configmodule(argc,argv) != NULL,
 	      "cannot load configuration module, exiting\n");
   logInit();
+  set_glog_onlinelog(true);
   // enable these lines if you need debug info
   set_glog(loglvl);
+  SET_LOG_DEBUG(UE_TIMING);
   // moreover you need to init itti with the following line
   // however itti will catch all signals, so ctrl-c won't work anymore
   // alternatively you can disable ITTI completely in CMakeLists.txt
@@ -1522,9 +1442,17 @@ int main(int argc, char **argv)
       reset_meas(&eNB->dlsch_interleaving_stats);
       reset_meas(&eNB->dlsch_rate_matching_stats);
       reset_meas(&eNB->dlsch_turbo_encoding_stats);
-
-      reset_meas(&UE->phy_proc_rx[UE->current_thread_id[subframe]]); // total UE rx
+      for (int i=0; i<RX_NB_TH; i++) {
+	reset_meas(&UE->phy_proc_rx[i]); // total UE rx
+	reset_meas(&UE->ue_front_end_stat[i]);
+        reset_meas(&UE->pdsch_procedures_stat[i]);
+	reset_meas(&UE->dlsch_procedures_stat[i]);
+	reset_meas(&UE->dlsch_decoding_stats[i]);
+	reset_meas(&UE->dlsch_llr_stats_parallelization[i][0]);
+	reset_meas(&UE->dlsch_llr_stats_parallelization[i][1]);
+      }
       reset_meas(&UE->ofdm_demod_stats);
+      reset_meas(&UE->crnti_procedures_stats);
       reset_meas(&UE->dlsch_channel_estimation_stats);
       reset_meas(&UE->dlsch_freq_offset_estimation_stats);
       reset_meas(&UE->rx_dft_stats);
@@ -1541,25 +1469,21 @@ int main(int argc, char **argv)
       reset_meas(&UE->dlsch_tc_intl1_stats);
       reset_meas(&UE->dlsch_tc_intl2_stats);
       // initialization
-      struct list time_vector_tx;
-      initialize(&time_vector_tx);
-      struct list time_vector_tx_ifft;
-      initialize(&time_vector_tx_ifft);
-      struct list time_vector_tx_mod;
-      initialize(&time_vector_tx_mod);
-      struct list time_vector_tx_enc;
-      initialize(&time_vector_tx_enc);
-
-      struct list time_vector_rx;
-      initialize(&time_vector_rx);
-      struct list time_vector_rx_fft;
-      initialize(&time_vector_rx_fft);
-      struct list time_vector_rx_demod;
-      initialize(&time_vector_rx_demod);
-      struct list time_vector_rx_dec;
-      initialize(&time_vector_rx_dec);
-
-
+            // initialization
+      varArray_t *table_tx=initVarArray(1000,sizeof(double));
+      varArray_t *table_tx_ifft=initVarArray(1000,sizeof(double));
+      varArray_t *table_tx_mod=initVarArray(1000,sizeof(double));
+      varArray_t *table_tx_enc=initVarArray(1000,sizeof(double));
+      varArray_t *table_rx=initVarArray(1000,sizeof(double));
+      time_stats_t phy_proc_rx_tot;
+      time_stats_t pdsch_procedures_tot;
+      time_stats_t dlsch_procedures_tot;
+      time_stats_t dlsch_decoding_tot;
+      time_stats_t dlsch_llr_tot;
+      time_stats_t ue_front_end_tot;
+      varArray_t *table_rx_fft=initVarArray(1000,sizeof(double));
+      varArray_t *table_rx_demod=initVarArray(1000,sizeof(double));
+      varArray_t *table_rx_dec=initVarArray(1000,sizeof(double));
 
       for (trials = 0; trials<n_frames; trials++) {
 	//printf("Trial %d\n",trials);
@@ -2004,120 +1928,53 @@ int main(int argc, char **argv)
         /* calculate the total processing time for each packet,
          * get the max, min, and number of packets that exceed t>2000us
          */
-        double t_tx = (double)eNB->phy_proc_tx.p_time/cpu_freq_GHz/1000.0;
-        double t_tx_ifft = (double)eNB->ofdm_mod_stats.p_time/cpu_freq_GHz/1000.0;
-        double t_tx_mod = (double)eNB->dlsch_modulation_stats.p_time/cpu_freq_GHz/1000.0;
-        double t_tx_enc = (double)eNB->dlsch_encoding_stats.p_time/cpu_freq_GHz/1000.0;
-
-
-        double t_rx = (double)UE->phy_proc_rx[UE->current_thread_id[subframe]].p_time/cpu_freq_GHz/1000.0;
-        double t_rx_fft = (double)UE->ofdm_demod_stats.p_time/cpu_freq_GHz/1000.0;
-        double t_rx_demod = (double)UE->dlsch_rx_pdcch_stats.p_time/cpu_freq_GHz/1000.0;
-        double t_rx_dec = (double)UE->dlsch_decoding_stats[UE->current_thread_id[subframe]].p_time/cpu_freq_GHz/1000.0;
-
-        if (t_tx > t_tx_max)
-          t_tx_max = t_tx;
-
-        if (t_tx < t_tx_min)
-          t_tx_min = t_tx;
-
-        if (t_rx > t_rx_max)
-          t_rx_max = t_rx;
-
-        if (t_rx < t_rx_min)
-          t_rx_min = t_rx;
-
-        if (t_tx > 2000)
+	double t_tx = inMicroS(eNB->phy_proc_tx.p_time);
+        double t_tx_ifft = inMicroS(eNB->ofdm_mod_stats.p_time);
+        double t_rx = inMicroS(UE->phy_proc_rx[UE->current_thread_id[subframe]].p_time);
+	sumUpStats(&phy_proc_rx_tot, UE->phy_proc_rx, UE->current_thread_id[subframe]);
+	sumUpStats(&ue_front_end_tot, UE->ue_front_end_stat, UE->current_thread_id[subframe]);
+	sumUpStats(&pdsch_procedures_tot, UE->pdsch_procedures_stat, UE->current_thread_id[subframe]);	
+	sumUpStats(&dlsch_procedures_tot, UE->dlsch_procedures_stat, UE->current_thread_id[subframe]);
+	sumUpStats(&dlsch_decoding_tot, UE->dlsch_decoding_stats, UE->current_thread_id[subframe]);
+	sumUpStatsSlot(&dlsch_llr_tot, UE->dlsch_llr_stats_parallelization, UE->current_thread_id[subframe]);
+
+
+	double t_rx_fft = inMicroS(UE->ofdm_demod_stats.p_time);
+        double t_rx_demod = inMicroS(UE->dlsch_rx_pdcch_stats.p_time);
+        double t_rx_dec = inMicroS(UE->dlsch_decoding_stats[UE->current_thread_id[subframe]].p_time);
+
+        if (t_tx > 2000 )// 2ms is too much time for a subframe
           n_tx_dropped++;
-
-        if (t_rx > 2000)
+	
+        if (t_rx > 2000 )
           n_rx_dropped++;
-
-        push_front(&time_vector_tx, t_tx);
-        push_front(&time_vector_tx_ifft, t_tx_ifft);
-        push_front(&time_vector_tx_mod, t_tx_mod);
-        push_front(&time_vector_tx_enc, t_tx_enc);
-
-        push_front(&time_vector_rx, t_rx);
-        push_front(&time_vector_rx_fft, t_rx_fft);
-        push_front(&time_vector_rx_demod, t_rx_demod);
-        push_front(&time_vector_rx_dec, t_rx_dec);
-
+	
+	appendVarArray(table_tx, &t_tx);
+        appendVarArray(table_tx_ifft, &t_tx_ifft);
+        appendVarArray(table_rx, &t_rx );
+        appendVarArray(table_rx_fft, &t_rx_fft );
+        appendVarArray(table_rx_demod, &t_rx_demod );
+        appendVarArray(table_rx_dec, &t_rx_dec );
 
       }   //trials
 
       // round_trials[0]: number of code word : goodput the protocol
-      double table_tx[time_vector_tx.size];
-      totable(table_tx, &time_vector_tx);
-      double table_tx_ifft[time_vector_tx_ifft.size];
-      totable(table_tx_ifft, &time_vector_tx_ifft);
-      double table_tx_mod[time_vector_tx_mod.size];
-      totable(table_tx_mod, &time_vector_tx_mod);
-      double table_tx_enc[time_vector_tx_enc.size];
-      totable(table_tx_enc, &time_vector_tx_enc);
-
-      double table_rx[time_vector_rx.size];
-      totable(table_rx, &time_vector_rx);
-      double table_rx_fft[time_vector_rx_fft.size];
-      totable(table_rx_fft, &time_vector_rx_fft);
-      double table_rx_demod[time_vector_rx_demod.size];
-      totable(table_rx_demod, &time_vector_rx_demod);
-      double table_rx_dec[time_vector_rx_dec.size];
-      totable(table_rx_dec, &time_vector_rx_dec);
-
-
       // sort table
-      qsort (table_tx, time_vector_tx.size, sizeof(double), &compare);
-      qsort (table_rx, time_vector_rx.size, sizeof(double), &compare);
+      qsort (dataArray(table_tx), table_tx->size, table_tx->atomSize, &cmpdouble);
+      qsort (dataArray(table_tx_ifft), table_tx_ifft->size, table_tx_ifft->atomSize, &cmpdouble);
+      qsort (dataArray(table_tx_mod), table_tx_mod->size, table_tx_mod->atomSize, &cmpdouble);
+      qsort (dataArray(table_tx_enc), table_tx_enc->size, table_tx_enc->atomSize, &cmpdouble);
+      qsort (dataArray(table_rx), table_rx->size, table_rx->atomSize, &cmpdouble);
+      qsort (dataArray(table_rx_fft), table_rx_fft->size, table_rx_fft->atomSize, &cmpdouble);
+      qsort (dataArray(table_rx_demod), table_rx_demod->size, table_rx_demod->atomSize, &cmpdouble);
+      qsort (dataArray(table_rx_dec), table_rx_dec->size, table_rx_dec->atomSize, &cmpdouble);
 
       if (dump_table == 1 ) {
         set_component_filelog(SIM);  // file located in /tmp/usim.txt
-        LOG_UDUMPMSG(SIM,table_tx,time_vector_tx.size,LOG_DUMP_DOUBLE,"The transmitter raw data: \n");
-        LOG_UDUMPMSG(SIM,table_rx,time_vector_rx.size,LOG_DUMP_DOUBLE,"Thereceiver raw data: \n");
+        LOG_UDUMPMSG(SIM,table_tx,table_tx->size,LOG_DUMP_DOUBLE,"The transmitter raw data: \n");
+        LOG_UDUMPMSG(SIM,table_rx,table_rx->size,LOG_DUMP_DOUBLE,"Thereceiver raw data: \n");
       }
 
-      double tx_median = table_tx[time_vector_tx.size/2];
-      double tx_q1 = table_tx[time_vector_tx.size/4];
-      double tx_q3 = table_tx[3*time_vector_tx.size/4];
-
-      double tx_ifft_median = table_tx_ifft[time_vector_tx_ifft.size/2];
-      double tx_ifft_q1 = table_tx_ifft[time_vector_tx_ifft.size/4];
-      double tx_ifft_q3 = table_tx_ifft[3*time_vector_tx_ifft.size/4];
-
-      double tx_mod_median = table_tx_mod[time_vector_tx_mod.size/2];
-      double tx_mod_q1 = table_tx_mod[time_vector_tx_mod.size/4];
-      double tx_mod_q3 = table_tx_mod[3*time_vector_tx_mod.size/4];
-
-      double tx_enc_median = table_tx_enc[time_vector_tx_enc.size/2];
-      double tx_enc_q1 = table_tx_enc[time_vector_tx_enc.size/4];
-      double tx_enc_q3 = table_tx_enc[3*time_vector_tx_enc.size/4];
-
-      double rx_median = table_rx[time_vector_rx.size/2];
-      double rx_q1 = table_rx[time_vector_rx.size/4];
-      double rx_q3 = table_rx[3*time_vector_rx.size/4];
-
-      double rx_fft_median = table_rx_fft[time_vector_rx_fft.size/2];
-      double rx_fft_q1 = table_rx_fft[time_vector_rx_fft.size/4];
-      double rx_fft_q3 = table_rx_fft[3*time_vector_rx_fft.size/4];
-
-      double rx_demod_median = table_rx_demod[time_vector_rx_demod.size/2];
-      double rx_demod_q1 = table_rx_demod[time_vector_rx_demod.size/4];
-      double rx_demod_q3 = table_rx_demod[3*time_vector_rx_demod.size/4];
-
-      double rx_dec_median = table_rx_dec[time_vector_rx_dec.size/2];
-      double rx_dec_q1 = table_rx_dec[time_vector_rx_dec.size/4];
-      double rx_dec_q3 = table_rx_dec[3*time_vector_rx_dec.size/4];
-
-      double std_phy_proc_tx=0;
-      double std_phy_proc_tx_ifft=0;
-      double std_phy_proc_tx_mod=0;
-      double std_phy_proc_tx_enc=0;
-
-      double std_phy_proc_rx=0;
-      double std_phy_proc_rx_fft=0;
-      double std_phy_proc_rx_demod=0;
-      double std_phy_proc_rx_dec=0;
-
       effective_rate = 1.0-((double)(errs[0]+errs[1]+errs[2]+errs[3])/((double)round_trials[0] + round_trials[1] + round_trials[2] + round_trials[3]));
 
       printf("\n**********************SNR = %f dB (tx_lev %f)**************************\n",
@@ -2149,108 +2006,49 @@ int main(int argc, char **argv)
              (double)eNB->dlsch[0][0]->harq_processes[0]->TBS,
              (1.0*(round_trials[0]-errs[0])+2.0*(round_trials[1]-errs[1])+3.0*(round_trials[2]-errs[2])+4.0*(round_trials[3]-errs[3]))/((double)round_trials[0]));
 
+      double timeBase=1/(1000*cpu_freq_GHz);
       if (print_perf==1) {
-        printf("eNB TX function statistics (per 1ms subframe)\n\n");
-        std_phy_proc_tx = sqrt((double)eNB->phy_proc_tx.diff_square/pow(cpu_freq_GHz,2)/pow(1000,
-                               2)/eNB->phy_proc_tx.trials - pow((double)eNB->phy_proc_tx.diff/eNB->phy_proc_tx.trials/cpu_freq_GHz/1000,2));
-        std_phy_proc_tx_ifft = sqrt((double)eNB->ofdm_mod_stats.diff_square/pow(cpu_freq_GHz,2)/pow(1000,
-                                    2)/eNB->ofdm_mod_stats.trials - pow((double)eNB->ofdm_mod_stats.diff/eNB->ofdm_mod_stats.trials/cpu_freq_GHz/1000,2));
-        printf("OFDM_mod time                     :%f us (%d trials)\n",(double)eNB->ofdm_mod_stats.diff/eNB->ofdm_mod_stats.trials/cpu_freq_GHz/1000.0,eNB->ofdm_mod_stats.trials);
-        printf("|__ Statistcs                           std: %fus median %fus q1 %fus q3 %fus \n",std_phy_proc_tx_ifft, tx_ifft_median, tx_ifft_q1, tx_ifft_q3);
-        printf("Total PHY proc tx                 :%f us (%d trials)\n",(double)eNB->phy_proc_tx.diff/eNB->phy_proc_tx.trials/cpu_freq_GHz/1000.0,eNB->phy_proc_tx.trials);
-        printf("|__ Statistcs                           std: %fus max: %fus min: %fus median %fus q1 %fus q3 %fus n_dropped: %d packet \n",std_phy_proc_tx, t_tx_max, t_tx_min, tx_median, tx_q1, tx_q3,
-               n_tx_dropped);
-
-        std_phy_proc_tx_mod = sqrt((double)eNB->dlsch_modulation_stats.diff_square/pow(cpu_freq_GHz,2)/pow(1000,
-                                   2)/eNB->dlsch_modulation_stats.trials - pow((double)eNB->dlsch_modulation_stats.diff/eNB->dlsch_modulation_stats.trials/cpu_freq_GHz/1000,2));
-        printf("DLSCH modulation time             :%f us (%d trials)\n",(double)eNB->dlsch_modulation_stats.diff/eNB->dlsch_modulation_stats.trials/cpu_freq_GHz/1000.0,
-               eNB->dlsch_modulation_stats.trials);
-        printf("|__ Statistcs                           std: %fus median %fus q1 %fus q3 %fus \n",std_phy_proc_tx_mod, tx_mod_median, tx_mod_q1, tx_mod_q3);
-        printf("DLSCH scrambling time             :%f us (%d trials)\n",(double)eNB->dlsch_scrambling_stats.diff/eNB->dlsch_scrambling_stats.trials/cpu_freq_GHz/1000.0,
-               eNB->dlsch_scrambling_stats.trials);
-        std_phy_proc_tx_enc = sqrt((double)eNB->dlsch_encoding_stats.diff_square/pow(cpu_freq_GHz,2)/pow(1000,
-                                   2)/eNB->dlsch_encoding_stats.trials - pow((double)eNB->dlsch_encoding_stats.diff/eNB->dlsch_encoding_stats.trials/cpu_freq_GHz/1000,2));
-        printf("DLSCH encoding time               :%f us (%d trials)\n",(double)eNB->dlsch_encoding_stats.diff/eNB->dlsch_encoding_stats.trials/cpu_freq_GHz/1000.0,
-               eNB->dlsch_modulation_stats.trials);
-        printf("|__ Statistcs                           std: %fus median %fus q1 %fus q3 %fus \n",std_phy_proc_tx_enc, tx_enc_median, tx_enc_q1, tx_enc_q3);
-        printf("|__ DLSCH turbo encoding time         :%f us (%d trials)\n",
-               ((double)eNB->dlsch_turbo_encoding_stats.trials/eNB->dlsch_encoding_stats.trials)*(double)
-               eNB->dlsch_turbo_encoding_stats.diff/eNB->dlsch_turbo_encoding_stats.trials/cpu_freq_GHz/1000.0,eNB->dlsch_turbo_encoding_stats.trials);
-        printf("|__ DLSCH rate-matching time          :%f us (%d trials)\n",
-               ((double)eNB->dlsch_rate_matching_stats.trials/eNB->dlsch_encoding_stats.trials)*(double)
-               eNB->dlsch_rate_matching_stats.diff/eNB->dlsch_rate_matching_stats.trials/cpu_freq_GHz/1000.0,eNB->dlsch_rate_matching_stats.trials);
-        printf("|__ DLSCH sub-block interleaving time :%f us (%d trials)\n",
-               ((double)eNB->dlsch_interleaving_stats.trials/eNB->dlsch_encoding_stats.trials)*(double)
-               eNB->dlsch_interleaving_stats.diff/eNB->dlsch_interleaving_stats.trials/cpu_freq_GHz/1000.0,eNB->dlsch_interleaving_stats.trials);
-
-        printf("\n\nUE RX function statistics (per 1ms subframe)\n\n");
-        std_phy_proc_rx = sqrt((double)UE->phy_proc_rx[UE->current_thread_id[subframe]].diff_square/pow(cpu_freq_GHz,2)/pow(1000,
-                               2)/UE->phy_proc_rx[UE->current_thread_id[subframe]].trials - pow((double)UE->phy_proc_rx[UE->current_thread_id[subframe]].diff/UE->phy_proc_rx[UE->current_thread_id[subframe]].trials/cpu_freq_GHz/1000,2));
-        printf("Total PHY proc rx                                   :%f us (%d trials)\n",(double)UE->phy_proc_rx[UE->current_thread_id[subframe]].diff/UE->phy_proc_rx[UE->current_thread_id[subframe]].trials/cpu_freq_GHz/1000.0,
-               UE->phy_proc_rx[UE->current_thread_id[subframe]].trials*2/3);
-        printf("|__Statistcs                                            std: %fus max: %fus min: %fus median %fus q1 %fus q3 %fus n_dropped: %d packet \n", std_phy_proc_rx, t_rx_max, t_rx_min, rx_median,
-               rx_q1, rx_q3, n_rx_dropped);
-        std_phy_proc_rx_fft = sqrt((double)UE->ofdm_demod_stats.diff_square/pow(cpu_freq_GHz,2)/pow(1000,
-                                   2)/UE->ofdm_demod_stats.trials - pow((double)UE->ofdm_demod_stats.diff/UE->ofdm_demod_stats.trials/cpu_freq_GHz/1000,2));
-        printf("DLSCH OFDM demodulation and channel_estimation time :%f us (%d trials)\n",(nsymb)*(double)UE->ofdm_demod_stats.diff/UE->ofdm_demod_stats.trials/cpu_freq_GHz/1000.0,
-               UE->ofdm_demod_stats.trials*2/3);
-        printf("|__ Statistcs                           std: %fus median %fus q1 %fus q3 %fus \n",std_phy_proc_rx_fft, rx_fft_median, rx_fft_q1, rx_fft_q3);
-        printf("|__ DLSCH rx dft                                        :%f us (%d trials)\n",
-               (nsymb*UE->frame_parms.nb_antennas_rx)*(double)UE->rx_dft_stats.diff/UE->rx_dft_stats.trials/cpu_freq_GHz/1000.0,UE->rx_dft_stats.trials*2/3);
-        printf("|__ DLSCH channel estimation time                       :%f us (%d trials)\n",
-               (4.0)*(double)UE->dlsch_channel_estimation_stats.diff/UE->dlsch_channel_estimation_stats.trials/cpu_freq_GHz/1000.0,UE->dlsch_channel_estimation_stats.trials*2/3);
-        printf("|__ DLSCH frequency offset estimation time              :%f us (%d trials)\n",
-               (4.0)*(double)UE->dlsch_freq_offset_estimation_stats.diff/UE->dlsch_freq_offset_estimation_stats.trials/cpu_freq_GHz/1000.0,
-               UE->dlsch_freq_offset_estimation_stats.trials*2/3);
-        printf("DLSCH rx pdcch                                       :%f us (%d trials)\n",(double)UE->dlsch_rx_pdcch_stats.diff/UE->dlsch_rx_pdcch_stats.trials/cpu_freq_GHz/1000.0,
-               UE->dlsch_rx_pdcch_stats.trials);
-        std_phy_proc_rx_demod = sqrt((double)UE->dlsch_llr_stats.diff_square/pow(cpu_freq_GHz,2)/pow(1000,
-                                     2)/UE->dlsch_llr_stats.trials - pow((double)UE->dlsch_llr_stats.diff/UE->dlsch_llr_stats.trials/cpu_freq_GHz/1000,2));
-        printf("DLSCH Channel Compensation and LLR generation time  :%f us (%d trials)\n",(14-num_pdcch_symbols)*(double)UE->dlsch_llr_stats.diff/UE->dlsch_llr_stats.trials/cpu_freq_GHz/1000.0,
-               UE->dlsch_llr_stats.trials/3);
-        printf("|__ Statistcs                           std: %fus median %fus q1 %fus q3 %fus \n",std_phy_proc_rx_demod, rx_demod_median, rx_demod_q1, rx_demod_q3);
-        printf("DLSCH unscrambling time                             :%f us (%d trials)\n",(double)UE->dlsch_unscrambling_stats.diff/UE->dlsch_unscrambling_stats.trials/cpu_freq_GHz/1000.0,
-               UE->dlsch_unscrambling_stats.trials);
-        std_phy_proc_rx_dec = sqrt((double)UE->dlsch_decoding_stats[UE->current_thread_id[subframe]].diff_square/pow(cpu_freq_GHz,2)/pow(1000,
-                                   2)/UE->dlsch_decoding_stats[UE->current_thread_id[subframe]].trials - pow((double)UE->dlsch_decoding_stats[UE->current_thread_id[subframe]].diff/UE->dlsch_decoding_stats[UE->current_thread_id[subframe]].trials/cpu_freq_GHz/1000,2));
-        printf("DLSCH Decoding time (%02.2f Mbit/s, avg iter %1.2f)    :%f us (%d trials, max %f)\n",
-               eNB->dlsch[0][0]->harq_processes[0]->TBS/1000.0,(double)avg_iter/iter_trials,
-               (double)UE->dlsch_decoding_stats[UE->current_thread_id[subframe]].diff/UE->dlsch_decoding_stats[UE->current_thread_id[subframe]].trials/cpu_freq_GHz/1000.0,UE->dlsch_decoding_stats[UE->current_thread_id[subframe]].trials,
-               (double)UE->dlsch_decoding_stats[UE->current_thread_id[subframe]].max/cpu_freq_GHz/1000.0);
-        printf("|__ Statistcs                           std: %fus median %fus q1 %fus q3 %fus \n",std_phy_proc_rx_dec, rx_dec_median, rx_dec_q1, rx_dec_q3);
-        printf("|__ DLSCH Rate Unmatching                               :%f us (%d trials)\n",
-               (double)UE->dlsch_rate_unmatching_stats.diff/UE->dlsch_rate_unmatching_stats.trials/cpu_freq_GHz/1000.0,UE->dlsch_rate_unmatching_stats.trials);
-        printf("|__ DLSCH Turbo Decoding(%d bits)                       :%f us (%d trials)\n",
-               UE->dlsch[UE->current_thread_id[subframe]][0][0]->harq_processes[0]->Cminus ? UE->dlsch[UE->current_thread_id[subframe]][0][0]->harq_processes[0]->Kminus : UE->dlsch[UE->current_thread_id[subframe]][0][0]->harq_processes[0]->Kplus,
-               (double)UE->dlsch_turbo_decoding_stats.diff/UE->dlsch_turbo_decoding_stats.trials/cpu_freq_GHz/1000.0,UE->dlsch_turbo_decoding_stats.trials);
-        printf("    |__ init                                            %f us (cycles/iter %f, %d trials)\n",
-               (double)UE->dlsch_tc_init_stats.diff/UE->dlsch_tc_init_stats.trials/cpu_freq_GHz/1000.0,
-               (double)UE->dlsch_tc_init_stats.diff/UE->dlsch_tc_init_stats.trials/((double)avg_iter/iter_trials),
-               UE->dlsch_tc_init_stats.trials);
-        printf("    |__ alpha                                           %f us (cycles/iter %f, %d trials)\n",
-               (double)UE->dlsch_tc_alpha_stats.diff/UE->dlsch_tc_alpha_stats.trials/cpu_freq_GHz/1000.0,
-               (double)UE->dlsch_tc_alpha_stats.diff/UE->dlsch_tc_alpha_stats.trials*2,
-               UE->dlsch_tc_alpha_stats.trials);
-        printf("    |__ beta                                            %f us (cycles/iter %f,%d trials)\n",
-               (double)UE->dlsch_tc_beta_stats.diff/UE->dlsch_tc_beta_stats.trials/cpu_freq_GHz/1000.0,
-               (double)UE->dlsch_tc_beta_stats.diff/UE->dlsch_tc_beta_stats.trials*2,
-               UE->dlsch_tc_beta_stats.trials);
-        printf("    |__ gamma                                           %f us (cycles/iter %f,%d trials)\n",
-               (double)UE->dlsch_tc_gamma_stats.diff/UE->dlsch_tc_gamma_stats.trials/cpu_freq_GHz/1000.0,
-               (double)UE->dlsch_tc_gamma_stats.diff/UE->dlsch_tc_gamma_stats.trials*2,
-               UE->dlsch_tc_gamma_stats.trials);
-        printf("    |__ ext                                             %f us (cycles/iter %f,%d trials)\n",
-               (double)UE->dlsch_tc_ext_stats.diff/UE->dlsch_tc_ext_stats.trials/cpu_freq_GHz/1000.0,
-               (double)UE->dlsch_tc_ext_stats.diff/UE->dlsch_tc_ext_stats.trials*2,
-               UE->dlsch_tc_ext_stats.trials);
-        printf("    |__ intl1                                           %f us (cycles/iter %f,%d trials)\n",
-               (double)UE->dlsch_tc_intl1_stats.diff/UE->dlsch_tc_intl1_stats.trials/cpu_freq_GHz/1000.0,
-               (double)UE->dlsch_tc_intl1_stats.diff/UE->dlsch_tc_intl1_stats.trials,
-               UE->dlsch_tc_intl1_stats.trials);
-        printf("    |__ intl2+HD+CRC                                    %f us (cycles/iter %f,%d trials)\n",
-               (double)UE->dlsch_tc_intl2_stats.diff/UE->dlsch_tc_intl2_stats.trials/cpu_freq_GHz/1000.0,
-               (double)UE->dlsch_tc_intl2_stats.diff/UE->dlsch_tc_intl2_stats.trials,
-               UE->dlsch_tc_intl2_stats.trials);
+        printf("\neNB TX function statistics (per 1ms subframe)\n");
+	printDistribution(&eNB->phy_proc_tx,table_tx,"PHY proc tx");
+	printStatIndent(&eNB->dlsch_common_and_dci,"DL common channels and dci time");
+	printStatIndent(&eNB->dlsch_encoding_stats,"DLSCH encoding time");
+	printStatIndent2(&eNB->dlsch_rate_matching_stats,"DLSCH rate matching time",eNB->dlsch_rate_matching_stats.trials);
+	printStatIndent2(&eNB->dlsch_turbo_encoding_stats,"DLSCH turbo encoding time", eNB->dlsch_turbo_encoding_stats.trials);
+	printStatIndent2(&eNB->dlsch_interleaving_stats,"DLSCH interleaving time", eNB->dlsch_interleaving_stats.trials);
+	printStatIndent(&eNB->dlsch_scrambling_stats,  "DLSCH scrambling time");
+	printStatIndent(&eNB->dlsch_modulation_stats, "DLSCH modulation time");
+	printDistribution(&eNB->ofdm_mod_stats,table_tx_ifft,"OFDM_mod (idft) time");
+
+        printf("\nUE RX function statistics (per 1ms subframe)\n");
+	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", pdsch_procedures_tot.trials);
+	printStatIndent2(&dlsch_procedures_tot,"dlsch processing", dlsch_procedures_tot.trials);
+	printStatIndent2(&UE->crnti_procedures_stats,"C-RNTI processing", UE->crnti_procedures_stats.trials);
+	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",
+	       UE->dlsch[UE->current_thread_id[subframe]][0][0]->harq_processes[0]->Cminus ?
+	       UE->dlsch[UE->current_thread_id[subframe]][0][0]->harq_processes[0]->Kminus :
+	       UE->dlsch[UE->current_thread_id[subframe]][0][0]->harq_processes[0]->Kplus,
+
+               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", UE->dlsch_tc_init_stats.trials);
+        printStatIndent2(&UE->dlsch_tc_alpha_stats,"alpha", UE->dlsch_tc_init_stats.trials);
+        printStatIndent2(&UE->dlsch_tc_beta_stats,"beta", UE->dlsch_tc_init_stats.trials);
+        printStatIndent2(&UE->dlsch_tc_gamma_stats,"gamma", UE->dlsch_tc_init_stats.trials);
+        printStatIndent2(&UE->dlsch_tc_ext_stats,"ext", UE->dlsch_tc_init_stats.trials);
+        printStatIndent2(&UE->dlsch_tc_intl1_stats,"turbo internal interleaver", UE->dlsch_tc_init_stats.trials);
+        printStatIndent2(&UE->dlsch_tc_intl2_stats,"intl2+HardDecode+CRC", UE->dlsch_tc_init_stats.trials);
+	
       }
 
       if ((transmission_mode != 3) && (transmission_mode != 4)) {
@@ -2399,7 +2197,7 @@ int main(int argc, char **argv)
                 eNB->dlsch_modulation_stats.trials,
                 eNB->dlsch_scrambling_stats.trials,
                 eNB->dlsch_encoding_stats.trials,
-                UE->phy_proc_rx[UE->current_thread_id[subframe]].trials,
+                phy_proc_rx_tot.trials,
                 UE->ofdm_demod_stats.trials,
                 UE->dlsch_rx_pdcch_stats.trials,
                 UE->dlsch_llr_stats.trials,
@@ -2412,7 +2210,7 @@ int main(int argc, char **argv)
                 get_time_meas_us(&eNB->dlsch_modulation_stats),
                 get_time_meas_us(&eNB->dlsch_scrambling_stats),
                 get_time_meas_us(&eNB->dlsch_encoding_stats),
-                get_time_meas_us(&UE->phy_proc_rx[UE->current_thread_id[subframe]]),
+                get_time_meas_us(&phy_proc_rx_tot),
                 nsymb*get_time_meas_us(&UE->ofdm_demod_stats),
                 get_time_meas_us(&UE->dlsch_rx_pdcch_stats),
                 3*get_time_meas_us(&UE->dlsch_llr_stats),
@@ -2420,45 +2218,36 @@ int main(int argc, char **argv)
                 get_time_meas_us(&UE->dlsch_decoding_stats[UE->current_thread_id[subframe]])
                );
         //fprintf(time_meas_fd,"eNB_PROC_TX_STD;eNB_PROC_TX_MAX;eNB_PROC_TX_MIN;eNB_PROC_TX_MED;eNB_PROC_TX_Q1;eNB_PROC_TX_Q3;eNB_PROC_TX_DROPPED;\n");
-        fprintf(time_meas_fd,"%f;%f;%f;%f;%f;%f;%d;", std_phy_proc_tx, t_tx_max, t_tx_min, tx_median, tx_q1, tx_q3, n_tx_dropped);
-
+        fprintf(time_meas_fd,"%f;%f;%f;%f;%f;%f;%d;",squareRoot(&UE->phy_proc_tx), t_tx_max, t_tx_min, median(table_tx), q1(table_tx), q3(table_tx), n_tx_dropped);
         //fprintf(time_meas_fd,"IFFT;\n");
-        fprintf(time_meas_fd,"%f;%f;%f;%f;", std_phy_proc_tx_ifft, tx_ifft_median, tx_ifft_q1, tx_ifft_q3);
-
+        fprintf(time_meas_fd,"%f;%f;%f;%f;",
+		squareRoot(&eNB->ofdm_mod_stats),
+                median(table_tx_ifft),q1(table_tx_ifft),q3(table_tx_ifft));
         //fprintf(time_meas_fd,"MOD;\n");
-        fprintf(time_meas_fd,"%f;%f;%f;%f;", std_phy_proc_tx_mod, tx_mod_median, tx_mod_q1, tx_mod_q3);
-
+        fprintf(time_meas_fd,"%f;%f;%f;%f;",
+		squareRoot(&eNB->dlsch_modulation_stats),
+                median(table_tx_mod), q1(table_tx_mod), q3(table_tx_mod));
         //fprintf(time_meas_fd,"ENC;\n");
-        fprintf(time_meas_fd,"%f;%f;%f;%f;", std_phy_proc_tx_enc, tx_enc_median, tx_enc_q1, tx_enc_q3);
-
-
-        //fprintf(time_meas_fd,"UE_PROC_RX_STD;UE_PROC_RX_MAX;UE_PROC_RX_MIN;UE_PROC_RX_MED;UE_PROC_RX_Q1;UE_PROC_RX_Q3;UE_PROC_RX_DROPPED;\n");
-        fprintf(time_meas_fd,"%f;%f;%f;%f;%f;%f;%d;", std_phy_proc_rx, t_rx_max, t_rx_min, rx_median, rx_q1, rx_q3, n_rx_dropped);
-
+        fprintf(time_meas_fd,"%f;%f;%f;%f;",
+		squareRoot(&eNB->dlsch_encoding_stats),
+                median(table_tx_enc),q1(table_tx_enc),q3(table_tx_enc));
+        //fprintf(time_meas_fd,"eNB_PROC_RX_STD;eNB_PROC_RX_MAX;eNB_PROC_RX_MIN;eNB_PROC_RX_MED;eNB_PROC_RX_Q1;eNB_PROC_RX_Q3;eNB_PROC_RX_DROPPED;\n");
+        fprintf(time_meas_fd,"%f;%f;%f;%f;%f;%f;%d;",
+		squareRoot(&phy_proc_rx_tot), t_rx_max, t_rx_min,
+                median(table_rx), q1(table_rx), q3(table_rx), n_rx_dropped);
         //fprintf(time_meas_fd,"FFT;\n");
-        fprintf(time_meas_fd,"%f;%f;%f;%f;", std_phy_proc_rx_fft, rx_fft_median, rx_fft_q1, rx_fft_q3);
-
+        fprintf(time_meas_fd,"%f;%f;%f;%f;",
+		squareRoot(&UE->ofdm_demod_stats),
+                median(table_rx_fft), q1(table_rx_fft), q3(table_rx_fft));
         //fprintf(time_meas_fd,"DEMOD;\n");
-        fprintf(time_meas_fd,"%f;%f;%f;%f;", std_phy_proc_rx_demod,rx_demod_median, rx_demod_q1, rx_demod_q3);
-
+        fprintf(time_meas_fd,"%f;%f;%f;%f;",
+		squareRoot(&UE->dlsch_demodulation_stats),
+                median(table_rx_demod), q1(table_rx_demod), q3(table_rx_demod));
         //fprintf(time_meas_fd,"DEC;\n");
-        fprintf(time_meas_fd,"%f;%f;%f;%f\n", std_phy_proc_rx_dec, rx_dec_median, rx_dec_q1, rx_dec_q3);
-
-
-        /*
-        fprintf(time_meas_fd,"%d;%d;%d;%d;%d;%d;%d;%d;%d;%d;%d;",
-        eNB->phy_proc_tx.trials,
-        eNB->ofdm_mod_stats.trials,
-        eNB->dlsch_modulation_stats.trials,
-        eNB->dlsch_scrambling_stats.trials,
-        eNB->dlsch_encoding_stats.trials,
-        UE->phy_proc_rx[UE->current_thread_id[subframe]].trials,
-        UE->ofdm_demod_stats.trials,
-        UE->dlsch_rx_pdcch_stats.trials,
-        UE->dlsch_llr_stats.trials,
-        UE->dlsch_unscrambling_stats.trials,
-        UE->dlsch_decoding_stats[UE->current_thread_id[subframe]].trials);
-        */
+        fprintf(time_meas_fd,"%f;%f;%f;%f\n",
+		squareRoot(&UE->dlsch_decoding_stats[subframe]),
+                median(table_rx_dec), q1(table_rx_dec), q3(table_rx_dec));
+
         printf("[passed] effective rate : %f  (%2.1f%%,%f)): log and break \n",rate*effective_rate, 100*effective_rate, rate );
 	test_passed = 1;
         break;
diff --git a/openair1/SIMULATION/LTE_PHY/ulsim.c b/openair1/SIMULATION/LTE_PHY/ulsim.c
index 8c09da1daf9..c015063b605 100644
--- a/openair1/SIMULATION/LTE_PHY/ulsim.c
+++ b/openair1/SIMULATION/LTE_PHY/ulsim.c
@@ -1,23 +1,23 @@
 /*
-   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
-*/
+ * 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
+ */
 
 /*! \file ulsim.c
   \brief Top-level UL simulator
@@ -60,32 +60,7 @@
 double cpuf;
 #define inMicroS(a) (((double)(a))/(cpu_freq_GHz*1000.0))
 //#define MCS_COUNT 23//added for PHY abstraction
-static int cmpdouble(const void *p1, const void *p2) {
-  return *(double *)p1 > *(double *)p2;
-}
-
-double median(varArray_t *input) {
-  return *(double *)((uint8_t *)(input+1)+(input->size/2)*input->atomSize);
-}
-
-double q1(varArray_t *input) {
-  return *(double *)((uint8_t *)(input+1)+(input->size/4)*input->atomSize);
-}
-
-double q3(varArray_t *input) {
-  return *(double *)((uint8_t *)(input+1)+(3*input->size/4)*input->atomSize);
-}
-
-void dumpVarArray(varArray_t *input) {
-  double *ptr=dataArray(input);
-  printf("dumping size=%ld\n", input->size);
-
-  for (int i=0; i < input->size; i++)
-    printf("%.1f:", *ptr++);
-
-  printf("\n");
-}
-
+#include <openair1/SIMULATION/LTE_PHY/common_sim.h>
 channel_desc_t *eNB2UE[NUMBER_OF_eNB_MAX][NUMBER_OF_UE_MAX];
 channel_desc_t *UE2eNB[NUMBER_OF_UE_MAX][NUMBER_OF_eNB_MAX];
 //Added for PHY abstractionopenair1/PHY/TOOLS/lte_phy_scope.h
@@ -348,48 +323,8 @@ void fill_ulsch_dci(PHY_VARS_eNB *eNB,
   ul_req->tl.tag = NFAPI_UL_CONFIG_REQUEST_BODY_TAG;
 }
 
-void printStatIndent(time_stats_t *ptr, char *txt) {
-  printf("|__ %-50s %.2f us (%d trials)\n",
-         txt,
-         inMicroS(ptr->diff/ptr->trials),
-         ptr->trials);
-}
-
-void printStatIndent2(time_stats_t *ptr, char *txt, int turbo_iter) {
-  double timeBase=1/(1000*cpu_freq_GHz);
-  printf("    |__ %-45s %.2f us (cycles/block %7g, %5d trials)\n",
-         txt,
-         ((double)ptr->diff)/ptr->trials*timeBase,
-         round(((double)ptr->diff)/turbo_iter),
-         ptr->trials);
-}
-
-double squareRoot(time_stats_t *ptr) {
-  double timeBase=1/(1000*cpu_freq_GHz);
-  return sqrt((double)ptr->diff_square*pow(timeBase,2)/ptr->trials -
-              pow((double)ptr->diff/ptr->trials*timeBase,2));
-}
-
-void printDistribution(time_stats_t *ptr, varArray_t *sortedList, char *txt) {
-  double timeBase=1/(1000*cpu_freq_GHz);
-  printf("%-50s             :%.2f us (%d trials)\n",
-         txt,
-         (double)ptr->diff/ptr->trials*timeBase,
-         ptr->trials);
-  printf("|__ Statistics std=%.2f, median=%.2f, q1=%.2f, q3=%.2f µs (on %ld trials)\n",
-         squareRoot(ptr), median(sortedList),q1(sortedList),q3(sortedList), sortedList->size);
-}
-
-void logDistribution(FILE* fd, time_stats_t *ptr, varArray_t *sortedList, int dropped) {
-  fprintf(fd,"%f;%f;%f;%f;%f;%f;%d;",
-	  squareRoot(ptr),
-	  (double)ptr->max, *(double*)dataArray(sortedList),
-	  median(sortedList),q1(sortedList),q3(sortedList),
-	  dropped); 
-}
-
 enum eTypes { eBool, eInt, eFloat, eText };
-static int verbose,disable_bundling=0,cqi_flag=0, extended_prefix_flag=0, test_perf=0, subframe=3, transmission_m=1,n_rx=1;
+static int verbose,help,disable_bundling=0,cqi_flag=0, extended_prefix_flag=0, test_perf=0, subframe=3, transmission_m=1,n_rx=1;
 
 int main(int argc, char **argv) {
   int i,j,aa,u;
@@ -505,13 +440,13 @@ int main(int argc, char **argv) {
   //set_glog(LOG_DEBUG,LOG_MED);
   //hapZEbm:n:Y:X:x:s:w:e:q:d:D:O:c:r:i:f:y:c:oA:C:R:g:N:l:S:T:QB:PI:LF
   static paramdef_t options[] = {
-    { "awgn", "Additive white gaussian noise", PARAMFLAG_BOOL, strptr:NULL, defintval:0, TYPE_INT, 0, NULL, NULL },
+    { "awgn", "Use AWGN channel and not multipath", PARAMFLAG_BOOL, strptr:NULL, defintval:0, TYPE_INT, 0, NULL, NULL },
     { "BnbRBs", "The LTE bandwith in RBs (100 is 20MHz)",0, iptr:&N_RB_DL,  defintval:25, TYPE_INT, 0 },
     { "mcs", "The MCS to use", 0, iptr:&mcs,  defintval:10, TYPE_INT, 0 },
     { "nb_frame", "number of frame in a test",0, iptr:&n_frames,  defintval:1, TYPE_INT, 0 },
     { "snr", "starting snr", 0, dblptr:&snr0,  defdblval:-2.9, TYPE_DOUBLE, 0 },
     { "wsnrInterrupt", "snr int ?", 0, dblptr:&snr_int,  defdblval:30, TYPE_DOUBLE, 0 },
-    { "e_snr_step", "step increasint snr",0, dblptr:&input_snr_step,  defdblval:0.2, TYPE_DOUBLE, 0 },
+    { "e_snr_step", "step increasing snr",0, dblptr:&input_snr_step,  defdblval:0.2, TYPE_DOUBLE, 0 },
     { "rb_dynamic", "number of rb in dynamic allocation",0, iptr:NULL,  defintval:0, TYPE_INT, 0 },
     { "first_rb", "first rb used in dynamic allocation",0, iptr:&first_rb,  defintval:0, TYPE_INT, 0 },
     { "osrs", "enable srs generation",PARAMFLAG_BOOL, iptr:&srs_flag,  defintval:0, TYPE_INT, 0 },
@@ -538,37 +473,12 @@ int main(int argc, char **argv) {
     { "bundling_disable", "bundling disable",PARAMFLAG_BOOL,  iptr:&disable_bundling, defintval:0, TYPE_INT, 0 },
     { "Y",  "n_ch_rlz",0, iptr:&n_ch_rlz,  defintval:1, TYPE_INT, 0 },
     { "X",  "abstx", PARAMFLAG_BOOL,  iptr:&abstx, defintval:0, TYPE_INT, 0 },
-    { "Operf", "test perf mode ?",0, iptr:&test_perf,  defintval:0, TYPE_INT, 0 },
+    { "Operf", "Set the percentage of effective rate to testbench the modem performance (typically 30 and 70, range 1-100)",0, iptr:&test_perf,  defintval:0, TYPE_INT, 0 },
     { "verbose", "display debug text", PARAMFLAG_BOOL,  iptr:&verbose, defintval:0, TYPE_INT, 0 },
+    { "help", "display help and exit", PARAMFLAG_BOOL,  iptr:&help, defintval:0, TYPE_INT, 0 },
     { "", "",0,  iptr:NULL, defintval:0, TYPE_INT, 0 },
   };
-  int l;
-
-  for(l=0; options[l].optname[0]!=0; l++) {};
-
-  struct option *long_options=calloc(sizeof(struct option),l);
-
-  for(int i=0; options[i].optname[0]!=0; i++) {
-    long_options[i].name=options[i].optname;
-    long_options[i].has_arg=options[i].paramflags==PARAMFLAG_BOOL?no_argument:required_argument;
-
-    if ( options[i].voidptr)
-      switch (options[i].type) {
-        case TYPE_INT:
-          *options[i].iptr=options[i].defintval;
-          break;
-
-        case TYPE_DOUBLE:
-          *options[i].dblptr=options[i].defdblval;
-          break;
-
-        default:
-          printf("not parsed type for default value %s\n", options[i].optname );
-          exit(1);
-      }
-
-    continue;
-  };
+  struct option * long_options = parse_oai_options(options); 
 
   int option_index;
 
@@ -579,113 +489,121 @@ int main(int argc, char **argv) {
       if (long_options[option_index].has_arg==no_argument)
         *(bool *)options[option_index].iptr=1;
       else switch (options[option_index].type) {
-          case TYPE_INT:
-            *(int *)options[option_index].iptr=atoi(optarg);
-            break;
-
-          case TYPE_DOUBLE:
-            *(double *)options[option_index].dblptr=atof(optarg);
-            break;
-
-          default:
-            printf("not decoded type.\n");
-            exit(1);
+	case TYPE_INT:
+	  *(int *)options[option_index].iptr=atoi(optarg);
+	  break;
+
+	case TYPE_DOUBLE:
+	  *(double *)options[option_index].dblptr=atof(optarg);
+	  break;
+
+	case TYPE_UINT8:
+	  *(uint8_t *)options[option_index].dblptr=atoi(optarg);
+	  break;
+	  	    
+	case TYPE_UINT16:
+	  *(uint16_t *)options[option_index].dblptr=atoi(optarg);
+	  break;
+	  
+	default:
+	  printf("not decoded type.\n");
+	  exit(1);
         }
 
       continue;
     }
 
     switch (long_options[option_index].name[0]) {
-      case 'T':
-        tdd_config=atoi(optarg);
-        frame_type=TDD;
-        break;
-
-      case 'a':
-        channel_model = AWGN;
-        chMod = 1;
-        break;
+    case 'T':
+      tdd_config=atoi(optarg);
+      frame_type=TDD;
+      break;
 
-      case 'g':
-        strncpy(channel_model_input,optarg,9);
-        struct tmp {
-          char opt;
-          int m;
-          int M;
-        }
-        tmp[]= {
-          {'A',SCM_A,2},
-          {'B',SCM_B,3},
-          {'C',SCM_C,4},
-          {'D',SCM_D,5},
-          {'E',EPA,6},
-          {'G',ETU,8},
-          {'H',Rayleigh8,9},
-          {'I',Rayleigh1,10},
-          {'J',Rayleigh1_corr,11},
-          {'K',Rayleigh1_anticorr,12},
-          {'L',Rice8,13},
-          {'M',Rice1,14},
-          {'N',AWGN,1},
-          {0,0,0}
-        };
-        struct tmp *ptr;
-
-        for (ptr=tmp; ptr->opt!=0; ptr++)
-          if ( ptr->opt == optarg[0] ) {
-            channel_model=ptr->m;
-            chMod=ptr->M;
-            break;
-          }
+    case 'a':
+      channel_model = AWGN;
+      chMod = 1;
+      break;
 
-        AssertFatal(ptr->opt != 0, "Unsupported channel model: %s !\n", optarg );
-        break;
+    case 'g':
+      strncpy(channel_model_input,optarg,9);
+      struct tmp {
+	char opt;
+	int m;
+	int M;
+      }
+      tmp[]= {
+	{'A',SCM_A,2},
+	{'B',SCM_B,3},
+	{'C',SCM_C,4},
+	{'D',SCM_D,5},
+	{'E',EPA,6},
+	{'G',ETU,8},
+	{'H',Rayleigh8,9},
+	{'I',Rayleigh1,10},
+	{'J',Rayleigh1_corr,11},
+	{'K',Rayleigh1_anticorr,12},
+	{'L',Rice8,13},
+	{'M',Rice1,14},
+	{'N',AWGN,1},
+	{0,0,0}
+      };
+      struct tmp *ptr;
+
+      for (ptr=tmp; ptr->opt!=0; ptr++)
+	if ( ptr->opt == optarg[0] ) {
+	  channel_model=ptr->m;
+	  chMod=ptr->M;
+	  break;
+	}
+
+      AssertFatal(ptr->opt != 0, "Unsupported channel model: %s !\n", optarg );
+      break;
 
-      case 'x':
-        transmission_m=atoi(optarg);
-        AssertFatal(transmission_m==1 || transmission_m==2,
-                    "Unsupported transmission mode %d\n",transmission_m);
-        break;
+    case 'x':
+      transmission_m=atoi(optarg);
+      AssertFatal(transmission_m==1 || transmission_m==2,
+		  "Unsupported transmission mode %d\n",transmission_m);
+      break;
 
-      case 'r':
-        nb_rb = atoi(optarg);
-        nb_rb_set = 1;
-        break;
+    case 'r':
+      nb_rb = atoi(optarg);
+      nb_rb_set = 1;
+      break;
 
       //case 'c':
       //  cyclic_shift = atoi(optarg);
       //  break;
 
-      case 'i':
-        input_fdUL = fopen(optarg,"r");
-        printf("Reading in %s (%p)\n",optarg,input_fdUL);
-        AssertFatal(input_fdUL != (FILE *)NULL,"Unknown file %s\n",optarg);
-        break;
+    case 'i':
+      input_fdUL = fopen(optarg,"r");
+      printf("Reading in %s (%p)\n",optarg,input_fdUL);
+      AssertFatal(input_fdUL != (FILE *)NULL,"Unknown file %s\n",optarg);
+      break;
 
-      case 'A':
-        beta_ACK = atoi(optarg);
-        AssertFatal(beta_ACK>15,"beta_ack must be in (0..15)\n");
-        break;
+    case 'A':
+      beta_ACK = atoi(optarg);
+      AssertFatal(beta_ACK>15,"beta_ack must be in (0..15)\n");
+      break;
 
-      case 'C':
-        beta_CQI = atoi(optarg);
-        AssertFatal((beta_CQI>15)||(beta_CQI<2),"beta_cqi must be in (2..15)\n");
-        break;
+    case 'C':
+      beta_CQI = atoi(optarg);
+      AssertFatal((beta_CQI>15)||(beta_CQI<2),"beta_cqi must be in (2..15)\n");
+      break;
 
-      case 'R':
-        beta_RI = atoi(optarg);
-        AssertFatal((beta_RI>15)||(beta_RI<2),"beta_ri must be in (0..13)\n");
-        break;
+    case 'R':
+      beta_RI = atoi(optarg);
+      AssertFatal((beta_RI>15)||(beta_RI<2),"beta_ri must be in (0..13)\n");
+      break;
 
-      case 'P':
-        dump_perf=1;
-        opp_enabled=1;
-        break;
+    case 'P':
+      dump_perf=1;
+      opp_enabled=1;
+      break;
 
-      default:
-        printf("Wrong option\n");
-        exit(1);
-        break;
+    default:
+      printf("Wrong option: %s\n",long_options[option_index].name);
+      exit(1);
+      break;
     }
   }
 
@@ -694,34 +612,12 @@ int main(int argc, char **argv) {
     exit(1);
   }
 
-  paramdef_t *ptr=options ;
-
-  for( ptr=options; ptr->optname[0]!=0; ptr++) {
-    char varText[256]="need specific display";
 
-    if (ptr->voidptr != NULL) {
-      if ( (ptr->paramflags & PARAMFLAG_BOOL) )
-        strcpy(varText, *(bool *)ptr->iptr ? "True": "False" );
-      else  switch (ptr->type) {
-          case TYPE_INT:
-            sprintf(varText,"%d",*ptr->iptr);
-            break;
-
-          case TYPE_DOUBLE:
-            sprintf(varText,"%.2f",*ptr->dblptr);
-            break;
-
-          default:
-            printf("not decoded type\n");
-            exit(1);
-        }
-    }
-
-    printf("Option: %20s set to %s\n",ptr->optname, varText);
-
-    if (verbose)
-      printf("%s\n",ptr->helpstr);
-  }
+  if (help || verbose )
+     display_options_values(options, true);
+  if (help)
+    exit(0);
+  
   set_parallel_conf("PARALLEL_RU_L1_TRX_SPLIT");
   set_worker_conf("WORKER_ENABLE");
   RC.nb_L1_inst = 1;
-- 
GitLab