diff --git a/cmake_targets/CMakeLists.txt b/cmake_targets/CMakeLists.txt
index c4e2399351da779e7367aeef57e8601c6a15b0f5..dd6fba9a18bfecf5f9383f12fffe5fa2f9340559 100644
--- a/cmake_targets/CMakeLists.txt
+++ b/cmake_targets/CMakeLists.txt
@@ -21,7 +21,7 @@
 
 # Author: laurent THOMAS, Lionel GAUTHIER
 
-cmake_minimum_required (VERSION 2.8)
+cmake_minimum_required (VERSION 3.0)
 
 #############################################
 # Base directories, compatible with legacy OAI building
@@ -169,11 +169,12 @@ endif()
 set(CMAKE_C_FLAGS
   "${CMAKE_C_FLAGS} ${C_FLAGS_PROCESSOR} -std=gnu99 -Wall -Wstrict-prototypes -fno-strict-aliasing -rdynamic -funroll-loops -Wno-packed-bitfield-compat -fPIC ")
 # add autotools definitions that were maybe used!
+set(MKVER "'MAKE_VERSION(a,b,c)=((a)*256+(b)*16+c)'")
 set(CMAKE_C_FLAGS
-  "${CMAKE_C_FLAGS} -DSTDC_HEADERS=1 -DHAVE_SYS_TYPES_H=1 -DHAVE_SYS_STAT_H=1 -DHAVE_STDLIB_H=1 -DHAVE_STRING_H=1 -DHAVE_MEMORY_H=1 -DHAVE_STRINGS_H=1 -DHAVE_INTTYPES_H=1 -DHAVE_STDINT_H=1 -DHAVE_UNISTD_H=1 -DHAVE_FCNTL_H=1 -DHAVE_ARPA_INET_H=1 -DHAVE_SYS_TIME_H=1 -DHAVE_SYS_SOCKET_H=1 -DHAVE_STRERROR=1 -DHAVE_SOCKET=1 -DHAVE_MEMSET=1 -DHAVE_GETTIMEOFDAY=1 -DHAVE_STDLIB_H=1 -DHAVE_MALLOC=1 -DHAVE_LIBSCTP -D'MAKE_VERSION(a,b,c)=((a)*256+(b)*16+c)'"
+	"${CMAKE_C_FLAGS} -DSTDC_HEADERS=1 -DHAVE_SYS_TYPES_H=1 -DHAVE_SYS_STAT_H=1 -DHAVE_STDLIB_H=1 -DHAVE_STRING_H=1 -DHAVE_MEMORY_H=1 -DHAVE_STRINGS_H=1 -DHAVE_INTTYPES_H=1 -DHAVE_STDINT_H=1 -DHAVE_UNISTD_H=1 -DHAVE_FCNTL_H=1 -DHAVE_ARPA_INET_H=1 -DHAVE_SYS_TIME_H=1 -DHAVE_SYS_SOCKET_H=1 -DHAVE_STRERROR=1 -DHAVE_SOCKET=1 -DHAVE_MEMSET=1 -DHAVE_GETTIMEOFDAY=1 -DHAVE_STDLIB_H=1 -DHAVE_MALLOC=1 -DHAVE_LIBSCTP -D${MKVER}"
 )
 set(CMAKE_CXX_FLAGS
-  "${CMAKE_CXX_FLAGS} ${C_FLAGS_PROCESSOR} -std=c++11 -D'MAKE_VERSION(a,b,c)=((a)*256+(b)*16+c)'"
+	"${CMAKE_CXX_FLAGS} ${C_FLAGS_PROCESSOR} -std=c++11 -D${MKVER}"
 )
 add_definitions("-DASN_DISABLE_OER_SUPPORT")
 
@@ -252,6 +253,7 @@ add_boolean_option(UE_TIMING_TRACE     False "Activate UE timing trace")
 add_boolean_option(DISABLE_LOG_X       False "Deactivate all LOG_* macros")
 add_boolean_option(USRP_REC_PLAY       False "Enable USRP record playback mode")
 add_boolean_option(UE_NAS_USE_TUN      False "Enable UE NAS TUN device instead of ue_ip.ko")
+add_boolean_option(NOS1      False "Allows to run without a EPC")
 add_boolean_option(BASIC_SIMULATOR     False "Has to be True when building the basic simulator, False otherwise")
 
 add_boolean_option(DEBUG_CONSOLE False "makes debugging easier, disables stdout/stderr buffering")
@@ -260,17 +262,17 @@ add_boolean_option(ENABLE_ITTI True "ITTI is internal messaging, should remain e
 set (OCP_ITTI ${OPENAIR_DIR}/common/utils/ocp_itti)
 if (${ENABLE_ITTI})
   add_library(ITTI
-    # add .h files if depend on (this one is generated)
     ${OCP_ITTI}/intertask_interface.cpp
     ${OPENAIR_DIR}/common/utils/backtrace.c
     ${OPENAIR_DIR}/common/utils/memory_pools.c
     )
+add_dependencies(ITTI rrc_flag)
   set(ITTI_LIB ITTI)
   set(GTPU_need_ITTI ${OPENAIR3_DIR}/GTPV1-U/gtpv1u_eNB.c)
 endif (${ENABLE_ITTI})
 
 #############################
-# ASN.1 grammar C code generation & dependancies
+# ASN.1 grammar C code generation & dependencies
 ################################
 # A difficulty: asn1c generates C code of a un-predictable list of files
 # so, generate the c from asn1c once at cmake run time
@@ -278,8 +280,6 @@ endif (${ENABLE_ITTI})
 # (so creating new asn.1 objects instead of modifying the object attributes)
 # New C code source file, cmake must be re-run (instead of re-running make only)
 #############
-# set(asn1c_call "${OPENAIR_CMAKE}/tools/generate_asn1")
-# set(fix_asn1c_call "${OPENAIR_CMAKE}/tools/fix_asn1")
 set(asn1_generated_dir ${OPENAIR_BIN_DIR})
 
 set(protoc_call "${OPENAIR_CMAKE}/tools/generate_protobuf")
@@ -290,7 +290,6 @@ set(protobuf_generated_dir ${OPENAIR_BIN_DIR})
 
 add_list2_option(RRC_ASN1_VERSION "Rel15" "ASN.1 version of RRC interface" "Rel8" "Rel10" "Rel14" "CBA")
 
-Message("RRC_ASN1_VERSION is ${RRC_ASN1_VERSION}")
 
 if (${RRC_ASN1_VERSION} STREQUAL "Rel8")
   make_version(RRC_VERSION 8 6 0)
@@ -320,34 +319,25 @@ elseif (${RRC_ASN1_VERSION} STREQUAL "Rel15")
 endif  (${RRC_ASN1_VERSION} STREQUAL "Rel8")
 add_definitions(-DRRC_VERSION=${RRC_VERSION})
 set (RRC_FULL_DIR ${asn1_generated_dir}/RRC_${RRC_ASN1_VERSION})
-message("calling asn1c -pdu=all -fcompound-names -gen-PER -no-gen-OER -no-gen-example -D ${RRC_FULL_DIR} ${RRC_GRAMMAR}")
-execute_process(COMMAND mkdir -p ${RRC_FULL_DIR}
-                COMMAND env asn1c -pdu=all -fcompound-names -gen-PER -no-gen-OER -no-gen-example -D ${RRC_FULL_DIR} ${RRC_GRAMMAR}
-                RESULT_VARIABLE ret
-		OUTPUT_QUIET
-                ERROR_QUIET)
+
+# Warning: if you modify ASN.1 source file to generate new C files, cmake should be re-run instead of make
+execute_process(COMMAND ${OPENAIR_CMAKE}/tools/make_asn1c_includes.sh "${RRC_FULL_DIR}" "${RRC_GRAMMAR}" 
+                RESULT_VARIABLE ret)
 if (NOT ${ret} STREQUAL 0)
   message(FATAL_ERROR "${ret}: error")
 endif (NOT ${ret} STREQUAL 0)
-
 file(GLOB rrc_source ${RRC_FULL_DIR}/*.c)
-file(GLOB rrc_h ${RRC_FULL_DIR}/*.h)
-set(rrc_h ${rrc_h} ${RRC_FULL_DIR}/asn_constant.h)
-set_source_files_properties(${rrc_source} PROPERTIES COMPILE_FLAGS -w) # suppress warnings from generated code
-add_library(RRC_LIB ${rrc_h} ${rrc_source}
-    ${OPENAIR2_DIR}/RRC/LTE/MESSAGES/asn1_msg.c
-    ${OPENAIR2_DIR}/RRC/LTE/MESSAGES/asn1_msg_NB_IoT.c)
-include_directories ("${RRC_FULL_DIR}")
-
-# add the command to generate the source code
-# Warning: if you modify ASN.1 source file to generate new C files, cmake should be re-run instead of make
-add_custom_command (
-  OUTPUT ${RRC_FULL_DIR}/asn_constant.h
-  COMMAND mkdir -p ${RRC_FULL_DIR}
-  COMMAND env asn1c -pdu=all -fcompound-names -gen-PER -no-gen-OER -no-gen-example -D ${RRC_FULL_DIR} ${RRC_GRAMMAR}
+add_custom_target (
+  rrc_flag ALL
+  ${OPENAIR_CMAKE}/tools/make_asn1c_includes.sh "${RRC_FULL_DIR}" "${RRC_GRAMMAR}"
   DEPENDS ${RRC_GRAMMAR}
   )
 
+add_library(RRC_LIB ${rrc_source}
+    ${OPENAIR2_DIR}/RRC/LTE/MESSAGES/asn1_msg.c
+    ${OPENAIR2_DIR}/RRC/LTE/MESSAGES/asn1_msg_NB_IoT.c)
+add_dependencies(RRC_LIB rrc_flag)
+include_directories ("${RRC_FULL_DIR}")
 
 #NR RRC
 ######
@@ -361,34 +351,26 @@ endif  (${NR_RRC_ASN1_VERSION} STREQUAL "NR_Rel15")
 add_definitions(-DNR_RRC_VERSION=${NR_RRC_VERSION})
 set (NR_RRC_FULL_DIR ${asn1_generated_dir}/${NR_RRC_ASN1_VERSION})
 
-message("calling ASN1C_PREFIX=NR_ asn1c -pdu=all -fcompound-names -findirect-choice -gen-PER -no-gen-OER -no-gen-example -D ${NR_RRC_FULL_DIR} ${NR_RRC_GRAMMAR}")
-execute_process(COMMAND mkdir -p ${NR_RRC_FULL_DIR}
-                COMMAND env "ASN1C_PREFIX=NR_" asn1c -fcompound-names -findirect-choice -gen-PER -no-gen-OER -no-gen-example -D ${NR_RRC_FULL_DIR} ${NR_RRC_GRAMMAR}
-                RESULT_VARIABLE ret
-		OUTPUT_QUIET
-		ERROR_QUIET)
-
-#if (NOT ${ret} STREQUAL 0)
-#   message(FATAL_ERROR "${ret}: error")
-#endif (NOT ${ret} STREQUAL 0)
-
+# Warning: if you modify ASN.1 source file to generate new C files, cmake should be re-run instead of make
+execute_process(COMMAND ${OPENAIR_CMAKE}/tools/make_asn1c_includes.sh "${NR_RRC_FULL_DIR}" "${NR_RRC_GRAMMAR}" "NR_" "-findirect-choice"
+                RESULT_VARIABLE ret)
+if (NOT ${ret} STREQUAL 0)
+  message(FATAL_ERROR "${ret}: error")
+endif ()
 file(GLOB nr_rrc_source ${NR_RRC_FULL_DIR}/*.c)
 file(GLOB nr_rrc_h ${NR_RRC_FULL_DIR}/*.h)
-set(nr_rrc_h ${nr_rrc_h} ${NR_RRC_FULL_DIR}/NR_asn_constant.h)
-#set_source_files_properties(${nr_rrc_source} PROPERTIES COMPILE_FLAGS -w) # suppress warnings from generated code
-add_library(NR_RRC_LIB 
-	    ${nr_rrc_h} 
-	    ${nr_rrc_source}
-            ${OPENAIR2_DIR}/RRC/NR/MESSAGES/asn1_msg.c)
-include_directories ("${NR_RRC_FULL_DIR}")
+add_custom_target (
+  nr_rrc_flag ALL
+  ${OPENAIR_CMAKE}/tools/make_asn1c_includes.sh "${NR_RRC_FULL_DIR}" "${NR_RRC_GRAMMAR}" "NR_" "-findirect-choice"
+  DEPENDS ${NR_RRC_GRAMMAR}
+  )
 
-# add the command to generate the source code
-# Warning: if you modify ASN.1 source file to generate new C files, cmake should be re-run instead of make
+add_library(NR_RRC_LIB ${nr_rrc_h} ${nr_rrc_source} 
+    ${OPENAIR2_DIR}/RRC/NR/MESSAGES/asn1_msg.c
+    )
+add_dependencies(NR_RRC_LIB nr_rrc_flag)
+include_directories ("${NR_RRC_FULL_DIR}")
 
-add_custom_command (OUTPUT ${NR_RRC_FULL_DIR}/NR_asn_constant.h
-  		    COMMAND mkdir -p ${NR_RRC_FULL_DIR}
-                    DEPENDS ${NR_RRC_GRAMMAR}
-                    )
 
 # S1AP
 # Same limitation as described in RRC: unknown generated file list
@@ -425,30 +407,26 @@ endif(${S1AP_RELEASE} STREQUAL "R8")
 add_definitions(-DS1AP_VERSION=${S1AP_VERSION})
 set(S1AP_ASN_DIR ${S1AP_DIR}/MESSAGES/ASN1/${S1AP_RELEASE})
 set(S1AP_C_DIR ${asn1_generated_dir}/S1AP_${S1AP_RELEASE})
-message("calling ASN1C_PREFIX=S1AP_ asn1c -pdu=all -fcompound-names -fno-include-deps -gen-PER -no-gen-OER -no-gen-example -D ${S1AP_C_DIR} ${S1AP_ASN_DIR}/${S1AP_ASN_FILES}")
-execute_process(COMMAND mkdir -p ${S1AP_C_DIR}
-                COMMAND env "ASN1C_PREFIX=S1AP_" asn1c -pdu=all -fcompound-names -fno-include-deps -gen-PER -no-gen-OER -no-gen-example -D ${S1AP_C_DIR} ${S1AP_ASN_DIR}/${S1AP_ASN_FILES}
-                RESULT_VARIABLE ret
-		OUTPUT_QUIET
-                ERROR_QUIET)
+
+# Warning: if you modify ASN.1 source file to generate new C files, cmake should be re-run instead of make
+execute_process(COMMAND ${OPENAIR_CMAKE}/tools/make_asn1c_includes.sh "${S1AP_C_DIR}" "${S1AP_ASN_DIR}/${S1AP_ASN_FILES}" "S1AP_" -fno-include-deps
+                RESULT_VARIABLE ret)
 if (NOT ${ret} STREQUAL 0)
   message(FATAL_ERROR "${ret}: error")
 endif (NOT ${ret} STREQUAL 0)
 file(GLOB S1AP_source ${S1AP_C_DIR}/*.c)
 
-file(GLOB s1ap_h ${S1AP_C_DIR}/*.h)
-set(s1ap_h ${s1ap_h})
-
-add_custom_command (
-  OUTPUT ${S1AP_C_DIR}/S1AP_asn_constant.h
-  COMMAND mkdir -p ${S1AP_C_DIR}
-  COMMAND env "ASN1C_PREFIX=S1AP_" asn1c -pdu=all -fcompound-names -fno-include-deps -gen-PER -no-gen-OER -no-gen-example -D ${S1AP_C_DIR} ${S1AP_ASN_DIR}/${S1AP_ASN_FILES}
-  DEPENDS ${S1AP_ASN_DIR}/${S1AP_ASN_FILES}
+add_custom_target (
+  s1ap_flag ALL
+  ${OPENAIR_CMAKE}/tools/make_asn1c_includes.sh "${S1AP_C_DIR}" "${S1AP_ASN_DIR}/${S1AP_ASN_FILES}" "S1AP_" -fno-include-deps
+  DEPENDS  "${S1AP_ASN_DIR}/${S1AP_ASN_FILES}" 
 )
+
 add_library(S1AP_LIB
   ${S1AP_source}
   ${S1AP_DIR}/s1ap_common.c
   )
+add_dependencies(S1AP_LIB rrc_flag s1ap_flag)
 
 include_directories ("${S1AP_C_DIR}")
 include_directories ("${S1AP_DIR}")
@@ -467,6 +445,7 @@ add_library(S1AP_ENB
   ${S1AP_DIR}/s1ap_eNB_trace.c
   ${S1AP_DIR}/s1ap_eNB_ue_context.c
   )
+add_dependencies(S1AP_ENB rrc_flag s1ap_flag)
 
 #X2AP
 # Same limitation as described in RRC/S1AP: unknown generated file list
@@ -494,24 +473,19 @@ endif(${X2AP_RELEASE} STREQUAL "R8")
 add_definitions(-DX2AP_VERSION=${X2AP_VERSION})
 set(X2AP_ASN_DIR ${X2AP_DIR}/MESSAGES/ASN1/${X2AP_RELEASE})
 set(X2AP_C_DIR ${asn1_generated_dir}/X2AP_${X2AP_RELEASE})
-message("calling ASN1C_PREFIX=X2AP_ asn1c -pdu=all -fcompound-names -fno-include-deps -gen-PER -no-gen-OER -no-gen-example -D ${X2AP_C_DIR} ${X2AP_ASN_DIR}/${X2AP_ASN_FILES}")
-execute_process(COMMAND mkdir -p ${X2AP_C_DIR}
-                COMMAND env "ASN1C_PREFIX=X2AP_" asn1c -pdu=all -fcompound-names -fno-include-deps -gen-PER -no-gen-OER -no-gen-example -D ${X2AP_C_DIR} ${X2AP_ASN_DIR}/${X2AP_ASN_FILES}
-                RESULT_VARIABLE ret
-                OUTPUT_QUIET
-                ERROR_QUIET)
+
+# Warning: if you modify ASN.1 source file to generate new C files, cmake should be re-run instead of make
+execute_process(COMMAND ${OPENAIR_CMAKE}/tools/make_asn1c_includes.sh "${X2AP_C_DIR}" "${X2AP_ASN_DIR}/${X2AP_ASN_FILES}"  "X2AP_" -fno-include-deps
+                RESULT_VARIABLE ret)
 if (NOT ${ret} STREQUAL 0)
   message(FATAL_ERROR "${ret}: error")
 endif (NOT ${ret} STREQUAL 0)
-file(GLOB X2AP_source ${X2AP_C_DIR}/*.c)
 
-file(GLOB x2ap_h ${X2AP_C_DIR}/*.h)
-set(x2ap_h ${x2ap_h})
+file(GLOB X2AP_source ${X2AP_C_DIR}/*.c)
 
-add_custom_command (
-  OUTPUT ${X2AP_C_DIR}/X2AP_asn_constant.h
-  COMMAND mkdir -p ${X2AP_C_DIR}
-  COMMAND env "ASN1C_PREFIX=X2AP_" asn1c -pdu=all -fcompound-names -fno-include-deps -gen-PER -no-gen-OER -no-gen-example -D ${X2AP_C_DIR} ${X2AP_ASN_DIR}/${X2AP_ASN_FILES}
+add_custom_target (
+  x2_flag ALL
+  COMMAND ${OPENAIR_CMAKE}/tools/make_asn1c_includes.sh "${X2AP_C_DIR}" "${X2AP_ASN_DIR}/${X2AP_ASN_FILES}"  "X2AP_" -fno-include-deps
   DEPENDS ${X2AP_ASN_DIR}/${X2AP_ASN_FILES}
   )
 
@@ -519,6 +493,7 @@ add_library(X2AP_LIB
   ${X2AP_source}
   ${X2AP_DIR}/x2ap_common.c
   )
+add_dependencies(X2AP_LIB rrc_flag x2_flag)
 
 include_directories ("${X2AP_C_DIR}")
 include_directories ("${X2AP_DIR}")
@@ -532,6 +507,7 @@ add_library(X2AP_ENB
   ${X2AP_DIR}/x2ap_eNB_management_procedures.c
   ${X2AP_DIR}/x2ap_eNB_generate_messages.c
  )
+add_dependencies(X2AP_ENB rrc_flag x2_flag)
 
 # Hardware dependant options
 ###################################
@@ -539,6 +515,10 @@ add_list1_option(NB_ANTENNAS_RX "2" "Number of antennas in reception" "1" "2" "4
 add_list1_option(NB_ANTENNAS_TX "4" "Number of antennas in transmission" "1" "2" "4")
 
 add_list2_option(RF_BOARD "EXMIMO" "RF head type" "None" "EXMIMO" "OAI_USRP" "OAI_BLADERF" "CPRIGW" "OAI_LMSSDR")
+if (NOT ${RF_BOARD} STREQUAL "None")
+   add_definitions(-DMANAGED_RF=1)
+endif()
+
 
 add_list2_option(TRANSP_PRO "None" "Transport protocol type" "None" "ETHERNET")
 #NOKIA config enhancement
@@ -639,6 +619,8 @@ set(HWLIB_TCP_BRIDGE_OAI_SOURCE
 add_library(tcp_bridge_oai MODULE ${HWLIB_TCP_BRIDGE_OAI_SOURCE} )
 set_target_properties(tcp_bridge_oai PROPERTIES COMPILE_FLAGS "-fvisibility=hidden")
 
+add_library(rfsimulator MODULE ${OPENAIR_TARGETS}/ARCH/rfsimulator/simulator.c)
+
 ##########################################################
 
 include_directories ("${OPENAIR_TARGETS}/ARCH/COMMON")
@@ -661,7 +643,6 @@ add_boolean_option(NAS_NETLINK False "useless ??? Must be True to compile nasmes
 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")
-add_list_string_option(PACKAGE_NAME "NotDefined" "As per attribute name")
 add_boolean_option(MESSAGE_CHART_GENERATOR False         "For generating sequence diagrams")
 add_boolean_option(MESSAGE_CHART_GENERATOR_RLC_MAC False "trace RLC-MAC exchanges in sequence diagrams")
 add_boolean_option(MESSAGE_CHART_GENERATOR_PHY     False "trace some PHY exchanges in sequence diagrams")
@@ -669,11 +650,7 @@ add_boolean_option(MESSAGE_CHART_GENERATOR_PHY     False "trace some PHY exchang
 add_boolean_option(UE_EXPANSION             False         "enable UE_EXPANSION with max 256 UE")
 add_boolean_option(PHY_TX_THREAD            False         "enable UE_EXPANSION with max 256 UE")
 add_boolean_option(PRE_SCD_THREAD           False         "enable UE_EXPANSION with max 256 UE")
-
-########################
-# Include order
-##########################
-add_boolean_option(ENB_MODE True "Swap the include directories between openair2 and openair3" )
+add_boolean_option(UESIM_EXPANSION          False         "enable UESIM_EXPANSION with max 256 UE")
 
 ##########################
 # SCHEDULING/REAL-TIME/PERF options
@@ -776,19 +753,13 @@ include_directories("${OPENAIR_BIN_DIR}")
 #include_directories("${include_dirs_all}")
 
 # Legacy exact order
-if(ENB_MODE)
-  include_directories("${OPENAIR2_DIR}/COMMON")
-  include_directories("${OPENAIR2_DIR}/UTIL")
-  include_directories("${OPENAIR2_DIR}/UTIL/LOG")
-  include_directories("${OPENAIR3_DIR}/COMMON")
-  include_directories("${OPENAIR3_DIR}/UTILS")
-else()
-  include_directories("${OPENAIR3_DIR}/COMMON")
-  include_directories("${OPENAIR3_DIR}/UTILS")
-  include_directories("${OPENAIR2_DIR}/COMMON")
-  include_directories("${OPENAIR2_DIR}/UTIL")
-  include_directories("${OPENAIR2_DIR}/UTIL/LOG")
-endif()
+
+include_directories("${OPENAIR2_DIR}/COMMON")
+include_directories("${OPENAIR2_DIR}/UTIL")
+include_directories("${OPENAIR2_DIR}/UTIL/LOG")
+include_directories("${OPENAIR3_DIR}/COMMON")
+include_directories("${OPENAIR3_DIR}/UTILS")
+
 include_directories("${NFAPI_DIR}/nfapi/public_inc")
 include_directories("${NFAPI_DIR}/common/public_inc")
 include_directories("${NFAPI_DIR}/pnf/public_inc")
@@ -927,6 +898,7 @@ add_library(FLEXRAN_AGENT
   ${OPENAIR2_DIR}/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac_internal.c
   ${OPENAIR2_DIR}/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac_slice_verification.c
   )
+add_dependencies(FLEXRAN_AGENT rrc_flag)
 set(FLEXRAN_AGENT_LIB FLEXRAN_AGENT)
 #include_directories(${OPENAIR2_DIR}/ENB_APP)
 
@@ -992,6 +964,7 @@ set(UTIL_SRC
 #  ${OPENAIR2_DIR}/UTIL/OTG/otg_rx.c
   )
 add_library(UTIL ${UTIL_SRC})
+add_dependencies(UTIL rrc_flag)
 
 #set(OMG_SUMO_SRC
 #  ${OPENAIR2_DIR}/UTIL/OMG/client_traci_OMG.c
@@ -1031,7 +1004,7 @@ set(SCHED_SRC
   ${OPENAIR1_DIR}/SCHED/phy_procedures_lte_common.c
 )
 add_library(SCHED_LIB ${SCHED_SRC})
-
+add_dependencies(SCHED_LIB rrc_flag)
 set(SCHED_NR_SRC
   ${OPENAIR1_DIR}/SCHED_NR/fapi_nr_l1.c
   ${OPENAIR1_DIR}/SCHED_NR/phy_procedures_nr_common.c
@@ -1045,6 +1018,7 @@ set(SCHED_SRC_RU
   ${OPENAIR1_DIR}/SCHED/prach_procedures.c
 )
 add_library(SCHED_RU_LIB ${SCHED_SRC_RU})
+add_dependencies(SCHED_RU_LIB rrc_flag)
 
 set(SCHED_SRC_UE
   ${OPENAIR1_DIR}/SCHED_UE/phy_procedures_lte_ue.c
@@ -1054,7 +1028,7 @@ set(SCHED_SRC_UE
   ${OPENAIR1_DIR}/SCHED_UE/srs_pc.c
 )
 add_library(SCHED_UE_LIB ${SCHED_SRC_UE})
-
+add_dependencies(SCHED_UE_LIB rrc_flag)
 set(SCHED_SRC_NR_UE
   ${OPENAIR1_DIR}/SCHED_NR_UE/phy_procedures_nr_ue.c
   ${OPENAIR1_DIR}/SCHED_NR/phy_procedures_nr_common.c
@@ -1116,6 +1090,7 @@ set(NFAPI_USER_SRC
   ${NFAPI_USER_DIR}/nfapi_vnf.c
 )
 add_library(NFAPI_USER_LIB ${NFAPI_USER_SRC})
+add_dependencies(NFAPI_USER_LIB rrc_flag)
 include_directories(${NFAPI_USER_DIR})
 
 # Layer 1
@@ -1154,11 +1129,7 @@ set(PHY_LDPCSRC
   )
 
 add_library(coding MODULE ${PHY_TURBOSRC} )
-
 set(PHY_SRC_COMMON
-  # depend on code generation from asn1c
-  ${RRC_FULL_DIR}/asn_constant.h
-  # actual source
   ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/dci_tools_common.c
   ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/lte_mcs.c
 #  ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/slss.c
@@ -1212,7 +1183,6 @@ set(PHY_SRC_COMMON
   )
 
 set(PHY_SRC
-  # actual source
   ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/pss.c
   ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/sss.c
   ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/sss_gen.c
@@ -1240,7 +1210,6 @@ set(PHY_SRC
   )
 
 set(PHY_SRC_RU
-  # actual source
   ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/if4_tools.c
   ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/if5_tools.c
   ${OPENAIR1_DIR}/PHY/MODULATION/slot_fep_ul.c
@@ -1255,7 +1224,6 @@ set(PHY_SRC_RU
   )
 
 set(PHY_SRC_UE
-  # actual source
   ${OPENAIR1_DIR}/PHY/LTE_UE_TRANSPORT/sss_ue.c
   ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/sss_gen.c
   ${OPENAIR1_DIR}/PHY/LTE_UE_TRANSPORT/dlsch_demodulation.c
@@ -1297,9 +1265,6 @@ set(PHY_SRC_UE
   )
 
   set(PHY_NR_SRC
-  # depend on code generation from asn1c
-  ${RRC_FULL_DIR}/asn_constant.h
-  # actual source
   ${OPENAIR1_DIR}/PHY/INIT/nr_init.c
   ${OPENAIR1_DIR}/PHY/INIT/nr_parms.c
   ${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_pss.c
@@ -1330,9 +1295,6 @@ set(PHY_SRC_UE
   )
 
   set(PHY_NR_UE_SRC
-  # depend on code generation from asn1c
-  ${RRC_FULL_DIR}/asn_constant.h
-  # actual source
   ${OPENAIR1_DIR}/PHY/MODULATION/slot_fep_nr.c
   ${OPENAIR1_DIR}/PHY/INIT/nr_parms.c
   ${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/pss_nr.c
@@ -1390,11 +1352,15 @@ if (${COMPILATION_AVX2} STREQUAL "True")
 endif ()
 
 add_library(PHY_COMMON ${PHY_SRC_COMMON})
+add_dependencies(PHY_COMMON rrc_flag)
 add_library(PHY ${PHY_SRC})
+add_dependencies(PHY rrc_flag)
 add_library(PHY_UE ${PHY_SRC_UE})
+add_dependencies(PHY_UE rrc_flag)
 add_library(PHY_NR ${PHY_NR_SRC})
 add_library(PHY_NR_UE ${PHY_NR_UE_SRC})
 add_library(PHY_RU ${PHY_SRC_RU})
+add_dependencies(PHY_RU rrc_flag)
 
 #Library for mex functions
 #########################3
@@ -1608,7 +1574,7 @@ add_library(L2
   ${MAC_SRC}
   ${ENB_APP_SRC}
   )
-
+add_dependencies(L2 rrc_flag s1ap_flag x2_flag)
 add_library(MAC_NR
   ${MAC_NR_SRC}
   )
@@ -1622,12 +1588,18 @@ add_library(L2_NR
   ${MAC_NR_SRC}
   ${GNB_APP_SRC}
   )
+add_dependencies(S1AP_LIB nr_rrc_flag s1ap_flag)
 
 add_library(L2_UE
   ${L2_SRC_UE}
   ${MAC_SRC_UE}
   #${MAC_NR_SRC_UE}
 )
+if (NOT ${NOS1})
+target_compile_definitions(L2_UE PUBLIC -DPDCP_USE_NETLINK)
+endif()
+
+add_dependencies(L2_UE rrc_flag s1ap_flag x2_flag)
 
 add_library( NR_L2_UE
     #${L2_SRC_UE}
@@ -1696,6 +1668,7 @@ set (GTPV1U_SRC
   ${GTPV1U_DIR}/gtpv1u_teid_pool.c
 )
 add_library(GTPV1U ${GTPV1U_SRC})
+add_dependencies(GTPV1U rrc_flag)
 
 set(SCTP_SRC
   ${OPENAIR3_DIR}/SCTP/sctp_common.c
@@ -1703,8 +1676,10 @@ set(SCTP_SRC
   ${OPENAIR3_DIR}/SCTP/sctp_eNB_itti_messaging.c
 )
 add_library(SCTP_CLIENT ${SCTP_SRC})
+add_dependencies(SCTP_CLIENT rrc_flag)
 
 add_library(UDP ${OPENAIR3_DIR}/UDP/udp_eNB_task.c)
+add_dependencies(UDP rrc_flag)
 
 
 set(NAS_SRC ${OPENAIR3_DIR}/NAS/)
@@ -1953,6 +1928,7 @@ if(NAS_UE)
     ${libnas_ue_esm_OBJS}
     ${libnas_ue_esm_sap_OBJS}
   )
+  add_dependencies(LIB_NAS_UE rrc_flag)
   set(NAS_UE_LIB LIB_NAS_UE)
 
   include_directories(${NAS_SRC}UE)
@@ -2213,8 +2189,6 @@ add_definitions(-DASN1_MINIMUM_VERSION=924)
 ###################################################
 
 add_executable(lte-softmodem
-  ${rrc_h}
-  ${s1ap_h}
   ${OPENAIR_TARGETS}/RT/USER/rt_wrapper.c
   ${OPENAIR_TARGETS}/RT/USER/lte-enb.c
   ${OPENAIR_TARGETS}/RT/USER/lte-ru.c
@@ -2236,6 +2210,7 @@ add_executable(lte-softmodem
   ${CONFIG_SOURCES}
   ${SHLIB_LOADER_SOURCES}
   )
+add_dependencies(lte-softmodem rrc_flag s1ap_flag x2_flag)
 
 target_link_libraries (lte-softmodem
   -Wl,--start-group
@@ -2252,8 +2227,6 @@ target_link_libraries (lte-softmodem ${T_LIB})
 # lte-softmodem-nos1 is both eNB and UE implementation
 ###################################################
 add_executable(lte-softmodem-nos1
-  ${rrc_h}
-  ${s1ap_h}
   ${OPENAIR_TARGETS}/RT/USER/rt_wrapper.c
   ${OPENAIR_TARGETS}/RT/USER/lte-enb.c
   ${OPENAIR_TARGETS}/RT/USER/lte-ru.c
@@ -2290,8 +2263,6 @@ target_link_libraries (lte-softmodem-nos1 ${T_LIB})
 #######################################
 
 add_executable(lte-uesoftmodem
-  ${rrc_h}
-  ${s1ap_h}
   ${OPENAIR_TARGETS}/RT/USER/rt_wrapper.c
   ${OPENAIR_TARGETS}/RT/USER/lte-ue.c
   ${OPENAIR_TARGETS}/RT/USER/lte-uesoftmodem.c
@@ -2313,6 +2284,10 @@ add_executable(lte-uesoftmodem
   ${SHLIB_LOADER_SOURCES}
   )
 
+add_dependencies(lte-uesoftmodem rrc_flag s1ap_flag x2_flag)
+if (NOT ${NOS1})
+	target_compile_definitions(lte-uesoftmodem PRIVATE -DPDCP_USE_NETLINK)
+endif()
 target_link_libraries (lte-uesoftmodem
   -Wl,--start-group
   RRC_LIB 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
@@ -2328,8 +2303,6 @@ target_link_libraries (lte-uesoftmodem ${T_LIB})
 # lte-uesoftmodem-nos1 is UE implementation
 ###################################################
 add_executable(lte-uesoftmodem-nos1
-  ${rrc_h}
-  ${s1ap_h}
   ${OPENAIR_TARGETS}/RT/USER/rt_wrapper.c
   ${OPENAIR_TARGETS}/RT/USER/lte-ue.c
   ${OPENAIR_TARGETS}/RT/USER/lte-uesoftmodem.c
@@ -2352,6 +2325,7 @@ add_executable(lte-uesoftmodem-nos1
   ${SHLIB_LOADER_SOURCES}
   )
 
+add_dependencies(lte-uesoftmodem-nos1 rrc_flag s1ap_flag x2_flag)
 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 SIMU ${RAL_LIB} ${ITTI_LIB}
@@ -2575,6 +2549,7 @@ foreach(myExe dlsim dlsim_tm7 ulsim pbchsim scansim mbmssim pdcchsim pucchsim pr
 
   add_executable(${myExe}
     ${OPENAIR1_DIR}/SIMULATION/LTE_PHY/${myExe}.c
+    ${OPENAIR_DIR}/common/utils/backtrace.c
     ${XFORMS_SOURCE}
     ${T_SOURCE}
     ${CONFIG_SOURCES}
@@ -2767,7 +2742,7 @@ endfunction(make_driver name dir src)
 # nashmesh module
 ################
 list(APPEND nasmesh_src device.c common.c ioctl.c classifier.c tool.c mesh.c)
-set(module_cc_opt "${module_cc_opt} -DNAS_NETLINK -DPDCP_USE_NETLINK")
+set(module_cc_opt "${module_cc_opt} -DNAS_NETLINK -DPDCP_USE_NETLINK -D${MKVER}")
 # legacy Makefile was using NAS_NETLINK flag, but other drivers the hereafter flag
 # so, this cmake use OAI_NW_DRIVER_USE_NETLINK everywhere
 if (OAI_NW_DRIVER_USE_NETLINK)
diff --git a/cmake_targets/build_oai b/cmake_targets/build_oai
index f018e8c4220037e68c93c9c3dd81c4e50e67f46c..2a4b13fe1d6d92b1f37bfa8d2291e295690cc3e2 100755
--- a/cmake_targets/build_oai
+++ b/cmake_targets/build_oai
@@ -250,7 +250,7 @@ function main() {
        -w | --hardware)
             HW="$2" #"${i#*=}"
             # Use OAI_USRP  as the key word USRP is used inside UHD driver
-	    if [ "$HW" != "BLADERF" -a  "$HW" != "USRP" -a "$HW" != "LMSSDR" -a  "$HW" != "None" -a  "$HW" != "EXMIMO" -a  "$HW" != "ADRV9371_ZC706"  ] ; then 
+	    if [ "$HW" != "BLADERF" -a  "$HW" != "USRP" -a "$HW" != "LMSSDR" -a  "$HW" != "None" -a  "$HW" != "EXMIMO" -a  "$HW" != "ADRV9371_ZC706"  -a  "$HW" != "SIMU" ] ; then 
 		echo_fatal "Unknown HW type $HW will exit..."		
 	    else
 		if [ "$HW" == "USRP" ] ; then 
@@ -265,6 +265,9 @@ function main() {
 		if [ "$HW" == "LMSSDR" ] ; then 
 		    HW="OAI_LMSSDR"
 		fi 
+		if [ "$HW" == "SIMU" ] ; then
+                    HW="OAI_SIMU"
+                fi
 		echo_info "Setting hardware to: $HW"
 	    fi
             shift 2;;
diff --git a/cmake_targets/tools/make_asn1c_includes.sh b/cmake_targets/tools/make_asn1c_includes.sh
new file mode 100755
index 0000000000000000000000000000000000000000..bd4254c9388e1a577ba8ca27ec4370f700022581
--- /dev/null
+++ b/cmake_targets/tools/make_asn1c_includes.sh
@@ -0,0 +1,15 @@
+#!/bin/bash
+GENERATED_FULL_DIR=$1
+shift
+ASN1_SOURCE_DIR=$1
+shift
+export ASN1C_PREFIX=$1 
+shift
+options=$*
+done_flag="$GENERATED_FULL_DIR"/done
+if [ "$done_flag" -ot $ASN1_SOURCE_DIR ] ; then 
+   rm -f "$GENERATED_FULL_DIR"/${ASN1C_PREFIX}*.c "$GENERATED_FULL_DIR"/${ASN1C_PREFIX}*.h
+   mkdir -p "$GENERATED_FULL_DIR"
+   asn1c -pdu=all -fcompound-names -gen-PER -no-gen-OER -no-gen-example $options -D $GENERATED_FULL_DIR $ASN1_SOURCE_DIR |& egrep -v "^Copied|^Compiled" | sort -u
+fi
+touch $done_flag
diff --git a/common/utils/backtrace.h b/common/utils/backtrace.h
index 9a77767cf4a11ede13185e9140b475e2f404adba..3977d0321c68c6f007edb2e451479f736c00e05c 100644
--- a/common/utils/backtrace.h
+++ b/common/utils/backtrace.h
@@ -23,9 +23,16 @@
 
 #ifndef BACKTRACE_H_
 #define BACKTRACE_H_
+#ifdef __cplusplus
+extern "C" {
+#endif
 
 void display_backtrace(void);
 
 void backtrace_handle_signal(siginfo_t *info);
+#ifdef __cplusplus
+}
+#endif
+
 
 #endif /* BACKTRACE_H_ */
diff --git a/openair1/PHY/TOOLS/lte_phy_scope.c b/openair1/PHY/TOOLS/lte_phy_scope.c
index 9f2ec54744941e783e0cb27cabeb19b93c95e4d5..d6f18ef3dfe3e1d58abec526d284d76e87074c80 100644
--- a/openair1/PHY/TOOLS/lte_phy_scope.c
+++ b/openair1/PHY/TOOLS/lte_phy_scope.c
@@ -151,12 +151,12 @@ FD_lte_phy_scope_enb *create_lte_phy_scope_enb( void )
 }
 
 void phy_scope_eNB(FD_lte_phy_scope_enb *form,
-                   PHY_VARS_eNB *phy_vars_enb,
+                   PHY_VARS_gNB *phy_vars_enb,
                    int UE_id)
 {
   int eNB_id = 0;
   int i,i2,arx,atx,ind,k;
-  LTE_DL_FRAME_PARMS *frame_parms = &phy_vars_enb->frame_parms;
+  NR_DL_FRAME_PARMS *frame_parms = &phy_vars_enb->frame_parms;
   int nsymb_ce = 12*frame_parms->N_RB_UL*frame_parms->symbols_per_tti;
   uint8_t nb_antennas_rx = frame_parms->nb_antennas_rx;
   uint8_t nb_antennas_tx = 1; // frame_parms->nb_antennas_tx; // in LTE Rel. 8 and 9 only a single transmit antenna is assumed at the UE
@@ -178,7 +178,7 @@ void phy_scope_eNB(FD_lte_phy_scope_enb *form,
   float time[FRAME_LENGTH_COMPLEX_SAMPLES];
   float time2[2048];
   float freq[nsymb_ce*nb_antennas_rx*nb_antennas_tx];
-  int frame = phy_vars_enb->proc.proc_rxtx[0].frame_tx;
+  int frame = phy_vars_enb->proc.L1_proc_tx.frame_tx;
   uint32_t total_dlsch_bitrate = phy_vars_enb->total_dlsch_bitrate;
   int coded_bits_per_codeword = 0;
   uint8_t harq_pid; // in TDD config 3 it is sf-2, i.e., can be 0,1,2
diff --git a/openair1/PHY/TOOLS/lte_phy_scope.h b/openair1/PHY/TOOLS/lte_phy_scope.h
index af9858ebad97796def7d13b4d007171fd61ca920..d6990db8ae5ef76280b96a59c6afaafa58c1e2e0 100644
--- a/openair1/PHY/TOOLS/lte_phy_scope.h
+++ b/openair1/PHY/TOOLS/lte_phy_scope.h
@@ -25,7 +25,7 @@
 #define FD_lte_scope_h_
 
 #include <forms.h>
-#include "PHY/defs_eNB.h"
+#include "PHY/defs_gNB.h"
 #include "PHY/defs_UE.h"
 #include "PHY/impl_defs_top.h"
 
@@ -66,7 +66,7 @@ FD_lte_phy_scope_enb * create_lte_phy_scope_enb( void );
 FD_lte_phy_scope_ue * create_lte_phy_scope_ue( void );
 
 void phy_scope_eNB(FD_lte_phy_scope_enb *form,
-                   PHY_VARS_eNB *phy_vars_enb,
+                   PHY_VARS_gNB *phy_vars_gnb,
                    int UE_id);
 
 void phy_scope_UE(FD_lte_phy_scope_ue *form,
diff --git a/openair1/PHY/defs_RU.h b/openair1/PHY/defs_RU.h
index 585f28f90fbce0e0f421d8b17564b4c6a1a1eb81..76769ed4db3866767b88eae7226f99eb94ec3fbb 100644
--- a/openair1/PHY/defs_RU.h
+++ b/openair1/PHY/defs_RU.h
@@ -399,7 +399,7 @@ typedef struct RU_t_s{
   /// function pointer to release function for radio interface
   int                  (*stop_rf)(struct RU_t_s *ru);
   /// function pointer to initialization function for radio interface
-  int                  (*start_if)(struct RU_t_s *ru,struct PHY_VARS_eNB_s *eNB);
+  int                  (*start_if)(struct RU_t_s *ru,struct PHY_VARS_gNB_s *gNB);
   /// function pointer to RX front-end processing routine (DFTs/prefix removal or NULL)
   void                 (*feprx)(struct RU_t_s *ru);
   /// function pointer to TX front-end processing routine (IDFTs and prefix removal or NULL)
diff --git a/openair1/PHY/defs_common.h b/openair1/PHY/defs_common.h
index f479c30b8cd0b0ef47ff4dab634033b77a8806cb..30e78f3832ed79b4228c32c7205bdf8283443a13 100644
--- a/openair1/PHY/defs_common.h
+++ b/openair1/PHY/defs_common.h
@@ -78,8 +78,8 @@
 
 #include "defs_RU.h"
 
-#define RX_NB_TH_MAX 2
-#define RX_NB_TH 2
+#define RX_NB_TH_MAX 1
+#define RX_NB_TH 1
 
 #define LTE_SLOTS_PER_SUBFRAME 2
 
diff --git a/openair1/SCHED_NR/phy_procedures_nr_common.c b/openair1/SCHED_NR/phy_procedures_nr_common.c
index 1a0a02f22df0aad6c9e001e43bc03d62ab4ce093..030a3733c201be9d2a953f86a6b17740c66f930d 100644
--- a/openair1/SCHED_NR/phy_procedures_nr_common.c
+++ b/openair1/SCHED_NR/phy_procedures_nr_common.c
@@ -36,4 +36,6 @@ nr_subframe_t nr_slot_select(nfapi_nr_config_request_t *cfg,unsigned char slot)
 {
   if (cfg->subframe_config.duplex_mode.value == FDD)
     return(SF_DL);
+  LOG_E(PHY,"Not developped TDD mode\n");
+  return -1;
 }
diff --git a/openair1/SCHED_UE/phy_procedures_lte_ue.c b/openair1/SCHED_UE/phy_procedures_lte_ue.c
index 3ace8ee79ae35f6c6010082601fec2e281340611..bfb6b1b467d3185408ed72538efdc49020cc5fc1 100644
--- a/openair1/SCHED_UE/phy_procedures_lte_ue.c
+++ b/openair1/SCHED_UE/phy_procedures_lte_ue.c
@@ -2885,10 +2885,10 @@ int ue_pdcch_procedures(uint8_t eNB_id,PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint
 	      {
                 ue->dlsch[th_id][eNB_id][0]->g_pucch += delta_pucch;
 	      }
-            LOG_D(PHY,"update TPC for PUCCH %d.%d / pid %d delta_PUCCH %d g_pucch %d %d \n",frame_rx, subframe_rx,ue->dlsch[ue->current_thread_id[subframe_rx]][eNB_id][0]->current_harq_pid,
+            LOG_D(PHY,"update TPC for PUCCH %d.%d / pid %d delta_PUCCH %d g_pucch %d\n",
+			    frame_rx, subframe_rx,ue->dlsch[ue->current_thread_id[subframe_rx]][eNB_id][0]->current_harq_pid,
 		  delta_pucch,
-		  ue->dlsch[0][eNB_id][0]->g_pucch,
-		  ue->dlsch[1][eNB_id][0]->g_pucch
+		  ue->dlsch[0][eNB_id][0]->g_pucch
 		  //ue->dlsch[2][eNB_id][0]->g_pucch
 		  );
           }
diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c
index d29a9fb90887cc9185595dcd111b3b132c8b56b9..d6166045c64f171dea9ad33f7b18127817907cb2 100644
--- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c
+++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c
@@ -58,6 +58,7 @@
 #endif
 
 #include "assertions.h"
+#include <openair1/PHY/LTE_TRANSPORT/transport_proto.h>
 
 #define ENABLE_MAC_PAYLOAD_DEBUG
 #define DEBUG_eNB_SCHEDULER 1
@@ -382,7 +383,7 @@ void gNB_dlsch_ulsch_scheduler(module_id_t module_idP,
           }
 
           for (int ii=0; ii<MAX_MOBILES_PER_GNB; ii++) {
-            LTE_eNB_DLSCH_t *dlsch = RC.gNB[module_idP][CC_id]->dlsch[ii][0];
+            NR_gNB_DLSCH_t *dlsch = RC.gNB[module_idP][CC_id]->dlsch[ii][0];
             if((dlsch != NULL) && (dlsch->rnti == rnti)){
               LOG_I(MAC, "clean_eNb_dlsch UE %x \n", rnti);
               clean_eNb_dlsch(dlsch);
diff --git a/targets/ARCH/COMMON/common_lib.c b/targets/ARCH/COMMON/common_lib.c
index cf62304ec88d6d004819e510ce6e26659fdf02c5..bcfa08c7eb23a108c461c5e46d2fe83d533ef801 100644
--- a/targets/ARCH/COMMON/common_lib.c
+++ b/targets/ARCH/COMMON/common_lib.c
@@ -34,40 +34,42 @@
 #include <dlfcn.h>
 #include <errno.h>
 #include <string.h>
+#include <stdlib.h>
 
 #include "common_lib.h"
 #include "common/utils/load_module_shlib.h"
+#include <common/utils/LOG/log.h>
 
 int set_device(openair0_device *device) {
 
   switch (device->type) {
     
   case EXMIMO_DEV:
-    printf("[%s] has loaded EXPRESS MIMO device.\n",((device->host_type == RAU_HOST) ? "RAU": "RRU"));
+    LOG_I(HW,"[%s] has loaded EXPRESS MIMO device.\n",((device->host_type == RAU_HOST) ? "RAU": "RRU"));
     break;
   case USRP_B200_DEV:
-    printf("[%s] has loaded USRP B200 device.\n",((device->host_type == RAU_HOST) ? "RAU": "RRU")); 
+    LOG_I(HW,"[%s] has loaded USRP B200 device.\n",((device->host_type == RAU_HOST) ? "RAU": "RRU")); 
     break;
-case USRP_X300_DEV:
-    printf("[%s] has loaded USRP X300 device.\n",((device->host_type == RAU_HOST) ? "RAU": "RRU")); 
+  case USRP_X300_DEV:
+    LOG_I(HW,"[%s] has loaded USRP X300 device.\n",((device->host_type == RAU_HOST) ? "RAU": "RRU")); 
     break;
   case BLADERF_DEV:
-    printf("[%s] has loaded BLADERF device.\n",((device->host_type == RAU_HOST) ? "RAU": "RRU")); 
+    LOG_I(HW,"[%s] has loaded BLADERF device.\n",((device->host_type == RAU_HOST) ? "RAU": "RRU")); 
     break;
   case LMSSDR_DEV:
-    printf("[%s] has loaded LMSSDR device.\n",((device->host_type == RAU_HOST) ? "RAU": "RRU")); 
+    LOG_I(HW,"[%s] has loaded LMSSDR device.\n",((device->host_type == RAU_HOST) ? "RAU": "RRU")); 
     break;
   case NONE_DEV:
-    printf("[%s] has not loaded a HW device.\n",((device->host_type == RAU_HOST) ? "RAU": "RRU"));
+    LOG_W(HW,"[%s] has not loaded a HW device.\n",((device->host_type == RAU_HOST) ? "RAU": "RRU"));
     break;    
   case ADRV9371_ZC706_DEV:
-    printf("[%s] has loaded ADRV9371_ZC706 device.\n",((device->host_type == RAU_HOST) ? "RAU": "RRU"));
+    LOG_I(HW,"[%s] has loaded ADRV9371_ZC706 device.\n",((device->host_type == RAU_HOST) ? "RAU": "RRU"));
     break;
   case UEDv2_DEV:
-    printf("[%s] has loaded UEDv2 device.\n",((device->host_type == RAU_HOST) ? "RAU": "RRU"));
+    LOG_I(HW,"[%s] has loaded UEDv2 device.\n",((device->host_type == RAU_HOST) ? "RAU": "RRU"));
     break;
   default:
-    printf("[%s] invalid HW device.\n",((device->host_type == RAU_HOST) ? "RAU": "RRU")); 
+    LOG_E(HW,"[%s] invalid HW device.\n",((device->host_type == RAU_HOST) ? "RAU": "RRU")); 
     return -1;
   }
   return 0;
@@ -78,15 +80,15 @@ int set_transport(openair0_device *device) {
   switch (device->transp_type) {
     
   case ETHERNET_TP:
-    printf("[%s] has loaded ETHERNET trasport protocol.\n",((device->host_type == RAU_HOST) ? "RAU": "RRU"));
+    LOG_I(HW,"[%s] has loaded ETHERNET trasport protocol.\n",((device->host_type == RAU_HOST) ? "RAU": "RRU"));
     return 0;     
     break;
   case NONE_TP:
-    printf("[%s] has not loaded a transport protocol.\n",((device->host_type == RAU_HOST) ? "RAU": "RRU"));
+    LOG_W(HW,"[%s] has not loaded a transport protocol.\n",((device->host_type == RAU_HOST) ? "RAU": "RRU"));
     return 0; 
     break;    
   default:
-    printf("[%s] invalid transport protocol.\n",((device->host_type == RAU_HOST) ? "RAU": "RRU")); 
+    LOG_E(HW,"[%s] invalid transport protocol.\n",((device->host_type == RAU_HOST) ? "RAU": "RRU")); 
     return -1;
     break;
   }
@@ -100,6 +102,9 @@ int load_lib(openair0_device *device, openair0_config_t *openair0_cfg, eth_param
   int ret=0;
   char *libname;
   if (flag == RAU_LOCAL_RADIO_HEAD) {
+	  if (getenv("RFSIMULATOR") != NULL) 
+     	  libname="rfsimulator";
+	  else 
       libname=OAI_RF_LIBNAME;
       shlib_fdesc[0].fname="device_init";
     } else {
@@ -108,7 +113,7 @@ int load_lib(openair0_device *device, openair0_config_t *openair0_cfg, eth_param
     } 
   ret=load_module_shlib(libname,shlib_fdesc,1,NULL);
   if (ret < 0) {
-       fprintf(stderr,"Library %s couldn't be loaded\n",libname);
+       LOG_E(HW,"Library %s couldn't be loaded\n",libname);
   } else {
        ret=((devfunc_t)shlib_fdesc[0].fptr)(device,openair0_cfg,cfg);
   }    
@@ -124,7 +129,7 @@ int openair0_device_load(openair0_device *device, openair0_config_t *openair0_cf
 
   if ( rc >= 0) {       
 	if ( set_device(device) < 0) {
-      fprintf(stderr, "%s %d:Unsupported radio head\n",__FILE__, __LINE__);
+      LOG_E(HW,"Unsupported radio head\n");
       return -1;		   
     }   
   }
@@ -136,7 +141,7 @@ int openair0_transport_load(openair0_device *device, openair0_config_t *openair0
   rc=load_lib(device, openair0_cfg, eth_params, RAU_REMOTE_RADIO_HEAD);
   if ( rc >= 0) {       
     if ( set_transport(device) < 0) {
-      fprintf(stderr, "%s %d:Unsupported transport protocol\n",__FILE__, __LINE__);
+      LOG_E(HW,"Unsupported transport protocol\n");
       return -1;		   
       }   
   }
diff --git a/targets/ARCH/rfsimulator/README.md b/targets/ARCH/rfsimulator/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..8a8ca3c8adc5f42f0a88528dea60145bc9a08fa6
--- /dev/null
+++ b/targets/ARCH/rfsimulator/README.md
@@ -0,0 +1,39 @@
+#General
+This is a RF simulator that allows to test OAI without a RF board.
+It replaces a actual RF board driver.
+
+As much as possible, it works like a RF board, but not in realtime: it can run faster than realtime if there is enough CPU or slower (it is CPU bound instead of real time RF sampling bound)
+
+#build 
+You can build it the same way, and together with actual RF driver
+
+Example:
+```bash
+./build_oai --ue-nas-use-tun --UE --eNB -w SIMU
+```
+It is also possible to build actual RF and use choose on each run:
+```bash
+./build_oai --ue-nas-use-tun --UE --eNB -w USRP --rfsimulator
+```
+Will build both the eNB (lte-softmodem) and the UE (lte-uesoftmodem)
+We recommend to use the option --ue-nas-use-tun that is much simpler to use than the OAI kernel driver.
+
+#usage
+Setting the env variable RFSIMULATOR enables the RF board simulator
+It should the set to "enb" in the eNB
+
+For the UE, it should be set to the IP address of the eNB
+example: 
+```bash
+sudo RFSIMULATOR=192.168.2.200 ./lte-uesoftmodem -C 2685000000 -r 50 
+```
+Except this, the UE and the eNB can be used as it the RF is real
+
+If you reach 'RA not active' on UE, be careful to generate a valid SIM
+```bash
+$OPENAIR_DIR/targets/bin/conf2uedata -c $OPENAIR_DIR/openair3/NAS/TOOLS/ue_eurecom_test_sfr.conf -o .
+```
+#Caveacts
+Still issues in power control: txgain, rxgain are not used
+
+no S1 mode is currently broken, so we were not able to test the simulator in noS1 mode
diff --git a/targets/ARCH/rfsimulator/simulator.c b/targets/ARCH/rfsimulator/simulator.c
new file mode 100644
index 0000000000000000000000000000000000000000..03084b538feb5347e4c28f12bd2e3ab5751c86dd
--- /dev/null
+++ b/targets/ARCH/rfsimulator/simulator.c
@@ -0,0 +1,478 @@
+/*
+  Author: Laurent THOMAS, Open Cells for Nokia
+  copyleft: OpenAirInterface Software Alliance and it's licence
+*/
+
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+#include <arpa/inet.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdbool.h>
+#include <errno.h>
+#include <sys/epoll.h>
+#include <string.h>
+
+#include <common/utils/assertions.h>
+#include <common/utils/LOG/log.h>
+#include "common_lib.h"
+#include <openair1/PHY/defs_eNB.h>
+#include "openair1/PHY/defs_UE.h"
+
+#define PORT 4043 //TCP port for this simulator
+#define CirSize 3072000 // 100ms is enough
+#define sample_t uint32_t // 2*16 bits complex number
+#define sampleToByte(a,b) ((a)*(b)*sizeof(sample_t))
+#define byteToSample(a,b) ((a)/(sizeof(sample_t)*(b)))
+#define MAGICeNB 0xA5A5A5A5A5A5A5A5
+#define MAGICUE  0x5A5A5A5A5A5A5A5A
+
+typedef struct {
+  uint64_t magic;
+  uint32_t size;
+  uint32_t nbAnt;
+  uint64_t timestamp;
+} transferHeader;
+
+typedef struct buffer_s {
+  int conn_sock;
+  bool alreadyWrote;
+  uint64_t lastReceivedTS;
+  bool headerMode;
+  transferHeader th;
+  char *transferPtr;
+  uint64_t remainToTransfer;
+  char *circularBufEnd;
+  sample_t *circularBuf;
+} buffer_t;
+
+
+typedef struct {
+  int listen_sock, epollfd;
+  uint64_t nextTimestamp;
+  uint64_t typeStamp;
+  uint64_t initialAhead;
+  char *ip;
+  buffer_t buf[FD_SETSIZE];
+} rfsimulator_state_t;
+
+void allocCirBuf(rfsimulator_state_t *bridge, int sock) {
+  buffer_t *ptr=&bridge->buf[sock];
+  AssertFatal ( (ptr->circularBuf=(sample_t *) malloc(sampleToByte(CirSize,1))) != NULL, "");
+  ptr->circularBufEnd=((char *)ptr->circularBuf)+sampleToByte(CirSize,1);
+  ptr->conn_sock=sock;
+  ptr->headerMode=true;
+  ptr->transferPtr=(char *)&ptr->th;
+  ptr->remainToTransfer=sizeof(transferHeader);
+  int sendbuff=1000*1000*10;
+  AssertFatal ( setsockopt(sock, SOL_SOCKET, SO_SNDBUF, &sendbuff, sizeof(sendbuff)) == 0, "");
+  struct epoll_event ev= {0};
+  ev.events = EPOLLIN | EPOLLRDHUP;
+  ev.data.fd = sock;
+  AssertFatal(epoll_ctl(bridge->epollfd, EPOLL_CTL_ADD,  sock, &ev) != -1, "");
+}
+
+void removeCirBuf(rfsimulator_state_t *bridge, int sock) {
+  AssertFatal( epoll_ctl(bridge->epollfd, EPOLL_CTL_DEL,  sock, NULL) != -1, "");
+  close(sock);
+  free(bridge->buf[sock].circularBuf);
+  memset(&bridge->buf[sock], 0, sizeof(buffer_t));
+  bridge->buf[sock].conn_sock=-1;
+}
+
+#define helpTxt "\
+\x1b[31m\
+rfsimulator: error: you have to run one UE and one eNB\n\
+For this, export RFSIMULATOR=enb (eNB case) or \n\
+                 RFSIMULATOR=<an ip address> (UE case)\n\
+\x1b[m"
+
+int fullwrite(int fd, void *_buf, int count) {
+  char *buf = _buf;
+  int ret = 0;
+  int l;
+
+  while (count) {
+    l = write(fd, buf, count);
+
+    if (l <= 0) {
+      if(errno==EAGAIN || errno==EINTR)
+        continue;
+      else
+        return -1;
+    }
+
+    count -= l;
+    buf += l;
+    ret += l;
+  }
+
+  return ret;
+}
+
+enum  blocking_t {
+  blocking,
+  notBlocking
+};
+
+void setblocking(int sock, enum blocking_t active) {
+  int opts;
+  AssertFatal( (opts = fcntl(sock, F_GETFL)) >= 0,"");
+
+  if (active==blocking)
+    opts = opts & ~O_NONBLOCK;
+  else
+    opts = opts | O_NONBLOCK;
+
+  AssertFatal(fcntl(sock, F_SETFL, opts) >= 0, "");
+}
+
+int server_start(openair0_device *device) {
+  rfsimulator_state_t *t = (rfsimulator_state_t *) device->priv;
+  t->typeStamp=MAGICeNB;
+  AssertFatal((t->listen_sock = socket(AF_INET, SOCK_STREAM, 0)) >= 0, "");
+  int enable = 1;
+  AssertFatal(setsockopt(t->listen_sock, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(int)) == 0, "");
+  struct sockaddr_in addr = {
+  sin_family: AF_INET,
+  sin_port: htons(PORT),
+  sin_addr: { s_addr: INADDR_ANY }
+  };
+  bind(t->listen_sock, (struct sockaddr *)&addr, sizeof(addr));
+  AssertFatal(listen(t->listen_sock, 5) == 0, "");
+  struct epoll_event ev;
+  ev.events = EPOLLIN;
+  ev.data.fd = t->listen_sock;
+  AssertFatal(epoll_ctl(t->epollfd, EPOLL_CTL_ADD,  t->listen_sock, &ev) != -1, "");
+  return 0;
+}
+
+int start_ue(openair0_device *device) {
+  rfsimulator_state_t *t = device->priv;
+  t->typeStamp=MAGICUE;
+  int sock;
+  AssertFatal((sock = socket(AF_INET, SOCK_STREAM, 0)) >= 0, "");
+  struct sockaddr_in addr = {
+  sin_family: AF_INET,
+  sin_port: htons(PORT),
+  sin_addr: { s_addr: INADDR_ANY }
+  };
+  addr.sin_addr.s_addr = inet_addr(t->ip);
+  bool connected=false;
+
+  while(!connected) {
+    LOG_I(HW,"rfsimulator: trying to connect to %s:%d\n", t->ip, PORT);
+
+    if (connect(sock, (struct sockaddr *)&addr, sizeof(addr)) == 0) {
+      LOG_I(HW,"rfsimulator: connection established\n");
+      connected=true;
+    }
+
+    perror("rfsimulator");
+    sleep(1);
+  }
+
+  setblocking(sock, notBlocking);
+  allocCirBuf(t, sock);
+  t->buf[sock].alreadyWrote=true; //+=t->initialAhead; // UE is slave
+  return 0;
+}
+
+int rfsimulator_write(openair0_device *device, openair0_timestamp timestamp, void **samplesVoid, int nsamps, int nbAnt, int flags) {
+  rfsimulator_state_t *t = device->priv;
+
+  for (int i=0; i<FD_SETSIZE; i++) {
+    buffer_t *ptr=&t->buf[i];
+
+    if (ptr->conn_sock >= 0 ) {
+      setblocking(ptr->conn_sock, blocking);
+      transferHeader header= {t->typeStamp, nsamps, nbAnt, timestamp};
+      int n=-1;
+      AssertFatal( fullwrite(ptr->conn_sock,&header, sizeof(header)) == sizeof(header), "");
+      sample_t tmpSamples[nsamps][nbAnt];
+
+      for(int a=0; a<nbAnt; a++) {
+        sample_t *in=(sample_t *)samplesVoid[a];
+
+        for(int s=0; s<nsamps; s++)
+          tmpSamples[s][a]=in[s];
+      }
+
+      n = fullwrite(ptr->conn_sock, (void *)tmpSamples, sampleToByte(nsamps,nbAnt));
+
+      if (n != sampleToByte(nsamps,nbAnt) ) {
+        LOG_E(HW,"rfsimulator: write error ret %d (wanted %ld) error %s\n", n, sampleToByte(nsamps,nbAnt), strerror(errno));
+        abort();
+      }
+
+      ptr->alreadyWrote=true; //+=nsamps;
+      setblocking(ptr->conn_sock, notBlocking);
+    }
+  }
+
+  LOG_D(HW,"sent %d samples at time: %ld->%ld, energy in first antenna: %d\n",
+        nsamps, timestamp, timestamp+nsamps, signal_energy(samplesVoid[0], nsamps) );
+  return nsamps;
+}
+
+bool flushInput(rfsimulator_state_t *t) {
+  // Process all incoming events on sockets
+  // store the data in lists
+  struct epoll_event events[FD_SETSIZE]= {0};
+  int nfds = epoll_wait(t->epollfd, events, FD_SETSIZE, 200);
+
+  if ( nfds==-1 ) {
+    if ( errno==EINTR || errno==EAGAIN )
+      return false;
+    else
+      AssertFatal(false,"error in epoll_wait\n");
+  }
+
+  for (int nbEv = 0; nbEv < nfds; ++nbEv) {
+    int fd=events[nbEv].data.fd;
+
+    if (events[nbEv].events & EPOLLIN && fd == t->listen_sock) {
+      int conn_sock;
+      AssertFatal( (conn_sock = accept(t->listen_sock,NULL,NULL)) != -1, "");
+      allocCirBuf(t, conn_sock);
+      LOG_I(HW,"A ue connected\n");
+    } else {
+      if ( events[nbEv].events & (EPOLLHUP | EPOLLERR | EPOLLRDHUP) ) {
+        LOG_W(HW,"Lost socket\n");
+        removeCirBuf(t, fd);
+
+        if (t->typeStamp==MAGICUE)
+          exit(1);
+
+        continue;
+      }
+
+      buffer_t *b=&t->buf[fd];
+
+      if ( b->circularBuf == NULL ) {
+        LOG_E(HW, "received data on not connected socket %d\n", events[nbEv].data.fd);
+        continue;
+      }
+
+      int blockSz;
+
+      if ( b->headerMode)
+        blockSz=b->remainToTransfer;
+      else
+        blockSz= b->transferPtr+b->remainToTransfer < b->circularBufEnd ?
+                 b->remainToTransfer :
+                 b->circularBufEnd - 1 - b->transferPtr ;
+
+      int sz=recv(fd, b->transferPtr, blockSz, MSG_DONTWAIT);
+
+      if ( sz < 0 ) {
+        if ( errno != EAGAIN ) {
+          LOG_E(HW,"socket failed %s\n", strerror(errno));
+          abort();
+        }
+      } else if ( sz == 0 )
+        continue;
+
+      AssertFatal((b->remainToTransfer-=sz) >= 0, "");
+      b->transferPtr+=sz;
+
+      if (b->transferPtr==b->circularBufEnd - 1)
+        b->transferPtr=(char *)b->circularBuf;
+
+      // check the header and start block transfer
+      if ( b->headerMode==true && b->remainToTransfer==0) {
+        AssertFatal( (t->typeStamp == MAGICUE  && b->th.magic==MAGICeNB) ||
+                     (t->typeStamp == MAGICeNB && b->th.magic==MAGICUE), "Socket Error in protocol");
+        b->headerMode=false;
+
+        if ( b->lastReceivedTS != b->th.timestamp) {
+          int nbAnt= b->th.nbAnt;
+
+          for (uint64_t index=b->lastReceivedTS; index < b->th.timestamp; index++ )
+            for (int a=0; a < nbAnt; a++)
+              b->circularBuf[(index*nbAnt+a)%CirSize]=0;
+
+          LOG_W(HW,"gap of: %ld in reception\n", b->th.timestamp-b->lastReceivedTS );
+        }
+
+        b->lastReceivedTS=b->th.timestamp;
+        b->transferPtr=(char *)&b->circularBuf[b->lastReceivedTS%CirSize];
+        b->remainToTransfer=sampleToByte(b->th.size, b->th.nbAnt);
+      }
+
+      if ( b->headerMode==false ) {
+        b->lastReceivedTS=b->th.timestamp+b->th.size-byteToSample(b->remainToTransfer,b->th.nbAnt);
+
+        if ( b->remainToTransfer==0) {
+          LOG_D(HW,"Completed block reception: %ld\n", b->lastReceivedTS);
+
+          // First block in UE, resync with the eNB current TS
+          if ( t->nextTimestamp == 0 )
+            t->nextTimestamp=b->lastReceivedTS-b->th.size;
+
+          b->headerMode=true;
+          b->transferPtr=(char *)&b->th;
+          b->remainToTransfer=sizeof(transferHeader);
+          b->th.magic=-1;
+        }
+      }
+    }
+  }
+
+  return nfds>0;
+}
+
+int rfsimulator_read(openair0_device *device, openair0_timestamp *ptimestamp, void **samplesVoid, int nsamps, int nbAnt) {
+  if (nbAnt != 1) { LOG_E(HW, "rfsimulator: only 1 antenna tested\n"); exit(1); }
+
+  rfsimulator_state_t *t = device->priv;
+  LOG_D(HW, "Enter rfsimulator_read, expect %d samples, will release at TS: %ld\n", nsamps, t->nextTimestamp+nsamps);
+  // deliver data from received data
+  // check if a UE is connected
+  int first_sock;
+
+  for (first_sock=0; first_sock<FD_SETSIZE; first_sock++)
+    if (t->buf[first_sock].circularBuf != NULL )
+      break;
+
+  if ( first_sock ==  FD_SETSIZE ) {
+    // no connected device (we are eNB, no UE is connected)
+    if (!flushInput(t)) {
+      for (int x=0; x < nbAnt; x++)
+        memset(samplesVoid[x],0,sampleToByte(nsamps,1));
+
+      t->nextTimestamp+=nsamps;
+      LOG_W(HW,"Generated void samples for Rx: %ld\n", t->nextTimestamp);
+
+      for (int a=0; a<nbAnt; a++) {
+        sample_t *out=(sample_t *)samplesVoid[a];
+
+        for ( int i=0; i < nsamps; i++ )
+          out[i]=0;
+      }
+
+      *ptimestamp = t->nextTimestamp-nsamps;
+      return nsamps;
+    }
+  } else {
+    bool have_to_wait;
+
+    do {
+      have_to_wait=false;
+
+      for ( int sock=0; sock<FD_SETSIZE; sock++)
+        if ( t->buf[sock].circularBuf &&
+             t->buf[sock].alreadyWrote && //>= t->initialAhead &&
+             (t->nextTimestamp+nsamps) > t->buf[sock].lastReceivedTS ) {
+          have_to_wait=true;
+          break;
+        }
+
+      if (have_to_wait)
+        /*printf("Waiting on socket, current last ts: %ld, expected at least : %ld\n",
+          ptr->lastReceivedTS,
+          t->nextTimestamp+nsamps);
+        */
+        flushInput(t);
+    } while (have_to_wait);
+  }
+
+  // Clear the output buffer
+  for (int a=0; a<nbAnt; a++) {
+    sample_t *out=(sample_t *)samplesVoid[a];
+
+    for ( int i=0; i < nsamps; i++ )
+      out[i]=0;
+  }
+
+  // Add all input signal in the output buffer
+  for (int sock=0; sock<FD_SETSIZE; sock++) {
+    buffer_t *ptr=&t->buf[sock];
+
+    if ( ptr->circularBuf && ptr->alreadyWrote ) {
+      for (int a=0; a<nbAnt; a++) {
+        sample_t *out=(sample_t *)samplesVoid[a];
+
+        for ( int i=0; i < nsamps; i++ )
+          out[i]+=ptr->circularBuf[((t->nextTimestamp+i)*nbAnt+a)%CirSize]<<1;
+      }
+    }
+  }
+
+  *ptimestamp = t->nextTimestamp; // return the time of the first sample
+  t->nextTimestamp+=nsamps;
+  LOG_D(HW,"Rx to upper layer: %d from %ld to %ld, energy in first antenna %d\n",
+        nsamps,
+        *ptimestamp, t->nextTimestamp,
+        signal_energy(samplesVoid[0], nsamps));
+  return nsamps;
+}
+
+
+int rfsimulator_request(openair0_device *device, void *msg, ssize_t msg_len) {
+  abort();
+  return 0;
+}
+int rfsimulator_reply(openair0_device *device, void *msg, ssize_t msg_len) {
+  abort();
+  return 0;
+}
+int rfsimulator_get_stats(openair0_device *device) {
+  return 0;
+}
+int rfsimulator_reset_stats(openair0_device *device) {
+  return 0;
+}
+void rfsimulator_end(openair0_device *device) {}
+int rfsimulator_stop(openair0_device *device) {
+  return 0;
+}
+int rfsimulator_set_freq(openair0_device *device, openair0_config_t *openair0_cfg,int exmimo_dump_config) {
+  return 0;
+}
+int rfsimulator_set_gains(openair0_device *device, openair0_config_t *openair0_cfg) {
+  return 0;
+}
+
+
+__attribute__((__visibility__("default")))
+int device_init(openair0_device *device, openair0_config_t *openair0_cfg) {
+  set_log(HW,OAILOG_DEBUG);
+  set_log(PHY,OAILOG_DEBUG);
+  rfsimulator_state_t *rfsimulator = (rfsimulator_state_t *)calloc(sizeof(rfsimulator_state_t),1);
+
+  if ((rfsimulator->ip=getenv("RFSIMULATOR")) == NULL ) {
+    LOG_E(HW,helpTxt);
+    exit(1);
+  }
+
+  rfsimulator->typeStamp = strncasecmp(rfsimulator->ip,"enb",3) == 0 ?
+                          MAGICeNB:
+                          MAGICUE;
+  LOG_I(HW,"rfsimulator: running as %s\n", rfsimulator-> typeStamp == MAGICeNB ? "eNB" : "UE");
+  device->trx_start_func       = rfsimulator->typeStamp == MAGICeNB ?
+                                 server_start :
+                                 start_ue;
+  device->trx_get_stats_func   = rfsimulator_get_stats;
+  device->trx_reset_stats_func = rfsimulator_reset_stats;
+  device->trx_end_func         = rfsimulator_end;
+  device->trx_stop_func        = rfsimulator_stop;
+  device->trx_set_freq_func    = rfsimulator_set_freq;
+  device->trx_set_gains_func   = rfsimulator_set_gains;
+  device->trx_write_func       = rfsimulator_write;
+  device->trx_read_func      = rfsimulator_read;
+  /* let's pretend to be a b2x0 */
+  device->type = USRP_B200_DEV;
+  device->openair0_cfg=&openair0_cfg[0];
+  device->priv = rfsimulator;
+
+  for (int i=0; i<FD_SETSIZE; i++)
+    rfsimulator->buf[i].conn_sock=-1;
+
+  AssertFatal((rfsimulator->epollfd = epoll_create1(0)) != -1,"");
+  rfsimulator->initialAhead=openair0_cfg[0].sample_rate/1000; // One sub frame
+  return 0;
+}
diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpn300.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpn300.conf
index 3aaf0c55060cecf80586fb640e3e6e584ac568af..b48ffd161b4f206de363a4ccc72e5b868ce8e428 100644
--- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpn300.conf
+++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpn300.conf
@@ -282,7 +282,7 @@ NETWORK_CONTROLLER :
      {
        global_log_level                      ="info";
        global_log_verbosity                  ="medium";
-       hw_log_level                          ="info";
+       hw_log_level                          ="debug";
        hw_log_verbosity                      ="medium";
        phy_log_level                         ="info";
        phy_log_verbosity                     ="medium";
diff --git a/targets/RT/USER/nr-ue.c b/targets/RT/USER/nr-ue.c
index 1dfa3dbd4fd8019fef47d9b1baa92f268be5c476..46353a29ff6473eb8c1d9eb64bc2f150a3cb6beb 100644
--- a/targets/RT/USER/nr-ue.c
+++ b/targets/RT/USER/nr-ue.c
@@ -630,7 +630,6 @@ static void *UE_thread_rxn_txnp4(void *arg) {
     struct nr_rxtx_thread_data *rtd = arg;
     UE_nr_rxtx_proc_t *proc = rtd->proc;
     PHY_VARS_NR_UE    *UE   = rtd->UE;
-    int ret;
 
     //proc->counter_decoder = 0;
     proc->instance_cnt_rxtx=-1;
@@ -782,7 +781,6 @@ void *UE_thread(void *arg) {
 
     PHY_VARS_NR_UE *UE = (PHY_VARS_NR_UE *) arg;
     //  int tx_enabled = 0;
-    int dummy_rx[UE->frame_parms.nb_antennas_rx][UE->frame_parms.samples_per_subframe] __attribute__((aligned(32)));
     openair0_timestamp timestamp;
     void* rxp[NB_ANTENNAS_RX], *txp[NB_ANTENNAS_TX];
     int start_rx_stream = 0;
@@ -834,45 +832,67 @@ void *UE_thread(void *arg) {
 
             if (instance_cnt_synch < 0) {  // we can invoke the synch
                 // grab 10 ms of signal and wakeup synch thread
-                for (int i=0; i<UE->frame_parms.nb_antennas_rx; i++)
-                    rxp[i] = (void*)&UE->common_vars.rxdata[i][0];
-
-                if (UE->mode != loop_through_memory)
-                    AssertFatal( UE->frame_parms.samples_per_subframe*10==
-                                 UE->rfdevice.trx_read_func(&UE->rfdevice,
-                                                            &timestamp,
-                                                            rxp,
-                                                            UE->frame_parms.samples_per_subframe*10,
-                                                            UE->frame_parms.nb_antennas_rx), "error reading samples");
-
-		AssertFatal ( 0== pthread_mutex_lock(&UE->proc.mutex_synch), "");
-                instance_cnt_synch = ++UE->proc.instance_cnt_synch;
-                if (instance_cnt_synch == 0) {
-                    AssertFatal( 0 == pthread_cond_signal(&UE->proc.cond_synch), "");
-                } else {
-                    LOG_E( PHY, "[SCHED][UE] UE sync thread busy!!\n" );
-                    exit_fun("nothing to add");
-                }
-		AssertFatal ( 0== pthread_mutex_unlock(&UE->proc.mutex_synch), "");
-            } else {
-#if OAISIM
-              (void)dummy_rx; /* avoid gcc warnings */
-              usleep(500);
-#else
-                // grab 10 ms of signal into dummy buffer
-                if (UE->mode != loop_through_memory) {
-                    for (int i=0; i<UE->frame_parms.nb_antennas_rx; i++)
-                        rxp[i] = (void*)&dummy_rx[i][0];
-                    for (int sf=0; sf<NR_NUMBER_OF_SUBFRAMES_PER_FRAME; sf++)
-                        //	    printf("Reading dummy sf %d\n",sf);
-		      AssertFatal(UE->frame_parms.samples_per_subframe==
-				 UE->rfdevice.trx_read_func(&UE->rfdevice,
-							    &timestamp,
-							    rxp,
-							    UE->frame_parms.samples_per_subframe,
-							    UE->frame_parms.nb_antennas_rx), "error reading samples");
-                }
-#endif
+	if (UE->mode != loop_through_memory) {
+	  void *dummy_tx[UE->frame_parms.nb_antennas_tx];
+	  for (int i=0; i<UE->frame_parms.nb_antennas_tx; i++)
+	    dummy_tx[i]=malloc16_clear(UE->frame_parms.samples_per_subframe*4);
+	  for(int x=0; x<10; x++) {
+	    for (int i=0; i<UE->frame_parms.nb_antennas_rx; i++)
+	      rxp[i] = ((void*)&UE->common_vars.rxdata[i][0]) + 4*x*UE->frame_parms.samples_per_subframe;
+	    AssertFatal( UE->frame_parms.samples_per_subframe ==
+			 UE->rfdevice.trx_read_func(&UE->rfdevice,
+						    &timestamp,
+						    rxp,
+						    UE->frame_parms.samples_per_subframe,
+						    UE->frame_parms.nb_antennas_rx), "");
+	    AssertFatal( UE->frame_parms.samples_per_subframe ==
+			 UE->rfdevice.trx_write_func(&UE->rfdevice,
+						     timestamp+(2*UE->frame_parms.samples_per_subframe) -
+						     openair0_cfg[0].tx_sample_advance,
+						     dummy_tx,
+						     UE->frame_parms.samples_per_subframe,
+						     UE->frame_parms.nb_antennas_tx,
+						     1),"");
+	  }
+	  for (int i=0; i<UE->frame_parms.nb_antennas_tx; i++)
+	    free(dummy_tx[i]);
+	}
+	AssertFatal( 0 == pthread_mutex_lock(&UE->proc.mutex_synch), "");
+	AssertFatal( 0 == ++UE->proc.instance_cnt_synch, "[SCHED][UE] UE sync thread busy!!\n" );
+        AssertFatal( 0 == pthread_cond_signal(&UE->proc.cond_synch), "");
+	AssertFatal( 0 == pthread_mutex_unlock(&UE->proc.mutex_synch), "");
+      } else {
+	// grab 10 ms of signal into dummy buffer to wait result of sync detection
+	if (UE->mode != loop_through_memory) {
+	  void *dummy_tx[UE->frame_parms.nb_antennas_tx];
+	  for (int i=0; i<UE->frame_parms.nb_antennas_tx; i++)
+	    dummy_tx[i]=malloc16_clear(UE->frame_parms.samples_per_subframe*4);
+	  void *dummy_rx[UE->frame_parms.nb_antennas_rx];
+	  for (int i=0; i<UE->frame_parms.nb_antennas_rx; i++)
+	    dummy_rx[i]=malloc16(UE->frame_parms.samples_per_subframe*4);
+	  for (int sf=0; sf<NR_NUMBER_OF_SUBFRAMES_PER_FRAME; sf++) {
+	    //	    printf("Reading dummy sf %d\n",sf);
+	    UE->rfdevice.trx_read_func(&UE->rfdevice,
+				       &timestamp,
+				       dummy_rx,
+				       UE->frame_parms.samples_per_subframe,
+				       UE->frame_parms.nb_antennas_rx);
+	  AssertFatal( UE->frame_parms.samples_per_subframe ==
+		       UE->rfdevice.trx_write_func(&UE->rfdevice,
+						   timestamp+(2*UE->frame_parms.samples_per_subframe) -
+						   openair0_cfg[0].tx_sample_advance,
+						   dummy_tx,
+						   UE->frame_parms.samples_per_subframe,
+						   UE->frame_parms.nb_antennas_tx,
+						   1),"");
+	   usleep(9000); // this sleep improves in the case of simulated RF and doesn't harm with true radio
+	  
+	  }
+	  for (int i=0; i<UE->frame_parms.nb_antennas_tx; i++)
+	    free(dummy_tx[i]);
+	  for (int i=0; i<UE->frame_parms.nb_antennas_rx; i++)
+	    free(dummy_rx[i]);
+	}
             }
 
         } // UE->is_synchronized==0
@@ -882,12 +902,28 @@ void *UE_thread(void *arg) {
                 if (UE->mode != loop_through_memory) {
                     if (UE->no_timing_correction==0) {
                         LOG_I(PHY,"Resynchronizing RX by %d samples (mode = %d)\n",UE->rx_offset,UE->mode);
-                        AssertFatal(UE->rx_offset ==
-                                    UE->rfdevice.trx_read_func(&UE->rfdevice,
-                                                               &timestamp,
-                                                               (void**)UE->common_vars.rxdata,
-                                                               UE->rx_offset,
-                                                               UE->frame_parms.nb_antennas_rx),"");
+		    void *dummy_tx[UE->frame_parms.nb_antennas_tx];
+		    for (int i=0; i<UE->frame_parms.nb_antennas_tx; i++)
+		      dummy_tx[i]=malloc16_clear(UE->frame_parms.samples_per_subframe*4);
+		    for ( int size=UE->rx_offset ; size > 0 ; size -= UE->frame_parms.samples_per_subframe ) { 
+		      int unitTransfer=size>UE->frame_parms.samples_per_subframe ? UE->frame_parms.samples_per_subframe : size ;
+		      AssertFatal(unitTransfer ==
+				  UE->rfdevice.trx_read_func(&UE->rfdevice,
+							     &timestamp,
+							     (void**)UE->common_vars.rxdata,
+							     unitTransfer,
+							     UE->frame_parms.nb_antennas_rx),"");
+		      AssertFatal( unitTransfer == 
+				   UE->rfdevice.trx_write_func(&UE->rfdevice,
+							       timestamp+(2*UE->frame_parms.samples_per_subframe) -
+							       openair0_cfg[0].tx_sample_advance,
+							       dummy_tx,
+							       unitTransfer,
+							       UE->frame_parms.nb_antennas_tx,
+							       1),"");
+		    }
+		    for (int i=0; i<UE->frame_parms.nb_antennas_tx; i++)
+		      free(dummy_tx[i]);
                     }
                     UE->rx_offset=0;
                     UE->time_sync_cell=0;
@@ -962,6 +998,7 @@ void *UE_thread(void *arg) {
                             UE->rx_offset_diff = 1;
 
                         LOG_D(PHY,"AbsSubframe %d.%d TTI SET rx_off_diff to %d rx_offset %d \n",proc->frame_rx,subframe_nr,UE->rx_offset_diff,UE->rx_offset);
+			
                         readBlockSize=UE->frame_parms.samples_per_subframe -
                                       UE->frame_parms.ofdm_symbol_size -
                                       UE->frame_parms.nb_prefix_samples0 -
@@ -1051,6 +1088,14 @@ void *UE_thread(void *arg) {
 #ifdef SAIF_ENABLED
 						g_ue_rx_thread_busy++;
 #endif
+	              if ( getenv("RFSIMULATOR") != NULL ) {
+		         do {
+			    AssertFatal (pthread_mutex_unlock(&proc->mutex_rxtx) == 0, "");
+			    usleep(100);
+			    AssertFatal (pthread_mutex_lock(&proc->mutex_rxtx) == 0, "");
+			 } while ( proc->instance_cnt_rxtx >= 0);
+
+		      } else
                       LOG_E( PHY, "[SCHED][UE %d] !! UE RX thread busy (IC %d)!!\n", UE->Mod_id, proc->instance_cnt_rxtx);
                       if (proc->instance_cnt_rxtx > 4)
                       {
diff --git a/targets/RT/USER/nr-uesoftmodem.c b/targets/RT/USER/nr-uesoftmodem.c
index 81f46d31b393212f83de1643b2454f5094767f90..45c3442d826e2532293ea4caaf1c00bc0f35010c 100644
--- a/targets/RT/USER/nr-uesoftmodem.c
+++ b/targets/RT/USER/nr-uesoftmodem.c
@@ -984,23 +984,16 @@ int main( int argc, char **argv ) {
     for (uint8_t i=0; i<RX_NB_TH_MAX; i++) {
       //UE[CC_id]->pdcch_vars[i][0]->agregationLevel = agregation_Level;
       //UE[CC_id]->pdcch_vars[i][0]->dciFormat     = dci_Format;
-    }
     
     /*compute_prach_seq(&UE[CC_id]->frame_parms.prach_config_common,
       UE[CC_id]->frame_parms.frame_type,
       UE[CC_id]->X_u);*/
     
     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;
-      }
+	UE[CC_id]->pdcch_vars[i][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]->pdcch_vars[i][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];