diff --git a/cmake_targets/CMakeLists.txt b/cmake_targets/CMakeLists.txt
index c02f327f1d797bf35c6db9ff7b4c963ec0f2790f..7f911528a1814385ba588c516c0298b7395b500f 100644
--- a/cmake_targets/CMakeLists.txt
+++ b/cmake_targets/CMakeLists.txt
@@ -242,6 +242,7 @@ add_boolean_option(UE_DEBUG_TRACE      False "Activate UE debug trace")
 add_boolean_option(UE_TIMING_TRACE     False "Activate UE timing trace")
 add_boolean_option(DISABLE_LOG_X       False "Deactivate all LOG_* macros")
 add_boolean_option(USRP_REC_PLAY       False "Enable USRP record playback mode")
+add_boolean_option(UE_NAS_USE_TUN      False "Enable UE NAS TUN device instead of ue_ip.ko")
 
 add_boolean_option(DEBUG_CONSOLE False "makes debugging easier, disables stdout/stderr buffering")
 
@@ -1294,6 +1295,7 @@ set (MAC_SRC
   ${MAC_DIR}/eNB_scheduler_bch.c
   ${MAC_DIR}/eNB_scheduler_primitives.c
   ${MAC_DIR}/eNB_scheduler_RA.c
+  ${MAC_DIR}/eNB_scheduler_phytest.c
   ${MAC_DIR}/pre_processor.c
   ${MAC_DIR}/config.c
   #${MAC_DIR}/config_ue.c
diff --git a/cmake_targets/build_oai b/cmake_targets/build_oai
index d7b98bce413beb48f97f9447b80fe913c88618f1..04bd45e48e2ac4c5fa68c82e5aa7e638039c5040 100755
--- a/cmake_targets/build_oai
+++ b/cmake_targets/build_oai
@@ -67,6 +67,7 @@ UE_TIMING_TRACE="False"
 DISABLE_LOG_X="False"
 USRP_REC_PLAY="False"
 BUILD_ECLIPSE=0
+UE_NAS_USE_TUN="False"
 trap handle_ctrl_c INT
 
 function print_help() {
@@ -156,6 +157,8 @@ Options
    Build eclipse project files. Paths are auto corrected by fixprj.sh
 --usrp-recplay
    Build for I/Q record-playback modes
+--ue-nas-use-tun
+   Use TUN devices for the UEs instead of ue_ip.ko
 Usage (first build):
  oaisim (eNB + UE): ./build_oai -I  --oaisim -x --install-system-files
  Eurecom EXMIMO + COTS UE : ./build_oai -I  --eNB -x --install-system-files
@@ -347,6 +350,10 @@ function main() {
             USRP_REC_PLAY="True"
             echo_info "Enabling USRP record playback mode"
             shift 1;;
+        --ue-nas-use-tun)
+            UE_NAS_USE_TUN="True"
+            echo_info "Enabling UE NAS TUN device usage instead of ue_ip.ko"
+            shift 1;;
         -h | --help)
             print_help
             exit 1;;
@@ -696,6 +703,7 @@ function main() {
     echo "set ( RRC_ASN1_VERSION \"${REL}\")" >>  $cmake_file
     echo "set ( ENABLE_VCD_FIFO $VCD_TIMING )" >>  $cmake_file
     echo "set ( T_TRACER $T_TRACER )"          >>  $cmake_file
+    echo "set ( UE_NAS_USE_TUN $UE_NAS_USE_TUN )" >>  $cmake_file
     echo 'include(${CMAKE_CURRENT_SOURCE_DIR}/../CMakeLists.txt)' >> $cmake_file
     [ "$CLEAN" = "1" ] && rm -rf $DIR/$oaisim_build_dir/build
     mkdir -p $DIR/$oaisim_build_dir/build
@@ -704,6 +712,12 @@ function main() {
     compilations \
 	  $oaisim_build_dir $oaisim_exec \
 	  $oaisim_exec $dbin/$oaisim_exec.$REL
+    compilations \
+	  $oaisim_build_dir $config_libconfig_shlib \
+	  lib$config_libconfig_shlib.so $dbin/lib$config_libconfig_shlib.so
+    compilations \
+          $oaisim_build_dir coding \
+          libcoding.so $dbin/libcoding.so
 
     if [ "$NOS1" != "1" ] ; then
 
diff --git a/common/config/libconfig/config_libconfig.c b/common/config/libconfig/config_libconfig.c
index a73a0737f25849fba1f59d820cc229f5547a063a..cfb0a214cfac14c337f894d67a5f64427d0f685e 100644
--- a/common/config/libconfig/config_libconfig.c
+++ b/common/config/libconfig/config_libconfig.c
@@ -130,6 +130,7 @@ int config_libconfig_get(paramdef_t *cfgoptions,int numoptions, char *prefix )
        {
        	case TYPE_STRING:
            
+printf("call config_lookup_string for '%s' %p\n", cfgpath, &(libconfig_privdata.cfg)); fflush(stdout);
            if ( config_lookup_string(&(libconfig_privdata.cfg),cfgpath, (const char **)&str)) {
               if ( cfgoptions[i].numelt > 0  && str != NULL && strlen(str) >= cfgoptions[i].numelt ) {
                   fprintf(stderr,"[LIBCONFIG] %s:  %s exceeds maximum length of %i bytes, value truncated\n",
diff --git a/common/utils/T/T_defs.h b/common/utils/T/T_defs.h
index 6bdda0edacdb8f53ead52a6eea844037de309080..16d35210f2aabf60358910dca52e7a02a1fe57c9 100644
--- a/common/utils/T/T_defs.h
+++ b/common/utils/T/T_defs.h
@@ -32,7 +32,7 @@ typedef struct {
 #define VCD_NUM_FUNCTIONS 187
 
 /* number of VCD variables (to be kept up to date! see in T_messages.txt) */
-#define VCD_NUM_VARIABLES 128
+#define VCD_NUM_VARIABLES 131
 
 /* first VCD function (to be kept up to date! see in T_messages.txt) */
 #define VCD_FIRST_FUNCTION    ((uintptr_t)T_VCD_FUNCTION_RT_SLEEP)
diff --git a/common/utils/T/T_messages.txt b/common/utils/T/T_messages.txt
index 8d531f9067708a301b395cb9ca4e2fb5d3bf1ec2..4d59a8d380f65c6d88efdeea2afa81640e81a7fa 100644
--- a/common/utils/T/T_messages.txt
+++ b/common/utils/T/T_messages.txt
@@ -1442,6 +1442,18 @@ ID = VCD_VARIABLE_UE0_TRX_WRITE_NS_MISSING
     DESC = VCD variable UE0_TRX_WRITE_NS_MISSING
     GROUP = ALL:VCD:UE:VCD_VARIABLE
     FORMAT = ulong,value
+ID = VCD_VARIABLE_CPUID_ENB_THREAD_RXTX
+    DESC = VCD variable CPUID_ENB_THREAD_RXTX
+    GROUP = ALL:VCD:ENB:VCD_VARIABLE
+    FORMAT = ulong,value
+ID = VCD_VARIABLE_CPUID_RU_THREAD
+    DESC = VCD variable CPUID_RU_THREAD
+    GROUP = ALL:VCD:ENB:VCD_VARIABLE
+    FORMAT = ulong,value
+ID = VCD_VARIABLE_CPUID_RU_THREAD_TX
+    DESC = VCD variable CPUID_RU_THREAD_TX
+    GROUP = ALL:VCD:ENB:VCD_VARIABLE
+    FORMAT = ulong,value
 
 #functions
 
diff --git a/common/utils/itti/intertask_interface.c b/common/utils/itti/intertask_interface.c
index 1d38a3692b358d4cd52ef951cf9108cee905d188..21a3304e202b6910ce27145b5c807c72b4552912 100644
--- a/common/utils/itti/intertask_interface.c
+++ b/common/utils/itti/intertask_interface.c
@@ -72,6 +72,9 @@ const int itti_debug = (ITTI_DEBUG_ISSUES | ITTI_DEBUG_MP_STATISTICS);
 /* Global message size */
 #define MESSAGE_SIZE(mESSAGEiD) (sizeof(MessageHeader) + itti_desc.messages_info[mESSAGEiD].size)
 
+
+extern int emulate_rf;
+
 typedef enum task_state_s {
   TASK_STATE_NOT_CONFIGURED, TASK_STATE_STARTING, TASK_STATE_READY, TASK_STATE_ENDED, TASK_STATE_MAX,
 } task_state_t;
@@ -342,14 +345,16 @@ int itti_send_msg_to_task(task_id_t destination_task_id, instance_t instance, Me
                  destination_task_id,
                  itti_get_task_name(destination_task_id));
     } else {
-      /* We cannot send a message if the task is not running */
-      AssertFatal (itti_desc.threads[destination_thread_id].task_state == TASK_STATE_READY,
-                   "Task %s Cannot send message %s (%d) to thread %d, it is not in ready state (%d)!\n",
-                   itti_get_task_name(origin_task_id),
-                   itti_desc.messages_info[message_id].name,
-                   message_id,
-                   destination_thread_id,
-                   itti_desc.threads[destination_thread_id].task_state);
+      if(!emulate_rf){
+        /* We cannot send a message if the task is not running */
+        AssertFatal (itti_desc.threads[destination_thread_id].task_state == TASK_STATE_READY,
+                     "Task %s Cannot send message %s (%d) to thread %d, it is not in ready state (%d)!\n",
+                     itti_get_task_name(origin_task_id),
+                     itti_desc.messages_info[message_id].name,
+                     message_id,
+                     destination_thread_id,
+                     itti_desc.threads[destination_thread_id].task_state);
+      }
 
       /* Allocate new list element */
       new = (message_list_t *) itti_malloc (origin_task_id, destination_task_id, sizeof(struct message_list_s));
diff --git a/nfapi/oai_integration/nfapi_vnf.c b/nfapi/oai_integration/nfapi_vnf.c
index 9184aa6e9d879815664b9a38b769651a631ef539..74e999528c51fc7d40f4eea48d56cd069a7ced04 100644
--- a/nfapi/oai_integration/nfapi_vnf.c
+++ b/nfapi/oai_integration/nfapi_vnf.c
@@ -202,8 +202,8 @@ void oai_create_enb(void) {
   eNB->CC_id   = bodge_counter;
   eNB->abstraction_flag   = 0;
   eNB->single_thread_flag = 0;//single_thread_flag;
-  eNB->td                   = ulsch_decoding_data;//(single_thread_flag==1) ? ulsch_decoding_data_2thread : ulsch_decoding_data;
-  eNB->te                   = dlsch_encoding;//(single_thread_flag==1) ? dlsch_encoding_2threads : dlsch_encoding;
+  eNB->td                   = ulsch_decoding_data_all;//(single_thread_flag==1) ? ulsch_decoding_data_2thread : ulsch_decoding_data;
+  eNB->te                   = dlsch_encoding_all;//(single_thread_flag==1) ? dlsch_encoding_2threads : dlsch_encoding;
 
   RC.nb_CC[bodge_counter] = 1;
 
diff --git a/openair1/PHY/LTE_TRANSPORT/dci.c b/openair1/PHY/LTE_TRANSPORT/dci.c
index 8c2496430e3522a1bb0736e2b8b8790e9be650a7..768f7d661e796cb2d128f2a6881c443dd050d8dc 100755
--- a/openair1/PHY/LTE_TRANSPORT/dci.c
+++ b/openair1/PHY/LTE_TRANSPORT/dci.c
@@ -354,7 +354,7 @@ uint8_t generate_dci_top(uint8_t num_pdcch_symbols,
   /* clear all bits, the above code may generate too much false detections
    * (not sure about this, to be checked somehow)
    */
-  // memset(e, 0, DCI_BITS_MAX);
+  //memset(e, 0, DCI_BITS_MAX);
 
   e_ptr = e;
 
@@ -376,6 +376,7 @@ uint8_t generate_dci_top(uint8_t num_pdcch_symbols,
 	#endif
 
         if (dci_alloc[i].firstCCE>=0) {
+//printf("generate DCI .%d rnti %d length %d\n", subframe, dci_alloc[i].rnti, dci_alloc[i].dci_length);
           e_ptr = generate_dci0(dci_alloc[i].dci_pdu,
                                 e+(72*dci_alloc[i].firstCCE),
                                 dci_alloc[i].dci_length,
diff --git a/openair1/PHY/LTE_TRANSPORT/dci_tools.c b/openair1/PHY/LTE_TRANSPORT/dci_tools.c
index 3f51b97904676bed5b96a087b75e4ef8ccbb0c8b..ed7def3489917076169f28725bf26153538a3a5d 100644
--- a/openair1/PHY/LTE_TRANSPORT/dci_tools.c
+++ b/openair1/PHY/LTE_TRANSPORT/dci_tools.c
@@ -1413,6 +1413,7 @@ void fill_dci_and_dlsch(PHY_VARS_eNB *eNB,int frame,int subframe,eNB_rxtx_proc_t
 
 #endif
     
+//printf("DCI %d.%d rnti %d harq %d TBS %d\n", frame, subframe, rel8->rnti, rel8->harq_process, dlsch0_harq->TBS);
 #if T_TRACER
   if (dlsch0->active)
     T(T_ENB_PHY_DLSCH_UE_DCI, T_INT(0), T_INT(frame), T_INT(subframe),
@@ -1939,3 +1940,4 @@ void fill_ulsch(PHY_VARS_eNB *eNB,nfapi_ul_config_ulsch_pdu *ulsch_pdu,int frame
 	ulsch->harq_processes[harq_pid]->round);  
 }
 
+
diff --git a/openair1/PHY/LTE_TRANSPORT/dlsch_coding.c b/openair1/PHY/LTE_TRANSPORT/dlsch_coding.c
index e96e5937da9c22e0f0a3e3141a322f273c308a3e..5e171748adcb1bbf6379a4ceb1502afefd070062 100644
--- a/openair1/PHY/LTE_TRANSPORT/dlsch_coding.c
+++ b/openair1/PHY/LTE_TRANSPORT/dlsch_coding.c
@@ -41,6 +41,7 @@
 #include "UTIL/LOG/vcd_signal_dumper.h"
 #include "UTIL/LOG/log.h"
 #include <syscall.h>
+#include "targets/RT/USER/rt_wrapper.h"
 
 //#define DEBUG_DLSCH_CODING
 //#define DEBUG_DLSCH_FREE 1
@@ -51,7 +52,13 @@
   ((pilots==1)&&(first_pilot==0)&&(((re<3))||((re>5)&&(re<9)))) \
 */
 #define is_not_pilot(pilots,first_pilot,re) (1)
+/*extern void thread_top_init(char *thread_name,
+		     int affinity,
+		     uint64_t runtime,
+		     uint64_t deadline,
+		     uint64_t period);*/
 
+extern int codingw;
 
 void free_eNB_dlsch(LTE_eNB_DLSCH_t *dlsch)
 {
@@ -243,11 +250,15 @@ void clean_eNb_dlsch(LTE_eNB_DLSCH_t *dlsch)
 }
 
 
+
+
 int dlsch_encoding_2threads0(te_params *tep) {
 
   LTE_eNB_DLSCH_t *dlsch          = tep->dlsch;
   unsigned int G                  = tep->G;
   unsigned char harq_pid          = tep->harq_pid;
+  unsigned int total_worker       = tep->total_worker;
+  unsigned int current_worker     = tep->current_worker;
 
   unsigned short iind;
 
@@ -260,7 +271,7 @@ int dlsch_encoding_2threads0(te_params *tep) {
 
   if (dlsch->harq_processes[harq_pid]->round == 0) {  // this is a new packet
 
-    for (r=0; r<dlsch->harq_processes[harq_pid]->C>>1; r++) {
+    for (r=(dlsch->harq_processes[harq_pid]->C/(total_worker+1))*current_worker; r<(dlsch->harq_processes[harq_pid]->C/(total_worker+1))*(current_worker+1); r++) {
 
       if (r<dlsch->harq_processes[harq_pid]->Cminus)
         Kr = dlsch->harq_processes[harq_pid]->Kminus;
@@ -303,21 +314,34 @@ int dlsch_encoding_2threads0(te_params *tep) {
   // Fill in the "e"-sequence from 36-212, V8.6 2009-03, p. 16-17 (for each "e") and concatenate the
   // outputs for each code segment, see Section 5.1.5 p.20
 
-  for (r=0; r<dlsch->harq_processes[harq_pid]->C>>1; r++) {
-    r_offset += lte_rate_matching_turbo(dlsch->harq_processes[harq_pid]->RTC[r],
-                                        G,  //G
-                                        dlsch->harq_processes[harq_pid]->w[r],
-                                        dlsch->harq_processes[harq_pid]->e+r_offset,
-                                        dlsch->harq_processes[harq_pid]->C, // C
-                                        dlsch->Nsoft,                    // Nsoft,
-                                        dlsch->Mdlharq,
-                                        dlsch->Kmimo,
-                                        dlsch->harq_processes[harq_pid]->rvidx,
-                                        dlsch->harq_processes[harq_pid]->Qm,
-                                        dlsch->harq_processes[harq_pid]->Nl,
-                                        r,
-                                        nb_rb);
-    //                                        m);                       // r
+  for (r=0,r_offset=0; r<(dlsch->harq_processes[harq_pid]->C/(total_worker+1))*(current_worker+1); r++) {
+    if(r<(dlsch->harq_processes[harq_pid]->C/(total_worker+1))*(current_worker)){
+	  int Nl=dlsch->harq_processes[harq_pid]->Nl;
+      int Qm=dlsch->harq_processes[harq_pid]->Qm;
+      int C = dlsch->harq_processes[harq_pid]->C;
+      int Gp = G/Nl/Qm;
+      int GpmodC = Gp%C;
+      if (r < (C-(GpmodC)))
+	    r_offset += Nl*Qm * (Gp/C);
+      else
+	    r_offset += Nl*Qm * ((GpmodC==0?0:1) + (Gp/C));
+	}
+	else{
+      r_offset += lte_rate_matching_turbo(dlsch->harq_processes[harq_pid]->RTC[r],
+                                          G,  //G
+                                          dlsch->harq_processes[harq_pid]->w[r],
+                                          dlsch->harq_processes[harq_pid]->e+r_offset,
+                                          dlsch->harq_processes[harq_pid]->C, // C
+                                          dlsch->Nsoft,                    // Nsoft,
+                                          dlsch->Mdlharq,
+                                          dlsch->Kmimo,
+                                          dlsch->harq_processes[harq_pid]->rvidx,
+                                          dlsch->harq_processes[harq_pid]->Qm,
+                                          dlsch->harq_processes[harq_pid]->Nl,
+                                          r,
+                                          nb_rb);
+      //                                        m);                       // r
+    }
   }
 
   VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_DLSCH_ENCODING_W, VCD_FUNCTION_OUT);
@@ -325,32 +349,46 @@ int dlsch_encoding_2threads0(te_params *tep) {
   return(0);
 }
 
+
 extern int oai_exit;
 void *te_thread(void *param) {
+  cpu_set_t cpuset;
+  CPU_ZERO(&cpuset);
+  
+  thread_top_init("te_thread",1,200000,250000,500000);
   pthread_setname_np( pthread_self(),"te processing");
-  LOG_I(PHY,"thread te created id=%ld", syscall(__NR_gettid));
+  LOG_I(PHY,"thread te created id=%ld\n", syscall(__NR_gettid));
+  
 
-  eNB_proc_t *proc = &((te_params *)param)->eNB->proc;
+  te_params *tep                 = (te_params *)param;
+  
+  //wait_sync("te_thread");
+  
   while (!oai_exit) {
 
+    if (wait_on_condition(&tep->mutex_te,&tep->cond_te,&tep->instance_cnt_te,"te thread")<0) break;
+    if(oai_exit) break;
 
-    if (wait_on_condition(&proc->mutex_te,&proc->cond_te,&proc->instance_cnt_te,"te thread")<0) break;
-
-    dlsch_encoding_2threads0((te_params*)param);
+    dlsch_encoding_2threads0(tep);
 
+    if (release_thread(&tep->mutex_te,&tep->instance_cnt_te,"te thread")<0) break;
 
-    if (release_thread(&proc->mutex_te,&proc->instance_cnt_te,"te thread")<0) break;
-
-    if (pthread_cond_signal(&proc->cond_te) != 0) {
+    if (pthread_cond_signal(&tep->cond_te) != 0) {
       printf("[eNB] ERROR pthread_cond_signal for te thread exit\n");
       exit_fun( "ERROR pthread_cond_signal" );
       return(NULL);
     }
+    /*if(opp_enabled == 1 && te_wakeup_stats0->diff_now>50*3000){
+      print_meas_now(te_wakeup_stats0,"coding_wakeup",stderr);
+      printf("te_thread0 delay for waking up in frame_rx: %d  subframe_rx: %d \n",proc->frame_rx,proc->subframe_rx);
+    }*/
   }
 
   return(NULL);
 }
 
+
+
 int dlsch_encoding_2threads(PHY_VARS_eNB *eNB,
 			    unsigned char *a,
 			    uint8_t num_pdcch_symbols,
@@ -359,9 +397,16 @@ int dlsch_encoding_2threads(PHY_VARS_eNB *eNB,
 			    uint8_t subframe,
 			    time_stats_t *rm_stats,
 			    time_stats_t *te_stats,
-			    time_stats_t *i_stats)
+				time_stats_t *te_wait_stats,
+                time_stats_t *te_main_stats,
+                time_stats_t *te_wakeup_stats0,
+                time_stats_t *te_wakeup_stats1,
+                time_stats_t *i_stats,
+                int worker_num)
 {
 
+  //start_meas(&eNB->dlsch_turbo_encoding_preperation_stats);
+
   LTE_DL_FRAME_PARMS *frame_parms = &eNB->frame_parms;
   eNB_proc_t *proc = &eNB->proc;
   unsigned int G;
@@ -381,19 +426,22 @@ int dlsch_encoding_2threads(PHY_VARS_eNB *eNB,
   mod_order = dlsch->harq_processes[harq_pid]->Qm;
   G = get_G(frame_parms,nb_rb,dlsch->harq_processes[harq_pid]->rb_alloc,mod_order,dlsch->harq_processes[harq_pid]->Nl,num_pdcch_symbols,frame,subframe,dlsch->harq_processes[harq_pid]->mimo_mode==TM7?7:0);
 
-
   if (dlsch->harq_processes[harq_pid]->round == 0) {  // this is a new packet
 
+    start_meas(&eNB->dlsch_turbo_encoding_preperation_stats);
     // Add 24-bit crc (polynomial A) to payload
     crc = crc24a(a,
                  A)>>8;
+    stop_meas(&eNB->dlsch_turbo_encoding_preperation_stats);
     a[A>>3] = ((uint8_t*)&crc)[2];
     a[1+(A>>3)] = ((uint8_t*)&crc)[1];
     a[2+(A>>3)] = ((uint8_t*)&crc)[0];
 
     dlsch->harq_processes[harq_pid]->B = A+24;
     memcpy(dlsch->harq_processes[harq_pid]->b,a,(A/8)+4);
+    //stop_meas(&eNB->dlsch_turbo_encoding_preperation_stats);
 
+    start_meas(&eNB->dlsch_turbo_encoding_segmentation_stats);
     if (lte_segmentation(dlsch->harq_processes[harq_pid]->b,
                          dlsch->harq_processes[harq_pid]->c,
                          dlsch->harq_processes[harq_pid]->B,
@@ -405,34 +453,41 @@ int dlsch_encoding_2threads(PHY_VARS_eNB *eNB,
                          &dlsch->harq_processes[harq_pid]->F)<0)
       return(-1);
 
-
-
-    if (proc->instance_cnt_te==0) {
-      printf("[eNB] TE thread busy\n");
-      exit_fun("TE thread busy");
-      pthread_mutex_unlock( &proc->mutex_te );
-      return(-1);
-    }
-
-    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_DLSCH_ENCODING, VCD_FUNCTION_OUT);
-    ++proc->instance_cnt_te;
-
-    proc->tep.eNB               = eNB;
-    proc->tep.dlsch             = dlsch;
-    proc->tep.G                 = G;
-    proc->tep.harq_pid          = harq_pid;
-
-    // wakeup worker to do second half segments
-    if (pthread_cond_signal(&proc->cond_te) != 0) {
-      printf("[eNB] ERROR pthread_cond_signal for te thread exit\n");
-      exit_fun( "ERROR pthread_cond_signal" );
-      return (-1);
+    stop_meas(&eNB->dlsch_turbo_encoding_segmentation_stats);
+    
+    start_meas(&eNB->dlsch_turbo_encoding_signal_stats);
+    for(int i=0;i<worker_num;i++)
+    {
+      proc->tep[i].eNB               = eNB;
+      proc->tep[i].dlsch             = dlsch;
+      proc->tep[i].G                 = G;
+      proc->tep[i].harq_pid          = harq_pid;
+      proc->tep[i].total_worker      = worker_num;
+      proc->tep[i].current_worker    = i;
+    
+      pthread_mutex_lock( &proc->tep[i].mutex_te );
+      if (proc->tep[i].instance_cnt_te==0) {
+        printf("[eNB] TE thread busy\n");
+        exit_fun("TE thread busy");
+        pthread_mutex_unlock( &proc->tep[i].mutex_te );
+        return(-1);
+      }
+      
+      ++proc->tep[i].instance_cnt_te;
+      
+      // wakeup worker to do segments
+      if (pthread_cond_signal(&proc->tep[i].cond_te) != 0) {
+        printf("[eNB] ERROR pthread_cond_signal for te thread %d exit\n",i);
+        exit_fun( "ERROR pthread_cond_signal" );
+        return (-1);
+      }
+      
+      pthread_mutex_unlock( &proc->tep[i].mutex_te );
     }
 
-    pthread_mutex_unlock( &proc->mutex_te );
-
-    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_DLSCH_ENCODING, VCD_FUNCTION_IN);
-    for (r=dlsch->harq_processes[harq_pid]->C>>1; r<dlsch->harq_processes[harq_pid]->C; r++) {
+    stop_meas(&eNB->dlsch_turbo_encoding_signal_stats);
+    start_meas(te_main_stats);
+    for (r=(dlsch->harq_processes[harq_pid]->C/(worker_num+1))*worker_num; r<dlsch->harq_processes[harq_pid]->C; r++) {
 
       if (r<dlsch->harq_processes[harq_pid]->Cminus)
         Kr = dlsch->harq_processes[harq_pid]->Kminus;
@@ -477,15 +532,18 @@ int dlsch_encoding_2threads(PHY_VARS_eNB *eNB,
   }
   else {
 
-    proc->tep.eNB          = eNB;
-    proc->tep.dlsch        = dlsch;
-    proc->tep.G            = G;
-
-    // wakeup worker to do second half segments
-    if (pthread_cond_signal(&proc->cond_te) != 0) {
+    for(int i=0;i<worker_num;i++)
+    {
+      proc->tep[i].eNB               = eNB;
+      proc->tep[i].dlsch             = dlsch;
+      proc->tep[i].G                 = G;
+      proc->tep[i].total_worker      = worker_num;
+      proc->tep[i].current_worker    = i;
+      if (pthread_cond_signal(&proc->tep[i].cond_te) != 0) {
       printf("[eNB] ERROR pthread_cond_signal for te thread exit\n");
       exit_fun( "ERROR pthread_cond_signal" );
       return (-1);
+      }
     }
   }
 
@@ -495,7 +553,7 @@ int dlsch_encoding_2threads(PHY_VARS_eNB *eNB,
   for (r=0,r_offset=0; r<dlsch->harq_processes[harq_pid]->C; r++) {
 
     // get information for E for the segments that are handled by the worker thread
-    if (r<(dlsch->harq_processes[harq_pid]->C>>1)) {
+    if (r<(dlsch->harq_processes[harq_pid]->C/(worker_num+1))*worker_num) {
       int Nl=dlsch->harq_processes[harq_pid]->Nl;
       int Qm=dlsch->harq_processes[harq_pid]->Qm;
       int C = dlsch->harq_processes[harq_pid]->C;
@@ -525,16 +583,138 @@ int dlsch_encoding_2threads(PHY_VARS_eNB *eNB,
       stop_meas(rm_stats);
     }
   }
+  stop_meas(te_main_stats);
 
-  // wait for worker to finish
-
-  wait_on_busy_condition(&proc->mutex_te,&proc->cond_te,&proc->instance_cnt_te,"te thread");
+  start_meas(te_wait_stats);
+  if(worker_num == 1)
+  {
+    wait_on_busy_condition(&proc->tep[0].mutex_te,&proc->tep[0].cond_te,&proc->tep[0].instance_cnt_te,"te thread 0");
+  }
+  else if(worker_num == 2)
+  {
+    wait_on_busy_condition(&proc->tep[0].mutex_te,&proc->tep[0].cond_te,&proc->tep[0].instance_cnt_te,"te thread 0");
+    wait_on_busy_condition(&proc->tep[1].mutex_te,&proc->tep[1].cond_te,&proc->tep[1].instance_cnt_te,"te thread 1");
+  }
+  else
+  {
+    wait_on_busy_condition(&proc->tep[0].mutex_te,&proc->tep[0].cond_te,&proc->tep[0].instance_cnt_te,"te thread 0");
+    wait_on_busy_condition(&proc->tep[1].mutex_te,&proc->tep[1].cond_te,&proc->tep[1].instance_cnt_te,"te thread 1");
+    wait_on_busy_condition(&proc->tep[2].mutex_te,&proc->tep[2].cond_te,&proc->tep[2].instance_cnt_te,"te thread 2");
+  }
+  stop_meas(te_wait_stats);
+  
+  /*if(opp_enabled == 1 && te_wait_stats->diff_now>100*3000){
+    print_meas_now(te_wait_stats,"coding_wait",stderr);
+	printf("coding delay in wait on codition in frame_rx: %d \n",proc->frame_rx);
+  }*/
 
 
   VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_DLSCH_ENCODING, VCD_FUNCTION_OUT);
 
   return(0);
 }
+int dlsch_encoding_all(PHY_VARS_eNB *eNB,
+		   unsigned char *a,
+                   uint8_t num_pdcch_symbols,
+                   LTE_eNB_DLSCH_t *dlsch,
+                   int frame,
+                   uint8_t subframe,
+                   time_stats_t *rm_stats,
+                   time_stats_t *te_stats,
+				   time_stats_t *te_wait_stats,
+                   time_stats_t *te_main_stats,
+                   time_stats_t *te_wakeup_stats0,
+                   time_stats_t *te_wakeup_stats1,
+                   time_stats_t *i_stats)
+{
+	int encoding_return = 0;
+	unsigned int L,C,B;
+	B = dlsch->harq_processes[dlsch->harq_ids[subframe]]->B;
+	if(B<=6144)
+	{
+		L=0;
+		C=1;
+	}
+	else
+	{
+		L=24;
+		C = B/(6144-L);
+		if((6144-L)*C < B)
+		{
+			C = C+1;
+		}
+	}
+
+    if(C >= 8 && get_nprocs()>=16 && codingw)//one main three worker
+    {
+        encoding_return =
+		dlsch_encoding_2threads(eNB,
+				   a,
+                   num_pdcch_symbols,
+                   dlsch,
+                   frame,
+                   subframe,
+                   rm_stats,
+                   te_stats,
+                   te_wait_stats,
+                   te_main_stats,
+                   te_wakeup_stats0,
+                   te_wakeup_stats1,
+                   i_stats,
+                   3);
+    }
+    else if(C >= 6 && get_nprocs()>=8 && codingw)//one main two worker
+    {
+        encoding_return =
+		dlsch_encoding_2threads(eNB,
+				   a,
+                   num_pdcch_symbols,
+                   dlsch,
+                   frame,
+                   subframe,
+                   rm_stats,
+                   te_stats,
+                   te_wait_stats,
+                   te_main_stats,
+                   te_wakeup_stats0,
+                   te_wakeup_stats1,
+                   i_stats,
+                   2);
+    }
+    else if(C >= 4 && get_nprocs()>=4 && codingw)//one main one worker
+    {
+        encoding_return =
+		dlsch_encoding_2threads(eNB,
+				   a,
+                   num_pdcch_symbols,
+                   dlsch,
+                   frame,
+                   subframe,
+                   rm_stats,
+                   te_stats,
+                   te_wait_stats,
+                   te_main_stats,
+                   te_wakeup_stats0,
+                   te_wakeup_stats1,
+                   i_stats,
+                   1);
+    }
+	else
+	{
+		encoding_return =
+		dlsch_encoding(eNB,
+				   a,
+                   num_pdcch_symbols,
+                   dlsch,
+                   frame,
+                   subframe,
+                   rm_stats,
+                   te_stats,
+                   i_stats);
+	}
+	return encoding_return;
+}
+
 
 int dlsch_encoding(PHY_VARS_eNB *eNB,
 		   unsigned char *a,
diff --git a/openair1/PHY/LTE_TRANSPORT/dlsch_modulation.c b/openair1/PHY/LTE_TRANSPORT/dlsch_modulation.c
index 417ee7f3616068ec60d807d1a468fd3abbe66b54..9ade420ccf173315dfed8d07f0dcc38b617739e9 100644
--- a/openair1/PHY/LTE_TRANSPORT/dlsch_modulation.c
+++ b/openair1/PHY/LTE_TRANSPORT/dlsch_modulation.c
@@ -37,7 +37,8 @@
 #include "PHY/LTE_TRANSPORT/transport_eNB.h"
 #include "UTIL/LOG/vcd_signal_dumper.h"
 
-//#define DEBUG_DLSCH_MODULATION 1
+//#define DEBUG_DLSCH_MODULATION
+#define NEW_ALLOC_RE
 
 //#define is_not_pilot(pilots,re,nushift,use2ndpilots) ((pilots==0) || ((re!=nushift) && (re!=nushift+6)&&((re!=nushift+3)||(use2ndpilots==1))&&((re!=nushift+9)||(use2ndpilots==1)))?1:0)
 
@@ -119,6 +120,17 @@ void generate_16qam_table(void)
     }
 }
 
+void generate_qpsk_table(void)
+{
+
+  int a,index;
+
+  for (a=-1; a<=1; a+=2) {
+    index = (1+a)/2;
+    qpsk_table[index] = -a*QPSK;  
+  }
+}
+
 
 
 
@@ -156,6 +168,158 @@ void layer1prec2A(int32_t *antenna0_sample, int32_t *antenna1_sample, uint8_t pr
 uint32_t FOUR[2]={0,4};
 uint32_t TWO[2]={0,2};
 
+int allocate_REs_in_RB_no_pilots_QPSK_siso(PHY_VARS_eNB* phy_vars_eNB,
+                                           int **txdataF,
+                                           uint32_t *jj,
+                                           uint32_t *jj2,
+                                           uint16_t re_offset,
+                                           uint32_t symbol_offset,
+                                           LTE_DL_eNB_HARQ_t *dlsch0_harq,
+                                           LTE_DL_eNB_HARQ_t *dlsch1_harq,
+                                           uint8_t pilots,
+                                           int16_t amp,
+                                           uint8_t precoder_index,
+                                           int16_t *qam_table_s0,
+                                           int16_t *qam_table_s1,
+                                           uint32_t *re_allocated,
+                                           uint8_t skip_dc,
+                                           uint8_t skip_half,
+                                           uint8_t lprime,
+                                           uint8_t mprime,
+                                           uint8_t Ns,
+                                           int *P1_SHIFT,
+                                           int *P2_SHIFT)
+{
+
+  LTE_DL_FRAME_PARMS *frame_parms = &phy_vars_eNB->frame_parms;
+  uint8_t *x0             = dlsch0_harq->e;
+  uint32_t qpsk_table_offset_re = 0;
+  uint32_t qpsk_table_offset_im = 0;
+
+  uint32_t tti_offset;
+  uint8_t re;
+  uint8_t *x0p;
+
+  if (skip_dc == 0) {
+    for (x0p=&x0[*jj],tti_offset=symbol_offset+re_offset,re=0;
+         re<12;
+         re++,x0p+=2,tti_offset++) {
+
+      qpsk_table_offset_re=x0p[0];
+      qpsk_table_offset_im=x0p[1];
+      ((int16_t *)&txdataF[0][tti_offset])[0]=qam_table_s0[qpsk_table_offset_re];
+      ((int16_t *)&txdataF[0][tti_offset])[1]=qam_table_s0[qpsk_table_offset_im];
+    }
+  }
+  else {
+    // 1st half of PRB
+    for (x0p=&x0[*jj],tti_offset=symbol_offset+re_offset,re=0;
+         re<6;
+         re++,x0p+=2,tti_offset++) {
+
+      qpsk_table_offset_re=x0p[0];
+      qpsk_table_offset_im=x0p[1];
+      ((int16_t *)&txdataF[0][tti_offset])[0]=qam_table_s0[qpsk_table_offset_re];
+      ((int16_t *)&txdataF[0][tti_offset])[1]=qam_table_s0[qpsk_table_offset_im];
+    }
+    // 2nd half of PRB
+    for (tti_offset=symbol_offset+re_offset-frame_parms->ofdm_symbol_size+7;
+         re<12;
+         re++,x0p+=2,tti_offset++) {
+
+      qpsk_table_offset_re=x0p[0];
+      qpsk_table_offset_im=x0p[1];
+      ((int16_t *)&txdataF[0][tti_offset])[0]=qam_table_s0[qpsk_table_offset_re];
+      ((int16_t *)&txdataF[0][tti_offset])[1]=qam_table_s0[qpsk_table_offset_im];
+    }
+  }
+  *re_allocated = *re_allocated + 12;
+  *jj=*jj + 24;
+
+    return(0);
+}
+
+int allocate_REs_in_RB_pilots_QPSK_siso(PHY_VARS_eNB* phy_vars_eNB,
+                                        int **txdataF,
+                                        uint32_t *jj,
+                                        uint32_t *jj2,
+                                        uint16_t re_offset,
+                                        uint32_t symbol_offset,
+                                        LTE_DL_eNB_HARQ_t *dlsch0_harq,
+                                        LTE_DL_eNB_HARQ_t *dlsch1_harq,
+                                        uint8_t pilots,
+                                        int16_t amp,
+                                        uint8_t precoder_index,
+                                        int16_t *qam_table_s0,
+                                        int16_t *qam_table_s1,
+                                        uint32_t *re_allocated,
+                                        uint8_t skip_dc,
+                                        uint8_t skip_half,
+                                        uint8_t lprime,
+                                        uint8_t mprime,
+                                        uint8_t Ns,
+                                        int *P1_SHIFT,
+                                        int *P2_SHIFT)
+{
+
+
+  LTE_DL_FRAME_PARMS *frame_parms=&phy_vars_eNB->frame_parms;
+
+  uint8_t *x0             = dlsch0_harq->e;
+  uint32_t qpsk_table_offset_re = 0;
+  uint32_t qpsk_table_offset_im = 0;
+
+  uint32_t tti_offset;
+  uint8_t re;
+  uint8_t *x0p;
+
+
+  if (skip_dc == 0) {
+    //    printf("pilots: P1_SHIFT[0] %d\n",P1_SHIFT[0]);
+    for (x0p=&x0[*jj],tti_offset=symbol_offset+re_offset+P1_SHIFT[0],re=P1_SHIFT[0];
+         re<12;
+         x0p+=2) {
+
+      qpsk_table_offset_re=x0p[0];
+      qpsk_table_offset_im=x0p[1];
+      ((int16_t *)&txdataF[0][tti_offset])[0]=qam_table_s0[qpsk_table_offset_re];
+      ((int16_t *)&txdataF[0][tti_offset])[1]=qam_table_s0[qpsk_table_offset_im];
+      //      printf("pilots: re %d, tti_offset %d, P1_SHIFT %d\n",re,tti_offset,P1_SHIFT[re+1]);
+      tti_offset+=P1_SHIFT[re+1];
+      re+=P1_SHIFT[re+1];
+    }
+  }
+  else {
+    for (x0p=&x0[*jj],tti_offset=symbol_offset+re_offset+P1_SHIFT[0],re=P1_SHIFT[0];
+         re<6;
+         x0p+=2) {
+
+      qpsk_table_offset_re+=x0p[0];
+      qpsk_table_offset_im+=x0p[1];
+      ((int16_t *)&txdataF[0][tti_offset])[0]=qam_table_s0[qpsk_table_offset_re];
+      ((int16_t *)&txdataF[0][tti_offset])[1]=qam_table_s0[qpsk_table_offset_im];
+      tti_offset+=P1_SHIFT[re+1];
+      re+=P1_SHIFT[re+1];
+    }
+
+    for (tti_offset=symbol_offset+re_offset-frame_parms->ofdm_symbol_size+6+P1_SHIFT[6];
+         re<12;
+         x0p+=2) {
+
+      qpsk_table_offset_re+=x0p[0];
+      qpsk_table_offset_im+=x0p[1];
+      ((int16_t *)&txdataF[0][tti_offset])[0]=qam_table_s0[qpsk_table_offset_re];
+      ((int16_t *)&txdataF[0][tti_offset])[1]=qam_table_s0[qpsk_table_offset_im];
+      tti_offset+=P1_SHIFT[re+1];
+      re+=P1_SHIFT[re+1];
+    }
+  }
+  *re_allocated = *re_allocated + 10;
+  *jj=*jj + 20;
+
+  return(0);
+}
+
 int allocate_REs_in_RB_no_pilots_16QAM_siso(PHY_VARS_eNB* phy_vars_eNB,
                                             int **txdataF,
                                             uint32_t *jj,
@@ -2010,11 +2174,11 @@ int dlsch_modulation(PHY_VARS_eNB* phy_vars_eNB,
   uint8_t mod_order0 = 0;
   uint8_t mod_order1 = 0;
   int16_t amp_rho_a, amp_rho_b;
-  int16_t qam16_table_a0[4],qam64_table_a0[8],qam16_table_b0[4],qam64_table_b0[8];
-  int16_t qam16_table_a1[4],qam64_table_a1[8],qam16_table_b1[4],qam64_table_b1[8];
+  int16_t qam16_table_a0[4],qam64_table_a0[8],qam16_table_b0[4],qam64_table_b0[8];//qpsk_table_a0[2],qpsk_table_b0[2]
+  int16_t qam16_table_a1[4],qam64_table_a1[8],qam16_table_b1[4],qam64_table_b1[8];//qpsk_table_a1[2],qpsk_table_b1[2]
 
   int16_t *qam_table_s0=NULL,*qam_table_s1=NULL;
-#if 0
+#ifdef NEW_ALLOC_RE
   /* TODO: variable to be removed? */
   int (*allocate_REs)(PHY_VARS_eNB*,
                       int **,
@@ -2124,8 +2288,15 @@ int dlsch_modulation(PHY_VARS_eNB* phy_vars_eNB,
   amp_rho_b = (int16_t)(((int32_t)amp*dlsch1->sqrt_rho_b)>>13);
   }
 
-
-  if (mod_order0 == 4)
+  /*if(mod_order0 == 2)
+  {
+    for(i=0;i<2;i++)
+    {
+      qpsk_table_a0[i] = (int16_t)(((int32_t)qpsk_table[i]*amp_rho_a)>>15);
+      qpsk_table_b0[i] = (int16_t)(((int32_t)qpsk_table[i]*amp_rho_b)>>15);
+    }
+  }
+  else*/ if (mod_order0 == 4)
     for (i=0;i<4; i++) {
       qam16_table_a0[i] = (int16_t)(((int32_t)qam16_table[i]*amp_rho_a)>>15);
       qam16_table_b0[i] = (int16_t)(((int32_t)qam16_table[i]*amp_rho_b)>>15);
@@ -2136,7 +2307,14 @@ int dlsch_modulation(PHY_VARS_eNB* phy_vars_eNB,
       qam64_table_b0[i] = (int16_t)(((int32_t)qam64_table[i]*amp_rho_b)>>15);
     }
 
-  if (mod_order1 == 4)
+  /*if (mod_order1 == 2)
+  {
+    for (i=0; i<2; i++) {
+      qpsk_table_a1[i] = (int16_t)(((int32_t)qpsk_table[i]*amp_rho_a)>>15);
+      qpsk_table_b1[i] = (int16_t)(((int32_t)qpsk_table[i]*amp_rho_b)>>15);
+    }
+  }
+  else*/ if (mod_order1 == 4)
     for (i=0; i<4; i++) {
       qam16_table_a1[i] = (int16_t)(((int32_t)qam16_table[i]*amp_rho_a)>>15);
       qam16_table_b1[i] = (int16_t)(((int32_t)qam16_table[i]*amp_rho_b)>>15);
@@ -2258,7 +2436,7 @@ int dlsch_modulation(PHY_VARS_eNB* phy_vars_eNB,
     re_offset = frame_parms->first_carrier_offset;
     symbol_offset = (uint32_t)frame_parms->ofdm_symbol_size*(l+(subframe_offset*nsymb));
 
-#if 0
+#ifdef NEW_ALLOC_RE
     /* TODO: remove this code? */
     allocate_REs = allocate_REs_in_RB;
 #endif
@@ -2266,11 +2444,30 @@ int dlsch_modulation(PHY_VARS_eNB* phy_vars_eNB,
     switch (mod_order0) {
     case 2:
       qam_table_s0 = NULL;
+      /*if (pilots) {
+        qam_table_s0 = qpsk_table_b0;
+#ifdef NEW_ALLOC_RE
+        // TODO: remove this code? //
+        allocate_REs = (dlsch0->harq_processes[harq_pid]->mimo_mode == SISO) ?
+          allocate_REs_in_RB_pilots_QPSK_siso :
+          allocate_REs_in_RB;
+#endif
+      }
+      else {
+        qam_table_s0 = qpsk_table_a0;
+#ifdef NEW_ALLOC_RE
+        // TODO: remove this code? //
+        allocate_REs = (dlsch0->harq_processes[harq_pid]->mimo_mode == SISO) ?
+          allocate_REs_in_RB_no_pilots_QPSK_siso :
+          allocate_REs_in_RB;
+#endif
+
+      }*/
       break;
     case 4:
       if (pilots) {
         qam_table_s0 = qam16_table_b0;
-#if 0
+#ifdef NEW_ALLOC_RE
         /* TODO: remove this code? */
         allocate_REs = (dlsch0->harq_processes[harq_pid]->mimo_mode == SISO) ?
           allocate_REs_in_RB_pilots_16QAM_siso :
@@ -2279,7 +2476,7 @@ int dlsch_modulation(PHY_VARS_eNB* phy_vars_eNB,
       }
       else {
         qam_table_s0 = qam16_table_a0;
-#if 0
+#ifdef NEW_ALLOC_RE
         /* TODO: remove this code? */
         allocate_REs = (dlsch0->harq_processes[harq_pid]->mimo_mode == SISO) ?
           allocate_REs_in_RB_no_pilots_16QAM_siso :
@@ -2292,7 +2489,7 @@ int dlsch_modulation(PHY_VARS_eNB* phy_vars_eNB,
     case 6:
       if (pilots) {
         qam_table_s0 = qam64_table_b0;
-#if 0
+#ifdef NEW_ALLOC_RE
         /* TODO: remove this code? */
         allocate_REs = (dlsch0->harq_processes[harq_pid]->mimo_mode == SISO) ?
           allocate_REs_in_RB_pilots_64QAM_siso :
@@ -2301,7 +2498,7 @@ int dlsch_modulation(PHY_VARS_eNB* phy_vars_eNB,
       }
       else {
         qam_table_s0 = qam64_table_a0;
-#if 0
+#ifdef NEW_ALLOC_RE
         /* TODO: remove this code? */
         allocate_REs = (dlsch0->harq_processes[harq_pid]->mimo_mode == SISO) ?
           allocate_REs_in_RB_no_pilots_64QAM_siso :
@@ -2315,10 +2512,16 @@ int dlsch_modulation(PHY_VARS_eNB* phy_vars_eNB,
     switch (mod_order1) {
     case 2:
       qam_table_s1 = NULL;
-#if 0
+#ifdef NEW_ALLOC_RE
         /* TODO: remove this code? */
       allocate_REs = allocate_REs_in_RB;
 #endif
+      /*if (pilots) {
+        qam_table_s1 = qpsk_table_b1;
+      }
+      else {
+        qam_table_s1 = qpsk_table_a1;
+      }*/
       break;
     case 4:
       if (pilots) {
diff --git a/openair1/PHY/LTE_TRANSPORT/transport_extern.h b/openair1/PHY/LTE_TRANSPORT/transport_extern.h
index f3c10b26caa3e9dc7d2c0364ff84afea758c7896..6a9fa49405a9bb3d8d3161aedc4ab4b1159b44c7 100644
--- a/openair1/PHY/LTE_TRANSPORT/transport_extern.h
+++ b/openair1/PHY/LTE_TRANSPORT/transport_extern.h
@@ -30,7 +30,7 @@ extern short *ul_ref_sigs_rx[30][2][33];
 extern unsigned short dftsizes[33];
 extern unsigned short ref_primes[33];
 
-extern int qam64_table[8],qam16_table[4];
+extern int qam64_table[8],qam16_table[4],qpsk_table[2];
 
 extern unsigned char cs_ri_normal[4];
 extern unsigned char cs_ri_extended[4];
diff --git a/openair1/PHY/LTE_TRANSPORT/transport_proto.h b/openair1/PHY/LTE_TRANSPORT/transport_proto.h
index b61828c16ae01a682c0d9edfa9d9d079a359042b..0202c9579fe7d22bf36c50e8a60058becb670f8a 100644
--- a/openair1/PHY/LTE_TRANSPORT/transport_proto.h
+++ b/openair1/PHY/LTE_TRANSPORT/transport_proto.h
@@ -450,6 +450,11 @@ void rx_ulsch(PHY_VARS_eNB *eNB,
               uint8_t UE_id);
 
 
+int ulsch_decoding_data_all(PHY_VARS_eNB *eNB,
+                        int UE_id,
+                        int harq_pid,
+                        int llr8_flag);
+
 /*!
   \brief Decoding of PUSCH/ACK/RI/ACK from 36-212.
   @param phy_vars_eNB Pointer to eNB top-level descriptor
diff --git a/openair1/PHY/LTE_TRANSPORT/transport_vars.h b/openair1/PHY/LTE_TRANSPORT/transport_vars.h
index 5ab7df1adecd89c4a6e140ba91616cd75e525948..611028e1e9805d748de9c9c4f77ba0b8856b2170 100644
--- a/openair1/PHY/LTE_TRANSPORT/transport_vars.h
+++ b/openair1/PHY/LTE_TRANSPORT/transport_vars.h
@@ -62,7 +62,7 @@ unsigned char ue_power_offsets[25] = {14,11,9,8,7,6,6,5,4,4,4,3,3,3,2,2,2,1,1,1,
 short conjugate[8]__attribute__((aligned(16))) = {-1,1,-1,1,-1,1,-1,1};
 short conjugate2[8]__attribute__((aligned(16))) = {1,-1,1,-1,1,-1,1,-1};
 
-int qam64_table[8],qam16_table[4];
+int qam64_table[8],qam16_table[4],qpsk_table[2];
 
 unsigned char cs_ri_normal[4]    = {1,4,7,10};
 unsigned char cs_ri_extended[4]  = {0,3,5,8};
diff --git a/openair1/PHY/LTE_TRANSPORT/ulsch_decoding.c b/openair1/PHY/LTE_TRANSPORT/ulsch_decoding.c
index dc202ab48803fa6a70e246f4e2b4d42a2fa21ef9..97cf5b827a71e36069c0adb29e35eb49815d5485 100644
--- a/openair1/PHY/LTE_TRANSPORT/ulsch_decoding.c
+++ b/openair1/PHY/LTE_TRANSPORT/ulsch_decoding.c
@@ -30,6 +30,8 @@
 * \warning
 */
 
+
+#include <syscall.h>
 #include "PHY/defs_eNB.h"
 #include "PHY/phy_extern.h"
 #include "PHY/CODING/coding_extern.h"
@@ -38,9 +40,11 @@
 #include "RRC/LTE/rrc_extern.h"
 #include "PHY_INTERFACE/phy_interface.h"
 
-
 #include "UTIL/LOG/vcd_signal_dumper.h"
 //#define DEBUG_ULSCH_DECODING
+#include "targets/RT/USER/rt_wrapper.h"
+
+extern int codingw;
 
 void free_eNB_ulsch(LTE_eNB_ULSCH_t *ulsch)
 {
@@ -216,8 +220,6 @@ uint8_t extract_cqi_crc(uint8_t *cqi,uint8_t CQI_LENGTH)
 
 
 
-
-
 int ulsch_decoding_data_2thread0(td_params* tdp) {
 
   PHY_VARS_eNB *eNB = tdp->eNB;
@@ -409,13 +411,20 @@ int ulsch_decoding_data_2thread0(td_params* tdp) {
 
 extern int oai_exit;
 void *td_thread(void *param) {
-  pthread_setname_np( pthread_self(), "td processing");
   PHY_VARS_eNB *eNB = ((td_params*)param)->eNB;
   eNB_proc_t *proc  = &eNB->proc;
+  cpu_set_t cpuset;
+  CPU_ZERO(&cpuset);
+  
+  thread_top_init("td_thread",1,200000,250000,500000);
+  pthread_setname_np( pthread_self(),"td processing");
+  LOG_I(PHY,"thread td created id=%ld\n", syscall(__NR_gettid));
+  //wait_sync("td_thread");
 
   while (!oai_exit) {
 
     if (wait_on_condition(&proc->mutex_td,&proc->cond_td,&proc->instance_cnt_td,"td thread")<0) break;  
+    if(oai_exit) break;
 
     ((td_params*)param)->ret = ulsch_decoding_data_2thread0((td_params*)param);
 
@@ -618,6 +627,7 @@ int ulsch_decoding_data_2thread(PHY_VARS_eNB *eNB,int UE_id,int harq_pid,int llr
       break;
     }
     stop_meas(&eNB->ulsch_turbo_decoding_stats);    
+  //printf("/////////////////////////////////////////**************************loop for %d time in ulsch_decoding main\n",r);
   }
 
    // wait for worker to finish
@@ -777,6 +787,20 @@ int ulsch_decoding_data(PHY_VARS_eNB *eNB,int UE_id,int harq_pid,int llr8_flag)
   return(ret);
 }
 
+int ulsch_decoding_data_all(PHY_VARS_eNB *eNB,int UE_id,int harq_pid,int llr8_flag) 
+{
+  int ret = 0;
+  /*if(codingw)
+  {
+    ret = ulsch_decoding_data_2thread(eNB,UE_id,harq_pid,llr8_flag);
+  }
+  else*/
+  {
+    ret = ulsch_decoding_data(eNB,UE_id,harq_pid,llr8_flag);
+  }
+  return ret;
+}
+
 static inline unsigned int lte_gold_unscram(unsigned int *x1, unsigned int *x2, unsigned char reset) __attribute__((always_inline));
 static inline unsigned int lte_gold_unscram(unsigned int *x1, unsigned int *x2, unsigned char reset)
 {
diff --git a/openair1/PHY/LTE_UE_TRANSPORT/dlsch_demodulation.c b/openair1/PHY/LTE_UE_TRANSPORT/dlsch_demodulation.c
index dabb845a42a088d95eda718f5eac8f83252a71a8..665d5cead04d59a18aaebce0701066b9f1861600 100644
--- a/openair1/PHY/LTE_UE_TRANSPORT/dlsch_demodulation.c
+++ b/openair1/PHY/LTE_UE_TRANSPORT/dlsch_demodulation.c
@@ -48,7 +48,7 @@ int16_t interf_unaw_shift = 13;
 
 //#define DEBUG_HARQ
 
-#define DEBUG_PHY 1
+//#define DEBUG_PHY 1
 //#define DEBUG_DLSCH_DEMOD 1
 
 //#define DISABLE_LOG_X
@@ -842,7 +842,7 @@ int rx_pdsch(PHY_VARS_UE *ue,
   pllr_symbol_cw1  = (int8_t*)pdsch_vars[eNB_id]->llr[1];
   pllr_symbol_cw0 += llr_offset_symbol;
   pllr_symbol_cw1 += llr_offset_symbol;
-
+  /*
   LOG_I(PHY,"compute LLRs [AbsSubframe %d.%d-%d] NbRB %d Qm %d LLRs-Length %d LLR-Offset %d @LLR Buff %p @LLR Buff(symb) %p\n",
              frame, subframe,symbol,
              nb_rb,dlsch0_harq->Qm,
@@ -850,7 +850,7 @@ int rx_pdsch(PHY_VARS_UE *ue,
              pdsch_vars[eNB_id]->llr_offset[symbol],
              (int16_t*)pdsch_vars[eNB_id]->llr[0],
              pllr_symbol_cw0);
-
+  */
   switch (dlsch0_harq->Qm) {
   case 2 :
     if ((rx_type==rx_standard) || (codeword_TB1 == -1)) {
diff --git a/openair1/PHY/LTE_UE_TRANSPORT/transport_proto_ue.h b/openair1/PHY/LTE_UE_TRANSPORT/transport_proto_ue.h
index d62bbed7942eb1d1d70d4b9a005a972fdad00a02..ba065b8e6fa342372d2da6f5463c5291ec6121e5 100644
--- a/openair1/PHY/LTE_UE_TRANSPORT/transport_proto_ue.h
+++ b/openair1/PHY/LTE_UE_TRANSPORT/transport_proto_ue.h
@@ -64,6 +64,7 @@ void free_ue_ulsch(LTE_UE_ULSCH_t *ulsch);
 
 LTE_UE_ULSCH_t *new_ue_ulsch(unsigned char N_RB_UL, uint8_t abstraction_flag);
 
+
 int rx_pmch(PHY_VARS_UE *phy_vars_ue,
             unsigned char eNB_id,
             uint8_t subframe,
@@ -1097,6 +1098,7 @@ void pbch_unscrambling(LTE_DL_FRAME_PARMS *frame_parms,
 
 void generate_64qam_table(void);
 void generate_16qam_table(void);
+void generate_qpsk_table(void);
 
 uint16_t extract_crc(uint8_t *dci,uint8_t DCI_LENGTH);
 
@@ -1402,6 +1404,7 @@ uint32_t ulsch_encoding(uint8_t *a,
 
 
 
+
 /* \brief  This routine demodulates the PHICH and updates PUSCH/ULSCH parameters.
    @param phy_vars_ue Pointer to UE variables
    @param proc Pointer to RXN_TXNp4 proc
diff --git a/openair1/PHY/TOOLS/time_meas.c b/openair1/PHY/TOOLS/time_meas.c
index d80832e243c9b0af7cea98e1d3da9fca0ff01b67..cb7775904099a769091795d62d23cc1b1d950b25 100644
--- a/openair1/PHY/TOOLS/time_meas.c
+++ b/openair1/PHY/TOOLS/time_meas.c
@@ -53,7 +53,7 @@ void print_meas_now(time_stats_t *ts, const char* name, FILE* file_name){
     if (ts->trials>0) {
 
       //fprintf(file_name,"Name %25s: Processing %15.3f ms for SF %d, diff_now %15.3f \n", name,(ts->diff_now/(cpu_freq_GHz*1000000.0)),subframe,ts->diff_now);
-      fprintf(file_name,"%15.3f ms, diff_now %15.3f \n",(ts->diff_now/(cpu_freq_GHz*1000000.0)),(double)ts->diff_now);
+      fprintf(file_name,"%15.3f us, diff_now %15.3f \n",(ts->diff_now/(cpu_freq_GHz*1000.0)),(double)ts->diff_now);
       
     }
   }
diff --git a/openair1/PHY/defs_eNB.h b/openair1/PHY/defs_eNB.h
index d39d187a5332eb7230f6318f1bf0ac3121978fdd..a96b532a1e1b976a0e0553eaacaa812416863230 100644
--- a/openair1/PHY/defs_eNB.h
+++ b/openair1/PHY/defs_eNB.h
@@ -71,6 +71,7 @@
 
 #include "openair2/PHY_INTERFACE/IF_Module.h"
 
+
 typedef struct RU_proc_t_s {
   /// Pointer to associated RU descriptor
   struct RU_t_s *ru;
@@ -105,6 +106,7 @@ typedef struct RU_proc_t_s {
   /// \brief Instance count for FH processing thread.
   /// \internal This variable is protected by \ref mutex_FH.
   int instance_cnt_FH;
+  int instance_cnt_FH1;
   /// \internal This variable is protected by \ref mutex_prach.
   int instance_cnt_prach;
 #ifdef Rel14
@@ -120,10 +122,13 @@ typedef struct RU_proc_t_s {
   int instance_cnt_asynch_rxtx;
   /// \internal This variable is protected by \ref mutex_fep
   int instance_cnt_fep;
-  /// \internal This variable is protected by \ref mutex_fep
+  /// \internal This variable is protected by \ref mutex_feptx
   int instance_cnt_feptx;
+  /// This varible is protected by \ref mutex_emulatedRF
+  int instance_cnt_emulateRF;
   /// pthread structure for RU FH processing thread
   pthread_t pthread_FH;
+  pthread_t pthread_FH1;
   /// pthread structure for RU prach processing thread
   pthread_t pthread_prach;
 #ifdef Rel14
@@ -134,8 +139,10 @@ typedef struct RU_proc_t_s {
   pthread_t pthread_synch;
   /// pthread struct for RU RX FEP worker thread
   pthread_t pthread_fep;
-  /// pthread struct for RU RX FEPTX worker thread
+  /// pthread struct for RU TX FEP worker thread
   pthread_t pthread_feptx;
+  /// pthread struct for emulated RF
+  pthread_t pthread_emulateRF;
   /// pthread structure for asychronous RX/TX processing thread
   pthread_t pthread_asynch_rxtx;
   /// flag to indicate first RX acquisition
@@ -144,6 +151,7 @@ typedef struct RU_proc_t_s {
   int first_tx;
   /// pthread attributes for RU FH processing thread
   pthread_attr_t attr_FH;
+  pthread_attr_t attr_FH1;
   /// pthread attributes for RU prach
   pthread_attr_t attr_prach;
 #ifdef Rel14
@@ -158,8 +166,11 @@ typedef struct RU_proc_t_s {
   pthread_attr_t attr_fep;
   /// pthread attributes for worker feptx thread
   pthread_attr_t attr_feptx;
+  /// pthread attributes for emulated RF
+  pthread_attr_t attr_emulateRF;
   /// scheduling parameters for RU FH thread
   struct sched_param sched_param_FH;
+  struct sched_param sched_param_FH1;
   /// scheduling parameters for RU prach thread
   struct sched_param sched_param_prach;
 #ifdef Rel14
@@ -172,6 +183,7 @@ typedef struct RU_proc_t_s {
   struct sched_param sched_param_asynch_rxtx;
   /// condition variable for RU FH thread
   pthread_cond_t cond_FH;
+  pthread_cond_t cond_FH1;
   /// condition variable for RU prach thread
   pthread_cond_t cond_prach;
 #ifdef Rel14
@@ -182,14 +194,17 @@ typedef struct RU_proc_t_s {
   pthread_cond_t cond_synch;
   /// condition variable for asynch RX/TX thread
   pthread_cond_t cond_asynch_rxtx;
-  /// condition varaible for RU RX FEP thread
+  /// condition varible for RU RX FEP thread
   pthread_cond_t cond_fep;
-  /// condition varaible for RU RX FEPTX thread
+  /// condition varible for RU TX FEP thread
   pthread_cond_t cond_feptx;
+  /// condition varible for emulated RF
+  pthread_cond_t cond_emulateRF;
   /// condition variable for eNB signal
   pthread_cond_t cond_eNBs;
   /// mutex for RU FH
   pthread_mutex_t mutex_FH;
+  pthread_mutex_t mutex_FH1;
   /// mutex for RU prach
   pthread_mutex_t mutex_prach;
 #ifdef Rel14
@@ -206,14 +221,159 @@ typedef struct RU_proc_t_s {
   pthread_mutex_t mutex_fep;
   /// mutex for fep TX worker thread
   pthread_mutex_t mutex_feptx;
+  /// mutex for emulated RF thread
+  pthread_mutex_t mutex_emulateRF;
   /// symbol mask for IF4p5 reception per subframe
   uint32_t symbol_mask[10];
   /// number of slave threads
   int                  num_slaves;
   /// array of pointers to slaves
   struct RU_proc_t_s           **slave_proc;
+  /// pipeline ready state
+  int ru_rx_ready;
+  int ru_tx_ready;
 } RU_proc_t;
 
+/// Context data structure for eNB subframe processing
+typedef struct eNB_proc_t_s {
+  /// Component Carrier index
+  uint8_t              CC_id;
+  /// thread index
+  int thread_index;
+  /// timestamp received from HW
+  openair0_timestamp timestamp_rx;
+  /// timestamp to send to "slave rru"
+  openair0_timestamp timestamp_tx;
+  /// subframe to act upon for reception
+  int subframe_rx;
+  /// subframe to act upon for PRACH
+  int subframe_prach;
+#ifdef Rel14
+  /// subframe to act upon for reception of prach BL/CE UEs
+  int subframe_prach_br;
+#endif
+  /// frame to act upon for reception
+  int frame_rx;
+  /// frame to act upon for transmission
+  int frame_tx;
+  /// frame to act upon for PRACH
+  int frame_prach;
+#ifdef Rel14
+  /// frame to act upon for PRACH BL/CE UEs
+  int frame_prach_br;
+#endif
+  /// \internal This variable is protected by \ref mutex_td.
+  int instance_cnt_td;
+  /// \internal This variable is protected by \ref mutex_te.
+  //int instance_cnt_te[3];
+  /// \internal This variable is protected by \ref mutex_prach.
+  int instance_cnt_prach;
+#ifdef Rel14
+  /// \internal This variable is protected by \ref mutex_prach for BL/CE UEs.
+  int instance_cnt_prach_br;
+#endif
+  // instance count for over-the-air eNB synchronization
+  int instance_cnt_synch;
+  /// \internal This variable is protected by \ref mutex_asynch_rxtx.
+  int instance_cnt_asynch_rxtx;
+  /// pthread structure for eNB single processing thread
+  pthread_t pthread_single;
+  /// pthread structure for asychronous RX/TX processing thread
+  pthread_t pthread_asynch_rxtx;
+  /// flag to indicate first RX acquisition
+  int first_rx;
+  /// flag to indicate first TX transmission
+  int first_tx;
+  /// pthread attributes for parallel turbo-decoder thread
+  pthread_attr_t attr_td;
+  /// pthread attributes for parallel turbo-encoder thread
+  //pthread_attr_t attr_te[3];
+  /// pthread attributes for single eNB processing thread
+  pthread_attr_t attr_single;
+  /// pthread attributes for prach processing thread
+  pthread_attr_t attr_prach;
+#ifdef Rel14
+  /// pthread attributes for prach processing thread BL/CE UEs
+  pthread_attr_t attr_prach_br;
+#endif
+  /// pthread attributes for asynchronous RX thread
+  pthread_attr_t attr_asynch_rxtx;
+  /// scheduling parameters for parallel turbo-decoder thread
+  struct sched_param sched_param_td;
+  /// scheduling parameters for parallel turbo-encoder thread
+  //struct sched_param sched_param_te[3];
+  /// scheduling parameters for single eNB thread
+  struct sched_param sched_param_single;
+  /// scheduling parameters for prach thread
+  struct sched_param sched_param_prach;
+#ifdef Rel14
+  /// scheduling parameters for prach thread
+  struct sched_param sched_param_prach_br;
+#endif
+  /// scheduling parameters for asynch_rxtx thread
+  struct sched_param sched_param_asynch_rxtx;
+  /// pthread structure for parallel turbo-decoder thread
+  pthread_t pthread_td;
+  /// pthread structure for parallel turbo-encoder thread
+  //pthread_t pthread_te[3];
+  /// pthread structure for PRACH thread
+  pthread_t pthread_prach;
+#ifdef Rel14
+  /// pthread structure for PRACH thread BL/CE UEs
+  pthread_t pthread_prach_br;
+#endif
+  /// condition variable for parallel turbo-decoder thread
+  pthread_cond_t cond_td;
+  /// condition variable for parallel turbo-encoder thread
+  //pthread_cond_t cond_te[3];
+  /// condition variable for PRACH processing thread;
+  pthread_cond_t cond_prach;
+#ifdef Rel14
+  /// condition variable for PRACH processing thread BL/CE UEs;
+  pthread_cond_t cond_prach_br;
+#endif
+  /// condition variable for asynch RX/TX thread
+  pthread_cond_t cond_asynch_rxtx;
+  /// mutex for parallel turbo-decoder thread
+  pthread_mutex_t mutex_td;
+  /// mutex for parallel turbo-encoder thread
+  //pthread_mutex_t mutex_te[3];
+  /// mutex for PRACH thread
+  pthread_mutex_t mutex_prach;
+#ifdef Rel14
+  /// mutex for PRACH thread for BL/CE UEs
+  pthread_mutex_t mutex_prach_br;
+#endif
+  /// mutex for asynch RX/TX thread
+  pthread_mutex_t mutex_asynch_rxtx;
+  /// mutex for RU access to eNB processing (PDSCH/PUSCH)
+  pthread_mutex_t mutex_RU;
+  /// mutex for RU access to eNB processing (PRACH)
+  pthread_mutex_t mutex_RU_PRACH;
+  /// mutex for RU access to eNB processing (PRACH BR)
+  pthread_mutex_t mutex_RU_PRACH_br;
+  /// mask for RUs serving eNB (PDSCH/PUSCH)
+  int RU_mask;
+  /// mask for RUs serving eNB (PRACH)
+  int RU_mask_prach;
+#ifdef Rel14
+  /// mask for RUs serving eNB (PRACH)
+  int RU_mask_prach_br;
+#endif
+  /// parameters for turbo-decoding worker thread
+  td_params tdp;
+  /// parameters for turbo-encoding worker thread
+  te_params tep[3];
+  /// set of scheduling variables RXn-TXnp4 threads
+  eNB_rxtx_proc_t proc_rxtx[2];
+  /// stats thread pthread descriptor
+  pthread_t process_stats_thread;
+  /// for waking up tx procedure
+  RU_proc_t *ru_proc;
+} eNB_proc_t;
+
+
+
 
 
 typedef enum {
@@ -223,6 +383,7 @@ typedef enum {
   REMOTE_IF4p5    =3,
   REMOTE_IF1pp    =4,
   MAX_RU_IF_TYPES =5
+  //EMULATE_RF      =6
 } RU_if_south_t;
 
 typedef struct RU_t_s{
@@ -831,7 +992,7 @@ typedef struct PHY_VARS_eNB_s {
   eth_params_t         eth_params;
   int                  rx_total_gain_dB;
   int                  (*td)(struct PHY_VARS_eNB_s *eNB,int UE_id,int harq_pid,int llr8_flag);
-  int                  (*te)(struct PHY_VARS_eNB_s *,uint8_t *,uint8_t,LTE_eNB_DLSCH_t *,int,uint8_t,time_stats_t *,time_stats_t *,time_stats_t *);
+  int                  (*te)(struct PHY_VARS_eNB_s *,uint8_t *,uint8_t,LTE_eNB_DLSCH_t *,int,uint8_t,time_stats_t *,time_stats_t *,time_stats_t *,time_stats_t *,time_stats_t *,time_stats_t *,time_stats_t *);
   int                  (*start_if)(struct RU_t_s *ru,struct PHY_VARS_eNB_s *eNB);
   uint8_t              local_flag;
   LTE_DL_FRAME_PARMS   frame_parms;
@@ -1010,7 +1171,14 @@ typedef struct PHY_VARS_eNB_s {
   time_stats_t dlsch_modulation_stats;
   time_stats_t dlsch_scrambling_stats;
   time_stats_t dlsch_rate_matching_stats;
+  time_stats_t dlsch_turbo_encoding_preperation_stats;
+  time_stats_t dlsch_turbo_encoding_segmentation_stats;
   time_stats_t dlsch_turbo_encoding_stats;
+  time_stats_t dlsch_turbo_encoding_waiting_stats;
+  time_stats_t dlsch_turbo_encoding_signal_stats;
+  time_stats_t dlsch_turbo_encoding_main_stats;
+  time_stats_t dlsch_turbo_encoding_wakeup_stats0;
+  time_stats_t dlsch_turbo_encoding_wakeup_stats1;
   time_stats_t dlsch_interleaving_stats;
 
   time_stats_t rx_dft_stats;
diff --git a/openair1/PHY/impl_defs_top.h b/openair1/PHY/impl_defs_top.h
index 27c0a2e6aee39cd16cc628b8501e1e14a6071626..d4f23ae763880a452715ddeac3ff269d095560ec 100644
--- a/openair1/PHY/impl_defs_top.h
+++ b/openair1/PHY/impl_defs_top.h
@@ -203,6 +203,9 @@
 
 // QAM amplitude definitions
 
+/// Amplitude for QPSK (\f$ 2^15 \times 1/\sqrt{2}\f$)
+#define QPSK 23170
+
 /// First Amplitude for QAM16 (\f$ 2^{15} \times 2/\sqrt{10}\f$)
 #define QAM16_n1 20724
 /// Second Amplitude for QAM16 (\f$ 2^{15} \times 1/\sqrt{10}\f$)
diff --git a/openair1/SCHED/phy_procedures_lte_eNb.c b/openair1/SCHED/phy_procedures_lte_eNb.c
index 162c0919328b3c8d202f6c1932c59120d43ced10..3a73f2d6542831a137a69404ad8eb79d1ebb2158 100644
--- a/openair1/SCHED/phy_procedures_lte_eNb.c
+++ b/openair1/SCHED/phy_procedures_lte_eNb.c
@@ -392,14 +392,24 @@ void pdsch_procedures(PHY_VARS_eNB *eNB,
     start_meas(&eNB->dlsch_encoding_stats);
 
     eNB->te(eNB,
-        dlsch_harq->pdu,
-        dlsch_harq->pdsch_start,
-        dlsch,
-        frame,subframe,
-        &eNB->dlsch_rate_matching_stats,
-        &eNB->dlsch_turbo_encoding_stats,
-        &eNB->dlsch_interleaving_stats);
+	  dlsch_harq->pdu,
+	  dlsch_harq->pdsch_start,
+	  dlsch,
+	  frame,
+	  subframe,
+	  &eNB->dlsch_rate_matching_stats,
+	  &eNB->dlsch_turbo_encoding_stats,
+	  &eNB->dlsch_turbo_encoding_waiting_stats,
+      &eNB->dlsch_turbo_encoding_main_stats,
+      &eNB->dlsch_turbo_encoding_wakeup_stats0,
+      &eNB->dlsch_turbo_encoding_wakeup_stats1,
+	  &eNB->dlsch_interleaving_stats);
     stop_meas(&eNB->dlsch_encoding_stats);
+  //////////////////////////////////////////////////*******************************************
+  if(eNB->dlsch_encoding_stats.diff_now>500*3000 && opp_enabled == 1)
+  {
+    print_meas_now(&eNB->dlsch_encoding_stats,"total coding",stderr);
+  }
   // 36-211
     start_meas(&eNB->dlsch_scrambling_stats);
     dlsch_scrambling(fp,
@@ -589,6 +599,7 @@ void phy_procedures_eNB_TX(PHY_VARS_eNB *eNB,
         else
         {
           // generate pdsch
+
           pdsch_procedures(eNB,
               proc,
               harq_pid,
@@ -1402,37 +1413,63 @@ extern int oai_exit;
 
 extern void *td_thread(void*);
 
-void init_td_thread(PHY_VARS_eNB *eNB,pthread_attr_t *attr_td) {
+void init_td_thread(PHY_VARS_eNB *eNB) {
 
   eNB_proc_t *proc = &eNB->proc;
 
   proc->tdp.eNB = eNB;
   proc->instance_cnt_td         = -1;
-    
+  
+  pthread_attr_init( &proc->attr_td);  
   pthread_mutex_init( &proc->mutex_td, NULL);
   pthread_cond_init( &proc->cond_td, NULL);
+  
+  pthread_create(&proc->pthread_td, &proc->attr_td, td_thread, (void*)&proc->tdp);
 
-  pthread_create(&proc->pthread_td, attr_td, td_thread, (void*)&proc->tdp);
+}
+void kill_td_thread(PHY_VARS_eNB *eNB) {
 
+  eNB_proc_t *proc = &eNB->proc;
+  proc->instance_cnt_td         = 0;
+  pthread_cond_signal(&proc->cond_td);
+  
+  pthread_join(proc->pthread_td, NULL);
+  pthread_mutex_destroy( &proc->mutex_td );
+  pthread_cond_destroy( &proc->cond_td );
 }
 
 extern void *te_thread(void*);
 
-void init_te_thread(PHY_VARS_eNB *eNB,pthread_attr_t *attr_te) {
+void init_te_thread(PHY_VARS_eNB *eNB) {
 
   eNB_proc_t *proc = &eNB->proc;
 
-  proc->tep.eNB = eNB;
-  proc->instance_cnt_te         = -1;
+  for(int i=0; i<3 ;i++){
+    proc->tep[i].eNB = eNB;
+    proc->tep[i].instance_cnt_te         = -1;
+      
+    pthread_mutex_init( &proc->tep[i].mutex_te, NULL);
+    pthread_cond_init( &proc->tep[i].cond_te, NULL);
+    pthread_attr_init( &proc->tep[i].attr_te);
     
-  pthread_mutex_init( &proc->mutex_te, NULL);
-  pthread_cond_init( &proc->cond_te, NULL);
+    printf("Creating te_thread 0\n");
+    pthread_create(&proc->tep[i].pthread_te, &proc->tep[i].attr_te, te_thread, (void*)&proc->tep[i]);
+  }
+}
+void kill_te_thread(PHY_VARS_eNB *eNB) {
 
-  printf("Creating te_thread\n");
-  pthread_create(&proc->pthread_te, attr_te, te_thread, (void*)&proc->tep);
+  eNB_proc_t *proc = &eNB->proc;
 
+  for(int i=0; i<3 ;i++){
+    proc->tep[i].instance_cnt_te         = 0;
+    pthread_cond_signal(&proc->tep[i].cond_te);
+    pthread_join(proc->tep[i].pthread_te, NULL);
+    pthread_mutex_destroy( &proc->tep[i].mutex_te);
+    pthread_cond_destroy( &proc->tep[i].cond_te);
+  }
 }
 
+
 void fill_rx_indication(PHY_VARS_eNB *eNB,int UE_id,int frame,int subframe)
 {
   nfapi_rx_indication_pdu_t *pdu;
@@ -1667,6 +1704,7 @@ void fill_ulsch_harq_indication(PHY_VARS_eNB *eNB,LTE_UL_eNB_HARQ_t *ulsch_harq,
       // release DLSCH if needed
       release_harq(eNB,UE_id,i,frame,subframe,0xffff, ulsch_harq->o_ACK[i] == 1);
 
+
 #if T_TRACER
       /* TODO: get correct harq pid */
       if (ulsch_harq->o_ACK[i] != 1)
@@ -1765,6 +1803,7 @@ void fill_uci_harq_indication(PHY_VARS_eNB *eNB,
       // release DLSCH if needed
       release_harq(eNB,UE_id,0,frame,subframe,0xffff, harq_ack[0] == 1);
 
+
 #if T_TRACER
       if (harq_ack[0] != 1)
         T(T_ENB_PHY_DLSCH_UE_NACK, T_INT(0), T_INT(frame), T_INT(subframe),
diff --git a/openair1/SCHED/ru_procedures.c b/openair1/SCHED/ru_procedures.c
index a22b26a72016622fd9d2c65e6bff12da930a91c3..3d200fbd6166a168fedfba43f6a0951ef23229a0 100644
--- a/openair1/SCHED/ru_procedures.c
+++ b/openair1/SCHED/ru_procedures.c
@@ -136,12 +136,22 @@ static void *feptx_thread(void *param) {
 
   RU_t *ru = (RU_t *)param;
   RU_proc_t *proc  = &ru->proc;
+  cpu_set_t cpuset;
+  CPU_ZERO(&cpuset);
+  
+  thread_top_init("feptx_thread",1,85000,120000,500000);
+  pthread_setname_np( pthread_self(),"feptx processing");
+  LOG_I(PHY,"thread feptx created id=%ld\n", syscall(__NR_gettid));
+  //CPU_SET(6, &cpuset);
+  //pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset);
+  //wait_sync("feptx_thread");
 
-  thread_top_init("feptx_thread",0,870000,1000000,1000000);
+  
 
   while (!oai_exit) {
 
     if (wait_on_condition(&proc->mutex_feptx,&proc->cond_feptx,&proc->instance_cnt_feptx,"feptx thread")<0) break;  
+    //stop_meas(&ru->ofdm_mod_wakeup_stats);
     feptx0(ru,1);
     if (release_thread(&proc->mutex_feptx,&proc->instance_cnt_feptx,"feptx thread")<0) break;
 
@@ -150,6 +160,10 @@ static void *feptx_thread(void *param) {
       exit_fun( "ERROR pthread_cond_signal" );
       return NULL;
     }
+	/*if(opp_enabled == 1 && ru->ofdm_mod_wakeup_stats.diff_now>30*3000){
+      print_meas_now(&ru->ofdm_mod_wakeup_stats,"fep wakeup",stderr);
+      printf("delay in fep wakeup in frame_tx: %d  subframe_rx: %d \n",proc->frame_tx,proc->subframe_tx);
+    }*/
   }
 
 
@@ -166,7 +180,7 @@ void feptx_ofdm_2thread(RU_t *ru) {
 
   wait.tv_sec=0;
   wait.tv_nsec=5000000L;
-
+  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_RU_FEPTX_OFDM , 1 );
   start_meas(&ru->ofdm_mod_stats);
 
   if (subframe_select(fp,subframe) == SF_UL) return;
@@ -196,17 +210,25 @@ void feptx_ofdm_2thread(RU_t *ru) {
       exit_fun( "ERROR pthread_cond_signal" );
       return;
     }
+	//start_meas(&ru->ofdm_mod_wakeup_stats);
     
     pthread_mutex_unlock( &proc->mutex_feptx );
   }
 
   // call first slot in this thread
   feptx0(ru,0);
+  start_meas(&ru->ofdm_mod_wait_stats);
   wait_on_busy_condition(&proc->mutex_feptx,&proc->cond_feptx,&proc->instance_cnt_feptx,"feptx thread");  
+  stop_meas(&ru->ofdm_mod_wait_stats);
+  /*if(opp_enabled == 1 && ru->ofdm_mod_wait_stats.diff_now>30*3000){
+    print_meas_now(&ru->ofdm_mod_wait_stats,"fep wakeup",stderr);
+    printf("delay in feptx wait on codition in frame_rx: %d  subframe_rx: %d \n",proc->frame_tx,proc->subframe_tx);
+  }*/
 
   VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_RU_FEPTX_OFDM , 0 );
 
   stop_meas(&ru->ofdm_mod_stats);
+  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_RU_FEPTX_OFDM , 0 );
 
 }
 
@@ -424,12 +446,23 @@ static void *fep_thread(void *param) {
   RU_t *ru = (RU_t *)param;
   RU_proc_t *proc  = &ru->proc;
 
-  thread_top_init("fep_thread",0,870000,1000000,1000000);
+  thread_top_init("fep_thread",1,100000,120000,5000000);
+  pthread_setname_np( pthread_self(),"fep processing");
+  LOG_I(PHY,"thread fep created id=%ld\n", syscall(__NR_gettid));
+
+  cpu_set_t cpuset;
+  CPU_ZERO(&cpuset);
+  //CPU_SET(2, &cpuset);
+  //pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset);
+  //wait_sync("fep_thread");
 
   while (!oai_exit) {
 
-    if (wait_on_condition(&proc->mutex_fep,&proc->cond_fep,&proc->instance_cnt_fep,"fep thread")<0) break;  
+    if (wait_on_condition(&proc->mutex_fep,&proc->cond_fep,&proc->instance_cnt_fep,"fep thread")<0) break; 
+	//stop_meas(&ru->ofdm_demod_wakeup_stats);
+	VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_RU_FEPRX1, 1 ); 
     fep0(ru,0);
+	VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_RU_FEPRX1, 0 ); 
     if (release_thread(&proc->mutex_fep,&proc->instance_cnt_fep,"fep thread")<0) break;
 
     if (pthread_cond_signal(&proc->cond_fep) != 0) {
@@ -437,6 +470,10 @@ static void *fep_thread(void *param) {
       exit_fun( "ERROR pthread_cond_signal" );
       return NULL;
     }
+    /*if(opp_enabled == 1 && ru->ofdm_demod_wakeup_stats.diff_now>30*3000){
+      print_meas_now(&ru->ofdm_demod_wakeup_stats,"fep wakeup",stderr);
+      printf("delay in fep wakeup in frame_rx: %d  subframe_rx: %d \n",proc->frame_rx,proc->subframe_rx);
+    }*/
   }
 
 
@@ -487,6 +524,7 @@ void ru_fep_full_2thread(RU_t *ru) {
   wait.tv_sec=0;
   wait.tv_nsec=5000000L;
 
+  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_RU_FEPRX, 1 );
   start_meas(&ru->ofdm_demod_stats);
 
   if (pthread_mutex_timedlock(&proc->mutex_fep,&wait) != 0) {
@@ -510,15 +548,23 @@ void ru_fep_full_2thread(RU_t *ru) {
     exit_fun( "ERROR pthread_cond_signal" );
     return;
   }
+  //start_meas(&ru->ofdm_demod_wakeup_stats);
   
   pthread_mutex_unlock( &proc->mutex_fep );
 
   // call second slot in this symbol
   fep0(ru,1);
 
+  start_meas(&ru->ofdm_demod_wait_stats);
   wait_on_busy_condition(&proc->mutex_fep,&proc->cond_fep,&proc->instance_cnt_fep,"fep thread");  
+  stop_meas(&ru->ofdm_demod_wait_stats);
+  if(opp_enabled == 1 && ru->ofdm_demod_wakeup_stats.diff_now>30*3000){
+    print_meas_now(&ru->ofdm_demod_wakeup_stats,"fep wakeup",stderr);
+    printf("delay in fep wait on codition in frame_rx: %d  subframe_rx: %d \n",proc->frame_rx,proc->subframe_rx);
+  }
 
   stop_meas(&ru->ofdm_demod_stats);
+  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_RU_FEPRX, 0 );
 }
 
 
diff --git a/openair1/SCHED_UE/phy_procedures_lte_ue.c b/openair1/SCHED_UE/phy_procedures_lte_ue.c
index 2edcb22480f09b2612c190d18e63e202de05e189..d4d2617a3ce402bb77cb4269e15d2f069b634099 100644
--- a/openair1/SCHED_UE/phy_procedures_lte_ue.c
+++ b/openair1/SCHED_UE/phy_procedures_lte_ue.c
@@ -37,9 +37,10 @@
 #include "PHY/phy_extern_ue.h"
 #include <sched.h>
 #include "targets/RT/USER/lte-softmodem.h"
+
 #include "PHY/LTE_UE_TRANSPORT/transport_proto_ue.h"
 #include "SCHED_UE/sched_UE.h"
-#define DEBUG_PHY_PROC
+//#define DEBUG_PHY_PROC
 
 #ifndef PUCCH
 #define PUCCH
@@ -78,7 +79,7 @@ extern uint32_t downlink_frequency[MAX_NUM_CCs][4];
 #endif
 
 
-#define UE_DEBUG_TRACE 1
+//#define UE_DEBUG_TRACE 1
 
 void dump_dlsch(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,uint8_t subframe,uint8_t harq_pid)
 {
diff --git a/openair1/SIMULATION/ETH_TRANSPORT/netlink_init.c b/openair1/SIMULATION/ETH_TRANSPORT/netlink_init.c
index b578721a1a0ffed4b79f7956551d8ae3fe49c00c..b90961a1c092fa84cdc6ee1fd2e057369fe44060 100644
--- a/openair1/SIMULATION/ETH_TRANSPORT/netlink_init.c
+++ b/openair1/SIMULATION/ETH_TRANSPORT/netlink_init.c
@@ -39,6 +39,13 @@
 #include <fcntl.h>
 #include <errno.h>
 #include "platform_constants.h"
+#ifdef UE_NAS_USE_TUN
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <linux/if.h>
+#include <linux/if_tun.h>
+#include "openairinterface5g_limits.h"
+#endif
 
 char nl_rx_buf[NL_MAX_PAYLOAD];
 
@@ -47,12 +54,121 @@ struct nlmsghdr *nas_nlh_tx = NULL;
 struct nlmsghdr *nas_nlh_rx = NULL;
 struct iovec nas_iov_tx;
 struct iovec nas_iov_rx = {nl_rx_buf, sizeof(nl_rx_buf)};
+#ifdef UE_NAS_USE_TUN
+int nas_sock_fd[NUMBER_OF_UE_MAX];
+#else
 int nas_sock_fd;
+#endif
 struct msghdr nas_msg_tx;
 struct msghdr nas_msg_rx;
 
 #define GRAAL_NETLINK_ID 31
 
+#ifdef UE_NAS_USE_TUN
+
+static int tun_alloc(char *dev)
+{
+  struct ifreq ifr;
+  int fd, err;
+
+  if( (fd = open("/dev/net/tun", O_RDWR)) < 0 ) {
+    printf("[TUN] failed to open /dev/net/tun\n");
+    return -1;
+  }
+
+  memset(&ifr, 0, sizeof(ifr));
+
+  /* Flags: IFF_TUN   - TUN device (no Ethernet headers)
+   *        IFF_TAP   - TAP device
+   *
+   *        IFF_NO_PI - Do not provide packet information
+   */
+  ifr.ifr_flags = IFF_TUN | IFF_NO_PI;
+  if( *dev )
+     strncpy(ifr.ifr_name, dev, IFNAMSIZ);
+
+  if( (err = ioctl(fd, TUNSETIFF, (void *) &ifr)) < 0 ){
+     close(fd);
+     return err;
+  }
+  strcpy(dev, ifr.ifr_name);
+  return fd;
+}
+
+int netlink_init(void)
+{
+  int i;
+  int ret;
+
+  char ifname[64];
+  for (i = 0; i < NUMBER_OF_UE_MAX; i++) {
+    sprintf(ifname, "oip%d", i+1);
+    nas_sock_fd[i] = tun_alloc(ifname);
+
+    if (nas_sock_fd[i] == -1) {
+      printf("[NETLINK] Error opening socket %d (%d:%s)\n",nas_sock_fd[i],errno, strerror(errno));
+#if defined(LINK_ENB_PDCP_TO_IP_DRIVER)
+      exit(1);
+#endif
+    }
+
+    printf("[NETLINK]Opened socket with fd %d\n",nas_sock_fd[i]);
+
+#if !defined(PDCP_USE_NETLINK_QUEUES)
+    ret = fcntl(nas_sock_fd[i],F_SETFL,O_NONBLOCK);
+
+    if (ret == -1) {
+      printf("[NETLINK] Error fcntl (%d:%s)\n",errno, strerror(errno));
+#if defined(LINK_ENB_PDCP_TO_IP_DRIVER)
+      exit(1);
+#endif
+    }
+
+#endif
+
+    memset(&nas_src_addr, 0, sizeof(nas_src_addr));
+    nas_src_addr.nl_family = AF_NETLINK;
+    nas_src_addr.nl_pid = 1;//getpid();  /* self pid */
+    nas_src_addr.nl_groups = 0;  /* not in mcast groups */
+    ret = bind(nas_sock_fd[i], (struct sockaddr*)&nas_src_addr, sizeof(nas_src_addr));
+
+
+
+    memset(&nas_dest_addr, 0, sizeof(nas_dest_addr));
+    nas_dest_addr.nl_family = AF_NETLINK;
+    nas_dest_addr.nl_pid = 0;   /* For Linux Kernel */
+    nas_dest_addr.nl_groups = 0; /* unicast */
+
+    // TX PART
+    nas_nlh_tx=(struct nlmsghdr *)malloc(NLMSG_SPACE(NL_MAX_PAYLOAD));
+    memset(nas_nlh_tx, 0, NLMSG_SPACE(NL_MAX_PAYLOAD));
+    /* Fill the netlink message header */
+    nas_nlh_tx->nlmsg_len = NLMSG_SPACE(NL_MAX_PAYLOAD);
+    nas_nlh_tx->nlmsg_pid = 1;//getpid();  /* self pid */
+    nas_nlh_tx->nlmsg_flags = 0;
+
+    nas_iov_tx.iov_base = (void *)nas_nlh_tx;
+    nas_iov_tx.iov_len = nas_nlh_tx->nlmsg_len;
+    memset(&nas_msg_tx,0,sizeof(nas_msg_tx));
+    nas_msg_tx.msg_name = (void *)&nas_dest_addr;
+    nas_msg_tx.msg_namelen = sizeof(nas_dest_addr);
+    nas_msg_tx.msg_iov = &nas_iov_tx;
+    nas_msg_tx.msg_iovlen = 1;
+
+
+    // RX PART
+    memset(&nas_msg_rx,0,sizeof(nas_msg_rx));
+    nas_msg_rx.msg_name = (void *)&nas_src_addr;
+    nas_msg_rx.msg_namelen = sizeof(nas_src_addr);
+    nas_msg_rx.msg_iov = &nas_iov_rx;
+    nas_msg_rx.msg_iovlen = 1;
+  }
+
+  return 1;
+}
+
+#else /* UE_NAS_USE_TUN */
+
 int netlink_init(void)
 {
   int ret;
@@ -119,3 +235,5 @@ int netlink_init(void)
 
   return(nas_sock_fd);
 }
+
+#endif /* UE_NAS_USE_TUN */
diff --git a/openair1/SIMULATION/LTE_PHY/dlsim.c b/openair1/SIMULATION/LTE_PHY/dlsim.c
index db6350df1403d4408969caac1b4bb530cff6a5ac..3780600a4211fc94638981720227fbe7e5adc7d9 100644
--- a/openair1/SIMULATION/LTE_PHY/dlsim.c
+++ b/openair1/SIMULATION/LTE_PHY/dlsim.c
@@ -76,6 +76,8 @@ double t_rx_min = 1000000000; /*!< \brief initial min process time for rx */
 int n_tx_dropped = 0; /*!< \brief initial max process time for tx */
 int n_rx_dropped = 0; /*!< \brief initial max process time for rx */
 
+int codingw = 0;
+
 void handler(int sig)
 {
   void *array[10];
diff --git a/openair1/SIMULATION/LTE_PHY/ulsim.c b/openair1/SIMULATION/LTE_PHY/ulsim.c
index cf1b8192b326d9726bae84e28cd21fc246e37613..6590ea4dbc5b7a1082407dabd174ded8a747a7f6 100644
--- a/openair1/SIMULATION/LTE_PHY/ulsim.c
+++ b/openair1/SIMULATION/LTE_PHY/ulsim.c
@@ -95,6 +95,8 @@ nfapi_tx_request_pdu_t tx_pdu_list[MAX_NUM_TX_REQUEST_PDU];
 nfapi_tx_request_t TX_req;
 Sched_Rsp_t sched_resp;
 
+int codingw = 0;
+
 void
 fill_nfapi_ulsch_config_request(nfapi_ul_config_request_pdu_t *ul_config_pdu,
 				uint8_t                        cqi_req,
diff --git a/openair1/SIMULATION/RF/dac.c b/openair1/SIMULATION/RF/dac.c
index ce3af07a7db096d64cee0913badef07ebc97a398..b09bd20374bf7bec5df4143443a841472c3a2876 100644
--- a/openair1/SIMULATION/RF/dac.c
+++ b/openair1/SIMULATION/RF/dac.c
@@ -91,10 +91,8 @@ double dac_fixed_gain(double *s_re[2],
 
   int i;
   int aa;
-  double amp,amp1_local,*amp1p;
-
-  amp = //sqrt(NB_RE)*pow(10.0,.05*txpwr_dBm)/sqrt(nb_tx_antennas); //this is amp per tx antenna
-    pow(10.0,.05*txpwr_dBm)/sqrt(nb_tx_antennas); //this is amp per tx antenna
+  double amp1_local,*amp1p;
+  double amp = pow(10.0,.05*txpwr_dBm)/sqrt(nb_tx_antennas); //this is amp per tx antenna
 
   if (amp1==NULL) amp1p = &amp1_local;
   else            amp1p = amp1;
@@ -123,7 +121,7 @@ double dac_fixed_gain(double *s_re[2],
     //printf("DL: amp1 %f dB (%d,%d), tx_power %f\n",20*log10(amp1),input_offset,input_offset_meas,txpwr_dBm);
   */
 
-
+  //  printf("DAC: amp/amp1p %f amp1 %f dB (%d,%d), tx_power %f\n",amp/(*amp1p),20*log10(*amp1p),input_offset,input_offset_meas,txpwr_dBm);
   for (i=0; i<length; i++) {
     for (aa=0; aa<nb_tx_antennas; aa++) {
       s_re[aa][i] = amp*((double)(((short *)input[aa]))[((i+input_offset)<<1)])/(*amp1p); 
@@ -131,7 +129,7 @@ double dac_fixed_gain(double *s_re[2],
     }
   }
 
-  //  printf("ener %e\n",signal_energy_fp(s_re,s_im,nb_tx_antennas,length,0));
+  //  printf("ener %e\n",signal_energy_fp(s_re,s_im,nb_tx_antennas,length<length_meas?length:length_meas,0));
 
   return(signal_energy_fp(s_re,s_im,nb_tx_antennas,length<length_meas?length:length_meas,0)/NB_RE);
 }
diff --git a/openair2/ENB_APP/enb_config.c b/openair2/ENB_APP/enb_config.c
index 50ebf13f798e588388ec98f69359f198bb0fb611..628f7d55d69a02376644aceedddf77f5d43e462d 100644
--- a/openair2/ENB_APP/enb_config.c
+++ b/openair2/ENB_APP/enb_config.c
@@ -297,6 +297,9 @@ void RCconfig_macrlc() {
     mac_top_init_eNB();   
     for (j=0;j<RC.nb_macrlc_inst;j++) {
 
+      //RC.mac[j]->phy_test = *(MacRLC_ParamList.paramarray[j][MACRLC_PHY_TEST_IDX].iptr);
+      //printf("PHY_TEST = %d,%d\n", RC.mac[j]->phy_test, j);
+
       if (strcmp(*(MacRLC_ParamList.paramarray[j][MACRLC_TRANSPORT_N_PREFERENCE_IDX].strptr), "local_RRC") == 0) {
 	// check number of instances is same as RRC/PDCP
 	
diff --git a/openair2/ENB_APP/enb_paramdef.h b/openair2/ENB_APP/enb_paramdef.h
index a8379c259f948882e6a17c4b98b5daccbfe2067f..fe2b5a8515c164681841375b1b00576255fcc59e 100755
--- a/openair2/ENB_APP/enb_paramdef.h
+++ b/openair2/ENB_APP/enb_paramdef.h
@@ -687,4 +687,43 @@ typedef enum {
 #define CONFIG_STRING_MACRLC_CONFIG                        "macrlc_config"
 
 
-
+/* MACRLC configuration parameters names   */
+#define CONFIG_STRING_MACRLC_CC                            "num_cc"
+#define CONFIG_STRING_MACRLC_TRANSPORT_N_PREFERENCE        "tr_n_preference"
+#define CONFIG_STRING_MACRLC_LOCAL_N_IF_NAME               "local_n_if_name"
+#define CONFIG_STRING_MACRLC_LOCAL_N_ADDRESS               "local_n_address"
+#define CONFIG_STRING_MACRLC_REMOTE_N_ADDRESS              "remote_n_address"
+#define CONFIG_STRING_MACRLC_LOCAL_N_PORTC                 "local_n_portc"
+#define CONFIG_STRING_MACRLC_REMOTE_N_PORTC                "remote_n_portc"
+#define CONFIG_STRING_MACRLC_LOCAL_N_PORTD                 "local_n_portd"
+#define CONFIG_STRING_MACRLC_REMOTE_N_PORTD                "remote_n_portd"
+#define CONFIG_STRING_MACRLC_TRANSPORT_S_PREFERENCE        "tr_s_preference"
+#define CONFIG_STRING_MACRLC_LOCAL_S_IF_NAME               "local_s_if_name"
+#define CONFIG_STRING_MACRLC_LOCAL_S_ADDRESS               "local_s_address"
+#define CONFIG_STRING_MACRLC_REMOTE_S_ADDRESS              "remote_s_address"
+#define CONFIG_STRING_MACRLC_LOCAL_S_PORTC                 "local_s_portc"
+#define CONFIG_STRING_MACRLC_REMOTE_S_PORTC                "remote_s_portc"
+#define CONFIG_STRING_MACRLC_LOCAL_S_PORTD                 "local_s_portd"
+#define CONFIG_STRING_MACRLC_REMOTE_S_PORTD                "remote_s_portd"
+#define CONFIG_STRING_MACRLC_PHY_TEST_MODE                 "phy_test_mode"
+
+
+#define MACRLC_CC_IDX                                          0
+#define MACRLC_TRANSPORT_N_PREFERENCE_IDX                      1
+#define MACRLC_LOCAL_N_IF_NAME_IDX                             2
+#define MACRLC_LOCAL_N_ADDRESS_IDX                             3
+#define MACRLC_REMOTE_N_ADDRESS_IDX                            4
+#define MACRLC_LOCAL_N_PORTC_IDX                               5
+#define MACRLC_REMOTE_N_PORTC_IDX                              6
+#define MACRLC_LOCAL_N_PORTD_IDX                               7
+#define MACRLC_REMOTE_N_PORTD_IDX                              8
+#define MACRLC_TRANSPORT_S_PREFERENCE_IDX                      9
+#define MACRLC_LOCAL_S_IF_NAME_IDX                             10
+#define MACRLC_LOCAL_S_ADDRESS_IDX                             11
+#define MACRLC_REMOTE_S_ADDRESS_IDX                            12
+#define MACRLC_LOCAL_S_PORTC_IDX                               13
+#define MACRLC_REMOTE_S_PORTC_IDX                              14
+#define MACRLC_LOCAL_S_PORTD_IDX                               15
+#define MACRLC_REMOTE_S_PORTD_IDX                              16
+#define MACRLC_PHY_TEST_IDX                                    17
+/*---------------------------------------------------------------------------------------------------------------------------------------------------------*/
diff --git a/openair2/LAYER2/MAC/eNB_scheduler.c b/openair2/LAYER2/MAC/eNB_scheduler.c
index 75a2fe462ecc945e9cb94090c6c79542da70cdd0..5d9add510e394705d86405fedfe13e38bc6b9d7a 100644
--- a/openair2/LAYER2/MAC/eNB_scheduler.c
+++ b/openair2/LAYER2/MAC/eNB_scheduler.c
@@ -61,6 +61,7 @@
 #define DEBUG_eNB_SCHEDULER 1
 
 extern RAN_CONTEXT_t RC;
+extern int phy_test;
 
 uint16_t pdcch_order_table[6] = { 31, 31, 511, 2047, 2047, 8191 };
 
@@ -538,7 +539,7 @@ eNB_dlsch_ulsch_scheduler(module_id_t module_idP, frame_t frameP,
     rnti = UE_RNTI(module_idP, i);
     CC_id = UE_PCCID(module_idP, i);
 
-    if ((frameP == 0) && (subframeP == 0)) {
+    if (((frameP&127) == 0) && (subframeP == 0)) {
       LOG_I(MAC,
             "UE  rnti %x : %s, PHR %d dB DL CQI %d PUSCH SNR %d PUCCH SNR %d\n",
             rnti,
@@ -638,26 +639,33 @@ eNB_dlsch_ulsch_scheduler(module_id_t module_idP, frame_t frameP,
 #endif
 
   // This schedules MIB
+
   if ((subframeP == 0) && (frameP & 3) == 0)
       schedule_mib(module_idP, frameP, subframeP);
-  // This schedules SI for legacy LTE and eMTC starting in subframeP
-  schedule_SI(module_idP, frameP, subframeP);
-  // This schedules Paging in subframeP
-  schedule_PCH(module_idP,frameP,subframeP);
-  // This schedules Random-Access for legacy LTE and eMTC starting in subframeP
-  schedule_RA(module_idP, frameP, subframeP);
-  // copy previously scheduled UL resources (ULSCH + HARQ)
-  copy_ulreq(module_idP, frameP, subframeP);
-  // This schedules SRS in subframeP
-  schedule_SRS(module_idP, frameP, subframeP);
-  // This schedules ULSCH in subframeP (dci0)
-  schedule_ulsch(module_idP, frameP, subframeP);
-  // This schedules UCI_SR in subframeP
-  schedule_SR(module_idP, frameP, subframeP);
-  // This schedules UCI_CSI in subframeP
-  schedule_CSI(module_idP, frameP, subframeP);
-  // This schedules DLSCH in subframeP
-  schedule_dlsch(module_idP, frameP, subframeP, mbsfn_status);
+  if (phy_test == 0){
+    // This schedules SI for legacy LTE and eMTC starting in subframeP
+    schedule_SI(module_idP, frameP, subframeP);
+    // This schedules Paging in subframeP
+    schedule_PCH(module_idP,frameP,subframeP);
+    // This schedules Random-Access for legacy LTE and eMTC starting in subframeP
+    schedule_RA(module_idP, frameP, subframeP);
+    // copy previously scheduled UL resources (ULSCH + HARQ)
+    copy_ulreq(module_idP, frameP, subframeP);
+    // This schedules SRS in subframeP
+    schedule_SRS(module_idP, frameP, subframeP);
+    // This schedules ULSCH in subframeP (dci0)
+    schedule_ulsch(module_idP, frameP, subframeP);
+    // This schedules UCI_SR in subframeP
+    schedule_SR(module_idP, frameP, subframeP);
+    // This schedules UCI_CSI in subframeP
+    schedule_CSI(module_idP, frameP, subframeP);
+    // This schedules DLSCH in subframeP
+    schedule_dlsch(module_idP, frameP, subframeP, mbsfn_status);
+  }
+  else{
+    schedule_ulsch_phy_test(module_idP,frameP,subframeP);
+    schedule_ue_spec_phy_test(module_idP,frameP,subframeP,mbsfn_status);
+  }
 
   if (RC.flexran[module_idP]->enabled)
     flexran_agent_send_update_stats(module_idP);
diff --git a/openair2/LAYER2/MAC/eNB_scheduler_bch.c b/openair2/LAYER2/MAC/eNB_scheduler_bch.c
index ec69bc55481333dc36da99908211474fec63ee58..8b391a0c1dee4aa7fcdeebd494d9aeec73d49de0 100644
--- a/openair2/LAYER2/MAC/eNB_scheduler_bch.c
+++ b/openair2/LAYER2/MAC/eNB_scheduler_bch.c
@@ -784,6 +784,7 @@ schedule_SI(module_id_t module_idP, frame_t frameP, sub_frame_t subframeP)
 		eNB->eNB_stats[CC_id].bcch_buffer = bcch_sdu_length;
 		eNB->eNB_stats[CC_id].total_bcch_buffer += bcch_sdu_length;
 		eNB->eNB_stats[CC_id].bcch_mcs = mcs;
+//printf("SI %d.%d\n", frameP, subframeP);/////////////////////////////////////////******************************
 	    } else {
 
 		//LOG_D(MAC,"[eNB %d] Frame %d : BCCH not active \n",Mod_id,frame);
diff --git a/openair2/LAYER2/MAC/eNB_scheduler_phytest.c b/openair2/LAYER2/MAC/eNB_scheduler_phytest.c
new file mode 100644
index 0000000000000000000000000000000000000000..e6258593245ea368c65d386e26dc6cc0aa5a362f
--- /dev/null
+++ b/openair2/LAYER2/MAC/eNB_scheduler_phytest.c
@@ -0,0 +1,353 @@
+/*
+ * 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.0  (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 eNB_scheduler_dlsch.c
+ * \brief procedures related to eNB for the DLSCH transport channel
+ * \author  Navid Nikaein and Raymond Knopp
+ * \date 2010 - 2014
+ * \email: navid.nikaein@eurecom.fr
+ * \version 1.0
+ * @ingroup _mac
+
+ */
+
+#include "assertions.h"
+#include "PHY/defs.h"
+#include "PHY/extern.h"
+
+#include "SCHED/defs.h"
+#include "SCHED/extern.h"
+
+#include "LAYER2/MAC/defs.h"
+#include "LAYER2/MAC/proto.h"
+#include "LAYER2/MAC/extern.h"
+#include "UTIL/LOG/log.h"
+#include "UTIL/LOG/vcd_signal_dumper.h"
+#include "UTIL/OPT/opt.h"
+#include "OCG.h"
+#include "OCG_extern.h"
+
+#include "SIMULATION/TOOLS/defs.h" // for taus
+
+#include "T.h"
+
+extern RAN_CONTEXT_t RC;
+
+//------------------------------------------------------------------------------
+void
+schedule_ue_spec_phy_test(
+  module_id_t   module_idP,
+  frame_t       frameP,
+  sub_frame_t   subframeP,
+  int*          mbsfn_flag
+)
+//------------------------------------------------------------------------------
+{
+  uint8_t                        CC_id;
+  int                            UE_id=0;
+  uint16_t                       N_RB_DL;
+  uint16_t                       TBS;
+  uint16_t                       nb_rb;
+
+  unsigned char                  harq_pid  = subframeP%5;
+  uint16_t                       rnti      = 0x1235;
+  uint32_t                       rb_alloc  = 0x1FFFFFFF;
+  int32_t                        tpc       = 1;
+  int32_t                        mcs       = 28;
+  int32_t                        cqi       = 15;
+  int32_t                        ndi       = subframeP/5;
+  int32_t                        dai       = 0;
+
+  eNB_MAC_INST                   *eNB      = RC.mac[module_idP];
+  COMMON_channels_t              *cc       = eNB->common_channels;
+  nfapi_dl_config_request_body_t *dl_req;
+  nfapi_dl_config_request_pdu_t  *dl_config_pdu;
+
+  N_RB_DL         = to_prb(cc->mib->message.dl_Bandwidth);
+
+  for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
+    LOG_D(MAC, "doing schedule_ue_spec for CC_id %d\n",CC_id);
+
+    dl_req        = &eNB->DL_req[CC_id].dl_config_request_body;
+
+    if (mbsfn_flag[CC_id]>0)
+      continue;
+
+    nb_rb = conv_nprb(0,rb_alloc,N_RB_DL);
+    //printf("////////////////////////////////////*************************nb_rb = %d\n",nb_rb);
+    TBS = get_TBS_DL(mcs,nb_rb);
+
+    LOG_D(PHY,"schedule_ue_spec_phy_test: subframe %d/%d: nb_rb=%d, TBS=%d, mcs=%d (rb_alloc=%x, N_RB_DL=%d)\n",frameP,subframeP,nb_rb,TBS,mcs,rb_alloc,N_RB_DL);
+
+    dl_config_pdu                                                         = &dl_req->dl_config_pdu_list[dl_req->number_pdu]; 
+    memset((void*)dl_config_pdu,0,sizeof(nfapi_dl_config_request_pdu_t));
+    dl_config_pdu->pdu_type                                               = NFAPI_DL_CONFIG_DCI_DL_PDU_TYPE; 
+    dl_config_pdu->pdu_size                                               = (uint8_t)(2+sizeof(nfapi_dl_config_dci_dl_pdu));
+    dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.dci_format                  = NFAPI_DL_DCI_FORMAT_1;
+    dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.aggregation_level           = get_aggregation(get_bw_index(module_idP,CC_id),cqi,format1);
+    dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.resource_allocation_type    = 0;
+    dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.virtual_resource_block_assignment_flag = 0;
+    dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.resource_block_coding       = rb_alloc;
+
+    dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.rnti                        = rnti;
+    dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.rnti_type                   = 1;    // CRNTI : see Table 4-10 from SCF082 - nFAPI specifications
+    dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.transmission_power          = 6000; // equal to RS power
+    
+    dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.harq_process                = harq_pid;
+    dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.tpc                         = tpc; // dont adjust power when retransmitting
+    dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.new_data_indicator_1        = ndi;
+    dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.mcs_1                       = mcs;
+    dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.redundancy_version_1        = 0;
+    //deactivate second codeword
+    dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.mcs_2                       = 0;
+    dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.redundancy_version_2        = 1;
+    
+    if (cc[CC_id].tdd_Config != NULL) { //TDD
+      dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.downlink_assignment_index = dai;
+      LOG_D(MAC,"[eNB %d] Initial transmission CC_id %d : harq_pid %d, dai %d, mcs %d\n",
+	    module_idP,CC_id,harq_pid,dai,mcs);
+    } else {
+      LOG_D(MAC,"[eNB %d] Initial transmission CC_id %d : harq_pid %d, mcs %d\n",
+	    module_idP,CC_id,harq_pid,mcs);
+      
+    }
+    LOG_D(MAC,"Checking feasibility pdu %d (new sdu)\n",dl_req->number_pdu);
+    if (!CCE_allocation_infeasible(module_idP,CC_id,1,subframeP,dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.aggregation_level,rnti)) {
+      
+      
+      //ue_sched_ctl->round[CC_id][harq_pid] = 0;
+      dl_req->number_dci++;
+      dl_req->number_pdu++;
+      
+      // Toggle NDI for next time
+      /*
+      LOG_D(MAC,"CC_id %d Frame %d, subframeP %d: Toggling Format1 NDI for UE %d (rnti %x/%d) oldNDI %d\n",
+	    CC_id, frameP,subframeP,UE_id,
+	    rnti,harq_pid,UE_list->UE_template[CC_id][UE_id].oldNDI[harq_pid]);
+      
+      UE_list->UE_template[CC_id][UE_id].oldNDI[harq_pid]=1-UE_list->UE_template[CC_id][UE_id].oldNDI[harq_pid];
+      UE_list->UE_template[CC_id][UE_id].oldmcs1[harq_pid] = mcs;
+      UE_list->UE_template[CC_id][UE_id].oldmcs2[harq_pid] = 0;
+      AssertFatal(UE_list->UE_template[CC_id][UE_id].physicalConfigDedicated!=NULL,"physicalConfigDedicated is NULL\n");
+      AssertFatal(UE_list->UE_template[CC_id][UE_id].physicalConfigDedicated->pdsch_ConfigDedicated!=NULL,"physicalConfigDedicated->pdsch_ConfigDedicated is NULL\n");
+      */
+
+
+      
+      fill_nfapi_dlsch_config(eNB,
+			      dl_req,
+			      TBS,
+			      eNB->pdu_index[CC_id],
+			      rnti,
+			      0, // type 0 allocation from 7.1.6 in 36.213
+			      0, // virtual_resource_block_assignment_flag
+			      rb_alloc, // resource_block_coding
+			      getQm(mcs),
+			      0, // redundancy version
+			      1, // transport blocks
+			      0, // transport block to codeword swap flag
+			      cc[CC_id].p_eNB == 1 ? 0 : 1, // transmission_scheme
+			      1, // number of layers
+			      1, // number of subbands
+			      //			     uint8_t codebook_index,
+			      4, // UE category capacity
+			      PDSCH_ConfigDedicated__p_a_dB0, 
+			      0, // delta_power_offset for TM5
+			      0, // ngap
+			      0, // nprb
+			      cc[CC_id].p_eNB == 1 ? 1 : 2, // transmission mode
+			      0, //number of PRBs treated as one subband, not used here
+			      0 // number of beamforming vectors, not used here
+			      );  
+
+      eNB->TX_req[CC_id].sfn_sf = fill_nfapi_tx_req(&eNB->TX_req[CC_id].tx_request_body,
+						    (frameP*10)+subframeP,
+						    TBS,
+						    eNB->pdu_index[CC_id],
+						    eNB->UE_list.DLSCH_pdu[CC_id][0][(unsigned char)UE_id].payload[0]);
+    }
+    else {
+      LOG_W(MAC,"[eNB_scheduler_phytest] DCI allocation infeasible!\n");
+    }
+  }
+}
+
+void schedule_ulsch_phy_test(module_id_t module_idP,frame_t frameP,sub_frame_t subframeP)
+{
+  uint16_t first_rb[MAX_NUM_CCs];
+  int               UE_id = 0;
+  uint8_t           aggregation    = 2;
+  rnti_t            rnti           = 0x1235;
+  uint8_t           mcs            = 0;
+  uint8_t           harq_pid       = 0;
+  uint32_t          cqi_req = 0,cshift,ndi,tpc = 1;
+  int32_t           normalized_rx_power;
+  int32_t           target_rx_power= 178;
+  int               CC_id = 0;
+  int               nb_rb = 96;
+  eNB_MAC_INST      *eNB = RC.mac[module_idP];
+  COMMON_channels_t *cc  = eNB->common_channels;
+  UE_list_t         *UE_list=&eNB->UE_list;
+  UE_TEMPLATE       *UE_template;
+  UE_sched_ctrl     *UE_sched_ctrl;
+  int               sched_frame=frameP;
+  int               sched_subframe = (subframeP+4)%10;
+  
+  if (sched_subframe<subframeP) sched_frame++;
+
+  nfapi_hi_dci0_request_body_t   *hi_dci0_req = &eNB->HI_DCI0_req[CC_id].hi_dci0_request_body;
+  nfapi_hi_dci0_request_pdu_t    *hi_dci0_pdu;
+
+  //nfapi_ul_config_request_pdu_t  *ul_config_pdu = &ul_req->ul_config_pdu_list[0];;
+  nfapi_ul_config_request_body_t *ul_req       = &eNB->UL_req[CC_id].ul_config_request_body;
+
+
+  eNB->UL_req[CC_id].sfn_sf   = (sched_frame<<4) + sched_subframe;
+  eNB->HI_DCI0_req[CC_id].sfn_sf = (frameP<<4)+subframeP;
+  
+  for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
+    //rnti = UE_RNTI(module_idP,UE_id);
+    //leave out first RB for PUCCH
+    first_rb[CC_id] = 1;
+  // loop over all active UEs
+
+      //      if (eNB_UE_stats->mode == PUSCH) { // ue has a ulsch channel
+
+      UE_template   = &UE_list->UE_template[CC_id][UE_id];
+      UE_sched_ctrl = &UE_list->UE_sched_ctrl[UE_id];
+      harq_pid      = subframe2harqpid(&cc[CC_id],sched_frame,sched_subframe);
+
+      LOG_D(MAC,"Scheduling for frame %d, subframe %d => harq_pid %d\n",sched_frame,sched_subframe,harq_pid);
+
+      RC.eNB[module_idP][CC_id]->pusch_stats_BO[UE_id][(frameP*10)+subframeP] = UE_template->TBS_UL[harq_pid];
+
+	  
+
+      //power control
+      //compute the expected ULSCH RX power (for the stats)
+	  
+      // this is the normalized RX power and this should be constant (regardless of mcs
+      normalized_rx_power = UE_sched_ctrl->pusch_snr[CC_id];
+	  
+      // new transmission
+	  
+      ndi = 1-UE_template->oldNDI_UL[harq_pid];
+      UE_template->oldNDI_UL[harq_pid]=ndi;
+	  UE_list->eNB_UE_stats[CC_id][UE_id].normalized_rx_power=normalized_rx_power;
+	  UE_list->eNB_UE_stats[CC_id][UE_id].target_rx_power=target_rx_power;
+	  UE_list->eNB_UE_stats[CC_id][UE_id].ulsch_mcs1 = mcs;
+      UE_template->mcs_UL[harq_pid] = mcs;//cmin (UE_template->pre_assigned_mcs_ul, openair_daq_vars.target_ue_ul_mcs); // adjust, based on user-defined MCS
+      UE_list->eNB_UE_stats[CC_id][UE_id].ulsch_mcs2 = mcs;
+	  //            buffer_occupancy = UE_template->ul_total_buffer;
+
+	    
+	    
+      UE_template->TBS_UL[harq_pid] = get_TBS_UL(mcs,nb_rb);
+	  UE_list->eNB_UE_stats[CC_id][UE_id].total_rbs_used_rx += nb_rb;
+	  UE_list->eNB_UE_stats[CC_id][UE_id].ulsch_TBS = get_TBS_UL(mcs,nb_rb);
+	  //            buffer_occupancy -= TBS;
+
+
+	    
+	  // bad indices : 20 (40 PRB), 21 (45 PRB), 22 (48 PRB)
+      //store for possible retransmission
+      UE_template->nb_rb_ul[harq_pid]    = nb_rb;
+      UE_template->first_rb_ul[harq_pid] = first_rb[CC_id];
+	    
+	  UE_sched_ctrl->ul_scheduled |= (1<<harq_pid);
+	    
+	  // adjust total UL buffer status by TBS, wait for UL sdus to do final update
+	  //UE_template->ul_total_buffer = UE_template->TBS_UL[harq_pid];
+	  // Cyclic shift for DM RS
+	  cshift = 0;// values from 0 to 7 can be used for mapping the cyclic shift (36.211 , Table 5.5.2.1.1-1)
+	  // save it for a potential retransmission
+      UE_template->cshift[harq_pid] = cshift;	    
+
+	  hi_dci0_pdu                                                         = &hi_dci0_req->hi_dci0_pdu_list[eNB->HI_DCI0_req[CC_id].hi_dci0_request_body.number_of_dci+eNB->HI_DCI0_req[CC_id].hi_dci0_request_body.number_of_hi]; 	
+	  memset((void*)hi_dci0_pdu,0,sizeof(nfapi_hi_dci0_request_pdu_t));
+	  hi_dci0_pdu->pdu_type                                               = NFAPI_HI_DCI0_DCI_PDU_TYPE; 
+	  hi_dci0_pdu->pdu_size                                               = 2+sizeof(nfapi_hi_dci0_dci_pdu);
+	  hi_dci0_pdu->dci_pdu.dci_pdu_rel8.dci_format                        = NFAPI_UL_DCI_FORMAT_0;
+	  hi_dci0_pdu->dci_pdu.dci_pdu_rel8.aggregation_level                 = aggregation;
+	  hi_dci0_pdu->dci_pdu.dci_pdu_rel8.rnti                              = rnti;
+	  hi_dci0_pdu->dci_pdu.dci_pdu_rel8.transmission_power                = 6000;
+	  hi_dci0_pdu->dci_pdu.dci_pdu_rel8.resource_block_start              = first_rb[CC_id];
+	  hi_dci0_pdu->dci_pdu.dci_pdu_rel8.number_of_resource_block          = nb_rb;
+	  hi_dci0_pdu->dci_pdu.dci_pdu_rel8.mcs_1                             = mcs;
+	  hi_dci0_pdu->dci_pdu.dci_pdu_rel8.cyclic_shift_2_for_drms           = cshift;
+	  hi_dci0_pdu->dci_pdu.dci_pdu_rel8.frequency_hopping_enabled_flag    = 0;
+	  hi_dci0_pdu->dci_pdu.dci_pdu_rel8.new_data_indication_1             = ndi;
+	  hi_dci0_pdu->dci_pdu.dci_pdu_rel8.tpc                               = tpc;
+	  hi_dci0_pdu->dci_pdu.dci_pdu_rel8.cqi_csi_request                   = cqi_req;
+	  hi_dci0_pdu->dci_pdu.dci_pdu_rel8.dl_assignment_index               = UE_template->DAI_ul[sched_subframe];
+
+	    
+	  eNB->HI_DCI0_req[CC_id].hi_dci0_request_body.number_of_dci++;
+	    
+	    
+	  // Add UL_config PDUs
+	  fill_nfapi_ulsch_config_request_rel8(&ul_req->ul_config_pdu_list[ul_req->number_of_pdus],
+						 cqi_req,
+						 cc,
+						 0,//UE_template->physicalConfigDedicated,
+						 get_tmode(module_idP,CC_id,UE_id),
+						 eNB->ul_handle,
+						 rnti,
+						 first_rb[CC_id], // resource_block_start
+						 nb_rb, // number_of_resource_blocks
+						 mcs,
+						 cshift, // cyclic_shift_2_for_drms
+						 0, // frequency_hopping_enabled_flag
+						 0, // frequency_hopping_bits
+						 ndi, // new_data_indication
+						 0, // redundancy_version
+						 harq_pid, // harq_process_number
+						 0, // ul_tx_mode
+						 0, // current_tx_nb
+						 0, // n_srs
+						 get_TBS_UL(mcs,nb_rb)
+						 );
+#ifdef Rel14
+	  if (UE_template->rach_resource_type>0) { // This is a BL/CE UE allocation
+	    fill_nfapi_ulsch_config_request_emtc(&ul_req->ul_config_pdu_list[ul_req->number_of_pdus],
+						   UE_template->rach_resource_type>2 ? 2 : 1,
+						   1, //total_number_of_repetitions
+						   1, //repetition_number
+						   (frameP*10)+subframeP);
+	    }
+#endif
+	  ul_req->number_of_pdus = 1;
+	  eNB->ul_handle++;
+	    
+	    
+	  	
+	  add_ue_ulsch_info(module_idP,
+			      CC_id,
+			      UE_id,
+			      subframeP,
+			      S_UL_SCHEDULED);
+	    
+            // increment first rb for next UE allocation
+       first_rb[CC_id]+= nb_rb;
+	    
+	  	  
+  } // loop of CC_id
+}
diff --git a/openair2/LAYER2/MAC/mac.h b/openair2/LAYER2/MAC/mac.h
index dfdb4333668493125c6c90d5b04b2fce9ea55a91..f7e9868c6af7e1628fbaf73dd01df7766f03df5e 100644
--- a/openair2/LAYER2/MAC/mac.h
+++ b/openair2/LAYER2/MAC/mac.h
@@ -1060,6 +1060,7 @@ typedef struct {
 /*! \brief top level eNB MAC structure */
 typedef struct eNB_MAC_INST_s {
     /// Ethernet parameters for northbound midhaul interface
+<<<<<<< HEAD:openair2/LAYER2/MAC/mac.h
   eth_params_t eth_params_n;
   /// Ethernet parameters for fronthaul interface
   eth_params_t eth_params_s;
diff --git a/openair2/LAYER2/MAC/mac_proto.h b/openair2/LAYER2/MAC/mac_proto.h
index 6fb5d541f836c91c86f4a5f31552417790d6b43b..3c4f830bdb323f6be973d848010e38dd2e0f0a65 100644
--- a/openair2/LAYER2/MAC/mac_proto.h
+++ b/openair2/LAYER2/MAC/mac_proto.h
@@ -151,6 +151,9 @@ void schedule_dlsch(module_id_t module_idP, frame_t frameP,
 void schedule_ue_spec(module_id_t module_idP, slice_id_t slice_idP,
 		      frame_t frameP,sub_frame_t subframe, int *mbsfn_flag);
 
+void schedule_ue_spec_phy_test(module_id_t module_idP,frame_t frameP,sub_frame_t subframe,int *mbsfn_flag);
+void schedule_ulsch_phy_test(module_id_t module_idP,frame_t frameP,sub_frame_t subframeP);
+
 
 /** \brief Function for UE/PHY to compute PUSCH transmit power in power-control procedure.
     @param Mod_id Module id of UE
diff --git a/openair2/LAYER2/PDCP_v10.1.0/pdcp.c b/openair2/LAYER2/PDCP_v10.1.0/pdcp.c
index ea67a660aef1f4e90a2c8d7fe272af50fe1a3b15..51817a02e1388da90ef96e04fd57bc86a4166ff1 100644
--- a/openair2/LAYER2/PDCP_v10.1.0/pdcp.c
+++ b/openair2/LAYER2/PDCP_v10.1.0/pdcp.c
@@ -859,7 +859,8 @@ void pdcp_update_stats(const protocol_ctxt_t* const  ctxt_pP){
     for (pdcp_uid=0; pdcp_uid< NUMBER_OF_UE_MAX;pdcp_uid++){
       //printf("frame %d and subframe %d \n", pdcp_enb[ctxt_pP->module_id].frame, pdcp_enb[ctxt_pP->module_id].subframe);
       // tx stats
-      if (pdcp_enb[ctxt_pP->module_id].sfn % Pdcp_stats_tx_window_ms[ctxt_pP->module_id][pdcp_uid] == 0){
+      if (Pdcp_stats_tx_window_ms[ctxt_pP->module_id][pdcp_uid] > 0 &&
+          pdcp_enb[ctxt_pP->module_id].sfn % Pdcp_stats_tx_window_ms[ctxt_pP->module_id][pdcp_uid] == 0){
 	// unit: bit/s
 	Pdcp_stats_tx_throughput_w[ctxt_pP->module_id][pdcp_uid][rb_id]=Pdcp_stats_tx_bytes_tmp_w[ctxt_pP->module_id][pdcp_uid][rb_id]*8;
 	Pdcp_stats_tx_w[ctxt_pP->module_id][pdcp_uid][rb_id]= Pdcp_stats_tx_tmp_w[ctxt_pP->module_id][pdcp_uid][rb_id];
@@ -875,7 +876,8 @@ void pdcp_update_stats(const protocol_ctxt_t* const  ctxt_pP){
 	Pdcp_stats_tx_aiat_tmp_w[ctxt_pP->module_id][pdcp_uid][rb_id]=0;
 	
       }
-      if (pdcp_enb[ctxt_pP->module_id].sfn % Pdcp_stats_rx_window_ms[ctxt_pP->module_id][pdcp_uid] == 0){
+      if (Pdcp_stats_rx_window_ms[ctxt_pP->module_id][pdcp_uid] > 0 &&
+          pdcp_enb[ctxt_pP->module_id].sfn % Pdcp_stats_rx_window_ms[ctxt_pP->module_id][pdcp_uid] == 0){
 	// rx stats
 	Pdcp_stats_rx_goodput_w[ctxt_pP->module_id][pdcp_uid][rb_id]=Pdcp_stats_rx_bytes_tmp_w[ctxt_pP->module_id][pdcp_uid][rb_id]*8;
 	Pdcp_stats_rx_w[ctxt_pP->module_id][pdcp_uid][rb_id]= 	Pdcp_stats_rx_tmp_w[ctxt_pP->module_id][pdcp_uid][rb_id];
diff --git a/openair2/LAYER2/PDCP_v10.1.0/pdcp_fifo.c b/openair2/LAYER2/PDCP_v10.1.0/pdcp_fifo.c
index 8f1bc7898ae9a0dfc4396b62e7cb54fb7a7d4d1a..86f68cc9497e797f90ea141de7e83b45ba4e6add 100644
--- a/openair2/LAYER2/PDCP_v10.1.0/pdcp_fifo.c
+++ b/openair2/LAYER2/PDCP_v10.1.0/pdcp_fifo.c
@@ -72,7 +72,11 @@ extern struct nlmsghdr *nas_nlh_tx;
 extern struct nlmsghdr *nas_nlh_rx;
 extern struct iovec nas_iov_tx;
 extern struct iovec nas_iov_rx;
+#ifdef UE_NAS_USE_TUN
+extern int nas_sock_fd[NUMBER_OF_UE_MAX];
+#else
 extern int nas_sock_fd;
+#endif
 extern struct msghdr nas_msg_tx;
 extern struct msghdr nas_msg_rx;
 
@@ -239,7 +243,11 @@ int pdcp_fifo_flush_sdus(const protocol_ctxt_t* const  ctxt_pP)
           nas_nlh_tx->nlmsg_len += pdcp_output_sdu_bytes_to_write;
           VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_UE_PDCP_FLUSH_SIZE, pdcp_output_sdu_bytes_to_write);
           VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_FIFO_FLUSH_BUFFER, 1 );
+#ifdef UE_NAS_USE_TUN
+          ret = write(nas_sock_fd[ctxt_pP->module_id], &(sdu_p->data[sizeof(pdcp_data_ind_header_t)]), pdcp_output_sdu_bytes_to_write);
+#else
           ret = sendmsg(nas_sock_fd,&nas_msg_tx,0);
+#endif
           VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_FIFO_FLUSH_BUFFER, 0 );
           VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_UE_PDCP_FLUSH_ERR, ret );
 
@@ -372,6 +380,62 @@ int pdcp_fifo_flush_sdus(const protocol_ctxt_t* const  ctxt_pP)
 //-----------------------------------------------------------------------------
 int pdcp_fifo_read_input_sdus (const protocol_ctxt_t* const  ctxt_pP)
 {
+#ifdef UE_NAS_USE_TUN
+  protocol_ctxt_t ctxt = *ctxt_pP;
+  hash_key_t key = HASHTABLE_NOT_A_KEY_VALUE;
+  hashtable_rc_t h_rc;
+  pdcp_t* pdcp_p = NULL;
+  int len;
+  rb_id_t rab_id = DEFAULT_RAB_ID;
+
+  do {
+    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_FIFO_READ, 1 );
+    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_FIFO_READ_BUFFER, 1 );
+    len = read(nas_sock_fd[ctxt_pP->module_id], &nl_rx_buf, NL_MAX_PAYLOAD);
+    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_FIFO_READ_BUFFER, 0 );
+
+    if (len<=0) continue;
+    LOG_D(PDCP, "PDCP_COLL_KEY_DEFAULT_DRB_VALUE(module_id=%d, rnti=%x, enb_flag=%d)\n",
+          ctxt.module_id, ctxt.rnti, ctxt.enb_flag);
+    key = PDCP_COLL_KEY_DEFAULT_DRB_VALUE(ctxt.module_id, ctxt.rnti, ctxt.enb_flag);
+    h_rc = hashtable_get(pdcp_coll_p, key, (void**)&pdcp_p);
+    if (h_rc == HASH_TABLE_OK) {
+      LOG_D(PDCP, "[FRAME %5u][UE][NETLINK][IP->PDCP] INST %d: Received socket with length %d on Rab %d \n",
+            ctxt.frame, ctxt.instance, len, rab_id);
+
+      LOG_D(PDCP, "[FRAME %5u][UE][IP][INSTANCE %u][RB %u][--- PDCP_DATA_REQ / %d Bytes --->][PDCP][MOD %u][UE %u][RB %u]\n",
+            ctxt.frame, ctxt.instance, rab_id, len, ctxt.module_id,
+            ctxt.rnti, rab_id);
+      MSC_LOG_RX_MESSAGE((ctxt_pP->enb_flag == ENB_FLAG_YES) ? MSC_PDCP_ENB:MSC_PDCP_UE,
+                         (ctxt_pP->enb_flag == ENB_FLAG_YES) ? MSC_IP_ENB:MSC_IP_UE,
+                         NULL, 0,
+                         MSC_AS_TIME_FMT" DATA-REQ inst %u rb %u rab %u size %u",
+                         MSC_AS_TIME_ARGS(ctxt_pP),
+                         ctxt.instance, rab_id, rab_id, len);
+
+      pdcp_data_req(&ctxt, SRB_FLAG_NO, rab_id, RLC_MUI_UNDEFINED,
+                    RLC_SDU_CONFIRM_NO, len, nl_rx_buf,
+                    PDCP_TRANSMISSION_MODE_DATA);
+    } else {
+      MSC_LOG_RX_DISCARDED_MESSAGE(
+      (ctxt_pP->enb_flag == ENB_FLAG_YES) ? MSC_PDCP_ENB:MSC_PDCP_UE,
+      (ctxt_pP->enb_flag == ENB_FLAG_YES) ? MSC_IP_ENB:MSC_IP_UE,
+      NULL,
+      0,
+      MSC_AS_TIME_FMT" DATA-REQ inst %u rb %u rab %u size %u",
+      MSC_AS_TIME_ARGS(ctxt_pP),
+      ctxt.instance, rab_id, rab_id, len);
+      LOG_D(PDCP,
+            "[FRAME %5u][UE][IP][INSTANCE %u][RB %u][--- PDCP_DATA_REQ / %d Bytes ---X][PDCP][MOD %u][UE %u][RB %u] NON INSTANCIATED INSTANCE key 0x%"PRIx64", DROPPED\n",
+            ctxt.frame, ctxt.instance, rab_id, len, ctxt.module_id,
+            ctxt.rnti, rab_id, key);
+    }
+  } while (len > 0);
+  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_FIFO_READ, 0 );
+  return len;
+
+#else /* UE_NAS_USE_TUN */
+
 #ifdef PDCP_USE_NETLINK
   protocol_ctxt_t                ctxt_cpy = *ctxt_pP;
   protocol_ctxt_t                ctxt;
@@ -764,6 +828,7 @@ int pdcp_fifo_read_input_sdus (const protocol_ctxt_t* const  ctxt_pP)
 #else // neither PDCP_USE_NETLINK nor PDCP_USE_RT_FIFO
   return 0;
 #endif // PDCP_USE_NETLINK
+#endif /* #else UE_NAS_USE_TUN */
 }
 
 
diff --git a/openair2/UTIL/LOG/vcd_signal_dumper.c b/openair2/UTIL/LOG/vcd_signal_dumper.c
index b18d2a25ffd714c778e16a96a971db1e081694d9..a026cfb081a70e1ffd8ab833dd711c329b6ee33e 100644
--- a/openair2/UTIL/LOG/vcd_signal_dumper.c
+++ b/openair2/UTIL/LOG/vcd_signal_dumper.c
@@ -191,6 +191,9 @@ const char* eurecomVariablesNames[] = {
   "ue0_trx_write_ns",
   "ue0_trx_read_ns_missing",
   "ue0_trx_write_ns_missing",
+  "enb_thread_rxtx_CPUID",
+  "ru_thread_CPUID",
+  "ru_thread_tx_CPUID"
 };
 
 const char* eurecomFunctionsNames[] = {
diff --git a/openair2/UTIL/LOG/vcd_signal_dumper.h b/openair2/UTIL/LOG/vcd_signal_dumper.h
index a4c8cd2476e08f0b234e47540b54b89b1d6b52fd..a47cdc059d1a8236b78255b28d457ad8979613e5 100644
--- a/openair2/UTIL/LOG/vcd_signal_dumper.h
+++ b/openair2/UTIL/LOG/vcd_signal_dumper.h
@@ -167,6 +167,9 @@ typedef enum {
   VCD_SIGNAL_DUMPER_VARIABLES_UE0_TRX_WRITE_NS,
   VCD_SIGNAL_DUMPER_VARIABLES_UE0_TRX_READ_NS_MISSING,
   VCD_SIGNAL_DUMPER_VARIABLES_UE0_TRX_WRITE_NS_MISSING,
+  VCD_SIGNAL_DUMPER_VARIABLES_CPUID_ENB_THREAD_RXTX,
+  VCD_SIGNAL_DUMPER_VARIABLES_CPUID_RU_THREAD,
+  VCD_SIGNAL_DUMPER_VARIABLES_CPUID_RU_THREAD_TX,
   VCD_SIGNAL_DUMPER_VARIABLES_END
 } vcd_signal_dump_variables;
 
diff --git a/targets/ARCH/COMMON/common_lib.c b/targets/ARCH/COMMON/common_lib.c
index d74b1c6d4fed2d65640c1d5989e2ec846c642dcf..7ff3b820dca5e121f585bd3b9c5a5827ddea1e95 100644
--- a/targets/ARCH/COMMON/common_lib.c
+++ b/targets/ARCH/COMMON/common_lib.c
@@ -117,7 +117,7 @@ int openair0_device_load(openair0_device *device, openair0_config_t *openair0_cf
   rc=load_lib(device, openair0_cfg, NULL,RAU_LOCAL_RADIO_HEAD );
 
   if ( rc >= 0) {       
-    if ( set_device(device) < 0) {
+	if ( set_device(device) < 0) {
       fprintf(stderr, "%s %d:Unsupported radio head\n",__FILE__, __LINE__);
       return -1;		   
     }   
diff --git a/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp b/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp
index 9b1755954ae84655a75cbe25ba0570291d01097f..a99c9d7a5d01d95060c9909486bf6528be2b547c 100644
--- a/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp
+++ b/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp
@@ -982,15 +982,20 @@ extern "C" {
             // workaround for an api problem, master clock has to be set with the constructor not via set_master_clock_rate
             args += boost::str(boost::format(",master_clock_rate=%f") % usrp_master_clock);
 
-//    args += ",num_send_frames=256,num_recv_frames=256, send_frame_size=4096, recv_frame_size=4096";
-
             //    args += ",num_send_frames=256,num_recv_frames=256, send_frame_size=4096, recv_frame_size=4096";
             uhd::device_addrs_t device_adds = uhd::device::find(args);
 
             if(device_adds.size() == 0) {
-                std::cerr<<"No USRP Device Found. " << std::endl;
-                free(s);
-                return -1;
+		args += ",addr=192.168.30.2";
+
+            	uhd::device_addrs_t device_adds = uhd::device::find(args);
+
+ 	        if(device_adds.size() == 0) {
+ 
+                	std::cerr<<"No USRP Device Found. " << std::endl;
+                	free(s);
+                	return -1;
+		}
             }
             LOG_I(PHY,"Found USRP X300\n");
             s->usrp = uhd::usrp::multi_usrp::make(args);
@@ -1016,6 +1021,20 @@ extern "C" {
             LOG_I(PHY,"%s() sample_rate:%u\n", __FUNCTION__, (int)openair0_cfg[0].sample_rate);
 
             switch ((int)openair0_cfg[0].sample_rate) {
+			case 122880000:
+                // from usrp_time_offset
+                //openair0_cfg[0].samples_per_packet    = 2048;
+				openair0_cfg[0].tx_sample_advance     = 15; //to be checked
+                openair0_cfg[0].tx_bw                 = 80e6;
+                openair0_cfg[0].rx_bw                 = 80e6;
+                break;
+            case 61440000:
+                // from usrp_time_offset
+                //openair0_cfg[0].samples_per_packet    = 2048;
+                openair0_cfg[0].tx_sample_advance     = 15;
+                openair0_cfg[0].tx_bw                 = 40e6;
+                openair0_cfg[0].rx_bw                 = 40e6;
+                break;
             case 30720000:
                 // from usrp_time_offset
                 //openair0_cfg[0].samples_per_packet    = 2048;
diff --git a/targets/COMMON/create_tasks.c b/targets/COMMON/create_tasks.c
index 70d29af2527d240ca1f259625b5bf2b310b7a6df..391e448deb590584e9a4b917edd4a6210b1fa1a5 100644
--- a/targets/COMMON/create_tasks.c
+++ b/targets/COMMON/create_tasks.c
@@ -40,6 +40,8 @@
 # endif
 # include "enb_app.h"
 
+extern int emulate_rf;
+
 int create_tasks(uint32_t enb_nb)
 {
   LOG_D(ENB_APP, "%s(enb_nb:%d\n", __FUNCTION__, enb_nb);
@@ -69,10 +71,11 @@ int create_tasks(uint32_t enb_nb)
           LOG_E(S1AP, "Create task for S1AP failed\n");
           return -1;
         }
-
-        if (itti_create_task (TASK_UDP, udp_eNB_task, NULL) < 0) {
-          LOG_E(UDP_, "Create task for UDP failed\n");
-          return -1;
+        if(!emulate_rf){
+          if (itti_create_task (TASK_UDP, udp_eNB_task, NULL) < 0) {
+            LOG_E(UDP_, "Create task for UDP failed\n");
+            return -1;
+          }
         }
 
         if (itti_create_task (TASK_GTPV1_U, &gtpv1u_eNB_task, NULL) < 0) {
diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.100PRB.usrpx310.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.100PRB.usrpx310.conf
new file mode 100644
index 0000000000000000000000000000000000000000..6c7c319a11239189d7c314f3d01c829441301cf2
--- /dev/null
+++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.100PRB.usrpx310.conf
@@ -0,0 +1,209 @@
+Active_eNBs = ( "eNB_Eurecom_LTEBox");
+# Asn1_verbosity, choice in: none, info, annoying
+Asn1_verbosity = "none";
+
+eNBs =
+(
+ {
+    ////////// Identification parameters:
+    eNB_ID    =  0xe00;
+
+    cell_type =  "CELL_MACRO_ENB";
+
+    eNB_name  =  "eNB_Eurecom_LTEBox";
+
+    // Tracking area code, 0x0000 and 0xfffe are reserved values
+    tracking_area_code  =  "1";
+
+    mobile_country_code =  "208";
+
+    mobile_network_code =  "93";
+
+    tr_s_preference     = "local_mac"
+
+    ////////// Physical parameters:
+
+    component_carriers = (
+      {
+      node_function             = "eNodeB_3GPP";
+      node_timing               = "synch_to_ext_device";
+      node_synch_ref            = 0;
+      frame_type					      = "FDD";
+      tdd_config 					      = 3;
+      tdd_config_s            			      = 0;
+      prefix_type             			      = "NORMAL";
+      eutra_band              			      = 7;
+      downlink_frequency      			      = 2685000000L;
+      uplink_frequency_offset 			      = -120000000;
+      Nid_cell					      = 0;
+      N_RB_DL                 			      = 100;
+      Nid_cell_mbsfn          			      = 0;
+      nb_antenna_ports                                = 1;
+      nb_antennas_tx          			      = 1;
+      nb_antennas_rx          			      = 1;
+      tx_gain                                            = 90;
+      rx_gain                                            = 125;
+      pbch_repetition                                 = "FALSE";
+      prach_root              			      = 0;
+      prach_config_index      			      = 0;
+      prach_high_speed        			      = "DISABLE";
+      prach_zero_correlation  			      = 1;
+      prach_freq_offset       			      = 2;
+      pucch_delta_shift       			      = 1;
+      pucch_nRB_CQI           			      = 1;
+      pucch_nCS_AN            			      = 0;
+      pucch_n1_AN             			      = 32;
+      pdsch_referenceSignalPower 			      = -27;
+      pdsch_p_b                  			      = 0;
+      pusch_n_SB                 			      = 1;
+      pusch_enable64QAM          			      = "DISABLE";
+      pusch_hoppingMode                                  = "interSubFrame";
+      pusch_hoppingOffset                                = 0;
+      pusch_groupHoppingEnabled  			      = "ENABLE";
+      pusch_groupAssignment      			      = 0;
+      pusch_sequenceHoppingEnabled		   	      = "DISABLE";
+      pusch_nDMRS1                                       = 1;
+      phich_duration                                     = "NORMAL";
+      phich_resource                                     = "ONESIXTH";
+      srs_enable                                         = "DISABLE";
+      /*  srs_BandwidthConfig                                =;
+      srs_SubframeConfig                                 =;
+      srs_ackNackST                                      =;
+      srs_MaxUpPts                                       =;*/
+
+      pusch_p0_Nominal                                   = -96;
+      pusch_alpha                                        = "AL1";
+      pucch_p0_Nominal                                   = -104;
+      msg3_delta_Preamble                                = 6;
+      pucch_deltaF_Format1                               = "deltaF2";
+      pucch_deltaF_Format1b                              = "deltaF3";
+      pucch_deltaF_Format2                               = "deltaF0";
+      pucch_deltaF_Format2a                              = "deltaF0";
+      pucch_deltaF_Format2b		    	      = "deltaF0";
+
+      rach_numberOfRA_Preambles                          = 64;
+      rach_preamblesGroupAConfig                         = "DISABLE";
+      /*
+      rach_sizeOfRA_PreamblesGroupA                      = ;
+      rach_messageSizeGroupA                             = ;
+      rach_messagePowerOffsetGroupB                      = ;
+      */
+      rach_powerRampingStep                              = 4;
+      rach_preambleInitialReceivedTargetPower            = -108;
+      rach_preambleTransMax                              = 10;
+      rach_raResponseWindowSize                          = 10;
+      rach_macContentionResolutionTimer                  = 48;
+      rach_maxHARQ_Msg3Tx                                = 4;
+
+      pcch_default_PagingCycle                           = 128;
+      pcch_nB                                            = "oneT";
+      bcch_modificationPeriodCoeff			      = 2;
+      ue_TimersAndConstants_t300			      = 1000;
+      ue_TimersAndConstants_t301			      = 1000;
+      ue_TimersAndConstants_t310			      = 1000;
+      ue_TimersAndConstants_t311			      = 10000;
+      ue_TimersAndConstants_n310			      = 20;
+      ue_TimersAndConstants_n311			      = 1;
+      ue_TransmissionMode                                    = 1;
+      }
+    );
+
+
+    srb1_parameters :
+    {
+        # timer_poll_retransmit = (ms) [5, 10, 15, 20,... 250, 300, 350, ... 500]
+        timer_poll_retransmit    = 80;
+
+        # timer_reordering = (ms) [0,5, ... 100, 110, 120, ... ,200]
+        timer_reordering         = 35;
+
+        # timer_reordering = (ms) [0,5, ... 250, 300, 350, ... ,500]
+        timer_status_prohibit    = 0;
+
+        # poll_pdu = [4, 8, 16, 32 , 64, 128, 256, infinity(>10000)]
+        poll_pdu                 =  4;
+
+        # poll_byte = (kB) [25,50,75,100,125,250,375,500,750,1000,1250,1500,2000,3000,infinity(>10000)]
+        poll_byte                =  99999;
+
+        # max_retx_threshold = [1, 2, 3, 4 , 6, 8, 16, 32]
+        max_retx_threshold       =  4;
+    }
+
+    # ------- SCTP definitions
+    SCTP :
+    {
+        # Number of streams to use in input/output
+        SCTP_INSTREAMS  = 2;
+        SCTP_OUTSTREAMS = 2;
+    };
+
+
+    ////////// MME parameters:
+    mme_ip_address      = ( { ipv4       = "192.168.12.26";
+                              ipv6       = "192:168:30::17";
+                              active     = "yes";
+                              preference = "ipv4";
+                            }
+                          );
+
+    NETWORK_INTERFACES :
+    {
+
+        ENB_INTERFACE_NAME_FOR_S1_MME            = "eth6";
+        ENB_IPV4_ADDRESS_FOR_S1_MME              = "192.168.12.111/24";
+        ENB_INTERFACE_NAME_FOR_S1U               = "eth6";
+        ENB_IPV4_ADDRESS_FOR_S1U                 = "192.168.12.111/24";
+        ENB_PORT_FOR_S1U                         = 2152; # Spec 2152
+    };
+  }
+);
+
+MACRLCs = (
+	{
+	num_cc = 1;
+	tr_s_preference = "local_L1";
+	tr_n_preference = "local_RRC";
+        }  
+);
+
+L1s = (
+    	{
+	num_cc = 1;
+	tr_n_preference = "local_mac";
+        }  
+);
+
+RUs = (
+    {		  
+       local_rf       = "yes"
+         nb_tx          = 1
+         nb_rx          = 1
+         att_tx         = 0
+         att_rx         = 0;
+         bands          = [7];
+         max_pdschReferenceSignalPower = -27;
+         max_rxgain                    = 116;
+         eNB_instances  = [0];
+
+    }
+);  
+
+     log_config :
+     {
+       global_log_level                      ="info";
+       global_log_verbosity                  ="medium";
+       hw_log_level                          ="info";
+       hw_log_verbosity                      ="medium";
+       phy_log_level                         ="info";
+       phy_log_verbosity                     ="medium";
+       mac_log_level                         ="info";
+       mac_log_verbosity                     ="medium";
+       rlc_log_level                         ="info";
+       rlc_log_verbosity                     ="medium";
+       pdcp_log_level                        ="info";
+       pdcp_log_verbosity                    ="medium";
+       rrc_log_level                         ="info";
+       rrc_log_verbosity                     ="medium";
+    };
+
diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.usrpb210.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.usrpb210.conf
index c4307f8ff2333d9bcbe202e719917912dbb947d9..cfbfa51cab275669015604756f7e00f9436121e1 100644
--- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.usrpb210.conf
+++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.usrpb210.conf
@@ -151,9 +151,9 @@ eNBs =
     {
 
         ENB_INTERFACE_NAME_FOR_S1_MME            = "eth0";
-        ENB_IPV4_ADDRESS_FOR_S1_MME              = "192.168.12.19/24";
+        ENB_IPV4_ADDRESS_FOR_S1_MME              = "192.168.12.111/24";
         ENB_INTERFACE_NAME_FOR_S1U               = "eth0";
-        ENB_IPV4_ADDRESS_FOR_S1U                 = "192.168.12.19/24";
+        ENB_IPV4_ADDRESS_FOR_S1U                 = "192.168.12.111/24";
         ENB_PORT_FOR_S1U                         = 2152; # Spec 2152
     };
   }
@@ -164,6 +164,7 @@ MACRLCs = (
 	num_cc = 1;
 	tr_s_preference = "local_L1";
 	tr_n_preference = "local_RRC";
+	phy_test_mode = 1;
         }  
 );
 
diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rcc.band7.tm1.if4p5.50PRB.lo.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rcc.band7.tm1.if4p5.50PRB.lo.conf
index aacc87e5b0c49c18d2432224e849121879a48b8a..771bf094997b62110b0394945f74f3acec5c103d 100644
--- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rcc.band7.tm1.if4p5.50PRB.lo.conf
+++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rcc.band7.tm1.if4p5.50PRB.lo.conf
@@ -73,8 +73,7 @@ eNBs =
       srs_SubframeConfig                                 =;
       srs_ackNackST                                      =;
       srs_MaxUpPts                                       =;*/
-
-      pusch_p0_Nominal                                   = -96;
+      pusch_p0_Nominal                                   = -104;
       pusch_alpha                                        = "AL1";
       pucch_p0_Nominal                                   = -104;
       msg3_delta_Preamble                                = 6;
diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rru.oaisim.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rru.oaisim.conf
index 24ae36a0a4c7c671f0cc4ad4754f1d6b233397a6..8a0f5feb58687406028e6c81b78a9b4175c3adec 100644
--- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rru.oaisim.conf
+++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rru.oaisim.conf
@@ -11,7 +11,7 @@ RUs = (
     	tr_preference                    = "udp_if4p5";
 	nb_tx                            = 1;
 	nb_rx                            = 1;
-	max_pdschReferenceSignalPower    = -29;
+	max_pdschReferenceSignalPower    = -15;
 	max_rxgain                       = 120;
 	bands                            = [7,13];
     }
diff --git a/targets/RT/USER/eNB_usrp.gtkw b/targets/RT/USER/eNB_usrp.gtkw
index 838ec54383f4de0dc6f6165fc374013a3f80e3b8..e50c1831b69ba1e7e49ab33f79f0df523cb15ec0 100644
--- a/targets/RT/USER/eNB_usrp.gtkw
+++ b/targets/RT/USER/eNB_usrp.gtkw
@@ -1,19 +1,19 @@
 [*]
 [*] GTKWave Analyzer v3.3.58 (w)1999-2014 BSI
-[*] Tue Jul 25 20:26:12 2017
+[*] Thu Feb 22 14:46:40 2018
 [*]
 [dumpfile] "/tmp/openair_dump_eNB.vcd"
-[dumpfile_mtime] "Tue Jul 25 20:11:55 2017"
-[dumpfile_size] 19201475
-[savefile] "/home/papillon/openairinterface5g/targets/RT/USER/eNB_usrp.gtkw"
-[timestart] 29023604000
-[size] 1236 578
-[pos] 309 0
-*-20.793451 29026062100 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
+[dumpfile_mtime] "Thu Feb 22 14:44:26 2018"
+[dumpfile_size] 3482761
+[savefile] "/homes/wangts/openairinterface5g/targets/RT/USER/eNB_usrp.gtkw"
+[timestart] 4525000000
+[size] 1920 1018
+[pos] 0 22
+*-21.506693 4530514310 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
 [sst_width] 386
-[signals_width] 262
+[signals_width] 344
 [sst_expanded] 1
-[sst_vpaned_height] 146
+[sst_vpaned_height] 303
 @28
 functions.trx_read
 functions.trx_write
@@ -25,12 +25,42 @@ functions.eNB_thread_rxtx0
 @24
 variables.frame_number_RX0_RU[63:0]
 variables.subframe_number_RX0_RU[63:0]
-@25
 variables.frame_number_TX0_RU[63:0]
-@24
 variables.subframe_number_TX0_RU[63:0]
 @28
+functions.mac_schedule_dlsch
+functions.macxface_eNB_dlsch_ulsch_scheduler
+functions.macxface_ue_scheduler
+functions.phy_eNB_ofdm_mod_l
+@24
+variables.frame_number_RX0_eNB[63:0]
+@25
+variables.subframe_number_RX0_eNB[63:0]
+@24
+variables.frame_number_TX0_eNB[63:0]
+variables.subframe_number_TX0_eNB[63:0]
+variables.frame_number_RX1_eNB[63:0]
+variables.subframe_number_RX1_eNB[63:0]
+variables.frame_number_TX1_eNB[63:0]
+variables.subframe_number_TX1_eNB[63:0]
+@28
+functions.phy_eNB_dlsch_modulation
+functions.phy_eNB_dlsch_encoding
+functions.phy_eNB_dlsch_scrambling
+functions.phy_eNB_beam_precoding
+functions.phy_enb_pdcch_tx
+functions.phy_enb_prach_rx
+functions.phy_procedures_ru_feprx0
+functions.phy_procedures_eNb_rx_uespec0
+functions.phy_procedures_eNb_rx_uespec1
+functions.phy_enb_sfgen
 functions.phy_procedures_eNb_tx0
+functions.phy_procedures_eNb_tx1
+functions.phy_procedures_ru_feprx1
+functions.phy_procedures_ru_feptx_ofdm0
+functions.phy_procedures_ru_feptx_ofdm1
+functions.phy_procedures_ru_feptx_prec0
+functions.phy_procedures_ru_feptx_prec1
 functions.eNB_thread_rxtx1
 functions.phy_enb_sfgen
 functions.phy_enb_prach_rx
diff --git a/targets/RT/USER/lte-enb.c b/targets/RT/USER/lte-enb.c
index a4bb8cfd60440928f628a9ebbf93228dbfa28659..9f4f62ccdef479a2784cc2fbaefd2677153af996 100644
--- a/targets/RT/USER/lte-enb.c
+++ b/targets/RT/USER/lte-enb.c
@@ -145,11 +145,13 @@ void exit_fun(const char* s);
 void init_eNB(int,int);
 void stop_eNB(int nb_inst);
 
-
+int wakeup_tx(PHY_VARS_eNB *eNB,RU_proc_t *ru_proc);
+int wakeup_txfh(eNB_rxtx_proc_t *proc,RU_proc_t *ru_proc);
 void wakeup_prach_eNB(PHY_VARS_eNB *eNB,RU_t *ru,int frame,int subframe);
 #ifdef Rel14
 void wakeup_prach_eNB_br(PHY_VARS_eNB *eNB,RU_t *ru,int frame,int subframe);
 #endif
+extern int codingw;
 
 extern uint8_t nfapi_mode;
 extern void oai_subframe_ind(uint16_t sfn, uint16_t sf);
@@ -217,6 +219,15 @@ static inline int rxtx(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc, char *thread_nam
   if (nfapi_mode == 0 || nfapi_mode == 1) {
     phy_procedures_eNB_uespec_RX(eNB, proc);
   }
+  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_DLSCH_ULSCH_SCHEDULER , 1 );
+
+  if(get_nprocs() >= 8){
+    if(wait_on_condition(&proc[1].mutex_rxtx,&proc[1].cond_rxtx,&proc[1].pipe_ready,"wakeup_tx")<0) {
+      LOG_E(PHY,"Frame %d, subframe %d: TX1 not ready\n",proc[1].frame_rx,proc[1].subframe_rx);
+      return(-1);
+    }
+    if (release_thread(&proc[1].mutex_rxtx,&proc[1].pipe_ready,"wakeup_tx")<0)  return(-1);
+  }
 
   pthread_mutex_lock(&eNB->UL_INFO_mutex);
 
@@ -228,17 +239,12 @@ static inline int rxtx(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc, char *thread_nam
   eNB->if_inst->UL_indication(&eNB->UL_INFO);
 
   pthread_mutex_unlock(&eNB->UL_INFO_mutex);
-
-  // *****************************************
-  // TX processing for subframe n+sf_ahead
-  // run PHY TX procedures the one after the other for all CCs to avoid race conditions
-  // (may be relaxed in the future for performance reasons)
-  // *****************************************
-  //if (wait_CCs(proc)<0) return(-1);
-  
-  if (oai_exit) return(-1);
   
-  phy_procedures_eNB_TX(eNB, proc, 1);
+  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_DLSCH_ULSCH_SCHEDULER , 0 );
+  if(oai_exit) return(-1);
+  if(get_nprocs() <= 4){
+    phy_procedures_eNB_TX(eNB, proc, 1);
+  }
 
   stop_meas( &softmodem_stats_rxtx_sf );
 
@@ -290,6 +296,50 @@ static inline int rxtx(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc, char *thread_nam
 }
 
 
+static void* tx_thread(void* param) {
+
+  eNB_proc_t *eNB_proc  = (eNB_proc_t*)param;
+  eNB_rxtx_proc_t *proc = &eNB_proc->proc_rxtx[1];
+  PHY_VARS_eNB *eNB = RC.eNB[0][proc->CC_id];
+  
+  char thread_name[100];
+  sprintf(thread_name,"TXnp4_%d\n",&eNB->proc.proc_rxtx[0] == proc ? 0 : 1);
+  thread_top_init(thread_name,1,470000,500000,500000);
+  
+  //wait_sync("tx_thread");
+  
+  while (!oai_exit) {
+    
+
+    if (wait_on_condition(&proc->mutex_rxtx,&proc->cond_rxtx,&proc->instance_cnt_rxtx,thread_name)<0) break;
+    if (oai_exit) break;    
+    // *****************************************
+    // TX processing for subframe n+4
+    // run PHY TX procedures the one after the other for all CCs to avoid race conditions
+    // (may be relaxed in the future for performance reasons)
+    // *****************************************
+    VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_TX1_ENB,proc->subframe_tx);
+    VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_RX1_ENB,proc->subframe_rx);
+    VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX1_ENB,proc->frame_tx);
+    VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX1_ENB,proc->frame_rx);
+    
+    phy_procedures_eNB_TX(eNB, proc, no_relay, NULL, 1);
+    if (release_thread(&proc->mutex_rxtx,&proc->instance_cnt_rxtx,thread_name)<0) break;
+	
+    pthread_mutex_lock( &proc->mutex_rxtx );
+    proc->pipe_ready++;
+    // the thread can now be woken up
+    if (pthread_cond_signal(&proc->cond_rxtx) != 0) {
+      LOG_E( PHY, "[eNB] ERROR pthread_cond_signal for eNB TXnp4 thread\n");
+      exit_fun( "ERROR pthread_cond_signal" );
+    }
+    pthread_mutex_unlock( &proc->mutex_rxtx );
+    wakeup_txfh(proc,eNB_proc->ru_proc);
+  }
+
+  return 0;
+}
+
 /*!
  * \brief The RX UE-specific and TX thread of eNB.
  * \param param is a \ref eNB_proc_t structure which contains the info what to process.
@@ -299,36 +349,66 @@ static inline int rxtx(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc, char *thread_nam
 static void* eNB_thread_rxtx( void* param ) {
 
   static int eNB_thread_rxtx_status;
-
-  eNB_rxtx_proc_t *proc = (eNB_rxtx_proc_t*)param;
+  eNB_proc_t *eNB_proc  = (eNB_proc_t*)param;
+  eNB_rxtx_proc_t *proc = &eNB_proc->proc_rxtx[0];
   PHY_VARS_eNB *eNB = RC.eNB[0][proc->CC_id];
+  //RU_proc_t *ru_proc = NULL;
 
   char thread_name[100];
 
+  cpu_set_t cpuset;
+  CPU_ZERO(&cpuset);
 
   // set default return value
   eNB_thread_rxtx_status = 0;
 
 
-  sprintf(thread_name,"RXn_TXnp4_%d",&eNB->proc.proc_rxtx[0] == proc ? 0 : 1);
-  thread_top_init(thread_name,1,850000L,1000000L,2000000L);
+  sprintf(thread_name,"RXn_TXnp4_%d\n",&eNB->proc.proc_rxtx[0] == proc ? 0 : 1);
+  thread_top_init(thread_name,1,470000,500000,500000);
+  pthread_setname_np( pthread_self(),"rxtx processing");
+  LOG_I(PHY,"thread rxtx created id=%ld\n", syscall(__NR_gettid));
+
+
 
   while (!oai_exit) {
+    
+    
     VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_RXTX0+(proc->subframe_rx&1), 0 );
+    T(T_ENB_MASTER_TICK, T_INT(0), T_INT(proc->frame_rx), T_INT(proc->subframe_rx));
 
     if (wait_on_condition(&proc->mutex_rxtx,&proc->cond_rxtx,&proc->instance_cnt_rxtx,thread_name)<0) break;
 
+    VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_CPUID_ENB_THREAD_RXTX,sched_getcpu());
     VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_RXTX0+(proc->subframe_rx&1), 1 );
+   
+    VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_TX0_ENB,proc->subframe_tx);
+    VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_RX0_ENB,proc->subframe_rx);
+    VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX0_ENB,proc->frame_tx);
+    VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX0_ENB,proc->frame_rx);
+ 
 
     if (oai_exit) break;
 
     if (eNB->CC_id==0)
     {
       if (rxtx(eNB,proc,thread_name) < 0) break;
-
     }
 
     if (release_thread(&proc->mutex_rxtx,&proc->instance_cnt_rxtx,thread_name)<0) break;
+    pthread_mutex_lock( &proc->mutex_rxtx );
+    proc->pipe_ready++;
+    // the thread can now be woken up
+    if (pthread_cond_signal(&proc->cond_rxtx) != 0) {
+      LOG_E( PHY, "[eNB] ERROR pthread_cond_signal for eNB TXnp4 thread\n");
+      exit_fun( "ERROR pthread_cond_signal" );
+    }
+    pthread_mutex_unlock( &proc->mutex_rxtx );
+    if(get_nprocs() >= 8)      wakeup_tx(eNB,eNB->proc.ru_proc);
+    else
+    {  
+      phy_procedures_eNB_TX(eNB, proc, no_relay, NULL, 1);
+      wakeup_txfh(proc,eNB->proc.ru_proc);
+    }
 
   } // while !oai_exit
 
@@ -364,10 +444,12 @@ static void wait_system_ready (char *message, volatile int *start_flag) {
 
 
 
-void eNB_top(PHY_VARS_eNB *eNB, int frame_rx, int subframe_rx, char *string)
+void eNB_top(PHY_VARS_eNB *eNB, int frame_rx, int subframe_rx, char *string,RU_t *ru)
 {
   eNB_proc_t *proc           = &eNB->proc;
   eNB_rxtx_proc_t *proc_rxtx = &proc->proc_rxtx[0];
+  LTE_DL_FRAME_PARMS *fp = &ru->frame_parms;
+  RU_proc_t *ru_proc=&ru->proc;
 
   proc->frame_rx    = frame_rx;
   proc->subframe_rx = subframe_rx;
@@ -375,23 +457,113 @@ void eNB_top(PHY_VARS_eNB *eNB, int frame_rx, int subframe_rx, char *string)
   if (!oai_exit) {
     T(T_ENB_MASTER_TICK, T_INT(0), T_INT(proc->frame_rx), T_INT(proc->subframe_rx));
 
-    proc_rxtx->subframe_rx = proc->subframe_rx;
-    proc_rxtx->frame_rx    = proc->frame_rx;
-    proc_rxtx->subframe_tx = (proc->subframe_rx+sf_ahead)%10;
-    proc_rxtx->frame_tx    = (proc->subframe_rx>(9-sf_ahead)) ? (1+proc->frame_rx)&1023 : proc->frame_rx;
-    proc->frame_tx         = proc_rxtx->frame_tx;
-    proc_rxtx->timestamp_tx = proc->timestamp_tx;
+    proc_rxtx->timestamp_tx = ru_proc->timestamp_rx + (sf_ahead*fp->samples_per_tti);
+    proc_rxtx->frame_rx     = ru_proc->frame_rx;
+    proc_rxtx->subframe_rx  = ru_proc->subframe_rx;
+    proc_rxtx->frame_tx     = (proc_rxtx->subframe_rx > (9-sf_ahead)) ? (proc_rxtx->frame_rx+1)&1023 : proc_rxtx->frame_rx;
+    proc_rxtx->subframe_tx  = (proc_rxtx->subframe_rx + sf_ahead)%10;
 
     if (rxtx(eNB,proc_rxtx,string) < 0) LOG_E(PHY,"eNB %d CC_id %d failed during execution\n",eNB->Mod_id,eNB->CC_id);
+    ru_proc->timestamp_tx = proc_rxtx->timestamp_tx;
+    ru_proc->subframe_tx  = proc_rxtx->subframe_tx;
+    ru_proc->frame_tx     = proc_rxtx->frame_tx;
+  }
+}
+
+int wakeup_txfh(eNB_rxtx_proc_t *proc,RU_proc_t *ru_proc) {
+  
+  struct timespec wait;
+  wait.tv_sec=0;
+  wait.tv_nsec=5000000L;
+
+  
+  if(wait_on_condition(&ru_proc->mutex_eNBs,&ru_proc->cond_eNBs,&ru_proc->ru_tx_ready,"wakeup_txfh")<0) {
+    LOG_E(PHY,"Frame %d, subframe %d: TX FH not ready\n", ru_proc->frame_tx, ru_proc->subframe_tx);
+    return(-1);
+  }
+  if (release_thread(&ru_proc->mutex_eNBs,&ru_proc->ru_tx_ready,"wakeup_txfh")<0) return(-1);
+  
+  if (ru_proc->instance_cnt_eNBs == 0) {
+    LOG_E(PHY,"Frame %d, subframe %d: TX FH thread busy, dropping Frame %d, subframe %d\n", ru_proc->frame_tx, ru_proc->subframe_tx, proc->frame_rx, proc->subframe_rx);
+    return(-1);
+  }
+  if (pthread_mutex_timedlock(&ru_proc->mutex_eNBs,&wait) != 0) {
+    LOG_E( PHY, "[eNB] ERROR pthread_mutex_lock for eNB TX1 thread %d (IC %d)\n", ru_proc->subframe_rx&1,ru_proc->instance_cnt_eNBs );
+    exit_fun( "error locking mutex_eNB" );
+    return(-1);
+  }
+
+    ++ru_proc->instance_cnt_eNBs;
+    ru_proc->timestamp_tx = proc->timestamp_tx;
+    ru_proc->subframe_tx  = proc->subframe_tx;
+    ru_proc->frame_tx     = proc->frame_tx;
+  
+  // the thread can now be woken up
+  if (pthread_cond_signal(&ru_proc->cond_eNBs) != 0) {
+    LOG_E( PHY, "[eNB] ERROR pthread_cond_signal for eNB TXnp4 thread\n");
+    exit_fun( "ERROR pthread_cond_signal" );
+    return(-1);
   }
+  
+  pthread_mutex_unlock( &ru_proc->mutex_eNBs );
+
+  return(0);
 }
 
+int wakeup_tx(PHY_VARS_eNB *eNB,RU_proc_t *ru_proc) {
+
+  eNB_proc_t *proc=&eNB->proc;
+
+  eNB_rxtx_proc_t *proc_rxtx1=&proc->proc_rxtx[1];//*proc_rxtx=&proc->proc_rxtx[proc->frame_rx&1];
+  eNB_rxtx_proc_t *proc_rxtx0=&proc->proc_rxtx[0];
+
+  
+  struct timespec wait;
+  wait.tv_sec=0;
+  wait.tv_nsec=5000000L;
+  
+  
+  
+  if (proc_rxtx1->instance_cnt_rxtx == 0) {
+    LOG_E(PHY,"Frame %d, subframe %d: TX1 thread busy, dropping\n",proc_rxtx1->frame_rx,proc_rxtx1->subframe_rx);
+    return(-1);
+  }
+  
+  if (pthread_mutex_timedlock(&proc_rxtx1->mutex_rxtx,&wait) != 0) {
+    LOG_E( PHY, "[eNB] ERROR pthread_mutex_lock for eNB TX1 thread %d (IC %d)\n", proc_rxtx1->subframe_rx&1,proc_rxtx1->instance_cnt_rxtx );
+    exit_fun( "error locking mutex_tx" );
+    return(-1);
+  }
+
+  ++proc_rxtx1->instance_cnt_rxtx;
+
+  
+  proc_rxtx1->subframe_rx   = proc_rxtx0->subframe_rx;
+  proc_rxtx1->frame_rx      = proc_rxtx0->frame_rx;
+  proc_rxtx1->subframe_tx   = proc_rxtx0->subframe_tx;
+  proc_rxtx1->frame_tx      = proc_rxtx0->frame_tx;
+  proc_rxtx1->timestamp_tx  = proc_rxtx0->timestamp_tx;
+  
+  // the thread can now be woken up
+  if (pthread_cond_signal(&proc_rxtx1->cond_rxtx) != 0) {
+    LOG_E( PHY, "[eNB] ERROR pthread_cond_signal for eNB TXnp4 thread\n");
+    exit_fun( "ERROR pthread_cond_signal" );
+    return(-1);
+  }
+  
+  pthread_mutex_unlock( &proc_rxtx1->mutex_rxtx );
+
+  return(0);
+}
 
 int wakeup_rxtx(PHY_VARS_eNB *eNB,RU_t *ru) {
 
   eNB_proc_t *proc=&eNB->proc;
+  RU_proc_t *ru_proc=&ru->proc;
 
-  eNB_rxtx_proc_t *proc_rxtx=&proc->proc_rxtx[proc->frame_rx&1];
+  eNB_rxtx_proc_t *proc_rxtx0=&proc->proc_rxtx[0];//*proc_rxtx=&proc->proc_rxtx[proc->frame_rx&1];
+  //eNB_rxtx_proc_t *proc_rxtx1=&proc->proc_rxtx[1];
+  
 
   LTE_DL_FRAME_PARMS *fp = &eNB->frame_parms;
 
@@ -423,25 +595,28 @@ int wakeup_rxtx(PHY_VARS_eNB *eNB,RU_t *ru) {
   wait.tv_sec=0;
   wait.tv_nsec=5000000L;
 
-  /* accept some delay in processing - up to 5ms */
-  for (i = 0; i < 10 && proc_rxtx->instance_cnt_rxtx == 0; i++) {
-    LOG_W( PHY,"[eNB] Frame %d Subframe %d, eNB RXn-TXnp4 thread busy!! (cnt_rxtx %i)\n", proc_rxtx->frame_tx, proc_rxtx->subframe_tx, proc_rxtx->instance_cnt_rxtx);
-    usleep(500);
+  
+  if(wait_on_condition(&proc_rxtx0->mutex_rxtx,&proc_rxtx0->cond_rxtx,&proc_rxtx0->pipe_ready,"wakeup_rxtx")<0) {
+    LOG_E(PHY,"Frame %d, subframe %d: RXTX0 not ready\n",proc_rxtx0->frame_rx,proc_rxtx0->subframe_rx);
+    return(-1);
   }
-  if (proc_rxtx->instance_cnt_rxtx == 0) {
-    exit_fun( "TX thread busy" );
+  if (release_thread(&proc_rxtx0->mutex_rxtx,&proc_rxtx0->pipe_ready,"wakeup_rxtx")<0) return(-1);
+  
+  if (proc_rxtx0->instance_cnt_rxtx == 0) {
+    LOG_E(PHY,"Frame %d, subframe %d: RXTX0 thread busy, dropping\n",proc_rxtx0->frame_rx,proc_rxtx0->subframe_rx);
     return(-1);
   }
 
   // wake up TX for subframe n+sf_ahead
   // lock the TX mutex and make sure the thread is ready
-  if (pthread_mutex_timedlock(&proc_rxtx->mutex_rxtx,&wait) != 0) {
-    LOG_E( PHY, "[eNB] ERROR pthread_mutex_lock for eNB RXTX thread %d (IC %d)\n", proc_rxtx->subframe_rx&1,proc_rxtx->instance_cnt_rxtx );
+  if (pthread_mutex_timedlock(&proc_rxtx0->mutex_rxtx,&wait) != 0) {
+    LOG_E( PHY, "[eNB] ERROR pthread_mutex_lock for eNB RXTX thread %d (IC %d)\n", proc_rxtx0->subframe_rx&1,proc_rxtx0->instance_cnt_rxtx );
     exit_fun( "error locking mutex_rxtx" );
     return(-1);
   }
   
-  ++proc_rxtx->instance_cnt_rxtx;
+
+  ++proc_rxtx0->instance_cnt_rxtx;
   
   // We have just received and processed the common part of a subframe, say n. 
   // TS_rx is the last received timestamp (start of 1st slot), TS_tx is the desired 
@@ -449,20 +624,20 @@ int wakeup_rxtx(PHY_VARS_eNB *eNB,RU_t *ru) {
   // The last (TS_rx mod samples_per_frame) was n*samples_per_tti, 
   // we want to generate subframe (n+sf_ahead), so TS_tx = TX_rx+sf_ahead*samples_per_tti,
   // and proc->subframe_tx = proc->subframe_rx+sf_ahead
-  proc_rxtx->timestamp_tx = proc->timestamp_rx + (sf_ahead*fp->samples_per_tti);
-  proc_rxtx->frame_rx     = proc->frame_rx;
-  proc_rxtx->subframe_rx  = proc->subframe_rx;
-  proc_rxtx->frame_tx     = (proc_rxtx->subframe_rx > (9-sf_ahead)) ? (proc_rxtx->frame_rx+1)&1023 : proc_rxtx->frame_rx;
-  proc_rxtx->subframe_tx  = (proc_rxtx->subframe_rx + sf_ahead)%10;
+  proc_rxtx0->timestamp_tx = ru_proc->timestamp_rx + (sf_ahead*fp->samples_per_tti);
+  proc_rxtx0->frame_rx     = ru_proc->frame_rx;
+  proc_rxtx0->subframe_rx  = ru_proc->subframe_rx;
+  proc_rxtx0->frame_tx     = (proc_rxtx0->subframe_rx > (9-sf_ahead)) ? (proc_rxtx0->frame_rx+1)&1023 : proc_rxtx0->frame_rx;
+  proc_rxtx0->subframe_tx  = (proc_rxtx0->subframe_rx + sf_ahead)%10;
 
   // the thread can now be woken up
-  if (pthread_cond_signal(&proc_rxtx->cond_rxtx) != 0) {
+  if (pthread_cond_signal(&proc_rxtx0->cond_rxtx) != 0) {
     LOG_E( PHY, "[eNB] ERROR pthread_cond_signal for eNB RXn-TXnp4 thread\n");
     exit_fun( "ERROR pthread_cond_signal" );
     return(-1);
   }
   
-  pthread_mutex_unlock( &proc_rxtx->mutex_rxtx );
+  pthread_mutex_unlock( &proc_rxtx0->mutex_rxtx );
 
   return(0);
 }
@@ -602,8 +777,9 @@ static void* eNB_thread_prach( void* param ) {
   // set default return value
   eNB_thread_prach_status = 0;
 
-  thread_top_init("eNB_thread_prach",1,500000L,1000000L,20000000L);
+  thread_top_init("eNB_thread_prach",1,500000,1000000,20000000);
 
+  //wait_sync("eNB_thread_prach");
 
   while (!oai_exit) {
     
@@ -644,7 +820,7 @@ static void* eNB_thread_prach_br( void* param ) {
   // set default return value
   eNB_thread_prach_status = 0;
 
-  thread_top_init("eNB_thread_prach_br",1,500000L,1000000L,20000000L);
+  thread_top_init("eNB_thread_prach_br",1,500000,1000000,20000000);
 
   while (!oai_exit) {
     
@@ -668,8 +844,40 @@ static void* eNB_thread_prach_br( void* param ) {
 #endif
 
 
-extern void init_td_thread(PHY_VARS_eNB *, pthread_attr_t *);
-extern void init_te_thread(PHY_VARS_eNB *, pthread_attr_t *);
+
+extern void init_td_thread(PHY_VARS_eNB *);
+extern void init_te_thread(PHY_VARS_eNB *);
+extern void kill_td_thread(PHY_VARS_eNB *);
+extern void kill_te_thread(PHY_VARS_eNB *);
+//////////////////////////////////////need to modified////////////////*****
+
+static void* process_stats_thread(void* param) {
+
+  PHY_VARS_eNB     *eNB      = (PHY_VARS_eNB*)param;
+
+  wait_sync("process_stats_thread");
+
+  while (!oai_exit) {
+     sleep(1);
+     if (opp_enabled == 1) {
+       if (eNB->td) print_meas(&eNB->ulsch_decoding_stats,"ulsch_decoding",NULL,NULL);
+       if (eNB->te)
+       {
+         print_meas(&eNB->dlsch_turbo_encoding_preperation_stats,"dlsch_coding_crc",NULL,NULL);
+         print_meas(&eNB->dlsch_turbo_encoding_segmentation_stats,"dlsch_segmentation",NULL,NULL);
+         print_meas(&eNB->dlsch_encoding_stats,"dlsch_encoding",NULL,NULL);
+         print_meas(&eNB->dlsch_turbo_encoding_signal_stats,"coding_signal",NULL,NULL);
+         print_meas(&eNB->dlsch_turbo_encoding_main_stats,"coding_main",NULL,NULL);
+         print_meas(&eNB->dlsch_turbo_encoding_waiting_stats,"coding_wait",NULL,NULL);
+         print_meas(&eNB->dlsch_turbo_encoding_wakeup_stats0,"coding_worker_0",NULL,NULL);
+         print_meas(&eNB->dlsch_turbo_encoding_wakeup_stats1,"coding_worker_1",NULL,NULL);
+	   }
+       print_meas(&eNB->dlsch_modulation_stats,"dlsch_modulation",NULL,NULL);
+     }
+  }
+  return(NULL);
+}
+
 
 void init_eNB_proc(int inst) {
   
@@ -679,7 +887,6 @@ void init_eNB_proc(int inst) {
   eNB_proc_t *proc;
   eNB_rxtx_proc_t *proc_rxtx;
   pthread_attr_t *attr0=NULL,*attr1=NULL,*attr_prach=NULL;
-    //*attr_td=NULL,*attr_te=NULL;
 #ifdef Rel14
   pthread_attr_t *attr_prach_br=NULL;
 #endif
@@ -696,8 +903,11 @@ void init_eNB_proc(int inst) {
     proc_rxtx                      = proc->proc_rxtx;
     proc_rxtx[0].instance_cnt_rxtx = -1;
     proc_rxtx[1].instance_cnt_rxtx = -1;
+    proc_rxtx[0].pipe_ready        = 0;
+    proc_rxtx[1].pipe_ready        = 0;
     proc->instance_cnt_prach       = -1;
     proc->instance_cnt_asynch_rxtx = -1;
+    proc->instance_cnt_synch       = -1;
     proc->CC_id                    = CC_id;    
 
     proc->first_rx=1;
@@ -721,8 +931,6 @@ void init_eNB_proc(int inst) {
 
     pthread_attr_init( &proc->attr_prach);
     pthread_attr_init( &proc->attr_asynch_rxtx);
-    //    pthread_attr_init( &proc->attr_td);
-    //    pthread_attr_init( &proc->attr_te);
     pthread_attr_init( &proc_rxtx[0].attr_rxtx);
     pthread_attr_init( &proc_rxtx[1].attr_rxtx);
 #ifdef Rel14
@@ -744,6 +952,15 @@ void init_eNB_proc(int inst) {
     //    attr_td     = &proc->attr_td;
     //    attr_te     = &proc->attr_te; 
 #endif
+    //////////////////////////////////////need to modified////////////////*****
+    if(get_nprocs() > 2 && codingw)
+    {
+      init_te_thread(eNB);
+      init_td_thread(eNB);
+    }
+    //////////////////////////////////////need to modified////////////////*****
+	pthread_create( &proc_rxtx[0].pthread_rxtx, attr0, eNB_thread_rxtx, proc );
+	pthread_create( &proc_rxtx[1].pthread_rxtx, attr1, tx_thread, proc);
 
     LOG_I(PHY,"eNB->single_thread_flag:%d\n", eNB->single_thread_flag);
 
@@ -764,6 +981,9 @@ void init_eNB_proc(int inst) {
     }
 
     AssertFatal(proc->instance_cnt_prach == -1,"instance_cnt_prach = %d\n",proc->instance_cnt_prach);
+	
+
+    if (opp_enabled == 1) pthread_create(&proc->process_stats_thread,NULL,process_stats_thread,(void*)eNB);
 
     
   }
@@ -789,6 +1009,8 @@ void init_eNB_proc(int inst) {
   pthread_mutex_init(&sync_phy_proc.mutex_phy_proc_tx, NULL);
   pthread_cond_init(&sync_phy_proc.cond_phy_proc_tx, NULL);
   sync_phy_proc.phy_proc_CC_id = 0;
+  
+  
 }
 
 
@@ -802,21 +1024,22 @@ void kill_eNB_proc(int inst) {
   PHY_VARS_eNB *eNB;
   eNB_proc_t *proc;
   eNB_rxtx_proc_t *proc_rxtx;
+  int i;
   for (int CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
     eNB=RC.eNB[inst][CC_id];
     
     proc = &eNB->proc;
     proc_rxtx = &proc->proc_rxtx[0];
 
+    kill_td_thread(eNB);
+    kill_te_thread(eNB);
     LOG_I(PHY, "Killing TX CC_id %d inst %d\n", CC_id, inst );
-
-    if (eNB->single_thread_flag==0) {
-      pthread_mutex_lock(&proc_rxtx[0].mutex_rxtx);
-      proc_rxtx[0].instance_cnt_rxtx = 0;
-      pthread_mutex_unlock(&proc_rxtx[0].mutex_rxtx);
-      pthread_mutex_lock(&proc_rxtx[1].mutex_rxtx);
-      proc_rxtx[1].instance_cnt_rxtx = 0;
-      pthread_mutex_unlock(&proc_rxtx[1].mutex_rxtx);
+    for (i=0; i<2; i++) {
+      pthread_mutex_lock(&proc_rxtx[i].mutex_rxtx);
+      proc_rxtx[i].instance_cnt_rxtx = 0;
+      proc_rxtx[i].pipe_ready = 0;
+      pthread_cond_signal(&proc_rxtx[i].cond_rxtx);
+      pthread_mutex_unlock(&proc_rxtx[i].mutex_rxtx);
     }
     proc->instance_cnt_prach = 0;
     pthread_cond_signal( &proc->cond_prach );
@@ -839,15 +1062,12 @@ void kill_eNB_proc(int inst) {
 #endif         
     LOG_I(PHY, "Destroying UL_INFO mutex\n");
     pthread_mutex_destroy(&eNB->UL_INFO_mutex);
-    int i;
-    if (eNB->single_thread_flag==0) {
-      for (i=0;i<2;i++) {
-	LOG_I(PHY, "Joining rxtx[%d] mutex/cond\n",i);
-	pthread_join( proc_rxtx[i].pthread_rxtx, (void**)&status );
-	LOG_I(PHY, "Destroying rxtx[%d] mutex/cond\n",i);
-	pthread_mutex_destroy( &proc_rxtx[i].mutex_rxtx );
-	pthread_cond_destroy( &proc_rxtx[i].cond_rxtx );
-      }
+    for (i=0;i<2;i++) {
+      LOG_I(PHY, "Joining rxtx[%d] mutex/cond\n",i);
+      pthread_join( proc_rxtx[i].pthread_rxtx, (void**)&status );
+      LOG_I(PHY, "Destroying rxtx[%d] mutex/cond\n",i);
+      pthread_mutex_destroy( &proc_rxtx[i].mutex_rxtx );
+      pthread_cond_destroy( &proc_rxtx[i].cond_rxtx );
     }
   }
 }
@@ -1091,8 +1311,8 @@ void init_eNB(int single_thread_flag,int wait_for_sync) {
 #endif
 
 
-      eNB->td                   = ulsch_decoding_data;//(single_thread_flag==1) ? ulsch_decoding_data_2thread : ulsch_decoding_data;
-      eNB->te                   = dlsch_encoding;//(single_thread_flag==1) ? dlsch_encoding_2threads : dlsch_encoding;
+      eNB->td                   = ulsch_decoding_data_all;//(get_nprocs()<=4) ? ulsch_decoding_data : ulsch_decoding_data_2thread;
+      eNB->te                   = dlsch_encoding_all;//(get_nprocs()<=4) ? dlsch_encoding : dlsch_encoding_2threads;
 
       
       LOG_I(PHY,"Registering with MAC interface module\n");
diff --git a/targets/RT/USER/lte-ru.c b/targets/RT/USER/lte-ru.c
index 8b025336b02ac39ab4eae2b8637cf08dcdbbaf94..4db66da4dc1d1af4e041fde8fa538248c1d9fbfd 100644
--- a/targets/RT/USER/lte-ru.c
+++ b/targets/RT/USER/lte-ru.c
@@ -111,7 +111,11 @@ static int DEFENBS[] = {0};
 
 #include "T.h"
 
+
 extern volatile int                    oai_exit;
+extern int emulate_rf;
+extern int numerology;
+extern int fepw;
 
 
 extern void  phy_init_RU(RU_t*);
@@ -673,6 +677,34 @@ void fh_if4p5_north_out(RU_t *ru) {
 
 }
 
+static void* emulatedRF_thread(void* param) {
+  RU_proc_t *proc = (RU_proc_t *) param;
+  int microsec = 500; // length of time to sleep, in miliseconds
+  struct timespec req = {0};
+  req.tv_sec = 0;
+  req.tv_nsec = (numerology>0)? ((microsec * 1000L)/numerology):(microsec * 1000L)*2;
+  cpu_set_t cpuset;
+  CPU_SET(1,&cpuset);
+  pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset);
+  
+  int policy;
+  struct sched_param sparam;
+  memset(&sparam, 0, sizeof(sparam));
+  sparam.sched_priority = sched_get_priority_max(SCHED_FIFO);
+  policy = SCHED_FIFO ; 
+  pthread_setschedparam(pthread_self(), policy, &sparam);
+  
+  wait_sync("emulatedRF_thread");
+  while(!oai_exit){
+    nanosleep(&req, (struct timespec *)NULL);
+    pthread_mutex_lock(&proc->mutex_emulateRF);
+    ++proc->instance_cnt_emulateRF;
+    pthread_mutex_unlock(&proc->mutex_emulateRF);
+    pthread_cond_signal(&proc->cond_emulateRF);
+  }
+  return 0;
+}
+
 void rx_rf(RU_t *ru,int *frame,int *subframe) {
 
   RU_proc_t *proc = &ru->proc;
@@ -680,7 +712,7 @@ void rx_rf(RU_t *ru,int *frame,int *subframe) {
   void *rxp[ru->nb_rx];
   unsigned int rxs;
   int i;
-  openair0_timestamp ts,old_ts;
+  openair0_timestamp ts=0,old_ts=0;
     
   for (i=0; i<ru->nb_rx; i++)
     rxp[i] = (void*)&ru->common.rxdata[i][*subframe*fp->samples_per_tti];
@@ -688,12 +720,18 @@ void rx_rf(RU_t *ru,int *frame,int *subframe) {
   VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ, 1 );
 
   old_ts = proc->timestamp_rx;
-
-  rxs = ru->rfdevice.trx_read_func(&ru->rfdevice,
+  if(emulate_rf){
+    wait_on_condition(&proc->mutex_emulateRF,&proc->cond_emulateRF,&proc->instance_cnt_emulateRF,"emulatedRF_thread");
+    release_thread(&proc->mutex_emulateRF,&proc->instance_cnt_emulateRF,"emulatedRF_thread");
+    rxs = fp->samples_per_tti;
+  }
+  else{
+    rxs = ru->rfdevice.trx_read_func(&ru->rfdevice,
 				   &ts,
 				   rxp,
 				   fp->samples_per_tti,
 				   ru->nb_rx);
+  }
   
   VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ, 0 );
  
@@ -709,7 +747,7 @@ void rx_rf(RU_t *ru,int *frame,int *subframe) {
   }
   else {
     if (proc->timestamp_rx - old_ts != fp->samples_per_tti) {
-      LOG_I(PHY,"rx_rf: rfdevice timing drift of %"PRId64" samples (ts_off %"PRId64")\n",proc->timestamp_rx - old_ts - fp->samples_per_tti,ru->ts_offset);
+      //LOG_I(PHY,"rx_rf: rfdevice timing drift of %"PRId64" samples (ts_off %"PRId64")\n",proc->timestamp_rx - old_ts - fp->samples_per_tti,ru->ts_offset);
       ru->ts_offset += (proc->timestamp_rx - old_ts - fp->samples_per_tti);
       proc->timestamp_rx = ts-ru->ts_offset;
     }
@@ -719,9 +757,9 @@ void rx_rf(RU_t *ru,int *frame,int *subframe) {
   proc->subframe_rx  = (proc->timestamp_rx / fp->samples_per_tti)%10;
   // synchronize first reception to frame 0 subframe 0
 
-  proc->timestamp_tx = proc->timestamp_rx+(sf_ahead*fp->samples_per_tti);
-  proc->subframe_tx  = (proc->subframe_rx+sf_ahead)%10;
-  proc->frame_tx     = (proc->subframe_rx>(9-sf_ahead)) ? (proc->frame_rx+1)&1023 : proc->frame_rx;
+  //proc->timestamp_tx = proc->timestamp_rx+(sf_ahead*fp->samples_per_tti);
+  //proc->subframe_tx  = (proc->subframe_rx+sf_ahead)%10;
+  //proc->frame_tx     = (proc->subframe_rx>(9-sf_ahead)) ? (proc->frame_rx+1)&1023 : proc->frame_rx;
   
   LOG_D(PHY,"RU %d/%d TS %llu (off %d), frame %d, subframe %d\n",
 	ru->idx, 
@@ -733,8 +771,6 @@ void rx_rf(RU_t *ru,int *frame,int *subframe) {
   if (ru == RC.ru[0]) {
     VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX0_RU, proc->frame_rx );
     VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_RX0_RU, proc->subframe_rx );
-    VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX0_RU, proc->frame_tx );
-    VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_TX0_RU, proc->subframe_tx );
   }
   
   if (proc->first_rx == 0) {
@@ -809,6 +845,8 @@ void tx_rf(RU_t *ru) {
     for (i=0; i<ru->nb_tx; i++)
       txp[i] = (void*)&ru->common.txdata[i][(proc->subframe_tx*fp->samples_per_tti)-sf_extension];
 
+    VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX0_RU, proc->frame_tx );
+    VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_TX0_RU, proc->subframe_tx );
     
     VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TST, (proc->timestamp_tx-ru->openair0_cfg.tx_sample_advance)&0xffffffff );
     VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE, 1 );
@@ -849,7 +887,7 @@ static void* ru_thread_asynch_rxtx( void* param ) {
 
   int subframe=0, frame=0; 
 
-  thread_top_init("ru_thread_asynch_rxtx",1,870000L,1000000L,1000000L);
+  thread_top_init("ru_thread_asynch_rxtx",1,870000,1000000,1000000);
 
   // wait for top-level synchronization and do one acquisition to get timestamp for setting frame/subframe
 
@@ -875,7 +913,7 @@ static void* ru_thread_asynch_rxtx( void* param ) {
       subframe++;
     }      
     LOG_D(PHY,"ru_thread_asynch_rxtx: Waiting on incoming fronthaul\n");
-    // asynchronous receive from south (Mobipass)
+	// asynchronous receive from south (Mobipass)
     if (ru->fh_south_asynch_in) ru->fh_south_asynch_in(ru,&frame,&subframe);
     // asynchronous receive from north (RRU IF4/IF5)
     else if (ru->fh_north_asynch_in) {
@@ -901,6 +939,7 @@ void wakeup_slaves(RU_proc_t *proc) {
   wait.tv_nsec=5000000L;
   
   for (i=0;i<proc->num_slaves;i++) {
+    //printf("////////////////////calling for slave thrads\n");////////////////////////********
     RU_proc_t *slave_proc = proc->slave_proc[i];
     // wake up slave FH thread
     // lock the FH mutex and make sure the thread is ready
@@ -948,7 +987,8 @@ static void* ru_thread_prach( void* param ) {
   // set default return value
   ru_thread_prach_status = 0;
 
-  thread_top_init("ru_thread_prach",1,500000L,1000000L,20000000L);
+  thread_top_init("ru_thread_prach",1,500000,1000000,20000000);
+  //wait_sync("ru_thread_prach");
 
   while (RC.ru_mask>0) {
     usleep(1e6);
@@ -1003,7 +1043,8 @@ static void* ru_thread_prach_br( void* param ) {
   // set default return value
   ru_thread_prach_status = 0;
 
-  thread_top_init("ru_thread_prach_br",1,500000L,1000000L,20000000L);
+  thread_top_init("ru_thread_prach_br",1,500000,1000000,20000000);
+  //wait_sync("ru_thread_prach_br");
 
   while (!oai_exit) {
     
@@ -1133,13 +1174,14 @@ void wakeup_eNBs(RU_t *ru) {
 
   LOG_D(PHY,"wakeup_eNBs (num %d) for RU %d ru->eNB_top:%p\n",ru->num_eNB,ru->idx, ru->eNB_top);
 
-  if (ru->num_eNB==1 && ru->eNB_top!=0) {
-    // call eNB function directly
 
+  if (ru->num_eNB==1 && ru->eNB_top!=0 && get_nprocs() <= 4) {
+    // call eNB function directly
+  
     char string[20];
     sprintf(string,"Incoming RU %d",ru->idx);
     LOG_D(PHY,"RU %d Call eNB_top\n",ru->idx);
-    ru->eNB_top(eNB_list[0],ru->proc.frame_rx,ru->proc.subframe_rx,string);
+    ru->eNB_top(eNB_list[0],ru->proc.frame_rx,ru->proc.subframe_rx,string,ru);
   }
   else {
 
@@ -1148,7 +1190,7 @@ void wakeup_eNBs(RU_t *ru) {
     for (i=0;i<ru->num_eNB;i++)
     {
       LOG_D(PHY,"ru->wakeup_rxtx:%p\n", ru->wakeup_rxtx);
-
+      eNB_list[i]->proc.ru_proc = &ru->proc;
       if (ru->wakeup_rxtx!=0 && ru->wakeup_rxtx(eNB_list[i],ru) < 0)
       {
 	LOG_E(PHY,"could not wakeup eNB rxtx process for subframe %d\n", ru->proc.subframe_rx);
@@ -1179,7 +1221,7 @@ static inline int wakeup_prach_ru(RU_t *ru) {
       ru->eNB_list[0]->proc.frame_prach = ru->proc.frame_rx;
       ru->eNB_list[0]->proc.subframe_prach = ru->proc.subframe_rx;
     }
-    LOG_I(PHY,"RU %d: waking up PRACH thread\n",ru->idx);
+    LOG_D(PHY,"RU %d: waking up PRACH thread\n",ru->idx);
     // the thread can now be woken up
     AssertFatal(pthread_cond_signal(&ru->proc.cond_prach) == 0, "ERROR pthread_cond_signal for RU prach thread\n");
   }
@@ -1225,20 +1267,39 @@ void fill_rf_config(RU_t *ru, char *rf_config_file) {
 
   LTE_DL_FRAME_PARMS *fp   = &ru->frame_parms;
   openair0_config_t *cfg   = &ru->openair0_cfg;
+  //printf("////////////////numerology in config = %d\n",numerology);
 
   if(fp->N_RB_DL == 100) {
-    if (fp->threequarter_fs) {
-      cfg->sample_rate=23.04e6;
-      cfg->samples_per_frame = 230400; 
-      cfg->tx_bw = 10e6;
-      cfg->rx_bw = 10e6;
-    }
-    else {
-      cfg->sample_rate=30.72e6;
+    if(numerology == 0){
+      if (fp->threequarter_fs) {
+        cfg->sample_rate=23.04e6;
+        cfg->samples_per_frame = 230400; 
+        cfg->tx_bw = 10e6;
+        cfg->rx_bw = 10e6;
+      }
+      else {
+        cfg->sample_rate=30.72e6;
+        cfg->samples_per_frame = 307200; 
+        cfg->tx_bw = 10e6;
+        cfg->rx_bw = 10e6;
+      }
+	}else if(numerology == 1){
+	  cfg->sample_rate=61.44e6;
+      cfg->samples_per_frame = 307200; 
+      cfg->tx_bw = 20e6;
+      cfg->rx_bw = 20e6;
+	}else if(numerology == 2){
+	  cfg->sample_rate=122.88e6;
+      cfg->samples_per_frame = 307200; 
+      cfg->tx_bw = 40e6;
+      cfg->rx_bw = 40e6;
+	}else{
+	  printf("Wrong input for numerology %d\n setting to 20MHz normal CP configuration",numerology);
+	  cfg->sample_rate=30.72e6;
       cfg->samples_per_frame = 307200; 
       cfg->tx_bw = 10e6;
       cfg->rx_bw = 10e6;
-    }
+	}
   } else if(fp->N_RB_DL == 50) {
     cfg->sample_rate=15.36e6;
     cfg->samples_per_frame = 153600;
@@ -1357,7 +1418,7 @@ static void* ru_stats_thread(void* param) {
 
   while (!oai_exit) {
      sleep(1);
-     if (opp_enabled == 1) {
+     if (opp_enabled == 1 && fepw) {
        if (ru->feprx) print_meas(&ru->ofdm_demod_stats,"feprx",NULL,NULL);
        if (ru->feptx_ofdm) print_meas(&ru->ofdm_mod_stats,"feptx_ofdm",NULL,NULL);
        if (ru->fh_north_asynch_in) print_meas(&ru->rx_fhaul,"rx_fhaul",NULL,NULL);
@@ -1371,6 +1432,59 @@ static void* ru_stats_thread(void* param) {
   return(NULL);
 }
 
+static void* ru_thread_tx( void* param ) {
+  RU_t *ru         = (RU_t*)param;
+  RU_proc_t *proc  = &ru->proc;
+  cpu_set_t cpuset;
+  CPU_ZERO(&cpuset);
+
+
+  thread_top_init("ru_thread_tx",1,400000,500000,500000);
+
+  //CPU_SET(5, &cpuset);
+  //pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset);
+  //wait_sync("ru_thread_tx");
+
+  wait_on_condition(&proc->mutex_FH1,&proc->cond_FH1,&proc->instance_cnt_FH1,"ru_thread_tx");
+
+  printf( "ru_thread_tx ready\n");
+  while (!oai_exit) { 
+
+    VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_CPUID_RU_THREAD_TX,sched_getcpu());   
+    if (oai_exit) break;   
+
+
+	LOG_D(PHY,"ru_thread_tx: Waiting for TX processing\n");
+	// wait until eNBs are finished subframe RX n and TX n+4
+    wait_on_condition(&proc->mutex_eNBs,&proc->cond_eNBs,&proc->instance_cnt_eNBs,"ru_thread_tx");
+    if (oai_exit) break;
+  	       
+    // do TX front-end processing if needed (precoding and/or IDFTs)
+    if (ru->feptx_prec) ru->feptx_prec(ru);
+  	  
+    // do OFDM if needed
+    if ((ru->fh_north_asynch_in == NULL) && (ru->feptx_ofdm)) ru->feptx_ofdm(ru);
+    if(!emulate_rf){    
+      // do outgoing fronthaul (south) if needed
+      if ((ru->fh_north_asynch_in == NULL) && (ru->fh_south_out)) ru->fh_south_out(ru);
+  	      
+      if (ru->fh_north_out) ru->fh_north_out(ru);
+	}
+    release_thread(&proc->mutex_eNBs,&proc->instance_cnt_eNBs,"ru_thread_tx");
+    
+    pthread_mutex_lock( &proc->mutex_eNBs );
+    proc->ru_tx_ready++;
+    // the thread can now be woken up
+    if (pthread_cond_signal(&proc->cond_eNBs) != 0) {
+      LOG_E( PHY, "[eNB] ERROR pthread_cond_signal for eNB TXnp4 thread\n");
+      exit_fun( "ERROR pthread_cond_signal" );
+    }
+    pthread_mutex_unlock( &proc->mutex_eNBs );
+  }
+  release_thread(&proc->mutex_FH1,&proc->instance_cnt_FH1,"ru_thread_tx");
+  return 0;
+}
+
 static void* ru_thread( void* param ) {
 
   static int ru_thread_status;
@@ -1381,35 +1495,54 @@ static void* ru_thread( void* param ) {
   int                ret;
   int                subframe =9;
   int                frame    =1023; 
+  cpu_set_t cpuset;
+  CPU_ZERO(&cpuset);
+
 
   // set default return value
   ru_thread_status = 0;
 
 
   // set default return value
-  thread_top_init("ru_thread",0,870000,1000000,1000000);
+  thread_top_init("ru_thread",1,400000,500000,500000);
 
-  LOG_I(PHY,"Starting RU %d (%s,%s),\n",ru->idx,eNB_functions[ru->function],eNB_timing[ru->if_timing]);
+  //CPU_SET(1, &cpuset);
+  //pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset);
+  pthread_setname_np( pthread_self(),"ru thread");
+  LOG_I(PHY,"thread ru created id=%ld\n", syscall(__NR_gettid));
 
+  LOG_I(PHY,"Starting RU %d (%s,%s),\n",ru->idx,eNB_functions[ru->function],eNB_timing[ru->if_timing]);
 
-  // Start IF device if any
-  if (ru->start_if) {
-    LOG_I(PHY,"Starting IF interface for RU %d\n",ru->idx);
-    AssertFatal(ru->start_if(ru,NULL) == 0, "Could not start the IF device\n");
-    if (ru->if_south == LOCAL_RF) ret = connect_rau(ru);
-    else ret = attach_rru(ru);
-    AssertFatal(ret==0,"Cannot connect to radio\n");
-  }
-  if (ru->if_south == LOCAL_RF) { // configure RF parameters only 
-        fill_rf_config(ru,ru->rf_config_file);
-        init_frame_parms(&ru->frame_parms,1);
-        phy_init_RU(ru);
- 
-        ret = openair0_device_load(&ru->rfdevice,&ru->openair0_cfg);
+  if(emulate_rf){
+    fill_rf_config(ru,ru->rf_config_file);
+    init_frame_parms(&ru->frame_parms,1);
+    phy_init_RU(ru);
+    if (setup_RU_buffers(ru)!=0) {
+          printf("Exiting, cannot initialize RU Buffers\n");
+          exit(-1);
+    }
   }
-  if (setup_RU_buffers(ru)!=0) {
-        printf("Exiting, cannot initialize RU Buffers\n");
-        exit(-1);
+  else{
+    // Start IF device if any
+    if (ru->start_if) {
+      LOG_I(PHY,"Starting IF interface for RU %d\n",ru->idx);
+      AssertFatal(ru->start_if(ru,NULL) == 0, "Could not start the IF device\n");
+      if (ru->if_south == LOCAL_RF) ret = connect_rau(ru);
+      else ret = attach_rru(ru);
+      AssertFatal(ret==0,"Cannot connect to radio\n");
+    }
+    if (ru->if_south == LOCAL_RF) { // configure RF parameters only 
+          fill_rf_config(ru,ru->rf_config_file);
+          init_frame_parms(&ru->frame_parms,1);
+          phy_init_RU(ru);
+    
+    
+          ret = openair0_device_load(&ru->rfdevice,&ru->openair0_cfg);
+    }
+    if (setup_RU_buffers(ru)!=0) {
+          printf("Exiting, cannot initialize RU Buffers\n");
+          exit(-1);
+    }
   }
 
   LOG_I(PHY, "Signaling main thread that RU %d is ready\n",ru->idx);
@@ -1418,38 +1551,46 @@ static void* ru_thread( void* param ) {
   pthread_cond_signal(&RC.ru_cond);
   pthread_mutex_unlock(&RC.ru_mutex);
   
-  wait_sync("ru_thread");
   
+  pthread_mutex_lock(&proc->mutex_FH1);
+  proc->instance_cnt_FH1 = 0;
+  pthread_mutex_unlock(&proc->mutex_FH1);
+  pthread_cond_signal(&proc->cond_FH1);
 
+  wait_sync("ru_thread");
 
-
-  // Start RF device if any
-  if (ru->start_rf) {
-    if (ru->start_rf(ru) != 0)
-      LOG_E(HW,"Could not start the RF device\n");
-    else LOG_I(PHY,"RU %d rf device ready\n",ru->idx);
+  if(!emulate_rf){
+    // Start RF device if any
+    if (ru->start_rf) {
+      if (ru->start_rf(ru) != 0)
+        LOG_E(HW,"Could not start the RF device\n");
+      else LOG_I(PHY,"RU %d rf device ready\n",ru->idx);
+    }
+    else LOG_I(PHY,"RU %d no rf device\n",ru->idx);
+    
+    // if an asnych_rxtx thread exists
+    // wakeup the thread because the devices are ready at this point
+    
+    if ((ru->fh_south_asynch_in)||(ru->fh_north_asynch_in)) {
+      pthread_mutex_lock(&proc->mutex_asynch_rxtx);
+      proc->instance_cnt_asynch_rxtx=0;
+      pthread_mutex_unlock(&proc->mutex_asynch_rxtx);
+      pthread_cond_signal(&proc->cond_asynch_rxtx);
+    }
+    else LOG_I(PHY,"RU %d no asynch_south interface\n",ru->idx);
+    
+    // if this is a slave RRU, try to synchronize on the DL frequency
+    if ((ru->is_slave) && (ru->if_south == LOCAL_RF)) do_ru_synch(ru);
   }
-  else LOG_I(PHY,"RU %d no rf device\n",ru->idx);
 
 
-  // if an asnych_rxtx thread exists
-  // wakeup the thread because the devices are ready at this point
- 
-  if ((ru->fh_south_asynch_in)||(ru->fh_north_asynch_in)) {
-    pthread_mutex_lock(&proc->mutex_asynch_rxtx);
-    proc->instance_cnt_asynch_rxtx=0;
-    pthread_mutex_unlock(&proc->mutex_asynch_rxtx);
-    pthread_cond_signal(&proc->cond_asynch_rxtx);
-  }
-  else LOG_I(PHY,"RU %d no asynch_south interface\n",ru->idx);
-
-  // if this is a slave RRU, try to synchronize on the DL frequency
-  if ((ru->is_slave) && (ru->if_south == LOCAL_RF)) do_ru_synch(ru);
 
 
   // This is a forever while loop, it loops over subframes which are scheduled by incoming samples from HW devices
   while (!oai_exit) {
 
+    VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_CPUID_RU_THREAD,sched_getcpu());
+
     // these are local subframe/frame counters to check that we are in synch with the fronthaul timing.
     // They are set on the first rx/tx in the underly FH routines.
     if (subframe==9) { 
@@ -1499,20 +1640,21 @@ static void* ru_thread( void* param ) {
 
     // wakeup all eNB processes waiting for this RU
     if (ru->num_eNB>0) wakeup_eNBs(ru);
+    
+    if(get_nprocs() <= 4){
+      // do TX front-end processing if needed (precoding and/or IDFTs)
+      if (ru->feptx_prec) ru->feptx_prec(ru);
+      
+      // do OFDM if needed
+      if ((ru->fh_north_asynch_in == NULL) && (ru->feptx_ofdm)) ru->feptx_ofdm(ru);
+      if(!emulate_rf){
+        // do outgoing fronthaul (south) if needed
+        if ((ru->fh_north_asynch_in == NULL) && (ru->fh_south_out)) ru->fh_south_out(ru);
+        
+        if (ru->fh_north_out) ru->fh_north_out(ru);
+      }
+    }
 
-    // wait until eNBs are finished subframe RX n and TX n+sf_ahead
-    wait_on_condition(&proc->mutex_eNBs,&proc->cond_eNBs,&proc->instance_cnt_eNBs,"ru_thread");
-
-
-    // do TX front-end processing if needed (precoding and/or IDFTs)
-    if (ru->feptx_prec) ru->feptx_prec(ru);
-   
-    // do OFDM if needed
-    if ((ru->fh_north_asynch_in == NULL) && (ru->feptx_ofdm)) ru->feptx_ofdm(ru);
-    // do outgoing fronthaul (south) if needed
-    if ((ru->fh_north_asynch_in == NULL) && (ru->fh_south_out)) ru->fh_south_out(ru);
- 
-    if (ru->fh_north_out) ru->fh_north_out(ru);
   }
   
 
@@ -1635,7 +1777,7 @@ void init_RU_proc(RU_t *ru) {
    
   int i=0;
   RU_proc_t *proc;
-  pthread_attr_t *attr_FH=NULL,*attr_prach=NULL,*attr_asynch=NULL,*attr_synch=NULL;
+  pthread_attr_t *attr_FH=NULL,*attr_FH1=NULL,*attr_prach=NULL,*attr_asynch=NULL,*attr_synch=NULL,*attr_emulateRF=NULL;
   //pthread_attr_t *attr_fep=NULL;
 #ifdef Rel14
   pthread_attr_t *attr_prach_br=NULL;
@@ -1650,14 +1792,19 @@ void init_RU_proc(RU_t *ru) {
 
   proc->ru = ru;
   proc->instance_cnt_prach       = -1;
-  proc->instance_cnt_synch       = -1;     ;
+  proc->instance_cnt_synch       = -1;
   proc->instance_cnt_FH          = -1;
+  proc->instance_cnt_FH1         = -1;
+  proc->instance_cnt_emulateRF   = -1;
   proc->instance_cnt_asynch_rxtx = -1;
+  proc->instance_cnt_eNBs        = -1;
   proc->first_rx                 = 1;
   proc->first_tx                 = 1;
   proc->frame_offset             = 0;
   proc->num_slaves               = 0;
   proc->frame_tx_unwrap          = 0;
+  proc->ru_rx_ready              = 0;
+  proc->ru_tx_ready              = 0;
 
   for (i=0;i<10;i++) proc->symbol_mask[i]=0;
   
@@ -1665,15 +1812,21 @@ void init_RU_proc(RU_t *ru) {
   pthread_mutex_init( &proc->mutex_asynch_rxtx, NULL);
   pthread_mutex_init( &proc->mutex_synch,NULL);
   pthread_mutex_init( &proc->mutex_FH,NULL);
+  pthread_mutex_init( &proc->mutex_FH1,NULL);
+  pthread_mutex_init( &proc->mutex_emulateRF,NULL);
   pthread_mutex_init( &proc->mutex_eNBs, NULL);
   
   pthread_cond_init( &proc->cond_prach, NULL);
   pthread_cond_init( &proc->cond_FH, NULL);
+  pthread_cond_init( &proc->cond_FH1, NULL);
+  pthread_cond_init( &proc->cond_emulateRF, NULL);
   pthread_cond_init( &proc->cond_asynch_rxtx, NULL);
   pthread_cond_init( &proc->cond_synch,NULL);
   pthread_cond_init( &proc->cond_eNBs, NULL);
   
   pthread_attr_init( &proc->attr_FH);
+  pthread_attr_init( &proc->attr_FH1);
+  pthread_attr_init( &proc->attr_emulateRF);
   pthread_attr_init( &proc->attr_prach);
   pthread_attr_init( &proc->attr_synch);
   pthread_attr_init( &proc->attr_asynch_rxtx);
@@ -1688,15 +1841,22 @@ void init_RU_proc(RU_t *ru) {
   
 #ifndef DEADLINE_SCHEDULER
   attr_FH        = &proc->attr_FH;
+  attr_FH1       = &proc->attr_FH1;
   attr_prach     = &proc->attr_prach;
   attr_synch     = &proc->attr_synch;
   attr_asynch    = &proc->attr_asynch_rxtx;
+  attr_emulateRF = &proc->attr_emulateRF;
 #ifdef Rel14
   attr_prach_br  = &proc->attr_prach_br;
 #endif
 #endif
   
   pthread_create( &proc->pthread_FH, attr_FH, ru_thread, (void*)ru );
+  if(emulate_rf)
+    pthread_create( &proc->pthread_emulateRF, attr_emulateRF, emulatedRF_thread, (void*)proc );
+
+  if (get_nprocs() > 4)
+    pthread_create( &proc->pthread_FH1, attr_FH1, ru_thread_tx, (void*)ru );
 
   if (ru->function == NGFI_RRU_IF4p5) {
     pthread_create( &proc->pthread_prach, attr_prach, ru_thread_prach, (void*)ru );
@@ -1708,7 +1868,10 @@ void init_RU_proc(RU_t *ru) {
     
     if ((ru->if_timing == synch_to_other) ||
 	(ru->function == NGFI_RRU_IF5) ||
-	(ru->function == NGFI_RRU_IF4p5)) pthread_create( &proc->pthread_asynch_rxtx, attr_asynch, ru_thread_asynch_rxtx, (void*)ru );
+	(ru->function == NGFI_RRU_IF4p5)) 
+	{
+		pthread_create( &proc->pthread_asynch_rxtx, attr_asynch, ru_thread_asynch_rxtx, (void*)ru );
+	}
     
     snprintf( name, sizeof(name), "ru_thread_FH %d", ru->idx );
     pthread_setname_np( proc->pthread_FH, name );
@@ -1719,7 +1882,7 @@ void init_RU_proc(RU_t *ru) {
     pthread_create( &proc->pthread_prach, attr_prach, ru_thread_prach, (void*)ru );
   }
 
-  if (get_nprocs()>=2) { 
+  if (get_nprocs()> 2 && fepw) { 
     if (ru->feprx) init_fep_thread(ru,NULL); 
     if (ru->feptx_ofdm) init_feptx_thread(ru,NULL);
   } 
@@ -1734,38 +1897,46 @@ void kill_RU_proc(int inst)
 
   pthread_mutex_lock(&proc->mutex_FH);
   proc->instance_cnt_FH = 0;
-  pthread_mutex_unlock(&proc->mutex_FH);
   pthread_cond_signal(&proc->cond_FH);
+  pthread_mutex_unlock(&proc->mutex_FH);
+
+  pthread_mutex_lock(&proc->mutex_FH1);
+  proc->instance_cnt_FH1 = 0;
+  pthread_cond_signal(&proc->cond_FH1);
+  pthread_mutex_unlock(&proc->mutex_FH1);
 
   pthread_mutex_lock(&proc->mutex_prach);
   proc->instance_cnt_prach = 0;
-  pthread_mutex_unlock(&proc->mutex_prach);
   pthread_cond_signal(&proc->cond_prach);
+  pthread_mutex_unlock(&proc->mutex_prach);
 
 #ifdef Rel14
   pthread_mutex_lock(&proc->mutex_prach_br);
   proc->instance_cnt_prach_br = 0;
-  pthread_mutex_unlock(&proc->mutex_prach_br);
   pthread_cond_signal(&proc->cond_prach_br);
+  pthread_mutex_unlock(&proc->mutex_prach_br);
 #endif
 
   pthread_mutex_lock(&proc->mutex_synch);
   proc->instance_cnt_synch = 0;
-  pthread_mutex_unlock(&proc->mutex_synch);
   pthread_cond_signal(&proc->cond_synch);
+  pthread_mutex_unlock(&proc->mutex_synch);
 
   pthread_mutex_lock(&proc->mutex_eNBs);
+  proc->ru_tx_ready = 0;
   proc->instance_cnt_eNBs = 0;
-  pthread_mutex_unlock(&proc->mutex_eNBs);
   pthread_cond_signal(&proc->cond_eNBs);
+  pthread_mutex_unlock(&proc->mutex_eNBs);
 
   pthread_mutex_lock(&proc->mutex_asynch_rxtx);
   proc->instance_cnt_asynch_rxtx = 0;
-  pthread_mutex_unlock(&proc->mutex_asynch_rxtx);
   pthread_cond_signal(&proc->cond_asynch_rxtx);
+  pthread_mutex_unlock(&proc->mutex_asynch_rxtx);
 
   LOG_D(PHY, "Joining pthread_FH\n");
   pthread_join(proc->pthread_FH, NULL);
+  LOG_D(PHY, "Joining pthread_FHTX\n");
+  pthread_join(proc->pthread_FH1, NULL);
   if (ru->function == NGFI_RRU_IF4p5) {
     LOG_D(PHY, "Joining pthread_prach\n");
     pthread_join(proc->pthread_prach, NULL);
@@ -1785,7 +1956,7 @@ void kill_RU_proc(int inst)
       pthread_join(proc->pthread_asynch_rxtx, NULL);
     }
   }
-  if (get_nprocs() >= 2) {
+  if (get_nprocs() > 2 && fepw) {
     if (ru->feprx) {
       pthread_mutex_lock(&proc->mutex_fep);
       proc->instance_cnt_fep = 0;
@@ -1816,15 +1987,18 @@ void kill_RU_proc(int inst)
   pthread_mutex_destroy(&proc->mutex_asynch_rxtx);
   pthread_mutex_destroy(&proc->mutex_synch);
   pthread_mutex_destroy(&proc->mutex_FH);
+  pthread_mutex_destroy(&proc->mutex_FH1);
   pthread_mutex_destroy(&proc->mutex_eNBs);
 
   pthread_cond_destroy(&proc->cond_prach);
   pthread_cond_destroy(&proc->cond_FH);
+  pthread_cond_destroy(&proc->cond_FH1);
   pthread_cond_destroy(&proc->cond_asynch_rxtx);
   pthread_cond_destroy(&proc->cond_synch);
   pthread_cond_destroy(&proc->cond_eNBs);
 
   pthread_attr_destroy(&proc->attr_FH);
+  pthread_attr_destroy(&proc->attr_FH1);
   pthread_attr_destroy(&proc->attr_prach);
   pthread_attr_destroy(&proc->attr_synch);
   pthread_attr_destroy(&proc->attr_asynch_rxtx);
@@ -2055,8 +2229,8 @@ void set_function_spec_param(RU_t *ru)
       ru->fh_north_out          = fh_if4p5_north_out;       // send_IF4p5 on reception
       ru->fh_south_out          = tx_rf;                    // send output to RF
       ru->fh_north_asynch_in    = fh_if4p5_north_asynch_in; // TX packets come asynchronously
-      ru->feprx                 = (get_nprocs()<=2) ? fep_full :ru_fep_full_2thread;                 // RX DFTs
-      ru->feptx_ofdm            = (get_nprocs()<=2) ? feptx_ofdm : feptx_ofdm_2thread;               // this is fep with idft only (no precoding in RRU)
+      ru->feprx                 = (get_nprocs()<=2 || !fepw) ? fep_full :ru_fep_full_2thread;                 // RX DFTs
+      ru->feptx_ofdm            = (get_nprocs()<=2 || !fepw) ? feptx_ofdm : feptx_ofdm_2thread;               // this is fep with idft only (no precoding in RRU)
       ru->feptx_prec            = NULL;
       ru->start_if              = start_if;                 // need to start the if interface for if4p5
       ru->ifdevice.host_type    = RRU_HOST;
@@ -2077,8 +2251,8 @@ void set_function_spec_param(RU_t *ru)
     }
     else if (ru->function == eNodeB_3GPP) {
       ru->do_prach             = 0;                       // no prach processing in RU
-      ru->feprx                = (get_nprocs()<=2) ? fep_full : ru_fep_full_2thread;                // RX DFTs
-      ru->feptx_ofdm           = (get_nprocs()<=2) ? feptx_ofdm : feptx_ofdm_2thread;              // this is fep with idft and precoding
+      ru->feprx                = (get_nprocs()<=2 || !fepw) ? fep_full : ru_fep_full_2thread;                // RX DFTs
+      ru->feptx_ofdm           = (get_nprocs()<=2 || !fepw) ? feptx_ofdm : feptx_ofdm_2thread;              // this is fep with idft and precoding
       ru->feptx_prec           = feptx_prec;              // this is fep with idft and precoding
       ru->fh_north_in          = NULL;                    // no incoming fronthaul from north
       ru->fh_north_out         = NULL;                    // no outgoing fronthaul to north
@@ -2106,9 +2280,9 @@ void set_function_spec_param(RU_t *ru)
 
   case REMOTE_IF5: // the remote unit is IF5 RRU
     ru->do_prach               = 0;
-    ru->feprx                  = (get_nprocs()<=2) ? fep_full : fep_full;                   // this is frequency-shift + DFTs
+    ru->feprx                  = (get_nprocs()<=2 || !fepw) ? fep_full : fep_full;                   // this is frequency-shift + DFTs
     ru->feptx_prec             = feptx_prec;                 // need to do transmit Precoding + IDFTs
-    ru->feptx_ofdm             = (get_nprocs()<=2) ? feptx_ofdm : feptx_ofdm_2thread;                 // need to do transmit Precoding + IDFTs
+    ru->feptx_ofdm             = (get_nprocs()<=2 || !fepw) ? feptx_ofdm : feptx_ofdm_2thread;                 // need to do transmit Precoding + IDFTs
     if (ru->if_timing == synch_to_other) {
       ru->fh_south_in          = fh_slave_south_in;                  // synchronize to master
       ru->fh_south_out         = fh_if5_mobipass_south_out;          // use send_IF5 for mobipass
@@ -2239,7 +2413,7 @@ void init_RU(char *rf_config_file) {
         }
       }
     }
-    //    LOG_I(PHY,"Initializing RRU descriptor %d : (%s,%s,%d)\n",ru_id,ru_if_types[ru->if_south],eNB_timing[ru->if_timing],ru->function);
+        LOG_I(PHY,"Initializing RRU descriptor %d : (%s,%s,%d)\n",ru_id,ru_if_types[ru->if_south],eNB_timing[ru->if_timing],ru->function);
 
     set_function_spec_param(ru);
     LOG_I(PHY,"Starting ru_thread %d\n",ru_id);
diff --git a/targets/RT/USER/lte-softmodem.c b/targets/RT/USER/lte-softmodem.c
index c48b89ea137622393c6da2ca90e90eedeb545f71..80e386b04a1ceaa2cd5c5e29a0cacec537e90f37 100644
--- a/targets/RT/USER/lte-softmodem.c
+++ b/targets/RT/USER/lte-softmodem.c
@@ -214,6 +214,10 @@ extern PHY_VARS_UE* init_ue_vars(LTE_DL_FRAME_PARMS *frame_parms,
 extern void init_eNB_afterRU(void);
 
 int transmission_mode=1;
+int emulate_rf = 0;
+int numerology = 0;
+int codingw = 0;
+int fepw = 0;
 
 
 
@@ -629,6 +633,7 @@ void init_openair0(void) {
 
   int card;
   int i;
+  
 
   for (card=0; card<MAX_CARDS; card++) {
 
@@ -636,6 +641,8 @@ void init_openair0(void) {
     openair0_cfg[card].configFilename = NULL;
 
     if(frame_parms[0]->N_RB_DL == 100) {
+	  if(numerology == 0)
+	  {
       if (frame_parms[0]->threequarter_fs) {
 	openair0_cfg[card].sample_rate=23.04e6;
 	openair0_cfg[card].samples_per_frame = 230400;
@@ -647,6 +654,22 @@ void init_openair0(void) {
 	openair0_cfg[card].tx_bw = 10e6;
 	openair0_cfg[card].rx_bw = 10e6;
       }
+	  }else if(numerology == 1)
+	  {
+		openair0_cfg[card].sample_rate=61.44e6;
+		openair0_cfg[card].samples_per_frame = 307200;
+		openair0_cfg[card].tx_bw = 20e6;
+		openair0_cfg[card].rx_bw = 20e6;
+	  }else if(numerology == 2)
+	  {
+		openair0_cfg[card].sample_rate=122.88e6;
+		openair0_cfg[card].samples_per_frame = 307200;
+		openair0_cfg[card].tx_bw = 20e6;
+		openair0_cfg[card].rx_bw = 20e6;
+	  }else
+	  {
+	    printf("Un supported numerology\n");
+	  }
     } else if(frame_parms[0]->N_RB_DL == 50) {
       openair0_cfg[card].sample_rate=15.36e6;
       openair0_cfg[card].samples_per_frame = 153600;
diff --git a/targets/RT/USER/lte-softmodem.h b/targets/RT/USER/lte-softmodem.h
index 9de60c37c29bf32504d7c6d31a2d9553cdce4ee2..ac88699b936879b5cdcfa13d57f449eb45353a62 100644
--- a/targets/RT/USER/lte-softmodem.h
+++ b/targets/RT/USER/lte-softmodem.h
@@ -86,6 +86,12 @@
 #define CONFIG_HLP_TPORT         "tracer port\n"
 #define CONFIG_HLP_NOTWAIT       "don't wait for tracer, start immediately\n"
 #define CONFIG_HLP_TNOFORK       "to ease debugging with gdb\n"
+
+#define CONFIG_HLP_NUMEROLOGY    "adding numerology for 5G\n"
+#define CONFIG_HLP_CODINGW       "coding worker thread enable(disable by defult)\n"
+#define CONFIG_HLP_FEPW          "FEP worker thread enabled(disable by defult)\n"
+#define CONFIG_HLP_EMULATE_RF    "Emulated RF enabled(disable by defult)\n"
+
 #define CONFIG_HLP_DISABLNBIOT   "disable nb-iot, even if defined in config\n"
 
 /***************************************************************************************************************************************/
@@ -141,35 +147,40 @@
 /*   optname                     helpstr                paramflags                      XXXptr                  defXXXval                            type           numelt   */
 /*---------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
 #define CMDLINE_PARAMS_DESC {  \
-{"rf-config-file",        	 CONFIG_HLP_RFCFGF,	0,		  strptr:(char **)&rf_config_file,	defstrval:NULL, 		   TYPE_STRING,   sizeof(rf_config_file)}, \
-{"ulsch-max-errors",      	 CONFIG_HLP_ULMAXE,	0,		  uptr:&ULSCH_max_consecutive_errors,	defuintval:0,			   TYPE_UINT,	  0},			   \
-{"phy-test",              	 CONFIG_HLP_PHYTST,	PARAMFLAG_BOOL,   iptr:&phy_test,			defintval:0,			   TYPE_INT,	  0},			   \
-{"usim-test",             	 CONFIG_HLP_USIM,	PARAMFLAG_BOOL,   u8ptr:&usim_test,			defintval:0,			   TYPE_UINT8,    0},			   \
-{"mmapped-dma",           	 CONFIG_HLP_DMAMAP,	PARAMFLAG_BOOL,   uptr:&mmapped_dma,			defintval:0,			   TYPE_INT,	  0},			   \
-{"external-clock",        	 CONFIG_HLP_EXCCLK,	PARAMFLAG_BOOL,   uptr:&clock_source,			defintval:0,			   TYPE_INT,	  0},			   \
-{"wait-for-sync",         	 NULL,  		PARAMFLAG_BOOL,   iptr:&wait_for_sync,  		defintval:0,			   TYPE_INT,	  0},			   \
-{"single-thread-disable", 	 CONFIG_HLP_NOSNGLT,	PARAMFLAG_BOOL,   iptr:&single_thread_flag,		defintval:1,			   TYPE_INT,	  0},			   \
-{"threadIQ",              	 NULL,  		0,		  iptr:&(threads.iq),			defintval:1,			   TYPE_INT,	  0},			   \
-{"threadOneSubframe",     	 NULL,  		0,		  iptr:&(threads.one),  		defintval:1,			   TYPE_INT,	  0},			   \
-{"threadTwoSubframe",    	 NULL,  		0,		  iptr:&(threads.two),  		defintval:1,			   TYPE_INT,	  0},			   \
-{"threadThreeSubframe",    	 NULL,  		0,		  iptr:&(threads.three),  		defintval:1,			   TYPE_INT,	  0},			   \
-{"threadSlot1ProcOne",     	 NULL,  		0,		  iptr:&(threads.slot1_proc_one),      	defintval:1,			   TYPE_INT,	  0},			   \
-{"threadSlot1ProcTwo",    	 NULL,  		0,		  iptr:&(threads.slot1_proc_two),      	defintval:1,			   TYPE_INT,	  0},			   \
-{"A" ,  		  	 CONFIG_HLP_TADV,	0,		  uptr:&timing_advance, 		defintval:0,			   TYPE_UINT,	  0},			   \
-{"C" ,  		  	 CONFIG_HLP_DLF,	0,		  uptr:&(downlink_frequency[0][0]),	defuintval:DEFAULT_DLF,  	   TYPE_UINT,	  0},			   \
-{"a" ,  		  	 CONFIG_HLP_CHOFF,	0,		  iptr:&chain_offset,			defintval:0,			   TYPE_INT,	  0},			   \
-{"d" ,  		  	 CONFIG_HLP_SOFTS,	PARAMFLAG_BOOL,	  uptr:(uint32_t *)&do_forms,		defintval:0,			   TYPE_INT8,	  0},			   \
-{"E" ,  		  	 CONFIG_HLP_TQFS,	PARAMFLAG_BOOL,   i8ptr:&threequarter_fs,		defintval:0,			   TYPE_INT8,	  0},			   \
-{"K" ,  		  	 CONFIG_HLP_ITTIL,	PARAMFLAG_NOFREE, strptr:&itti_dump_file,		defstrval:"/tmp/itti.dump",	   TYPE_STRING,   0},			   \
-{"m" ,  		  	 CONFIG_HLP_DLMCS,	0,		  uptr:&target_dl_mcs,  		defintval:0,			   TYPE_UINT,	  0},			   \
-{"t" ,  		  	 CONFIG_HLP_ULMCS,	0,		  uptr:&target_ul_mcs,  		defintval:0,			   TYPE_UINT,	  0},			   \
-{"W" ,  		  	 CONFIG_HLP_L2MONW,	0,		  strptr:(char **)&in_ip,		defstrval:"127.0.0.1",  	   TYPE_STRING,   sizeof(in_ip)},	   \
-{"P" ,  		  	 CONFIG_HLP_L2MONP,	0,		  strptr:(char **)&in_path,		defstrval:"/tmp/oai_opt.pcap",     TYPE_STRING,   sizeof(in_path)},	   \
-{"V" ,  		  	 CONFIG_HLP_VCD,	PARAMFLAG_BOOL,   iptr:&ouput_vcd,			defintval:0,			   TYPE_INT,	  0},			   \
-{"q" ,  		  	 CONFIG_HLP_STMON,	PARAMFLAG_BOOL,   iptr:&opp_enabled,			defintval:0,			   TYPE_INT,	  0},			   \
-{"S" ,  		  	 CONFIG_HLP_MSLOTS,	PARAMFLAG_BOOL,   u8ptr:&exit_missed_slots,		defintval:1,			   TYPE_UINT8,    0},			   \
-{"T" ,  		  	 CONFIG_HLP_TDD,	PARAMFLAG_BOOL,   iptr:&tddflag,			defintval:0,			   TYPE_INT,	  0},			   \
-{"nbiot-disable",        	 CONFIG_HLP_DISABLNBIOT,PARAMFLAG_BOOL,   iptr:&nonbiotflag,			defintval:0,			   TYPE_INT,	  0}                       \
+{"rf-config-file",          CONFIG_HLP_RFCFGF,      0,                      strptr:(char **)&rf_config_file,    defstrval:NULL,                 TYPE_STRING,    sizeof(rf_config_file)}, \
+{"ulsch-max-errors",        CONFIG_HLP_ULMAXE,      0,                      uptr:&ULSCH_max_consecutive_errors, defuintval:0,                   TYPE_UINT,      0},                     \
+{"phy-test",                CONFIG_HLP_PHYTST,      PARAMFLAG_BOOL,         iptr:&phy_test,                     defintval:0,                    TYPE_INT,       0},                     \
+{"usim-test",               CONFIG_HLP_USIM,        PARAMFLAG_BOOL,         u8ptr:&usim_test,                   defintval:0,                    TYPE_UINT8,     0},                     \
+{"mmapped-dma",             CONFIG_HLP_DMAMAP,      PARAMFLAG_BOOL,         uptr:&mmapped_dma,                  defintval:0,                    TYPE_INT,       0},                     \
+{"external-clock",          CONFIG_HLP_EXCCLK,      PARAMFLAG_BOOL,         uptr:&clock_source,                 defintval:0,                    TYPE_INT,       0},                     \
+{"wait-for-sync",           NULL,                   PARAMFLAG_BOOL,         iptr:&wait_for_sync,                defintval:0,                    TYPE_INT,       0},                     \
+{"single-thread-disable",   CONFIG_HLP_NOSNGLT,     PARAMFLAG_BOOL,         iptr:&single_thread_flag,           defintval:1,                    TYPE_INT,       0},                     \
+{"threadIQ",                NULL,                   0,                      iptr:&(threads.iq),                 defintval:1,                    TYPE_INT,       0},                     \
+{"threadOneSubframe",       NULL,                   0,                      iptr:&(threads.one),                defintval:1,                    TYPE_INT,       0},                     \
+{"threadTwoSubframe",       NULL,                   0,                      iptr:&(threads.two),                defintval:1,                    TYPE_INT,       0},                     \
+{"threadThreeSubframe",     NULL,                   0,                      iptr:&(threads.three),              defintval:1,                    TYPE_INT,       0},                     \
+{"threadSlot1ProcOne",      NULL,                   0,                      iptr:&(threads.slot1_proc_one),     defintval:1,                    TYPE_INT,       0},                     \
+{"threadSlot1ProcTwo",      NULL,                   0,                      iptr:&(threads.slot1_proc_two),     defintval:1,                    TYPE_INT,       0},                     \
+{"dlsch-demod-shift",       CONFIG_HLP_DLSHIFT,     0,                      iptr:(int32_t *)&dlsch_demod_shift, defintval:0,                    TYPE_INT,       0},                     \
+{"A" ,                      CONFIG_HLP_TADV,        0,                      uptr:&timing_advance,               defintval:0,                    TYPE_UINT,      0},                     \
+{"C" ,                      CONFIG_HLP_DLF,         0,                      uptr:&(downlink_frequency[0][0]),   defuintval:2680000000,          TYPE_UINT,      0},                     \
+{"a" ,                      CONFIG_HLP_CHOFF,       0,                      iptr:&chain_offset,                 defintval:0,                    TYPE_INT,       0},                     \
+{"d" ,                      CONFIG_HLP_SOFTS,       PARAMFLAG_BOOL,         uptr:(uint32_t *)&do_forms,         defintval:0,                    TYPE_INT8,      0},                     \
+{"E" ,                      CONFIG_HLP_TQFS,        PARAMFLAG_BOOL,         i8ptr:&threequarter_fs,             defintval:0,                    TYPE_INT8,      0},                     \
+{"K" ,                      CONFIG_HLP_ITTIL,       PARAMFLAG_NOFREE,       strptr:&itti_dump_file,             defstrval:"/tmp/itti.dump",     TYPE_STRING,    0},                     \
+{"m" ,                      CONFIG_HLP_DLMCS,       0,                      uptr:&target_dl_mcs,                defintval:0,                    TYPE_UINT,      0},                     \
+{"t" ,                      CONFIG_HLP_ULMCS,       0,                      uptr:&target_ul_mcs,                defintval:0,                    TYPE_UINT,      0},                     \
+{"W" ,                      CONFIG_HLP_L2MONW,      0,                      strptr:(char **)&in_ip,             defstrval:"127.0.0.1",          TYPE_STRING,    sizeof(in_ip)},         \
+{"P" ,                      CONFIG_HLP_L2MONP,      0,                      strptr:(char **)&in_path,           defstrval:"/tmp/oai_opt.pcap",  TYPE_STRING,    sizeof(in_path)},       \
+{"V" ,                      CONFIG_HLP_VCD,         PARAMFLAG_BOOL,         iptr:&ouput_vcd,                    defintval:0,                    TYPE_INT,       0},                     \
+{"q" ,                      CONFIG_HLP_STMON,       PARAMFLAG_BOOL,         iptr:&opp_enabled,                  defintval:0,                    TYPE_INT,       0},                     \
+{"S" ,                      CONFIG_HLP_MSLOTS,      PARAMFLAG_BOOL,         u8ptr:&exit_missed_slots,           defintval:1,                    TYPE_UINT8,     0},                     \
+{"T" ,                      CONFIG_HLP_TDD,         PARAMFLAG_BOOL,         iptr:&tddflag,                      defintval:0,                    TYPE_INT,       0},                     \
+{"numerology" ,             CONFIG_HLP_NUMEROLOGY,  PARAMFLAG_BOOL,         iptr:&numerology,                   defintval:0,                    TYPE_INT,       0},                     \
+{"emulate-rf" ,             CONFIG_HLP_EMULATE_RF,  PARAMFLAG_BOOL,         iptr:&emulate_rf,                   defintval:0,                    TYPE_INT,       0},                     \
+{"codingw" ,                CONFIG_HLP_CODINGW,     PARAMFLAG_BOOL,         iptr:&codingw,                      defintval:0,                    TYPE_INT,       0},                     \
+{"fepw" ,                   CONFIG_HLP_FEPW,        PARAMFLAG_BOOL,         iptr:&fepw,                         defintval:0,                    TYPE_INT,       0},                     \
+{"nbiot-disable",           CONFIG_HLP_DISABLNBIOT, PARAMFLAG_BOOL,         iptr:&nonbiotflag,			defintval:0,			TYPE_INT,	0} \
 }
 
 #define CONFIG_HLP_FLOG          "Enable online log \n"
@@ -263,8 +274,10 @@ extern void reset_opp_meas(void);
 extern void print_opp_meas(void);
 
 extern void init_fep_thread(PHY_VARS_eNB *, pthread_attr_t *);
-extern void init_td_thread(PHY_VARS_eNB *, pthread_attr_t *);
-extern void init_te_thread(PHY_VARS_eNB *, pthread_attr_t *);
+extern void init_td_thread(PHY_VARS_eNB *);
+extern void init_te_thread(PHY_VARS_eNB *);
+extern void kill_td_thread(PHY_VARS_eNB *);
+extern void kill_te_thread(PHY_VARS_eNB *);
 
 PHY_VARS_UE* init_ue_vars(LTE_DL_FRAME_PARMS *frame_parms,
                           uint8_t UE_id,
diff --git a/targets/RT/USER/lte-uesoftmodem.c b/targets/RT/USER/lte-uesoftmodem.c
index 538c74e157b37c827a1e23ecc99ac55ac3a1bce6..349dd3afb55458fdd7de2b13ce5554167fd404bc 100644
--- a/targets/RT/USER/lte-uesoftmodem.c
+++ b/targets/RT/USER/lte-uesoftmodem.c
@@ -213,7 +213,10 @@ extern PHY_VARS_UE* init_ue_vars(LTE_DL_FRAME_PARMS *frame_parms,
 
 int transmission_mode=1;
 
-
+int emulate_rf = 0;
+int numerology = 0;
+int codingw = 0;
+int fepw = 0;
 
 /* struct for ethernet specific parameters given in eNB conf file */
 eth_params_t *eth_params;
diff --git a/targets/RT/USER/rt_wrapper.c b/targets/RT/USER/rt_wrapper.c
index 497fdb1f4636eb0a25a31b844f783130155fcb9f..443d183068e634ab97e751d7ed5f448edd820732 100644
--- a/targets/RT/USER/rt_wrapper.c
+++ b/targets/RT/USER/rt_wrapper.c
@@ -43,6 +43,7 @@
 #include <getopt.h>
 #include <sys/sysinfo.h>
 #include "rt_wrapper.h"
+#include <errno.h>
 
 #include "openair1/PHY/defs_common.h"
 
@@ -283,6 +284,7 @@ void thread_top_init(char *thread_name,
 
   if (sched_setattr(0, &attr, flags) < 0 ) {
     perror("[SCHED] eNB tx thread: sched_setattr failed\n");
+    fprintf(stderr,"sched_setattr Error = %s",strerror(errno));
     exit(1);
   }
 
diff --git a/targets/SIMU/USER/channel_sim.c b/targets/SIMU/USER/channel_sim.c
index 94bd1bbe43d2f3ee8bb02dc1ab18a246dfad9710..553d4807824625f102c74a4850822a2c5d50ae66 100644
--- a/targets/SIMU/USER/channel_sim.c
+++ b/targets/SIMU/USER/channel_sim.c
@@ -60,7 +60,11 @@
 #include "oaisim.h"
 
 #define RF
-//#define DEBUG_SIM
+#define DEBUG_SIM
+/*
+#undef LOG_D
+#define LOG_D(A,B,C...) printf(B,C)
+*/
 
 int number_rb_ul;
 int first_rbUL ;
@@ -232,7 +236,6 @@ void do_DL_sig(channel_desc_t *RU2UE[NUMBER_OF_RU_MAX][NUMBER_OF_UE_MAX][MAX_NUM
     pthread_mutex_lock(&RU_output_mutex[UE_id]);
  
     if (RU_output_mask[UE_id] == 0) {  //  This is the first eNodeB for this UE, clear the buffer
-      
       for (aa=0; aa<nb_antennas_rx; aa++) {
 	memset((void*)r_re_DL[UE_id][aa],0,(RC.ru[0]->frame_parms.samples_per_tti)*sizeof(double));
 	memset((void*)r_im_DL[UE_id][aa],0,(RC.ru[0]->frame_parms.samples_per_tti)*sizeof(double));
@@ -375,7 +378,8 @@ void do_DL_sig(channel_desc_t *RU2UE[NUMBER_OF_RU_MAX][NUMBER_OF_UE_MAX][MAX_NUM
             UE_id,ru_id,
             10*log10(rx_pwr),subframe);
 #endif
-      
+
+
       pthread_mutex_lock(&RU_output_mutex[UE_id]);
       for (i=0; i<frame_parms->samples_per_tti; i++) {
         for (aa=0; aa<nb_antennas_rx; aa++) {
@@ -389,14 +393,14 @@ void do_DL_sig(channel_desc_t *RU2UE[NUMBER_OF_RU_MAX][NUMBER_OF_UE_MAX][MAX_NUM
       
 
 
-	double *r_re_p[2] = {r_re_DL[ru_id][0],r_re_DL[ru_id][1]};
-	double *r_im_p[2] = {r_im_DL[ru_id][0],r_im_DL[ru_id][1]};
+	double *r_re_p[2] = {r_re_DL[UE_id][0],r_re_DL[UE_id][1]};
+	double *r_im_p[2] = {r_im_DL[UE_id][0],r_im_DL[UE_id][1]};
 
 #ifdef DEBUG_SIM
 	rx_pwr = signal_energy_fp(r_re_p,r_im_p,nb_antennas_rx,length<length_meas?length:length_meas,0)/(12.0*frame_parms->N_RB_DL);
 	LOG_D(OCM,"[SIM][DL] UE %d : ADC in %f dBm/RE for subframe %d\n",UE_id,10*log10(rx_pwr),subframe);
 #endif
-	
+
 	rxdata = PHY_vars_UE_g[UE_id][CC_id]->common_vars.rxdata;
 	sf_offset = (subframe*frame_parms->samples_per_tti)+offset;
 
diff --git a/targets/SIMU/USER/oaisim.c b/targets/SIMU/USER/oaisim.c
index 0008ba3bbde128740f20be36289ad2b419d018e9..71436347634e00e060c1ae3b193e5153f6aa8ce3 100644
--- a/targets/SIMU/USER/oaisim.c
+++ b/targets/SIMU/USER/oaisim.c
@@ -195,6 +195,11 @@ time_stats_t oaisim_stats_f;
 time_stats_t dl_chan_stats;
 time_stats_t ul_chan_stats;
 
+int emulate_rf = 0;
+int numerology = 0;
+int codingw = 0;
+int fepw = 0;
+
 // this should reflect the channel models in openair1/SIMULATION/TOOLS/defs.h
 mapping small_scale_names[] = { 
   { "custom", custom }, { "SCM_A", SCM_A },
@@ -737,19 +742,16 @@ l2l1_task (void *args_p)
 
 	CC_id=0;
         int all_done=0;
-
         while (all_done==0) {
 
           pthread_mutex_lock(&subframe_mutex);
-          int subframe_ru_mask_local = subframe_ru_mask;
-          int subframe_UE_mask_local  = subframe_UE_mask;
+          int subframe_ru_mask_local  = (subframe_select(&RC.ru[0]->frame_parms,(sf+4)%10)!=SF_UL) ? subframe_ru_mask : ((1<<NB_RU)-1);
+          int subframe_UE_mask_local  = (RC.ru[0]->frame_parms.frame_type == FDD || subframe_select(&RC.ru[0]->frame_parms,(sf+4)%10)!=SF_DL) ? subframe_UE_mask : ((1<<NB_UE_INST)-1);
           pthread_mutex_unlock(&subframe_mutex);
           LOG_D(EMU,"Frame %d, Subframe %d, NB_RU %d, NB_UE %d: Checking masks %x,%x\n",frame,sf,NB_RU,NB_UE_INST,subframe_ru_mask_local,subframe_UE_mask_local);
           if ((subframe_ru_mask_local == ((1<<NB_RU)-1)) &&
-              (subframe_UE_mask_local == ((1<<NB_UE_INST)-1)))
-             all_done=1;
-          else
-	    usleep(1500);
+              (subframe_UE_mask_local == ((1<<NB_UE_INST)-1))) all_done=1;
+          else usleep(1500);
         }
 
 
@@ -816,18 +818,16 @@ l2l1_task (void *args_p)
               fwrite (stats_buffer, 1, len, eNB_stats[eNB_inst]);
               fflush(eNB_stats[eNB_inst]);
             }
-	    */
 #ifdef OPENAIR2
-/*
             if (eNB_l2_stats) {
               len = dump_eNB_l2_stats (stats_buffer, 0);
               rewind (eNB_l2_stats);
               fwrite (stats_buffer, 1, len, eNB_l2_stats);
               fflush(eNB_l2_stats);
             }
-*/
 
 #endif
+*/
 #endif
           }
         }// eNB_inst loop
@@ -1070,6 +1070,7 @@ void set_UE_defaults(int nb_ue) {
 	PHY_vars_UE_g[UE_id][CC_id]->pdcch_vars[i][0]->agregationLevel      = 0xFF;
       }
       PHY_vars_UE_g[UE_id][CC_id]->current_dlsch_cqi[0] = 10;
+      PHY_vars_UE_g[UE_id][CC_id]->tx_power_max_dBm = 23;
     }
   }
 }
diff --git a/targets/SIMU/USER/oaisim_functions.c b/targets/SIMU/USER/oaisim_functions.c
index ceaae1958b9c08df2b57028dd7f54c4fa7fe79b5..5900170480ed339009e85baef66d303d6535eff2 100644
--- a/targets/SIMU/USER/oaisim_functions.c
+++ b/targets/SIMU/USER/oaisim_functions.c
@@ -1087,20 +1087,21 @@ int ru_trx_read(openair0_device *device, openair0_timestamp *ptimestamp, void **
 
     
     subframe = (last_ru_rx_timestamp[ru_id][CC_id]/RC.ru[ru_id]->frame_parms.samples_per_tti)%10;
-    LOG_D(EMU,"RU_trx_read generating UL subframe %d (Ts %llu, current TS %llu)\n",
-	  subframe,(unsigned long long)*ptimestamp,
-	  (unsigned long long)current_ru_rx_timestamp[ru_id][CC_id]);
-    
-    do_UL_sig(UE2RU,
-	      enb_data,
-	      ue_data,
-	      subframe,
-	      0,  // abstraction_flag
-	      &RC.ru[ru_id]->frame_parms,
-	      0,  // frame is only used for abstraction
-	      ru_id,
-	      CC_id);
-  
+    if (subframe_select(&RC.ru[ru_id]->frame_parms,subframe) != SF_DL || RC.ru[ru_id]->frame_parms.frame_type == FDD) { 
+      LOG_D(EMU,"RU_trx_read generating UL subframe %d (Ts %llu, current TS %llu)\n",
+	    subframe,(unsigned long long)*ptimestamp,
+	    (unsigned long long)current_ru_rx_timestamp[ru_id][CC_id]);
+      
+      do_UL_sig(UE2RU,
+		enb_data,
+		ue_data,
+		subframe,
+		0,  // abstraction_flag
+		&RC.ru[ru_id]->frame_parms,
+		0,  // frame is only used for abstraction
+		ru_id,
+		CC_id);
+    }
     last_ru_rx_timestamp[ru_id][CC_id] += RC.ru[ru_id]->frame_parms.samples_per_tti;
     sample_count += RC.ru[ru_id]->frame_parms.samples_per_tti;
   }
@@ -1352,9 +1353,6 @@ void init_devices(void){
 	PHY_vars_UE_g[UE_id][CC_id]->rfdevice.trx_set_freq_func    = UE_trx_set_freq;
 	PHY_vars_UE_g[UE_id][CC_id]->rfdevice.trx_set_gains_func   = UE_trx_set_gains;
 	last_UE_rx_timestamp[UE_id][CC_id] = 0;
-
-
-
       }
     }
   }
@@ -1529,11 +1527,11 @@ void update_ocm()
     //LOG_D(OMG," extracting position of eNb...\n");
     //display_node_list(enb_node_list);
     //  display_node_list(ue_node_list);
-    extract_position(enb_node_list, enb_data, RC.nb_RU);
+    //extract_position(enb_node_list, enb_data, RC.nb_RU);
     //extract_position_fixed_enb(enb_data, NB_eNB_INST,frame);
     //LOG_D(OMG," extracting position of UE...\n");
     //      if (oai_emulation.info.omg_model_ue == TRACE)
-    extract_position(ue_node_list, ue_data, NB_UE_INST);
+    //extract_position(ue_node_list, ue_data, NB_UE_INST);
 
     /* if (frame % 50 == 0)
        LOG_N(OCM,"Path loss for TTI %d : \n", frame);