From eb363157c6f2ee604cafe7177a8d0e988b285d36 Mon Sep 17 00:00:00 2001
From: Raymond Knopp <raymond.knopp@eurecom.fr>
Date: Wed, 30 May 2018 17:49:55 -0700
Subject: [PATCH] moved simulation target into lte-uesoftmodem with --simL1
 option

---
 cmake_targets/CMakeLists.txt                  | 111 +---
 common/utils/itti/signals.c                   |   4 +-
 openair1/PHY/phy_extern.h                     |   1 -
 openair1/PHY/phy_extern_ue.h                  |   1 -
 openair1/PHY/phy_vars.h                       |   1 -
 openair1/PHY/phy_vars_ue.h                    |   1 -
 .../SIMULATION/ETH_TRANSPORT/multicast_link.c |  38 +-
 openair1/SIMULATION/TOOLS/channel_sim.c       | 494 ++++++++++++++
 openair2/UTIL/LOG/log.c                       |  32 +-
 openair2/UTIL/LOG/log.h                       |   2 +-
 targets/RT/USER/lte-ru.c                      |   2 +-
 targets/RT/USER/lte-softmodem.c               |  17 +-
 targets/RT/USER/lte-softmodem.h               |   8 +-
 targets/RT/USER/lte-ue.c                      |  67 +-
 targets/RT/USER/lte-uesoftmodem.c             | 228 ++-----
 targets/RT/USER/rfsim.c                       | 580 ++++++++++++++++
 targets/SIMU/USER/channel_sim.c               | 618 ------------------
 17 files changed, 1269 insertions(+), 936 deletions(-)
 create mode 100644 openair1/SIMULATION/TOOLS/channel_sim.c
 create mode 100644 targets/RT/USER/rfsim.c
 delete mode 100644 targets/SIMU/USER/channel_sim.c

diff --git a/cmake_targets/CMakeLists.txt b/cmake_targets/CMakeLists.txt
index f75bc26b7d..ae5eaefc43 100644
--- a/cmake_targets/CMakeLists.txt
+++ b/cmake_targets/CMakeLists.txt
@@ -621,9 +621,7 @@ add_boolean_option(RRC_DEFAULT_RAB_IS_AM False "set the RLC mode to AM for the d
 add_boolean_option(OAI_NW_DRIVER_TYPE_ETHERNET False "????")
 add_boolean_option(DEADLINE_SCHEDULER True "Use the Linux scheduler SCHED_DEADLINE: kernel >= 3.14")
 add_boolean_option(CPU_AFFINITY False "Enable CPU Affinity of threads (only valid without deadline scheduler). It is enabled only with >2 CPUs")
-add_boolean_option(NAS_ADDRESS_FIX False "specific to oaisim: for nasmesh driver")
 add_boolean_option(NAS_NETLINK False "useless ??? Must be True to compile nasmesh driver without rtai ????")
-add_boolean_option(OAISIM False "specific to oaisim")
 add_boolean_option(OAI_NW_DRIVER_USE_NETLINK True "????")
 
 add_boolean_option(USE_MME False "this flag is used only one time in lte-softmodem.c")
@@ -652,9 +650,7 @@ add_boolean_option(OPENAIR_LTE             True "Seems legacy: keep it to true")
 # PHY options
 ##########################
 add_boolean_option(DRIVER2013              True "only relevant for EXMIMO")
-add_boolean_option(ENABLE_NEW_MULTICAST    False "specific to oaisim")
 add_boolean_option(EXMIMO_IOT              True "????")
-add_boolean_option(LARGE_SCALE             False "specific to oaisim: defines max eNB=2 and max UE=120")
 add_boolean_option(LOCALIZATION            False "???")
 add_integer_option(MAX_NUM_CCs             1     "????")
 add_boolean_option(MU_RECEIVER             False "????")
@@ -677,7 +673,6 @@ add_boolean_option(NAS_UE                  True  "NAS UE INSTANCE (<> NAS_MME)")
 ##########################
 # ACCESS STRATUM LAYER2 OPTIONS
 ##########################
-add_boolean_option(MAC_CONTEXT             True  "specific to oaisim")
 add_boolean_option(JUMBO_FRAME             True  "ENABLE LARGE SDU in ACCESS STRATUM (larger than common MTU)")
 
 ##########################
@@ -1720,12 +1715,14 @@ ${OPENAIR1_DIR}/SIMULATION/TOOLS/taus.c
 ${OPENAIR1_DIR}/SIMULATION/TOOLS/multipath_channel.c
 ${OPENAIR1_DIR}/SIMULATION/TOOLS/multipath_tv_channel.c
 ${OPENAIR1_DIR}/SIMULATION/TOOLS/abstraction.c
+${OPENAIR1_DIR}/SIMULATION/TOOLS/channel_sim.c
 ${OPENAIR1_DIR}/SIMULATION/RF/rf.c
 ${OPENAIR1_DIR}/SIMULATION/RF/dac.c
 ${OPENAIR1_DIR}/SIMULATION/RF/adc.c
 ${OPENAIR1_DIR}/SIMULATION/ETH_TRANSPORT/netlink_init.c
 )
 
+
 add_library(SIMU_ETH
 ${OPENAIR1_DIR}/SIMULATION/ETH_TRANSPORT/netlink_init.c
 ${OPENAIR1_DIR}/SIMULATION/ETH_TRANSPORT/multicast_link.c
@@ -1982,6 +1979,8 @@ add_executable(lte-uesoftmodem
   ${OPENAIR_TARGETS}/RT/USER/rt_wrapper.c
   ${OPENAIR_TARGETS}/RT/USER/lte-ue.c
   ${OPENAIR_TARGETS}/RT/USER/lte-uesoftmodem.c
+  ${OPENAIR_TARGETS}/RT/USER/lte-ru.c
+  ${OPENAIR_TARGETS}/RT/USER/rfsim.c
   ${OPENAIR1_DIR}/SIMULATION/TOOLS/taus.c
   ${OPENAIR_TARGETS}/COMMON/create_tasks_ue.c
   ${OPENAIR_TARGETS}/ARCH/COMMON/common_lib.c
@@ -2000,13 +1999,13 @@ add_executable(lte-uesoftmodem
 
 target_link_libraries (lte-uesoftmodem
   -Wl,--start-group
-  RRC_LIB S1AP_LIB S1AP_ENB GTPV1U SECU_CN SECU_OSA UTIL HASHTABLE SCTP_CLIENT UDP SCHED_RU_LIB SCHED_UE_LIB PHY_COMMON PHY_UE PHY_RU LFDS L2_UE 
+  RRC_LIB S1AP_LIB S1AP_ENB GTPV1U SECU_CN SECU_OSA UTIL HASHTABLE SCTP_CLIENT UDP SCHED_RU_LIB SCHED_UE_LIB PHY_COMMON PHY_UE PHY_RU LFDS L2_UE SIMU 
   ${MSC_LIB} ${RAL_LIB} ${NAS_UE_LIB} ${ITTI_LIB} ${FLPT_MSG_LIB} ${ASYNC_IF_LIB} LFDS7
   NFAPI_COMMON_LIB NFAPI_LIB NFAPI_PNF_LIB NFAPI_USER_LIB
   -Wl,--end-group z dl)
 
 target_link_libraries (lte-uesoftmodem ${LIBXML2_LIBRARIES})
-target_link_libraries (lte-uesoftmodem pthread m ${CONFIG_LIBRARIES} rt crypt ${CRYPTO_LIBRARIES} ${OPENSSL_LIBRARIES} ${NETTLE_LIBRARIES} sctp  ${XFORMS_LIBRARIES} ${PROTOBUF_LIB}  ${CMAKE_DL_LIBS} ${LIBYAML_LIBRARIES})
+target_link_libraries (lte-uesoftmodem pthread m ${CONFIG_LIBRARIES} rt crypt ${CRYPTO_LIBRARIES} ${OPENSSL_LIBRARIES} ${NETTLE_LIBRARIES} sctp  ${XFORMS_LIBRARIES} ${PROTOBUF_LIB}  ${CMAKE_DL_LIBS} ${LIBYAML_LIBRARIES} ${ATLAS_LIBRARIES})
 target_link_libraries (lte-uesoftmodem ${LIB_LMS_LIBRARIES})
 target_link_libraries (lte-uesoftmodem ${T_LIB})
 
@@ -2019,6 +2018,8 @@ add_executable(lte-uesoftmodem-nos1
   ${OPENAIR_TARGETS}/RT/USER/rt_wrapper.c
   ${OPENAIR_TARGETS}/RT/USER/lte-ue.c
   ${OPENAIR_TARGETS}/RT/USER/lte-uesoftmodem.c
+  ${OPENAIR_TARGETS}/RT/USER/lte-ru.c
+  ${OPENAIR_TARGETS}/RT/USER/rfsim.c
   ${OPENAIR1_DIR}/SIMULATION/TOOLS/taus.c
   ${OPENAIR_TARGETS}/COMMON/create_tasks_ue.c
   ${OPENAIR_TARGETS}/ARCH/COMMON/common_lib.c
@@ -2038,13 +2039,13 @@ add_executable(lte-uesoftmodem-nos1
 
 target_link_libraries (lte-uesoftmodem-nos1
   -Wl,--start-group
-  RRC_LIB SECU_CN SECU_OSA UTIL HASHTABLE SCHED_RU_LIB SCHED_UE_LIB PHY_COMMON PHY_UE PHY_RU LFDS L2_UE ${MSC_LIB} ${RAL_LIB} ${ITTI_LIB} 
+  RRC_LIB SECU_CN SECU_OSA UTIL HASHTABLE SCHED_RU_LIB SCHED_UE_LIB PHY_COMMON PHY_UE PHY_RU LFDS L2_UE SIMU ${MSC_LIB} ${RAL_LIB} ${ITTI_LIB} 
   ${MIH_LIB} ${FLPT_MSG_LIB} ${ASYNC_IF_LIB} LFDS7
   NFAPI_COMMON_LIB NFAPI_LIB NFAPI_PNF_LIB NFAPI_USER_LIB
   -Wl,--end-group z dl )
 
 target_link_libraries (lte-uesoftmodem-nos1 ${LIBXML2_LIBRARIES})
-target_link_libraries (lte-uesoftmodem-nos1 pthread m ${CONFIG_LIBRARIES} rt crypt ${CRYPTO_LIBRARIES} ${OPENSSL_LIBRARIES} ${NETTLE_LIBRARIES} sctp  ${XFORMS_LIBRARIES} ${PROTOBUF_LIB} ${CMAKE_DL_LIBS} ${LIBYAML_LIBRARIES})
+target_link_libraries (lte-uesoftmodem-nos1 pthread m ${CONFIG_LIBRARIES} rt crypt ${CRYPTO_LIBRARIES} ${OPENSSL_LIBRARIES} ${NETTLE_LIBRARIES} sctp  ${XFORMS_LIBRARIES} ${PROTOBUF_LIB} ${CMAKE_DL_LIBS} ${LIBYAML_LIBRARIES} ${ATLAS_LIBRARIES})
 target_link_libraries (lte-uesoftmodem-nos1  ${LIB_LMS_LIBRARIES})
 target_link_libraries (lte-uesoftmodem-nos1 ${T_LIB})
 
@@ -2075,96 +2076,6 @@ target_link_libraries (lte-uesoftmodem-nos1 ${T_LIB})
 # Addexecutables for tests
 ####################################
 
-# A all in one network simulator
-################
-add_executable(oaisim
-  ${rrc_h}
-  ${s1ap_h}
-  ${x2ap_h}
-  ${OPENAIR_BIN_DIR}/messages_xml.h
-  ${OPENAIR_TARGETS}/RT/USER/lte-ue.c
-  ${OPENAIR_TARGETS}/RT/USER/lte-ru.c
-  ${OPENAIR_TARGETS}/RT/USER/rt_wrapper.c
-  ${OPENAIR_TARGETS}/SIMU/USER/channel_sim.c
-#  ${OPENAIR_TARGETS}/SIMU/USER/oaisim_config.c
-  ${OPENAIR_TARGETS}/SIMU/USER/sinr_sim.c
-  ${OPENAIR_TARGETS}/SIMU/USER/cor_SF_sim.c
-  ${OPENAIR_TARGETS}/SIMU/USER/oaisim_functions.c
-  ${OPENAIR_TARGETS}/SIMU/USER/event_handler.c
-  ${OPENAIR_TARGETS}/SIMU/USER/oaisim.c
-  ${OPENAIR_TARGETS}/ARCH/COMMON/common_lib.c
-  ${OPENAIR2_DIR}/RRC/NAS/nas_config.c
-  ${OPENAIR2_DIR}/RRC/NAS/rb_config.c
-  ${OPENAIR3_DIR}/NAS/UE/nas_ue_task.c
-  ${OPENAIR_DIR}/common/utils/utils.c
-  ${OPENAIR_DIR}/common/utils/system.c
-  ${OPENAIR_TARGETS}/COMMON/create_tasks_ue.c
-  ${XFORMS_SOURCE}
-  ${T_SOURCE}
-  ${CONFIG_SOURCES}
-  ${SHLIB_LOADER_SOURCES}
-)
-
-
-target_include_directories(oaisim PUBLIC  ${OPENAIR_TARGETS}/SIMU/USER)
-target_link_libraries (oaisim
-  -Wl,-ldl,--start-group
-  RRC_LIB S1AP_LIB S1AP_ENB X2AP_LIB SECU_CN UTIL HASHTABLE SCTP_CLIENT UDP SCHED_RU_LIB SCHED_UE_LIB PHY_COMMON PHY_UE PHY_RU LFDS L2_UE ${MSC_LIB} LIB_NAS_UE SIMU SECU_OSA ${ITTI_LIB}  ${MIH_LIB}
-  ${FLPT_MSG_LIB} ${ASYNC_IF_LIB} ${FLEXRAN_AGENT_LIB} LFDS7
-  -Wl,--end-group z dl)
-
-target_link_libraries (oaisim ${LIBXML2_LIBRARIES} ${LAPACK_LIBRARIES})
-target_link_libraries (oaisim pthread m ${CONFIG_LIBRARIES} rt crypt ${CRYPTO_LIBRARIES} ${OPENSSL_LIBRARIES}  ${NETTLE_LIBRARIES} sctp z
-  ${ATLAS_LIBRARIES} ${XFORMS_LIBRARIES} ${OPENPGM_LIBRARIES} ${PROTOBUF_LIB} ${CMAKE_DL_LIBS} ${LIBYAML_LIBRARIES})
-#Force link with forms, regardless XFORMS option
-target_link_libraries (oaisim forms)
-target_link_libraries (oaisim ${T_LIB})
-
-
-# A all in one network simulator
-################
-add_executable(oaisim_nos1
-  ${rrc_h}
-  ${s1ap_h}
-  ${x2ap_h}
-  ${OPENAIR_BIN_DIR}/messages_xml.h
-  ${OPENAIR_TARGETS}/RT/USER/lte-ue.c
-  ${OPENAIR_TARGETS}/RT/USER/lte-ru.c
-  ${OPENAIR1_DIR}/SCHED/prach_procedures.c
-  ${OPENAIR_TARGETS}/RT/USER/rt_wrapper.c
-  ${OPENAIR_TARGETS}/SIMU/USER/channel_sim.c
-#  ${OPENAIR_TARGETS}/SIMU/USER/oaisim_config.c
-  ${OPENAIR_TARGETS}/SIMU/USER/sinr_sim.c
-  ${OPENAIR_TARGETS}/SIMU/USER/cor_SF_sim.c
-  ${OPENAIR_TARGETS}/SIMU/USER/oaisim_functions.c
-  ${OPENAIR_TARGETS}/SIMU/USER/event_handler.c
-  ${OPENAIR_TARGETS}/SIMU/USER/oaisim.c
-  ${OPENAIR_TARGETS}/ARCH/COMMON/common_lib.c
-  ${OPENAIR2_DIR}/RRC/NAS/nas_config.c
-  ${OPENAIR2_DIR}/RRC/NAS/rb_config.c
-  ${OPENAIR_TARGETS}/COMMON/create_tasks_ue.c
-  ${OPENAIR_DIR}/common/utils/system.c
-  ${XFORMS_SOURCE}
-  ${T_SOURCE}
-  ${CONFIG_SOURCES}
-  ${SHLIB_LOADER_SOURCES}
-)
-target_include_directories(oaisim_nos1 PUBLIC  ${OPENAIR_TARGETS}/SIMU/USER)
-target_link_libraries (oaisim_nos1
-  -Wl,--start-group
-  RRC_LIB X2AP_LIB SECU_CN UTIL HASHTABLE SCHED_RU_LIB SCHED_UE_LIB PHY_COMMON PHY_UE PHY_RU LFDS ${MSC_LIB} ${ITTI_LIB} SIMU L2_UE ${FLPT_MSG_LIB} ${ASYNC_IF_LIB} LFDS7
-  -Wl,--end-group z dl )
-
-target_link_libraries (oaisim_nos1 ${LIBXML2_LIBRARIES} ${LAPACK_LIBRARIES})
-target_link_libraries (oaisim_nos1 pthread m ${CONFIG_LIBRARIES} rt crypt ${CRYPTO_LIBRARIES} ${OPENSSL_LIBRARIES}  ${NETTLE_LIBRARIES}  
-  ${ATLAS_LIBRARIES} ${XFORMS_LIBRARIES} ${OPENPGM_LIBRARIES} ${PROTOBUF_LIB} ${CMAKE_DL_LIBS} ${LIBYAML_LIBRARIES})
-#Force link with forms, regardless XFORMS option
-target_link_libraries (oaisim_nos1 forms)
-
-#message("protobuflib is  ${PROTOBUF_LIB}")
-
-target_link_libraries (oaisim_nos1 ${T_LIB})
-
 
 # Unitary tests for each piece of L1: example, mbmssim is MBMS L1 simulator
 #####################################
@@ -2262,7 +2173,7 @@ endforeach(myExe)
 if (${T_TRACER})
   foreach(i
         #all "add_executable" definitions (except tests, rb_tool, updatefw)
-        lte-softmodem lte-softmodem-nos1 oaisim oaisim_nos1
+        lte-softmodem lte-softmodem-nos1
         dlsim_tm4 dlsim dlsim_tm7 ulsim pbchsim scansim mbmssim
         pdcchsim pucchsim prachsim syncsim
         #all "add_library" definitions
diff --git a/common/utils/itti/signals.c b/common/utils/itti/signals.c
index 9767ba3f67..4e1ae1129c 100644
--- a/common/utils/itti/signals.c
+++ b/common/utils/itti/signals.c
@@ -42,8 +42,8 @@
 #include "log.h"
 
 #if defined (LOG_D) && defined (LOG_E)
-# define SIG_DEBUG(x, args...)  LOG_D(EMU, x, ##args)
-# define SIG_ERROR(x, args...)  LOG_E(EMU, x, ##args)
+# define SIG_DEBUG(x, args...)  LOG_D(SIM, x, ##args)
+# define SIG_ERROR(x, args...)  LOG_E(SIM, x, ##args)
 #endif
 
 #ifndef SIG_DEBUG
diff --git a/openair1/PHY/phy_extern.h b/openair1/PHY/phy_extern.h
index 4cb3cc538f..ece40bd7b4 100644
--- a/openair1/PHY/phy_extern.h
+++ b/openair1/PHY/phy_extern.h
@@ -70,7 +70,6 @@ extern char mode_string[4][20];
 
 
 
-extern unsigned char NB_RU;
 
 #ifndef OPENAIR2
 extern unsigned char NB_eNB_INST;
diff --git a/openair1/PHY/phy_extern_ue.h b/openair1/PHY/phy_extern_ue.h
index 98dbfb886e..964c9977b3 100644
--- a/openair1/PHY/phy_extern_ue.h
+++ b/openair1/PHY/phy_extern_ue.h
@@ -65,7 +65,6 @@ extern int flagMag;
 
 extern char mode_string[4][20];
 
-extern unsigned char NB_RU;
 
 #ifndef OPENAIR2
 extern unsigned char NB_eNB_INST;
diff --git a/openair1/PHY/phy_vars.h b/openair1/PHY/phy_vars.h
index 783a151046..c556453e77 100644
--- a/openair1/PHY/phy_vars.h
+++ b/openair1/PHY/phy_vars.h
@@ -67,7 +67,6 @@ char mode_string[4][20] = {"NOT SYNCHED","PRACH","RAR","PUSCH"};
 
 #include "SIMULATION/ETH_TRANSPORT/vars.h"
 
-unsigned char NB_RU=0;
 
 #ifndef OPENAIR2
 unsigned char NB_eNB_INST=0;
diff --git a/openair1/PHY/phy_vars_ue.h b/openair1/PHY/phy_vars_ue.h
index c323d1eade..c6937c8af3 100644
--- a/openair1/PHY/phy_vars_ue.h
+++ b/openair1/PHY/phy_vars_ue.h
@@ -61,7 +61,6 @@ char mode_string[4][20] = {"NOT SYNCHED","PRACH","RAR","PUSCH"};
 
 #include "SIMULATION/ETH_TRANSPORT/vars.h"
 
-unsigned char NB_RU=0;
 
 #ifndef OPENAIR2
 unsigned char NB_eNB_INST=0;
diff --git a/openair1/SIMULATION/ETH_TRANSPORT/multicast_link.c b/openair1/SIMULATION/ETH_TRANSPORT/multicast_link.c
index 8cf9e13212..83b2d9765e 100644
--- a/openair1/SIMULATION/ETH_TRANSPORT/multicast_link.c
+++ b/openair1/SIMULATION/ETH_TRANSPORT/multicast_link.c
@@ -99,7 +99,7 @@ multicast_link_init(void)
                                  SOCK_DGRAM,
                                  &group_list[group].port, &sin);
 
-    LOG_D(EMU, "multicast_link_init(): Created socket %d for group %d, port %d\n",
+    LOG_D(SIM, "multicast_link_init(): Created socket %d for group %d, port %d\n",
           group_list[group].socket,group,group_list[group].port);
 
     /* Used so we can re-bind to our port while a previous connection is still
@@ -107,17 +107,17 @@ multicast_link_init(void)
      */
     if (setsockopt(group_list[group].socket, SOL_SOCKET, SO_REUSEADDR,
                    &reuse_addr, sizeof (reuse_addr)) < 0) {
-      LOG_E(EMU, "[MULTICAST] ERROR : setsockopt:SO_REUSEADDR, exiting ...");
+      LOG_E(SIM, "[MULTICAST] ERROR : setsockopt:SO_REUSEADDR, exiting ...");
       exit (EXIT_FAILURE);
     }
 
     if (multicast_if != NULL) {
       if (setsockopt(group_list[group].socket, SOL_SOCKET,SO_BINDTODEVICE,
                      multicast_if, strlen(multicast_if)) < 0) {
-        LOG_E(EMU,
+        LOG_E(SIM,
               "[MULTICAST] ERROR : setsockopt:SO_BINDTODEVICE on interface %s, exiting ...\n",
               multicast_if);
-        LOG_E(EMU,
+        LOG_E(SIM,
               "[MULTICAST] make sure that you have a root privilage or run with sudo -E \n");
         exit (EXIT_FAILURE);
       }
@@ -132,7 +132,7 @@ multicast_link_init(void)
 
     if (setsockopt (group_list[group].socket, IPPROTO_IP, IP_MULTICAST_LOOP,
                     &multicast_loop, sizeof (multicast_loop)) < 0) {
-      LOG_E(EMU,
+      LOG_E(SIM,
             "[MULTICAST] ERROR: %s line %d multicast_link_main_loop() IP_MULTICAST_LOOP %m",
             __FILE__, __LINE__);
       exit (EXIT_FAILURE);
@@ -143,13 +143,13 @@ multicast_link_init(void)
     command.imr_interface.s_addr = htonl (INADDR_ANY);
 
     if (command.imr_multiaddr.s_addr == -1) {
-      LOG_E(EMU, "[MULTICAST] ERROR: %s line %d NO MULTICAST", __FILE__, __LINE__);
+      LOG_E(SIM, "[MULTICAST] ERROR: %s line %d NO MULTICAST", __FILE__, __LINE__);
       exit (EXIT_FAILURE);
     }
 
     if (setsockopt (group_list[group].socket, IPPROTO_IP, IP_ADD_MEMBERSHIP,
                     &command, sizeof (command)) < 0) {
-      LOG_E(EMU, "[MULTICAST] ERROR: %s line %d IP_ADD_MEMBERSHIP %m", __FILE__,
+      LOG_E(SIM, "[MULTICAST] ERROR: %s line %d IP_ADD_MEMBERSHIP %m", __FILE__,
             __LINE__);
       exit (EXIT_FAILURE);
     }
@@ -202,13 +202,13 @@ multicast_link_read_data (int groupP)
   if ((groupP < MULTICAST_LINK_NUM_GROUPS) && (groupP >= 0)) {
     if ((num_bytes = recvfrom (group_list[groupP].socket,
                                group_list[groupP].rx_buffer, 40000, 0, 0, 0)) < 0) {
-      LOG_E(EMU, "[MULTICAST] recvfrom has failed (%d:%s)\n   (%s:%d)\n",
+      LOG_E(SIM, "[MULTICAST] recvfrom has failed (%d:%s)\n   (%s:%d)\n",
             errno, strerror(errno), __FILE__, __LINE__);
     } else {
       rx_handler(num_bytes,group_list[groupP].rx_buffer);
     }
   } else {
-    LOG_E(EMU, "[MULTICAST] ERROR: groupP out of bounds %d\n", groupP);
+    LOG_E(SIM, "[MULTICAST] ERROR: groupP out of bounds %d\n", groupP);
   }
 }
 
@@ -242,7 +242,7 @@ multicast_link_write_sock(int groupP, char *dataP, uint32_t sizeP)
   if ((num = sendto (group_list[groupP].socket, dataP, sizeP, 0,
                      (struct sockaddr *) &group_list[groupP].sock_remote_addr,
                      sizeof (group_list[groupP].sock_remote_addr))) < 0) {
-    LOG_E(EMU, "[MULTICAST] sendto has failed (%d:%s)\n   (%s:%d)\n",
+    LOG_E(SIM, "[MULTICAST] sendto has failed (%d:%s)\n   (%s:%d)\n",
           errno, strerror(errno),
           __FILE__, __LINE__);
   }
@@ -274,22 +274,22 @@ int multicast_link_read_data_from_sock(uint8_t is_master)
 
   multicast_link_build_select_list ();
 
-  LOG_D(EMU, "Stuck on select with timeout %s\n",
+  LOG_D(SIM, "Stuck on select with timeout %s\n",
         timeout_p == NULL ? "infinite" : "15000 usecs");
 
   readsocks = select(highsock + 1, &socks, (fd_set *) 0, (fd_set *) 0, timeout_p);
 
   if (readsocks < 0) {
-    LOG_E(EMU, "Multicast select failed (%d:%s)\n", errno, strerror(errno));
+    LOG_E(SIM, "Multicast select failed (%d:%s)\n", errno, strerror(errno));
     exit(EXIT_FAILURE);
   } else if (readsocks > 0) {
-#ifdef DEBUG_EMU
-    LOG_D(EMU, "Multicast Normal read\n");
+#ifdef DEBUG_SIM
+    LOG_D(SIM, "Multicast Normal read\n");
 #endif
     multicast_link_read();
   } else {
     /* Timeout */
-    LOG_I(EMU, "Multicast select time-out\n");
+    LOG_I(SIM, "Multicast select time-out\n");
     return 1;
   }
 
@@ -311,21 +311,21 @@ void multicast_link_start(void (*rx_handlerP) (unsigned int, char *),
   rx_handler = rx_handlerP;
   multicast_group = _multicast_group;
   multicast_if =  multicast_ifname;
-  LOG_I(EMU, "[MULTICAST] LINK START on interface=%s for group=%d: handler=%p\n",
+  LOG_I(SIM, "[MULTICAST] LINK START on interface=%s for group=%d: handler=%p\n",
         (multicast_if == NULL) ? "not specified" : multicast_if, multicast_group,
         rx_handler);
   multicast_link_init ();
 #if ! defined(ENABLE_NEW_MULTICAST)
-  LOG_D(EMU, "[MULTICAST] multicast link start thread\n");
+  LOG_D(SIM, "[MULTICAST] multicast link start thread\n");
 
   if (pthread_create (&main_loop_thread, NULL, multicast_link_main_loop,
                       NULL) != 0) {
-    LOG_E(EMU, "[MULTICAST LINK] Error in pthread_create (%d:%s)\n",
+    LOG_E(SIM, "[MULTICAST LINK] Error in pthread_create (%d:%s)\n",
           errno, strerror(errno));
     exit(EXIT_FAILURE);
   } else {
     pthread_detach(main_loop_thread);  // disassociate from parent
-    LOG_I(EMU, "[MULTICAST LINK] Thread detached\n");
+    LOG_I(SIM, "[MULTICAST LINK] Thread detached\n");
   }
 
 #endif
diff --git a/openair1/SIMULATION/TOOLS/channel_sim.c b/openair1/SIMULATION/TOOLS/channel_sim.c
new file mode 100644
index 0000000000..7e5adc20fe
--- /dev/null
+++ b/openair1/SIMULATION/TOOLS/channel_sim.c
@@ -0,0 +1,494 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+#include <string.h>
+#include <math.h>
+#include <unistd.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <time.h>
+
+#include "SIMULATION/TOOLS/sim.h"
+#include "SIMULATION/RF/rf.h"
+#include "PHY/types.h"
+#include "PHY/defs_eNB.h"
+#include "PHY/phy_extern.h"
+#include "PHY/phy_extern_ue.h"
+
+#include "LAYER2/MAC/mac.h"
+#include "LAYER2/MAC/mac_extern.h"
+#include "UTIL/LOG/log_if.h"
+#include "UTIL/LOG/log_extern.h"
+#include "RRC/LTE/rrc_extern.h"
+#include "PHY_INTERFACE/phy_interface_extern.h"
+#include "UTIL/OCG/OCG.h"
+#include "UTIL/OPT/opt.h" // to test OPT
+
+#include "UTIL/FIFO/types.h"
+
+#define RF
+#define DEBUG_SIM
+/*
+#undef LOG_D
+#define LOG_D(A,B,C...) printf(B,C)
+*/
+
+int number_rb_ul;
+int first_rbUL ;
+
+extern Signal_buffers_t *signal_buffers_g;
+
+
+double r_re_DL[NUMBER_OF_UE_MAX][2][30720];
+double r_im_DL[NUMBER_OF_UE_MAX][2][30720];
+double r_re_UL[NUMBER_OF_eNB_MAX][2][30720];
+double r_im_UL[NUMBER_OF_eNB_MAX][2][30720];
+int RU_output_mask[NUMBER_OF_UE_MAX];
+int UE_output_mask[NUMBER_OF_RU_MAX];
+pthread_mutex_t RU_output_mutex[NUMBER_OF_UE_MAX];
+pthread_mutex_t UE_output_mutex[NUMBER_OF_RU_MAX];
+
+double ru_amp[NUMBER_OF_RU_MAX];
+
+void do_DL_sig(channel_desc_t *RU2UE[NUMBER_OF_RU_MAX][NUMBER_OF_UE_MAX][MAX_NUM_CCs],
+	       uint16_t subframe,
+	       uint32_t offset,
+	       uint32_t length,
+	       uint8_t abstraction_flag,LTE_DL_FRAME_PARMS *ue_frame_parms,
+	       uint8_t UE_id,
+	       int CC_id)
+{
+
+  int32_t att_eNB_id=-1;
+  int32_t **txdata,**rxdata;
+
+  uint32_t eNB_id,ru_id=0;
+  double tx_pwr;
+  double rx_pwr;
+  int32_t rx_pwr2;
+  uint32_t i,aa;
+  uint32_t sf_offset;
+
+  double min_path_loss=-200;
+  uint8_t hold_channel=0;
+  uint8_t nb_antennas_rx = RU2UE[0][0][CC_id]->nb_rx; // number of rx antennas at UE
+  uint8_t nb_antennas_tx = RU2UE[0][0][CC_id]->nb_tx; // number of tx antennas at eNB
+
+  double s_re0[30720];
+  double s_re1[30720];
+  double *s_re[2];
+  double s_im0[30720];
+  double s_im1[30720];
+  double *s_im[2];
+  double r_re00[30720];
+  double r_re01[30720];
+  double *r_re0[2];
+  double r_im00[30720];
+  double r_im01[30720];
+  double *r_im0[2];
+  LTE_DL_FRAME_PARMS *frame_parms;
+
+  s_re[0] = s_re0;
+  s_im[0] = s_im0;
+  s_re[1] = s_re1;
+  s_im[1] = s_im1;
+
+  r_re0[0] = r_re00;
+  r_im0[0] = r_im00;
+  r_re0[1] = r_re01;
+  r_im0[1] = r_im01;
+
+  if (subframe==0)
+    hold_channel = 0;
+  else
+    hold_channel = 1;
+
+  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));
+    }
+  }
+  pthread_mutex_unlock(&RU_output_mutex[UE_id]);
+  
+  for (ru_id=0; ru_id<RC.nb_RU; ru_id++) {
+    txdata = RC.ru[ru_id]->common.txdata;
+    frame_parms = &RC.ru[ru_id]->frame_parms;
+    
+    sf_offset = (subframe*frame_parms->samples_per_tti) + offset;
+    LOG_D(SIM,">>>>>>>>>>>>>>>>>TXPATH: RU %d : DL_sig reading TX for subframe %d (sf_offset %d, length %d) from %p\n",ru_id,subframe,sf_offset,length,txdata[0]+sf_offset); 
+    int length_meas = frame_parms->ofdm_symbol_size;
+    if (sf_offset+length <= frame_parms->samples_per_tti*10) {
+      
+      tx_pwr = dac_fixed_gain(s_re,
+			      s_im,
+			      txdata,
+			      sf_offset,
+			      nb_antennas_tx,
+			      length,
+			      sf_offset,
+			      length_meas,
+			      14,
+			      frame_parms->pdsch_config_common.referenceSignalPower, // dBm/RE
+			      0,
+			      &ru_amp[ru_id],
+			      frame_parms->N_RB_DL*12);
+      
+    }
+    else {
+      tx_pwr = dac_fixed_gain(s_re,
+			      s_im,
+			      txdata,
+			      sf_offset,
+			      nb_antennas_tx,
+			      (frame_parms->samples_per_tti*10)-sf_offset,
+			      sf_offset,
+			      length_meas,
+			      14,
+			      frame_parms->pdsch_config_common.referenceSignalPower, // dBm/RE
+			      0,
+			      &ru_amp[ru_id],
+			      frame_parms->N_RB_DL*12);
+      
+      tx_pwr = dac_fixed_gain(s_re,
+			      s_im,
+			      txdata,
+			      sf_offset,
+			      nb_antennas_tx,
+			      length+sf_offset-(frame_parms->samples_per_tti*10),
+			      sf_offset,
+			      length_meas,
+			      14,
+			      frame_parms->pdsch_config_common.referenceSignalPower, // dBm/RE
+			      0,
+			      &ru_amp[ru_id],
+			      frame_parms->N_RB_DL*12);
+    }
+#ifdef DEBUG_SIM
+    LOG_D(PHY,"[SIM][DL] subframe %d: txp (time) %d dB\n",
+	  subframe,dB_fixed(signal_energy(&txdata[0][sf_offset],length_meas)));
+    
+    LOG_D(OCM,"[SIM][DL] RU %d (CCid %d): tx_pwr %.1f dBm/RE (target %d dBm/RE), for subframe %d\n",
+	  ru_id,CC_id,
+	  10*log10(tx_pwr),
+	  frame_parms->pdsch_config_common.referenceSignalPower,
+	  subframe);
+    
+#endif
+    tx_pwr = signal_energy_fp(s_re,s_im,nb_antennas_tx,
+			      length<length_meas?length:length_meas,
+			      0)/(12.0*frame_parms->N_RB_DL);
+    
+    //RU2UE[eNB_id][UE_id]->path_loss_dB = 0;
+    multipath_channel(RU2UE[ru_id][UE_id][CC_id],s_re,s_im,r_re0,r_im0,
+		      length,hold_channel);
+#ifdef DEBUG_SIM
+    rx_pwr = signal_energy_fp2(RU2UE[ru_id][UE_id][CC_id]->ch[0],
+			       RU2UE[ru_id][UE_id][CC_id]->channel_length)*RU2UE[ru_id][UE_id][CC_id]->channel_length;
+    LOG_D(OCM,"[SIM][DL] Channel RU %d => UE %d (CCid %d): Channel gain %f dB (%f)\n",ru_id,UE_id,CC_id,10*log10(rx_pwr),rx_pwr);
+#endif
+    
+    
+#ifdef DEBUG_SIM
+    
+    for (i=0; i<RU2UE[ru_id][UE_id][CC_id]->channel_length; i++)
+      LOG_D(OCM,"channel(%d,%d)[%d] : (%f,%f)\n",ru_id,UE_id,i,RU2UE[ru_id][UE_id][CC_id]->ch[0][i].x,RU2UE[ru_id][UE_id][CC_id]->ch[0][i].y);
+    
+#endif
+    
+    LOG_D(OCM,"[SIM][DL] Channel RU %d => UE %d (CCid %d): tx_power %.1f dBm/RE, path_loss %1.f dB\n",
+	  ru_id,UE_id,CC_id,
+	  (double)frame_parms->pdsch_config_common.referenceSignalPower,
+	  RU2UE[ru_id][UE_id][CC_id]->path_loss_dB);
+    
+#ifdef DEBUG_SIM
+    rx_pwr = signal_energy_fp(r_re0,r_im0,nb_antennas_rx,
+			      length<length_meas?length:length_meas,
+			      0)/(12.0*frame_parms->N_RB_DL);
+    LOG_D(OCM,"[SIM][DL] UE %d : rx_pwr %f dBm/RE (%f dBm RSSI,tx %f dB)for subframe %d (length %d)\n",UE_id,
+	  10*log10(rx_pwr),
+	  10*log10(rx_pwr*(double)frame_parms->N_RB_DL*12),
+	  10*log10(tx_pwr),subframe,
+	  length<length_meas?length:length_meas);
+
+    
+    LOG_D(OCM,"[SIM][DL] UE %d : rx_pwr (noise) -132 dBm/RE (N0fs = %.1f dBm, N0B = %.1f dBm) for subframe %d\n",
+	  UE_id,
+	  10*log10(RU2UE[ru_id][UE_id][CC_id]->sampling_rate*1e6)-174,
+	  10*log10(RU2UE[ru_id][UE_id][CC_id]->sampling_rate*1e6*12*frame_parms->N_RB_DL/(double)frame_parms->ofdm_symbol_size)-174,
+	  subframe);
+#endif
+    
+    if (RU2UE[ru_id][UE_id][CC_id]->first_run == 1)
+      RU2UE[ru_id][UE_id][CC_id]->first_run = 0;
+    
+    
+    // RF model
+#ifdef DEBUG_SIM
+    LOG_D(OCM,"[SIM][DL] UE %d (CCid %d): rx_gain %d dB (-ADC %f) for subframe %d\n",UE_id,CC_id,PHY_vars_UE_g[UE_id][CC_id]->rx_total_gain_dB,
+	  PHY_vars_UE_g[UE_id][CC_id]->rx_total_gain_dB-66.227,subframe);
+#endif
+    
+    rf_rx_simple(r_re0,
+		 r_im0,
+		 nb_antennas_rx,
+		 length,
+		 1e3/RU2UE[ru_id][UE_id][CC_id]->sampling_rate,  // sampling time (ns)
+		 (double)PHY_vars_UE_g[UE_id][CC_id]->rx_total_gain_dB - 66.227);   // rx_gain (dB) (66.227 = 20*log10(pow2(11)) = gain from the adc that will be applied later)
+    
+#ifdef DEBUG_SIM
+    rx_pwr = signal_energy_fp(r_re0,r_im0,
+			      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 (RU %d) %f dBm/RE for subframe %d\n",
+	  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++) {
+	r_re_DL[UE_id][aa][i]+=r_re0[aa][i];
+	r_im_DL[UE_id][aa][i]+=r_im0[aa][i];
+      }
+    }
+    RU_output_mask[UE_id] |= (1<<ru_id);
+    if (RU_output_mask[UE_id] == (1<<RC.nb_RU)-1) {
+      RU_output_mask[UE_id]=0;
+      
+      
+      
+      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;
+      
+      
+      adc(r_re_p,
+	  r_im_p,
+	  0,
+	  sf_offset,
+	  rxdata,
+	  nb_antennas_rx,
+	  length,
+	  12);
+      
+#ifdef DEBUG_SIM
+      rx_pwr2 = signal_energy(rxdata[0]+sf_offset,length<length_meas?length:length_meas)/(12.0*frame_parms->N_RB_DL);
+      LOG_D(OCM,"[SIM][DL] UE %d : rx_pwr (ADC out) %f dB/RE (%d) for subframe %d, writing to %p, length %d\n",UE_id, 10*log10((double)rx_pwr2),rx_pwr2,subframe,rxdata,length<length_meas?length:length_meas);
+      LOG_D(OCM,"[SIM][DL] UE %d : rx_pwr (ADC out) %f dB for subframe %d\n",UE_id,10*log10((double)rx_pwr2*12*frame_parms->N_RB_DL) ,subframe);
+#else
+      UNUSED_VARIABLE(rx_pwr2);
+      UNUSED_VARIABLE(tx_pwr);
+      UNUSED_VARIABLE(rx_pwr);
+#endif
+	
+    } // RU_output_mask
+    pthread_mutex_unlock(&RU_output_mutex[UE_id]);      
+  } // ru_id
+  
+}
+
+
+
+
+void do_UL_sig(channel_desc_t *UE2RU[NUMBER_OF_UE_MAX][NUMBER_OF_RU_MAX][MAX_NUM_CCs],
+	       uint16_t subframe,uint8_t abstraction_flag,LTE_DL_FRAME_PARMS *frame_parms, 
+	       uint32_t frame,int ru_id,uint8_t CC_id)
+{
+
+  int32_t **txdata,**rxdata;
+  uint8_t UE_id=0;
+
+  uint8_t nb_antennas_rx = UE2RU[0][0][CC_id]->nb_rx; // number of rx antennas at eNB
+  uint8_t nb_antennas_tx = UE2RU[0][0][CC_id]->nb_tx; // number of tx antennas at UE
+
+  double tx_pwr, rx_pwr;
+  int32_t rx_pwr2;
+  uint32_t i,aa;
+  uint32_t sf_offset;
+
+  uint8_t hold_channel=0;
+
+  double s_re0[30720];
+  double s_re1[30720];
+  double *s_re[2];
+  double s_im0[30720];
+  double s_im1[30720];
+  double *s_im[2];
+  double r_re00[30720];
+  double r_re01[30720];
+  double *r_re0[2];
+  double r_im00[30720];
+  double r_im01[30720];
+  double *r_im0[2];
+
+  s_re[0] = s_re0;
+  s_im[0] = s_im0;
+  s_re[1] = s_re1;
+  s_im[1] = s_im1;
+
+  r_re0[0] = r_re00;
+  r_im0[0] = r_im00;
+  r_re0[1] = r_re01;
+  r_im0[1] = r_im01;
+  
+  pthread_mutex_lock(&UE_output_mutex[ru_id]);
+  // Clear RX signal for eNB = eNB_id
+  for (i=0; i<frame_parms->samples_per_tti; i++) {
+    for (aa=0; aa<nb_antennas_rx; aa++) {
+      r_re_UL[ru_id][aa][i]=0.0;
+      r_im_UL[ru_id][aa][i]=0.0;
+    }
+  }
+  pthread_mutex_unlock(&UE_output_mutex[ru_id]);
+  
+  // Compute RX signal for eNB = eNB_id
+  for (UE_id=0; UE_id<NB_UE_INST; UE_id++) {
+    
+    txdata = PHY_vars_UE_g[UE_id][CC_id]->common_vars.txdata;
+    AssertFatal(txdata != NULL,"txdata is null\n");
+    sf_offset = subframe*frame_parms->samples_per_tti;
+    if (((double)PHY_vars_UE_g[UE_id][CC_id]->tx_power_dBm[subframe] +
+	 UE2RU[UE_id][ru_id][CC_id]->path_loss_dB) <= -125.0) {
+      // don't simulate a UE that is too weak
+      LOG_D(OCM,"[SIM][UL] ULPOWERS UE %d tx_pwr %d dBm (num_RE %d) for subframe %d (sf_offset %d)\n",
+	    UE_id,
+	    PHY_vars_UE_g[UE_id][CC_id]->tx_power_dBm[subframe],
+	    PHY_vars_UE_g[UE_id][CC_id]->tx_total_RE[subframe],
+	    subframe,sf_offset);	
+    } else {
+      tx_pwr = dac_fixed_gain((double**)s_re,
+			      (double**)s_im,
+			      txdata,
+			      sf_offset,
+			      nb_antennas_tx,
+			      frame_parms->samples_per_tti,
+			      sf_offset,
+			      frame_parms->ofdm_symbol_size,
+			      14,
+			      (double)PHY_vars_UE_g[UE_id][CC_id]->tx_power_dBm[subframe]-10*log10((double)PHY_vars_UE_g[UE_id][CC_id]->tx_total_RE[subframe]),
+			      1,
+			      NULL,
+			      PHY_vars_UE_g[UE_id][CC_id]->tx_total_RE[subframe]);  // This make the previous argument the total power
+      LOG_D(OCM,"[SIM][UL] ULPOWERS UE %d tx_pwr %f dBm (target %d dBm, num_RE %d) for subframe %d (sf_offset %d)\n",
+	    UE_id,
+	    10*log10(tx_pwr*PHY_vars_UE_g[UE_id][CC_id]->tx_total_RE[subframe]),
+	    PHY_vars_UE_g[UE_id][CC_id]->tx_power_dBm[subframe],
+	    PHY_vars_UE_g[UE_id][CC_id]->tx_total_RE[subframe],
+	    subframe,sf_offset);
+      
+      
+      multipath_channel(UE2RU[UE_id][ru_id][CC_id],s_re,s_im,r_re0,r_im0,
+			frame_parms->samples_per_tti,hold_channel);
+      
+      
+      rx_pwr = signal_energy_fp2(UE2RU[UE_id][ru_id][CC_id]->ch[0],
+				 UE2RU[UE_id][ru_id][CC_id]->channel_length)*UE2RU[UE_id][ru_id][CC_id]->channel_length;
+      
+      LOG_D(OCM,"[SIM][UL] subframe %d Channel UE %d => RU %d : %f dB (hold %d,length %d, PL %f)\n",subframe,UE_id,ru_id,10*log10(rx_pwr),
+	    hold_channel,UE2RU[UE_id][ru_id][CC_id]->channel_length,
+	    UE2RU[UE_id][ru_id][CC_id]->path_loss_dB);
+      
+      rx_pwr = signal_energy_fp(r_re0,r_im0,nb_antennas_rx,frame_parms->samples_per_tti,0);
+      LOG_D(OCM,"[SIM][UL] RU %d (%d/%d rx antennas) : rx_pwr %f dBm (tx_pwr - PL %f) for subframe %d, sptti %d\n",
+	    ru_id,nb_antennas_rx,UE2RU[UE_id][ru_id][CC_id]->nb_rx,10*log10(rx_pwr),10*log10(tx_pwr*PHY_vars_UE_g[UE_id][CC_id]->tx_total_RE[subframe])+UE2RU[UE_id][ru_id][CC_id]->path_loss_dB,subframe,frame_parms->samples_per_tti);
+      /*	
+		if (abs(10*log10(rx_pwr)-10*log10(tx_pwr*PHY_vars_UE_g[UE_id][CC_id]->tx_total_RE[subframe])-UE2RU[UE_id][ru_id][CC_id]->path_loss_dB)>3) {
+		write_output("txsig_re.m","s_re",s_re[0],frame_parms->samples_per_tti,1,7);
+		write_output("txsig_im.m","s_im",s_im[0],frame_parms->samples_per_tti,1,7);
+		write_output("rxsig_re.m","r_re",r_re0[0],frame_parms->samples_per_tti,1,7);
+		write_output("rxsig_im.m","r_im",r_im0[0],frame_parms->samples_per_tti,1,7);
+		exit(-1);
+		}*/
+      
+      if (UE2RU[UE_id][ru_id][CC_id]->first_run == 1)
+	UE2RU[UE_id][ru_id][CC_id]->first_run = 0;
+      
+      
+      pthread_mutex_lock(&UE_output_mutex[ru_id]);
+      for (aa=0; aa<nb_antennas_rx; aa++) {
+	for (i=0; i<frame_parms->samples_per_tti; i++) {
+	  r_re_UL[ru_id][aa][i]+=r_re0[aa][i];
+	  r_im_UL[ru_id][aa][i]+=r_im0[aa][i];
+	}
+      }
+      pthread_mutex_unlock(&UE_output_mutex[ru_id]);
+    }
+  } //UE_id
+  
+  double *r_re_p[2] = {r_re_UL[ru_id][0],r_re_UL[ru_id][1]};
+  double *r_im_p[2] = {r_im_UL[ru_id][0],r_im_UL[ru_id][1]};
+  
+  rx_pwr = signal_energy_fp(r_re_p,r_im_p,nb_antennas_rx,frame_parms->samples_per_tti,0);
+  LOG_D(OCM,"[SIM][UL] RU %d (%d/%d rx antennas) : rx_pwr %f dBm (before RF) for subframe %d, gain %f\n",
+	ru_id,nb_antennas_rx,nb_antennas_rx,10*log10(rx_pwr),subframe,
+	(double)RC.ru[ru_id]->max_rxgain-(double)RC.ru[ru_id]->att_rx - 66.227);
+  rf_rx_simple(r_re_p,
+	       r_im_p,
+	       nb_antennas_rx,
+	       frame_parms->samples_per_tti,
+	       1e3/UE2RU[0][ru_id][CC_id]->sampling_rate,  // sampling time (ns)
+	       (double)RC.ru[ru_id]->max_rxgain-(double)RC.ru[ru_id]->att_rx - 66.227);   // rx_gain (dB) (66.227 = 20*log10(pow2(11)) = gain from the adc that will be applied later)
+  
+  //#ifdef DEBUG_SIM
+  rx_pwr = signal_energy_fp(r_re_p,r_im_p,nb_antennas_rx,frame_parms->samples_per_tti,0);//*(double)frame_parms->ofdm_symbol_size/(12.0*frame_parms->N_RB_DL;
+  LOG_D(OCM,"[SIM][UL] rx_pwr (ADC in) %f dB for subframe %d (rx_gain %f)\n",10*log10(rx_pwr),subframe,
+	(double)RC.ru[ru_id]->max_rxgain-(double)RC.ru[ru_id]->att_rx);
+  //#endif
+  
+  rxdata = RC.ru[ru_id]->common.rxdata;
+  sf_offset = subframe*frame_parms->samples_per_tti;
+  
+  
+  adc(r_re_p,
+      r_im_p,
+      0,
+      sf_offset,
+      rxdata,
+      nb_antennas_rx,
+      frame_parms->samples_per_tti,
+      12);
+  
+#ifdef DEBUG_SIM
+  rx_pwr2 = signal_energy(rxdata[0]+sf_offset,frame_parms->samples_per_tti)*(double)frame_parms->ofdm_symbol_size/(12.0*frame_parms->N_RB_DL);
+  LOG_D(OCM,"[SIM][UL] RU %d rx_pwr (ADC out) %f dB (%d) for subframe %d (offset %d) = %p\n",ru_id,10*log10((double)rx_pwr2),rx_pwr2,subframe,sf_offset,rxdata[0]+sf_offset);
+#else
+  UNUSED_VARIABLE(tx_pwr);
+  UNUSED_VARIABLE(rx_pwr);
+  UNUSED_VARIABLE(rx_pwr2);
+#endif
+    
+}
+
+
+
+
diff --git a/openair2/UTIL/LOG/log.c b/openair2/UTIL/LOG/log.c
index ff6a5cd573..dcdf3bad86 100644
--- a/openair2/UTIL/LOG/log.c
+++ b/openair2/UTIL/LOG/log.c
@@ -212,13 +212,13 @@ int logInit (void)
   g_log->log_component[RRC].filelog = 0;
   g_log->log_component[RRC].filelog_name = "/tmp/rrc.log";
 
-  g_log->log_component[EMU].name = "EMU";
-  g_log->log_component[EMU].level = LOG_EMERG;
-  g_log->log_component[EMU].flag =  LOG_MED;
-  g_log->log_component[EMU].interval =  1;
-  g_log->log_component[EMU].fd = 0;
-  g_log->log_component[EMU].filelog = 0;
-  g_log->log_component[EMU].filelog_name = "";
+  g_log->log_component[SIM].name = "SIM";
+  g_log->log_component[SIM].level = LOG_EMERG;
+  g_log->log_component[SIM].flag =  LOG_MED;
+  g_log->log_component[SIM].interval =  1;
+  g_log->log_component[SIM].fd = 0;
+  g_log->log_component[SIM].filelog = 0;
+  g_log->log_component[SIM].filelog_name = "";
 
   g_log->log_component[OMG].name = "OMG";
   g_log->log_component[OMG].level = LOG_EMERG;
@@ -474,7 +474,7 @@ int logInit (void)
 
   if (g_log->syslog) {
 #if ! defined(CN_BUILD)
-    openlog(g_log->log_component[EMU].name, LOG_PID, g_log->config.facility);
+    openlog(g_log->log_component[SIM].name, LOG_PID, g_log->config.facility);
 #endif // ! defined(CN_BUILD)
   }
   log_getconfig(g_log);
@@ -1737,16 +1737,16 @@ int main(int argc, char *argv[])
 int test_log(void)
 {
   LOG_ENTER(MAC); // because the default level is DEBUG
-  LOG_I(EMU, "1 Starting OAI logs version %s Build date: %s on %s\n",
+  LOG_I(SIM, "1 Starting OAI logs version %s Build date: %s on %s\n",
         BUILD_VERSION, BUILD_DATE, BUILD_HOST);
   LOG_D(MAC, "1 debug  MAC \n");
   LOG_N(MAC, "1 notice MAC \n");
   LOG_W(MAC, "1 warning MAC \n");
 
-  set_comp_log(EMU, LOG_INFO, FLAG_ONLINE);
+  set_comp_log(SIM, LOG_INFO, FLAG_ONLINE);
   set_comp_log(MAC, LOG_WARNING, 0);
 
-  LOG_I(EMU, "2 Starting OAI logs version %s Build date: %s on %s\n",
+  LOG_I(SIM, "2 Starting OAI logs version %s Build date: %s on %s\n",
         BUILD_VERSION, BUILD_DATE, BUILD_HOST);
   LOG_E(MAC, "2 emerge MAC\n");
   LOG_D(MAC, "2 debug  MAC \n");
@@ -1758,7 +1758,7 @@ int test_log(void)
   set_comp_log(MAC, LOG_NOTICE, 1);
 
   LOG_ENTER(MAC);
-  LOG_I(EMU, "3 Starting OAI logs version %s Build date: %s on %s\n",
+  LOG_I(SIM, "3 Starting OAI logs version %s Build date: %s on %s\n",
         BUILD_VERSION, BUILD_DATE, BUILD_HOST);
   LOG_D(MAC, "3 debug  MAC \n");
   LOG_N(MAC, "3 notice MAC \n");
@@ -1766,10 +1766,10 @@ int test_log(void)
   LOG_I(MAC, "3 info MAC \n");
 
   set_comp_log(MAC, LOG_DEBUG,1);
-  set_comp_log(EMU, LOG_DEBUG,1);
+  set_comp_log(SIM, LOG_DEBUG,1);
 
   LOG_ENTER(MAC);
-  LOG_I(EMU, "4 Starting OAI logs version %s Build date: %s on %s\n",
+  LOG_I(SIM, "4 Starting OAI logs version %s Build date: %s on %s\n",
         BUILD_VERSION, BUILD_DATE, BUILD_HOST);
   LOG_D(MAC, "4 debug  MAC \n");
   LOG_N(MAC, "4 notice MAC \n");
@@ -1778,7 +1778,7 @@ int test_log(void)
 
 
   set_comp_log(MAC, LOG_DEBUG,0);
-  set_comp_log(EMU, LOG_DEBUG,0);
+  set_comp_log(SIM, LOG_DEBUG,0);
 
   LOG_I(LOG, "5 Starting OAI logs version %s Build date: %s on %s\n",
         BUILD_VERSION, BUILD_DATE, BUILD_HOST);
@@ -1789,7 +1789,7 @@ int test_log(void)
 
 
   set_comp_log(MAC, LOG_TRACE,0X07F);
-  set_comp_log(EMU, LOG_TRACE,0X07F);
+  set_comp_log(SIM, LOG_TRACE,0X07F);
 
   LOG_ENTER(MAC);
   LOG_I(LOG, "6 Starting OAI logs version %s Build date: %s on %s\n",
diff --git a/openair2/UTIL/LOG/log.h b/openair2/UTIL/LOG/log.h
index d0ac13dac3..d101ed999c 100644
--- a/openair2/UTIL/LOG/log.h
+++ b/openair2/UTIL/LOG/log.h
@@ -150,7 +150,7 @@ typedef enum {
     MIN_LOG_COMPONENTS = 0,
     PHY = MIN_LOG_COMPONENTS,
     MAC,
-    EMU,
+    SIM,
     OCG,
     OMG,
     OPT,
diff --git a/targets/RT/USER/lte-ru.c b/targets/RT/USER/lte-ru.c
index 89c57849ca..057052aa32 100644
--- a/targets/RT/USER/lte-ru.c
+++ b/targets/RT/USER/lte-ru.c
@@ -2467,7 +2467,7 @@ void RCconfig_RU(void) {
 
 
 
-    RC.ru_mask=(1<<NB_RU) - 1;
+    RC.ru_mask=(1<<RC.nb_RU) - 1;
     printf("Set RU mask to %lx\n",RC.ru_mask);
 
     for (j = 0; j < RC.nb_RU; j++) {
diff --git a/targets/RT/USER/lte-softmodem.c b/targets/RT/USER/lte-softmodem.c
index 7163d8bd7d..e9373620fb 100644
--- a/targets/RT/USER/lte-softmodem.c
+++ b/targets/RT/USER/lte-softmodem.c
@@ -459,7 +459,7 @@ void *l2l1_task(void *arg) {
       switch (ITTI_MSG_ID(message_p)) {
       case INITIALIZE_MESSAGE:
 	/* Start eNB thread */
-	LOG_D(EMU, "L2L1 TASK received %s\n", ITTI_MSG_NAME(message_p));
+	printf("L2L1 TASK received %s\n", ITTI_MSG_NAME(message_p));
 	start_eNB = 1;
 	break;
 
@@ -471,7 +471,7 @@ void *l2l1_task(void *arg) {
 	break;
 
       default:
-	LOG_E(EMU, "Received unexpected message %s\n", ITTI_MSG_NAME(message_p));
+	printf("Received unexpected message %s\n", ITTI_MSG_NAME(message_p));
 	break;
       }
     } while (ITTI_MSG_ID(message_p) != INITIALIZE_MESSAGE);
@@ -498,11 +498,11 @@ void *l2l1_task(void *arg) {
       break;
 
     case MESSAGE_TEST:
-      LOG_I(EMU, "Received %s\n", ITTI_MSG_NAME(message_p));
+      printf("Received %s\n", ITTI_MSG_NAME(message_p));
       break;
 
     default:
-      LOG_E(EMU, "Received unexpected message %s\n", ITTI_MSG_NAME(message_p));
+      printf("Received unexpected message %s\n", ITTI_MSG_NAME(message_p));
       break;
     }
 
@@ -564,8 +564,7 @@ static void get_options(void) {
       /* Read RC configuration file */
       RCConfig();
       NB_eNB_INST = RC.nb_inst;
-      NB_RU	  = RC.nb_RU;
-      printf("Configuration: nb_rrc_inst %d, nb_L1_inst %d, nb_ru %d\n",NB_eNB_INST,RC.nb_L1_inst,NB_RU);
+      printf("Configuration: nb_rrc_inst %d, nb_L1_inst %d, nb_ru %d\n",NB_eNB_INST,RC.nb_L1_inst,RC.nb_RU);
       if (nonbiotflag <= 0) {
          load_NB_IoT();
          printf("               nb_nbiot_rrc_inst %d, nb_nbiot_L1_inst %d, nb_nbiot_macrlc_inst %d\n",
@@ -1285,7 +1284,7 @@ int main( int argc, char **argv )
 
   // cleanup
     stop_eNB(NB_eNB_INST);
-    stop_RU(NB_RU);
+    stop_RU(RC.nb_RU);
     /* release memory used by the RU/eNB threads (incomplete), after all
      * threads have been stopped (they partially use the same memory) */
     for (int inst = 0; inst < NB_eNB_INST; inst++) {
@@ -1294,7 +1293,7 @@ int main( int argc, char **argv )
         phy_free_lte_eNB(RC.eNB[inst][cc_id]);
       }
     }
-    for (int inst = 0; inst < NB_RU; inst++) {
+    for (int inst = 0; inst < RC.nb_RU; inst++) {
       phy_free_RU(RC.ru[inst]);
     }
     free_lte_top();
@@ -1313,7 +1312,7 @@ int main( int argc, char **argv )
 
   // *** Handle per CC_id openair0
 
-    for(ru_id=0; ru_id<NB_RU; ru_id++) {
+    for(ru_id=0; ru_id<RC.nb_RU; ru_id++) {
       if (RC.ru[ru_id]->rfdevice.trx_end_func)
 	RC.ru[ru_id]->rfdevice.trx_end_func(&RC.ru[ru_id]->rfdevice);  
       if (RC.ru[ru_id]->ifdevice.trx_end_func)
diff --git a/targets/RT/USER/lte-softmodem.h b/targets/RT/USER/lte-softmodem.h
index c375d28106..87cda69951 100644
--- a/targets/RT/USER/lte-softmodem.h
+++ b/targets/RT/USER/lte-softmodem.h
@@ -52,6 +52,7 @@
 #define CONFIG_HLP_DBGUEPR       "UE run normal prach power ramping, but don't continue random-access\n"
 #define CONFIG_HLP_CALPRACH      "UE run normal prach with maximum power, but don't continue random-access\n"
 #define CONFIG_HLP_NOL2CN        "bypass L2 and upper layers\n"
+#define CONFIG_HLP_SIML1         "activate RF simulator instead of HW\n"
 #define CONFIG_HLP_UERXG         "set UE RX gain\n"
 #define CONFIG_HLP_UERXGOFF      "external UE amplifier offset\n"
 #define CONFIG_HLP_UETXG         "set UE TX gain\n"
@@ -131,6 +132,7 @@
 /*   optname                     helpstr             paramflags                      XXXptr                  defXXXval       type          numelt   */
 /*--------------------------------------------------------------------------------------------------------------------------------------------------*/
 #define CMDLINE_UEPARAMS_DESC {  \
+{"siml1",                      CONFIG_HLP_SIML1,      PARAMFLAG_BOOL,   iptr:&simL1flag,                    defintval:0,    TYPE_INT,      0}, \
 {"ue-rxgain",        	       CONFIG_HLP_UERXG,      0,		dblptr:&(rx_gain[0][0]),	    defdblval:0,    TYPE_DOUBLE,   0},     \
 {"ue-rxgain-off",    	       CONFIG_HLP_UERXGOFF,   0,		dblptr:&rx_gain_off,		    defdblval:0,    TYPE_DOUBLE,   0},     \
 {"ue-txgain",        	       CONFIG_HLP_UETXG,      0,		dblptr:&(tx_gain[0][0]),	    defdblval:0,    TYPE_DOUBLE,   0},     \
@@ -138,8 +140,8 @@
 {"ue-nb-ant-tx",     	       CONFIG_HLP_UENANTT,    0,		u8ptr:&nb_antenna_tx,		    defuintval:1,   TYPE_UINT8,    0},     \
 {"ue-scan-carrier",  	       CONFIG_HLP_UESCAN,     PARAMFLAG_BOOL,	iptr:&UE_scan_carrier,  	    defintval:0,    TYPE_INT,	   0},     \
 {"ue-max-power",     	       NULL,		      0,		iptr:&(tx_max_power[0]),	    defintval:90,   TYPE_INT,	   0},     \
-{"emul-iface",                 CONFIG_HLP_EMULIFACE,  0,                strptr:&emul_iface,                  defstrval:"lo", TYPE_STRING,   100}, \
-{"L2-emul",                 	NULL,  				  0,                u8ptr:&nfapi_mode,                  defuintval:3, TYPE_UINT8,   0}, \
+{"emul-iface",                 CONFIG_HLP_EMULIFACE,  0,                strptr:&emul_iface,                 defstrval:"lo", TYPE_STRING,   100},   \
+{"L2-emul",                    NULL,  		      0,                u8ptr:&nfapi_mode,                  defuintval:3, TYPE_UINT8,   0}, \
 {"num-ues",     	       		   NULL,		      	  0,				u8ptr:&(NB_UE_INST),	    defuintval:1,   	TYPE_UINT8,	   0},     \
 {"r"  ,                        CONFIG_HLP_PRB,        0,                u8ptr:&(frame_parms[0]->N_RB_DL),   defintval:25,   TYPE_UINT8,    0},     \
 {"dlsch-demod-shift",     	 CONFIG_HLP_DLSHIFT,	0,		  iptr:(int32_t *)&dlsch_demod_shift,	defintval:0,			   TYPE_INT,	  0},			   \
@@ -272,7 +274,7 @@ extern void set_function_spec_param(RU_t *ru);
 extern int setup_ue_buffers(PHY_VARS_UE **phy_vars_ue, openair0_config_t *openair0_cfg);
 extern void fill_ue_band_info(void);
 
-extern void init_UE(int,int,int,int);
+extern void init_UE(int nb_inst,int eMBMS_active, int uecap_xer_in, int timing_correction, int phy_test, int UE_scan, int UE_scan_carrier, runmode_t mode,int rxgain,int txpowermax, int nb_rx, int nb_tx);
 extern void init_thread(int sched_runtime, int sched_deadline, int sched_fifo, cpu_set_t *cpuset, char * name);
 
 extern void reset_opp_meas(void);
diff --git a/targets/RT/USER/lte-ue.c b/targets/RT/USER/lte-ue.c
index 492a17a365..c113b1264c 100644
--- a/targets/RT/USER/lte-ue.c
+++ b/targets/RT/USER/lte-ue.c
@@ -79,7 +79,7 @@ void init_UE_threads(int);
 void init_UE_threads_stub(int);
 void init_UE_single_thread_stub(int);
 void *UE_thread(void *arg);
-void init_UE(int nb_inst,int,int,int);
+void init_UE(int nb_inst,int eMBMS_active, int uecap_xer_in, int timing_correction, int phy_test, int UE_scan, int UE_scan_carrier, runmode_t mode,int rxgain,int txpowermax,int nb_rx,int nb_tx);
 void init_UE_stub(int nb_inst,int,int,char*);
 void init_UE_stub_single_thread(int nb_inst,int,int,char*);
 int init_timer_thread(void);
@@ -93,6 +93,8 @@ extern int oai_nfapi_sr_indication(nfapi_sr_indication_t *ind);
 extern int oai_nfapi_rx_ind(nfapi_rx_indication_t *ind);
 extern int multicast_link_write_sock(int groupP, char *dataP, uint32_t sizeP);
 
+extern int simL1flag;
+
 //extern int tx_req_UE_MAC1();
 
 void ue_stub_rx_handler(unsigned int, char *);
@@ -236,7 +238,7 @@ void init_thread(int sched_runtime, int sched_deadline, int sched_fifo, cpu_set_
 
 }
 
-void init_UE(int nb_inst,int eMBMS_active, int uecap_xer_in, int timing_correction) {
+void init_UE(int nb_inst,int eMBMS_active, int uecap_xer_in, int timing_correction, int phy_test, int UE_scan, int UE_scan_carrier, runmode_t mode,int rxgain,int txpowermax,int nb_rx,int nb_tx) {
 
   PHY_VARS_UE *UE;
   int         inst;
@@ -248,18 +250,58 @@ void init_UE(int nb_inst,int eMBMS_active, int uecap_xer_in, int timing_correcti
 	     0,// cba_group_active
 	     0); // HO flag
 
+  if (PHY_vars_UE_g==NULL) PHY_vars_UE_g = (PHY_VARS_UE***)calloc(1+nb_inst,sizeof(PHY_VARS_UE**));
+   
   for (inst=0;inst<nb_inst;inst++) {
-
-    LOG_I(PHY,"Initializing memory for UE instance %d (%p)\n",inst,PHY_vars_UE_g[inst]);
-    PHY_vars_UE_g[inst][0] = init_ue_vars(NULL,inst,0);
+    if (PHY_vars_UE_g[inst]==NULL) PHY_vars_UE_g[inst] = (PHY_VARS_UE**)calloc(1+MAX_NUM_CCs,sizeof(PHY_VARS_UE*));
+    if (simL1flag == 0) PHY_vars_UE_g[inst][0] = init_ue_vars(NULL,inst,0);
+    else                PHY_vars_UE_g[inst][0] = init_ue_vars(&RC.ru[0]->frame_parms,inst,0);
     // turn off timing control loop in UE
     PHY_vars_UE_g[inst][0]->no_timing_correction = timing_correction;
 
+    UE = PHY_vars_UE_g[inst][0];
+    printf("PHY_vars_UE_g[0][0] = %p\n",UE);
+
+    if (phy_test==1)
+      UE->mac_enabled = 0;
+    else
+      UE->mac_enabled = 1;
+
+    if (UE->mac_enabled == 0) {  //set default UL parameters for testing mode
+      for (int i=0; i<NUMBER_OF_CONNECTED_eNB_MAX; i++) {
+        UE->pusch_config_dedicated[i].betaOffset_ACK_Index = 0;
+        UE->pusch_config_dedicated[i].betaOffset_RI_Index  = 0;
+        UE->pusch_config_dedicated[i].betaOffset_CQI_Index = 2;
+        
+        UE->scheduling_request_config[i].sr_PUCCH_ResourceIndex = 0;
+        UE->scheduling_request_config[i].sr_ConfigIndex = 7+(0%3);
+        UE->scheduling_request_config[i].dsr_TransMax = sr_n4;
+      }
+    }
+
+    UE->UE_scan = UE_scan;
+    UE->UE_scan_carrier = UE_scan_carrier;
+    UE->mode    = mode;
+    printf("UE->mode = %d\n",mode);
+
+    if (UE->mac_enabled == 1) {
+      UE->pdcch_vars[0][0]->crnti = 0x1234;
+      UE->pdcch_vars[1][0]->crnti = 0x1234;
+    }else {
+      UE->pdcch_vars[0][0]->crnti = 0x1235;
+      UE->pdcch_vars[1][0]->crnti = 0x1235;
+    }
+    UE->rx_total_gain_dB =  rxgain;
+    UE->tx_power_max_dBm = txpowermax;
+
+    UE->frame_parms.nb_antennas_tx = nb_tx;
+    UE->frame_parms.nb_antennas_rx = nb_rx; 
+
+    if (simL1flag == 1) init_ue_devices();
     LOG_I(PHY,"Intializing UE Threads for instance %d (%p,%p)...\n",inst,PHY_vars_UE_g[inst],PHY_vars_UE_g[inst][0]);
     init_UE_threads(inst);
-    UE = PHY_vars_UE_g[inst][0];
 
-    if (oaisim_flag == 0) {
+    if (simL1flag == 0) {
       ret = openair0_device_load(&(UE->rfdevice), &openair0_cfg[0]);
       if (ret !=0){
 	exit_fun("Error loading device library");
@@ -443,9 +485,12 @@ static void *UE_thread_synch(void *arg)
     }
   }
 
+/*
   while (sync_var<0)
     pthread_cond_wait(&sync_cond, &sync_mutex);
   pthread_mutex_unlock(&sync_mutex);
+*/
+  wait_sync("UE_thread_sync");
 
   printf("Started device, unlocked sync_mutex (UE_sync_thread)\n");
 
@@ -1425,6 +1470,14 @@ void *UE_thread(void *arg) {
   init_thread(100000, 500000, FIFO_PRIORITY, &cpuset,
 	      "UHD Threads");
 
+  /*
+  while (sync_var<0)
+    pthread_cond_wait(&sync_cond, &sync_mutex);
+  pthread_mutex_unlock(&sync_mutex);
+  */
+
+  wait_sync("UE thread\n");
+  LOG_I(PHY,"UE_thread Got sync\n");
 #ifdef NAS_UE
   MessageDef *message_p;
   message_p = itti_alloc_new_message(TASK_NAS_UE, INITIALIZE_MESSAGE);
diff --git a/targets/RT/USER/lte-uesoftmodem.c b/targets/RT/USER/lte-uesoftmodem.c
index 4007542918..9b803009a2 100644
--- a/targets/RT/USER/lte-uesoftmodem.c
+++ b/targets/RT/USER/lte-uesoftmodem.c
@@ -156,6 +156,7 @@ static char                    *itti_dump_file = NULL;
 
 int UE_scan = 1;
 int UE_scan_carrier = 0;
+int simL1flag = 0;
 runmode_t mode = normal_txrx;
 
 FILE *input_fd=NULL;
@@ -212,6 +213,7 @@ uint8_t exit_missed_slots=1;
 uint64_t num_missed_slots=0; // counter for the number of missed slots
 
 
+extern void init_ue_devices();
 extern void reset_opp_meas(void);
 extern void print_opp_meas(void);
 extern void init_UE_stub_single_thread(int nb_inst,int eMBMS_active, int uecap_xer_in, char *emul_iface);
@@ -452,11 +454,11 @@ void *l2l1_task(void *arg) {
       break;
 
     case MESSAGE_TEST:
-      LOG_I(EMU, "Received %s\n", ITTI_MSG_NAME(message_p));
+      LOG_I(SIM, "Received %s\n", ITTI_MSG_NAME(message_p));
       break;
 
     default:
-      LOG_E(EMU, "Received unexpected message %s\n", ITTI_MSG_NAME(message_p));
+      LOG_E(SIM, "Received unexpected message %s\n", ITTI_MSG_NAME(message_p));
       break;
     }
 
@@ -539,8 +541,7 @@ static void get_options(void) {
   }
   UE_scan=0;
    
-
-  if (tddflag > 0) {
+    if (tddflag > 0) {
      for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) 
     	 frame_parms[CC_id]->frame_type = TDD;
   }
@@ -581,7 +582,7 @@ static void get_options(void) {
   paramdef_t cmdline_ttraceparams[] =CMDLINE_TTRACEPARAMS_DESC ;
   config_process_cmdline( cmdline_ttraceparams,sizeof(cmdline_ttraceparams)/sizeof(paramdef_t),NULL);   
 #endif
-
+  /*
   if ( !(CONFIG_ISFLAGSET(CONFIG_ABORT))  && (!(CONFIG_ISFLAGSET(CONFIG_NOOOPT))) ) {
     // Here the configuration file is the XER encoded UE capabilities
     // Read it in and store in asn1c data structures
@@ -589,7 +590,7 @@ static void get_options(void) {
     printf("%s\n",uecap_xer);
     if(nfapi_mode!=3)
     	uecap_xer_in=1;
-  } /* UE with config file  */
+	} *//* UE with config file  */
 }
 
 
@@ -648,7 +649,7 @@ void set_default_frame_parms(LTE_DL_FRAME_PARMS *frame_parms[MAX_NUM_CCs]) {
 
 }
 
-void init_openair0(void) {
+void init_openair0(LTE_DL_FRAME_PARMS *frame_parms,int rxgain) {
 
   int card;
   int i;
@@ -658,8 +659,8 @@ void init_openair0(void) {
     openair0_cfg[card].mmapped_dma=mmapped_dma;
     openair0_cfg[card].configFilename = NULL;
 
-    if(frame_parms[0]->N_RB_DL == 100) {
-      if (frame_parms[0]->threequarter_fs) {
+    if(frame_parms->N_RB_DL == 100) {
+      if (frame_parms->threequarter_fs) {
 	openair0_cfg[card].sample_rate=23.04e6;
 	openair0_cfg[card].samples_per_frame = 230400;
 	openair0_cfg[card].tx_bw = 10e6;
@@ -670,17 +671,17 @@ void init_openair0(void) {
 	openair0_cfg[card].tx_bw = 10e6;
 	openair0_cfg[card].rx_bw = 10e6;
       }
-    } else if(frame_parms[0]->N_RB_DL == 50) {
+    } else if(frame_parms->N_RB_DL == 50) {
       openair0_cfg[card].sample_rate=15.36e6;
       openair0_cfg[card].samples_per_frame = 153600;
       openair0_cfg[card].tx_bw = 5e6;
       openair0_cfg[card].rx_bw = 5e6;
-    } else if (frame_parms[0]->N_RB_DL == 25) {
+    } else if (frame_parms->N_RB_DL == 25) {
       openair0_cfg[card].sample_rate=7.68e6;
       openair0_cfg[card].samples_per_frame = 76800;
       openair0_cfg[card].tx_bw = 2.5e6;
       openair0_cfg[card].rx_bw = 2.5e6;
-    } else if (frame_parms[0]->N_RB_DL == 6) {
+    } else if (frame_parms->N_RB_DL == 6) {
       openair0_cfg[card].sample_rate=1.92e6;
       openair0_cfg[card].samples_per_frame = 19200;
       openair0_cfg[card].tx_bw = 1.5e6;
@@ -690,23 +691,20 @@ void init_openair0(void) {
 
 
 
-    if (frame_parms[0]->frame_type==TDD)
+    if (frame_parms->frame_type==TDD)
       openair0_cfg[card].duplex_mode = duplex_mode_TDD;
     else //FDD
       openair0_cfg[card].duplex_mode = duplex_mode_FDD;
 
-    printf("HW: Configuring card %d, nb_antennas_tx/rx %d/%d\n",card,
-	   PHY_vars_UE_g[0][0]->frame_parms.nb_antennas_tx,
-	   PHY_vars_UE_g[0][0]->frame_parms.nb_antennas_rx);
     openair0_cfg[card].Mod_id = 0;
 
-    openair0_cfg[card].num_rb_dl=frame_parms[0]->N_RB_DL;
+    openair0_cfg[card].num_rb_dl=frame_parms->N_RB_DL;
 
     openair0_cfg[card].clock_source = clock_source;
 
 
-    openair0_cfg[card].tx_num_channels=min(2,PHY_vars_UE_g[0][0]->frame_parms.nb_antennas_tx);
-    openair0_cfg[card].rx_num_channels=min(2,PHY_vars_UE_g[0][0]->frame_parms.nb_antennas_rx);
+    openair0_cfg[card].tx_num_channels=min(2,frame_parms->nb_antennas_tx);
+    openair0_cfg[card].rx_num_channels=min(2,frame_parms->nb_antennas_rx);
 
     for (i=0; i<4; i++) {
 
@@ -722,7 +720,7 @@ void init_openair0(void) {
 
       openair0_cfg[card].autocal[i] = 1;
       openair0_cfg[card].tx_gain[i] = tx_gain[0][i];
-      openair0_cfg[card].rx_gain[i] = PHY_vars_UE_g[0][0]->rx_total_gain_dB - rx_gain_off;
+      openair0_cfg[card].rx_gain[i] = rxgain - rx_gain_off;
      
 
       openair0_cfg[card].configFilename = rf_config_file;
@@ -789,7 +787,6 @@ int main( int argc, char **argv )
 
   int CC_id;
   uint8_t  abstraction_flag=0;
-  uint8_t beta_ACK=0,beta_RI=0,beta_CQI=2;
 
   // Default value for the number of UEs. It will hold,
   // if not changed from the command line option --num-ues
@@ -809,7 +806,6 @@ int main( int argc, char **argv )
   setvbuf(stderr, NULL, _IONBF, 0);
 #endif
 
-  PHY_VARS_UE *UE[MAX_NUM_CCs];
 
   mode = normal_txrx;
   memset(&openair0_cfg[0],0,sizeof(openair0_config_t)*MAX_CARDS);
@@ -857,7 +853,7 @@ int main( int argc, char **argv )
     set_comp_log(OTG,     LOG_INFO,   LOG_HIGH, 1);
     set_comp_log(RRC,     LOG_INFO,   LOG_HIGH, 1);
 #if defined(ENABLE_ITTI)
-    set_comp_log(EMU,     LOG_INFO,   LOG_MED, 1);
+    set_comp_log(SIM,     LOG_INFO,   LOG_MED, 1);
 # if defined(ENABLE_USE_MME)
     set_comp_log(NAS,     LOG_INFO,   LOG_HIGH, 1);
 # endif
@@ -934,33 +930,6 @@ int main( int argc, char **argv )
 
 
 
-  printf("Before CC \n");
-
-
-
-  // Panos: From old version
-  /*if (UE_flag==1) {
-	  PHY_vars_UE_g = malloc(sizeof(PHY_VARS_UE**)*NB_UE_INST);
-	  for (int i=0; i<NB_UE_INST; i++) {
-		  for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
-
-			  PHY_vars_UE_g[i] = malloc(sizeof(PHY_VARS_UE*)*MAX_NUM_CCs);
-			  PHY_vars_UE_g[i][CC_id] = init_ue_vars(frame_parms[CC_id], i,abstraction_flag);
-
-			  UE[CC_id] = PHY_vars_UE_g[i][CC_id];
-			  printf("PHY_vars_UE_g[inst][%d] = %p\n",CC_id,UE[CC_id]);
-
-			  if (phy_test==1)
-				  UE[CC_id]->mac_enabled = 0;
-			  else
-				  UE[CC_id]->mac_enabled = 1;
-		  }
-	  }
-  }*/
-
-
-
-  //NB_UE_INST=1;
   NB_INST=1;
   if(nfapi_mode == 3){
 	  PHY_vars_UE_g = malloc(sizeof(PHY_VARS_UE**)*NB_UE_INST);
@@ -969,80 +938,59 @@ int main( int argc, char **argv )
 	  			PHY_vars_UE_g[i] = malloc(sizeof(PHY_VARS_UE*)*MAX_NUM_CCs);
 	  			PHY_vars_UE_g[i][CC_id] = init_ue_vars(frame_parms[CC_id], i,abstraction_flag);
 
-	  			UE[CC_id] = PHY_vars_UE_g[i][CC_id];
-	  			printf("PHY_vars_UE_g[inst][%d] = %p\n",CC_id,UE[CC_id]);
+	  			 PHY_vars_UE_g[i][CC_id];
 
 	  			if (phy_test==1)
-	  				UE[CC_id]->mac_enabled = 0;
+	  				PHY_vars_UE_g[i][CC_id]->mac_enabled = 0;
 	  			else
-	  				UE[CC_id]->mac_enabled = 1;
+	  				PHY_vars_UE_g[i][CC_id]->mac_enabled = 1;
 	  		}
 	  	  }
   }
-  else{
+  else init_openair0(frame_parms[0],(int)rx_gain[0][0]);
 
 
-  for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
-      //NB_UE_INST=1;
-      NB_INST=1;
-      PHY_vars_UE_g = malloc(sizeof(PHY_VARS_UE**));
-      PHY_vars_UE_g[0] = malloc(sizeof(PHY_VARS_UE*)*MAX_NUM_CCs);
-      PHY_vars_UE_g[0][CC_id] = init_ue_vars(frame_parms[CC_id], 0,abstraction_flag);
-      UE[CC_id] = PHY_vars_UE_g[0][CC_id];
-      printf("PHY_vars_UE_g[0][%d] = %p\n",CC_id,UE[CC_id]);
-
-      if (phy_test==1)
-	UE[CC_id]->mac_enabled = 0;
-      else
-	UE[CC_id]->mac_enabled = 1;
-
-      if (UE[CC_id]->mac_enabled == 0) {  //set default UL parameters for testing mode
-	for (i=0; i<NUMBER_OF_CONNECTED_eNB_MAX; i++) {
-	  UE[CC_id]->pusch_config_dedicated[i].betaOffset_ACK_Index = beta_ACK;
-	  UE[CC_id]->pusch_config_dedicated[i].betaOffset_RI_Index  = beta_RI;
-	  UE[CC_id]->pusch_config_dedicated[i].betaOffset_CQI_Index = beta_CQI;
-	  
-	  UE[CC_id]->scheduling_request_config[i].sr_PUCCH_ResourceIndex = 0;
-	  UE[CC_id]->scheduling_request_config[i].sr_ConfigIndex = 7+(0%3);
-	  UE[CC_id]->scheduling_request_config[i].dsr_TransMax = sr_n4;
-	}
-      }
+  if (simL1flag==1) {
+    AssertFatal(NULL!=load_configmodule(argc,argv),
+                "[SOFTMODEM] Error, configuration module init failed\n");
 
-      UE[CC_id]->UE_scan = UE_scan;
-      UE[CC_id]->UE_scan_carrier = UE_scan_carrier;
-      UE[CC_id]->mode    = mode;
-      printf("UE[%d]->mode = %d\n",CC_id,mode);
-
-      if (UE[CC_id]->mac_enabled == 1) {
-	UE[CC_id]->pdcch_vars[0][0]->crnti = 0x1234;
-	UE[CC_id]->pdcch_vars[1][0]->crnti = 0x1234;
-      }else {
-	UE[CC_id]->pdcch_vars[0][0]->crnti = 0x1235;
-	UE[CC_id]->pdcch_vars[1][0]->crnti = 0x1235;
-      }
-      UE[CC_id]->rx_total_gain_dB =  (int)rx_gain[CC_id][0] + rx_gain_off;
-      UE[CC_id]->tx_power_max_dBm = tx_max_power[CC_id];
+    RCConfig_sim();
+  }
 
-      if (frame_parms[CC_id]->frame_type==FDD) {
-	UE[CC_id]->N_TA_offset = 0;
-      }
-      else {
-	if (frame_parms[CC_id]->N_RB_DL == 100)
-	  UE[CC_id]->N_TA_offset = 624;
-	else if (frame_parms[CC_id]->N_RB_DL == 50)
-	  UE[CC_id]->N_TA_offset = 624/2;
-	else if (frame_parms[CC_id]->N_RB_DL == 25)
-	  UE[CC_id]->N_TA_offset = 624/4;
+  // start the main UE threads
+  int eMBMS_active = 0;
 
-    }
-    init_openair0();
+  if (nfapi_mode==3) // UE-STUB-PNF
+  {
+      config_sync_var=0;
+      wait_nfapi_init("main?");
+      //Panos: Temporarily we will be using single set of threads for multiple UEs.
+      //init_UE_stub(1,eMBMS_active,uecap_xer_in,emul_iface);
+      init_UE_stub_single_thread(NB_UE_INST,eMBMS_active,uecap_xer_in,emul_iface);
+  }
+  else {
+      init_UE(1,eMBMS_active,uecap_xer_in,0,phy_test,UE_scan,UE_scan_carrier,mode,(int)rx_gain[0][0],tx_max_power,
+              frame_parms[0]->nb_antennas_rx,
+              frame_parms[0]->nb_antennas_tx);
   }
 
 
-  printf("Runtime table\n");
-  fill_modeled_runtime_table(runtime_phy_rx,runtime_phy_tx);
-  cpuf=get_cpu_freq_GHz();
+  if (phy_test==0) {
+    printf("Filling UE band info\n");
+    fill_ue_band_info();
+    dl_phy_sync_success (0, 0, 0, 1);
+  }
+
+  if (nfapi_mode!=3){
+      number_of_cards = 1;
+      for(CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
+              PHY_vars_UE_g[0][CC_id]->rf_map.card=0;
+              PHY_vars_UE_g[0][CC_id]->rf_map.chain=CC_id+chain_offset;
+      }
   }
+
+  
+  cpuf=get_cpu_freq_GHz();
   
   
   
@@ -1099,8 +1047,8 @@ int main( int argc, char **argv )
 #endif
 
   // init UE_PF_PO and mutex lock
-  pthread_mutex_init(&ue_pf_po_mutex, NULL);
-  memset (&UE_PF_PO[0][0], 0, sizeof(UE_PF_PO_t)*NUMBER_OF_UE_MAX*MAX_NUM_CCs);
+    //  pthread_mutex_init(&ue_pf_po_mutex, NULL);
+    //  memset (&UE_PF_PO[0][0], 0, sizeof(UE_PF_PO_t)*NUMBER_OF_UE_MAX*MAX_NUM_CCs);
   
   mlockall(MCL_CURRENT | MCL_FUTURE);
   
@@ -1170,74 +1118,41 @@ int main( int argc, char **argv )
     printf("NFAPI MODE:%s\n", nfapi_mode_str);
 
 
-  // start the main threads
-    int eMBMS_active = 0;
-
-    if (nfapi_mode==3) // UE-STUB-PNF
-    {
-    	config_sync_var=0;
-    	wait_nfapi_init("main?");
-    	//Panos: Temporarily we will be using single set of threads for multiple UEs.
-    	//init_UE_stub(1,eMBMS_active,uecap_xer_in,emul_iface);
-    	init_UE_stub_single_thread(NB_UE_INST,eMBMS_active,uecap_xer_in,emul_iface);
-    }
-    else {
-    	init_UE(1,eMBMS_active,uecap_xer_in,0);
-    }
-
-    if (phy_test==0) {
-      printf("Filling UE band info\n");
-      fill_ue_band_info();
-      dl_phy_sync_success (0, 0, 0, 1);
-    }
-
-    if (nfapi_mode!=3){
-    	number_of_cards = 1;
-    	for(CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
-    		PHY_vars_UE_g[0][CC_id]->rf_map.card=0;
-    		PHY_vars_UE_g[0][CC_id]->rf_map.chain=CC_id+chain_offset;
-    	}
-    }
-
 
   
   // connect the TX/RX buffers
 
-    for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
       
-      
-#ifdef OAI_USRP
-      UE[CC_id]->hw_timing_advance = timing_advance;
-#else
-      UE[CC_id]->hw_timing_advance = 160;
-#endif
-    }
+    /*  
     if(nfapi_mode!=3) {
-    	if (setup_ue_buffers(UE,&openair0_cfg[0])!=0) {
+    	if (setup_ue_buffers(PHY_vars_UE_g[0],&openair0_cfg[0])!=0) {
     		printf("Error setting up eNB buffer\n");
     		exit(-1);
     	}
     }
-    
+   */ 
     
     
 
     if (input_fd) {
       printf("Reading in from file to antenna buffer %d\n",0);
-      if (fread(UE[0]->common_vars.rxdata[0],
+      if (fread(PHY_vars_UE_g[0][0]->common_vars.rxdata[0],
 		sizeof(int32_t),
 		frame_parms[0]->samples_per_tti*10,
 		input_fd) != frame_parms[0]->samples_per_tti*10)
 	printf("error reading from file\n");
     }
     //p_exmimo_config->framing.tdd_config = TXRXSWITCH_TESTRX;
-  
+ 
+  if (simL1flag==1) init_ocm();
+ 
   printf("Sending sync to all threads\n");
   
   pthread_mutex_lock(&sync_mutex);
   sync_var=0;
   pthread_cond_broadcast(&sync_cond);
   pthread_mutex_unlock(&sync_mutex);
+
   printf("About to call end_configmodule() from %s() %s:%d\n", __FUNCTION__, __FILE__, __LINE__);
   end_configmodule();
   printf("Called end_configmodule() from %s() %s:%d\n", __FUNCTION__, __FILE__, __LINE__);
@@ -1246,6 +1161,7 @@ int main( int argc, char **argv )
   printf("TYPE <CTRL-C> TO TERMINATE\n");
   //getchar();
 
+
 #if defined(ENABLE_ITTI)
   printf("Entering ITTI signals handler\n");
   itti_wait_tasks_end();
@@ -1254,9 +1170,9 @@ int main( int argc, char **argv )
   printf("oai_exit=%d\n",oai_exit);
 #else
 
-  while (oai_exit==0)
-    rt_sleep_ns(100000000ULL);
-  printf("Terminating application - oai_exit=%d\n",oai_exit);
+    while (oai_exit==0)
+      rt_sleep_ns(100000000ULL);
+    printf("Terminating application - oai_exit=%d\n",oai_exit);
 
 #endif
 
@@ -1279,7 +1195,7 @@ int main( int argc, char **argv )
   pthread_cond_destroy(&sync_cond);
   pthread_mutex_destroy(&sync_mutex);
 
-  pthread_mutex_destroy(&ue_pf_po_mutex);
+  //  pthread_mutex_destroy(&ue_pf_po_mutex);
 
   // *** Handle per CC_id openair0
   if (PHY_vars_UE_g[0][0]->rfdevice.trx_end_func)
diff --git a/targets/RT/USER/rfsim.c b/targets/RT/USER/rfsim.c
new file mode 100644
index 0000000000..32897c5c2c
--- /dev/null
+++ b/targets/RT/USER/rfsim.c
@@ -0,0 +1,580 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+/*! \file rfsim.c
+* \brief function for simulated RF device
+* \author R. Knopp
+* \date 2018
+* \version 1.0
+* \company Eurecom
+* \email: openair_tech@eurecom.fr
+* \note
+* \warning
+*/
+
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <signal.h>
+#include <execinfo.h>
+#include <time.h>
+#include <mcheck.h>
+#include <sys/timerfd.h>
+
+#include "assertions.h"
+#include "rfsim.h"
+#include "openair1/SIMULATION/TOOLS/sim.h"
+#include "enb_config.h"
+#include "enb_paramdef.h"
+#include "platform_constants.h"
+#include "common/config/config_paramdesc.h"
+#include "common/config/config_userapi.h"
+#include "common/ran_context.h"
+#include "PHY/defs_UE.h"
+#include "PHY/defs_eNB.h"
+
+RAN_CONTEXT_t RC;
+extern PHY_VARS_UE ***PHY_vars_UE_g;
+
+
+// put all of these in a common structure after
+channel_desc_t *RU2UE[NUMBER_OF_RU_MAX][NUMBER_OF_UE_MAX][MAX_NUM_CCs];
+channel_desc_t *UE2RU[NUMBER_OF_UE_MAX][NUMBER_OF_RU_MAX][MAX_NUM_CCs];
+double r_re_DL[NUMBER_OF_UE_MAX][2][30720];
+double r_im_DL[NUMBER_OF_UE_MAX][2][30720];
+double r_re_UL[NUMBER_OF_eNB_MAX][2][30720];
+double r_im_UL[NUMBER_OF_eNB_MAX][2][30720];
+int RU_output_mask[NUMBER_OF_UE_MAX];
+int UE_output_mask[NUMBER_OF_RU_MAX];
+pthread_mutex_t RU_output_mutex[NUMBER_OF_UE_MAX];
+pthread_mutex_t UE_output_mutex[NUMBER_OF_RU_MAX];
+pthread_mutex_t subframe_mutex;
+int subframe_ru_mask=0,subframe_UE_mask=0;
+openair0_timestamp current_ru_rx_timestamp[NUMBER_OF_RU_MAX][MAX_NUM_CCs];
+openair0_timestamp current_UE_rx_timestamp[MAX_MOBILES_PER_ENB][MAX_NUM_CCs];
+openair0_timestamp last_ru_rx_timestamp[NUMBER_OF_RU_MAX][MAX_NUM_CCs];
+openair0_timestamp last_UE_rx_timestamp[MAX_MOBILES_PER_ENB][MAX_NUM_CCs];
+double ru_amp[NUMBER_OF_RU_MAX];
+pthread_t rfsim_thread;
+
+
+void init_ru_devices(void);
+void init_RU(const char*);
+void rfsim_top(void *n_frames);
+
+void wait_RUs(void)
+{
+  int i;
+  
+  // wait for all RUs to be configured over fronthaul
+  pthread_mutex_lock(&RC.ru_mutex);
+  
+  
+  
+  while (RC.ru_mask>0) {
+    pthread_cond_wait(&RC.ru_cond,&RC.ru_mutex);
+  }
+  
+  // copy frame parameters from RU to UEs
+  for (i=0;i<NB_UE_INST;i++) {
+/*
+    PHY_vars_UE_g[i][0]->frame_parms.N_RB_DL              = RC.ru[0]->frame_parms.N_RB_DL;
+    PHY_vars_UE_g[i][0]->frame_parms.N_RB_UL              = RC.ru[0]->frame_parms.N_RB_UL;
+    PHY_vars_UE_g[i][0]->frame_parms.nb_antennas_tx       = 1;
+    PHY_vars_UE_g[i][0]->frame_parms.nb_antennas_rx       = 1;
+    // set initially to 2, it will be revised after initial synchronization
+    PHY_vars_UE_g[i][0]->frame_parms.nb_antenna_ports_eNB = 2;
+    PHY_vars_UE_g[i][0]->frame_parms.tdd_config = 1;
+    PHY_vars_UE_g[i][0]->frame_parms.dl_CarrierFreq       = RC.ru[0]->frame_parms.dl_CarrierFreq;
+    PHY_vars_UE_g[i][0]->frame_parms.ul_CarrierFreq       = RC.ru[0]->frame_parms.ul_CarrierFreq;
+    PHY_vars_UE_g[i][0]->frame_parms.eutra_band           = RC.ru[0]->frame_parms.eutra_band;
+    LOG_I(PHY,"Initializing UE %d frame parameters from RU information: N_RB_DL %d, p %d, dl_Carrierfreq %u, ul_CarrierFreq %u, eutra_band %d\n",
+          i,
+          PHY_vars_UE_g[i][0]->frame_parms.N_RB_DL,
+          PHY_vars_UE_g[i][0]->frame_parms.nb_antenna_ports_eNB,
+          PHY_vars_UE_g[i][0]->frame_parms.dl_CarrierFreq,
+          PHY_vars_UE_g[i][0]->frame_parms.ul_CarrierFreq,
+          PHY_vars_UE_g[i][0]->frame_parms.eutra_band);
+
+*/
+
+    current_UE_rx_timestamp[i][0] = RC.ru[0]->frame_parms.samples_per_tti + RC.ru[0]->frame_parms.ofdm_symbol_size + RC.ru[0]->frame_parms.nb_prefix_samples0;
+
+  }
+
+  for (int ru_id=0;ru_id<RC.nb_RU;ru_id++) current_ru_rx_timestamp[ru_id][0] = RC.ru[ru_id]->frame_parms.samples_per_tti;
+
+  printf("RUs are ready, let's go\n");
+}
+
+void wait_eNBs(void)
+{
+  return;
+}
+
+
+void RCConfig_sim(void) {
+
+  paramlist_def_t RUParamList = {CONFIG_STRING_RU_LIST,NULL,0};
+
+  //  AssertFatal(RC.config_file_name!=NULL,"configuration file is undefined\n");
+
+  // Get num RU instances
+  config_getlist( &RUParamList,NULL,0, NULL);
+  RC.nb_RU     = RUParamList.numelt;
+  
+  printf("returned with %d rus\n",RC.nb_RU);
+  
+  init_RU(NULL);
+
+  printf("Waiting for RUs to get set up\n"); 
+  wait_RUs();
+
+  init_ru_devices();
+
+  int nframes = 100000;
+ 
+  AssertFatal(0 == pthread_create(&rfsim_thread,
+                                  NULL,
+                                  rfsim_top,
+                                  (void*)&nframes), "");
+
+}
+
+
+
+int ru_trx_start(openair0_device *device) {
+  return(0);
+}
+
+void ru_trx_end(openair0_device *device) {
+  return;
+}
+
+int ru_trx_stop(openair0_device *device) {
+  return(0);
+}
+int UE_trx_start(openair0_device *device) {
+  return(0);
+}
+void UE_trx_end(openair0_device *device) {
+  return;
+}
+int UE_trx_stop(openair0_device *device) {
+  return(0);
+}
+int ru_trx_set_freq(openair0_device *device, openair0_config_t *openair0_cfg, int dummy) {
+  return(0);
+}
+int ru_trx_set_gains(openair0_device *device, openair0_config_t *openair0_cfg) {
+  return(0);
+}
+int UE_trx_set_freq(openair0_device *device, openair0_config_t *openair0_cfg, int dummy) {
+  return(0);
+}
+int UE_trx_set_gains(openair0_device *device, openair0_config_t *openair0_cfg) {
+  return(0);
+}
+
+extern pthread_mutex_t subframe_mutex;
+extern int subframe_ru_mask,subframe_UE_mask;
+
+
+int ru_trx_read(openair0_device *device, openair0_timestamp *ptimestamp, void **buff, int nsamps, int cc) {
+
+  int ru_id  = device->Mod_id;
+  int CC_id  = device->CC_id;
+
+  int subframe;
+  int sample_count=0;
+
+  *ptimestamp = last_ru_rx_timestamp[ru_id][CC_id];
+
+
+  LOG_D(SIM,"RU_trx_read nsamps %d TS(%llu,%llu) => subframe %d\n",nsamps,
+        (unsigned long long)current_ru_rx_timestamp[ru_id][CC_id],
+        (unsigned long long)last_ru_rx_timestamp[ru_id][CC_id],
+	(int)((*ptimestamp/RC.ru[ru_id]->frame_parms.samples_per_tti)%10));
+  // if we're at a subframe boundary generate UL signals for this ru
+
+  while (sample_count<nsamps) {
+    while (current_ru_rx_timestamp[ru_id][CC_id]<
+	   (nsamps+last_ru_rx_timestamp[ru_id][CC_id])) {
+      LOG_D(SIM,"RU: current TS %"PRIi64", last TS %"PRIi64", sleeping\n",current_ru_rx_timestamp[ru_id][CC_id],last_ru_rx_timestamp[ru_id][CC_id]);
+      usleep(500);
+    }
+
+    
+    subframe = (last_ru_rx_timestamp[ru_id][CC_id]/RC.ru[ru_id]->frame_parms.samples_per_tti)%10;
+    if (subframe_select(&RC.ru[ru_id]->frame_parms,subframe) != SF_DL || RC.ru[ru_id]->frame_parms.frame_type == FDD) { 
+      LOG_D(SIM,"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,
+		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;
+  }
+  
+
+  return(nsamps);
+}
+
+int UE_trx_read(openair0_device *device, openair0_timestamp *ptimestamp, void **buff, int nsamps, int cc)
+{
+  int UE_id = device->Mod_id;
+  int CC_id  = device->CC_id;
+
+  int subframe;
+  int sample_count=0;
+  int read_size;
+  int sptti = PHY_vars_UE_g[UE_id][CC_id]->frame_parms.samples_per_tti;
+
+  *ptimestamp = last_UE_rx_timestamp[UE_id][CC_id];
+
+  LOG_D(SIM,"UE %d DL simulation 0: UE_trx_read nsamps %d TS %llu (%llu, offset %d) antenna %d\n",
+        UE_id,
+        nsamps,
+        (unsigned long long)current_UE_rx_timestamp[UE_id][CC_id],
+        (unsigned long long)last_UE_rx_timestamp[UE_id][CC_id],
+        (int)(last_UE_rx_timestamp[UE_id][CC_id]%sptti),
+	cc);
+
+
+  if (nsamps < sptti)
+    read_size = nsamps;
+  else
+    read_size = sptti;
+
+  while (sample_count<nsamps) {
+    LOG_D(SIM,"UE %d: DL simulation 1: UE_trx_read : current TS now %"PRIi64", last TS %"PRIi64"\n",UE_id,current_UE_rx_timestamp[UE_id][CC_id],last_UE_rx_timestamp[UE_id][CC_id]);
+    while (current_UE_rx_timestamp[UE_id][CC_id] < 
+	   (last_UE_rx_timestamp[UE_id][CC_id]+read_size)) {
+      LOG_D(SIM,"UE %d: DL simulation 2: UE_trx_read : current TS %"PRIi64", last TS %"PRIi64", sleeping\n",UE_id,current_UE_rx_timestamp[UE_id][CC_id],last_UE_rx_timestamp[UE_id][CC_id]);
+      usleep(500);
+    }
+    LOG_D(SIM,"UE %d: DL simulation 3: UE_trx_read : current TS now %"PRIi64", last TS %"PRIi64"\n",UE_id,current_UE_rx_timestamp[UE_id][CC_id],last_UE_rx_timestamp[UE_id][CC_id]);
+
+    // if we cross a subframe-boundary
+    subframe = (last_UE_rx_timestamp[UE_id][CC_id]/sptti)%10;
+
+    // tell top-level we are busy 
+    pthread_mutex_lock(&subframe_mutex);
+    subframe_UE_mask|=(1<<UE_id);
+    LOG_D(SIM,"Setting UE_id %d mask to busy (%d)\n",UE_id,subframe_UE_mask);
+    pthread_mutex_unlock(&subframe_mutex);
+    
+    
+
+    LOG_D(PHY,"UE %d: DL simulation 4: UE_trx_read generating DL subframe %d (Ts %llu, current TS %llu,nsamps %d)\n",
+	  UE_id,subframe,(unsigned long long)*ptimestamp,
+	  (unsigned long long)current_UE_rx_timestamp[UE_id][CC_id],
+	  nsamps);
+
+    LOG_D(SIM,"UE %d: DL simulation 5: Doing DL simulation for %d samples starting in subframe %d at offset %d\n",
+	  UE_id,nsamps,subframe,
+	  (int)(last_UE_rx_timestamp[UE_id][CC_id]%sptti));
+
+    do_DL_sig(RU2UE,
+	      subframe,
+	      last_UE_rx_timestamp[UE_id][CC_id]%sptti,
+	      sptti,
+	      0, //abstraction_flag,
+	      &PHY_vars_UE_g[UE_id][CC_id]->frame_parms,
+	      UE_id,
+	      CC_id);
+    LOG_D(SIM,"UE %d: DL simulation 6: UE_trx_read @ TS %"PRIi64" (%"PRIi64")=> frame %d, subframe %d\n",
+	  UE_id, current_UE_rx_timestamp[UE_id][CC_id],
+	  last_UE_rx_timestamp[UE_id][CC_id],
+	  (int)((last_UE_rx_timestamp[UE_id][CC_id]/(sptti*10))&1023),
+	  subframe);
+
+    last_UE_rx_timestamp[UE_id][CC_id] += read_size;
+    sample_count += read_size;
+ 
+
+
+
+  }
+
+
+  return(nsamps);
+}
+
+extern double ru_amp[NUMBER_OF_RU_MAX];
+
+int ru_trx_write(openair0_device *device,openair0_timestamp timestamp, void **buff, int nsamps, int cc, int flags) {
+
+  int ru_id = device->Mod_id;
+
+  LTE_DL_FRAME_PARMS *frame_parms = &RC.ru[ru_id]->frame_parms;
+
+  pthread_mutex_lock(&subframe_mutex);
+  LOG_D(SIM,"[TXPATH] ru_trx_write: RU %d mask %d\n",ru_id,subframe_ru_mask);
+  pthread_mutex_unlock(&subframe_mutex); 
+
+  // compute amplitude of TX signal from first symbol in subframe
+  // note: assumes that the packet is an entire subframe 
+
+  ru_amp[ru_id] = 0;
+  for (int aa=0; aa<RC.ru[ru_id]->nb_tx; aa++) {
+    ru_amp[ru_id] += (double)signal_energy((int32_t*)buff[aa],frame_parms->ofdm_symbol_size)/(12*frame_parms->N_RB_DL);
+  }
+  ru_amp[ru_id] = sqrt(ru_amp[ru_id]);
+
+  LOG_D(SIM,"Setting amp for RU %d to %f (%d)\n",ru_id,ru_amp[ru_id], dB_fixed((double)signal_energy((int32_t*)buff[0],frame_parms->ofdm_symbol_size)));
+  // tell top-level we are done
+  pthread_mutex_lock(&subframe_mutex);
+  subframe_ru_mask|=(1<<ru_id);
+  LOG_D(SIM,"Setting RU %d to busy\n",ru_id);
+  pthread_mutex_unlock(&subframe_mutex);
+
+  return(nsamps);
+}
+
+int UE_trx_write(openair0_device *device,openair0_timestamp timestamp, void **buff, int nsamps, int cc, int flags) {
+
+  return(nsamps);
+}
+
+void init_ru_devices(){
+
+
+  module_id_t ru_id;
+  RU_t *ru;
+
+  // allocate memory for RU if not already done
+  if (RC.ru==NULL) RC.ru = (RU_t**)malloc(RC.nb_RU*sizeof(RU_t*));
+
+  for (ru_id=0;ru_id<RC.nb_RU;ru_id++) {
+    LOG_I(SIM,"Initiaizing rfdevice for RU %d\n",ru_id);
+    if (RC.ru[ru_id]==NULL) RC.ru[ru_id] = (RU_t*)malloc(sizeof(RU_t));
+    ru               = RC.ru[ru_id];
+    ru->rfdevice.Mod_id             = ru_id;
+    ru->rfdevice.CC_id              = 0;
+    ru->rfdevice.trx_start_func     = ru_trx_start;
+    ru->rfdevice.trx_read_func      = ru_trx_read;
+    ru->rfdevice.trx_write_func     = ru_trx_write;
+    ru->rfdevice.trx_end_func       = ru_trx_end;
+    ru->rfdevice.trx_stop_func      = ru_trx_stop;
+    ru->rfdevice.trx_set_freq_func  = ru_trx_set_freq;
+    ru->rfdevice.trx_set_gains_func = ru_trx_set_gains;
+    last_ru_rx_timestamp[ru_id][0] = 0;
+
+  }
+}
+
+init_ue_devices() {
+
+  AssertFatal(PHY_vars_UE_g!=NULL,"Top-level structure for UE is null\n");
+  for (int UE_id=0;UE_id<NB_UE_INST;UE_id++) {
+    AssertFatal(PHY_vars_UE_g[UE_id]!=NULL,"UE %d context is not allocated\n");
+    printf("Initializing UE %d\n",UE_id);
+    for (int CC_id=0;CC_id<MAX_NUM_CCs;CC_id++) {
+        PHY_vars_UE_g[UE_id][CC_id]->rfdevice.Mod_id               = UE_id;
+        PHY_vars_UE_g[UE_id][CC_id]->rfdevice.CC_id                = CC_id;
+        PHY_vars_UE_g[UE_id][CC_id]->rfdevice.trx_start_func       = UE_trx_start;
+        PHY_vars_UE_g[UE_id][CC_id]->rfdevice.trx_read_func        = UE_trx_read;
+        PHY_vars_UE_g[UE_id][CC_id]->rfdevice.trx_write_func       = UE_trx_write;
+        PHY_vars_UE_g[UE_id][CC_id]->rfdevice.trx_end_func         = UE_trx_end;
+        PHY_vars_UE_g[UE_id][CC_id]->rfdevice.trx_stop_func        = UE_trx_stop;
+        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;
+    }
+  }
+}
+
+void init_ocm(double snr_dB,double sinr_dB)
+{
+  module_id_t UE_id, ru_id;
+  int CC_id;
+
+  randominit(0);
+  set_taus_seed(0);
+
+
+  init_channel_vars ();//fp, &s_re, &s_im, &r_re, &r_im, &r_re0, &r_im0);
+
+  // initialize channel descriptors
+  LOG_I(PHY,"Initializing channel descriptors (nb_RU %d, nb_UE %d)\n",RC.nb_RU,NB_UE_INST);
+  for (ru_id = 0; ru_id < RC.nb_RU; ru_id++) {
+    for (UE_id = 0; UE_id < NB_UE_INST; UE_id++) {
+      for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
+
+	LOG_I(PHY,"Initializing channel descriptors (RU %d, UE %d) for N_RB_DL %d\n",ru_id,UE_id,
+	      RC.ru[ru_id]->frame_parms.N_RB_DL);
+        RU2UE[ru_id][UE_id][CC_id] = 
+	  new_channel_desc_scm(RC.ru[ru_id]->nb_tx,
+			       PHY_vars_UE_g[UE_id][CC_id]->frame_parms.nb_antennas_rx,
+			       AWGN,
+			       N_RB2sampling_rate(RC.ru[ru_id]->frame_parms.N_RB_DL),
+			       N_RB2channel_bandwidth(RC.ru[ru_id]->frame_parms.N_RB_DL),
+			       0.0,
+			       0,
+			       0);
+        random_channel(RU2UE[ru_id][UE_id][CC_id],0);
+        LOG_D(OCM,"[SIM] Initializing channel (%s) from UE %d to ru %d\n", "AWGN",UE_id, ru_id);
+
+
+        UE2RU[UE_id][ru_id][CC_id] = 
+	  new_channel_desc_scm(PHY_vars_UE_g[UE_id][CC_id]->frame_parms.nb_antennas_tx,
+			       RC.ru[ru_id]->nb_rx,
+			       AWGN,
+			       N_RB2sampling_rate(RC.ru[ru_id]->frame_parms.N_RB_UL),
+			       N_RB2channel_bandwidth(RC.ru[ru_id]->frame_parms.N_RB_UL),
+			       0.0,
+			       0,
+			       0);
+
+        random_channel(UE2RU[UE_id][ru_id][CC_id],0);
+
+        // to make channel reciprocal uncomment following line instead of previous. However this only works for SISO at the moment. For MIMO the channel would need to be transposed.
+        //UE2RU[UE_id][ru_id] = RU2UE[ru_id][UE_id];
+
+	AssertFatal(RU2UE[ru_id][UE_id][CC_id]!=NULL,"RU2UE[%d][%d][%d] is null\n",ru_id,UE_id,CC_id);
+	AssertFatal(UE2RU[UE_id][ru_id][CC_id]!=NULL,"UE2RU[%d][%d][%d] is null\n",UE_id,ru_id,CC_id);
+	//pathloss: -132.24 dBm/15kHz RE + target SNR - eNB TX power per RE
+	if (ru_id == (UE_id % RC.nb_RU)) {
+	  RU2UE[ru_id][UE_id][CC_id]->path_loss_dB = -132.24 + snr_dB - RC.ru[ru_id]->frame_parms.pdsch_config_common.referenceSignalPower;
+	  UE2RU[UE_id][ru_id][CC_id]->path_loss_dB = -132.24 + snr_dB - RC.ru[ru_id]->frame_parms.pdsch_config_common.referenceSignalPower; 
+	} else {
+	  RU2UE[ru_id][UE_id][CC_id]->path_loss_dB = -132.24 + sinr_dB - RC.ru[ru_id]->frame_parms.pdsch_config_common.referenceSignalPower;
+	  UE2RU[UE_id][ru_id][CC_id]->path_loss_dB = -132.24 + sinr_dB - RC.ru[ru_id]->frame_parms.pdsch_config_common.referenceSignalPower;
+	}
+	
+	LOG_D(OCM,"Path loss from eNB %d to UE %d (CCid %d)=> %f dB (eNB TX %d, SNR %f)\n",ru_id,UE_id,CC_id,
+	      RU2UE[ru_id][UE_id][CC_id]->path_loss_dB,
+	      RC.ru[ru_id]->frame_parms.pdsch_config_common.referenceSignalPower,snr_dB);
+	
+
+      }
+    }
+  }
+}
+
+
+void update_ocm(double snr_dB,double sinr_dB)
+{
+  module_id_t UE_id, ru_id;
+  int CC_id;
+
+
+   for (ru_id = 0; ru_id < RC.nb_RU; ru_id++) {
+     for (UE_id = 0; UE_id < NB_UE_INST; UE_id++) {
+       for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
+
+         AssertFatal(RU2UE[ru_id][UE_id][CC_id]!=NULL,"RU2UE[%d][%d][%d] is null\n",ru_id,UE_id,CC_id);
+	 AssertFatal(UE2RU[UE_id][ru_id][CC_id]!=NULL,"UE2RU[%d][%d][%d] is null\n",UE_id,ru_id,CC_id);
+	 //pathloss: -132.24 dBm/15kHz RE + target SNR - eNB TX power per RE
+	 if (ru_id == (UE_id % RC.nb_RU)) {
+	   RU2UE[ru_id][UE_id][CC_id]->path_loss_dB = -132.24 + snr_dB - RC.ru[ru_id]->frame_parms.pdsch_config_common.referenceSignalPower;
+	   UE2RU[UE_id][ru_id][CC_id]->path_loss_dB = -132.24 + snr_dB - RC.ru[ru_id]->frame_parms.pdsch_config_common.referenceSignalPower; 
+	 } else {
+	   RU2UE[ru_id][UE_id][CC_id]->path_loss_dB = -132.24 + sinr_dB - RC.ru[ru_id]->frame_parms.pdsch_config_common.referenceSignalPower;
+	   UE2RU[UE_id][ru_id][CC_id]->path_loss_dB = -132.24 + sinr_dB - RC.ru[ru_id]->frame_parms.pdsch_config_common.referenceSignalPower;
+	 }
+	    
+	 LOG_D(OCM,"Path loss from eNB %d to UE %d (CCid %d)=> %f dB (eNB TX %d, SNR %f)\n",ru_id,UE_id,CC_id,
+	      RU2UE[ru_id][UE_id][CC_id]->path_loss_dB,
+	      RC.ru[ru_id]->frame_parms.pdsch_config_common.referenceSignalPower,snr_dB);
+	    
+       }
+     }
+   }
+}
+
+
+void init_channel_vars(void)
+{
+
+  int i;
+
+  memset(RU_output_mask,0,sizeof(int)*NUMBER_OF_UE_MAX);
+  for (i=0;i<NB_UE_INST;i++)
+    pthread_mutex_init(&RU_output_mutex[i],NULL);
+
+  memset(UE_output_mask,0,sizeof(int)*NUMBER_OF_RU_MAX);
+  for (i=0;i<RC.nb_RU;i++)
+    pthread_mutex_init(&UE_output_mutex[i],NULL);
+
+}
+
+
+
+void rfsim_top(void *n_frames) {
+
+  LOG_I(PHY,"rfsim_top: Waiting for sync\n");
+
+  while (sync_var<0)
+    pthread_cond_wait(&sync_cond, &sync_mutex);
+  pthread_mutex_unlock(&sync_mutex);
+
+
+  for (int frame = 0;
+       frame < *(int*)n_frames;
+       frame++) {
+
+    for (int sf = 0; sf < 10; sf++) {
+      int CC_id=0;
+      int all_done=0;
+      printf("Running %d.%d\n",frame,sf);
+      while (all_done==0) {
+	
+	pthread_mutex_lock(&subframe_mutex);
+	int subframe_ru_mask_local  = (subframe_select(&RC.ru[0]->frame_parms,(sf+4)%10)!=SF_UL) ? subframe_ru_mask : ((1<<RC.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(SIM,"Frame %d, Subframe %d, NB_RU %d, NB_UE %d: Checking masks %x,%x\n",frame,sf,RC.nb_RU,NB_UE_INST,subframe_ru_mask_local,subframe_UE_mask_local);
+	if ((subframe_ru_mask_local == ((1<<RC.nb_RU)-1)) &&
+	    (subframe_UE_mask_local == ((1<<NB_UE_INST)-1))) all_done=1;
+	else usleep(1500);
+      }
+      
+      
+      //clear subframe masks for next round
+      pthread_mutex_lock(&subframe_mutex);
+      subframe_ru_mask=0;
+      subframe_UE_mask=0;
+      pthread_mutex_unlock(&subframe_mutex);
+      
+      // increment timestamps
+      for (int ru_id=0;ru_id<RC.nb_RU;ru_id++) {
+	current_ru_rx_timestamp[ru_id][CC_id] += RC.ru[ru_id]->frame_parms.samples_per_tti;
+	LOG_D(SIM,"RU %d/%d: TS %"PRIi64"\n",ru_id,CC_id,current_ru_rx_timestamp[ru_id][CC_id]);
+      }
+      for (int UE_inst = 0; UE_inst<NB_UE_INST;UE_inst++) {
+	current_UE_rx_timestamp[UE_inst][CC_id] += PHY_vars_UE_g[UE_inst][CC_id]->frame_parms.samples_per_tti;
+	LOG_D(SIM,"UE %d/%d: TS %"PRIi64"\n",UE_inst,CC_id,current_UE_rx_timestamp[UE_inst][CC_id]);
+      }
+      if (oai_exit == 1) return;
+    }
+  }
+
+}
diff --git a/targets/SIMU/USER/channel_sim.c b/targets/SIMU/USER/channel_sim.c
deleted file mode 100644
index 3018dbe1fb..0000000000
--- a/targets/SIMU/USER/channel_sim.c
+++ /dev/null
@@ -1,618 +0,0 @@
-/*
- * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The OpenAirInterface Software Alliance licenses this file to You under
- * the OAI Public License, Version 1.1  (the "License"); you may not use this file
- * except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.openairinterface.org/?page_id=698
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *-------------------------------------------------------------------------------
- * For more information about the OpenAirInterface (OAI) Software Alliance:
- *      contact@openairinterface.org
- */
-
-#include <string.h>
-#include <math.h>
-#include <unistd.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <time.h>
-
-#include "SIMULATION/TOOLS/sim.h"
-#include "SIMULATION/RF/rf.h"
-#include "PHY/types.h"
-#include "PHY/defs_eNB.h"
-#include "PHY/phy_extern.h"
-#include "PHY/phy_extern_ue.h"
-
-#include "LAYER2/MAC/mac.h"
-#include "LAYER2/MAC/mac_extern.h"
-#include "UTIL/LOG/log_if.h"
-#include "UTIL/LOG/log_extern.h"
-#include "RRC/LTE/rrc_extern.h"
-#include "PHY_INTERFACE/phy_interface_extern.h"
-#include "UTIL/OCG/OCG.h"
-#include "UTIL/OPT/opt.h" // to test OPT
-
-#include "UTIL/FIFO/types.h"
-
-#ifdef XFORMS
-#include "forms.h"
-#include "phy_procedures_sim_form.h"
-#endif
-
-#include "oaisim.h"
-
-#define RF
-#define DEBUG_SIM
-/*
-#undef LOG_D
-#define LOG_D(A,B,C...) printf(B,C)
-*/
-
-int number_rb_ul;
-int first_rbUL ;
-
-extern Signal_buffers_t *signal_buffers_g;
-
-
-double r_re_DL[NUMBER_OF_UE_MAX][2][30720];
-double r_im_DL[NUMBER_OF_UE_MAX][2][30720];
-double r_re_UL[NUMBER_OF_eNB_MAX][2][30720];
-double r_im_UL[NUMBER_OF_eNB_MAX][2][30720];
-int RU_output_mask[NUMBER_OF_UE_MAX];
-int UE_output_mask[NUMBER_OF_RU_MAX];
-pthread_mutex_t RU_output_mutex[NUMBER_OF_UE_MAX];
-pthread_mutex_t UE_output_mutex[NUMBER_OF_RU_MAX];
-
-double ru_amp[NUMBER_OF_RU_MAX];
-
-void do_DL_sig(channel_desc_t *RU2UE[NUMBER_OF_RU_MAX][NUMBER_OF_UE_MAX][MAX_NUM_CCs],
-	       node_desc_t *enb_data[NUMBER_OF_RU_MAX],
-	       node_desc_t *ue_data[NUMBER_OF_UE_MAX],
-	       uint16_t subframe,
-	       uint32_t offset,
-	       uint32_t length,
-	       uint8_t abstraction_flag,LTE_DL_FRAME_PARMS *ue_frame_parms,
-	       uint8_t UE_id,
-	       int CC_id)
-{
-
-  int32_t att_eNB_id=-1;
-  int32_t **txdata,**rxdata;
-
-  uint32_t eNB_id,ru_id=0;
-  double tx_pwr;
-  double rx_pwr;
-  int32_t rx_pwr2;
-  uint32_t i,aa;
-  uint32_t sf_offset;
-
-  double min_path_loss=-200;
-  uint8_t hold_channel=0;
-  uint8_t nb_antennas_rx = RU2UE[0][0][CC_id]->nb_rx; // number of rx antennas at UE
-  uint8_t nb_antennas_tx = RU2UE[0][0][CC_id]->nb_tx; // number of tx antennas at eNB
-
-  double s_re0[30720];
-  double s_re1[30720];
-  double *s_re[2];
-  double s_im0[30720];
-  double s_im1[30720];
-  double *s_im[2];
-  double r_re00[30720];
-  double r_re01[30720];
-  double *r_re0[2];
-  double r_im00[30720];
-  double r_im01[30720];
-  double *r_im0[2];
-  LTE_DL_FRAME_PARMS *frame_parms;
-
-  s_re[0] = s_re0;
-  s_im[0] = s_im0;
-  s_re[1] = s_re1;
-  s_im[1] = s_im1;
-
-  r_re0[0] = r_re00;
-  r_im0[0] = r_im00;
-  r_re0[1] = r_re01;
-  r_im0[1] = r_im01;
-
-  if (subframe==0)
-    hold_channel = 0;
-  else
-    hold_channel = 1;
-
-  if (abstraction_flag != 0) {
-    //for (UE_id=0;UE_id<NB_UE_INST;UE_id++) {
-
-    if (!hold_channel) {
-      // calculate the random channel from each RU
-      for (ru_id=0; ru_id<RC.nb_RU; ru_id++) {
-        frame_parms = &RC.ru[ru_id]->frame_parms;
-
-        random_channel(RU2UE[ru_id][UE_id][CC_id],abstraction_flag);
-        /*
-        for (i=0;i<RU2UE[eNB_id][UE_id]->nb_taps;i++)
-        printf("RU2UE[%d][%d]->a[0][%d] = (%f,%f)\n",eNB_id,UE_id,i,RU2UE[eNB_id][UE_id]->a[0][i].x,RU2UE[eNB_id][UE_id]->a[0][i].y);
-        */
-        freq_channel(RU2UE[ru_id][UE_id][CC_id], frame_parms->N_RB_DL,frame_parms->N_RB_DL*12+1);
-      }
-
-      // find out which eNB the UE is attached to
-      /*
-      for (eNB_id=0; eNB_id<RC.nb_inst; eNB_id++) {
-        if (find_ue(PHY_vars_UE_g[UE_id][CC_id]->pdcch_vars[0][0]->crnti,RC.eNB[eNB_id][CC_id])>=0) {
-          // UE with UE_id is connected to eNb with eNB_id
-          att_eNB_id=eNB_id;
-          LOG_D(OCM,"A: UE attached to eNB (UE%d->eNB%d)\n",UE_id,eNB_id);
-        }
-      }
-      */
-      // if UE is not attached yet, find assume its the eNB with the smallest pathloss
-      if (att_eNB_id<0) {
-        for (eNB_id=0; eNB_id<NB_eNB_INST; eNB_id++) {
-	  for (int ru=0;ru<RC.nb_RU;ru++) {
-	    ru_id = RC.eNB[eNB_id][CC_id]->RU_list[ru]->idx;
-	    if (min_path_loss<RU2UE[ru_id][UE_id][CC_id]->path_loss_dB) {
-	      min_path_loss = RU2UE[ru_id][UE_id][CC_id]->path_loss_dB;
-	      att_eNB_id=eNB_id;
-	      LOG_D(OCM,"B: UE attached to eNB (UE%d->eNB%d)\n",UE_id,eNB_id);
-	    }
-	  }
-        }
-      }
-
-      if (att_eNB_id<0) {
-        LOG_E(OCM,"Cannot find eNB for UE %d, return\n",UE_id);
-        return; //exit(-1);
-      }
-
-#ifdef DEBUG_SIM
-      rx_pwr = signal_energy_fp2(RU2UE[att_eNB_id][UE_id][CC_id]->ch[0],
-                                 RU2UE[att_eNB_id][UE_id][CC_id]->channel_length)*RU2UE[att_eNB_id][UE_id][CC_id]->channel_length;
-      LOG_D(OCM,"Channel (CCid %d) eNB %d => UE %d : tx_power %d dBm, path_loss %f dB\n",
-            CC_id,att_eNB_id,UE_id,
-            frame_parms->pdsch_config_common.referenceSignalPower,
-            RU2UE[att_eNB_id][UE_id][CC_id]->path_loss_dB);
-#endif
-
-      //dlsch_abstraction(PHY_vars_UE_g[UE_id]->sinr_dB, rb_alloc, 8);
-      // fill in perfect channel estimates
-      channel_desc_t *desc1 = RU2UE[att_eNB_id][UE_id][CC_id];
-      int32_t **dl_channel_est = PHY_vars_UE_g[UE_id][CC_id]->common_vars.common_vars_rx_data_per_thread[subframe&0x1].dl_ch_estimates[0];
-      //      double scale = pow(10.0,(enb_data[att_eNB_id]->tx_power_dBm + RU2UE[att_eNB_id][UE_id]->path_loss_dB + (double) PHY_vars_UE_g[UE_id]->rx_total_gain_dB)/20.0);
-      double scale = pow(10.0,(frame_parms->pdsch_config_common.referenceSignalPower+RU2UE[att_eNB_id][UE_id][CC_id]->path_loss_dB + (double) PHY_vars_UE_g[UE_id][CC_id]->rx_total_gain_dB)/20.0);
-      LOG_D(OCM,"scale =%lf (%d dB)\n",scale,(int) (20*log10(scale)));
-      // freq_channel(desc1,frame_parms->N_RB_DL,nb_samples);
-      //write_output("channel.m","ch",desc1->ch[0],desc1->channel_length,1,8);
-      //write_output("channelF.m","chF",desc1->chF[0],nb_samples,1,8);
-      int count,count1,a_rx,a_tx;
-
-      for(a_tx=0; a_tx<nb_antennas_tx; a_tx++) {
-        for (a_rx=0; a_rx<nb_antennas_rx; a_rx++) {
-          //for (count=0;count<frame_parms->symbols_per_tti/2;count++)
-          for (count=0; count<1; count++) {
-            for (count1=0; count1<frame_parms->N_RB_DL*12; count1++) {
-              ((int16_t *) dl_channel_est[(a_tx<<1)+a_rx])[2*count1+(count*frame_parms->ofdm_symbol_size+LTE_CE_FILTER_LENGTH)*2]=(int16_t)(desc1->chF[a_rx+(a_tx*nb_antennas_rx)][count1].x*scale);
-              ((int16_t *) dl_channel_est[(a_tx<<1)+a_rx])[2*count1+1+(count*frame_parms->ofdm_symbol_size+LTE_CE_FILTER_LENGTH)*2]=(int16_t)(desc1->chF[a_rx+(a_tx*nb_antennas_rx)][count1].y*scale) ;
-            }
-          }
-        }
-      }
-
-      // calculate the SNR for the attached eNB (this assumes eNB always uses PMI stored in eNB_UE_stats; to be improved)
-      init_snr(RU2UE[att_eNB_id][UE_id][CC_id], enb_data[att_eNB_id], ue_data[UE_id], PHY_vars_UE_g[UE_id][CC_id]->sinr_dB, &PHY_vars_UE_g[UE_id][CC_id]->N0,
-               PHY_vars_UE_g[UE_id][CC_id]->transmission_mode[att_eNB_id], RC.eNB[att_eNB_id][CC_id]->UE_stats[UE_id].DL_pmi_single,
-	       RC.eNB[att_eNB_id][CC_id]->mu_mimo_mode[UE_id].dl_pow_off,RC.eNB[att_eNB_id][CC_id]->frame_parms.N_RB_DL);
-
-      // calculate sinr here
-      for (eNB_id = 0; eNB_id < NB_eNB_INST; eNB_id++) {
-        if (att_eNB_id != eNB_id) {
-          calculate_sinr(RU2UE[eNB_id][UE_id][CC_id], enb_data[eNB_id], ue_data[UE_id], PHY_vars_UE_g[UE_id][CC_id]->sinr_dB,
-			 RC.eNB[att_eNB_id][CC_id]->frame_parms.N_RB_DL);
-        }
-      }
-    } // hold channel
-  }
-  else { //abstraction_flag
-
-
-    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));
-      }
-    }
-    pthread_mutex_unlock(&RU_output_mutex[UE_id]);
-
-    for (ru_id=0; ru_id<RC.nb_RU; ru_id++) {
-      txdata = RC.ru[ru_id]->common.txdata;
-      frame_parms = &RC.ru[ru_id]->frame_parms;
-
-      sf_offset = (subframe*frame_parms->samples_per_tti) + offset;
-      LOG_D(EMU,">>>>>>>>>>>>>>>>>TXPATH: RU %d : DL_sig reading TX for subframe %d (sf_offset %d, length %d) from %p\n",ru_id,subframe,sf_offset,length,txdata[0]+sf_offset); 
-      int length_meas = frame_parms->ofdm_symbol_size;
-      if (sf_offset+length <= frame_parms->samples_per_tti*10) {
-
-	tx_pwr = dac_fixed_gain(s_re,
-				s_im,
-				txdata,
-				sf_offset,
-				nb_antennas_tx,
-				length,
-				sf_offset,
-				length_meas,
-				14,
-				frame_parms->pdsch_config_common.referenceSignalPower, // dBm/RE
-				0,
-				&ru_amp[ru_id],
-				frame_parms->N_RB_DL*12);
-
-      }
-      else {
-	tx_pwr = dac_fixed_gain(s_re,
-				s_im,
-				txdata,
-				sf_offset,
-				nb_antennas_tx,
-				(frame_parms->samples_per_tti*10)-sf_offset,
-				sf_offset,
-				length_meas,
-				14,
-				frame_parms->pdsch_config_common.referenceSignalPower, // dBm/RE
-				0,
-				&ru_amp[ru_id],
-				frame_parms->N_RB_DL*12);
-
-	tx_pwr = dac_fixed_gain(s_re,
-				s_im,
-				txdata,
-				sf_offset,
-				nb_antennas_tx,
-				length+sf_offset-(frame_parms->samples_per_tti*10),
-				sf_offset,
-				length_meas,
-				14,
-				frame_parms->pdsch_config_common.referenceSignalPower, // dBm/RE
-				0,
-				&ru_amp[ru_id],
-				frame_parms->N_RB_DL*12);
-      }
-#ifdef DEBUG_SIM
-      LOG_D(PHY,"[SIM][DL] subframe %d: txp (time) %d dB\n",
-	    subframe,dB_fixed(signal_energy(&txdata[0][sf_offset],length_meas)));
-	    
-      LOG_D(OCM,"[SIM][DL] RU %d (CCid %d): tx_pwr %.1f dBm/RE (target %d dBm/RE), for subframe %d\n",
-            ru_id,CC_id,
-            10*log10(tx_pwr),
-            frame_parms->pdsch_config_common.referenceSignalPower,
-            subframe);
-
-#endif
-      tx_pwr = signal_energy_fp(s_re,s_im,nb_antennas_tx,
-				length<length_meas?length:length_meas,
-                                0)/(12.0*frame_parms->N_RB_DL);
- 
-      //RU2UE[eNB_id][UE_id]->path_loss_dB = 0;
-      multipath_channel(RU2UE[ru_id][UE_id][CC_id],s_re,s_im,r_re0,r_im0,
-                        length,hold_channel);
-#ifdef DEBUG_SIM
-      rx_pwr = signal_energy_fp2(RU2UE[ru_id][UE_id][CC_id]->ch[0],
-                                 RU2UE[ru_id][UE_id][CC_id]->channel_length)*RU2UE[ru_id][UE_id][CC_id]->channel_length;
-      LOG_D(OCM,"[SIM][DL] Channel RU %d => UE %d (CCid %d): Channel gain %f dB (%f)\n",ru_id,UE_id,CC_id,10*log10(rx_pwr),rx_pwr);
-#endif
-
-
-#ifdef DEBUG_SIM
-
-      for (i=0; i<RU2UE[ru_id][UE_id][CC_id]->channel_length; i++)
-        LOG_D(OCM,"channel(%d,%d)[%d] : (%f,%f)\n",ru_id,UE_id,i,RU2UE[ru_id][UE_id][CC_id]->ch[0][i].x,RU2UE[ru_id][UE_id][CC_id]->ch[0][i].y);
-
-#endif
-
-      LOG_D(OCM,"[SIM][DL] Channel RU %d => UE %d (CCid %d): tx_power %.1f dBm/RE, path_loss %1.f dB\n",
-            ru_id,UE_id,CC_id,
-            (double)frame_parms->pdsch_config_common.referenceSignalPower,
-            //         enb_data[eNB_id]->tx_power_dBm,
-            RU2UE[ru_id][UE_id][CC_id]->path_loss_dB);
-
-#ifdef DEBUG_SIM
-      rx_pwr = signal_energy_fp(r_re0,r_im0,nb_antennas_rx,
-                                length<length_meas?length:length_meas,
-                                0)/(12.0*frame_parms->N_RB_DL);
-     LOG_D(OCM,"[SIM][DL] UE %d : rx_pwr %f dBm/RE (%f dBm RSSI,tx %f dB)for subframe %d (length %d)\n",UE_id,
-	   10*log10(rx_pwr),
-	   10*log10(rx_pwr*(double)frame_parms->N_RB_DL*12),
-	   10*log10(tx_pwr),subframe,
-	   length<length_meas?length:length_meas);
-
-      
-      LOG_D(OCM,"[SIM][DL] UE %d : rx_pwr (noise) -132 dBm/RE (N0fs = %.1f dBm, N0B = %.1f dBm) for subframe %d\n",
-            UE_id,
-            10*log10(RU2UE[ru_id][UE_id][CC_id]->sampling_rate*1e6)-174,
-            10*log10(RU2UE[ru_id][UE_id][CC_id]->sampling_rate*1e6*12*frame_parms->N_RB_DL/(double)frame_parms->ofdm_symbol_size)-174,
-            subframe);
-#endif
-
-      if (RU2UE[ru_id][UE_id][CC_id]->first_run == 1)
-        RU2UE[ru_id][UE_id][CC_id]->first_run = 0;
-
-
-      // RF model
-#ifdef DEBUG_SIM
-      LOG_D(OCM,"[SIM][DL] UE %d (CCid %d): rx_gain %d dB (-ADC %f) for subframe %d\n",UE_id,CC_id,PHY_vars_UE_g[UE_id][CC_id]->rx_total_gain_dB,
-            PHY_vars_UE_g[UE_id][CC_id]->rx_total_gain_dB-66.227,subframe);
-#endif
-
-      rf_rx_simple(r_re0,
-                   r_im0,
-                   nb_antennas_rx,
-                   length,
-                   1e3/RU2UE[ru_id][UE_id][CC_id]->sampling_rate,  // sampling time (ns)
-                   (double)PHY_vars_UE_g[UE_id][CC_id]->rx_total_gain_dB - 66.227);   // rx_gain (dB) (66.227 = 20*log10(pow2(11)) = gain from the adc that will be applied later)
-
-#ifdef DEBUG_SIM
-      rx_pwr = signal_energy_fp(r_re0,r_im0,
-                                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 (RU %d) %f dBm/RE for subframe %d\n",
-            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++) {
-          r_re_DL[UE_id][aa][i]+=r_re0[aa][i];
-          r_im_DL[UE_id][aa][i]+=r_im0[aa][i];
-        }
-      }
-      RU_output_mask[UE_id] |= (1<<ru_id);
-      if (RU_output_mask[UE_id] == (1<<RC.nb_RU)-1) {
-	RU_output_mask[UE_id]=0;
-      
-
-
-	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;
-
-
-	adc(r_re_p,
-	    r_im_p,
-	    0,
-	    sf_offset,
-	    rxdata,
-	    nb_antennas_rx,
-	    length,
-	    12);
-	
-#ifdef DEBUG_SIM
-	rx_pwr2 = signal_energy(rxdata[0]+sf_offset,length<length_meas?length:length_meas)/(12.0*frame_parms->N_RB_DL);
-	LOG_D(OCM,"[SIM][DL] UE %d : rx_pwr (ADC out) %f dB/RE (%d) for subframe %d, writing to %p, length %d\n",UE_id, 10*log10((double)rx_pwr2),rx_pwr2,subframe,rxdata,length<length_meas?length:length_meas);
-	LOG_D(OCM,"[SIM][DL] UE %d : rx_pwr (ADC out) %f dB for subframe %d\n",UE_id,10*log10((double)rx_pwr2*12*frame_parms->N_RB_DL) ,subframe);
-#else
-	UNUSED_VARIABLE(rx_pwr2);
-	UNUSED_VARIABLE(tx_pwr);
-	UNUSED_VARIABLE(rx_pwr);
-#endif
-		
-      } // RU_output_mask
-      pthread_mutex_unlock(&RU_output_mutex[UE_id]);      
-    } // ru_id
-
-  }
-
-}
-
-
-void do_UL_sig(channel_desc_t *UE2RU[NUMBER_OF_UE_MAX][NUMBER_OF_RU_MAX][MAX_NUM_CCs],
-               node_desc_t *enb_data[NUMBER_OF_RU_MAX],node_desc_t *ue_data[NUMBER_OF_UE_MAX],
-	       uint16_t subframe,uint8_t abstraction_flag,LTE_DL_FRAME_PARMS *frame_parms, 
-	       uint32_t frame,int ru_id,uint8_t CC_id)
-{
-
-  int32_t **txdata,**rxdata;
-  uint8_t UE_id=0;
-
-  uint8_t nb_antennas_rx = UE2RU[0][0][CC_id]->nb_rx; // number of rx antennas at eNB
-  uint8_t nb_antennas_tx = UE2RU[0][0][CC_id]->nb_tx; // number of tx antennas at UE
-
-  double tx_pwr, rx_pwr;
-  int32_t rx_pwr2;
-  uint32_t i,aa;
-  uint32_t sf_offset;
-
-  uint8_t hold_channel=0;
-
-  double s_re0[30720];
-  double s_re1[30720];
-  double *s_re[2];
-  double s_im0[30720];
-  double s_im1[30720];
-  double *s_im[2];
-  double r_re00[30720];
-  double r_re01[30720];
-  double *r_re0[2];
-  double r_im00[30720];
-  double r_im01[30720];
-  double *r_im0[2];
-
-  s_re[0] = s_re0;
-  s_im[0] = s_im0;
-  s_re[1] = s_re1;
-  s_im[1] = s_im1;
-
-  r_re0[0] = r_re00;
-  r_im0[0] = r_im00;
-  r_re0[1] = r_re01;
-  r_im0[1] = r_im01;
-  
-  if (abstraction_flag!=0)  {
-  } else { //without abstraction
-
-    pthread_mutex_lock(&UE_output_mutex[ru_id]);
-    // Clear RX signal for eNB = eNB_id
-    for (i=0; i<frame_parms->samples_per_tti; i++) {
-      for (aa=0; aa<nb_antennas_rx; aa++) {
-	r_re_UL[ru_id][aa][i]=0.0;
-	r_im_UL[ru_id][aa][i]=0.0;
-      }
-    }
-    pthread_mutex_unlock(&UE_output_mutex[ru_id]);
-
-    // Compute RX signal for eNB = eNB_id
-    for (UE_id=0; UE_id<NB_UE_INST; UE_id++) {
-      
-      txdata = PHY_vars_UE_g[UE_id][CC_id]->common_vars.txdata;
-      AssertFatal(txdata != NULL,"txdata is null\n");
-      sf_offset = subframe*frame_parms->samples_per_tti;
-      if (((double)PHY_vars_UE_g[UE_id][CC_id]->tx_power_dBm[subframe] +
-	   UE2RU[UE_id][ru_id][CC_id]->path_loss_dB) <= -125.0) {
-	// don't simulate a UE that is too weak
-	LOG_D(OCM,"[SIM][UL] ULPOWERS UE %d tx_pwr %d dBm (num_RE %d) for subframe %d (sf_offset %d)\n",
-	      UE_id,
-	      PHY_vars_UE_g[UE_id][CC_id]->tx_power_dBm[subframe],
-	      PHY_vars_UE_g[UE_id][CC_id]->tx_total_RE[subframe],
-	      subframe,sf_offset);	
-      } else {
-	tx_pwr = dac_fixed_gain((double**)s_re,
-				(double**)s_im,
-				txdata,
-				sf_offset,
-				nb_antennas_tx,
-				frame_parms->samples_per_tti,
-				sf_offset,
-				frame_parms->ofdm_symbol_size,
-				14,
-				(double)PHY_vars_UE_g[UE_id][CC_id]->tx_power_dBm[subframe]-10*log10((double)PHY_vars_UE_g[UE_id][CC_id]->tx_total_RE[subframe]),
-				1,
-				NULL,
-				PHY_vars_UE_g[UE_id][CC_id]->tx_total_RE[subframe]);  // This make the previous argument the total power
-	LOG_D(OCM,"[SIM][UL] ULPOWERS UE %d tx_pwr %f dBm (target %d dBm, num_RE %d) for subframe %d (sf_offset %d)\n",
-	      UE_id,
-	      10*log10(tx_pwr*PHY_vars_UE_g[UE_id][CC_id]->tx_total_RE[subframe]),
-	      PHY_vars_UE_g[UE_id][CC_id]->tx_power_dBm[subframe],
-	      PHY_vars_UE_g[UE_id][CC_id]->tx_total_RE[subframe],
-	      subframe,sf_offset);
-       
-		
-	multipath_channel(UE2RU[UE_id][ru_id][CC_id],s_re,s_im,r_re0,r_im0,
-			  frame_parms->samples_per_tti,hold_channel);
-	
-
-	rx_pwr = signal_energy_fp2(UE2RU[UE_id][ru_id][CC_id]->ch[0],
-				   UE2RU[UE_id][ru_id][CC_id]->channel_length)*UE2RU[UE_id][ru_id][CC_id]->channel_length;
-
-	LOG_D(OCM,"[SIM][UL] subframe %d Channel UE %d => RU %d : %f dB (hold %d,length %d, PL %f)\n",subframe,UE_id,ru_id,10*log10(rx_pwr),
-	      hold_channel,UE2RU[UE_id][ru_id][CC_id]->channel_length,
-	      UE2RU[UE_id][ru_id][CC_id]->path_loss_dB);
-
-	rx_pwr = signal_energy_fp(r_re0,r_im0,nb_antennas_rx,frame_parms->samples_per_tti,0);
-	LOG_D(OCM,"[SIM][UL] RU %d (%d/%d rx antennas) : rx_pwr %f dBm (tx_pwr - PL %f) for subframe %d, sptti %d\n",
-	      ru_id,nb_antennas_rx,UE2RU[UE_id][ru_id][CC_id]->nb_rx,10*log10(rx_pwr),10*log10(tx_pwr*PHY_vars_UE_g[UE_id][CC_id]->tx_total_RE[subframe])+UE2RU[UE_id][ru_id][CC_id]->path_loss_dB,subframe,frame_parms->samples_per_tti);
-	/*	
-	if (abs(10*log10(rx_pwr)-10*log10(tx_pwr*PHY_vars_UE_g[UE_id][CC_id]->tx_total_RE[subframe])-UE2RU[UE_id][ru_id][CC_id]->path_loss_dB)>3) {
-	  write_output("txsig_re.m","s_re",s_re[0],frame_parms->samples_per_tti,1,7);
-	  write_output("txsig_im.m","s_im",s_im[0],frame_parms->samples_per_tti,1,7);
-	  write_output("rxsig_re.m","r_re",r_re0[0],frame_parms->samples_per_tti,1,7);
-	  write_output("rxsig_im.m","r_im",r_im0[0],frame_parms->samples_per_tti,1,7);
-	  exit(-1);
-	  }*/
-
-	if (UE2RU[UE_id][ru_id][CC_id]->first_run == 1)
-	  UE2RU[UE_id][ru_id][CC_id]->first_run = 0;
-	
-	
-	pthread_mutex_lock(&UE_output_mutex[ru_id]);
-	for (aa=0; aa<nb_antennas_rx; aa++) {
-	  for (i=0; i<frame_parms->samples_per_tti; i++) {
-	    r_re_UL[ru_id][aa][i]+=r_re0[aa][i];
-	    r_im_UL[ru_id][aa][i]+=r_im0[aa][i];
-	  }
-	}
-	pthread_mutex_unlock(&UE_output_mutex[ru_id]);
-      }
-    } //UE_id
-    
-    double *r_re_p[2] = {r_re_UL[ru_id][0],r_re_UL[ru_id][1]};
-    double *r_im_p[2] = {r_im_UL[ru_id][0],r_im_UL[ru_id][1]};
-
-    rx_pwr = signal_energy_fp(r_re_p,r_im_p,nb_antennas_rx,frame_parms->samples_per_tti,0);
-    LOG_D(OCM,"[SIM][UL] RU %d (%d/%d rx antennas) : rx_pwr %f dBm (before RF) for subframe %d, gain %f\n",
-	  ru_id,nb_antennas_rx,nb_antennas_rx,10*log10(rx_pwr),subframe,
-	  (double)RC.ru[ru_id]->max_rxgain-(double)RC.ru[ru_id]->att_rx - 66.227);
-    rf_rx_simple(r_re_p,
-		 r_im_p,
-		 nb_antennas_rx,
-		 frame_parms->samples_per_tti,
-		 1e3/UE2RU[0][ru_id][CC_id]->sampling_rate,  // sampling time (ns)
-		 (double)RC.ru[ru_id]->max_rxgain-(double)RC.ru[ru_id]->att_rx - 66.227);   // rx_gain (dB) (66.227 = 20*log10(pow2(11)) = gain from the adc that will be applied later)
-    
-    //#ifdef DEBUG_SIM
-    rx_pwr = signal_energy_fp(r_re_p,r_im_p,nb_antennas_rx,frame_parms->samples_per_tti,0);//*(double)frame_parms->ofdm_symbol_size/(12.0*frame_parms->N_RB_DL;
-    LOG_D(OCM,"[SIM][UL] rx_pwr (ADC in) %f dB for subframe %d (rx_gain %f)\n",10*log10(rx_pwr),subframe,
-	  (double)RC.ru[ru_id]->max_rxgain-(double)RC.ru[ru_id]->att_rx);
-    //#endif
-    
-    rxdata = RC.ru[ru_id]->common.rxdata;
-    sf_offset = subframe*frame_parms->samples_per_tti;
-
-    
-    adc(r_re_p,
-	r_im_p,
-	0,
-	sf_offset,
-	rxdata,
-	nb_antennas_rx,
-	frame_parms->samples_per_tti,
-	12);
-    
-#ifdef DEBUG_SIM
-    rx_pwr2 = signal_energy(rxdata[0]+sf_offset,frame_parms->samples_per_tti)*(double)frame_parms->ofdm_symbol_size/(12.0*frame_parms->N_RB_DL);
-    LOG_D(OCM,"[SIM][UL] RU %d rx_pwr (ADC out) %f dB (%d) for subframe %d (offset %d) = %p\n",ru_id,10*log10((double)rx_pwr2),rx_pwr2,subframe,sf_offset,rxdata[0]+sf_offset);
-#else
-    UNUSED_VARIABLE(tx_pwr);
-    UNUSED_VARIABLE(rx_pwr);
-    UNUSED_VARIABLE(rx_pwr2);
-#endif
-    
-  } // abstraction_flag==0
-
-}
-
-
-void init_channel_vars(LTE_DL_FRAME_PARMS *frame_parms, double ***s_re,double ***s_im,double ***r_re,double ***r_im,double ***r_re0,double ***r_im0)
-{
-
-  int i;
-
-  memset(RU_output_mask,0,sizeof(int)*NUMBER_OF_UE_MAX);
-  for (i=0;i<NB_UE_INST;i++)
-    pthread_mutex_init(&RU_output_mutex[i],NULL);
-
-  memset(UE_output_mask,0,sizeof(int)*NUMBER_OF_RU_MAX);
-  for (i=0;i<NB_eNB_INST;i++)
-    pthread_mutex_init(&UE_output_mutex[i],NULL);
-
-}
-
-- 
GitLab