[0-9A-Za-z]+)\\\\r\\\\n', str(self.ssh.before))
if result is not None:
self.UsrpBoard = result.group('usrp_board')
@@ -3184,19 +3360,17 @@ class SSHConnection():
elif (str(status) == 'KO'):
if (processesStatus == 0):
self.htmlFile.write(' | ' + str(status) + ' | \n')
- elif (processesStatus == ENB_PROCESS_FAILED):
- self.htmlFile.write(' KO - eNB process not found | \n')
- elif (processesStatus == OAI_UE_PROCESS_FAILED):
- self.htmlFile.write(' KO - OAI UE process not found | \n')
+ elif (processesStatus == ENB_PROCESS_FAILED) or (processesStatus == UE_PROCESS_FAILED):
+ self.htmlFile.write(' KO - ' + machine + ' process not found | \n')
elif (processesStatus == ENB_PROCESS_SEG_FAULT):
self.htmlFile.write(' KO - ' + machine + ' process ended in Segmentation Fault | \n')
- elif (processesStatus == ENB_PROCESS_ASSERTION) or (processesStatus == OAI_UE_PROCESS_ASSERTION):
+ elif (processesStatus == ENB_PROCESS_ASSERTION) or (processesStatus == UE_PROCESS_ASSERTION):
self.htmlFile.write(' KO - ' + machine + ' process ended in Assertion | \n')
elif (processesStatus == ENB_PROCESS_REALTIME_ISSUE):
self.htmlFile.write(' KO - ' + machine + ' process faced Real Time issue(s) | \n')
- elif (processesStatus == ENB_PROCESS_NOLOGFILE_TO_ANALYZE) or (processesStatus == OAI_UE_PROCESS_NOLOGFILE_TO_ANALYZE):
+ elif (processesStatus == ENB_PROCESS_NOLOGFILE_TO_ANALYZE) or (processesStatus == UE_PROCESS_NOLOGFILE_TO_ANALYZE):
self.htmlFile.write(' OK? | \n')
- elif (processesStatus == OAI_UE_PROCESS_COULD_NOT_SYNC):
+ elif (processesStatus == UE_PROCESS_COULD_NOT_SYNC):
self.htmlFile.write(' KO - UE could not sync | \n')
elif (processesStatus == HSS_PROCESS_FAILED):
self.htmlFile.write(' KO - HSS process not found | \n')
@@ -3311,8 +3485,11 @@ def Usage():
print(' --XMLTestFile=[XML Test File to be run]')
print('------------------------------------------------------------')
+#def GetModeFromXML():
+# SSH.mode = test.findtext('mode')
+
def CheckClassValidity(action,id):
- if action != 'Build_eNB' and action != 'Initialize_eNB' and action != 'Terminate_eNB' and action != 'Initialize_UE' and action != 'Terminate_UE' and action != 'Attach_UE' and action != 'Detach_UE' and action != 'Build_OAI_UE' and action != 'Initialize_OAI_UE' and action != 'Terminate_OAI_UE' and action != 'Ping' and action != 'Iperf' and action != 'Reboot_UE' and action != 'Initialize_HSS' and action != 'Terminate_HSS' and action != 'Initialize_MME' and action != 'Terminate_MME' and action != 'Initialize_SPGW' and action != 'Terminate_SPGW' and action != 'Initialize_CatM_module' and action != 'Terminate_CatM_module' and action != 'Attach_CatM_module' and action != 'Detach_CatM_module' and action != 'Ping_CatM_module' and action != 'IdleSleep':
+ if action != 'Build_eNB' and action != 'Initialize_eNB' and action != 'Terminate_eNB' and action != 'Initialize_UE' and action != 'Terminate_UE' and action != 'Attach_UE' and action != 'Detach_UE' and action != 'Build_OAI_UE' and action != 'Initialize_OAI_UE' and action != 'Terminate_OAI_UE' and action != 'Initialize_OAI_eNB' and action != 'Ping' and action != 'Iperf' and action != 'Reboot_UE' and action != 'Initialize_HSS' and action != 'Terminate_HSS' and action != 'Initialize_MME' and action != 'Terminate_MME' and action != 'Initialize_SPGW' and action != 'Terminate_SPGW' and action != 'Initialize_CatM_module' and action != 'Terminate_CatM_module' and action != 'Attach_CatM_module' and action != 'Detach_CatM_module' and action != 'Ping_CatM_module' and action != 'IdleSleep':
logging.debug('ERROR: test-case ' + id + ' has wrong class ' + action)
return False
return True
@@ -3326,11 +3503,21 @@ def GetParametersFromXML(action):
SSH.eNB_instance = test.findtext('eNB_instance')
if (SSH.eNB_instance is None):
SSH.eNB_instance = '0'
-
+ SSH.air_interface = test.findtext('air_interface')
+ if (SSH.air_interface is None):
+ SSH.air_interface = 'lte'
+ else:
+ SSH.air_interface = SSH.air_interface.lower()
+
if action == 'Terminate_eNB':
SSH.eNB_instance = test.findtext('eNB_instance')
if (SSH.eNB_instance is None):
SSH.eNB_instance = '0'
+ SSH.air_interface = test.findtext('air_interface')
+ if (SSH.air_interface is None):
+ SSH.air_interface = 'lte'
+ else:
+ SSH.air_interface = SSH.air_interface.lower()
if action == 'Attach_UE':
nbMaxUEtoAttach = test.findtext('nbMaxUEtoAttach')
@@ -3341,12 +3528,33 @@ def GetParametersFromXML(action):
if action == 'Build_OAI_UE':
SSH.Build_OAI_UE_args = test.findtext('Build_OAI_UE_args')
+ SSH.clean_repository = test.findtext('clean_repository')
+ if (SSH.clean_repository == 'false'):
+ SSH.clean_repository = False
+ else:
+ SSH.clean_repository = True
if action == 'Initialize_OAI_UE':
SSH.Initialize_OAI_UE_args = test.findtext('Initialize_OAI_UE_args')
SSH.UE_instance = test.findtext('UE_instance')
if (SSH.UE_instance is None):
SSH.UE_instance = '0'
+ SSH.air_interface = test.findtext('air_interface')
+ if (SSH.air_interface is None):
+ SSH.air_interface = 'lte'
+ else:
+ SSH.air_interface = SSH.air_interface.lower()
+
+ if action == 'Initialize_OAI_eNB':
+ SSH.Initialize_OAI_eNB_args = test.findtext('Initialize_OAI_eNB_args')
+ SSH.UE_instance = test.findtext('eNB_instance')
+ if (SSH.eNB_instance is None):
+ SSH.eNB_instance = '0'
+ SSH.air_interface = test.findtext('air_interface')
+ if (SSH.air_interface is None):
+ SSH.air_interface = 'lte'
+ else:
+ SSH.air_interface = SSH.air_interface.lower()
if action == 'Terminate_OAI_UE':
SSH.eNB_instance = test.findtext('UE_instance')
@@ -3404,6 +3612,9 @@ while len(argvs) > 1:
sys.exit(0)
elif re.match('^\-\-mode=(.+)$', myArgv, re.IGNORECASE):
matchReg = re.match('^\-\-mode=(.+)$', myArgv, re.IGNORECASE)
+ #if matchReg and mode is not None:
+ #print('Warning: the mode is defined in both xml file and command line')
+ #print('ignoring the mode defined in the xml file')
mode = matchReg.group(1)
elif re.match('^\-\-eNBIPAddress=(.+)$', myArgv, re.IGNORECASE):
matchReg = re.match('^\-\-eNBIPAddress=(.+)$', myArgv, re.IGNORECASE)
@@ -3557,10 +3768,10 @@ elif re.match('^LogCollectIperf$', mode, re.IGNORECASE):
sys.exit('Insufficient Parameter')
SSH.LogCollectIperf()
elif re.match('^LogCollectOAIUE$', mode, re.IGNORECASE):
- if SSH.UEIPAddress == '' or SSH.UEUserName == '' or SSH.UEPassword == '' or SSH.UESourceCodePath == '':
- Usage()
- sys.exit('Insufficient Parameter')
- SSH.LogCollectOAIUE()
+ if SSH.UEIPAddress == '' or SSH.UEUserName == '' or SSH.UEPassword == '' or SSH.UESourceCodePath == '':
+ Usage()
+ sys.exit('Insufficient Parameter')
+ SSH.LogCollectOAIUE()
elif re.match('^InitiateHtml$', mode, re.IGNORECASE):
if (SSH.ADBIPAddress == '' or SSH.ADBUserName == '' or SSH.ADBPassword == ''):
Usage()
@@ -3569,9 +3780,11 @@ elif re.match('^InitiateHtml$', mode, re.IGNORECASE):
foundCount = 0
while (count < SSH.nbTestXMLfiles):
xml_test_file = cwd + "/" + SSH.testXMLfiles[count]
- xml_test_file = sys.path[0] + "/" + SSH.testXMLfiles[count]
if (os.path.isfile(xml_test_file)):
- xmlTree = ET.parse(xml_test_file)
+ try:
+ xmlTree = ET.parse(xml_test_file)
+ except:
+ print("Error while parsing file: " + xml_test_file)
xmlRoot = xmlTree.getroot()
SSH.htmlTabRefs.append(xmlRoot.findtext('htmlTabRef',default='test-tab-' + str(count)))
SSH.htmlTabNames.append(xmlRoot.findtext('htmlTabName',default='Test-' + str(count)))
@@ -3585,10 +3798,17 @@ elif re.match('^FinalizeHtml$', mode, re.IGNORECASE):
SSH.CreateHtmlFooter(SSH.finalStatus)
elif re.match('^TesteNB$', mode, re.IGNORECASE) or re.match('^TestUE$', mode, re.IGNORECASE):
if re.match('^TesteNB$', mode, re.IGNORECASE):
- if SSH.eNBIPAddress == '' or SSH.eNBRepository == '' or SSH.eNBBranch == '' or SSH.eNBUserName == '' or SSH.eNBPassword == '' or SSH.eNBSourceCodePath == '' or SSH.EPCIPAddress == '' or SSH.EPCUserName == '' or SSH.EPCPassword == '' or SSH.EPCType == '' or SSH.EPCSourceCodePath == '' or SSH.ADBIPAddress == '' or SSH.ADBUserName == '' or SSH.ADBPassword == '':
+ if (SSH.eNBRepository == '' or SSH.eNBBranch == '' or SSH.eNBSourceCodePath == ''):
+ Usage()
+ sys.exit('Insufficient Parameter')
+ if (SSH.eNBIPAddress == '' or SSH.eNBUserName == '' or SSH.eNBPassword == '') and (SSH.UEIPAddress == '' or SSH.UEUserName == '' or SSH.UEPassword == ''):
+ Usage()
+ sys.exit('Insufficient Parameter')
+ elif SSH.ADBIPAddress == 'none' and SSH.EPCIPAddress == 'none':
+ pass
+ elif SSH.EPCIPAddress == '' or SSH.EPCUserName == '' or SSH.EPCPassword == '' or SSH.EPCType == '' or SSH.EPCSourceCodePath == '' or SSH.ADBIPAddress == '' or SSH.ADBUserName == '' or SSH.ADBPassword == '':
Usage()
sys.exit('Insufficient Parameter')
-
if (SSH.EPCIPAddress != ''):
SSH.copyout(SSH.EPCIPAddress, SSH.EPCUserName, SSH.EPCPassword, cwd + "/tcp_iperf_stats.awk", "/tmp")
SSH.copyout(SSH.EPCIPAddress, SSH.EPCUserName, SSH.EPCPassword, cwd + "/active_net_interfaces.awk", "/tmp")
@@ -3658,6 +3878,7 @@ elif re.match('^TesteNB$', mode, re.IGNORECASE) or re.match('^TestUE$', mode, re
SSH.testCase_id = id
SSH.desc = test.findtext('desc')
action = test.findtext('class')
+ mode = test.findtext('mode')
if (CheckClassValidity(action, id) == False):
continue
SSH.ShowTestID()
@@ -3686,6 +3907,8 @@ elif re.match('^TesteNB$', mode, re.IGNORECASE) or re.match('^TestUE$', mode, re
SSH.InitializeOAIUE()
elif action == 'Terminate_OAI_UE':
SSH.TerminateOAIUE()
+ elif action == 'Initialize_OAI_eNB':
+ SSH.InitializeOAIeNB()
elif action == 'Initialize_CatM_module':
SSH.InitializeCatM()
elif action == 'Terminate_CatM_module':
diff --git a/ci-scripts/xml_files/gnb_nr_ue_usrp_run.xml b/ci-scripts/xml_files/gnb_nr_ue_usrp_run.xml
new file mode 100644
index 0000000000..f9d068c5b2
--- /dev/null
+++ b/ci-scripts/xml_files/gnb_nr_ue_usrp_run.xml
@@ -0,0 +1,64 @@
+
+
+ run-OAI-gNB-NR-UE-USRP
+ run OAI gNB and OAI NR UE USRP
+ tasks
+
+090101 000001 090102 000001 090108 090109
+
+
+
+
+ Initialize_OAI_eNB
+ Initialize gNB USRP
+ -O ../../../ci-scripts/conf_files/gnb.band78.tm1.106PRB.usrpn300.conf
+ NR
+
+
+
+ IdleSleep
+ Sleep
+ 5
+
+
+
+ Initialize_OAI_UE
+ Initialize NR UE USRP
+ -C 3510000000 --numerology 1 -r 106 --phy-test --usrp-args "addr=192.168.30.2,clock_source=external,time_source=external" --threadoffset 16
+ NR
+
+
+
+ Terminate_OAI_UE
+ Terminate NR UE
+ NR
+
+
+
+ Terminate_eNB
+ Terminate gNB
+ NR
+
+
+
diff --git a/ci-scripts/xml_files/gnb_usrp_build.xml b/ci-scripts/xml_files/gnb_usrp_build.xml
new file mode 100644
index 0000000000..1b57c077ba
--- /dev/null
+++ b/ci-scripts/xml_files/gnb_usrp_build.xml
@@ -0,0 +1,39 @@
+
+
+ gnb-build-tab
+ Build-gNB
+ wrench
+
+010101
+
+
+
+
+ TesteNB
+ Build_eNB
+ Build gNB (USRP)
+ --gNB -w USRP
+
+
+
diff --git a/ci-scripts/xml_files/nr_ue_usrp_build.xml b/ci-scripts/xml_files/nr_ue_usrp_build.xml
new file mode 100644
index 0000000000..7d8d97d2c5
--- /dev/null
+++ b/ci-scripts/xml_files/nr_ue_usrp_build.xml
@@ -0,0 +1,40 @@
+
+
+ nr-ue-build-tab
+ Build-NR-UE
+ wrench
+
+010102
+
+
+
+
+ TestUE
+ Build_OAI_UE
+ Build NR UE (USRP)
+ --nrUE -w USRP
+ false
+
+
+
diff --git a/cmake_targets/CMakeLists.txt b/cmake_targets/CMakeLists.txt
index 075c92ef25..de3f75eb5e 100644
--- a/cmake_targets/CMakeLists.txt
+++ b/cmake_targets/CMakeLists.txt
@@ -812,6 +812,7 @@ include_directories("${OPENAIR_BIN_DIR}")
# Legacy exact order
+include_directories("${OPENAIR_DIR}/executables")
include_directories("${OPENAIR2_DIR}/COMMON")
include_directories("${OPENAIR2_DIR}/UTIL")
include_directories("${OPENAIR2_DIR}/UTIL/LOG")
@@ -2243,11 +2244,18 @@ if (${XFORMS})
${OPENAIR1_DIR}/PHY/TOOLS/nr_phy_scope.c
)
set(XFORMS_SOURCE_SOFTMODEM
- ${OPENAIR_TARGETS}/RT/USER/stats.c
+ ${OPENAIR_DIR}/targets/RT/USER/stats.c
)
set(XFORMS_LIBRARIES "forms")
endif (${XFORMS})
+include_directories ("/usr/include/X11")
+
+add_library(gnbScope MODULE
+ ${OPENAIR1_DIR}/PHY/TOOLS/nr_phy_scope.c
+ )
+target_link_libraries(gnbScope forms)
+
set(CMAKE_MODULE_PATH "${OPENAIR_DIR}/cmake_targets/tools/MODULES" "${CMAKE_MODULE_PATH}")
#include T directory even if the T is off because T macros are in the code
@@ -2291,6 +2299,24 @@ add_definitions(-DASN1_MINIMUM_VERSION=924)
#################################
# add executables for operation
#################################
+add_library(minimal_lib
+ ${OPENAIR_DIR}/common/utils/backtrace.c
+ ${OPENAIR_DIR}/common/utils/LOG/log.c
+ ${OPENAIR_DIR}/common/config/config_userapi.c
+ ${OPENAIR_DIR}/common/config/config_load_configmodule.c
+ ${OPENAIR_DIR}/common/config/config_cmdline.c
+ ${OPENAIR_DIR}/common/utils/minimal_stub.c
+ )
+target_link_libraries(minimal_lib pthread dl)
+
+add_executable(replay_node
+ ${OPENAIR_TARGETS}/ARCH/rfsimulator/stored_node.c
+ )
+target_link_libraries (replay_node minimal_lib)
+
+add_executable(measurement_display
+ ${OPENAIR_DIR}/common/utils/threadPool/measurement_display.c)
+target_link_libraries (measurement_display minimal_lib)
# lte-softmodem is both eNB and UE implementation
###################################################
@@ -2497,19 +2523,16 @@ add_executable(nr-softmodem
${nr_rrc_h}
${s1ap_h}
# ${OPENAIR_BIN_DIR}/messages_xml.h
- ${OPENAIR_TARGETS}/RT/USER/rt_wrapper.c
- ${OPENAIR_TARGETS}/RT/USER/nr-gnb.c
- ${OPENAIR_TARGETS}/RT/USER/nr-ru.c
- ${OPENAIR_TARGETS}/RT/USER/nr-softmodem.c
+ ${OPENAIR_DIR}/executables/nr-gnb.c
+ ${OPENAIR_DIR}/executables/nr-ru.c
+ ${OPENAIR_DIR}/executables/nr-softmodem.c
${OPENAIR1_DIR}/SIMULATION/TOOLS/taus.c
- ${OPENAIR_TARGETS}/COMMON/create_nr_tasks.c
${OPENAIR_TARGETS}/ARCH/COMMON/common_lib.c
${OPENAIR1_DIR}/SIMULATION/ETH_TRANSPORT/netlink_init.c
${OPENAIR_DIR}/common/utils/utils.c
${OPENAIR_DIR}/common/utils/system.c
${GTPU_need_ITTI}
- ${XFORMS_SOURCE}
- ${XFORMS_SOURCE_SOFTMODEM}
+ ${XFORMS_SOURCE_NR}
${T_SOURCE}
${CONFIG_SOURCES}
${SHLIB_LOADER_SOURCES}
@@ -2535,13 +2558,10 @@ add_executable(nr-softmodem-nos1
${rrc_h}
${s1ap_h}
# ${OPENAIR_BIN_DIR}/messages_xml.h
- ${OPENAIR_TARGETS}/RT/USER/rt_wrapper.c
- ${OPENAIR_TARGETS}/RT/USER/nr-gnb.c
- ${OPENAIR_TARGETS}/RT/USER/nr-ru.c
- ${OPENAIR_TARGETS}/RT/USER/nr-softmodem.c
+ ${OPENAIR_DIR}/executables/nr-gnb.c
+ ${OPENAIR_DIR}/executables/nr-ru.c
+ ${OPENAIR_DIR}/executables/nr-softmodem.c
${OPENAIR1_DIR}/SIMULATION/TOOLS/taus.c
- ${OPENAIR_TARGETS}/COMMON/create_tasks.c
- ${OPENAIR_TARGETS}/COMMON/create_nr_tasks.c
${OPENAIR_TARGETS}/ARCH/COMMON/common_lib.c
${OPENAIR2_DIR}/RRC/NAS/nas_config.c
${OPENAIR2_DIR}/RRC/NAS/rb_config.c
@@ -2549,8 +2569,7 @@ add_executable(nr-softmodem-nos1
${OPENAIR_DIR}/common/utils/utils.c
${OPENAIR_DIR}/common/utils/system.c
${GTPU_need_ITTI}
- ${XFORMS_SOURCE}
- ${XFORMS_SOURCE_SOFTMODEM}
+ ${XFORMS_SOURCE_NR}
${T_SOURCE}
${CONFIG_SOURCES}
${SHLIB_LOADER_SOURCES}
@@ -2586,7 +2605,6 @@ add_executable(nr-uesoftmodem
${OPENAIR_DIR}/common/utils/utils.c
${OPENAIR_DIR}/common/utils/system.c
${XFORMS_SOURCE_NR}
- ${XFORMS_SOURCE_SOFTMODEM}
${T_SOURCE}
${CONFIG_SOURCES}
${SHLIB_LOADER_SOURCES}
@@ -2610,17 +2628,14 @@ add_executable(nr-uesoftmodem-nos1
${rrc_h}
${s1ap_h}
# ${OPENAIR_BIN_DIR}/messages_xml.h
- ${OPENAIR_TARGETS}/RT/USER/rt_wrapper.c
${OPENAIR_DIR}/executables/nr-ue.c
${OPENAIR_DIR}/executables/nr-uesoftmodem.c
${OPENAIR1_DIR}/SIMULATION/TOOLS/taus.c
- #${OPENAIR_TARGETS}/COMMON/create_tasks_ue.c
${OPENAIR_TARGETS}/ARCH/COMMON/common_lib.c
${OPENAIR1_DIR}/SIMULATION/ETH_TRANSPORT/netlink_init.c
${OPENAIR_DIR}/common/utils/utils.c
${OPENAIR_DIR}/common/utils/system.c
${XFORMS_SOURCE_NR}
- ${XFORMS_SOURCE_SOFTMODEM}
${T_SOURCE}
${CONFIG_SOURCES}
${SHLIB_LOADER_SOURCES}
@@ -2673,6 +2688,7 @@ target_link_libraries (nr-uesoftmodem-nos1 ${T_LIB})
add_executable(dlsim_tm4
${OPENAIR1_DIR}/SIMULATION/LTE_PHY/dlsim_tm4.c
${OPENAIR1_DIR}/PHY/TOOLS/lte_phy_scope_tm4.c
+ ${OPENAIR_DIR}/common/utils/system.c
${T_SOURCE}
)
target_link_libraries (dlsim_tm4
@@ -2699,18 +2715,21 @@ target_link_libraries(ldpctest SIMU PHY PHY_NR m ${ATLAS_LIBRARIES})
add_executable(nr_dlschsim
${OPENAIR1_DIR}/SIMULATION/NR_PHY/dlschsim.c
${OPENAIR_DIR}/common/utils/backtrace.c
+ ${OPENAIR_DIR}/common/utils/system.c
${T_SOURCE})
target_link_libraries(nr_dlschsim -Wl,--start-group UTIL SIMU PHY_COMMON PHY_NR PHY_NR_UE SCHED_NR_LIB CONFIG_LIB -Wl,--end-group m pthread ${ATLAS_LIBRARIES} ${T_LIB} dl)
add_executable(nr_pbchsim
${OPENAIR1_DIR}/SIMULATION/NR_PHY/pbchsim.c
${OPENAIR_DIR}/common/utils/backtrace.c
+ ${OPENAIR_DIR}/common/utils/system.c
${T_SOURCE})
target_link_libraries(nr_pbchsim -Wl,--start-group UTIL SIMU PHY_COMMON PHY_NR PHY_NR_UE SCHED_NR_LIB CONFIG_LIB -Wl,--end-group m pthread ${ATLAS_LIBRARIES} ${T_LIB} dl)
add_executable(nr_dlsim
${OPENAIR1_DIR}/SIMULATION/NR_PHY/dlsim.c
${OPENAIR_DIR}/common/utils/backtrace.c
+ ${OPENAIR_DIR}/common/utils/system.c
${T_SOURCE})
target_link_libraries(nr_dlsim -Wl,--start-group UTIL SIMU PHY_COMMON PHY_NR PHY_NR_UE SCHED_NR_LIB SCHED_NR_UE_LIB MAC_NR MAC_UE_NR MAC_NR_COMMON RRC_LIB NR_RRC_LIB CONFIG_LIB L2_NR -Wl,--end-group m pthread ${ATLAS_LIBRARIES} ${T_LIB} dl)
@@ -2726,6 +2745,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
+ ${OPENAIR_DIR}/common/utils/system.c
${XFORMS_SOURCE}
${T_SOURCE}
${CONFIG_SOURCES}
diff --git a/cmake_targets/build_oai b/cmake_targets/build_oai
index bdfc7e5a59..c95219b514 100755
--- a/cmake_targets/build_oai
+++ b/cmake_targets/build_oai
@@ -419,11 +419,6 @@ function main() {
CMAKE_CMD="$CMAKE_CMD .."
echo_info "CMAKE_CMD=$CMAKE_CMD"
- if [ "$eNB" = "1" -o "$gNB" = "1" ] && [ "$UE" = "1" -o "$nrUE" = "1" ]; then
- echo_error "Cannot build UE/nrUE and eNB/gNB on one build_oai execution"
- echo_error "use 2 build_oai invocations"
- exit
- fi
#########################################################
# check validity of HW and TP parameters for eNB / gNB
diff --git a/common/utils/minimal_stub.c b/common/utils/minimal_stub.c
new file mode 100644
index 0000000000..86454fe53f
--- /dev/null
+++ b/common/utils/minimal_stub.c
@@ -0,0 +1,4 @@
+int T_stdout;
+
+void exit_function(const char *file, const char *function, const int line, const char *s) {
+}
diff --git a/common/utils/ocp_itti/intertask_interface.cpp b/common/utils/ocp_itti/intertask_interface.cpp
index 3d0bd0e1a3..e8b12fcd4d 100644
--- a/common/utils/ocp_itti/intertask_interface.cpp
+++ b/common/utils/ocp_itti/intertask_interface.cpp
@@ -8,6 +8,7 @@
#include
+#include
typedef struct timer_elm_s {
timer_type_t type; ///< Timer type
@@ -263,7 +264,8 @@ extern "C" {
pthread_mutex_unlock (&t->queue_cond_lock);
}
- void itti_poll_msg(task_id_t task_id, MessageDef **received_msg) {
+ void itti_poll_msg(task_id_t task_id, MessageDef **received_msg)
+ {
//reception of one message, non-blocking
task_list_t *t=&tasks[task_id];
pthread_mutex_lock(&t->queue_cond_lock);
@@ -278,24 +280,13 @@ extern "C" {
pthread_mutex_unlock (&t->queue_cond_lock);
}
- int itti_create_task(task_id_t task_id, void *(*start_routine)(void *), void *args_p) {
+ int itti_create_task(task_id_t task_id,
+ void *(*start_routine)(void *),
+ void *args_p)
+ {
task_list_t *t=&tasks[task_id];
- AssertFatal ( pthread_create (&t->thread, NULL, start_routine, args_p) ==0,
- "Thread creation for task %d failed!\n", task_id);
- pthread_setname_np( t->thread, itti_get_task_name(task_id) );
+ threadCreate (&t->thread, start_routine, args_p, (char*)itti_get_task_name(task_id),-1,OAI_PRIORITY_RT);
LOG_I(TMR,"Created Posix thread %s\n", itti_get_task_name(task_id) );
-#if 1 // BMC test RT prio
- {
- int policy;
- struct sched_param sparam;
- memset(&sparam, 0, sizeof(sparam));
- sparam.sched_priority = sched_get_priority_max(SCHED_FIFO)-10;
- policy = SCHED_FIFO ;
- if (pthread_setschedparam(t->thread, policy, &sparam) != 0) {
- LOG_E(TMR,"task %s : Failed to set pthread priority\n", itti_get_task_name(task_id) );
- }
- }
-#endif
return 0;
}
@@ -303,14 +294,19 @@ extern "C" {
pthread_exit (NULL);
}
- void itti_terminate_tasks(task_id_t task_id) {
+ void itti_terminate_tasks(task_id_t task_id)
+ {
// Sends Terminate signals to all tasks.
itti_send_terminate_message (task_id);
usleep(100*1000); // Allow the tasks to receive the message before going returning to main thread
}
- int itti_init(task_id_t task_max, thread_id_t thread_max, MessagesIds messages_id_max, const task_info_t *tasks_info,
- const message_info_t *messages_info) {
+ int itti_init(task_id_t task_max,
+ thread_id_t thread_max,
+ MessagesIds messages_id_max,
+ const task_info_t *tasks_info,
+ const message_info_t *messages_info)
+ {
AssertFatal(TASK_MAX
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include "common_lib.h"
+
+#ifdef T
+ #undef T
+ #define T(...)
+#endif
+
+#endif
diff --git a/common/utils/system.c b/common/utils/system.c
index dcec681e2d..31c1035129 100644
--- a/common/utils/system.c
+++ b/common/utils/system.c
@@ -28,13 +28,23 @@
* separate process solves this problem.
*/
+#define _GNU_SOURCE
#include "system.h"
#include
#include
#include
#include
#include
-
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
#define MAX_COMMAND 4096
static int command_pipe_read;
@@ -50,37 +60,37 @@ static int module_initialized = 0;
/* util functions */
/********************************************************************/
-static void lock_system(void)
-{
+static void lock_system(void) {
if (pthread_mutex_lock(&lock) != 0) {
printf("pthread_mutex_lock fails\n");
abort();
}
}
-static void unlock_system(void)
-{
+static void unlock_system(void) {
if (pthread_mutex_unlock(&lock) != 0) {
printf("pthread_mutex_unlock fails\n");
abort();
}
}
-static void write_pipe(int p, char *b, int size)
-{
+static void write_pipe(int p, char *b, int size) {
while (size) {
int ret = write(p, b, size);
+
if (ret <= 0) exit(0);
+
b += ret;
size -= ret;
}
}
-static void read_pipe(int p, char *b, int size)
-{
+static void read_pipe(int p, char *b, int size) {
while (size) {
int ret = read(p, b, size);
+
if (ret <= 0) exit(0);
+
b += ret;
size -= ret;
}
@@ -95,14 +105,13 @@ static void read_pipe(int p, char *b, int size)
* when the main process exits, because then a "read" on the pipe
* will return 0, in which case "read_pipe" exits.
*/
-static void background_system_process(void)
-{
+static void background_system_process(void) {
int len;
int ret;
char command[MAX_COMMAND+1];
while (1) {
- read_pipe(command_pipe_read, (char*)&len, sizeof(int));
+ read_pipe(command_pipe_read, (char *)&len, sizeof(int));
read_pipe(command_pipe_read, command, len);
ret = system(command);
write_pipe(result_pipe_write, (char *)&ret, sizeof(int));
@@ -114,8 +123,7 @@ static void background_system_process(void)
/* return -1 on error, 0 on success */
/********************************************************************/
-int background_system(char *command)
-{
+int background_system(char *command) {
int res;
int len;
@@ -125,18 +133,22 @@ int background_system(char *command)
}
len = strlen(command)+1;
+
if (len > MAX_COMMAND) {
printf("FATAL: command too long. Increase MAX_COMMAND (%d).\n", MAX_COMMAND);
printf("command was: '%s'\n", command);
abort();
}
+
/* only one command can run at a time, so let's lock/unlock */
lock_system();
- write_pipe(command_pipe_write, (char*)&len, sizeof(int));
+ write_pipe(command_pipe_write, (char *)&len, sizeof(int));
write_pipe(command_pipe_write, command, len);
- read_pipe(result_pipe_read, (char*)&res, sizeof(int));
+ read_pipe(result_pipe_read, (char *)&res, sizeof(int));
unlock_system();
+
if (res == -1 || !WIFEXITED(res) || WEXITSTATUS(res) != 0) return -1;
+
return 0;
}
@@ -146,17 +158,16 @@ int background_system(char *command)
/* to be called very early by the main processing */
/********************************************************************/
-void start_background_system(void)
-{
+void start_background_system(void) {
int p[2];
pid_t son;
-
module_initialized = 1;
if (pipe(p) == -1) {
perror("pipe");
exit(1);
}
+
command_pipe_read = p[0];
command_pipe_write = p[1];
@@ -164,10 +175,11 @@ void start_background_system(void)
perror("pipe");
exit(1);
}
+
result_pipe_read = p[0];
result_pipe_write = p[1];
-
son = fork();
+
if (son == -1) {
perror("fork");
exit(1);
@@ -181,6 +193,56 @@ void start_background_system(void)
close(result_pipe_read);
close(command_pipe_write);
-
background_system_process();
}
+
+
+void threadCreate(pthread_t* t, void * (*func)(void*), void * param, char* name, int affinity, int priority){
+ pthread_attr_t attr;
+ pthread_attr_init(&attr);
+ pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
+ pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED);
+ pthread_attr_setschedpolicy(&attr, SCHED_FIFO);
+ struct sched_param sparam={0};
+ sparam.sched_priority = priority;
+ pthread_attr_setschedparam(&attr, &sparam);
+
+ pthread_create(t, &attr, func, param);
+
+ pthread_setname_np(*t, name);
+ if (affinity != -1 ) {
+ cpu_set_t cpuset;
+ CPU_ZERO(&cpuset);
+ CPU_SET(affinity, &cpuset);
+ AssertFatal( pthread_setaffinity_np(*t, sizeof(cpu_set_t), &cpuset) == 0, "Error setting processor affinity");
+ }
+
+ pthread_attr_destroy(&attr);
+}
+
+// Block CPU C-states deep sleep
+void configure_linux(void) {
+ int ret;
+ static int latency_target_fd=-1;
+ uint32_t latency_target_value=10; // in microseconds
+ if (latency_target_fd == -1) {
+ if ( (latency_target_fd = open("/dev/cpu_dma_latency", O_RDWR)) != -1 ) {
+ ret = write(latency_target_fd, &latency_target_value, sizeof(latency_target_value));
+ if (ret == 0) {
+ printf("# error setting cpu_dma_latency to %d!: %s\n", latency_target_value, strerror(errno));
+ close(latency_target_fd);
+ latency_target_fd=-1;
+ return;
+ }
+ }
+ }
+ if (latency_target_fd != -1)
+ LOG_I(HW,"# /dev/cpu_dma_latency set to %dus\n", latency_target_value);
+ else
+ LOG_E(HW,"Can't set /dev/cpu_dma_latency to %dus\n", latency_target_value);
+
+ // Set CPU frequency to it's maximum
+ if ( 0 != system("for d in /sys/devices/system/cpu/cpu[0-9]*; do cat $d/cpufreq/cpuinfo_max_freq > $d/cpufreq/scaling_min_freq; done"))
+ LOG_W(HW,"Can't set cpu frequency\n");
+
+}
diff --git a/common/utils/system.h b/common/utils/system.h
index 658c17adc1..a89a6c5b17 100644
--- a/common/utils/system.h
+++ b/common/utils/system.h
@@ -21,6 +21,12 @@
#ifndef _SYSTEM_H_OAI_
#define _SYSTEM_H_OAI_
+#include
+#include
+#ifdef __cplusplus
+extern "C" {
+#endif
+
/****************************************************
* send a command to the background process
@@ -36,4 +42,23 @@ int background_system(char *command);
void start_background_system(void);
+void set_latency_target(void);
+void configure_linux(void);
+
+void threadCreate(pthread_t* t, void * (*func)(void*), void * param, char* name, int affinity, int priority);
+#define OAI_PRIORITY_RT_LOW sched_get_priority_min(SCHED_FIFO)
+#define OAI_PRIORITY_RT sched_get_priority_max(SCHED_FIFO)-10
+#define OAI_PRIORITY_RT_MAX sched_get_priority_max(SCHED_FIFO)
+
+void thread_top_init(char *thread_name,
+ int affinity,
+ uint64_t runtime,
+ uint64_t deadline,
+ uint64_t period);
+
+#ifdef __cplusplus
+}
+#endif
+
+
#endif /* _SYSTEM_H_OAI_ */
diff --git a/common/utils/threadPool/Makefile b/common/utils/threadPool/Makefile
index 6f0e884886..af0b44996c 100644
--- a/common/utils/threadPool/Makefile
+++ b/common/utils/threadPool/Makefile
@@ -1,8 +1,8 @@
all: measurement_display thread-pool-test
measurement_display: measurement_display.c thread-pool.h
- gcc measurement_display.c -I /data/openairinterface5g.nr/common/utils/ -I. /data/openairinterface5g.nr/common/utils/backtrace.c -lpthread -D TEST_THREAD_POOL -I../LOG -I../../utils/T -o measurement_display
+ gcc measurement_display.c -I ${OPENAIR_DIR}/ -I ${OPENAIR_DIR}/common/utils/ -I. ${OPENAIR_DIR}/common/utils/backtrace.c -lpthread -D TEST_THREAD_POOL -I../LOG -I../../utils/T -o measurement_display
thread-pool-test: thread-pool.c thread-pool.h
- gcc -g thread-pool.c -I /data/openairinterface5g.nr/common/utils/ -I. /data/openairinterface5g.nr/common/utils/backtrace.c -lpthread -D TEST_THREAD_POOL -I../LOG -I../../utils/T -o thread-pool-test
+ gcc -g thread-pool.c -I ${OPENAIR_DIR}/ -I ${OPENAIR_DIR}/common/utils/ -I. ${OPENAIR_DIR}/common/utils/backtrace.c -I ${OPENAIR_DIR}/openair2/COMMON ${OPENAIR_DIR}/common/utils/LOG/log.c ${OPENAIR_DIR}/common/config/config_userapi.c ${OPENAIR_DIR}/common/config/config_load_configmodule.c ${OPENAIR_DIR}/common/config/config_cmdline.c -lpthread -ldl -D TEST_THREAD_POOL -I../LOG -I../../utils/T -o thread-pool-test
diff --git a/common/utils/threadPool/measurement_display.c b/common/utils/threadPool/measurement_display.c
index ac7beca1fe..8f6e2c239a 100644
--- a/common/utils/threadPool/measurement_display.c
+++ b/common/utils/threadPool/measurement_display.c
@@ -2,22 +2,8 @@
Author: Laurent THOMAS, Open Cells
copyleft: OpenAirInterface Software Alliance and it's licence
*/
+#include
-#define __USE_GNU
-#define _GNU_SOURCE
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
#include "thread-pool.h"
#define SEP "\t"
@@ -26,7 +12,7 @@ uint64_t cpuCyclesMicroSec;
int main(int argc, char *argv[]) {
if(argc != 2) {
- printf("Need one paramter: the trace Linux pipe (fifo)");
+ printf("Need one parameter: the trace Linux pipe (fifo)");
exit(1);
}
diff --git a/common/utils/threadPool/thread-pool.c b/common/utils/threadPool/thread-pool.c
index 4cc56fc9b8..b45a8fa722 100644
--- a/common/utils/threadPool/thread-pool.c
+++ b/common/utils/threadPool/thread-pool.c
@@ -49,23 +49,6 @@ void *one_thread(void *arg) {
struct one_thread *myThread=(struct one_thread *) arg;
struct thread_pool *tp=myThread->pool;
- // configure the thread core assignment
- // TBD: reserve the core for us exclusively
- if ( myThread->coreID >= 0 && myThread->coreID < get_nprocs_conf()) {
- cpu_set_t cpuset;
- CPU_ZERO(&cpuset);
- CPU_SET(myThread->coreID, &cpuset);
- pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset);
- }
-
- //Configure the thread scheduler policy for Linux
- struct sched_param sparam= {0};
- sparam.sched_priority = sched_get_priority_max(SCHED_RR);
- pthread_setschedparam(pthread_self(), SCHED_RR, &sparam);
- // set the thread name for debugging
- sprintf(myThread->name,"Tpool_%d",myThread->coreID);
- pthread_setname_np(pthread_self(), myThread->name );
-
// Infinite loop to process requests
do {
notifiedFIFO_elt_t *elt=pullNotifiedFifoRemember(&tp->incomingFifo, myThread);
@@ -106,10 +89,6 @@ void initTpool(char *params,tpool_t *pool, bool performanceMeas) {
} else
pool->traceFd=-1;
- //Configure the thread scheduler policy for Linux
- struct sched_param sparam= {0};
- sparam.sched_priority = sched_get_priority_max(SCHED_RR)-1;
- pthread_setschedparam(pthread_self(), SCHED_RR, &sparam);
pool->activated=true;
initNotifiedFIFO(&pool->incomingFifo);
char *saveptr, * curptr;
@@ -136,7 +115,11 @@ void initTpool(char *params,tpool_t *pool, bool performanceMeas) {
pool->allthreads->coreID=atoi(curptr);
pool->allthreads->id=pool->nbThreads;
pool->allthreads->pool=pool;
- pthread_create(&pool->allthreads->threadID, NULL, one_thread, (void *)pool->allthreads);
+ //Configure the thread scheduler policy for Linux
+ // set the thread name for debugging
+ sprintf(pool->allthreads->name,"Tpool_%d",pool->allthreads->coreID);
+ threadCreate(&pool->allthreads->threadID, one_thread, (void *)pool->allthreads,
+ pool->allthreads->name, pool->allthreads->coreID, OAI_PRIORITY_RT);
pool->nbThreads++;
}
@@ -151,6 +134,9 @@ void initTpool(char *params,tpool_t *pool, bool performanceMeas) {
#ifdef TEST_THREAD_POOL
+void exit_function(const char *file, const char *function, const int line, const char *s) {
+}
+
struct testData {
int id;
char txt[30];
diff --git a/common/utils/threadPool/thread-pool.h b/common/utils/threadPool/thread-pool.h
index aa0003fd8a..d6dc332c5a 100644
--- a/common/utils/threadPool/thread-pool.h
+++ b/common/utils/threadPool/thread-pool.h
@@ -11,6 +11,7 @@
#include
#include
#include
+#include
#ifdef DEBUG
#define THREADINIT PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP
@@ -77,16 +78,18 @@ static inline void delNotifiedFIFO_elt(notifiedFIFO_elt_t *elt) {
//LOG_W(UTIL,"delNotifiedFIFO on something not allocated by newNotifiedFIFO\n");
}
+static inline void initNotifiedFIFO_nothreadSafe(notifiedFIFO_t *nf) {
+ nf->inF=NULL;
+ nf->outF=NULL;
+}
static inline void initNotifiedFIFO(notifiedFIFO_t *nf) {
mutexinit(nf->lockF);
condinit (nf->notifF);
- nf->inF=NULL;
- nf->outF=NULL;
+ initNotifiedFIFO_nothreadSafe(nf);
// No delete function: the creator has only to free the memory
}
-static inline void pushNotifiedFIFO(notifiedFIFO_t *nf, notifiedFIFO_elt_t *msg) {
- mutexlock(nf->lockF);
+static inline void pushNotifiedFIFO_nothreadSafe(notifiedFIFO_t *nf, notifiedFIFO_elt_t *msg) {
msg->next=NULL;
if (nf->outF == NULL)
@@ -96,22 +99,39 @@ static inline void pushNotifiedFIFO(notifiedFIFO_t *nf, notifiedFIFO_elt_t *msg)
nf->inF->next = msg;
nf->inF = msg;
+}
+
+static inline void pushNotifiedFIFO(notifiedFIFO_t *nf, notifiedFIFO_elt_t *msg) {
+ mutexlock(nf->lockF);
+ pushNotifiedFIFO_nothreadSafe(nf,msg);
condbroadcast(nf->notifF);
mutexunlock(nf->lockF);
}
-static inline notifiedFIFO_elt_t *pullNotifiedFIFO(notifiedFIFO_t *nf) {
- mutexlock(nf->lockF);
-
- while(nf->outF == NULL)
- condwait(nf->notifF, nf->lockF);
+static inline notifiedFIFO_elt_t *pullNotifiedFIFO_nothreadSafe(notifiedFIFO_t *nf) {
+ if (nf->outF == NULL)
+ return NULL;
notifiedFIFO_elt_t *ret=nf->outF;
+
+ if (nf->outF==nf->outF->next)
+ LOG_E(TMR,"Circular list in thread pool: push several times the same buffer is forbidden\n");
+
nf->outF=nf->outF->next;
if (nf->outF==NULL)
nf->inF=NULL;
+ return ret;
+}
+
+static inline notifiedFIFO_elt_t *pullNotifiedFIFO(notifiedFIFO_t *nf) {
+ mutexlock(nf->lockF);
+ notifiedFIFO_elt_t *ret;
+
+ while((ret=pullNotifiedFIFO_nothreadSafe(nf)) == NULL)
+ condwait(nf->notifF, nf->lockF);
+
mutexunlock(nf->lockF);
return ret;
}
@@ -122,18 +142,7 @@ static inline notifiedFIFO_elt_t *pollNotifiedFIFO(notifiedFIFO_t *nf) {
if (tmp != 0 )
return NULL;
- notifiedFIFO_elt_t *ret=nf->outF;
-
- if (ret!=NULL) {
- if (nf->outF==nf->outF->next)
- LOG_E(TMR,"Circular list in thread pool: push several times the same buffer is forbidden\n");
-
- nf->outF=nf->outF->next;
- }
-
- if (nf->outF==NULL)
- nf->inF=NULL;
-
+ notifiedFIFO_elt_t *ret=pullNotifiedFIFO_nothreadSafe(nf);
mutexunlock(nf->lockF);
return ret;
}
@@ -195,7 +204,7 @@ static inline notifiedFIFO_elt_t *pullTpool(notifiedFIFO_t *responseFifo, tpool_
if (t->measurePerf)
msg->returnTime=rdtsc();
- if (t->traceFd)
+ if (t->traceFd >= 0)
if(write(t->traceFd, msg, sizeof(*msg)));
return msg;
diff --git a/executables/nr-gnb.c b/executables/nr-gnb.c
new file mode 100644
index 0000000000..c0571f2bc5
--- /dev/null
+++ b/executables/nr-gnb.c
@@ -0,0 +1,941 @@
+/*
+ * 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 lte-enb.c
+ * \brief Top-level threads for gNodeB
+ * \author R. Knopp, F. Kaltenberger, Navid Nikaein
+ * \date 2012
+ * \version 0.1
+ * \company Eurecom
+ * \email: knopp@eurecom.fr,florian.kaltenberger@eurecom.fr, navid.nikaein@eurecom.fr
+ * \note
+ * \warning
+ */
+
+#define _GNU_SOURCE
+#include
+
+#include "time_utils.h"
+
+#undef MALLOC //there are two conflicting definitions, so we better make sure we don't use it at all
+
+#include "assertions.h"
+#include
+#include
+
+#include "PHY/types.h"
+
+#include "PHY/INIT/phy_init.h"
+
+#include "PHY/defs_gNB.h"
+#include "SCHED/sched_eNB.h"
+#include "SCHED_NR/sched_nr.h"
+#include "SCHED_NR/fapi_nr_l1.h"
+#include "PHY/LTE_TRANSPORT/transport_proto.h"
+
+#undef MALLOC //there are two conflicting definitions, so we better make sure we don't use it at all
+//#undef FRAME_LENGTH_COMPLEX_SAMPLES //there are two conflicting definitions, so we better make sure we don't use it at all
+
+#include "../../ARCH/COMMON/common_lib.h"
+
+//#undef FRAME_LENGTH_COMPLEX_SAMPLES //there are two conflicting definitions, so we better make sure we don't use it at all
+
+#include "PHY/LTE_TRANSPORT/if4_tools.h"
+#include "PHY/LTE_TRANSPORT/if5_tools.h"
+
+#include "PHY/phy_extern.h"
+
+
+#include "LAYER2/MAC/mac.h"
+#include "LAYER2/MAC/mac_extern.h"
+#include "LAYER2/MAC/mac_proto.h"
+#include "RRC/LTE/rrc_extern.h"
+#include "PHY_INTERFACE/phy_interface.h"
+#include "common/utils/LOG/log_extern.h"
+#include "UTIL/OTG/otg_tx.h"
+#include "UTIL/OTG/otg_externs.h"
+#include "UTIL/MATH/oml.h"
+#include "common/utils/LOG/vcd_signal_dumper.h"
+#include "UTIL/OPT/opt.h"
+#include "enb_config.h"
+
+
+#ifndef OPENAIR2
+ #include "UTIL/OTG/otg_extern.h"
+#endif
+
+#if defined(ENABLE_ITTI)
+ #if defined(ENABLE_USE_MME)
+ #include "s1ap_eNB.h"
+ #ifdef PDCP_USE_NETLINK
+ #include "SIMULATION/ETH_TRANSPORT/proto.h"
+ #endif
+ #endif
+#endif
+
+#include "T.h"
+
+//#define DEBUG_THREADS 1
+
+//#define USRP_DEBUG 1
+// Fix per CC openair rf/if device update
+// extern openair0_device openair0;
+
+
+#if defined(ENABLE_ITTI)
+ extern volatile int start_gNB;
+ extern volatile int start_UE;
+#endif
+extern volatile int oai_exit;
+
+extern openair0_config_t openair0_cfg[MAX_CARDS];
+
+extern int transmission_mode;
+
+uint16_t sl_ahead=4;
+uint16_t sf_ahead=4;
+//pthread_t main_gNB_thread;
+
+time_stats_t softmodem_stats_mt; // main thread
+time_stats_t softmodem_stats_hw; // hw acquisition
+time_stats_t softmodem_stats_rxtx_sf; // total tx time
+time_stats_t nfapi_meas; // total tx time
+time_stats_t softmodem_stats_rx_sf; // total rx time
+
+/* mutex, cond and variable to serialize phy proc TX calls
+ * (this mechanism may be relaxed in the future for better
+ * performances)
+ */
+static struct {
+ pthread_mutex_t mutex_phy_proc_tx;
+ pthread_cond_t cond_phy_proc_tx;
+ volatile uint8_t phy_proc_CC_id;
+} sync_phy_proc;
+
+extern double cpuf;
+
+void init_gNB(int,int);
+void stop_gNB(int nb_inst);
+
+int wakeup_txfh(gNB_L1_rxtx_proc_t *proc,PHY_VARS_gNB *gNB);
+int wakeup_tx(PHY_VARS_gNB *gNB);
+extern PARALLEL_CONF_t get_thread_parallel_conf(void);
+extern WORKER_CONF_t get_thread_worker_conf(void);
+
+
+void wakeup_prach_gNB(PHY_VARS_gNB *gNB,RU_t *ru,int frame,int subframe);
+
+extern uint8_t nfapi_mode;
+extern void oai_subframe_ind(uint16_t sfn, uint16_t sf);
+extern void add_subframe(uint16_t *frameP, uint16_t *subframeP, int offset);
+
+//#define TICK_TO_US(ts) (ts.diff)
+#define TICK_TO_US(ts) (ts.trials==0?0:ts.diff/ts.trials)
+
+
+static inline int rxtx(PHY_VARS_gNB *gNB,gNB_L1_rxtx_proc_t *proc, char *thread_name) {
+ start_meas(&softmodem_stats_rxtx_sf);
+
+ // *******************************************************************
+
+ if (nfapi_mode == 1) {
+ // I am a PNF and I need to let nFAPI know that we have a (sub)frame tick
+ uint16_t frame = proc->frame_rx;
+ uint16_t slot = proc->slot_rx;
+ //add_subframe(&frame, &subframe, 4);
+ //oai_subframe_ind(proc->frame_tx, proc->subframe_tx);
+ //LOG_D(PHY, "oai_subframe_ind(frame:%u, subframe:%d) - NOT CALLED ********\n", frame, subframe);
+ start_meas(&nfapi_meas);
+ oai_subframe_ind(frame, slot);
+ stop_meas(&nfapi_meas);
+
+ if (gNB->UL_INFO.rx_ind.rx_indication_body.number_of_pdus||
+ gNB->UL_INFO.harq_ind.harq_indication_body.number_of_harqs ||
+ gNB->UL_INFO.crc_ind.crc_indication_body.number_of_crcs ||
+ gNB->UL_INFO.rach_ind.rach_indication_body.number_of_preambles ||
+ gNB->UL_INFO.cqi_ind.number_of_cqis
+ ) {
+ LOG_D(PHY, "UL_info[rx_ind:%05d:%d harqs:%05d:%d crcs:%05d:%d preambles:%05d:%d cqis:%d] RX:%04d%d TX:%04d%d \n",
+ NFAPI_SFNSF2DEC(gNB->UL_INFO.rx_ind.sfn_sf), gNB->UL_INFO.rx_ind.rx_indication_body.number_of_pdus,
+ NFAPI_SFNSF2DEC(gNB->UL_INFO.harq_ind.sfn_sf), gNB->UL_INFO.harq_ind.harq_indication_body.number_of_harqs,
+ NFAPI_SFNSF2DEC(gNB->UL_INFO.crc_ind.sfn_sf), gNB->UL_INFO.crc_ind.crc_indication_body.number_of_crcs,
+ NFAPI_SFNSF2DEC(gNB->UL_INFO.rach_ind.sfn_sf), gNB->UL_INFO.rach_ind.rach_indication_body.number_of_preambles,
+ gNB->UL_INFO.cqi_ind.number_of_cqis,
+ proc->frame_rx, proc->slot_rx,
+ proc->frame_tx, proc->slot_tx);
+ }
+ }
+
+ /// NR disabling
+ // ****************************************
+ // Common RX procedures subframe n
+ T(T_GNB_PHY_DL_TICK, T_INT(gNB->Mod_id), T_INT(proc->frame_tx), T_INT(proc->slot_tx));
+ /*
+ // if this is IF5 or 3GPP_gNB
+ if (gNB && gNB->RU_list && gNB->RU_list[0] && gNB->RU_list[0]->function < NGFI_RAU_IF4p5) {
+ wakeup_prach_gNB(gNB,NULL,proc->frame_rx,proc->slot_rx);
+ }
+
+ // UE-specific RX processing for subframe n
+ if (nfapi_mode == 0 || nfapi_mode == 1) {
+ phy_procedures_gNB_uespec_RX(gNB, proc, no_relay );
+ }
+ */
+ pthread_mutex_lock(&gNB->UL_INFO_mutex);
+ gNB->UL_INFO.frame = proc->frame_rx;
+ gNB->UL_INFO.slot = proc->slot_rx;
+ gNB->UL_INFO.module_id = gNB->Mod_id;
+ gNB->UL_INFO.CC_id = gNB->CC_id;
+ gNB->if_inst->NR_UL_indication(&gNB->UL_INFO);
+ pthread_mutex_unlock(&gNB->UL_INFO_mutex);
+
+ /// end
+ // *****************************************
+ // TX processing for subframe n+sl_ahead
+ // run PHY TX procedures the one after the other for all CCs to avoid race conditions
+ // (may be relaxed in the future for performance reasons)
+ // *****************************************
+ //if (wait_CCs(proc)<0) return(-1);
+
+ if (oai_exit) return(-1);
+
+ if(get_thread_parallel_conf() == PARALLEL_SINGLE_THREAD) {
+ phy_procedures_gNB_TX(gNB, proc, 1);
+ }
+
+ stop_meas( &softmodem_stats_rxtx_sf );
+ LOG_D(PHY,"%s() Exit proc[rx:%d%d tx:%d%d]\n", __FUNCTION__, proc->frame_rx, proc->slot_rx, proc->frame_tx, proc->slot_tx);
+#if 0
+ LOG_D(PHY, "rxtx:%lld nfapi:%lld phy:%lld tx:%lld rx:%lld prach:%lld ofdm:%lld ",
+ softmodem_stats_rxtx_sf.diff_now, nfapi_meas.diff_now,
+ TICK_TO_US(gNB->phy_proc),
+ TICK_TO_US(gNB->phy_proc_tx),
+ TICK_TO_US(gNB->phy_proc_rx),
+ TICK_TO_US(gNB->rx_prach),
+ TICK_TO_US(gNB->ofdm_mod_stats),
+ softmodem_stats_rxtx_sf.diff_now, nfapi_meas.diff_now);
+ LOG_D(PHY,
+ "dlsch[enc:%lld mod:%lld scr:%lld rm:%lld t:%lld i:%lld] rx_dft:%lld ",
+ TICK_TO_US(gNB->dlsch_encoding_stats),
+ TICK_TO_US(gNB->dlsch_modulation_stats),
+ TICK_TO_US(gNB->dlsch_scrambling_stats),
+ TICK_TO_US(gNB->dlsch_rate_matching_stats),
+ TICK_TO_US(gNB->dlsch_turbo_encoding_stats),
+ TICK_TO_US(gNB->dlsch_interleaving_stats),
+ TICK_TO_US(gNB->rx_dft_stats));
+ LOG_D(PHY," ulsch[ch:%lld freq:%lld dec:%lld demod:%lld ru:%lld ",
+ TICK_TO_US(gNB->ulsch_channel_estimation_stats),
+ TICK_TO_US(gNB->ulsch_freq_offset_estimation_stats),
+ TICK_TO_US(gNB->ulsch_decoding_stats),
+ TICK_TO_US(gNB->ulsch_demodulation_stats),
+ TICK_TO_US(gNB->ulsch_rate_unmatching_stats));
+ LOG_D(PHY, "td:%lld dei:%lld dem:%lld llr:%lld tci:%lld ",
+ TICK_TO_US(gNB->ulsch_turbo_decoding_stats),
+ TICK_TO_US(gNB->ulsch_deinterleaving_stats),
+ TICK_TO_US(gNB->ulsch_demultiplexing_stats),
+ TICK_TO_US(gNB->ulsch_llr_stats),
+ TICK_TO_US(gNB->ulsch_tc_init_stats));
+ LOG_D(PHY, "tca:%lld tcb:%lld tcg:%lld tce:%lld l1:%lld l2:%lld]\n\n",
+ TICK_TO_US(gNB->ulsch_tc_alpha_stats),
+ TICK_TO_US(gNB->ulsch_tc_beta_stats),
+ TICK_TO_US(gNB->ulsch_tc_gamma_stats),
+ TICK_TO_US(gNB->ulsch_tc_ext_stats),
+ TICK_TO_US(gNB->ulsch_tc_intl1_stats),
+ TICK_TO_US(gNB->ulsch_tc_intl2_stats)
+ );
+#endif
+ return(0);
+}
+
+static void *gNB_L1_thread_tx(void *param) {
+ PHY_VARS_gNB *gNB = (PHY_VARS_gNB *)param;
+ gNB_L1_proc_t *gNB_proc = &gNB->proc;
+ gNB_L1_rxtx_proc_t *proc = &gNB_proc->L1_proc_tx;
+ //PHY_VARS_gNB *gNB = RC.gNB[0][proc->CC_id];
+ char thread_name[100];
+ sprintf(thread_name,"TXnp4_%d\n",&gNB->proc.L1_proc == proc ? 0 : 1);
+
+ //wait_sync("tx_thread");
+
+ while (!oai_exit) {
+ VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_gNB_PROC_RXTX1, 0 );
+
+ if (wait_on_condition(&proc->mutex,&proc->cond,&proc->instance_cnt,thread_name)<0) break;
+
+ VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_gNB_PROC_RXTX1, 1 );
+
+ if (oai_exit) break;
+
+ // *****************************************
+ // TX processing for subframe n+4
+ // run PHY TX procedures the one after the other for all CCs to avoid race conditions
+ // (may be relaxed in the future for performance reasons)
+ // *****************************************
+ VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_SLOT_NUMBER_TX1_GNB,proc->slot_tx);
+ VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_SLOT_NUMBER_RX1_GNB,proc->slot_rx);
+ VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX1_GNB,proc->frame_tx);
+ VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX1_GNB,proc->frame_rx);
+ phy_procedures_gNB_TX(gNB, proc, 1);
+ pthread_mutex_lock( &proc->mutex );
+ proc->instance_cnt = -1;
+
+ // the thread can now be woken up
+ if (pthread_cond_signal(&proc->cond) != 0) {
+ LOG_E( PHY, "[gNB] ERROR pthread_cond_signal for gNB TXnp4 thread\n");
+ exit_fun( "ERROR pthread_cond_signal" );
+ }
+
+ pthread_mutex_unlock( &proc->mutex );
+ wakeup_txfh(proc,gNB);
+ }
+
+ return 0;
+}
+
+/*!
+ * \brief The RX UE-specific and TX thread of gNB.
+ * \param param is a \ref gNB_L1_proc_t structure which contains the info what to process.
+ * \returns a pointer to an int. The storage is not on the heap and must not be freed.
+ */
+
+static void *gNB_L1_thread( void *param ) {
+ static int gNB_thread_rxtx_status;
+ PHY_VARS_gNB *gNB = (PHY_VARS_gNB *)param;
+ gNB_L1_proc_t *gNB_proc = &gNB->proc;
+ gNB_L1_rxtx_proc_t *proc = &gNB_proc->L1_proc;
+ //PHY_VARS_gNB *gNB = RC.gNB[0][proc->CC_id];
+ char thread_name[100];
+ // set default return value
+ gNB_thread_rxtx_status = 0;
+ sprintf(thread_name,"RXn_TXnp4_%d",&gNB->proc.L1_proc == proc ? 0 : 1);
+
+ while (!oai_exit) {
+ VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_gNB_PROC_RXTX0, 0 );
+
+ if (wait_on_condition(&proc->mutex,&proc->cond,&proc->instance_cnt,thread_name)<0) break;
+
+ VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_gNB_PROC_RXTX0, 1 );
+ VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_SLOT_NUMBER_TX0_GNB,proc->slot_tx);
+ VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_SLOT_NUMBER_RX0_GNB,proc->slot_rx);
+ VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX0_GNB,proc->frame_tx);
+ VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX0_GNB,proc->frame_rx);
+
+ if (oai_exit) break;
+
+ if (gNB->CC_id==0) {
+ if (rxtx(gNB,proc,thread_name) < 0) break;
+ }
+
+ if(get_thread_parallel_conf() == PARALLEL_RU_L1_SPLIT) {
+ phy_procedures_gNB_TX(gNB, proc, 1);
+ }
+
+ if (release_thread(&proc->mutex,&proc->instance_cnt,thread_name)<0) break;
+
+ if(get_thread_parallel_conf() == PARALLEL_RU_L1_TRX_SPLIT) {
+ wakeup_tx(gNB);
+ } else if(get_thread_parallel_conf() == PARALLEL_RU_L1_SPLIT) {
+ wakeup_txfh(proc,gNB);
+ }
+ } // while !oai_exit
+
+ LOG_D(PHY, " *** Exiting gNB thread RXn_TXnp4\n");
+ gNB_thread_rxtx_status = 0;
+ return &gNB_thread_rxtx_status;
+}
+
+
+#if 0 //defined(ENABLE_ITTI) && defined(ENABLE_USE_MME)
+// Wait for gNB application initialization to be complete (gNB registration to MME)
+static void wait_system_ready (char *message, volatile int *start_flag) {
+ static char *indicator[] = {". ", ".. ", "... ", ".... ", ".....",
+ " ....", " ...", " ..", " .", " "
+ };
+ int i = 0;
+
+ while ((!oai_exit) && (*start_flag == 0)) {
+ LOG_N(EMU, message, indicator[i]);
+ fflush(stdout);
+ i = (i + 1) % (sizeof(indicator) / sizeof(indicator[0]));
+ usleep(200000);
+ }
+
+ LOG_D(EMU,"\n");
+}
+#endif
+
+
+
+
+
+void gNB_top(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, char *string, struct RU_t_s *ru) {
+ gNB_L1_proc_t *proc = &gNB->proc;
+ gNB_L1_rxtx_proc_t *L1_proc = &proc->L1_proc;
+ NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms;
+ RU_proc_t *ru_proc=&ru->proc;
+ proc->frame_rx = frame_rx;
+ proc->slot_rx = slot_rx;
+
+ if (!oai_exit) {
+ T(T_ENB_MASTER_TICK, T_INT(0), T_INT(proc->frame_rx), T_INT(proc->slot_rx));
+ L1_proc->timestamp_tx = ru_proc->timestamp_rx + (sl_ahead*fp->samples_per_slot);
+ L1_proc->frame_rx = ru_proc->frame_rx;
+ L1_proc->slot_rx = ru_proc->tti_rx;
+ L1_proc->frame_tx = (L1_proc->slot_rx > (fp->slots_per_frame-1-sl_ahead)) ? (L1_proc->frame_rx+1)&1023 : L1_proc->frame_rx;
+ L1_proc->slot_tx = (L1_proc->slot_rx + sl_ahead)%fp->slots_per_frame;
+
+ if (rxtx(gNB,L1_proc,string) < 0) LOG_E(PHY,"gNB %d CC_id %d failed during execution\n",gNB->Mod_id,gNB->CC_id);
+
+ ru_proc->timestamp_tx = L1_proc->timestamp_tx;
+ ru_proc->tti_tx = L1_proc->slot_tx;
+ ru_proc->frame_tx = L1_proc->frame_tx;
+ }
+}
+
+int wakeup_txfh(gNB_L1_rxtx_proc_t *proc,PHY_VARS_gNB *gNB) {
+ RU_t *ru;
+ RU_proc_t *ru_proc;
+ struct timespec wait;
+ wait.tv_sec=0;
+ wait.tv_nsec=5000000L;
+ //printf("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~inside wakeup_txfh %d.%d IC_RU = %d\n", proc->frame_tx, proc->slot_tx, proc->instance_cnt_RUs);
+
+ if(wait_on_condition(&proc->mutex_RUs,&proc->cond_RUs,&proc->instance_cnt_RUs,"wakeup_txfh")<0) {
+ LOG_E(PHY,"Frame %d, subframe %d: TX FH not ready\n", proc->frame_tx, proc->slot_tx);
+ return(-1);
+ }
+
+ pthread_mutex_lock(&gNB->proc.mutex_RU_tx);
+ gNB->proc.RU_mask_tx = 0;
+ pthread_mutex_unlock(&gNB->proc.mutex_RU_tx);
+
+ if (release_thread(&proc->mutex_RUs,&proc->instance_cnt_RUs,"wakeup_txfh")<0) return(-1);
+
+ for(int i=0; inum_RU; i++) {
+ ru = gNB->RU_list[i];
+ ru_proc = &ru->proc;
+
+ if (ru_proc->instance_cnt_gNBs == 0) {
+ LOG_E(PHY,"Frame %d, subframe %d: TX FH thread busy, dropping Frame %d, subframe %d\n", ru_proc->frame_tx, ru_proc->tti_tx, proc->frame_rx, proc->slot_rx);
+ return(-1);
+ }
+
+ if (pthread_mutex_timedlock(&ru_proc->mutex_gNBs,&wait) != 0) {
+ LOG_E( PHY, "[eNB] ERROR pthread_mutex_lock for eNB TX1 thread %d (IC %d)\n", ru_proc->tti_rx&1,ru_proc->instance_cnt_gNBs );
+ exit_fun( "error locking mutex_gNB" );
+ return(-1);
+ }
+
+ ru_proc->instance_cnt_gNBs = 0;
+ ru_proc->timestamp_tx = proc->timestamp_tx;
+ ru_proc->tti_tx = proc->slot_tx;
+ ru_proc->frame_tx = proc->frame_tx;
+ LOG_I(PHY,"Signaling tx_thread_fh for %d.%d\n",ru_proc->frame_tx,ru_proc->tti_tx);
+
+ // the thread can now be woken up
+ if (pthread_cond_signal(&ru_proc->cond_gNBs) != 0) {
+ LOG_E( PHY, "[gNB] ERROR pthread_cond_signal for gNB TXnp4 thread\n");
+ exit_fun( "ERROR pthread_cond_signal" );
+ return(-1);
+ }
+
+ pthread_mutex_unlock( &ru_proc->mutex_gNBs );
+ }
+
+ return(0);
+}
+
+int wakeup_tx(PHY_VARS_gNB *gNB) {
+ gNB_L1_proc_t *proc=&gNB->proc;
+ gNB_L1_rxtx_proc_t *L1_proc_tx = &proc->L1_proc_tx;
+ gNB_L1_rxtx_proc_t *L1_proc = &proc->L1_proc;
+ struct timespec wait;
+ wait.tv_sec=0;
+ wait.tv_nsec=5000000L;
+
+ if (pthread_mutex_timedlock(&L1_proc_tx->mutex,&wait) != 0) {
+ LOG_E(PHY, "[SCHED][eNB] ERROR locking mutex for eNB L1_thread_tx\n");
+ exit_fun("ERROR pthread_lock");
+ return(-1);
+ }
+
+ while(L1_proc_tx->instance_cnt == 0) {
+ pthread_cond_wait(&L1_proc_tx->cond,&L1_proc_tx->mutex);
+ }
+
+ L1_proc_tx->instance_cnt = 0;
+ L1_proc_tx->slot_rx = L1_proc->slot_rx;
+ L1_proc_tx->frame_rx = L1_proc->frame_rx;
+ L1_proc_tx->slot_tx = L1_proc->slot_tx;
+ L1_proc_tx->frame_tx = L1_proc->frame_tx;
+ L1_proc_tx->timestamp_tx = L1_proc->timestamp_tx;
+
+ // the thread can now be woken up
+ if (pthread_cond_signal(&L1_proc_tx->cond) != 0) {
+ LOG_E( PHY, "[eNB] ERROR pthread_cond_signal for eNB TXnp4 thread\n");
+ exit_fun( "ERROR pthread_cond_signal" );
+ return(-1);
+ }
+
+ pthread_mutex_unlock( &L1_proc_tx->mutex);
+ return(0);
+}
+
+int wakeup_rxtx(PHY_VARS_gNB *gNB,RU_t *ru) {
+ gNB_L1_proc_t *proc=&gNB->proc;
+ gNB_L1_rxtx_proc_t *L1_proc=&proc->L1_proc;
+ NR_DL_FRAME_PARMS *fp = &gNB->frame_parms;
+ RU_proc_t *ru_proc=&ru->proc;
+ int i;
+ struct timespec wait;
+ pthread_mutex_lock(&proc->mutex_RU);
+
+ for (i=0; inum_RU; i++) {
+ if (ru == gNB->RU_list[i]) {
+ if ((proc->RU_mask&(1< 0)
+ LOG_E(PHY,"gNB %d frame %d, subframe %d : previous information from RU %d (num_RU %d,mask %x) has not been served yet!\n",
+ gNB->Mod_id,proc->frame_rx,proc->slot_rx,ru->idx,gNB->num_RU,proc->RU_mask);
+
+ proc->RU_mask |= (1<RU_mask != (1<num_RU)-1) { // not all RUs have provided their information so return
+ LOG_E(PHY,"Not all RUs have provided their info\n");
+ pthread_mutex_unlock(&proc->mutex_RU);
+ return(0);
+ } else { // all RUs have provided their information so continue on and wakeup gNB processing
+ proc->RU_mask = 0;
+ pthread_mutex_unlock(&proc->mutex_RU);
+ }
+
+ wait.tv_sec=0;
+ wait.tv_nsec=5000000L;
+
+ /* accept some delay in processing - up to 5ms */
+ for (i = 0; i < fp->slots_per_frame && L1_proc->instance_cnt == 0; i++) {
+ LOG_W( PHY,"[gNB] SFN.SL %d.%d, gNB RXn-TXnp4 thread busy!! (i %d, cnt %i)\n", L1_proc->frame_tx, L1_proc->slot_tx, i,L1_proc->instance_cnt);
+ usleep(100);
+ }
+
+ if (L1_proc->instance_cnt == 0) {
+ exit_fun( "TX thread busy" );
+ return(-1);
+ }
+
+ // wake up TX for subframe n+sl_ahead
+ // lock the TX mutex and make sure the thread is ready
+ if (pthread_mutex_timedlock(&L1_proc->mutex,&wait) != 0) {
+ LOG_E( PHY, "[gNB] ERROR pthread_mutex_lock for gNB RXTX thread %d (IC %d)\n", L1_proc->slot_rx&1,L1_proc->instance_cnt );
+ exit_fun( "error locking mutex" );
+ return(-1);
+ }
+
+ ++L1_proc->instance_cnt;
+ // We have just received and processed the common part of a subframe, say n.
+ // TS_rx is the last received timestamp (start of 1st slot), TS_tx is the desired
+ // transmitted timestamp of the next TX slot (first).
+ // The last (TS_rx mod samples_per_frame) was n*samples_per_tti,
+ // we want to generate subframe (n+sl_ahead), so TS_tx = TX_rx+sl_ahead*samples_per_tti,
+ // and proc->slot_tx = proc->slot_rx+sl_ahead
+ L1_proc->timestamp_tx = ru_proc->timestamp_rx + (sl_ahead*fp->samples_per_slot);
+ L1_proc->frame_rx = ru_proc->frame_rx;
+ L1_proc->slot_rx = ru_proc->tti_rx;
+ L1_proc->frame_tx = (L1_proc->slot_rx > (fp->slots_per_frame-1-sl_ahead)) ? (L1_proc->frame_rx+1)&1023 : L1_proc->frame_rx;
+ L1_proc->slot_tx = (L1_proc->slot_rx + sl_ahead)%fp->slots_per_frame;
+ LOG_I(PHY,"wakeupL1: passing parameter IC = %d, RX: %d.%d, TX: %d.%d to L1 sl_ahead = %d\n", L1_proc->instance_cnt, L1_proc->frame_rx, L1_proc->slot_rx, L1_proc->frame_tx, L1_proc->slot_tx, sl_ahead);
+
+ // the thread can now be woken up
+ if (pthread_cond_signal(&L1_proc->cond) != 0) {
+ LOG_E( PHY, "[gNB] ERROR pthread_cond_signal for gNB RXn-TXnp4 thread\n");
+ exit_fun( "ERROR pthread_cond_signal" );
+ return(-1);
+ }
+
+ pthread_mutex_unlock( &L1_proc->mutex );
+ return(0);
+}
+/*
+void wakeup_prach_gNB(PHY_VARS_gNB *gNB,RU_t *ru,int frame,int subframe) {
+
+ gNB_L1_proc_t *proc = &gNB->proc;
+ LTE_DL_FRAME_PARMS *fp=&gNB->frame_parms;
+ int i;
+
+ if (ru!=NULL) {
+ pthread_mutex_lock(&proc->mutex_RU_PRACH);
+ for (i=0;inum_RU;i++) {
+ if (ru == gNB->RU_list[i]) {
+ LOG_D(PHY,"frame %d, subframe %d: RU %d for gNB %d signals PRACH (mask %x, num_RU %d)\n",frame,subframe,i,gNB->Mod_id,proc->RU_mask_prach,gNB->num_RU);
+ if ((proc->RU_mask_prach&(1< 0)
+ LOG_E(PHY,"gNB %d frame %d, subframe %d : previous information (PRACH) from RU %d (num_RU %d, mask %x) has not been served yet!\n",
+ gNB->Mod_id,frame,subframe,ru->idx,gNB->num_RU,proc->RU_mask_prach);
+ proc->RU_mask_prach |= (1<RU_mask_prach != (1<num_RU)-1) { // not all RUs have provided their information so return
+ pthread_mutex_unlock(&proc->mutex_RU_PRACH);
+ return;
+ }
+ else { // all RUs have provided their information so continue on and wakeup gNB processing
+ proc->RU_mask_prach = 0;
+ pthread_mutex_unlock(&proc->mutex_RU_PRACH);
+ }
+ }
+
+ // check if we have to detect PRACH first
+ if (is_prach_subframe(fp,frame,subframe)>0) {
+ LOG_D(PHY,"Triggering prach processing, frame %d, subframe %d\n",frame,subframe);
+ if (proc->instance_cnt_prach == 0) {
+ LOG_W(PHY,"[gNB] Frame %d Subframe %d, dropping PRACH\n", frame,subframe);
+ return;
+ }
+
+ // wake up thread for PRACH RX
+ if (pthread_mutex_lock(&proc->mutex_prach) != 0) {
+ LOG_E( PHY, "[gNB] ERROR pthread_mutex_lock for gNB PRACH thread %d (IC %d)\n", proc->thread_index, proc->instance_cnt_prach);
+ exit_fun( "error locking mutex_prach" );
+ return;
+ }
+
+ ++proc->instance_cnt_prach;
+ // set timing for prach thread
+ proc->frame_prach = frame;
+ proc->subframe_prach = subframe;
+
+ // the thread can now be woken up
+ if (pthread_cond_signal(&proc->cond_prach) != 0) {
+ LOG_E( PHY, "[gNB] ERROR pthread_cond_signal for gNB PRACH thread %d\n", proc->thread_index);
+ exit_fun( "ERROR pthread_cond_signal" );
+ return;
+ }
+
+ pthread_mutex_unlock( &proc->mutex_prach );
+ }
+
+}*/
+
+/*!
+ * \brief The prach receive thread of gNB.
+ * \param param is a \ref gNB_L1_proc_t structure which contains the info what to process.
+ * \returns a pointer to an int. The storage is not on the heap and must not be freed.
+ */
+/*
+static void* gNB_thread_prach( void* param ) {
+ static int gNB_thread_prach_status;
+
+
+ PHY_VARS_gNB *gNB= (PHY_VARS_gNB *)param;
+ gNB_L1_proc_t *proc = &gNB->proc;
+
+ // set default return value
+ gNB_thread_prach_status = 0;
+
+
+
+ while (!oai_exit) {
+
+ if (oai_exit) break;
+
+
+ if (wait_on_condition(&proc->mutex_prach,&proc->cond_prach,&proc->instance_cnt_prach,"gNB_prach_thread") < 0) break;
+
+ LOG_D(PHY,"Running gNB prach procedures\n");
+ prach_procedures(gNB
+#if (RRC_VERSION >= MAKE_VERSION(14, 0, 0))
+ ,0
+#endif
+ );
+
+ if (release_thread(&proc->mutex_prach,&proc->instance_cnt_prach,"gNB_prach_thread") < 0) break;
+ }
+
+ LOG_I(PHY, "Exiting gNB thread PRACH\n");
+
+ gNB_thread_prach_status = 0;
+ return &gNB_thread_prach_status;
+}
+*/
+
+extern void init_td_thread(PHY_VARS_gNB *);
+extern void init_te_thread(PHY_VARS_gNB *);
+
+void init_gNB_proc(int inst) {
+ int i=0;
+ int CC_id;
+ PHY_VARS_gNB *gNB;
+ gNB_L1_proc_t *proc;
+ gNB_L1_rxtx_proc_t *L1_proc,*L1_proc_tx;
+ LOG_I(PHY,"%s(inst:%d) RC.nb_nr_CC[inst]:%d \n",__FUNCTION__,inst,RC.nb_nr_CC[inst]);
+
+ for (CC_id=0; CC_idproc;
+ L1_proc = &proc->L1_proc;
+ L1_proc_tx = &proc->L1_proc_tx;
+ L1_proc->instance_cnt = -1;
+ L1_proc_tx->instance_cnt = -1;
+ L1_proc->instance_cnt_RUs = 0;
+ L1_proc_tx->instance_cnt_RUs = 0;
+ proc->instance_cnt_prach = -1;
+ proc->instance_cnt_asynch_rxtx = -1;
+ proc->CC_id = CC_id;
+ proc->first_rx =1;
+ proc->first_tx =1;
+ proc->RU_mask =0;
+ proc->RU_mask_tx = (1<num_RU)-1;
+ proc->RU_mask_prach =0;
+ pthread_mutex_init( &gNB->UL_INFO_mutex, NULL);
+ pthread_mutex_init( &L1_proc->mutex, NULL);
+ pthread_mutex_init( &L1_proc_tx->mutex, NULL);
+ pthread_cond_init( &L1_proc->cond, NULL);
+ pthread_cond_init( &L1_proc_tx->cond, NULL);
+ pthread_mutex_init( &proc->mutex_prach, NULL);
+ pthread_mutex_init( &proc->mutex_asynch_rxtx, NULL);
+ pthread_mutex_init( &proc->mutex_RU,NULL);
+ pthread_mutex_init( &proc->mutex_RU_tx,NULL);
+ pthread_mutex_init( &proc->mutex_RU_PRACH,NULL);
+ pthread_cond_init( &proc->cond_prach, NULL);
+ pthread_cond_init( &proc->cond_asynch_rxtx, NULL);
+ LOG_I(PHY,"gNB->single_thread_flag:%d\n", gNB->single_thread_flag);
+
+ if (get_thread_parallel_conf() == PARALLEL_RU_L1_SPLIT || get_thread_parallel_conf() == PARALLEL_RU_L1_TRX_SPLIT) {
+ threadCreate( &L1_proc->pthread, gNB_L1_thread, gNB, "L1_proc", -1, OAI_PRIORITY_RT );
+ threadCreate( &L1_proc_tx->pthread, gNB_L1_thread_tx, gNB,"L1_proc_tx", -1, OAI_PRIORITY_RT);
+ }
+
+ //pthread_create( &proc->pthread_prach, attr_prach, gNB_thread_prach, gNB );
+ char name[16];
+
+ if (gNB->single_thread_flag==0) {
+ snprintf( name, sizeof(name), "L1 %d", i );
+ pthread_setname_np( L1_proc->pthread, name );
+ snprintf( name, sizeof(name), "L1TX %d", i );
+ pthread_setname_np( L1_proc_tx->pthread, name );
+ }
+
+ AssertFatal(proc->instance_cnt_prach == -1,"instance_cnt_prach = %d\n",proc->instance_cnt_prach);
+ }
+
+ /* setup PHY proc TX sync mechanism */
+ pthread_mutex_init(&sync_phy_proc.mutex_phy_proc_tx, NULL);
+ pthread_cond_init(&sync_phy_proc.cond_phy_proc_tx, NULL);
+ sync_phy_proc.phy_proc_CC_id = 0;
+}
+
+
+
+/*!
+ * \brief Terminate gNB TX and RX threads.
+ */
+void kill_gNB_proc(int inst) {
+ int *status;
+ PHY_VARS_gNB *gNB;
+ gNB_L1_proc_t *proc;
+ gNB_L1_rxtx_proc_t *L1_proc, *L1_proc_tx;
+
+ for (int CC_id=0; CC_idproc;
+ L1_proc = &proc->L1_proc;
+ L1_proc_tx = &proc->L1_proc_tx;
+ LOG_I(PHY, "Killing TX CC_id %d inst %d\n", CC_id, inst );
+
+ if (get_thread_parallel_conf() == PARALLEL_RU_L1_SPLIT || get_thread_parallel_conf() == PARALLEL_RU_L1_TRX_SPLIT) {
+ pthread_mutex_lock(&L1_proc->mutex);
+ L1_proc->instance_cnt = 0;
+ pthread_cond_signal(&L1_proc->cond);
+ pthread_mutex_unlock(&L1_proc->mutex);
+ pthread_mutex_lock(&L1_proc_tx->mutex);
+ L1_proc_tx->instance_cnt = 0;
+ pthread_cond_signal(&L1_proc_tx->cond);
+ pthread_mutex_unlock(&L1_proc_tx->mutex);
+ }
+
+ proc->instance_cnt_prach = 0;
+ pthread_cond_signal( &proc->cond_prach );
+ pthread_cond_signal( &proc->cond_asynch_rxtx );
+ pthread_cond_broadcast(&sync_phy_proc.cond_phy_proc_tx);
+ // LOG_D(PHY, "joining pthread_prach\n");
+ // pthread_join( proc->pthread_prach, (void**)&status );
+ LOG_I(PHY, "Destroying prach mutex/cond\n");
+ pthread_mutex_destroy( &proc->mutex_prach );
+ pthread_cond_destroy( &proc->cond_prach );
+ LOG_I(PHY, "Destroying UL_INFO mutex\n");
+ pthread_mutex_destroy(&gNB->UL_INFO_mutex);
+
+ if (get_thread_parallel_conf() == PARALLEL_RU_L1_SPLIT || get_thread_parallel_conf() == PARALLEL_RU_L1_TRX_SPLIT) {
+ LOG_I(PHY, "Joining L1_proc mutex/cond\n");
+ pthread_join( L1_proc->pthread, (void **)&status );
+ LOG_I(PHY, "Joining L1_proc_tx mutex/cond\n");
+ pthread_join( L1_proc_tx->pthread, (void **)&status );
+ }
+
+ LOG_I(PHY, "Destroying L1_proc mutex/cond\n");
+ pthread_mutex_destroy( &L1_proc->mutex );
+ pthread_cond_destroy( &L1_proc->cond );
+ LOG_I(PHY, "Destroying L1_proc_tx mutex/cond\n");
+ pthread_mutex_destroy( &L1_proc_tx->mutex );
+ pthread_cond_destroy( &L1_proc_tx->cond );
+ pthread_mutex_destroy( &proc->mutex_RU );
+ pthread_mutex_destroy( &proc->mutex_RU_tx );
+ }
+}
+
+
+
+
+void reset_opp_meas(void) {
+ int sfn;
+ reset_meas(&softmodem_stats_mt);
+ reset_meas(&softmodem_stats_hw);
+
+ for (sfn=0; sfn < 10; sfn++) {
+ reset_meas(&softmodem_stats_rxtx_sf);
+ reset_meas(&softmodem_stats_rx_sf);
+ }
+}
+
+
+void print_opp_meas(void) {
+ int sfn=0;
+ print_meas(&softmodem_stats_mt, "Main gNB Thread", NULL, NULL);
+ print_meas(&softmodem_stats_hw, "HW Acquisation", NULL, NULL);
+
+ for (sfn=0; sfn < 10; sfn++) {
+ print_meas(&softmodem_stats_rxtx_sf,"[gNB][total_phy_proc_rxtx]",NULL, NULL);
+ print_meas(&softmodem_stats_rx_sf,"[gNB][total_phy_proc_rx]",NULL,NULL);
+ }
+}
+
+
+/// eNB kept in function name for nffapi calls, TO FIX
+void init_eNB_afterRU(void) {
+ int inst,CC_id,ru_id,i,aa;
+ PHY_VARS_gNB *gNB;
+ LOG_I(PHY,"%s() RC.nb_nr_inst:%d\n", __FUNCTION__, RC.nb_nr_inst);
+
+ for (inst=0; instnum_RU>0,"Number of RU attached to gNB %d is zero\n",gNB->Mod_id);
+
+ LOG_I(PHY,"Mapping RX ports from %d RUs to gNB %d\n",gNB->num_RU,gNB->Mod_id);
+ //LOG_I(PHY,"Overwriting gNB->prach_vars.rxsigF[0]:%p\n", gNB->prach_vars.rxsigF[0]);
+ gNB->prach_vars.rxsigF[0] = (int16_t **)malloc16(64*sizeof(int16_t *));
+ LOG_I(PHY,"gNB->num_RU:%d\n", gNB->num_RU);
+
+ for (ru_id=0,aa=0; ru_idnum_RU; ru_id++) {
+ AssertFatal(gNB->RU_list[ru_id]->common.rxdataF!=NULL,
+ "RU %d : common.rxdataF is NULL\n",
+ gNB->RU_list[ru_id]->idx);
+ AssertFatal(gNB->RU_list[ru_id]->prach_rxsigF!=NULL,
+ "RU %d : prach_rxsigF is NULL\n",
+ gNB->RU_list[ru_id]->idx);
+
+ for (i=0; iRU_list[ru_id]->nb_rx; aa++,i++) {
+ LOG_I(PHY,"Attaching RU %d antenna %d to gNB antenna %d\n",gNB->RU_list[ru_id]->idx,i,aa);
+ gNB->prach_vars.rxsigF[0][aa] = gNB->RU_list[ru_id]->prach_rxsigF[i];
+ gNB->common_vars.rxdataF[aa] = gNB->RU_list[ru_id]->common.rxdataF[i];
+ }
+ }
+
+ /* TODO: review this code, there is something wrong.
+ * In monolithic mode, we come here with nb_antennas_rx == 0
+ * (not tested in other modes).
+ */
+ //init_precoding_weights(RC.gNB[inst][CC_id]);
+ }
+
+ init_gNB_proc(inst);
+ }
+
+ for (ru_id=0; ru_idnr_wakeup_rxtx = wakeup_rxtx;
+ // RC.ru[ru_id]->wakeup_prach_eNB = wakeup_prach_gNB;
+ RC.ru[ru_id]->gNB_top = gNB_top;
+ }
+}
+
+void init_gNB(int single_thread_flag,int wait_for_sync) {
+ int CC_id;
+ int inst;
+ PHY_VARS_gNB *gNB;
+ LOG_I(PHY,"[nr-softmodem.c] gNB structure about to allocated RC.nb_nr_L1_inst:%d RC.nb_nr_L1_CC[0]:%d\n",RC.nb_nr_L1_inst,RC.nb_nr_L1_CC[0]);
+
+ if (RC.gNB == NULL) RC.gNB = (PHY_VARS_gNB ***) malloc(RC.nb_nr_L1_inst*sizeof(PHY_VARS_gNB **));
+
+ LOG_I(PHY,"[lte-softmodem.c] gNB structure RC.gNB allocated\n");
+
+ for (inst=0; instabstraction_flag = 0;
+ gNB->single_thread_flag = single_thread_flag;
+ /*nr_polar_init(&gNB->nrPolar_params,
+ NR_POLAR_PBCH_MESSAGE_TYPE,
+ NR_POLAR_PBCH_PAYLOAD_BITS,
+ NR_POLAR_PBCH_AGGREGATION_LEVEL);*/
+ LOG_I(PHY,"Initializing gNB %d CC_id %d single_thread_flag:%d\n",inst,CC_id,single_thread_flag);
+#ifndef OCP_FRAMEWORK
+ LOG_I(PHY,"Initializing gNB %d CC_id %d\n",inst,CC_id);
+#endif
+ LOG_I(PHY,"Registering with MAC interface module\n");
+ AssertFatal((gNB->if_inst = NR_IF_Module_init(inst))!=NULL,"Cannot register interface");
+ gNB->if_inst->NR_Schedule_response = nr_schedule_response;
+ gNB->if_inst->NR_PHY_config_req = nr_phy_config_request;
+ memset((void *)&gNB->UL_INFO,0,sizeof(gNB->UL_INFO));
+ memset((void *)&gNB->Sched_INFO,0,sizeof(gNB->Sched_INFO));
+ LOG_I(PHY,"Setting indication lists\n");
+ gNB->UL_INFO.rx_ind.rx_indication_body.rx_pdu_list = gNB->rx_pdu_list;
+ gNB->UL_INFO.crc_ind.crc_indication_body.crc_pdu_list = gNB->crc_pdu_list;
+ gNB->UL_INFO.sr_ind.sr_indication_body.sr_pdu_list = gNB->sr_pdu_list;
+ gNB->UL_INFO.harq_ind.harq_indication_body.harq_pdu_list = gNB->harq_pdu_list;
+ gNB->UL_INFO.cqi_ind.cqi_pdu_list = gNB->cqi_pdu_list;
+ gNB->UL_INFO.cqi_ind.cqi_raw_pdu_list = gNB->cqi_raw_pdu_list;
+ gNB->prach_energy_counter = 0;
+ }
+ }
+
+ LOG_I(PHY,"[nr-softmodem.c] gNB structure allocated\n");
+}
+
+
+void stop_gNB(int nb_inst) {
+ for (int inst=0; inst.
+
+ Contact Information
+ OpenAirInterface Admin: openair_admin@eurecom.fr
+ OpenAirInterface Tech : openair_tech@eurecom.fr
+ OpenAirInterface Dev : openair4g-devel@lists.eurecom.fr
+
+ Address : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE
+
+*******************************************************************************/
+
+/*! \file lte-enb.c
+ * \brief Top-level threads for eNodeB
+ * \author R. Knopp, F. Kaltenberger, Navid Nikaein
+ * \date 2012
+ * \version 0.1
+ * \company Eurecom
+ * \email: knopp@eurecom.fr,florian.kaltenberger@eurecom.fr, navid.nikaein@eurecom.fr
+ * \note
+ * \warning
+ */
+#define _GNU_SOURCE
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#undef MALLOC //there are two conflicting definitions, so we better make sure we don't use it at all
+
+#include "common/utils/assertions.h"
+#include "common/utils/system.h"
+#include "msc.h"
+
+#include "../../ARCH/COMMON/common_lib.h"
+#include "../../ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.h"
+
+#include "PHY/LTE_TRANSPORT/if4_tools.h"
+#include "PHY/LTE_TRANSPORT/if5_tools.h"
+
+#include "PHY/types.h"
+#include "PHY/defs_nr_common.h"
+#include "PHY/phy_extern.h"
+#include "PHY/LTE_TRANSPORT/transport_proto.h"
+#include "PHY/INIT/phy_init.h"
+#include "SCHED/sched_eNB.h"
+#include "SCHED_NR/sched_nr.h"
+
+#include "LAYER2/MAC/mac.h"
+#include "LAYER2/MAC/mac_extern.h"
+#include "LAYER2/MAC/mac_proto.h"
+#include "RRC/LTE/rrc_extern.h"
+#include "PHY_INTERFACE/phy_interface.h"
+
+#include "common/utils/LOG/log.h"
+#include "common/utils/LOG/vcd_signal_dumper.h"
+
+#include "enb_config.h"
+
+#ifdef SMBV
+#include "PHY/TOOLS/smbv.h"
+unsigned short config_frames[4] = {2,9,11,13};
+#endif
+
+/* these variables have to be defined before including ENB_APP/enb_paramdef.h */
+static int DEFBANDS[] = {7};
+static int DEFENBS[] = {0};
+
+#include "ENB_APP/enb_paramdef.h"
+#include "common/config/config_userapi.h"
+
+#ifndef OPENAIR2
+ #include "UTIL/OTG/otg_extern.h"
+#endif
+
+#if defined(ENABLE_ITTI)
+ #if defined(ENABLE_USE_MME)
+ #include "s1ap_eNB.h"
+ #ifdef PDCP_USE_NETLINK
+ #include "SIMULATION/ETH_TRANSPORT/proto.h"
+ #endif
+ #endif
+#endif
+
+#include "T.h"
+#include "nfapi_interface.h"
+
+extern volatile int oai_exit;
+
+
+extern void nr_phy_free_RU(RU_t *);
+extern void nr_phy_config_request(NR_PHY_Config_t *gNB);
+
+extern PARALLEL_CONF_t get_thread_parallel_conf(void);
+extern WORKER_CONF_t get_thread_worker_conf(void);
+
+void init_RU(char *);
+void stop_RU(int nb_ru);
+void do_ru_sync(RU_t *ru);
+
+void configure_ru(int idx,
+ void *arg);
+
+void configure_rru(int idx,
+ void *arg);
+
+int attach_rru(RU_t *ru);
+
+int connect_rau(RU_t *ru);
+
+extern uint16_t sl_ahead;
+
+extern int emulate_rf;
+extern int numerology;
+
+/*************************************************************/
+/* Functions to attach and configure RRU */
+
+extern void wait_gNBs(void);
+
+int attach_rru(RU_t *ru) {
+ ssize_t msg_len,len;
+ RRU_CONFIG_msg_t rru_config_msg;
+ int received_capabilities=0;
+ wait_gNBs();
+
+ // Wait for capabilities
+ while (received_capabilities==0) {
+ memset((void *)&rru_config_msg,0,sizeof(rru_config_msg));
+ rru_config_msg.type = RAU_tick;
+ rru_config_msg.len = sizeof(RRU_CONFIG_msg_t)-MAX_RRU_CONFIG_SIZE;
+ LOG_I(PHY,"Sending RAU tick to RRU %d\n",ru->idx);
+ AssertFatal((ru->ifdevice.trx_ctlsend_func(&ru->ifdevice,&rru_config_msg,rru_config_msg.len)!=-1),
+ "RU %d cannot access remote radio\n",ru->idx);
+ msg_len = sizeof(RRU_CONFIG_msg_t)-MAX_RRU_CONFIG_SIZE+sizeof(RRU_capabilities_t);
+
+ // wait for answer with timeout
+ if ((len = ru->ifdevice.trx_ctlrecv_func(&ru->ifdevice,
+ &rru_config_msg,
+ msg_len))<0) {
+ LOG_I(PHY,"Waiting for RRU %d\n",ru->idx);
+ } else if (rru_config_msg.type == RRU_capabilities) {
+ AssertFatal(rru_config_msg.len==msg_len,"Received capabilities with incorrect length (%d!=%d)\n",(int)rru_config_msg.len,(int)msg_len);
+ LOG_I(PHY,"Received capabilities from RRU %d (len %d/%d, num_bands %d,max_pdschReferenceSignalPower %d, max_rxgain %d, nb_tx %d, nb_rx %d)\n",ru->idx,
+ (int)rru_config_msg.len,(int)msg_len,
+ ((RRU_capabilities_t *)&rru_config_msg.msg[0])->num_bands,
+ ((RRU_capabilities_t *)&rru_config_msg.msg[0])->max_pdschReferenceSignalPower[0],
+ ((RRU_capabilities_t *)&rru_config_msg.msg[0])->max_rxgain[0],
+ ((RRU_capabilities_t *)&rru_config_msg.msg[0])->nb_tx[0],
+ ((RRU_capabilities_t *)&rru_config_msg.msg[0])->nb_rx[0]);
+ received_capabilities=1;
+ } else {
+ LOG_E(PHY,"Received incorrect message %d from RRU %d\n",rru_config_msg.type,ru->idx);
+ }
+ }
+
+ configure_ru(ru->idx,
+ (RRU_capabilities_t *)&rru_config_msg.msg[0]);
+ rru_config_msg.type = RRU_config;
+ rru_config_msg.len = sizeof(RRU_CONFIG_msg_t)-MAX_RRU_CONFIG_SIZE+sizeof(RRU_config_t);
+ LOG_I(PHY,"Sending Configuration to RRU %d (num_bands %d,band0 %d,txfreq %u,rxfreq %u,att_tx %d,att_rx %d,N_RB_DL %d,N_RB_UL %d,3/4FS %d, prach_FO %d, prach_CI %d)\n",ru->idx,
+ ((RRU_config_t *)&rru_config_msg.msg[0])->num_bands,
+ ((RRU_config_t *)&rru_config_msg.msg[0])->band_list[0],
+ ((RRU_config_t *)&rru_config_msg.msg[0])->tx_freq[0],
+ ((RRU_config_t *)&rru_config_msg.msg[0])->rx_freq[0],
+ ((RRU_config_t *)&rru_config_msg.msg[0])->att_tx[0],
+ ((RRU_config_t *)&rru_config_msg.msg[0])->att_rx[0],
+ ((RRU_config_t *)&rru_config_msg.msg[0])->N_RB_DL[0],
+ ((RRU_config_t *)&rru_config_msg.msg[0])->N_RB_UL[0],
+ ((RRU_config_t *)&rru_config_msg.msg[0])->threequarter_fs[0],
+ ((RRU_config_t *)&rru_config_msg.msg[0])->prach_FreqOffset[0],
+ ((RRU_config_t *)&rru_config_msg.msg[0])->prach_ConfigIndex[0]);
+ AssertFatal((ru->ifdevice.trx_ctlsend_func(&ru->ifdevice,&rru_config_msg,rru_config_msg.len)!=-1),
+ "RU %d failed send configuration to remote radio\n",ru->idx);
+ return 0;
+}
+
+int connect_rau(RU_t *ru) {
+ RRU_CONFIG_msg_t rru_config_msg;
+ ssize_t msg_len;
+ int tick_received = 0;
+ int configuration_received = 0;
+ RRU_capabilities_t *cap;
+ int i;
+ int len;
+
+ // wait for RAU_tick
+ while (tick_received == 0) {
+ msg_len = sizeof(RRU_CONFIG_msg_t)-MAX_RRU_CONFIG_SIZE;
+
+ if ((len = ru->ifdevice.trx_ctlrecv_func(&ru->ifdevice,
+ &rru_config_msg,
+ msg_len))<0) {
+ LOG_I(PHY,"Waiting for RAU\n");
+ } else {
+ if (rru_config_msg.type == RAU_tick) {
+ LOG_I(PHY,"Tick received from RAU\n");
+ tick_received = 1;
+ } else LOG_E(PHY,"Received erroneous message (%d)from RAU, expected RAU_tick\n",rru_config_msg.type);
+ }
+ }
+
+ // send capabilities
+ rru_config_msg.type = RRU_capabilities;
+ rru_config_msg.len = sizeof(RRU_CONFIG_msg_t)-MAX_RRU_CONFIG_SIZE+sizeof(RRU_capabilities_t);
+ cap = (RRU_capabilities_t *)&rru_config_msg.msg[0];
+ LOG_I(PHY,"Sending Capabilities (len %d, num_bands %d,max_pdschReferenceSignalPower %d, max_rxgain %d, nb_tx %d, nb_rx %d)\n",
+ (int)rru_config_msg.len,ru->num_bands,ru->max_pdschReferenceSignalPower,ru->max_rxgain,ru->nb_tx,ru->nb_rx);
+
+ switch (ru->function) {
+ case NGFI_RRU_IF4p5:
+ cap->FH_fmt = OAI_IF4p5_only;
+ break;
+
+ case NGFI_RRU_IF5:
+ cap->FH_fmt = OAI_IF5_only;
+ break;
+
+ case MBP_RRU_IF5:
+ cap->FH_fmt = MBP_IF5;
+ break;
+
+ default:
+ AssertFatal(1==0,"RU_function is unknown %d\n",RC.ru[0]->function);
+ break;
+ }
+
+ cap->num_bands = ru->num_bands;
+
+ for (i=0; inum_bands; i++) {
+ LOG_I(PHY,"Band %d: nb_rx %d nb_tx %d pdschReferenceSignalPower %d rxgain %d\n",
+ ru->band[i],ru->nb_rx,ru->nb_tx,ru->max_pdschReferenceSignalPower,ru->max_rxgain);
+ cap->band_list[i] = ru->band[i];
+ cap->nb_rx[i] = ru->nb_rx;
+ cap->nb_tx[i] = ru->nb_tx;
+ cap->max_pdschReferenceSignalPower[i] = ru->max_pdschReferenceSignalPower;
+ cap->max_rxgain[i] = ru->max_rxgain;
+ }
+
+ AssertFatal((ru->ifdevice.trx_ctlsend_func(&ru->ifdevice,&rru_config_msg,rru_config_msg.len)!=-1),
+ "RU %d failed send capabilities to RAU\n",ru->idx);
+ // wait for configuration
+ rru_config_msg.len = sizeof(RRU_CONFIG_msg_t)-MAX_RRU_CONFIG_SIZE+sizeof(RRU_config_t);
+
+ while (configuration_received == 0) {
+ if ((len = ru->ifdevice.trx_ctlrecv_func(&ru->ifdevice,
+ &rru_config_msg,
+ rru_config_msg.len))<0) {
+ LOG_I(PHY,"Waiting for configuration from RAU\n");
+ } else {
+ LOG_I(PHY,"Configuration received from RAU (num_bands %d,band0 %d,txfreq %u,rxfreq %u,att_tx %d,att_rx %d,N_RB_DL %d,N_RB_UL %d,3/4FS %d, prach_FO %d, prach_CI %d)\n",
+ ((RRU_config_t *)&rru_config_msg.msg[0])->num_bands,
+ ((RRU_config_t *)&rru_config_msg.msg[0])->band_list[0],
+ ((RRU_config_t *)&rru_config_msg.msg[0])->tx_freq[0],
+ ((RRU_config_t *)&rru_config_msg.msg[0])->rx_freq[0],
+ ((RRU_config_t *)&rru_config_msg.msg[0])->att_tx[0],
+ ((RRU_config_t *)&rru_config_msg.msg[0])->att_rx[0],
+ ((RRU_config_t *)&rru_config_msg.msg[0])->N_RB_DL[0],
+ ((RRU_config_t *)&rru_config_msg.msg[0])->N_RB_UL[0],
+ ((RRU_config_t *)&rru_config_msg.msg[0])->threequarter_fs[0],
+ ((RRU_config_t *)&rru_config_msg.msg[0])->prach_FreqOffset[0],
+ ((RRU_config_t *)&rru_config_msg.msg[0])->prach_ConfigIndex[0]);
+ configure_rru(ru->idx,
+ (void *)&rru_config_msg.msg[0]);
+ configuration_received = 1;
+ }
+ }
+
+ return 0;
+}
+/*************************************************************/
+/* Southbound Fronthaul functions, RCC/RAU */
+
+// southbound IF5 fronthaul for 16-bit OAI format
+static inline void fh_if5_south_out(RU_t *ru) {
+ if (ru == RC.ru[0]) VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TST, ru->proc.timestamp_tx&0xffffffff );
+
+ send_IF5(ru, ru->proc.timestamp_tx, ru->proc.tti_tx, &ru->seqno, IF5_RRH_GW_DL);
+}
+
+// southbound IF5 fronthaul for Mobipass packet format
+static inline void fh_if5_mobipass_south_out(RU_t *ru) {
+ if (ru == RC.ru[0]) VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TST, ru->proc.timestamp_tx&0xffffffff );
+
+ send_IF5(ru, ru->proc.timestamp_tx, ru->proc.tti_tx, &ru->seqno, IF5_MOBIPASS);
+}
+
+// southbound IF4p5 fronthaul
+static inline void fh_if4p5_south_out(RU_t *ru) {
+ if (ru == RC.ru[0]) VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TST, ru->proc.timestamp_tx&0xffffffff );
+
+ LOG_D(PHY,"Sending IF4p5 for frame %d subframe %d\n",ru->proc.frame_tx,ru->proc.tti_tx);
+
+ if (nr_slot_select(&ru->gNB_list[0]->gNB_config,ru->proc.tti_tx)!=SF_UL)
+ send_IF4p5(ru,ru->proc.frame_tx, ru->proc.tti_tx, IF4p5_PDLFFT);
+}
+
+/*************************************************************/
+/* Input Fronthaul from south RCC/RAU */
+
+// Synchronous if5 from south
+void fh_if5_south_in(RU_t *ru,int *frame, int *tti) {
+ NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms;
+ RU_proc_t *proc = &ru->proc;
+ recv_IF5(ru, &proc->timestamp_rx, *tti, IF5_RRH_GW_UL);
+ proc->frame_rx = (proc->timestamp_rx / (fp->samples_per_slot*20))&1023;
+ proc->tti_rx = (proc->timestamp_rx / fp->samples_per_slot)%20;
+
+ if (proc->first_rx == 0) {
+ if (proc->tti_rx != *tti) {
+ LOG_E(PHY,"Received Timestamp doesn't correspond to the time we think it is (proc->tti_rx %d, subframe %d)\n",proc->tti_rx,*tti);
+ exit_fun("Exiting");
+ }
+
+ if (proc->frame_rx != *frame) {
+ LOG_E(PHY,"Received Timestamp doesn't correspond to the time we think it is (proc->frame_rx %d frame %d)\n",proc->frame_rx,*frame);
+ exit_fun("Exiting");
+ }
+ } else {
+ proc->first_rx = 0;
+ *frame = proc->frame_rx;
+ *tti = proc->tti_rx;
+ }
+
+ VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TS, proc->timestamp_rx&0xffffffff );
+}
+
+// Synchronous if4p5 from south
+void fh_if4p5_south_in(RU_t *ru,int *frame,int *slot) {
+ NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms;
+ RU_proc_t *proc = &ru->proc;
+ int f,sl;
+ uint16_t packet_type;
+ uint32_t symbol_number=0;
+ uint32_t symbol_mask_full=0;
+
+ /*
+ if ((fp->frame_type == TDD) && (subframe_select(fp,*slot)==SF_S))
+ symbol_mask_full = (1<ul_symbols_in_S_subframe)-1;
+ else
+ symbol_mask_full = (1<symbols_per_slot)-1;
+
+ AssertFatal(proc->symbol_mask[*slot]==0,"rx_fh_if4p5: proc->symbol_mask[%d] = %x\n",*slot,proc->symbol_mask[*slot]);*/
+ do { // Blocking, we need a timeout on this !!!!!!!!!!!!!!!!!!!!!!!
+ recv_IF4p5(ru, &f, &sl, &packet_type, &symbol_number);
+
+ if (packet_type == IF4p5_PULFFT) proc->symbol_mask[sl] = proc->symbol_mask[sl] | (1<first_rx==0) && (f!=*frame)) LOG_E(PHY,"rx_fh_if4p5: PULTICK received frame %d != expected %d\n",f,*frame);
+
+ if ((proc->first_rx==0) && (sl!=*slot)) LOG_E(PHY,"rx_fh_if4p5: PULTICK received subframe %d != expected %d (first_rx %d)\n",sl,*slot,proc->first_rx);
+
+ break;
+ } else if (packet_type == IF4p5_PRACH) {
+ // nothing in RU for RAU
+ }
+
+ LOG_D(PHY,"rx_fh_if4p5: subframe %d symbol mask %x\n",*slot,proc->symbol_mask[sl]);
+ } while(proc->symbol_mask[sl] != symbol_mask_full);
+
+ //caculate timestamp_rx, timestamp_tx based on frame and subframe
+ proc->tti_rx = sl;
+ proc->frame_rx = f;
+ proc->timestamp_rx = ((proc->frame_rx * fp->slots_per_frame) + proc->tti_rx ) * fp->samples_per_slot ;
+ // proc->timestamp_tx = proc->timestamp_rx + (4*fp->samples_per_subframe);
+ proc->tti_tx = (sl+sl_ahead)%fp->slots_per_frame;
+ proc->frame_tx = (sl>(fp->slots_per_frame-sl_ahead)) ? (f+1)&1023 : f;
+
+ if (proc->first_rx == 0) {
+ if (proc->tti_rx != *slot) {
+ LOG_E(PHY,"Received Timestamp (IF4p5) doesn't correspond to the time we think it is (proc->tti_rx %d, subframe %d)\n",proc->tti_rx,*slot);
+ exit_fun("Exiting");
+ }
+
+ if (proc->frame_rx != *frame) {
+ LOG_E(PHY,"Received Timestamp (IF4p5) doesn't correspond to the time we think it is (proc->frame_rx %d frame %d)\n",proc->frame_rx,*frame);
+ exit_fun("Exiting");
+ }
+ } else {
+ proc->first_rx = 0;
+ *frame = proc->frame_rx;
+ *slot = proc->tti_rx;
+ }
+
+ if (ru == RC.ru[0]) {
+ VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX0_RU, f );
+ VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TTI_NUMBER_RX0_RU, sl);
+ VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX0_RU, proc->frame_tx );
+ VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TTI_NUMBER_TX0_RU, proc->tti_tx );
+ }
+
+ proc->symbol_mask[proc->tti_rx] = 0;
+ VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TS, proc->timestamp_rx&0xffffffff );
+ LOG_D(PHY,"RU %d: fh_if4p5_south_in sleeping ...\n",ru->idx);
+}
+
+// asynchronous inbound if4p5 fronthaul from south
+void fh_if4p5_south_asynch_in(RU_t *ru,int *frame,int *slot) {
+ NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms;
+ RU_proc_t *proc = &ru->proc;
+ uint16_t packet_type;
+ uint32_t symbol_number,symbol_mask,prach_rx;
+ // uint32_t got_prach_info=0;
+ symbol_number = 0;
+ symbol_mask = (1<<(fp->symbols_per_slot))-1;
+ prach_rx = 0;
+
+ do { // Blocking, we need a timeout on this !!!!!!!!!!!!!!!!!!!!!!!
+ recv_IF4p5(ru, &proc->frame_rx, &proc->tti_rx, &packet_type, &symbol_number);
+
+ // grab first prach information for this new subframe
+ /*if (got_prach_info==0) {
+ prach_rx = is_prach_subframe(fp, proc->frame_rx, proc->tti_rx);
+ got_prach_info = 1;
+ }*/
+ if (proc->first_rx != 0) {
+ *frame = proc->frame_rx;
+ *slot = proc->tti_rx;
+ proc->first_rx = 0;
+ } else {
+ if (proc->frame_rx != *frame) {
+ LOG_E(PHY,"frame_rx %d is not what we expect %d\n",proc->frame_rx,*frame);
+ exit_fun("Exiting");
+ }
+
+ if (proc->tti_rx != *slot) {
+ LOG_E(PHY,"tti_rx %d is not what we expect %d\n",proc->tti_rx,*slot);
+ exit_fun("Exiting");
+ }
+ }
+
+ if (packet_type == IF4p5_PULFFT) symbol_mask &= (~(1< 0) || (prach_rx >0)); // haven't received all PUSCH symbols and PRACH information
+}
+
+
+
+
+
+/*************************************************************/
+/* Input Fronthaul from North RRU */
+
+// RRU IF4p5 TX fronthaul receiver. Assumes an if_device on input and if or rf device on output
+// receives one subframe's worth of IF4p5 OFDM symbols and OFDM modulates
+void fh_if4p5_north_in(RU_t *ru,int *frame,int *slot) {
+ uint32_t symbol_number=0;
+ uint32_t symbol_mask, symbol_mask_full;
+ uint16_t packet_type;
+ /// **** incoming IF4p5 from remote RCC/RAU **** ///
+ symbol_number = 0;
+ symbol_mask = 0;
+ symbol_mask_full = (1<<(ru->nr_frame_parms->symbols_per_slot))-1;
+
+ do {
+ recv_IF4p5(ru, frame, slot, &packet_type, &symbol_number);
+ symbol_mask = symbol_mask | (1<nr_frame_parms;
+ RU_proc_t *proc = &ru->proc;
+ int tti_tx,frame_tx;
+ openair0_timestamp timestamp_tx;
+ recv_IF5(ru, ×tamp_tx, *slot, IF5_RRH_GW_DL);
+ // printf("Received subframe %d (TS %llu) from RCC\n",tti_tx,timestamp_tx);
+ tti_tx = (timestamp_tx/fp->samples_per_slot)%fp->slots_per_frame;
+ frame_tx = (timestamp_tx/(fp->samples_per_slot*fp->slots_per_frame))&1023;
+
+ if (proc->first_tx != 0) {
+ *slot = tti_tx;
+ *frame = frame_tx;
+ proc->first_tx = 0;
+ } else {
+ AssertFatal(tti_tx == *slot,
+ "tti_tx %d is not what we expect %d\n",tti_tx,*slot);
+ AssertFatal(frame_tx == *frame,
+ "frame_tx %d is not what we expect %d\n",frame_tx,*frame);
+ }
+}
+
+void fh_if4p5_north_asynch_in(RU_t *ru,int *frame,int *slot) {
+ NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms;
+ nfapi_nr_config_request_t *cfg = &ru->gNB_list[0]->gNB_config;
+ RU_proc_t *proc = &ru->proc;
+ uint16_t packet_type;
+ uint32_t symbol_number,symbol_mask,symbol_mask_full=0;
+ int slot_tx,frame_tx;
+ LOG_D(PHY, "%s(ru:%p frame, subframe)\n", __FUNCTION__, ru);
+ symbol_number = 0;
+ symbol_mask = 0;
+
+ // symbol_mask_full = ((subframe_select(fp,*slot) == SF_S) ? (1<dl_symbols_in_S_subframe) : (1<symbols_per_slot))-1;
+ do {
+ recv_IF4p5(ru, &frame_tx, &slot_tx, &packet_type, &symbol_number);
+
+ if ((nr_slot_select(cfg,slot_tx) == SF_DL) && (symbol_number == 0)) start_meas(&ru->rx_fhaul);
+
+ LOG_D(PHY,"subframe %d (%d): frame %d, subframe %d, symbol %d\n",
+ *slot,nr_slot_select(cfg,*slot),frame_tx,slot_tx,symbol_number);
+
+ if (proc->first_tx != 0) {
+ *frame = frame_tx;
+ *slot = slot_tx;
+ proc->first_tx = 0;
+ //symbol_mask_full = ((subframe_select(fp,*slot) == SF_S) ? (1<dl_symbols_in_S_subframe) : (1<symbols_per_slot))-1;
+ } else {
+ AssertFatal(frame_tx == *frame,
+ "frame_tx %d is not what we expect %d\n",frame_tx,*frame);
+ AssertFatal(slot_tx == *slot,
+ "slot_tx %d is not what we expect %d\n",slot_tx,*slot);
+ }
+
+ if (packet_type == IF4p5_PDLFFT) {
+ symbol_mask = symbol_mask | (1<rx_fhaul);
+
+ proc->tti_tx = slot_tx;
+ proc->frame_tx = frame_tx;
+
+ if ((frame_tx == 0)&&(slot_tx == 0)) proc->frame_tx_unwrap += 1024;
+
+ proc->timestamp_tx = ((((uint64_t)frame_tx + (uint64_t)proc->frame_tx_unwrap) * fp->slots_per_frame) + (uint64_t)slot_tx) * (uint64_t)fp->samples_per_slot;
+ LOG_D(PHY,"RU %d/%d TST %llu, frame %d, subframe %d\n",ru->idx,0,(long long unsigned int)proc->timestamp_tx,frame_tx,slot_tx);
+
+ // dump VCD output for first RU in list
+ if (ru == RC.ru[0]) {
+ VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX0_RU, frame_tx );
+ VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TTI_NUMBER_TX0_RU, slot_tx );
+ }
+
+ if (ru->feptx_ofdm) ru->feptx_ofdm(ru);
+
+ if (ru->fh_south_out) ru->fh_south_out(ru);
+}
+
+void fh_if5_north_out(RU_t *ru) {
+ RU_proc_t *proc=&ru->proc;
+ uint8_t seqno=0;
+ /// **** send_IF5 of rxdata to BBU **** ///
+ VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_SEND_IF5, 1 );
+ send_IF5(ru, proc->timestamp_rx, proc->tti_rx, &seqno, IF5_RRH_GW_UL);
+ VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_SEND_IF5, 0 );
+}
+
+// RRU IF4p5 northbound interface (RX)
+void fh_if4p5_north_out(RU_t *ru) {
+ RU_proc_t *proc=&ru->proc;
+
+ //NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms;
+ //const int subframe = proc->tti_rx;
+ if (ru->idx==0) VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TTI_NUMBER_RX0_RU, proc->tti_rx );
+
+ /*
+ if ((fp->frame_type == TDD) && (subframe_select(fp,subframe)!=SF_UL)) {
+ /// **** in TDD during DL send_IF4 of ULTICK to RCC **** ///
+ send_IF4p5(ru, proc->frame_rx, proc->tti_rx, IF4p5_PULTICK);
+ return;
+ }*/
+ start_meas(&ru->tx_fhaul);
+ send_IF4p5(ru, proc->frame_rx, proc->tti_rx, IF4p5_PULFFT);
+ stop_meas(&ru->tx_fhaul);
+}
+
+static void *emulatedRF_thread(void *param) {
+ RU_proc_t *proc = (RU_proc_t *) param;
+ int microsec = 500; // length of time to sleep, in miliseconds
+ struct timespec req = {0};
+ req.tv_sec = 0;
+ req.tv_nsec = (numerology>0)? ((microsec * 1000L)/numerology):(microsec * 1000L)*2;
+ wait_sync("emulatedRF_thread");
+
+ while(!oai_exit) {
+ nanosleep(&req, (struct timespec *)NULL);
+ pthread_mutex_lock(&proc->mutex_emulateRF);
+ ++proc->instance_cnt_emulateRF;
+ pthread_mutex_unlock(&proc->mutex_emulateRF);
+ pthread_cond_signal(&proc->cond_emulateRF);
+ }
+
+ return 0;
+}
+
+void rx_rf(RU_t *ru,int *frame,int *slot) {
+ RU_proc_t *proc = &ru->proc;
+ NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms;
+ void *rxp[ru->nb_rx];
+ unsigned int rxs;
+ int i;
+ openair0_timestamp ts,old_ts;
+ AssertFatal(*slotslots_per_frame && *slot>=0, "slot %d is illegal (%d)\n",*slot,fp->slots_per_frame);
+
+ for (i=0; inb_rx; i++)
+ rxp[i] = (void *)&ru->common.rxdata[i][*slot*fp->samples_per_slot];
+
+ VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ, 1 );
+ old_ts = proc->timestamp_rx;
+ LOG_D(PHY,"Reading %d samples for slot %d (%p)\n",fp->samples_per_slot,*slot,rxp[0]);
+
+ if(emulate_rf) {
+ wait_on_condition(&proc->mutex_emulateRF,&proc->cond_emulateRF,&proc->instance_cnt_emulateRF,"emulatedRF_thread");
+ release_thread(&proc->mutex_emulateRF,&proc->instance_cnt_emulateRF,"emulatedRF_thread");
+ rxs = fp->samples_per_slot;
+ ts = old_ts + rxs;
+ } else {
+ rxs = ru->rfdevice.trx_read_func(&ru->rfdevice,
+ &ts,
+ rxp,
+ fp->samples_per_slot,
+ ru->nb_rx);
+ }
+
+ VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ, 0 );
+ proc->timestamp_rx = ts-ru->ts_offset;
+
+ //AssertFatal(rxs == fp->samples_per_subframe,
+ //"rx_rf: Asked for %d samples, got %d from USRP\n",fp->samples_per_subframe,rxs);
+ if (rxs != fp->samples_per_slot) LOG_E(PHY, "rx_rf: Asked for %d samples, got %d from USRP\n",fp->samples_per_slot,rxs);
+
+ if (proc->first_rx == 1) {
+ ru->ts_offset = proc->timestamp_rx;
+ proc->timestamp_rx = 0;
+ } else {
+ if (proc->timestamp_rx - old_ts != fp->samples_per_slot) {
+ LOG_I(PHY,"rx_rf: rfdevice timing drift of %"PRId64" samples (ts_off %"PRId64")\n",proc->timestamp_rx - old_ts - fp->samples_per_slot,ru->ts_offset);
+ ru->ts_offset += (proc->timestamp_rx - old_ts - fp->samples_per_slot);
+ proc->timestamp_rx = ts-ru->ts_offset;
+ }
+ }
+
+ proc->frame_rx = (proc->timestamp_rx / (fp->samples_per_slot*fp->slots_per_frame))&1023;
+ proc->tti_rx = (proc->timestamp_rx / fp->samples_per_slot)%fp->slots_per_frame;
+ // synchronize first reception to frame 0 subframe 0
+ proc->timestamp_tx = proc->timestamp_rx+(sl_ahead*fp->samples_per_slot);
+ proc->tti_tx = (proc->tti_rx+sl_ahead)%fp->slots_per_frame;
+ proc->frame_tx = (proc->tti_rx>(fp->slots_per_frame-1-sl_ahead)) ? (proc->frame_rx+1)&1023 : proc->frame_rx;
+ LOG_I(PHY,"RU %d/%d TS %llu (off %d), frame %d, slot %d.%d / %d\n",
+ ru->idx,
+ 0,
+ (unsigned long long int)proc->timestamp_rx,
+ (int)ru->ts_offset,proc->frame_rx,proc->tti_rx,proc->tti_tx,fp->slots_per_frame);
+
+ // dump VCD output for first RU in list
+ if (ru == RC.ru[0]) {
+ VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX0_RU, proc->frame_rx );
+ VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TTI_NUMBER_RX0_RU, proc->tti_rx );
+ }
+
+ if (proc->first_rx == 0) {
+ if (proc->tti_rx != *slot) {
+ LOG_E(PHY,"Received Timestamp (%llu) doesn't correspond to the time we think it is (proc->tti_rx %d, subframe %d)\n",(long long unsigned int)proc->timestamp_rx,proc->tti_rx,*slot);
+ exit_fun("Exiting");
+ }
+
+ if (proc->frame_rx != *frame) {
+ LOG_E(PHY,"Received Timestamp (%llu) doesn't correspond to the time we think it is (proc->frame_rx %d frame %d)\n",(long long unsigned int)proc->timestamp_rx,proc->frame_rx,*frame);
+ exit_fun("Exiting");
+ }
+ } else {
+ proc->first_rx = 0;
+ *frame = proc->frame_rx;
+ *slot = proc->tti_rx;
+ }
+
+ //printf("timestamp_rx %lu, frame %d(%d), subframe %d(%d)\n",ru->timestamp_rx,proc->frame_rx,frame,proc->tti_rx,subframe);
+ VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TS, proc->timestamp_rx&0xffffffff );
+
+ if (rxs != fp->samples_per_slot) {
+ //exit_fun( "problem receiving samples" );
+ LOG_E(PHY, "problem receiving samples\n");
+ }
+}
+
+
+void tx_rf(RU_t *ru) {
+ RU_proc_t *proc = &ru->proc;
+ NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms;
+ nfapi_nr_config_request_t *cfg = &ru->gNB_list[0]->gNB_config;
+ void *txp[ru->nb_tx];
+ unsigned int txs;
+ int i;
+ T(T_ENB_PHY_OUTPUT_SIGNAL, T_INT(0), T_INT(0), T_INT(proc->frame_tx), T_INT(proc->tti_tx),
+ T_INT(0), T_BUFFER(&ru->common.txdata[0][proc->tti_tx * fp->samples_per_slot], fp->samples_per_slot * 4));
+ nr_subframe_t SF_type = nr_slot_select(cfg,proc->tti_tx%fp->slots_per_frame);
+ int sf_extension = 0;
+
+ if ((SF_type == SF_DL) ||
+ (SF_type == SF_S)) {
+ int siglen=fp->samples_per_slot,flags=1;
+ /*
+ if (SF_type == SF_S) {
+ siglen = fp->dl_symbols_in_S_subframe*(fp->ofdm_symbol_size+fp->nb_prefix_samples0);
+ flags=3; // end of burst
+ }
+ if ((fp->frame_type == TDD) &&
+ (SF_type == SF_DL)&&
+ (prevSF_type == SF_UL) &&
+ (nextSF_type == SF_DL)) {
+ flags = 2; // start of burst
+ sf_extension = ru->N_TA_offset<<1;
+ }
+
+ if ((cfg->subframe_config.duplex_mode == TDD) &&
+ (SF_type == SF_DL)&&
+ (prevSF_type == SF_UL) &&
+ (nextSF_type == SF_UL)) {
+ flags = 4; // start of burst and end of burst (only one DL SF between two UL)
+ sf_extension = ru->N_TA_offset<<1;
+ } */
+ VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX0_RU, proc->frame_tx );
+ VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TTI_NUMBER_TX0_RU, proc->tti_tx );
+
+ for (i=0; inb_tx; i++)
+ txp[i] = (void *)&ru->common.txdata[i][(proc->tti_tx*fp->samples_per_slot)-sf_extension];
+
+ VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TST, (proc->timestamp_tx-ru->openair0_cfg.tx_sample_advance)&0xffffffff );
+ VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE, 1 );
+ // prepare tx buffer pointers
+ txs = ru->rfdevice.trx_write_func(&ru->rfdevice,
+ proc->timestamp_tx+ru->ts_offset-ru->openair0_cfg.tx_sample_advance-sf_extension,
+ txp,
+ siglen+sf_extension,
+ ru->nb_tx,
+ flags);
+ LOG_D(PHY,"[TXPATH] RU %d tx_rf, writing to TS %llu, frame %d, unwrapped_frame %d, subframe %d\n",ru->idx,
+ (long long unsigned int)proc->timestamp_tx,proc->frame_tx,proc->frame_tx_unwrap,proc->tti_tx);
+ VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE, 0 );
+ AssertFatal(txs == siglen+sf_extension,"TX : Timeout (sent %d/%d)\n",txs, siglen);
+ }
+}
+
+
+/*!
+ * \brief The Asynchronous RX/TX FH thread of RAU/RCC/gNB/RRU.
+ * This handles the RX FH for an asynchronous RRU/UE
+ * \param param is a \ref gNB_L1_proc_t structure which contains the info what to process.
+ * \returns a pointer to an int. The storage is not on the heap and must not be freed.
+ */
+static void *ru_thread_asynch_rxtx( void *param ) {
+ static int ru_thread_asynch_rxtx_status;
+ RU_t *ru = (RU_t *)param;
+ RU_proc_t *proc = &ru->proc;
+ int subframe=0, frame=0;
+ // wait for top-level synchronization and do one acquisition to get timestamp for setting frame/subframe
+ wait_sync("ru_thread_asynch_rxtx");
+ // wait for top-level synchronization and do one acquisition to get timestamp for setting frame/subframe
+ printf( "waiting for devices (ru_thread_asynch_rx)\n");
+ wait_on_condition(&proc->mutex_asynch_rxtx,&proc->cond_asynch_rxtx,&proc->instance_cnt_asynch_rxtx,"thread_asynch");
+ printf( "devices ok (ru_thread_asynch_rx)\n");
+
+ while (!oai_exit) {
+ if (oai_exit) break;
+
+ if (subframe==9) {
+ subframe=0;
+ frame++;
+ frame&=1023;
+ } else {
+ subframe++;
+ }
+
+ LOG_D(PHY,"ru_thread_asynch_rxtx: Waiting on incoming fronthaul\n");
+
+ // asynchronous receive from south (Mobipass)
+ if (ru->fh_south_asynch_in) ru->fh_south_asynch_in(ru,&frame,&subframe);
+ // asynchronous receive from north (RRU IF4/IF5)
+ else if (ru->fh_north_asynch_in) {
+ if (nr_slot_select(&ru->gNB_list[0]->gNB_config,subframe)!=SF_UL)
+ ru->fh_north_asynch_in(ru,&frame,&subframe);
+ } else AssertFatal(1==0,"Unknown function in ru_thread_asynch_rxtx\n");
+ }
+
+ ru_thread_asynch_rxtx_status=0;
+ return(&ru_thread_asynch_rxtx_status);
+}
+
+
+
+
+/*!
+ * \brief The prach receive thread of RU.
+ * \param param is a \ref RU_proc_t structure which contains the info what to process.
+ * \returns a pointer to an int. The storage is not on the heap and must not be freed.
+ */
+static void *ru_thread_prach( void *param ) {
+ static int ru_thread_prach_status;
+ RU_t *ru = (RU_t *)param;
+ RU_proc_t *proc = (RU_proc_t *)&ru->proc;
+ // set default return value
+ ru_thread_prach_status = 0;
+
+ while (RC.ru_mask>0) {
+ usleep(1e6);
+ LOG_I(PHY,"%s() RACH waiting for RU to be configured\n", __FUNCTION__);
+ }
+
+ LOG_I(PHY,"%s() RU configured - RACH processing thread running\n", __FUNCTION__);
+
+ while (!oai_exit) {
+ if (oai_exit) break;
+
+ if (wait_on_condition(&proc->mutex_prach,&proc->cond_prach,&proc->instance_cnt_prach,"ru_prach_thread") < 0) break;
+
+ VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_RU_PRACH_RX, 1 );
+
+ /*if (ru->gNB_list[0]){
+ prach_procedures(
+ ru->gNB_list[0]
+ #if (RRC_VERSION >= MAKE_VERSION(14, 0, 0))
+ ,0
+ #endif
+ );
+ }
+ else {
+ rx_prach(NULL,
+ ru,
+ NULL,
+ NULL,
+ NULL,
+ proc->frame_prach,
+ 0
+ #if (RRC_VERSION >= MAKE_VERSION(14, 0, 0))
+ ,0
+ #endif
+ );
+ }
+ VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_RU_PRACH_RX, 0 ); */
+ if (release_thread(&proc->mutex_prach,&proc->instance_cnt_prach,"ru_prach_thread") < 0) break;
+ }
+
+ LOG_I(PHY, "Exiting RU thread PRACH\n");
+ ru_thread_prach_status = 0;
+ return &ru_thread_prach_status;
+}
+
+
+int wakeup_synch(RU_t *ru) {
+ struct timespec wait;
+ wait.tv_sec=0;
+ wait.tv_nsec=5000000L;
+
+ // wake up synch thread
+ // lock the synch mutex and make sure the thread is ready
+ if (pthread_mutex_timedlock(&ru->proc.mutex_synch,&wait) != 0) {
+ LOG_E( PHY, "[RU] ERROR pthread_mutex_lock for RU synch thread (IC %d)\n", ru->proc.instance_cnt_synch );
+ exit_fun( "error locking mutex_synch" );
+ return(-1);
+ }
+
+ ++ru->proc.instance_cnt_synch;
+
+ // the thread can now be woken up
+ if (pthread_cond_signal(&ru->proc.cond_synch) != 0) {
+ LOG_E( PHY, "[RU] ERROR pthread_cond_signal for RU synch thread\n");
+ exit_fun( "ERROR pthread_cond_signal" );
+ return(-1);
+ }
+
+ pthread_mutex_unlock( &ru->proc.mutex_synch );
+ return(0);
+}
+
+void do_ru_synch(RU_t *ru) {
+ NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms;
+ RU_proc_t *proc = &ru->proc;
+ int i;
+ void *rxp[2],*rxp2[2];
+ int32_t dummy_rx[ru->nb_rx][fp->samples_per_subframe] __attribute__((aligned(32)));
+ int rxs;
+ int ic;
+
+ // initialize the synchronization buffer to the common_vars.rxdata
+ for (int i=0; inb_rx; i++)
+ rxp[i] = &ru->common.rxdata[i][0];
+
+ double temp_freq1 = ru->rfdevice.openair0_cfg->rx_freq[0];
+ double temp_freq2 = ru->rfdevice.openair0_cfg->tx_freq[0];
+
+ for (i=0; i<4; i++) {
+ ru->rfdevice.openair0_cfg->rx_freq[i] = ru->rfdevice.openair0_cfg->tx_freq[i];
+ ru->rfdevice.openair0_cfg->tx_freq[i] = temp_freq1;
+ }
+
+ ru->rfdevice.trx_set_freq_func(&ru->rfdevice,ru->rfdevice.openair0_cfg,0);
+
+ while ((ru->in_synch ==0)&&(!oai_exit)) {
+ // read in frame
+ rxs = ru->rfdevice.trx_read_func(&ru->rfdevice,
+ &(proc->timestamp_rx),
+ rxp,
+ fp->samples_per_subframe*10,
+ ru->nb_rx);
+
+ if (rxs != fp->samples_per_subframe*10) LOG_E(PHY,"requested %d samples, got %d\n",fp->samples_per_subframe*10,rxs);
+
+ // wakeup synchronization processing thread
+ wakeup_synch(ru);
+ ic=0;
+
+ while ((ic>=0)&&(!oai_exit)) {
+ // continuously read in frames, 1ms at a time,
+ // until we are done with the synchronization procedure
+ for (i=0; inb_rx; i++)
+ rxp2[i] = (void *)&dummy_rx[i][0];
+
+ for (i=0; i<10; i++)
+ rxs = ru->rfdevice.trx_read_func(&ru->rfdevice,
+ &(proc->timestamp_rx),
+ rxp2,
+ fp->samples_per_subframe,
+ ru->nb_rx);
+
+ pthread_mutex_lock(&ru->proc.mutex_synch);
+ ic = ru->proc.instance_cnt_synch;
+ pthread_mutex_unlock(&ru->proc.mutex_synch);
+ } // ic>=0
+ } // in_synch==0
+
+ // read in rx_offset samples
+ LOG_I(PHY,"Resynchronizing by %d samples\n",ru->rx_offset);
+ rxs = ru->rfdevice.trx_read_func(&ru->rfdevice,
+ &(proc->timestamp_rx),
+ rxp,
+ ru->rx_offset,
+ ru->nb_rx);
+
+ for (i=0; i<4; i++) {
+ ru->rfdevice.openair0_cfg->rx_freq[i] = temp_freq1;
+ ru->rfdevice.openair0_cfg->tx_freq[i] = temp_freq2;
+ }
+
+ ru->rfdevice.trx_set_freq_func(&ru->rfdevice,ru->rfdevice.openair0_cfg,0);
+}
+
+
+
+void wakeup_gNB_L1s(RU_t *ru) {
+ int i;
+ PHY_VARS_gNB **gNB_list = ru->gNB_list;
+ LOG_D(PHY,"wakeup_gNB_L1s (num %d) for RU %d ru->gNB_top:%p\n",ru->num_gNB,ru->idx, ru->gNB_top);
+
+ if (ru->num_gNB==1 && ru->gNB_top!=0 && get_thread_parallel_conf() == PARALLEL_SINGLE_THREAD) {
+ // call gNB function directly
+ char string[20];
+ sprintf(string,"Incoming RU %d",ru->idx);
+ LOG_D(PHY,"RU %d Call gNB_top\n",ru->idx);
+ ru->gNB_top(gNB_list[0],ru->proc.frame_rx,ru->proc.tti_rx,string,ru);
+ } else {
+ LOG_D(PHY,"ru->num_gNB:%d\n", ru->num_gNB);
+
+ for (i=0; inum_gNB; i++) {
+ LOG_D(PHY,"ru->wakeup_rxtx:%p\n", ru->nr_wakeup_rxtx);
+
+ if (ru->nr_wakeup_rxtx!=0 && ru->nr_wakeup_rxtx(gNB_list[i],ru) < 0) {
+ LOG_E(PHY,"could not wakeup gNB rxtx process for subframe %d\n", ru->proc.tti_rx);
+ }
+ }
+ }
+}
+
+static inline int wakeup_prach_ru(RU_t *ru) {
+ struct timespec wait;
+ wait.tv_sec=0;
+ wait.tv_nsec=5000000L;
+
+ if (pthread_mutex_timedlock(&ru->proc.mutex_prach,&wait) !=0) {
+ LOG_E( PHY, "[RU] ERROR pthread_mutex_lock for RU prach thread (IC %d)\n", ru->proc.instance_cnt_prach);
+ exit_fun( "error locking mutex_rxtx" );
+ return(-1);
+ }
+
+ if (ru->proc.instance_cnt_prach==-1) {
+ ++ru->proc.instance_cnt_prach;
+ ru->proc.frame_prach = ru->proc.frame_rx;
+ ru->proc.subframe_prach = ru->proc.tti_rx;
+
+ // DJP - think prach_procedures() is looking at gNB frame_prach
+ if (ru->gNB_list[0]) {
+ ru->gNB_list[0]->proc.frame_prach = ru->proc.frame_rx;
+ ru->gNB_list[0]->proc.slot_prach = ru->proc.tti_rx;
+ }
+
+ LOG_I(PHY,"RU %d: waking up PRACH thread\n",ru->idx);
+ // the thread can now be woken up
+ AssertFatal(pthread_cond_signal(&ru->proc.cond_prach) == 0, "ERROR pthread_cond_signal for RU prach thread\n");
+ } else LOG_W(PHY,"RU prach thread busy, skipping\n");
+
+ pthread_mutex_unlock( &ru->proc.mutex_prach );
+ return(0);
+}
+
+// this is for RU with local RF unit
+void fill_rf_config(RU_t *ru, char *rf_config_file) {
+ int i;
+ NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms;
+ nfapi_nr_config_request_t *gNB_config = &ru->gNB_list[0]->gNB_config; //tmp index
+ openair0_config_t *cfg = &ru->openair0_cfg;
+ int N_RB = gNB_config->rf_config.dl_carrier_bandwidth.value;
+ int mu = gNB_config->subframe_config.numerology_index_mu.value;
+
+ if (mu == NR_MU_0) { //or if LTE
+ if(N_RB == 100) {
+ if (fp->threequarter_fs) {
+ cfg->sample_rate=23.04e6;
+ cfg->samples_per_frame = 230400;
+ cfg->tx_bw = 10e6;
+ cfg->rx_bw = 10e6;
+ } else {
+ cfg->sample_rate=30.72e6;
+ cfg->samples_per_frame = 307200;
+ cfg->tx_bw = 10e6;
+ cfg->rx_bw = 10e6;
+ }
+ } else if(N_RB == 50) {
+ cfg->sample_rate=15.36e6;
+ cfg->samples_per_frame = 153600;
+ cfg->tx_bw = 5e6;
+ cfg->rx_bw = 5e6;
+ } else if (N_RB == 25) {
+ cfg->sample_rate=7.68e6;
+ cfg->samples_per_frame = 76800;
+ cfg->tx_bw = 2.5e6;
+ cfg->rx_bw = 2.5e6;
+ } else if (N_RB == 6) {
+ cfg->sample_rate=1.92e6;
+ cfg->samples_per_frame = 19200;
+ cfg->tx_bw = 1.5e6;
+ cfg->rx_bw = 1.5e6;
+ } else AssertFatal(1==0,"Unknown N_RB %d\n",N_RB);
+ } else if (mu == NR_MU_1) {
+ if(N_RB == 217) {
+ if (fp->threequarter_fs) {
+ cfg->sample_rate=92.16e6;
+ cfg->samples_per_frame = 921600;
+ cfg->tx_bw = 40e6;
+ cfg->rx_bw = 40e6;
+ } else {
+ cfg->sample_rate=122.88e6;
+ cfg->samples_per_frame = 1228800;
+ cfg->tx_bw = 40e6;
+ cfg->rx_bw = 40e6;
+ }
+ } else if(N_RB == 106) {
+ cfg->sample_rate=61.44e6;
+ cfg->samples_per_frame = 614400;
+ cfg->tx_bw = 20e6;
+ cfg->rx_bw = 20e6;
+ } else {
+ AssertFatal(0==1,"N_RB %d not yet supported for numerology %d\n",N_RB,mu);
+ }
+ } else {
+ AssertFatal(0 == 1,"Numerology %d not supported for the moment\n",mu);
+ }
+
+ if (gNB_config->subframe_config.duplex_mode.value==TDD)
+ cfg->duplex_mode = duplex_mode_TDD;
+ else //FDD
+ cfg->duplex_mode = duplex_mode_FDD;
+
+ cfg->Mod_id = 0;
+ cfg->num_rb_dl=N_RB;
+ cfg->tx_num_channels=ru->nb_tx;
+ cfg->rx_num_channels=ru->nb_rx;
+
+ for (i=0; inb_tx; i++) {
+ cfg->tx_freq[i] = (double)fp->dl_CarrierFreq;
+ cfg->rx_freq[i] = (double)fp->ul_CarrierFreq;
+ cfg->tx_gain[i] = ru->att_tx;
+ cfg->rx_gain[i] = ru->max_rxgain-ru->att_rx;
+ cfg->configFilename = rf_config_file;
+ printf("channel %d, Setting tx_gain offset %f, rx_gain offset %f, tx_freq %f, rx_freq %f\n",
+ i, cfg->tx_gain[i],
+ cfg->rx_gain[i],
+ cfg->tx_freq[i],
+ cfg->rx_freq[i]);
+ }
+}
+
+/* this function maps the RU tx and rx buffers to the available rf chains.
+ Each rf chain is is addressed by the card number and the chain on the card. The
+ rf_map specifies for each antenna port, on which rf chain the mapping should start. Multiple
+ antennas are mapped to successive RF chains on the same card. */
+int setup_RU_buffers(RU_t *ru) {
+ int i,j;
+ int card,ant;
+ //uint16_t N_TA_offset = 0;
+ NR_DL_FRAME_PARMS *frame_parms;
+ //nfapi_nr_config_request_t *gNB_config = ru->gNB_list[0]->gNB_config; //tmp index
+
+ if (ru) {
+ frame_parms = ru->nr_frame_parms;
+ printf("setup_RU_buffers: frame_parms = %p\n",frame_parms);
+ } else {
+ printf("RU[%d] not initialized\n", ru->idx);
+ return(-1);
+ }
+
+ /* if (frame_parms->frame_type == TDD) {
+ if (frame_parms->N_RB_DL == 100) ru->N_TA_offset = 624;
+ else if (frame_parms->N_RB_DL == 50) ru->N_TA_offset = 624/2;
+ else if (frame_parms->N_RB_DL == 25) ru->N_TA_offset = 624/4;
+ } */
+ if (ru->openair0_cfg.mmapped_dma == 1) {
+ // replace RX signal buffers with mmaped HW versions
+ for (i=0; inb_rx; i++) {
+ card = i/4;
+ ant = i%4;
+ printf("Mapping RU id %d, rx_ant %d, on card %d, chain %d\n",ru->idx,i,ru->rf_map.card+card, ru->rf_map.chain+ant);
+ free(ru->common.rxdata[i]);
+ ru->common.rxdata[i] = ru->openair0_cfg.rxbase[ru->rf_map.chain+ant];
+ printf("rxdata[%d] @ %p\n",i,ru->common.rxdata[i]);
+
+ for (j=0; j<16; j++) {
+ printf("rxbuffer %d: %x\n",j,ru->common.rxdata[i][j]);
+ ru->common.rxdata[i][j] = 16-j;
+ }
+ }
+
+ for (i=0; inb_tx; i++) {
+ card = i/4;
+ ant = i%4;
+ printf("Mapping RU id %d, tx_ant %d, on card %d, chain %d\n",ru->idx,i,ru->rf_map.card+card, ru->rf_map.chain+ant);
+ free(ru->common.txdata[i]);
+ ru->common.txdata[i] = ru->openair0_cfg.txbase[ru->rf_map.chain+ant];
+ printf("txdata[%d] @ %p\n",i,ru->common.txdata[i]);
+
+ for (j=0; j<16; j++) {
+ printf("txbuffer %d: %x\n",j,ru->common.txdata[i][j]);
+ ru->common.txdata[i][j] = 16-j;
+ }
+ }
+ } else { // not memory-mapped DMA
+ //nothing to do, everything already allocated in lte_init
+ }
+
+ return(0);
+}
+
+static void *ru_stats_thread(void *param) {
+ RU_t *ru = (RU_t *)param;
+ wait_sync("ru_stats_thread");
+
+ while (!oai_exit) {
+ sleep(1);
+
+ if (opp_enabled == 1) {
+ if (ru->feprx) print_meas(&ru->ofdm_demod_stats,"feprx",NULL,NULL);
+
+ if (ru->feptx_ofdm) print_meas(&ru->ofdm_mod_stats,"feptx_ofdm",NULL,NULL);
+
+ if (ru->fh_north_asynch_in) print_meas(&ru->rx_fhaul,"rx_fhaul",NULL,NULL);
+
+ if (ru->fh_north_out) {
+ print_meas(&ru->tx_fhaul,"tx_fhaul",NULL,NULL);
+ print_meas(&ru->compression,"compression",NULL,NULL);
+ print_meas(&ru->transport,"transport",NULL,NULL);
+ }
+ }
+ }
+
+ return(NULL);
+}
+
+static void *ru_thread_tx( void *param ) {
+ RU_t *ru = (RU_t *)param;
+ RU_proc_t *proc = &ru->proc;
+ PHY_VARS_gNB *gNB;
+ gNB_L1_proc_t *gNB_proc;
+ gNB_L1_rxtx_proc_t *L1_proc;
+ NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms;
+ char filename[40];
+ int print_frame = 8;
+ int i = 0;
+ cpu_set_t cpuset;
+ CPU_ZERO(&cpuset);
+ //CPU_SET(5, &cpuset);
+ //pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset);
+ //wait_sync("ru_thread_tx");
+ wait_on_condition(&proc->mutex_FH1,&proc->cond_FH1,&proc->instance_cnt_FH1,"ru_thread_tx");
+ printf( "ru_thread_tx ready\n");
+
+ while (!oai_exit) {
+ if (oai_exit) break;
+
+ LOG_I(PHY,"ru_thread_tx: Waiting for TX processing\n");
+ // wait until eNBs are finished subframe RX n and TX n+4
+ wait_on_condition(&proc->mutex_gNBs,&proc->cond_gNBs,&proc->instance_cnt_gNBs,"ru_thread_tx");
+
+ if (oai_exit) break;
+
+ //printf("~~~~~~~~~~~~~~~~start process for ru_thread_tx %d.%d\n", proc->frame_tx, proc->tti_tx);
+ VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX0_RU, proc->frame_tx );
+ VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TTI_NUMBER_TX0_RU, proc->tti_tx );
+
+ // do TX front-end processing if needed (precoding and/or IDFTs)
+ if (ru->feptx_prec) ru->feptx_prec(ru);
+
+ // do OFDM if needed
+ if ((ru->fh_north_asynch_in == NULL) && (ru->feptx_ofdm)) ru->feptx_ofdm(ru);
+
+ if(!emulate_rf) {
+ // do outgoing fronthaul (south) if needed
+ if ((ru->fh_north_asynch_in == NULL) && (ru->fh_south_out)) ru->fh_south_out(ru);
+
+ if (ru->fh_north_out) ru->fh_north_out(ru);
+ } else {
+ if(proc->frame_tx == print_frame) {
+ for (i=0; inb_tx; i++) {
+ sprintf(filename,"tx%ddataF_frame%d_sl%d.m", i, print_frame, proc->tti_tx);
+ LOG_M(filename,"txdataF_frame",&ru->common.txdataF_BF[i][0],fp->samples_per_subframe_wCP, 1, 1);
+
+ if(proc->tti_tx == 9) {
+ sprintf(filename,"tx%ddata_frame%d.m", i, print_frame);
+ LOG_M(filename,"txdata_frame",&ru->common.txdata[i][0],fp->samples_per_frame, 1, 1);
+ sprintf(filename,"tx%ddata_frame%d.dat", i, print_frame);
+ FILE *output_fd = fopen(filename,"w");
+
+ if (output_fd) {
+ fwrite(&ru->common.txdata[i][0],
+ sizeof(int32_t),
+ fp->samples_per_frame,
+ output_fd);
+ fclose(output_fd);
+ } else {
+ LOG_E(PHY,"Cannot write to file %s\n",filename);
+ }
+ }//if(proc->tti_tx == 9)
+ }//for (i=0; inb_tx; i++)
+ }//if(proc->frame_tx == print_frame)
+ }//else emulate_rf
+
+ release_thread(&proc->mutex_gNBs,&proc->instance_cnt_gNBs,"ru_thread_tx");
+
+ for(i = 0; inum_gNB; i++) {
+ gNB = ru->gNB_list[i];
+ gNB_proc = &gNB->proc;
+ L1_proc = (get_thread_parallel_conf() == PARALLEL_RU_L1_TRX_SPLIT)? &gNB_proc->L1_proc_tx : &gNB_proc->L1_proc;
+ pthread_mutex_lock(&gNB_proc->mutex_RU_tx);
+
+ for (int j=0; jnum_RU; j++) {
+ if (ru == gNB->RU_list[j]) {
+ if ((gNB_proc->RU_mask_tx&(1< 0)
+ LOG_E(PHY,"eNB %d frame %d, subframe %d : previous information from RU tx %d (num_RU %d,mask %x) has not been served yet!\n",
+ gNB->Mod_id,gNB_proc->frame_rx,gNB_proc->slot_rx,ru->idx,gNB->num_RU,gNB_proc->RU_mask_tx);
+
+ gNB_proc->RU_mask_tx |= (1<RU_mask_tx != (1<num_RU)-1) { // not all RUs have provided their information so return
+ pthread_mutex_unlock(&gNB_proc->mutex_RU_tx);
+ } else { // all RUs TX are finished so send the ready signal to eNB processing
+ gNB_proc->RU_mask_tx = 0;
+ pthread_mutex_unlock(&gNB_proc->mutex_RU_tx);
+ pthread_mutex_lock( &L1_proc->mutex_RUs);
+ L1_proc->instance_cnt_RUs = 0;
+
+ // the thread can now be woken up
+ if (pthread_cond_signal(&L1_proc->cond_RUs) != 0) {
+ LOG_E( PHY, "[eNB] ERROR pthread_cond_signal for eNB TXnp4 thread\n");
+ exit_fun( "ERROR pthread_cond_signal" );
+ }
+
+ pthread_mutex_unlock( &L1_proc->mutex_RUs );
+ }
+ }
+ }
+
+ release_thread(&proc->mutex_FH1,&proc->instance_cnt_FH1,"ru_thread_tx");
+ return 0;
+}
+
+static void *ru_thread( void *param ) {
+ static int ru_thread_status;
+ RU_t *ru = (RU_t *)param;
+ RU_proc_t *proc = &ru->proc;
+ NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms;
+ int ret;
+ int slot = fp->slots_per_frame-1;
+ int frame =1023;
+ char filename[40],threadname[40];
+ int print_frame = 8;
+ int i = 0;
+ // set default return value
+ ru_thread_status = 0;
+ // set default return value
+ sprintf(threadname,"ru_thread %d",ru->idx);
+ LOG_I(PHY,"Starting RU %d (%s,%s),\n",ru->idx,NB_functions[ru->function],NB_timing[ru->if_timing]);
+
+ if(emulate_rf) {
+ fill_rf_config(ru,ru->rf_config_file);
+ nr_init_frame_parms(&ru->gNB_list[0]->gNB_config, fp);
+ nr_dump_frame_parms(fp);
+ nr_phy_init_RU(ru);
+
+ if (setup_RU_buffers(ru)!=0) {
+ printf("Exiting, cannot initialize RU Buffers\n");
+ exit(-1);
+ }
+ } else {
+ // Start IF device if any
+ if (ru->start_if) {
+ LOG_I(PHY,"Starting IF interface for RU %d\n",ru->idx);
+ AssertFatal(ru->start_if(ru,NULL) == 0, "Could not start the IF device\n");
+
+ if (ru->if_south == LOCAL_RF) ret = connect_rau(ru);
+ else ret = attach_rru(ru);
+
+ AssertFatal(ret==0,"Cannot connect to remote radio\n");
+ }
+
+ if (ru->if_south == LOCAL_RF) { // configure RF parameters only
+ fill_rf_config(ru,ru->rf_config_file);
+ nr_init_frame_parms(&ru->gNB_list[0]->gNB_config, fp);
+ nr_dump_frame_parms(fp);
+ nr_phy_init_RU(ru);
+ ret = openair0_device_load(&ru->rfdevice,&ru->openair0_cfg);
+ AssertFatal(ret==0,"Cannot connect to local radio\n");
+ }
+
+ if (setup_RU_buffers(ru)!=0) {
+ printf("Exiting, cannot initialize RU Buffers\n");
+ exit(-1);
+ }
+ }
+
+ LOG_I(PHY, "Signaling main thread that RU %d is ready\n",ru->idx);
+ pthread_mutex_lock(&RC.ru_mutex);
+ RC.ru_mask &= ~(1<idx);
+ pthread_cond_signal(&RC.ru_cond);
+ pthread_mutex_unlock(&RC.ru_mutex);
+ wait_sync("ru_thread");
+
+ if(!emulate_rf) {
+ // Start RF device if any
+ if (ru->start_rf) {
+ if (ru->start_rf(ru) != 0)
+ LOG_E(HW,"Could not start the RF device\n");
+ else LOG_I(PHY,"RU %d rf device ready\n",ru->idx);
+ } else LOG_I(PHY,"RU %d no rf device\n",ru->idx);
+
+ // if an asnych_rxtx thread exists
+ // wakeup the thread because the devices are ready at this point
+
+ if ((ru->fh_south_asynch_in)||(ru->fh_north_asynch_in)) {
+ pthread_mutex_lock(&proc->mutex_asynch_rxtx);
+ proc->instance_cnt_asynch_rxtx=0;
+ pthread_mutex_unlock(&proc->mutex_asynch_rxtx);
+ pthread_cond_signal(&proc->cond_asynch_rxtx);
+ } else LOG_I(PHY,"RU %d no asynch_south interface\n",ru->idx);
+
+ // if this is a slave RRU, try to synchronize on the DL frequency
+ if ((ru->is_slave) && (ru->if_south == LOCAL_RF)) do_ru_synch(ru);
+ }
+
+ pthread_mutex_lock(&proc->mutex_FH1);
+ proc->instance_cnt_FH1 = 0;
+ pthread_mutex_unlock(&proc->mutex_FH1);
+ pthread_cond_signal(&proc->cond_FH1);
+
+ // This is a forever while loop, it loops over subframes which are scheduled by incoming samples from HW devices
+ while (!oai_exit) {
+ // these are local subframe/frame counters to check that we are in synch with the fronthaul timing.
+ // They are set on the first rx/tx in the underly FH routines.
+ if (slot==(fp->slots_per_frame-1)) {
+ slot=0;
+ frame++;
+ frame&=1023;
+ } else {
+ slot++;
+ }
+
+ // synchronization on input FH interface, acquire signals/data and block
+ if (ru->fh_south_in) ru->fh_south_in(ru,&frame,&slot);
+ else AssertFatal(1==0, "No fronthaul interface at south port");
+
+ LOG_D(PHY,"AFTER fh_south_in - SFN/SL:%d%d RU->proc[RX:%d.%d TX:%d.%d] RC.gNB[0][0]:[RX:%d%d TX(SFN):%d]\n",
+ frame,slot,
+ proc->frame_rx,proc->tti_rx,
+ proc->frame_tx,proc->tti_tx,
+ RC.gNB[0][0]->proc.frame_rx,RC.gNB[0][0]->proc.slot_rx,
+ RC.gNB[0][0]->proc.frame_tx);
+ /*
+ LOG_D(PHY,"RU thread (do_prach %d, is_prach_subframe %d), received frame %d, subframe %d\n",
+ ru->do_prach,
+ is_prach_subframe(fp, proc->frame_rx, proc->tti_rx),
+ proc->frame_rx,proc->tti_rx);
+
+ if ((ru->do_prach>0) && (is_prach_subframe(fp, proc->frame_rx, proc->tti_rx)==1)) {
+ wakeup_prach_ru(ru);
+ }*/
+
+ // adjust for timing offset between RU
+ //printf("~~~~~~~~~~~~~~~~~~~~~~~~~~%d.%d in ru_thread is in process\n", proc->frame_rx, proc->tti_rx);
+ if (ru->idx!=0) proc->frame_tx = (proc->frame_tx+proc->frame_offset)&1023;
+
+ // do RX front-end processing (frequency-shift, dft) if needed
+ if (ru->feprx) ru->feprx(ru);
+
+ // At this point, all information for subframe has been received on FH interface
+
+ // wakeup all gNB processes waiting for this RU
+ if (ru->num_gNB>0) wakeup_gNB_L1s(ru);
+
+ if(get_thread_parallel_conf() == PARALLEL_SINGLE_THREAD && ru->num_eNB==0) {
+ // do TX front-end processing if needed (precoding and/or IDFTs)
+ if (ru->feptx_prec) ru->feptx_prec(ru);
+
+ // do OFDM if needed
+ if ((ru->fh_north_asynch_in == NULL) && (ru->feptx_ofdm)) ru->feptx_ofdm(ru);
+
+ if(!emulate_rf) {
+ // do outgoing fronthaul (south) if needed
+ if ((ru->fh_north_asynch_in == NULL) && (ru->fh_south_out)) ru->fh_south_out(ru);
+
+ if (ru->fh_north_out) ru->fh_north_out(ru);
+ } else {
+ if(proc->frame_tx == print_frame) {
+ for (i=0; inb_tx; i++) {
+ sprintf(filename,"tx%ddataF_frame%d_sl%d.m", i, print_frame, proc->tti_tx);
+ LOG_M(filename,"txdataF_frame",&ru->common.txdataF_BF[i][0],fp->samples_per_slot_wCP, 1, 1);
+
+ if(proc->tti_tx == 9) {
+ sprintf(filename,"tx%ddata_frame%d.m", i, print_frame);
+ LOG_M(filename,"txdata_frame",&ru->common.txdata[i][0],fp->samples_per_frame, 1, 1);
+ sprintf(filename,"tx%ddata_frame%d.dat", i, print_frame);
+ FILE *output_fd = fopen(filename,"w");
+
+ if (output_fd) {
+ fwrite(&ru->common.txdata[i][0],
+ sizeof(int32_t),
+ fp->samples_per_frame,
+ output_fd);
+ fclose(output_fd);
+ } else {
+ LOG_E(PHY,"Cannot write to file %s\n",filename);
+ }
+ }//if(proc->tti_tx == 9)
+ }//for (i=0; inb_tx; i++)
+ }//if(proc->frame_tx == print_frame)
+ }//else emulate_rf
+
+ proc->emulate_rf_busy = 0;
+ }//if(get_thread_parallel_conf() == PARALLEL_SINGLE_THREAD)
+ }
+
+ printf( "Exiting ru_thread \n");
+
+ if (ru->stop_rf != NULL) {
+ if (ru->stop_rf(ru) != 0)
+ LOG_E(HW,"Could not stop the RF device\n");
+ else LOG_I(PHY,"RU %d rf device stopped\n",ru->idx);
+ }
+
+ ru_thread_status = 0;
+ return &ru_thread_status;
+}
+/*
+// This thread run the initial synchronization like a UE
+void *ru_thread_synch(void *arg) {
+
+ RU_t *ru = (RU_t*)arg;
+ NR_DL_FRAME_PARMS *fp=ru->nr_frame_parms;
+ int32_t sync_pos,sync_pos2;
+ uint32_t peak_val;
+ uint32_t sync_corr[307200] __attribute__((aligned(32)));
+ static int ru_thread_synch_status;
+
+
+
+ wait_sync("ru_thread_synch");
+
+ // initialize variables for PSS detection
+ lte_sync_time_init(ru->nr_frame_parms);
+
+ while (!oai_exit) {
+
+ // wait to be woken up
+ if (wait_on_condition(&ru->proc.mutex_synch,&ru->proc.cond_synch,&ru->proc.instance_cnt_synch,"ru_thread_synch")<0) break;
+
+ // if we're not in synch, then run initial synch
+ if (ru->in_synch == 0) {
+ // run intial synch like UE
+ LOG_I(PHY,"Running initial synchronization\n");
+
+ sync_pos = lte_sync_time_gNB(ru->common.rxdata,
+ fp,
+ fp->samples_per_subframe*5,
+ &peak_val,
+ sync_corr);
+ LOG_I(PHY,"RU synch: %d, val %d\n",sync_pos,peak_val);
+
+ if (sync_pos >= 0) {
+ if (sync_pos >= fp->nb_prefix_samples)
+ sync_pos2 = sync_pos - fp->nb_prefix_samples;
+ else
+ sync_pos2 = sync_pos + (fp->samples_per_subframe*10) - fp->nb_prefix_samples;
+
+ if (fp->frame_type == FDD) {
+
+ // PSS is hypothesized in last symbol of first slot in Frame
+ int sync_pos_slot = (fp->samples_per_subframe>>1) - fp->ofdm_symbol_size - fp->nb_prefix_samples;
+
+ if (sync_pos2 >= sync_pos_slot)
+ ru->rx_offset = sync_pos2 - sync_pos_slot;
+ else
+ ru->rx_offset = (fp->samples_per_subframe*10) + sync_pos2 - sync_pos_slot;
+ }
+ else {
+
+ }
+
+ LOG_I(PHY,"Estimated sync_pos %d, peak_val %d => timing offset %d\n",sync_pos,peak_val,ru->rx_offset);
+
+ if ((peak_val > 300000) && (sync_pos > 0)) {
+ // if (sync_pos++ > 3) {
+ write_output("ru_sync.m","sync",(void*)&sync_corr[0],fp->samples_per_subframe*5,1,2);
+ write_output("ru_rx.m","rxs",(void*)ru->ru_time.rxdata[0][0],fp->samples_per_subframe*10,1,1);
+ exit(-1);
+ }
+
+ ru->in_synch=1;
+ }
+ }
+
+ if (release_thread(&ru->proc.mutex_synch,&ru->proc.instance_cnt_synch,"ru_synch_thread") < 0) break;
+ } // oai_exit
+
+ ru_thread_synch_status = 0;
+ return &ru_thread_synch_status;
+
+}
+*/
+
+int start_if(struct RU_t_s *ru,struct PHY_VARS_gNB_s *gNB) {
+ return(ru->ifdevice.trx_start_func(&ru->ifdevice));
+}
+
+int start_rf(RU_t *ru) {
+ return(ru->rfdevice.trx_start_func(&ru->rfdevice));
+}
+
+int stop_rf(RU_t *ru) {
+ ru->rfdevice.trx_end_func(&ru->rfdevice);
+ return 0;
+}
+
+extern void fep_full(RU_t *ru);
+extern void ru_fep_full_2thread(RU_t *ru);
+extern void nr_feptx_ofdm(RU_t *ru);
+extern void nr_feptx_ofdm_2thread(RU_t *ru);
+extern void feptx_prec(RU_t *ru);
+extern void init_fep_thread(RU_t *ru);
+extern void init_nr_feptx_thread(RU_t *ru);
+
+void init_RU_proc(RU_t *ru) {
+ int i=0;
+ RU_proc_t *proc;
+ char name[100];
+#ifndef OCP_FRAMEWORK
+ LOG_I(PHY,"Initializing RU proc %d (%s,%s),\n",ru->idx,NB_functions[ru->function],NB_timing[ru->if_timing]);
+#endif
+ proc = &ru->proc;
+ memset((void *)proc,0,sizeof(RU_proc_t));
+ proc->ru = ru;
+ proc->instance_cnt_prach = -1;
+ proc->instance_cnt_synch = -1; ;
+ proc->instance_cnt_FH = -1;
+ proc->instance_cnt_FH1 = -1;
+ proc->instance_cnt_gNBs = -1;
+ proc->instance_cnt_asynch_rxtx = -1;
+ proc->instance_cnt_emulateRF = -1;
+ proc->first_rx = 1;
+ proc->first_tx = 1;
+ proc->frame_offset = 0;
+ proc->num_slaves = 0;
+ proc->frame_tx_unwrap = 0;
+
+ for (i=0; i<10; i++) proc->symbol_mask[i]=0;
+
+ pthread_mutex_init( &proc->mutex_prach, NULL);
+ pthread_mutex_init( &proc->mutex_asynch_rxtx, NULL);
+ pthread_mutex_init( &proc->mutex_synch,NULL);
+ pthread_mutex_init( &proc->mutex_FH,NULL);
+ pthread_mutex_init( &proc->mutex_FH1,NULL);
+ pthread_mutex_init( &proc->mutex_emulateRF,NULL);
+ pthread_mutex_init( &proc->mutex_gNBs, NULL);
+ pthread_cond_init( &proc->cond_prach, NULL);
+ pthread_cond_init( &proc->cond_FH, NULL);
+ pthread_cond_init( &proc->cond_FH1, NULL);
+ pthread_cond_init( &proc->cond_emulateRF, NULL);
+ pthread_cond_init( &proc->cond_asynch_rxtx, NULL);
+ pthread_cond_init( &proc->cond_synch,NULL);
+ pthread_cond_init( &proc->cond_gNBs, NULL);
+ threadCreate( &proc->pthread_FH, ru_thread, (void *)ru, "thread_FH", -1, OAI_PRIORITY_RT_MAX );
+
+ if (get_thread_parallel_conf() == PARALLEL_RU_L1_SPLIT || get_thread_parallel_conf() == PARALLEL_RU_L1_TRX_SPLIT)
+ threadCreate( &proc->pthread_FH1, ru_thread_tx, (void *)ru, "thread_FH1", -1, OAI_PRIORITY_RT );
+
+ if(emulate_rf)
+ threadCreate( &proc->pthread_emulateRF, emulatedRF_thread, (void *)proc, "emulateRF", -1, OAI_PRIORITY_RT );
+
+ if (ru->function == NGFI_RRU_IF4p5) {
+ threadCreate( &proc->pthread_prach, ru_thread_prach, (void *)ru, "RACH", -1, OAI_PRIORITY_RT );
+ ///tmp deactivation of synch thread
+ // if (ru->is_slave == 1) pthread_create( &proc->pthread_synch, attr_synch, ru_thread_synch, (void*)ru);
+
+ if ((ru->if_timing == synch_to_other) ||
+ (ru->function == NGFI_RRU_IF5) ||
+ (ru->function == NGFI_RRU_IF4p5)) threadCreate( &proc->pthread_asynch_rxtx, ru_thread_asynch_rxtx, (void *)ru, "asynch_rxtx", -1, OAI_PRIORITY_RT );
+
+ snprintf( name, sizeof(name), "ru_thread_FH %d", ru->idx );
+ pthread_setname_np( proc->pthread_FH, name );
+ } else if (ru->function == gNodeB_3GPP && ru->if_south == LOCAL_RF) { // DJP - need something else to distinguish between monolithic and PNF
+ LOG_I(PHY,"%s() DJP - added creation of pthread_prach\n", __FUNCTION__);
+ threadCreate( &proc->pthread_prach, ru_thread_prach, (void *)ru,"RACH", -1, OAI_PRIORITY_RT );
+ }
+
+ if (get_nprocs()>=2) {
+ if (ru->feprx) init_fep_thread(ru);
+
+ if (ru->feptx_ofdm) nr_init_feptx_thread(ru);
+ }
+
+ if (opp_enabled == 1) threadCreate(&ru->ru_stats_thread,ru_stats_thread,(void *)ru, "emulateRF", -1, OAI_PRIORITY_RT_LOW);
+}
+
+void kill_RU_proc(int inst) {
+ RU_t *ru = RC.ru[inst];
+ RU_proc_t *proc = &ru->proc;
+ pthread_mutex_lock(&proc->mutex_FH);
+ proc->instance_cnt_FH = 0;
+ pthread_mutex_unlock(&proc->mutex_FH);
+ pthread_cond_signal(&proc->cond_FH);
+ pthread_mutex_lock(&proc->mutex_prach);
+ proc->instance_cnt_prach = 0;
+ pthread_mutex_unlock(&proc->mutex_prach);
+ pthread_cond_signal(&proc->cond_prach);
+ pthread_mutex_lock(&proc->mutex_synch);
+ proc->instance_cnt_synch = 0;
+ pthread_mutex_unlock(&proc->mutex_synch);
+ pthread_cond_signal(&proc->cond_synch);
+ pthread_mutex_lock(&proc->mutex_gNBs);
+ proc->instance_cnt_gNBs = 0;
+ pthread_mutex_unlock(&proc->mutex_gNBs);
+ pthread_cond_signal(&proc->cond_gNBs);
+ pthread_mutex_lock(&proc->mutex_asynch_rxtx);
+ proc->instance_cnt_asynch_rxtx = 0;
+ pthread_mutex_unlock(&proc->mutex_asynch_rxtx);
+ pthread_cond_signal(&proc->cond_asynch_rxtx);
+ LOG_D(PHY, "Joining pthread_FH\n");
+ pthread_join(proc->pthread_FH, NULL);
+
+ if (ru->function == NGFI_RRU_IF4p5) {
+ LOG_D(PHY, "Joining pthread_prach\n");
+ pthread_join(proc->pthread_prach, NULL);
+
+ if (ru->is_slave) {
+ LOG_D(PHY, "Joining pthread_\n");
+ pthread_join(proc->pthread_synch, NULL);
+ }
+
+ if ((ru->if_timing == synch_to_other) ||
+ (ru->function == NGFI_RRU_IF5) ||
+ (ru->function == NGFI_RRU_IF4p5)) {
+ LOG_D(PHY, "Joining pthread_asynch_rxtx\n");
+ pthread_join(proc->pthread_asynch_rxtx, NULL);
+ }
+ }
+
+ if (get_nprocs() >= 2) {
+ if (ru->feprx) {
+ pthread_mutex_lock(&proc->mutex_fep);
+ proc->instance_cnt_fep = 0;
+ pthread_mutex_unlock(&proc->mutex_fep);
+ pthread_cond_signal(&proc->cond_fep);
+ LOG_D(PHY, "Joining pthread_fep\n");
+ pthread_join(proc->pthread_fep, NULL);
+ pthread_mutex_destroy(&proc->mutex_fep);
+ pthread_cond_destroy(&proc->cond_fep);
+ }
+
+ if (ru->feptx_ofdm) {
+ pthread_mutex_lock(&proc->mutex_feptx);
+ proc->instance_cnt_feptx = 0;
+ pthread_mutex_unlock(&proc->mutex_feptx);
+ pthread_cond_signal(&proc->cond_feptx);
+ LOG_D(PHY, "Joining pthread_feptx\n");
+ pthread_join(proc->pthread_feptx, NULL);
+ pthread_mutex_destroy(&proc->mutex_feptx);
+ pthread_cond_destroy(&proc->cond_feptx);
+ }
+ }
+
+ if (opp_enabled) {
+ LOG_D(PHY, "Joining ru_stats_thread\n");
+ pthread_join(ru->ru_stats_thread, NULL);
+ }
+
+ pthread_mutex_destroy(&proc->mutex_prach);
+ pthread_mutex_destroy(&proc->mutex_asynch_rxtx);
+ pthread_mutex_destroy(&proc->mutex_synch);
+ pthread_mutex_destroy(&proc->mutex_FH);
+ pthread_mutex_destroy(&proc->mutex_gNBs);
+ pthread_cond_destroy(&proc->cond_prach);
+ pthread_cond_destroy(&proc->cond_FH);
+ pthread_cond_destroy(&proc->cond_asynch_rxtx);
+ pthread_cond_destroy(&proc->cond_synch);
+ pthread_cond_destroy(&proc->cond_gNBs);
+}
+
+int check_capabilities(RU_t *ru,RRU_capabilities_t *cap) {
+ FH_fmt_options_t fmt = cap->FH_fmt;
+ int i;
+ int found_band=0;
+ LOG_I(PHY,"RRU %d, num_bands %d, looking for band %d\n",ru->idx,cap->num_bands,ru->nr_frame_parms->eutra_band);
+
+ for (i=0; inum_bands; i++) {
+ LOG_I(PHY,"band %d on RRU %d\n",cap->band_list[i],ru->idx);
+
+ if (ru->nr_frame_parms->eutra_band == cap->band_list[i]) {
+ found_band=1;
+ break;
+ }
+ }
+
+ if (found_band == 0) {
+ LOG_I(PHY,"Couldn't find target EUTRA band %d on RRU %d\n",ru->nr_frame_parms->eutra_band,ru->idx);
+ return(-1);
+ }
+
+ switch (ru->if_south) {
+ case LOCAL_RF:
+ AssertFatal(1==0, "This RU should not have a local RF, exiting\n");
+ return(0);
+ break;
+
+ case REMOTE_IF5:
+ if (fmt == OAI_IF5_only || fmt == OAI_IF5_and_IF4p5) return(0);
+
+ break;
+
+ case REMOTE_IF4p5:
+ if (fmt == OAI_IF4p5_only || fmt == OAI_IF5_and_IF4p5) return(0);
+
+ break;
+
+ case REMOTE_MBP_IF5:
+ if (fmt == MBP_IF5) return(0);
+
+ break;
+
+ default:
+ LOG_I(PHY,"No compatible Fronthaul interface found for RRU %d\n", ru->idx);
+ return(-1);
+ }
+
+ return(-1);
+}
+
+
+char rru_format_options[4][20] = {"OAI_IF5_only","OAI_IF4p5_only","OAI_IF5_and_IF4p5","MBP_IF5"};
+
+char rru_formats[3][20] = {"OAI_IF5","MBP_IF5","OAI_IF4p5"};
+char ru_if_formats[4][20] = {"LOCAL_RF","REMOTE_OAI_IF5","REMOTE_MBP_IF5","REMOTE_OAI_IF4p5"};
+
+void configure_ru(int idx,
+ void *arg) {
+ RU_t *ru = RC.ru[idx];
+ RRU_config_t *config = (RRU_config_t *)arg;
+ RRU_capabilities_t *capabilities = (RRU_capabilities_t *)arg;
+ nfapi_nr_config_request_t *gNB_config = &ru->gNB_list[0]->gNB_config;
+ int ret;
+ LOG_I(PHY, "Received capabilities from RRU %d\n",idx);
+
+ if (capabilities->FH_fmt < MAX_FH_FMTs) LOG_I(PHY, "RU FH options %s\n",rru_format_options[capabilities->FH_fmt]);
+
+ AssertFatal((ret=check_capabilities(ru,capabilities)) == 0,
+ "Cannot configure RRU %d, check_capabilities returned %d\n", idx,ret);
+ // take antenna capabilities of RRU
+ ru->nb_tx = capabilities->nb_tx[0];
+ ru->nb_rx = capabilities->nb_rx[0];
+ // Pass configuration to RRU
+ LOG_I(PHY, "Using %s fronthaul (%d), band %d \n",ru_if_formats[ru->if_south],ru->if_south,ru->nr_frame_parms->eutra_band);
+ // wait for configuration
+ config->FH_fmt = ru->if_south;
+ config->num_bands = 1;
+ config->band_list[0] = ru->nr_frame_parms->eutra_band;
+ config->tx_freq[0] = ru->nr_frame_parms->dl_CarrierFreq;
+ config->rx_freq[0] = ru->nr_frame_parms->ul_CarrierFreq;
+ //config->tdd_config[0] = ru->nr_frame_parms->tdd_config;
+ //config->tdd_config_S[0] = ru->nr_frame_parms->tdd_config_S;
+ config->att_tx[0] = ru->att_tx;
+ config->att_rx[0] = ru->att_rx;
+ config->N_RB_DL[0] = gNB_config->rf_config.dl_carrier_bandwidth.value;
+ config->N_RB_UL[0] = gNB_config->rf_config.ul_carrier_bandwidth.value;
+ config->threequarter_fs[0] = ru->nr_frame_parms->threequarter_fs;
+ /* if (ru->if_south==REMOTE_IF4p5) {
+ config->prach_FreqOffset[0] = ru->nr_frame_parms->prach_config_common.prach_ConfigInfo.prach_FreqOffset;
+ config->prach_ConfigIndex[0] = ru->nr_frame_parms->prach_config_common.prach_ConfigInfo.prach_ConfigIndex;
+ LOG_I(PHY,"REMOTE_IF4p5: prach_FrequOffset %d, prach_ConfigIndex %d\n",
+ config->prach_FreqOffset[0],config->prach_ConfigIndex[0]);*/
+ nr_init_frame_parms(&ru->gNB_list[0]->gNB_config, ru->nr_frame_parms);
+ nr_phy_init_RU(ru);
+}
+
+void configure_rru(int idx,
+ void *arg) {
+ RRU_config_t *config = (RRU_config_t *)arg;
+ RU_t *ru = RC.ru[idx];
+ nfapi_nr_config_request_t *gNB_config = &ru->gNB_list[0]->gNB_config;
+ ru->nr_frame_parms->eutra_band = config->band_list[0];
+ ru->nr_frame_parms->dl_CarrierFreq = config->tx_freq[0];
+ ru->nr_frame_parms->ul_CarrierFreq = config->rx_freq[0];
+
+ if (ru->nr_frame_parms->dl_CarrierFreq == ru->nr_frame_parms->ul_CarrierFreq) {
+ gNB_config->subframe_config.duplex_mode.value = TDD;
+ //ru->nr_frame_parms->tdd_config = config->tdd_config[0];
+ //ru->nr_frame_parms->tdd_config_S = config->tdd_config_S[0];
+ } else
+ gNB_config->subframe_config.duplex_mode.value = FDD;
+
+ ru->att_tx = config->att_tx[0];
+ ru->att_rx = config->att_rx[0];
+ gNB_config->rf_config.dl_carrier_bandwidth.value = config->N_RB_DL[0];
+ gNB_config->rf_config.ul_carrier_bandwidth.value = config->N_RB_UL[0];
+ ru->nr_frame_parms->threequarter_fs = config->threequarter_fs[0];
+
+ //ru->nr_frame_parms->pdsch_config_common.referenceSignalPower = ru->max_pdschReferenceSignalPower-config->att_tx[0];
+ if (ru->function==NGFI_RRU_IF4p5) {
+ ru->nr_frame_parms->att_rx = ru->att_rx;
+ ru->nr_frame_parms->att_tx = ru->att_tx;
+ /*
+ LOG_I(PHY,"Setting ru->function to NGFI_RRU_IF4p5, prach_FrequOffset %d, prach_ConfigIndex %d, att (%d,%d)\n",
+ config->prach_FreqOffset[0],config->prach_ConfigIndex[0],ru->att_tx,ru->att_rx);
+ ru->nr_frame_parms->prach_config_common.prach_ConfigInfo.prach_FreqOffset = config->prach_FreqOffset[0];
+ ru->nr_frame_parms->prach_config_common.prach_ConfigInfo.prach_ConfigIndex = config->prach_ConfigIndex[0]; */
+ }
+
+ fill_rf_config(ru,ru->rf_config_file);
+ nr_init_frame_parms(&ru->gNB_list[0]->gNB_config, ru->nr_frame_parms);
+ nr_phy_init_RU(ru);
+}
+
+/*
+void init_precoding_weights(PHY_VARS_gNB *gNB) {
+
+ int layer,ru_id,aa,re,ue,tb;
+ LTE_DL_FRAME_PARMS *fp=&gNB->frame_parms;
+ RU_t *ru;
+ LTE_gNB_DLSCH_t *dlsch;
+
+ // init precoding weigths
+ for (ue=0;uedlsch[ue][tb];
+ for (layer=0; layer<4; layer++) {
+ int nb_tx=0;
+ for (ru_id=0;ru_idnb_tx;
+ }
+ dlsch->ue_spec_bf_weights[layer] = (int32_t**)malloc16(nb_tx*sizeof(int32_t*));
+
+ for (aa=0; aaue_spec_bf_weights[layer][aa] = (int32_t *)malloc16(fp->ofdm_symbol_size*sizeof(int32_t));
+ for (re=0;reofdm_symbol_size; re++) {
+ dlsch->ue_spec_bf_weights[layer][aa][re] = 0x00007fff;
+ }
+ }
+ }
+ }
+ }
+}*/
+
+void set_function_spec_param(RU_t *ru) {
+ int ret;
+
+ switch (ru->if_south) {
+ case LOCAL_RF: // this is an RU with integrated RF (RRU, gNB)
+ if (ru->function == NGFI_RRU_IF5) { // IF5 RRU
+ ru->do_prach = 0; // no prach processing in RU
+ ru->fh_north_in = NULL; // no shynchronous incoming fronthaul from north
+ ru->fh_north_out = fh_if5_north_out; // need only to do send_IF5 reception
+ ru->fh_south_out = tx_rf; // send output to RF
+ ru->fh_north_asynch_in = fh_if5_north_asynch_in; // TX packets come asynchronously
+ ru->feprx = NULL; // nothing (this is a time-domain signal)
+ ru->feptx_ofdm = NULL; // nothing (this is a time-domain signal)
+ ru->feptx_prec = NULL; // nothing (this is a time-domain signal)
+ ru->start_if = start_if; // need to start the if interface for if5
+ ru->ifdevice.host_type = RRU_HOST;
+ ru->rfdevice.host_type = RRU_HOST;
+ ru->ifdevice.eth_params = &ru->eth_params;
+ reset_meas(&ru->rx_fhaul);
+ reset_meas(&ru->tx_fhaul);
+ reset_meas(&ru->compression);
+ reset_meas(&ru->transport);
+ ret = openair0_transport_load(&ru->ifdevice,&ru->openair0_cfg,&ru->eth_params);
+ printf("openair0_transport_init returns %d for ru_id %d\n", ret, ru->idx);
+
+ if (ret<0) {
+ printf("Exiting, cannot initialize transport protocol\n");
+ exit(-1);
+ }
+ } else if (ru->function == NGFI_RRU_IF4p5) {
+ ru->do_prach = 1; // do part of prach processing in RU
+ ru->fh_north_in = NULL; // no synchronous incoming fronthaul from north
+ ru->fh_north_out = fh_if4p5_north_out; // send_IF4p5 on reception
+ ru->fh_south_out = tx_rf; // send output to RF
+ ru->fh_north_asynch_in = fh_if4p5_north_asynch_in; // TX packets come asynchronously
+ ru->feprx = (get_nprocs()<=2) ? fep_full :ru_fep_full_2thread; // RX DFTs
+ ru->feptx_ofdm = (get_nprocs()<=2) ? nr_feptx_ofdm : nr_feptx_ofdm_2thread; // this is fep with idft only (no precoding in RRU)
+ ru->feptx_prec = NULL;
+ ru->start_if = start_if; // need to start the if interface for if4p5
+ ru->ifdevice.host_type = RRU_HOST;
+ ru->rfdevice.host_type = RRU_HOST;
+ ru->ifdevice.eth_params = &ru->eth_params;
+ reset_meas(&ru->rx_fhaul);
+ reset_meas(&ru->tx_fhaul);
+ reset_meas(&ru->compression);
+ reset_meas(&ru->transport);
+ ret = openair0_transport_load(&ru->ifdevice,&ru->openair0_cfg,&ru->eth_params);
+ printf("openair0_transport_init returns %d for ru_id %d\n", ret, ru->idx);
+
+ if (ret<0) {
+ printf("Exiting, cannot initialize transport protocol\n");
+ exit(-1);
+ }
+
+ malloc_IF4p5_buffer(ru);
+ } else if (ru->function == gNodeB_3GPP) {
+ ru->do_prach = 0; // no prach processing in RU
+ ru->feprx = (get_nprocs()<=2) ? fep_full : ru_fep_full_2thread; // RX DFTs
+ ru->feptx_ofdm = (get_nprocs()<=2) ? nr_feptx_ofdm : nr_feptx_ofdm_2thread; // this is fep with idft and precoding
+ ru->feptx_prec = feptx_prec; // this is fep with idft and precoding
+ ru->fh_north_in = NULL; // no incoming fronthaul from north
+ ru->fh_north_out = NULL; // no outgoing fronthaul to north
+ ru->start_if = NULL; // no if interface
+ ru->rfdevice.host_type = RAU_HOST;
+ }
+
+ ru->fh_south_in = rx_rf; // local synchronous RF RX
+ ru->fh_south_out = tx_rf; // local synchronous RF TX
+ ru->start_rf = start_rf; // need to start the local RF interface
+ ru->stop_rf = stop_rf;
+ printf("configuring ru_id %d (start_rf %p)\n", ru->idx, start_rf);
+ /*
+ if (ru->function == gNodeB_3GPP) { // configure RF parameters only for 3GPP eNodeB, we need to get them from RAU otherwise
+ fill_rf_config(ru,rf_config_file);
+ init_frame_parms(&ru->frame_parms,1);
+ nr_phy_init_RU(ru);
+ }
+
+ ret = openair0_device_load(&ru->rfdevice,&ru->openair0_cfg);
+ if (setup_RU_buffers(ru)!=0) {
+ printf("Exiting, cannot initialize RU Buffers\n");
+ exit(-1);
+ }*/
+ break;
+
+ case REMOTE_IF5: // the remote unit is IF5 RRU
+ ru->do_prach = 0;
+ ru->feprx = (get_nprocs()<=2) ? fep_full : fep_full; // this is frequency-shift + DFTs
+ ru->feptx_prec = feptx_prec; // need to do transmit Precoding + IDFTs
+ ru->feptx_ofdm = (get_nprocs()<=2) ? nr_feptx_ofdm : nr_feptx_ofdm_2thread; // need to do transmit Precoding + IDFTs
+ ru->fh_south_in = fh_if5_south_in; // synchronous IF5 reception
+ ru->fh_south_out = fh_if5_south_out; // synchronous IF5 transmission
+ ru->fh_south_asynch_in = NULL; // no asynchronous UL
+ ru->start_rf = NULL; // no local RF
+ ru->stop_rf = NULL;
+ ru->start_if = start_if; // need to start if interface for IF5
+ ru->ifdevice.host_type = RAU_HOST;
+ ru->ifdevice.eth_params = &ru->eth_params;
+ ru->ifdevice.configure_rru = configure_ru;
+ ret = openair0_transport_load(&ru->ifdevice,&ru->openair0_cfg,&ru->eth_params);
+ printf("openair0_transport_init returns %d for ru_id %d\n", ret, ru->idx);
+
+ if (ret<0) {
+ printf("Exiting, cannot initialize transport protocol\n");
+ exit(-1);
+ }
+
+ break;
+
+ case REMOTE_IF4p5:
+ ru->do_prach = 0;
+ ru->feprx = NULL; // DFTs
+ ru->feptx_prec = feptx_prec; // Precoding operation
+ ru->feptx_ofdm = NULL; // no OFDM mod
+ ru->fh_south_in = fh_if4p5_south_in; // synchronous IF4p5 reception
+ ru->fh_south_out = fh_if4p5_south_out; // synchronous IF4p5 transmission
+ ru->fh_south_asynch_in = (ru->if_timing == synch_to_other) ? fh_if4p5_south_in : NULL; // asynchronous UL if synch_to_other
+ ru->fh_north_out = NULL;
+ ru->fh_north_asynch_in = NULL;
+ ru->start_rf = NULL; // no local RF
+ ru->stop_rf = NULL;
+ ru->start_if = start_if; // need to start if interface for IF4p5
+ ru->ifdevice.host_type = RAU_HOST;
+ ru->ifdevice.eth_params = &ru->eth_params;
+ ru->ifdevice.configure_rru = configure_ru;
+ ret = openair0_transport_load(&ru->ifdevice, &ru->openair0_cfg, &ru->eth_params);
+ printf("openair0_transport_init returns %d for ru_id %d\n", ret, ru->idx);
+
+ if (ret<0) {
+ printf("Exiting, cannot initialize transport protocol\n");
+ exit(-1);
+ }
+
+ malloc_IF4p5_buffer(ru);
+ break;
+
+ default:
+ LOG_E(PHY,"RU with invalid or unknown southbound interface type %d\n",ru->if_south);
+ break;
+ } // switch on interface type
+}
+
+extern void RCconfig_RU(void);
+
+void init_RU(char *rf_config_file) {
+ int ru_id;
+ RU_t *ru;
+ PHY_VARS_gNB *gNB0= (PHY_VARS_gNB *)NULL;
+ NR_DL_FRAME_PARMS *fp = (NR_DL_FRAME_PARMS *)NULL;
+ int i;
+ int CC_id;
+ // create status mask
+ RC.ru_mask = 0;
+ pthread_mutex_init(&RC.ru_mutex,NULL);
+ pthread_cond_init(&RC.ru_cond,NULL);
+ // read in configuration file)
+ printf("configuring RU from file\n");
+ RCconfig_RU();
+ LOG_I(PHY,"number of L1 instances %d, number of RU %d, number of CPU cores %d\n",RC.nb_nr_L1_inst,RC.nb_RU,get_nprocs());
+
+ if (RC.nb_nr_CC != 0)
+ for (i=0; inum_RU=0;
+
+ LOG_D(PHY,"Process RUs RC.nb_RU:%d\n",RC.nb_RU);
+
+ for (ru_id=0; ru_idrf_config_file = rf_config_file;
+ ru->idx = ru_id;
+ ru->ts_offset = 0;
+ // use gNB_list[0] as a reference for RU frame parameters
+ // NOTE: multiple CC_id are not handled here yet!
+
+ if (ru->num_gNB > 0) {
+ LOG_D(PHY, "%s() RC.ru[%d].num_gNB:%d ru->gNB_list[0]:%p RC.gNB[0][0]:%p rf_config_file:%s\n", __FUNCTION__, ru_id, ru->num_gNB, ru->gNB_list[0], RC.gNB[0][0], ru->rf_config_file);
+
+ if (ru->gNB_list[0] == 0) {
+ LOG_E(PHY,"%s() DJP - ru->gNB_list ru->num_gNB are not initialized - so do it manually\n", __FUNCTION__);
+ ru->gNB_list[0] = RC.gNB[0][0];
+ ru->num_gNB=1;
+ //
+ // DJP - feptx_prec() / feptx_ofdm() parses the gNB_list (based on num_gNB) and copies the txdata_F to txdata in RU
+ //
+ } else {
+ LOG_E(PHY,"DJP - delete code above this %s:%d\n", __FILE__, __LINE__);
+ }
+ }
+
+ gNB0 = ru->gNB_list[0];
+ fp = ru->nr_frame_parms;
+ LOG_D(PHY, "RU FUnction:%d ru->if_south:%d\n", ru->function, ru->if_south);
+
+ if (gNB0) {
+ if ((ru->function != NGFI_RRU_IF5) && (ru->function != NGFI_RRU_IF4p5))
+ AssertFatal(gNB0!=NULL,"gNB0 is null!\n");
+
+ if (gNB0) {
+ LOG_I(PHY,"Copying frame parms from gNB %d to ru %d\n",gNB0->Mod_id,ru->idx);
+ memcpy((void *)fp,(void *)&gNB0->frame_parms,sizeof(NR_DL_FRAME_PARMS));
+ memset((void *)ru->frame_parms, 0, sizeof(LTE_DL_FRAME_PARMS));
+ // attach all RU to all gNBs in its list/
+ LOG_D(PHY,"ru->num_gNB:%d gNB0->num_RU:%d\n", ru->num_gNB, gNB0->num_RU);
+
+ for (i=0; inum_gNB; i++) {
+ gNB0 = ru->gNB_list[i];
+ gNB0->RU_list[gNB0->num_RU++] = ru;
+ }
+ }
+ }
+
+ // LOG_I(PHY,"Initializing RRU descriptor %d : (%s,%s,%d)\n",ru_id,ru_if_types[ru->if_south],gNB_timing[ru->if_timing],ru->function);
+ set_function_spec_param(ru);
+ LOG_I(PHY,"Starting ru_thread %d\n",ru_id);
+ init_RU_proc(ru);
+ } // for ru_id
+
+ // sleep(1);
+ LOG_D(HW,"[nr-softmodem.c] RU threads created\n");
+}
+
+
+
+
+void stop_RU(int nb_ru) {
+ for (int inst = 0; inst < nb_ru; inst++) {
+ LOG_I(PHY, "Stopping RU %d processing threads\n", inst);
+ kill_RU_proc(inst);
+ }
+}
+
+
+/* --------------------------------------------------------*/
+/* from here function to use configuration module */
+void RCconfig_RU(void) {
+ int j = 0;
+ int i = 0;
+ paramdef_t RUParams[] = RUPARAMS_DESC;
+ paramlist_def_t RUParamList = {CONFIG_STRING_RU_LIST,NULL,0};
+ config_getlist( &RUParamList,RUParams,sizeof(RUParams)/sizeof(paramdef_t), NULL);
+
+ if ( RUParamList.numelt > 0) {
+ RC.ru = (RU_t **)malloc(RC.nb_RU*sizeof(RU_t *));
+ RC.ru_mask=(1<idx = j;
+ RC.ru[j]->nr_frame_parms = (NR_DL_FRAME_PARMS *)malloc(sizeof(NR_DL_FRAME_PARMS));
+ RC.ru[j]->frame_parms = (LTE_DL_FRAME_PARMS *)malloc(sizeof(LTE_DL_FRAME_PARMS));
+ printf("Creating RC.ru[%d]:%p\n", j, RC.ru[j]);
+ RC.ru[j]->if_timing = synch_to_ext_device;
+
+ if (RC.nb_nr_L1_inst >0)
+ RC.ru[j]->num_gNB = RUParamList.paramarray[j][RU_ENB_LIST_IDX].numelt;
+ else
+ RC.ru[j]->num_gNB = 0;
+
+ for (i=0; inum_gNB; i++) RC.ru[j]->gNB_list[i] = RC.gNB[RUParamList.paramarray[j][RU_ENB_LIST_IDX].iptr[i]][0];
+
+ if (config_isparamset(RUParamList.paramarray[j], RU_SDR_ADDRS)) {
+ RC.ru[j]->openair0_cfg.sdr_addrs = strdup(*(RUParamList.paramarray[j][RU_SDR_ADDRS].strptr));
+ }
+
+ if (config_isparamset(RUParamList.paramarray[j], RU_SDR_CLK_SRC)) {
+ if (strcmp(*(RUParamList.paramarray[j][RU_SDR_CLK_SRC].strptr), "internal") == 0) {
+ RC.ru[j]->openair0_cfg.clock_source = internal;
+ LOG_D(PHY, "RU clock source set as internal\n");
+ } else if (strcmp(*(RUParamList.paramarray[j][RU_SDR_CLK_SRC].strptr), "external") == 0) {
+ RC.ru[j]->openair0_cfg.clock_source = external;
+ LOG_D(PHY, "RU clock source set as external\n");
+ } else if (strcmp(*(RUParamList.paramarray[j][RU_SDR_CLK_SRC].strptr), "gpsdo") == 0) {
+ RC.ru[j]->openair0_cfg.clock_source = gpsdo;
+ LOG_D(PHY, "RU clock source set as gpsdo\n");
+ } else {
+ LOG_E(PHY, "Erroneous RU clock source in the provided configuration file: '%s'\n", *(RUParamList.paramarray[j][RU_SDR_CLK_SRC].strptr));
+ }
+ }
+
+ if (strcmp(*(RUParamList.paramarray[j][RU_LOCAL_RF_IDX].strptr), "yes") == 0) {
+ if ( !(config_isparamset(RUParamList.paramarray[j],RU_LOCAL_IF_NAME_IDX)) ) {
+ RC.ru[j]->if_south = LOCAL_RF;
+ RC.ru[j]->function = gNodeB_3GPP;
+ printf("Setting function for RU %d to gNodeB_3GPP\n",j);
+ } else {
+ RC.ru[j]->eth_params.local_if_name = strdup(*(RUParamList.paramarray[j][RU_LOCAL_IF_NAME_IDX].strptr));
+ RC.ru[j]->eth_params.my_addr = strdup(*(RUParamList.paramarray[j][RU_LOCAL_ADDRESS_IDX].strptr));
+ RC.ru[j]->eth_params.remote_addr = strdup(*(RUParamList.paramarray[j][RU_REMOTE_ADDRESS_IDX].strptr));
+ RC.ru[j]->eth_params.my_portc = *(RUParamList.paramarray[j][RU_LOCAL_PORTC_IDX].uptr);
+ RC.ru[j]->eth_params.remote_portc = *(RUParamList.paramarray[j][RU_REMOTE_PORTC_IDX].uptr);
+ RC.ru[j]->eth_params.my_portd = *(RUParamList.paramarray[j][RU_LOCAL_PORTD_IDX].uptr);
+ RC.ru[j]->eth_params.remote_portd = *(RUParamList.paramarray[j][RU_REMOTE_PORTD_IDX].uptr);
+
+ if (strcmp(*(RUParamList.paramarray[j][RU_TRANSPORT_PREFERENCE_IDX].strptr), "udp") == 0) {
+ RC.ru[j]->if_south = LOCAL_RF;
+ RC.ru[j]->function = NGFI_RRU_IF5;
+ RC.ru[j]->eth_params.transp_preference = ETH_UDP_MODE;
+ printf("Setting function for RU %d to NGFI_RRU_IF5 (udp)\n",j);
+ } else if (strcmp(*(RUParamList.paramarray[j][RU_TRANSPORT_PREFERENCE_IDX].strptr), "raw") == 0) {
+ RC.ru[j]->if_south = LOCAL_RF;
+ RC.ru[j]->function = NGFI_RRU_IF5;
+ RC.ru[j]->eth_params.transp_preference = ETH_RAW_MODE;
+ printf("Setting function for RU %d to NGFI_RRU_IF5 (raw)\n",j);
+ } else if (strcmp(*(RUParamList.paramarray[j][RU_TRANSPORT_PREFERENCE_IDX].strptr), "udp_if4p5") == 0) {
+ RC.ru[j]->if_south = LOCAL_RF;
+ RC.ru[j]->function = NGFI_RRU_IF4p5;
+ RC.ru[j]->eth_params.transp_preference = ETH_UDP_IF4p5_MODE;
+ printf("Setting function for RU %d to NGFI_RRU_IF4p5 (udp)\n",j);
+ } else if (strcmp(*(RUParamList.paramarray[j][RU_TRANSPORT_PREFERENCE_IDX].strptr), "raw_if4p5") == 0) {
+ RC.ru[j]->if_south = LOCAL_RF;
+ RC.ru[j]->function = NGFI_RRU_IF4p5;
+ RC.ru[j]->eth_params.transp_preference = ETH_RAW_IF4p5_MODE;
+ printf("Setting function for RU %d to NGFI_RRU_IF4p5 (raw)\n",j);
+ }
+ }
+
+ RC.ru[j]->max_pdschReferenceSignalPower = *(RUParamList.paramarray[j][RU_MAX_RS_EPRE_IDX].uptr);;
+ RC.ru[j]->max_rxgain = *(RUParamList.paramarray[j][RU_MAX_RXGAIN_IDX].uptr);
+ RC.ru[j]->num_bands = RUParamList.paramarray[j][RU_BAND_LIST_IDX].numelt;
+
+ for (i=0; inum_bands; i++) RC.ru[j]->band[i] = RUParamList.paramarray[j][RU_BAND_LIST_IDX].iptr[i];
+ } //strcmp(local_rf, "yes") == 0
+ else {
+ printf("RU %d: Transport %s\n",j,*(RUParamList.paramarray[j][RU_TRANSPORT_PREFERENCE_IDX].strptr));
+ RC.ru[j]->eth_params.local_if_name = strdup(*(RUParamList.paramarray[j][RU_LOCAL_IF_NAME_IDX].strptr));
+ RC.ru[j]->eth_params.my_addr = strdup(*(RUParamList.paramarray[j][RU_LOCAL_ADDRESS_IDX].strptr));
+ RC.ru[j]->eth_params.remote_addr = strdup(*(RUParamList.paramarray[j][RU_REMOTE_ADDRESS_IDX].strptr));
+ RC.ru[j]->eth_params.my_portc = *(RUParamList.paramarray[j][RU_LOCAL_PORTC_IDX].uptr);
+ RC.ru[j]->eth_params.remote_portc = *(RUParamList.paramarray[j][RU_REMOTE_PORTC_IDX].uptr);
+ RC.ru[j]->eth_params.my_portd = *(RUParamList.paramarray[j][RU_LOCAL_PORTD_IDX].uptr);
+ RC.ru[j]->eth_params.remote_portd = *(RUParamList.paramarray[j][RU_REMOTE_PORTD_IDX].uptr);
+
+ if (strcmp(*(RUParamList.paramarray[j][RU_TRANSPORT_PREFERENCE_IDX].strptr), "udp") == 0) {
+ RC.ru[j]->if_south = REMOTE_IF5;
+ RC.ru[j]->function = NGFI_RAU_IF5;
+ RC.ru[j]->eth_params.transp_preference = ETH_UDP_MODE;
+ } else if (strcmp(*(RUParamList.paramarray[j][RU_TRANSPORT_PREFERENCE_IDX].strptr), "raw") == 0) {
+ RC.ru[j]->if_south = REMOTE_IF5;
+ RC.ru[j]->function = NGFI_RAU_IF5;
+ RC.ru[j]->eth_params.transp_preference = ETH_RAW_MODE;
+ } else if (strcmp(*(RUParamList.paramarray[j][RU_TRANSPORT_PREFERENCE_IDX].strptr), "udp_if4p5") == 0) {
+ RC.ru[j]->if_south = REMOTE_IF4p5;
+ RC.ru[j]->function = NGFI_RAU_IF4p5;
+ RC.ru[j]->eth_params.transp_preference = ETH_UDP_IF4p5_MODE;
+ } else if (strcmp(*(RUParamList.paramarray[j][RU_TRANSPORT_PREFERENCE_IDX].strptr), "raw_if4p5") == 0) {
+ RC.ru[j]->if_south = REMOTE_IF4p5;
+ RC.ru[j]->function = NGFI_RAU_IF4p5;
+ RC.ru[j]->eth_params.transp_preference = ETH_RAW_IF4p5_MODE;
+ } else if (strcmp(*(RUParamList.paramarray[j][RU_TRANSPORT_PREFERENCE_IDX].strptr), "raw_if5_mobipass") == 0) {
+ RC.ru[j]->if_south = REMOTE_IF5;
+ RC.ru[j]->function = NGFI_RAU_IF5;
+ RC.ru[j]->if_timing = synch_to_other;
+ RC.ru[j]->eth_params.transp_preference = ETH_RAW_IF5_MOBIPASS;
+ }
+ } /* strcmp(local_rf, "yes") != 0 */
+
+ RC.ru[j]->nb_tx = *(RUParamList.paramarray[j][RU_NB_TX_IDX].uptr);
+ RC.ru[j]->nb_rx = *(RUParamList.paramarray[j][RU_NB_RX_IDX].uptr);
+ RC.ru[j]->att_tx = *(RUParamList.paramarray[j][RU_ATT_TX_IDX].uptr);
+ RC.ru[j]->att_rx = *(RUParamList.paramarray[j][RU_ATT_RX_IDX].uptr);
+ }// j=0..num_rus
+ } else {
+ RC.nb_RU = 0;
+ } // setting != NULL
+
+ return;
+}
diff --git a/executables/nr-softmodem.c b/executables/nr-softmodem.c
new file mode 100644
index 0000000000..3147284e99
--- /dev/null
+++ b/executables/nr-softmodem.c
@@ -0,0 +1,1237 @@
+/*
+ * 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
+ */
+
+
+#define _GNU_SOURCE /* See feature_test_macros(7) */
+#include
+
+
+#include "T.h"
+
+#undef MALLOC //there are two conflicting definitions, so we better make sure we don't use it at all
+#include
+
+#include "msc.h"
+
+#include "PHY/types.h"
+#include "common/ran_context.h"
+
+#include "PHY/defs_gNB.h"
+#include "common/config/config_userapi.h"
+#include "common/utils/load_module_shlib.h"
+#undef MALLOC //there are two conflicting definitions, so we better make sure we don't use it at all
+//#undef FRAME_LENGTH_COMPLEX_SAMPLES //there are two conflicting definitions, so we better make sure we don't use it at all
+
+#include "../../ARCH/COMMON/common_lib.h"
+#include "../../ARCH/ETHERNET/USERSPACE/LIB/if_defs.h"
+
+//#undef FRAME_LENGTH_COMPLEX_SAMPLES //there are two conflicting definitions, so we better make sure we don't use it at all
+
+#include "PHY/phy_vars.h"
+#include "SCHED/sched_common_vars.h"
+#include "LAYER2/MAC/mac_vars.h"
+
+#include "LAYER2/MAC/mac.h"
+#include "LAYER2/MAC/mac_proto.h"
+#include "RRC/LTE/rrc_vars.h"
+#include "PHY_INTERFACE/phy_interface_vars.h"
+#include "gnb_config.h"
+
+#ifdef SMBV
+#include "PHY/TOOLS/smbv.h"
+unsigned short config_frames[4] = {2,9,11,13};
+#endif
+
+#include "common/utils/LOG/log.h"
+#include "common/utils/LOG/vcd_signal_dumper.h"
+
+#include "UTIL/OPT/opt.h"
+
+//#include "PHY/TOOLS/time_meas.h"
+
+#ifndef OPENAIR2
+ #include "UTIL/OTG/otg_vars.h"
+#endif
+
+#if defined(ENABLE_ITTI)
+ #include "intertask_interface.h"
+#endif
+
+#include "PHY/INIT/phy_init.h"
+
+#include "system.h"
+#include
+
+#ifdef XFORMS
+ #include "PHY/TOOLS/nr_phy_scope.h"
+ #include "stats.h"
+#endif
+#include "nr-softmodem.h"
+#include "NB_IoT_interface.h"
+
+#ifdef XFORMS
+ // current status is that every UE has a DL scope for a SINGLE eNB (gnb_id=0)
+ // at eNB 0, an UL scope for every UE
+
+ FD_phy_scope_gnb *form_gnb[MAX_NUM_CCs][NUMBER_OF_UE_MAX];
+ FD_stats_form *form_stats=NULL,*form_stats_l2=NULL;
+ char title[255];
+ unsigned char scope_enb_num_ue = 2;
+ static pthread_t forms_thread; //xforms
+
+#endif //XFORMS
+
+short nr_mod_table[NR_MOD_TABLE_SIZE_SHORT] = {0,0,16384,16384,-16384,-16384,16384,16384,16384,-16384,-16384,16384,-16384,-16384,7327,7327,7327,21981,21981,7327,21981,21981,7327,-7327,7327,-21981,21981,-7327,21981,-21981,-7327,7327,-7327,21981,-21981,7327,-21981,21981,-7327,-7327,-7327,-21981,-21981,-7327,-21981,-21981,10726,10726,10726,3576,3576,10726,3576,3576,10726,17876,10726,25027,3576,17876,3576,25027,17876,10726,17876,3576,25027,10726,25027,3576,17876,17876,17876,25027,25027,17876,25027,25027,10726,-10726,10726,-3576,3576,-10726,3576,-3576,10726,-17876,10726,-25027,3576,-17876,3576,-25027,17876,-10726,17876,-3576,25027,-10726,25027,-3576,17876,-17876,17876,-25027,25027,-17876,25027,-25027,-10726,10726,-10726,3576,-3576,10726,-3576,3576,-10726,17876,-10726,25027,-3576,17876,-3576,25027,-17876,10726,-17876,3576,-25027,10726,-25027,3576,-17876,17876,-17876,25027,-25027,17876,-25027,25027,-10726,-10726,-10726,-3576,-3576,-10726,-3576,-3576,-10726,-17876,-10726,-25027,-3576,-17876,-3576,-25027,-17876,-10726,-17876,-3576,-25027,-10726,-25027,-3576,-17876,-17876,-17876,-25027,-25027,-17876,-25027,-25027,8886,8886,8886,12439,12439,8886,12439,12439,8886,5332,8886,1778,12439,5332,12439,1778,5332,8886,5332,12439,1778,8886,1778,12439,5332,5332,5332,1778,1778,5332,1778,1778,8886,19547,8886,15993,12439,19547,12439,15993,8886,23101,8886,26655,12439,23101,12439,26655,5332,19547,5332,15993,1778,19547,1778,15993,5332,23101,5332,26655,1778,23101,1778,26655,19547,8886,19547,12439,15993,8886,15993,12439,19547,5332,19547,1778,15993,5332,15993,1778,23101,8886,23101,12439,26655,8886,26655,12439,23101,5332,23101,1778,26655,5332,26655,1778,19547,19547,19547,15993,15993,19547,15993,15993,19547,23101,19547,26655,15993,23101,15993,26655,23101,19547,23101,15993,26655,19547,26655,15993,23101,23101,23101,26655,26655,23101,26655,26655,8886,-8886,8886,-12439,12439,-8886,12439,-12439,8886,-5332,8886,-1778,12439,-5332,12439,-1778,5332,-8886,5332,-12439,1778,-8886,1778,-12439,5332,-5332,5332,-1778,1778,-5332,1778,-1778,8886,-19547,8886,-15993,12439,-19547,12439,-15993,8886,-23101,8886,-26655,12439,-23101,12439,-26655,5332,-19547,5332,-15993,1778,-19547,1778,-15993,5332,-23101,5332,-26655,1778,-23101,1778,-26655,19547,-8886,19547,-12439,15993,-8886,15993,-12439,19547,-5332,19547,-1778,15993,-5332,15993,-1778,23101,-8886,23101,-12439,26655,-8886,26655,-12439,23101,-5332,23101,-1778,26655,-5332,26655,-1778,19547,-19547,19547,-15993,15993,-19547,15993,-15993,19547,-23101,19547,-26655,15993,-23101,15993,-26655,23101,-19547,23101,-15993,26655,-19547,26655,-15993,23101,-23101,23101,-26655,26655,-23101,26655,-26655,-8886,8886,-8886,12439,-12439,8886,-12439,12439,-8886,5332,-8886,1778,-12439,5332,-12439,1778,-5332,8886,-5332,12439,-1778,8886,-1778,12439,-5332,5332,-5332,1778,-1778,5332,-1778,1778,-8886,19547,-8886,15993,-12439,19547,-12439,15993,-8886,23101,-8886,26655,-12439,23101,-12439,26655,-5332,19547,-5332,15993,-1778,19547,-1778,15993,-5332,23101,-5332,26655,-1778,23101,-1778,26655,-19547,8886,-19547,12439,-15993,8886,-15993,12439,-19547,5332,-19547,1778,-15993,5332,-15993,1778,-23101,8886,-23101,12439,-26655,8886,-26655,12439,-23101,5332,-23101,1778,-26655,5332,-26655,1778,-19547,19547,-19547,15993,-15993,19547,-15993,15993,-19547,23101,-19547,26655,-15993,23101,-15993,26655,-23101,19547,-23101,15993,-26655,19547,-26655,15993,-23101,23101,-23101,26655,-26655,23101,-26655,26655,-8886,-8886,-8886,-12439,-12439,-8886,-12439,-12439,-8886,-5332,-8886,-1778,-12439,-5332,-12439,-1778,-5332,-8886,-5332,-12439,-1778,-8886,-1778,-12439,-5332,-5332,-5332,-1778,-1778,-5332,-1778,-1778,-8886,-19547,-8886,-15993,-12439,-19547,-12439,-15993,-8886,-23101,-8886,-26655,-12439,-23101,-12439,-26655,-5332,-19547,-5332,-15993,-1778,-19547,-1778,-15993,-5332,-23101,-5332,-26655,-1778,-23101,-1778,-26655,-19547,-8886,-19547,-12439,-15993,-8886,-15993,-12439,-19547,-5332,-19547,-1778,-15993,-5332,-15993,-1778,-23101,-8886,-23101,-12439,-26655,-8886,-26655,-12439,-23101,-5332,-23101,-1778,-26655,-5332,-26655,-1778,-19547,-19547,-19547,-15993,-15993,-19547,-15993,-15993,-19547,-23101,-19547,-26655,-15993,-23101,-15993,-26655,-23101,-19547,-23101,-15993,-26655,-19547,-26655,-15993,-23101,-23101,-23101,-26655,-26655,-23101,-26655,-26655};
+
+
+pthread_cond_t nfapi_sync_cond;
+pthread_mutex_t nfapi_sync_mutex;
+int nfapi_sync_var=-1; //!< protected by mutex \ref nfapi_sync_mutex
+
+uint8_t nfapi_mode = 0; // Default to monolithic mode
+
+pthread_cond_t sync_cond;
+pthread_mutex_t sync_mutex;
+int sync_var=-1; //!< protected by mutex \ref sync_mutex.
+int config_sync_var=-1;
+
+#if defined(ENABLE_ITTI)
+ volatile int start_gNB = 0;
+#endif
+volatile int oai_exit = 0;
+
+static clock_source_t clock_source = internal;
+static int wait_for_sync = 0;
+
+unsigned int mmapped_dma=0;
+int single_thread_flag=1;
+
+static int8_t threequarter_fs=0;
+
+uint32_t downlink_frequency[MAX_NUM_CCs][4];
+int32_t uplink_frequency_offset[MAX_NUM_CCs][4];
+
+//Temp fix for inexisting NR upper layer
+unsigned char NB_gNB_INST = 1;
+
+#if defined(ENABLE_ITTI)
+ static char *itti_dump_file = NULL;
+#endif
+
+int UE_scan = 1;
+int UE_scan_carrier = 0;
+runmode_t mode = normal_txrx;
+
+FILE *input_fd=NULL;
+
+
+#if MAX_NUM_CCs == 1
+rx_gain_t rx_gain_mode[MAX_NUM_CCs][4] = {{max_gain,max_gain,max_gain,max_gain}};
+double tx_gain[MAX_NUM_CCs][4] = {{20,0,0,0}};
+double rx_gain[MAX_NUM_CCs][4] = {{110,0,0,0}};
+#else
+rx_gain_t rx_gain_mode[MAX_NUM_CCs][4] = {{max_gain,max_gain,max_gain,max_gain},{max_gain,max_gain,max_gain,max_gain}};
+double tx_gain[MAX_NUM_CCs][4] = {{20,0,0,0},{20,0,0,0}};
+double rx_gain[MAX_NUM_CCs][4] = {{110,0,0,0},{20,0,0,0}};
+#endif
+
+double rx_gain_off = 0.0;
+
+double sample_rate=30.72e6;
+double bw = 10.0e6;
+
+static int tx_max_power[MAX_NUM_CCs]; /* = {0,0}*/;
+
+char rf_config_file[1024]="/usr/local/etc/syriq/ue.band7.tm1.PRB100.NR40.dat";
+
+int chain_offset=0;
+int phy_test = 0;
+uint8_t usim_test = 0;
+
+uint8_t dci_Format = 0;
+uint8_t agregation_Level =0xFF;
+
+uint8_t nb_antenna_tx = 1;
+uint8_t nb_antenna_rx = 1;
+
+char ref[128] = "internal";
+char channels[128] = "0";
+
+int rx_input_level_dBm;
+
+#ifdef XFORMS
+ extern int otg_enabled;
+ static char do_forms=0;
+#else
+ int otg_enabled;
+#endif
+//int number_of_cards = 1;
+
+
+//static NR_DL_FRAME_PARMS *frame_parms[MAX_NUM_CCs];
+//static nfapi_nr_config_request_t *config[MAX_NUM_CCs];
+uint32_t target_dl_mcs = 28; //maximum allowed mcs
+uint32_t target_ul_mcs = 20;
+uint32_t timing_advance = 0;
+uint8_t exit_missed_slots=1;
+uint64_t num_missed_slots=0; // counter for the number of missed slots
+
+
+extern void reset_opp_meas(void);
+extern void print_opp_meas(void);
+
+extern void init_eNB_afterRU(void);
+
+int transmission_mode=1;
+int emulate_rf = 0;
+int numerology = 0;
+char *parallel_config = NULL;
+char *worker_config = NULL;
+
+static THREAD_STRUCT thread_struct;
+void set_parallel_conf(char *parallel_conf) {
+ if(strcmp(parallel_conf,"PARALLEL_SINGLE_THREAD")==0) thread_struct.parallel_conf = PARALLEL_SINGLE_THREAD;
+ else if(strcmp(parallel_conf,"PARALLEL_RU_L1_SPLIT")==0) thread_struct.parallel_conf = PARALLEL_RU_L1_SPLIT;
+ else if(strcmp(parallel_conf,"PARALLEL_RU_L1_TRX_SPLIT")==0) thread_struct.parallel_conf = PARALLEL_RU_L1_TRX_SPLIT;
+
+ printf("[CONFIG] parallel conf is set to %d\n",thread_struct.parallel_conf);
+}
+void set_worker_conf(char *worker_conf) {
+ if(strcmp(worker_conf,"WORKER_DISABLE")==0) thread_struct.worker_conf = WORKER_DISABLE;
+ else if(strcmp(worker_conf,"WORKER_ENABLE")==0) thread_struct.worker_conf = WORKER_ENABLE;
+
+ printf("[CONFIG] worker conf is set to %d\n",thread_struct.worker_conf);
+}
+PARALLEL_CONF_t get_thread_parallel_conf(void) {
+ return thread_struct.parallel_conf;
+}
+WORKER_CONF_t get_thread_worker_conf(void) {
+ return thread_struct.worker_conf;
+}
+
+
+/* struct for ethernet specific parameters given in eNB conf file */
+eth_params_t *eth_params;
+
+openair0_config_t openair0_cfg[MAX_CARDS];
+
+double cpuf;
+
+extern char uecap_xer[1024];
+char uecap_xer_in=0;
+
+/* see file openair2/LAYER2/MAC/main.c for why abstraction_flag is needed
+ * this is very hackish - find a proper solution
+ */
+uint8_t abstraction_flag=0;
+
+/* forward declarations */
+void set_default_frame_parms(nfapi_nr_config_request_t *config[MAX_NUM_CCs], NR_DL_FRAME_PARMS *frame_parms[MAX_NUM_CCs]);
+
+/*---------------------BMC: timespec helpers -----------------------------*/
+
+struct timespec min_diff_time = { .tv_sec = 0, .tv_nsec = 0 };
+struct timespec max_diff_time = { .tv_sec = 0, .tv_nsec = 0 };
+
+struct timespec clock_difftime(struct timespec start, struct timespec end) {
+ struct timespec temp;
+
+ if ((end.tv_nsec-start.tv_nsec)<0) {
+ temp.tv_sec = end.tv_sec-start.tv_sec-1;
+ temp.tv_nsec = 1000000000+end.tv_nsec-start.tv_nsec;
+ } else {
+ temp.tv_sec = end.tv_sec-start.tv_sec;
+ temp.tv_nsec = end.tv_nsec-start.tv_nsec;
+ }
+
+ return temp;
+}
+
+void print_difftimes(void) {
+#ifdef DEBUG
+ printf("difftimes min = %lu ns ; max = %lu ns\n", min_diff_time.tv_nsec, max_diff_time.tv_nsec);
+#else
+ LOG_I(HW,"difftimes min = %lu ns ; max = %lu ns\n", min_diff_time.tv_nsec, max_diff_time.tv_nsec);
+#endif
+}
+
+void update_difftimes(struct timespec start, struct timespec end) {
+ struct timespec diff_time = { .tv_sec = 0, .tv_nsec = 0 };
+ int changed = 0;
+ diff_time = clock_difftime(start, end);
+
+ if ((min_diff_time.tv_nsec == 0) || (diff_time.tv_nsec < min_diff_time.tv_nsec)) {
+ min_diff_time.tv_nsec = diff_time.tv_nsec;
+ changed = 1;
+ }
+
+ if ((max_diff_time.tv_nsec == 0) || (diff_time.tv_nsec > max_diff_time.tv_nsec)) {
+ max_diff_time.tv_nsec = diff_time.tv_nsec;
+ changed = 1;
+ }
+
+#if 1
+
+ if (changed) print_difftimes();
+
+#endif
+}
+
+/*------------------------------------------------------------------------*/
+
+unsigned int build_rflocal(int txi, int txq, int rxi, int rxq) {
+ return (txi + (txq<<6) + (rxi<<12) + (rxq<<18));
+}
+unsigned int build_rfdc(int dcoff_i_rxfe, int dcoff_q_rxfe) {
+ return (dcoff_i_rxfe + (dcoff_q_rxfe<<8));
+}
+
+#if !defined(ENABLE_ITTI)
+void signal_handler(int sig) {
+ void *array[10];
+ size_t size;
+
+ if (sig==SIGSEGV) {
+ // get void*'s for all entries on the stack
+ size = backtrace(array, 10);
+ // print out all the frames to stderr
+ fprintf(stderr, "Error: signal %d:\n", sig);
+ backtrace_symbols_fd(array, size, 2);
+ exit(-1);
+ } else {
+ printf("trying to exit gracefully...\n");
+ oai_exit = 1;
+ }
+}
+#endif
+#define KNRM "\x1B[0m"
+#define KRED "\x1B[31m"
+#define KGRN "\x1B[32m"
+#define KBLU "\x1B[34m"
+#define RESET "\033[0m"
+
+#if defined(ENABLE_ITTI)
+void signal_handler_itti(int sig) {
+ // Call exit function
+ char msg[256];
+ memset(msg, 0, 256);
+ sprintf(msg, "caught signal %s\n", strsignal(sig));
+ exit_function(__FILE__, __FUNCTION__, __LINE__, msg);
+}
+#endif
+
+void exit_function(const char *file, const char *function, const int line, const char *s) {
+ int ru_id;
+
+ if (s != NULL) {
+ printf("%s:%d %s() Exiting OAI softmodem: %s\n",file,line, function, s);
+ }
+
+ oai_exit = 1;
+
+ if (RC.ru == NULL)
+ exit(-1); // likely init not completed, prevent crash or hang, exit now...
+
+ for (ru_id=0; ru_idrfdevice.trx_end_func) {
+ RC.ru[ru_id]->rfdevice.trx_end_func(&RC.ru[ru_id]->rfdevice);
+ RC.ru[ru_id]->rfdevice.trx_end_func = NULL;
+ }
+
+ if (RC.ru[ru_id] && RC.ru[ru_id]->ifdevice.trx_end_func) {
+ RC.ru[ru_id]->ifdevice.trx_end_func(&RC.ru[ru_id]->ifdevice);
+ RC.ru[ru_id]->ifdevice.trx_end_func = NULL;
+ }
+ }
+
+ sleep(1); //allow lte-softmodem threads to exit first
+#if defined(ENABLE_ITTI)
+ itti_terminate_tasks (TASK_UNKNOWN);
+#endif
+ exit(1);
+}
+
+#ifdef XFORMS
+
+
+void reset_stats(FL_OBJECT *button, long arg) {
+ PHY_VARS_gNB *phy_vars_gNB = RC.gNB[0][0];
+
+ for (int i=0; idlsch[i][0]->Mlimit; j++) {
+ phy_vars_gNB->UE_stats[i].dlsch_NAK[k][j]=0;
+ phy_vars_gNB->UE_stats[i].dlsch_ACK[k][j]=0;
+ phy_vars_gNB->UE_stats[i].dlsch_trials[k][j]=0;
+ }*/
+ phy_vars_gNB->UE_stats[i].dlsch_l2_errors[k]=0;
+ phy_vars_gNB->UE_stats[i].ulsch_errors[k]=0;
+ phy_vars_gNB->UE_stats[i].ulsch_consecutive_errors=0;
+ phy_vars_gNB->UE_stats[i].dlsch_sliding_cnt=0;
+ phy_vars_gNB->UE_stats[i].dlsch_NAK_round0=0;
+ phy_vars_gNB->UE_stats[i].dlsch_mcs_offset=0;
+ }
+ }
+}
+
+static void *scope_thread(void *arg) {
+ int UE_id, CC_id;
+ int ue_cnt=0;
+# ifdef ENABLE_XFORMS_WRITE_STATS
+ FILE *gNB_stats = fopen("gNB_stats.txt", "w");
+#endif
+
+ while (!oai_exit) {
+ ue_cnt=0;
+
+ for(UE_id=0; UE_id 0) {
+ /* Last task to create, others task must be ready before its start */
+ if (itti_create_task (TASK_GNB_APP, gNB_app_task, NULL) < 0) {
+ LOG_E(GNB_APP, "Create task for gNB APP failed\n");
+ return -1;
+ }
+ }
+
+ /*
+ # if defined(ENABLE_USE_MME)
+ if (gnb_nb > 0) {
+ if (itti_create_task (TASK_SCTP, sctp_eNB_task, NULL) < 0) {
+ LOG_E(SCTP, "Create task for SCTP failed\n");
+ return -1;
+ }
+
+ if (itti_create_task (TASK_S1AP, s1ap_eNB_task, NULL) < 0) {
+ LOG_E(S1AP, "Create task for S1AP failed\n");
+ return -1;
+ }
+ if(!emulate_rf){
+ if (itti_create_task (TASK_UDP, udp_eNB_task, NULL) < 0) {
+ LOG_E(UDP_, "Create task for UDP failed\n");
+ return -1;
+ }
+ }
+
+ if (itti_create_task (TASK_GTPV1_U, >pv1u_eNB_task, NULL) < 0) {
+ LOG_E(GTPU, "Create task for GTPV1U failed\n");
+ return -1;
+ }
+ }
+
+ # endif
+ */
+
+ if (gnb_nb > 0) {
+ LOG_I(NR_RRC,"Creating NR RRC gNB Task\n");
+
+ if (itti_create_task (TASK_RRC_GNB, rrc_gnb_task, NULL) < 0) {
+ LOG_E(NR_RRC, "Create task for NR RRC gNB failed\n");
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+
+static void get_options(void) {
+ int tddflag, nonbiotflag;
+ uint32_t online_log_messages;
+ uint32_t glog_level, glog_verbosity;
+ uint32_t start_telnetsrv;
+ paramdef_t cmdline_params[] =CMDLINE_PARAMS_DESC ;
+ paramdef_t cmdline_logparams[] =CMDLINE_LOGPARAMS_DESC ;
+ config_process_cmdline( cmdline_params,sizeof(cmdline_params)/sizeof(paramdef_t),NULL);
+
+ if (strlen(in_path) > 0) {
+ opt_type = OPT_PCAP;
+ opt_enabled=1;
+ printf("Enabling OPT for PCAP with the following file %s \n",in_path);
+ }
+
+ if (strlen(in_ip) > 0) {
+ opt_enabled=1;
+ opt_type = OPT_WIRESHARK;
+ printf("Enabling OPT for wireshark for local interface");
+ }
+
+ config_process_cmdline( cmdline_logparams,sizeof(cmdline_logparams)/sizeof(paramdef_t),NULL);
+
+ if(config_isparamset(cmdline_logparams,CMDLINE_ONLINELOG_IDX)) {
+ set_glog_onlinelog(online_log_messages);
+ }
+
+ if(config_isparamset(cmdline_logparams,CMDLINE_GLOGLEVEL_IDX)) {
+ set_glog(glog_level);
+ }
+
+ if (start_telnetsrv) {
+ load_module_shlib("telnetsrv",NULL,0,NULL);
+ }
+
+#if T_TRACER
+ 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)) ) {
+ memset((void *)&RC,0,sizeof(RC));
+ /* Read RC configuration file */
+ NRRCConfig();
+ NB_gNB_INST = RC.nb_nr_inst;
+ NB_RU = RC.nb_RU;
+ printf("Configuration: nb_rrc_inst %d, nb_nr_L1_inst %d, nb_ru %d\n",NB_gNB_INST,RC.nb_nr_L1_inst,NB_RU);
+ }
+
+ if(parallel_config != NULL) set_parallel_conf(parallel_config);
+
+ if(worker_config != NULL) set_worker_conf(worker_config);
+}
+
+
+#if T_TRACER
+ int T_nowait = 0; /* by default we wait for the tracer */
+ int T_port = 2021; /* default port to listen to to wait for the tracer */
+ int T_dont_fork = 0; /* default is to fork, see 'T_init' to understand */
+#endif
+
+
+
+void set_default_frame_parms(nfapi_nr_config_request_t *config[MAX_NUM_CCs], NR_DL_FRAME_PARMS *frame_parms[MAX_NUM_CCs]) {
+ int CC_id;
+
+ for (CC_id=0; CC_idsubframe_config.numerology_index_mu.value =1;
+ config[CC_id]->subframe_config.duplex_mode.value = 1; //FDD
+ config[CC_id]->subframe_config.dl_cyclic_prefix_type.value = 0; //NORMAL
+ config[CC_id]->rf_config.dl_carrier_bandwidth.value = 106;
+ config[CC_id]->rf_config.ul_carrier_bandwidth.value = 106;
+ config[CC_id]->sch_config.physical_cell_id.value = 0;
+ ///dl frequency to be filled in
+ /* //Set some default values that may be overwritten while reading options
+ frame_parms[CC_id]->frame_type = FDD;
+ frame_parms[CC_id]->tdd_config = 3;
+ frame_parms[CC_id]->tdd_config_S = 0;
+ frame_parms[CC_id]->N_RB_DL = 100;
+ frame_parms[CC_id]->N_RB_UL = 100;
+ frame_parms[CC_id]->Ncp = NORMAL;
+ frame_parms[CC_id]->Ncp_UL = NORMAL;
+ frame_parms[CC_id]->Nid_cell = 0;
+ frame_parms[CC_id]->num_MBSFN_config = 0;
+ frame_parms[CC_id]->nb_antenna_ports_eNB = 1;
+ frame_parms[CC_id]->nb_antennas_tx = 1;
+ frame_parms[CC_id]->nb_antennas_rx = 1;
+
+ frame_parms[CC_id]->nushift = 0;
+
+ frame_parms[CC_id]->phich_config_common.phich_resource = oneSixth;
+ frame_parms[CC_id]->phich_config_common.phich_duration = normal;
+ // UL RS Config
+ frame_parms[CC_id]->pusch_config_common.ul_ReferenceSignalsPUSCH.cyclicShift = 0;//n_DMRS1 set to 0
+ frame_parms[CC_id]->pusch_config_common.ul_ReferenceSignalsPUSCH.groupHoppingEnabled = 0;
+ frame_parms[CC_id]->pusch_config_common.ul_ReferenceSignalsPUSCH.sequenceHoppingEnabled = 0;
+ frame_parms[CC_id]->pusch_config_common.ul_ReferenceSignalsPUSCH.groupAssignmentPUSCH = 0;
+
+ frame_parms[CC_id]->prach_config_common.rootSequenceIndex=22;
+ frame_parms[CC_id]->prach_config_common.prach_ConfigInfo.zeroCorrelationZoneConfig=1;
+ frame_parms[CC_id]->prach_config_common.prach_ConfigInfo.prach_ConfigIndex=0;
+ frame_parms[CC_id]->prach_config_common.prach_ConfigInfo.highSpeedFlag=0;
+ frame_parms[CC_id]->prach_config_common.prach_ConfigInfo.prach_FreqOffset=0;
+
+ // downlink_frequency[CC_id][0] = 2680000000; // Use float to avoid issue with frequency over 2^31.
+ // downlink_frequency[CC_id][1] = downlink_frequency[CC_id][0];
+ // downlink_frequency[CC_id][2] = downlink_frequency[CC_id][0];
+ // downlink_frequency[CC_id][3] = downlink_frequency[CC_id][0];
+ //printf("Downlink for CC_id %d frequency set to %u\n", CC_id, downlink_frequency[CC_id][0]);
+ frame_parms[CC_id]->dl_CarrierFreq=downlink_frequency[CC_id][0];
+ */
+ }
+}
+
+/*
+void init_openair0(void) {
+
+ int card;
+ int i;
+
+ for (card=0; cardrf_config.dl_carrier_bandwidth.value == 100) {
+ if (frame_parms[0]->threequarter_fs) {
+ openair0_cfg[card].sample_rate=23.04e6;
+ openair0_cfg[card].samples_per_frame = 230400;
+ openair0_cfg[card].tx_bw = 10e6;
+ openair0_cfg[card].rx_bw = 10e6;
+ } else {
+ openair0_cfg[card].sample_rate=30.72e6;
+ openair0_cfg[card].samples_per_frame = 307200;
+ openair0_cfg[card].tx_bw = 10e6;
+ openair0_cfg[card].rx_bw = 10e6;
+ }
+ } else if(config[0]->rf_config.dl_carrier_bandwidth.value == 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 (config[0]->rf_config.dl_carrier_bandwidth.value == 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 (config[0]->rf_config.dl_carrier_bandwidth.value == 6) {
+ openair0_cfg[card].sample_rate=1.92e6;
+ openair0_cfg[card].samples_per_frame = 19200;
+ openair0_cfg[card].tx_bw = 1.5e6;
+ openair0_cfg[card].rx_bw = 1.5e6;
+ }
+
+
+ if (config[0]->subframe_config.duplex_mode.value==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,
+ RC.gNB[0][0]->gNB_config.rf_config.tx_antenna_ports.value,
+ RC.gNB[0][0]->gNB_config.rf_config.tx_antenna_ports.value );
+ openair0_cfg[card].Mod_id = 0;
+
+ openair0_cfg[card].num_rb_dl=config[0]->rf_config.dl_carrier_bandwidth.value;
+
+ openair0_cfg[card].clock_source = clock_source;
+
+
+ openair0_cfg[card].tx_num_channels=min(2,RC.gNB[0][0]->gNB_config.rf_config.tx_antenna_ports.value );
+ openair0_cfg[card].rx_num_channels=min(2,RC.gNB[0][0]->gNB_config.rf_config.tx_antenna_ports.value );
+
+ for (i=0; i<4; i++) {
+
+ if (irx_total_gain_dB;
+
+
+ openair0_cfg[card].configFilename = rf_config_file;
+ printf("Card %d, channel %d, Setting tx_gain %f, rx_gain %f, tx_freq %f, rx_freq %f\n",
+ card,i, openair0_cfg[card].tx_gain[i],
+ openair0_cfg[card].rx_gain[i],
+ openair0_cfg[card].tx_freq[i],
+ openair0_cfg[card].rx_freq[i]);
+ }
+ } // for loop on cards
+}
+*/
+
+void wait_RUs(void) {
+ LOG_I(PHY,"Waiting for RUs to be configured ... RC.ru_mask:%02lx\n", RC.ru_mask);
+ // 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);
+ printf("RC.ru_mask:%02lx\n", RC.ru_mask);
+ }
+
+ pthread_mutex_unlock(&RC.ru_mutex);
+ LOG_I(PHY,"RUs configured\n");
+}
+
+void wait_gNBs(void) {
+ int i,j;
+ int waiting=1;
+
+ while (waiting==1) {
+ printf("Waiting for gNB L1 instances to all get configured ... sleeping 50ms (nb_nr_sL1_inst %d)\n",RC.nb_nr_L1_inst);
+ usleep(50*1000);
+ waiting=0;
+
+ for (i=0; iconfigured==0) {
+ waiting=1;
+ break;
+ }
+ }
+ }
+ }
+
+ printf("gNB L1 are configured\n");
+}
+
+#if defined(ENABLE_ITTI)
+/*
+ * helper function to terminate a certain ITTI task
+ */
+void terminate_task(task_id_t task_id, module_id_t mod_id) {
+ LOG_I(ENB_APP, "sending TERMINATE_MESSAGE to task %s (%d)\n", itti_get_task_name(task_id), task_id);
+ MessageDef *msg;
+ msg = itti_alloc_new_message (ENB_APP, TERMINATE_MESSAGE);
+ itti_send_msg_to_task (task_id, ENB_MODULE_ID_TO_INSTANCE(mod_id), msg);
+}
+
+//extern void free_transport(PHY_VARS_gNB *);
+extern void nr_phy_free_RU(RU_t *);
+
+int stop_L1L2(module_id_t gnb_id) {
+ LOG_W(ENB_APP, "stopping nr-softmodem\n");
+ oai_exit = 1;
+
+ if (!RC.ru) {
+ LOG_F(ENB_APP, "no RU configured\n");
+ return -1;
+ }
+
+ /* stop trx devices, multiple carrier currently not supported by RU */
+ if (RC.ru[gnb_id]) {
+ if (RC.ru[gnb_id]->rfdevice.trx_stop_func) {
+ RC.ru[gnb_id]->rfdevice.trx_stop_func(&RC.ru[gnb_id]->rfdevice);
+ LOG_I(ENB_APP, "turned off RU rfdevice\n");
+ } else {
+ LOG_W(ENB_APP, "can not turn off rfdevice due to missing trx_stop_func callback, proceding anyway!\n");
+ }
+
+ if (RC.ru[gnb_id]->ifdevice.trx_stop_func) {
+ RC.ru[gnb_id]->ifdevice.trx_stop_func(&RC.ru[gnb_id]->ifdevice);
+ LOG_I(ENB_APP, "turned off RU ifdevice\n");
+ } else {
+ LOG_W(ENB_APP, "can not turn off ifdevice due to missing trx_stop_func callback, proceding anyway!\n");
+ }
+ } else {
+ LOG_W(ENB_APP, "no RU found for index %d\n", gnb_id);
+ return -1;
+ }
+
+ /* these tasks need to pick up new configuration */
+ terminate_task(TASK_RRC_ENB, gnb_id);
+ terminate_task(TASK_L2L1, gnb_id);
+ LOG_I(ENB_APP, "calling kill_gNB_proc() for instance %d\n", gnb_id);
+ kill_gNB_proc(gnb_id);
+ LOG_I(ENB_APP, "calling kill_RU_proc() for instance %d\n", gnb_id);
+ kill_RU_proc(gnb_id);
+ oai_exit = 0;
+
+ for (int cc_id = 0; cc_id < RC.nb_nr_CC[gnb_id]; cc_id++) {
+ //free_transport(RC.gNB[gnb_id][cc_id]);
+ phy_free_nr_gNB(RC.gNB[gnb_id][cc_id]);
+ }
+
+ nr_phy_free_RU(RC.ru[gnb_id]);
+ free_lte_top();
+ return 0;
+}
+
+/*
+ * Restart the nr-softmodem after it has been soft-stopped with stop_L1L2()
+ */
+int restart_L1L2(module_id_t gnb_id) {
+ RU_t *ru = RC.ru[gnb_id];
+ int cc_id;
+ MessageDef *msg_p = NULL;
+ LOG_W(ENB_APP, "restarting nr-softmodem\n");
+ /* block threads */
+ sync_var = -1;
+
+ for (cc_id = 0; cc_id < RC.nb_nr_L1_CC[gnb_id]; cc_id++) {
+ RC.gNB[gnb_id][cc_id]->configured = 0;
+ }
+
+ RC.ru_mask |= (1 << ru->idx);
+ /* copy the changed frame parameters to the RU */
+ /* TODO this should be done for all RUs associated to this gNB */
+ memcpy(&ru->nr_frame_parms, &RC.gNB[gnb_id][0]->frame_parms, sizeof(NR_DL_FRAME_PARMS));
+ set_function_spec_param(RC.ru[gnb_id]);
+ LOG_I(ENB_APP, "attempting to create ITTI tasks\n");
+
+ if (itti_create_task (TASK_RRC_ENB, rrc_enb_task, NULL) < 0) {
+ LOG_E(RRC, "Create task for RRC eNB failed\n");
+ return -1;
+ } else {
+ LOG_I(RRC, "Re-created task for RRC gNB successfully\n");
+ }
+
+ if (itti_create_task (TASK_L2L1, l2l1_task, NULL) < 0) {
+ LOG_E(PDCP, "Create task for L2L1 failed\n");
+ return -1;
+ } else {
+ LOG_I(PDCP, "Re-created task for L2L1 successfully\n");
+ }
+
+ /* pass a reconfiguration request which will configure everything down to
+ * RC.eNB[i][j]->frame_parms, too */
+ msg_p = itti_alloc_new_message(TASK_ENB_APP, RRC_CONFIGURATION_REQ);
+ RRC_CONFIGURATION_REQ(msg_p) = RC.rrc[gnb_id]->configuration;
+ itti_send_msg_to_task(TASK_RRC_ENB, ENB_MODULE_ID_TO_INSTANCE(gnb_id), msg_p);
+ /* TODO XForms might need to be restarted, but it is currently (09/02/18)
+ * broken, so we cannot test it */
+ wait_gNBs();
+ init_RU_proc(ru);
+ ru->rf_map.card = 0;
+ ru->rf_map.chain = 0; /* CC_id + chain_offset;*/
+ wait_RUs();
+ init_eNB_afterRU();
+ 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);
+ return 0;
+}
+#endif
+
+static void wait_nfapi_init(char *thread_name) {
+ printf( "waiting for NFAPI PNF connection and population of global structure (%s)\n",thread_name);
+ pthread_mutex_lock( &nfapi_sync_mutex );
+
+ while (nfapi_sync_var<0)
+ pthread_cond_wait( &nfapi_sync_cond, &nfapi_sync_mutex );
+
+ pthread_mutex_unlock(&nfapi_sync_mutex);
+ printf( "NFAPI: got sync (%s)\n", thread_name);
+}
+
+int main( int argc, char **argv ) {
+ int i;
+#if defined (XFORMS)
+ //void *status;
+#endif
+ int CC_id;
+ int ru_id;
+#if defined (XFORMS)
+ int ret;
+#endif
+ start_background_system();
+
+ ///static configuration for NR at the moment
+ if ( load_configmodule(argc,argv) == NULL) {
+ exit_fun("[SOFTMODEM] Error, configuration module init failed\n");
+ }
+
+#ifdef DEBUG_CONSOLE
+ setvbuf(stdout, NULL, _IONBF, 0);
+ setvbuf(stderr, NULL, _IONBF, 0);
+#endif
+ mode = normal_txrx;
+ memset(&openair0_cfg[0],0,sizeof(openair0_config_t)*MAX_CARDS);
+ memset(tx_max_power,0,sizeof(int)*MAX_NUM_CCs);
+ configure_linux();
+ logInit();
+ printf("Reading in command-line options\n");
+ get_options ();
+
+ if (CONFIG_ISFLAGSET(CONFIG_ABORT) ) {
+ fprintf(stderr,"Getting configuration failed\n");
+ exit(-1);
+ }
+
+#if T_TRACER
+ T_Config_Init();
+#endif
+ //randominit (0);
+ set_taus_seed (0);
+ printf("configuring for RAU/RRU\n");
+
+ if (opp_enabled ==1) {
+ reset_opp_meas();
+ }
+
+ cpuf=get_cpu_freq_GHz();
+#if defined(ENABLE_ITTI)
+ itti_init(TASK_MAX, THREAD_MAX, MESSAGES_ID_MAX, tasks_info, messages_info);
+ // initialize mscgen log after ITTI
+ MSC_INIT(MSC_E_UTRAN, THREAD_MAX+TASK_MAX);
+#endif
+
+ if (opt_type != OPT_NONE) {
+ if (init_opt(in_path, in_ip) == -1)
+ LOG_E(OPT,"failed to run OPT \n");
+ }
+
+#ifdef PDCP_USE_NETLINK
+ netlink_init();
+#if defined(PDCP_USE_NETLINK_QUEUES)
+ pdcp_netlink_init();
+#endif
+#endif
+#if !defined(ENABLE_ITTI)
+ // to make a graceful exit when ctrl-c is pressed
+ signal(SIGSEGV, signal_handler);
+ signal(SIGINT, signal_handler);
+#endif
+#ifndef PACKAGE_VERSION
+# define PACKAGE_VERSION "UNKNOWN-EXPERIMENTAL"
+#endif
+ LOG_I(HW, "Version: %s\n", PACKAGE_VERSION);
+#if defined(ENABLE_ITTI)
+
+ if (RC.nb_nr_inst > 0) {
+ // don't create if node doesn't connect to RRC/S1/GTP
+ AssertFatal(create_gNB_tasks(1) == 0,"cannot create ITTI tasks\n");
+ } else {
+ printf("No ITTI, Initializing L1\n");
+ RCconfig_L1();
+ }
+
+#endif
+ /* Start the agent. If it is turned off in the configuration, it won't start */
+ RCconfig_nr_flexran();
+
+ for (i = 0; i < RC.nb_nr_L1_inst; i++) {
+ flexran_agent_start(i);
+ }
+
+ // 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);
+ mlockall(MCL_CURRENT | MCL_FUTURE);
+ pthread_cond_init(&sync_cond,NULL);
+ pthread_mutex_init(&sync_mutex, NULL);
+#ifdef XFORMS
+ int UE_id;
+
+ if (do_forms==1) {
+ fl_initialize (&argc, argv, NULL, 0, 0);
+ form_stats_l2 = create_form_stats_form();
+ fl_show_form (form_stats_l2->stats_form, FL_PLACE_HOTSPOT, FL_FULLBORDER, "l2 stats");
+ form_stats = create_form_stats_form();
+ fl_show_form (form_stats->stats_form, FL_PLACE_HOTSPOT, FL_FULLBORDER, "stats");
+
+ for(UE_id=0; UE_idphy_scope_gnb, FL_PLACE_HOTSPOT, FL_FULLBORDER, title);
+
+ if (otg_enabled) {
+ fl_set_button(form_gnb[CC_id][UE_id]->button_0,1);
+ fl_set_object_label(form_gnb[CC_id][UE_id]->button_0,"DL Traffic ON");
+ } else {
+ fl_set_button(form_gnb[CC_id][UE_id]->button_0,0);
+ fl_set_object_label(form_gnb[CC_id][UE_id]->button_0,"DL Traffic OFF");
+ }
+ } // CC_id
+ } // UE_id
+
+ threadCreate(&forms_thread, scope_thread, NULL, "scope", -1, OAI_PRIORITY_RT_LOW);
+ printf("Scope thread created, ret=%d\n",ret);
+ }
+
+#endif
+ usleep(10*1000);
+
+ if (nfapi_mode) {
+ printf("NFAPI*** - mutex and cond created - will block shortly for completion of PNF connection\n");
+ pthread_cond_init(&sync_cond,NULL);
+ pthread_mutex_init(&sync_mutex, NULL);
+ }
+
+ const char *nfapi_mode_str = "";
+
+ switch(nfapi_mode) {
+ case 0:
+ nfapi_mode_str = "MONOLITHIC";
+ break;
+
+ case 1:
+ nfapi_mode_str = "PNF";
+ break;
+
+ case 2:
+ nfapi_mode_str = "VNF";
+ break;
+
+ default:
+ nfapi_mode_str = "";
+ break;
+ }
+
+ printf("NFAPI MODE:%s\n", nfapi_mode_str);
+
+ if (nfapi_mode==2) // VNF
+ wait_nfapi_init("main?");
+
+ printf("START MAIN THREADS\n");
+ // start the main threads
+ number_of_cards = 1;
+ printf("RC.nb_nr_L1_inst:%d\n", RC.nb_nr_L1_inst);
+
+ if (RC.nb_nr_L1_inst > 0) {
+ printf("Initializing gNB threads single_thread_flag:%d wait_for_sync:%d\n", single_thread_flag,wait_for_sync);
+ init_gNB(single_thread_flag,wait_for_sync);
+ }
+
+ printf("wait_gNBs()\n");
+ wait_gNBs();
+ printf("About to Init RU threads RC.nb_RU:%d\n", RC.nb_RU);
+
+ if (RC.nb_RU >0) {
+ printf("Initializing RU threads\n");
+ init_RU(rf_config_file);
+
+ for (ru_id=0; ru_idrf_map.card=0;
+ RC.ru[ru_id]->rf_map.chain=CC_id+chain_offset;
+ }
+ }
+
+ config_sync_var=0;
+
+ if (nfapi_mode==1) { // PNF
+ wait_nfapi_init("main?");
+ }
+
+ printf("wait RUs\n");
+ wait_RUs();
+ printf("ALL RUs READY!\n");
+ printf("RC.nb_RU:%d\n", RC.nb_RU);
+ // once all RUs are ready initialize the rest of the gNBs ((dependence on final RU parameters after configuration)
+ printf("ALL RUs ready - init gNBs\n");
+
+ if (nfapi_mode != 1 && nfapi_mode != 2) {
+ printf("Not NFAPI mode - call init_eNB_afterRU()\n");
+ init_eNB_afterRU();
+ } else {
+ printf("NFAPI mode - DO NOT call init_gNB_afterRU()\n");
+ }
+
+ printf("ALL RUs ready - ALL gNBs ready\n");
+ // connect the TX/RX buffers
+ 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__);
+ // wait for end of program
+ printf("TYPE TO TERMINATE\n");
+ //getchar();
+#if defined(ENABLE_ITTI)
+ printf("Entering ITTI signals handler\n");
+ itti_wait_tasks_end();
+ printf("Returned from ITTI signal handler\n");
+ oai_exit=1;
+ printf("oai_exit=%d\n",oai_exit);
+#else
+
+ while (oai_exit==0)
+ sleep(1);
+
+ printf("Terminating application - oai_exit=%d\n",oai_exit);
+#endif
+ // stop threads
+#ifdef XFORMS
+ /*
+ printf("waiting for XFORMS thread\n");
+
+ if (do_forms==1) {
+ pthread_join(forms_thread,&status);
+ fl_hide_form(form_stats->stats_form);
+ fl_free_form(form_stats->stats_form);
+
+ fl_hide_form(form_stats_l2->stats_form);
+ fl_free_form(form_stats_l2->stats_form);
+
+ for(UE_id=0; UE_idphy_scope_gNB);
+ fl_free_form(form_enb[CC_id][UE_id]->phy_scope_gNB);
+ }
+ }
+ }
+ */
+#endif
+ printf("stopping MODEM threads\n");
+ // cleanup
+ stop_gNB(NB_gNB_INST);
+ stop_RU(NB_RU);
+
+ /* release memory used by the RU/gNB threads (incomplete), after all
+ * threads have been stopped (they partially use the same memory) */
+ for (int inst = 0; inst < NB_gNB_INST; inst++) {
+ for (int cc_id = 0; cc_id < RC.nb_nr_CC[inst]; cc_id++) {
+ //free_transport(RC.gNB[inst][cc_id]);
+ phy_free_nr_gNB(RC.gNB[inst][cc_id]);
+ }
+ }
+
+ for (int inst = 0; inst < NB_RU; inst++) {
+ nr_phy_free_RU(RC.ru[inst]);
+ }
+
+ free_lte_top();
+ pthread_cond_destroy(&sync_cond);
+ pthread_mutex_destroy(&sync_mutex);
+ pthread_cond_destroy(&nfapi_sync_cond);
+ pthread_mutex_destroy(&nfapi_sync_mutex);
+ pthread_mutex_destroy(&ue_pf_po_mutex);
+
+ // *** Handle per CC_id openair0
+
+ for(ru_id=0; ru_idrfdevice.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)
+ RC.ru[ru_id]->ifdevice.trx_end_func(&RC.ru[ru_id]->ifdevice);
+ }
+
+ if (opt_enabled == 1)
+ terminate_opt();
+
+ logClean();
+ printf("Bye.\n");
+ return 0;
+}
diff --git a/executables/nr-softmodem.h b/executables/nr-softmodem.h
new file mode 100644
index 0000000000..b01d92e6ed
--- /dev/null
+++ b/executables/nr-softmodem.h
@@ -0,0 +1,240 @@
+#ifndef NR_SOFTMODEM_H
+#define NR_SOFTMODEM_H
+
+#define _GNU_SOURCE
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include "targets/ARCH/COMMON/common_lib.h"
+#undef MALLOC
+#include "assertions.h"
+#include "msc.h"
+#include "PHY/types.h"
+
+#include "flexran_agent.h"
+#include "PHY/defs_gNB.h"
+
+#if defined(ENABLE_ITTI)
+ #if defined(ENABLE_USE_MME)
+ #include "s1ap_eNB.h"
+ #ifdef PDCP_USE_NETLINK
+ #include "SIMULATION/ETH_TRANSPORT/proto.h"
+ #endif
+ #endif
+#endif
+
+/* help strings definition for command line options, used in CMDLINE_XXX_DESC macros and printed when -h option is used */
+#define CONFIG_HLP_RFCFGF "Configuration file for front-end (e.g. LMS7002M)\n"
+#define CONFIG_HLP_ULMAXE "set the eNodeB max ULSCH erros\n"
+#define CONFIG_HLP_CALUER "set UE RX calibration\n"
+#define CONFIG_HLP_CALUERM ""
+#define CONFIG_HLP_CALUERB ""
+#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_UERXG "set UE RX gain\n"
+#define CONFIG_HLP_UERXGOFF "external UE amplifier offset\n"
+#define CONFIG_HLP_UETXG "set UE TX gain\n"
+#define CONFIG_HLP_UENANTR "set UE number of rx antennas\n"
+#define CONFIG_HLP_UENANTT "set UE number of tx antennas\n"
+#define CONFIG_HLP_UESCAN "set UE to scan around carrier\n"
+#define CONFIG_HLP_DUMPFRAME "dump UE received frame to rxsig_frame0.dat and exit\n"
+#define CONFIG_HLP_DLSHIFT "dynamic shift for LLR compuation for TM3/4 (default 0)\n"
+#define CONFIG_HLP_UELOOP "get softmodem (UE) to loop through memory instead of acquiring from HW\n"
+#define CONFIG_HLP_PHYTST "test UE phy layer, mac disabled\n"
+#define CONFIG_HLP_DMAMAP "sets flag for improved EXMIMO UE performance\n"
+#define CONFIG_HLP_EXCCLK "tells hardware to use an external clock reference\n"
+#define CONFIG_HLP_USIM "use XOR autentication algo in case of test usim mode\n"
+#define CONFIG_HLP_NOSNGLT "Disables single-thread mode in lte-softmodem\n"
+#define CONFIG_HLP_TADV "Set timing_advance\n"
+#define CONFIG_HLP_DLF "Set the downlink frequency for all component carriers\n"
+#define CONFIG_HLP_CHOFF "Channel id offset\n"
+#define CONFIG_HLP_SOFTS "Enable soft scope and L1 and L2 stats (Xforms)\n"
+#define CONFIG_HLP_EXMCAL "Calibrate the EXMIMO borad, available files: exmimo2_2arxg.lime exmimo2_2brxg.lime \n"
+#define CONFIG_HLP_ITTIL "Generate ITTI analyzser logs (similar to wireshark logs but with more details)\n"
+#define CONFIG_HLP_DLMCS "Set the maximum downlink MCS\n"
+#define CONFIG_HLP_STMON "Enable processing timing measurement of lte softmodem on per subframe basis \n"
+#define CONFIG_HLP_PRB "Set the PRB, valid values: 6, 25, 50, 100 \n"
+#define CONFIG_HLP_MSLOTS "Skip the missed slots/subframes \n"
+#define CONFIG_HLP_ULMCS "Set the maximum uplink MCS\n"
+#define CONFIG_HLP_TDD "Set hardware to TDD mode (default: FDD). Used only with -U (otherwise set in config file).\n"
+#define CONFIG_HLP_UE "Set the lte softmodem as a UE\n"
+#define CONFIG_HLP_L2MONW "Enable L2 wireshark messages on localhost \n"
+#define CONFIG_HLP_L2MONP "Enable L2 pcap messages on localhost \n"
+#define CONFIG_HLP_VCD "Enable VCD (generated file will is named openair_dump_eNB.vcd, read it with target/RT/USER/eNB.gtkw\n"
+#define CONFIG_HLP_TQFS "Apply three-quarter of sampling frequency, 23.04 Msps to reduce the data rate on USB/PCIe transfers (only valid for 20 MHz)\n"
+#define CONFIG_HLP_TPORT "tracer port\n"
+#define CONFIG_HLP_NOTWAIT "don't wait for tracer, start immediately\n"
+#define CONFIG_HLP_TNOFORK "to ease debugging with gdb\n"
+#define CONFIG_HLP_DISABLNBIOT "disable nb-iot, even if defined in config\n"
+
+#define CONFIG_HLP_NUMEROLOGY "adding numerology for 5G\n"
+#define CONFIG_HLP_EMULATE_RF "Emulated RF enabled(disable by defult)\n"
+#define CONFIG_HLP_PARALLEL_CMD "three config for level of parallelism 'PARALLEL_SINGLE_THREAD', 'PARALLEL_RU_L1_SPLIT', or 'PARALLEL_RU_L1_TRX_SPLIT'\n"
+#define CONFIG_HLP_WORKER_CMD "two option for worker 'WORKER_DISABLE' or 'WORKER_ENABLE'\n"
+
+/***************************************************************************************************************************************/
+/* command line options definitions, CMDLINE_XXXX_DESC macros are used to initialize paramdef_t arrays which are then used as argument
+ when calling config_get or config_getlist functions */
+
+
+/*------------------------------------------------------------------------------------------------------------------------------------------*/
+/* command line parameters defining UE running mode */
+/* optname helpstr paramflags XXXptr defXXXval type numelt */
+/*------------------------------------------------------------------------------------------------------------------------------------------*/
+#define CMDLINE_UEMODEPARAMS_DESC { \
+ {"calib-ue-rx", CONFIG_HLP_CALUER, 0, iptr:&rx_input_level_dBm, defintval:0, TYPE_INT, 0}, \
+ {"calib-ue-rx-med", CONFIG_HLP_CALUERM, 0, iptr:&rx_input_level_dBm, defintval:0, TYPE_INT, 0}, \
+ {"calib-ue-rx-byp", CONFIG_HLP_CALUERB, 0, iptr:&rx_input_level_dBm, defintval:0, TYPE_INT, 0}, \
+ {"debug-ue-prach", CONFIG_HLP_DBGUEPR, PARAMFLAG_BOOL, uptr:NULL, defuintval:1, TYPE_INT, 0}, \
+ {"no-L2-connect", CONFIG_HLP_NOL2CN, PARAMFLAG_BOOL, uptr:NULL, defuintval:1, TYPE_INT, 0}, \
+ {"calib-prach-tx", CONFIG_HLP_CALPRACH, PARAMFLAG_BOOL, uptr:NULL, defuintval:1, TYPE_INT, 0}, \
+ {"loop-memory", CONFIG_HLP_UELOOP, 0, strptr:&loopfile, defstrval:"iqs.in", TYPE_STRING,0}, \
+ {"ue-dump-frame", CONFIG_HLP_DUMPFRAME, PARAMFLAG_BOOL, iptr:&dumpframe, defintval:0, TYPE_INT, 0}, \
+ }
+#define CMDLINE_CALIBUERX_IDX 0
+#define CMDLINE_CALIBUERXMED_IDX 1
+#define CMDLINE_CALIBUERXBYP_IDX 2
+#define CMDLINE_DEBUGUEPRACH_IDX 3
+#define CMDLINE_NOL2CONNECT_IDX 4
+#define CMDLINE_CALIBPRACHTX_IDX 5
+#define CMDLINE_MEMLOOP_IDX 6
+#define CMDLINE_DUMPMEMORY_IDX 7
+/*------------------------------------------------------------------------------------------------------------------------------------------*/
+
+
+#define DEFAULT_DLF 2680000000
+
+/*---------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
+/* command line parameters common to eNodeB and UE */
+/* optname helpstr paramflags XXXptr defXXXval type numelt */
+/*---------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
+#define CMDLINE_PARAMS_DESC { \
+ {"rf-config-file", CONFIG_HLP_RFCFGF, 0, strptr:(char **)&rf_config_file, defstrval:NULL, TYPE_STRING, sizeof(rf_config_file)}, \
+ {"ulsch-max-errors", CONFIG_HLP_ULMAXE, 0, uptr:&ULSCH_max_consecutive_errors, defuintval:0, TYPE_UINT, 0}, \
+ {"phy-test", CONFIG_HLP_PHYTST, PARAMFLAG_BOOL, iptr:&phy_test, defintval:0, TYPE_INT, 0}, \
+ {"usim-test", CONFIG_HLP_USIM, PARAMFLAG_BOOL, u8ptr:&usim_test, defintval:0, TYPE_UINT8, 0}, \
+ {"mmapped-dma", CONFIG_HLP_DMAMAP, PARAMFLAG_BOOL, uptr:&mmapped_dma, defintval:0, TYPE_INT, 0}, \
+ {"external-clock", CONFIG_HLP_EXCCLK, PARAMFLAG_BOOL, uptr:&clock_source, defintval:0, TYPE_INT, 0}, \
+ {"wait-for-sync", NULL, PARAMFLAG_BOOL, iptr:&wait_for_sync, defintval:0, TYPE_INT, 0}, \
+ {"single-thread-disable", CONFIG_HLP_NOSNGLT, PARAMFLAG_BOOL, iptr:&single_thread_flag, defintval:1, TYPE_INT, 0}, \
+ {"A" , CONFIG_HLP_TADV, 0, uptr:&timing_advance, defintval:0, TYPE_UINT, 0}, \
+ {"C" , CONFIG_HLP_DLF, 0, uptr:&(downlink_frequency[0][0]), defuintval:DEFAULT_DLF, TYPE_UINT, 0}, \
+ {"a" , CONFIG_HLP_CHOFF, 0, iptr:&chain_offset, defintval:0, TYPE_INT, 0}, \
+ {"d" , CONFIG_HLP_SOFTS, PARAMFLAG_BOOL, uptr:(uint32_t *)&do_forms, defintval:0, TYPE_INT8, 0}, \
+ {"E" , CONFIG_HLP_TQFS, PARAMFLAG_BOOL, i8ptr:&threequarter_fs, defintval:0, TYPE_INT8, 0}, \
+ {"K" , CONFIG_HLP_ITTIL, PARAMFLAG_NOFREE, strptr:&itti_dump_file, defstrval:"/tmp/itti.dump", TYPE_STRING, 0}, \
+ {"m" , CONFIG_HLP_DLMCS, 0, uptr:&target_dl_mcs, defintval:0, TYPE_UINT, 0}, \
+ {"t" , CONFIG_HLP_ULMCS, 0, uptr:&target_ul_mcs, defintval:0, TYPE_UINT, 0}, \
+ {"W" , CONFIG_HLP_L2MONW, 0, strptr:(char **)&in_ip, defstrval:"127.0.0.1", TYPE_STRING, sizeof(in_ip)}, \
+ {"P" , CONFIG_HLP_L2MONP, 0, strptr:(char **)&in_path, defstrval:"/tmp/oai_opt.pcap", TYPE_STRING, sizeof(in_path)}, \
+ {"q" , CONFIG_HLP_STMON, PARAMFLAG_BOOL, iptr:&opp_enabled, defintval:0, TYPE_INT, 0}, \
+ {"S" , CONFIG_HLP_MSLOTS, PARAMFLAG_BOOL, u8ptr:&exit_missed_slots, defintval:1, TYPE_UINT8, 0}, \
+ {"T" , CONFIG_HLP_TDD, PARAMFLAG_BOOL, iptr:&tddflag, defintval:0, TYPE_INT, 0}, {"numerology" , CONFIG_HLP_NUMEROLOGY, PARAMFLAG_BOOL, iptr:&numerology, defintval:0, TYPE_INT, 0}, \
+ {"emulate-rf" , CONFIG_HLP_EMULATE_RF, PARAMFLAG_BOOL, iptr:&emulate_rf, defintval:0, TYPE_INT, 0}, \
+ {"parallel-config", CONFIG_HLP_PARALLEL_CMD,0, strptr:(char **)¶llel_config, defstrval:NULL, TYPE_STRING, 0}, \
+ {"worker-config", CONFIG_HLP_WORKER_CMD, 0, strptr:(char **)&worker_config, defstrval:NULL, TYPE_STRING, 0}, \
+ {"nbiot-disable", CONFIG_HLP_DISABLNBIOT,PARAMFLAG_BOOL, iptr:&nonbiotflag, defintval:0, TYPE_INT, 0} \
+ }
+
+#define CONFIG_HLP_FLOG "Enable online log \n"
+#define CONFIG_HLP_LOGL "Set the global log level, valide options: (9:trace, 8/7:debug, 6:info, 4:warn, 3:error)\n"
+#define CONFIG_HLP_LOGV "Set the global log verbosity \n"
+#define CONFIG_HLP_TELN "Start embedded telnet server \n"
+/*---------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
+/* command line parameters for LOG utility */
+/* optname helpstr paramflags XXXptr defXXXval type numelt */
+/*---------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
+#define CMDLINE_LOGPARAMS_DESC { \
+ {"R" , CONFIG_HLP_FLOG, 0, uptr:&online_log_messages, defintval:1, TYPE_INT, 0}, \
+ {"g" , CONFIG_HLP_LOGL, 0, uptr:&glog_level, defintval:0, TYPE_UINT, 0}, \
+ {"G" , CONFIG_HLP_LOGV, 0, uptr:&glog_verbosity, defintval:0, TYPE_UINT16, 0}, \
+ {"telnetsrv", CONFIG_HLP_TELN, PARAMFLAG_BOOL, uptr:&start_telnetsrv, defintval:0, TYPE_UINT, 0}, \
+ }
+#define CMDLINE_ONLINELOG_IDX 0
+#define CMDLINE_GLOGLEVEL_IDX 1
+#define CMDLINE_GLOGVERBO_IDX 2
+#define CMDLINE_STARTTELN_IDX 3
+
+
+typedef struct {
+ int *argc;
+ char **argv;
+} scopeParms_t;
+
+extern int T_port;
+extern int T_nowait;
+extern int T_dont_fork;
+
+
+/***************************************************************************************************************************************/
+/* */
+extern pthread_cond_t sync_cond;
+extern pthread_mutex_t sync_mutex;
+extern int sync_var;
+
+
+extern uint32_t downlink_frequency[MAX_NUM_CCs][4];
+extern int32_t uplink_frequency_offset[MAX_NUM_CCs][4];
+
+extern int rx_input_level_dBm;
+extern uint8_t exit_missed_slots;
+extern uint64_t num_missed_slots; // counter for the number of missed slots
+
+extern int oaisim_flag;
+extern volatile int oai_exit;
+
+extern openair0_config_t openair0_cfg[MAX_CARDS];
+extern pthread_cond_t sync_cond;
+extern pthread_mutex_t sync_mutex;
+extern int sync_var;
+extern int transmission_mode;
+extern double cpuf;
+
+#if defined(ENABLE_ITTI)
+ extern volatile int start_gNB;
+#endif
+
+#include "threads_t.h"
+extern threads_t threads;
+
+// In nr-gnb.c
+extern void init_gNB(int single_thread_flag,int wait_for_sync);
+extern void stop_gNB(int);
+extern void kill_gNB_proc(int inst);
+
+// In nr-ru.c
+extern void init_RU(const char *);
+extern void init_RU_proc(RU_t *ru);
+extern void stop_RU(int nb_ru);
+extern void kill_RU_proc(int inst);
+extern void set_function_spec_param(RU_t *ru);
+
+extern void reset_opp_meas(void);
+extern void print_opp_meas(void);
+
+extern void init_fep_thread(PHY_VARS_gNB *);
+
+void init_gNB_afterRU(void);
+
+extern int stop_L1L2(module_id_t gnb_id);
+extern int restart_L1L2(module_id_t gnb_id);
+
+#endif
+
diff --git a/executables/nr-ue.c b/executables/nr-ue.c
index 19b462d770..bf0dc9809a 100644
--- a/executables/nr-ue.c
+++ b/executables/nr-ue.c
@@ -43,6 +43,7 @@
#include "PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h"
#include "common/utils/LOG/log.h"
+#include "common/utils/system.h"
#include "common/utils/LOG/vcd_signal_dumper.h"
#include "T.h"
@@ -123,7 +124,6 @@ extern double cpuf;
#define FRAME_PERIOD 100000000ULL
#define DAQ_PERIOD 66667ULL
-#define FIFO_PRIORITY 40
typedef enum {
pss=0,
@@ -156,7 +156,7 @@ PHY_VARS_NR_UE *init_nr_ue_vars(NR_DL_FRAME_PARMS *frame_parms,
*/
typedef struct syncData_s {
- UE_nr_rxtx_proc_t *proc;
+ UE_nr_rxtx_proc_t proc;
PHY_VARS_NR_UE *UE;
} syncData_t;
@@ -239,7 +239,7 @@ static void UE_synch(void *arg) {
case pbch:
LOG_I(PHY, "[UE thread Synch] Running Initial Synch (mode %d)\n",UE->mode);
- if (nr_initial_sync( syncD->proc, UE, UE->mode ) == 0) {
+ if (nr_initial_sync( &syncD->proc, UE, UE->mode ) == 0) {
freq_offset = UE->common_vars.freq_offset; // frequency offset computed with pss in initial sync
hw_slot_offset = (UE->rx_offset<<1) / UE->frame_parms.samples_per_slot;
LOG_I(PHY,"Got synch: hw_slot_offset %d, carrier off %d Hz, rxgain %d (DL %u, UL %u), UE_scan_carrier %d\n",
@@ -375,7 +375,9 @@ void processSubframeRX( PHY_VARS_NR_UE *UE, UE_nr_rxtx_proc_t *proc) {
#ifdef UE_SLOT_PARALLELISATION
phy_procedures_slot_parallelization_nrUE_RX( UE, proc, 0, 0, 1, UE->mode, no_relay, NULL );
#else
+ uint64_t a=rdtsc();
phy_procedures_nrUE_RX( UE, proc, 0, 1, UE->mode);
+ LOG_D(PHY,"phy_procedures_nrUE_RX: slot:%d, time %lu\n", proc->nr_tti_rx, (rdtsc()-a)/3500);
// printf(">>> nr_ue_pdcch_procedures ended\n");
#endif
}
@@ -530,10 +532,12 @@ int computeSamplesShift(PHY_VARS_NR_UE *UE) {
//LOG_I(PHY,"!!!adjusting +1 samples!!!\n");
return 1;
}
+
return 0;
}
void *UE_thread(void *arg) {
+ //this thread should be over the processing thread to keep in real time
PHY_VARS_NR_UE *UE = (PHY_VARS_NR_UE *) arg;
// int tx_enabled = 0;
openair0_timestamp timestamp;
@@ -547,40 +551,45 @@ void *UE_thread(void *arg) {
initNotifiedFIFO(&nf);
int nbSlotProcessing=0;
int thread_idx=0;
- notifiedFIFO_elt_t *processingMsg[RX_NB_TH];
+ notifiedFIFO_t freeBlocks;
+ initNotifiedFIFO_nothreadSafe(&freeBlocks);
- for (int i=0; iUE=UE;
- }
+ for (int i=0; iUE=UE;
- syncD->proc=&((processingData_t *)NotifiedFifoData(processingMsg[0]))->proc;
const int nb_slot_frame = 10*UE->frame_parms.slots_per_subframe;
- int absolute_slot, decoded_frame_rx=INT_MAX, trashed_frames=0;
+ int absolute_slot=0, decoded_frame_rx=INT_MAX, trashed_frames=0;
while (!oai_exit) {
- if (!syncD->UE->is_synchronized) {
- if (syncRunning) {
- notifiedFIFO_elt_t *res=tryPullTpool(&nf, Tpool);
+ if (syncRunning) {
+ notifiedFIFO_elt_t *res=tryPullTpool(&nf, Tpool);
- if (res) {
- syncRunning=false;
- } else {
- trashFrame(UE, ×tamp);
- trashed_frames++;
- }
+ if (res) {
+ syncRunning=false;
+ syncData_t *tmp=(syncData_t *)NotifiedFifoData(res);
+ // shift the frame index with all the frames we trashed meanwhile we perform the synch search
+ decoded_frame_rx=(tmp->proc.decoded_frame_rx+trashed_frames) % MAX_FRAME_NUMBER;
+ delNotifiedFIFO_elt(res);
} else {
- readFrame(UE, ×tamp);
- pushTpool(Tpool, syncMsg);
- trashed_frames=0;
- syncRunning=true;
+ trashFrame(UE, ×tamp);
+ trashed_frames++;
+ continue;
}
+ }
+ AssertFatal( !syncRunning, "At this point synchronisation can't be running\n");
+
+ if (!UE->is_synchronized) {
+ readFrame(UE, ×tamp);
+ notifiedFIFO_elt_t *Msg=newNotifiedFIFO_elt(sizeof(syncData_t),0,&nf,UE_synch);
+ syncData_t *syncMsg=(syncData_t *)NotifiedFifoData(Msg);
+ syncMsg->UE=UE;
+ memset(&syncMsg->proc, 0, sizeof(syncMsg->proc));
+ pushTpool(Tpool, Msg);
+ trashed_frames=0;
+ syncRunning=true;
continue;
}
@@ -598,29 +607,32 @@ void *UE_thread(void *arg) {
UE->frame_parms.nb_antennas_rx),"");
// we have the decoded frame index in the return of the synch process
// and we shifted above to the first slot of next frame
- // the synch thread proc context is hard linked to regular processing thread context, thread id = 0
- UE_nr_rxtx_proc_t *proc=&(((processingData_t *)NotifiedFifoData(processingMsg[0]))->proc);
- // shift the frame index with all the frames we trashed meanwhile we perform the synch search
- proc->decoded_frame_rx=(proc->decoded_frame_rx + trashed_frames) % MAX_FRAME_NUMBER;
- decoded_frame_rx=proc->decoded_frame_rx;
- // we do ++ first in the regular processing, so it will be 0;
+ decoded_frame_rx++;
+ // we do ++ first in the regular processing, so it will be beging of frame;
absolute_slot=decoded_frame_rx*nb_slot_frame + nb_slot_frame -1;
continue;
}
absolute_slot++;
+ // whatever means thread_idx
+ // Fix me: will be wrong when slot 1 is slow, as slot 2 finishes
+ // Slot 3 will overlap if RX_NB_TH is 2
+ // this is general failure in UE !!!
thread_idx = absolute_slot % RX_NB_TH;
int slot_nr = absolute_slot % nb_slot_frame;
- UE_nr_rxtx_proc_t *proc=&(((processingData_t *)NotifiedFifoData(processingMsg[thread_idx]))->proc);
+ notifiedFIFO_elt_t *msgToPush;
+ AssertFatal((msgToPush=pullNotifiedFIFO_nothreadSafe(&freeBlocks)) != NULL,"chained list failure");
+ processingData_t *curMsg=(processingData_t *)NotifiedFifoData(msgToPush);
+ curMsg->UE=UE;
// update thread index for received subframe
- proc->nr_tti_rx= slot_nr;
- UE->current_thread_id[slot_nr] = thread_idx;
- proc->subframe_rx=table_sf_slot[slot_nr];
- proc->nr_tti_tx = (absolute_slot + DURATION_RX_TO_TX) % nb_slot_frame;
- proc->subframe_tx=proc->nr_tti_rx;
- proc->frame_rx = ( absolute_slot/nb_slot_frame ) % MAX_FRAME_NUMBER;
- proc->frame_tx = ( (absolute_slot + DURATION_RX_TO_TX) /nb_slot_frame ) % MAX_FRAME_NUMBER;
- proc->decoded_frame_rx=-1;
+ curMsg->proc.nr_tti_rx= slot_nr;
+ curMsg->UE->current_thread_id[slot_nr] = thread_idx;
+ curMsg->proc.subframe_rx=table_sf_slot[slot_nr];
+ curMsg->proc.nr_tti_tx = (absolute_slot + DURATION_RX_TO_TX) % nb_slot_frame;
+ curMsg->proc.subframe_tx=curMsg->proc.nr_tti_rx;
+ curMsg->proc.frame_rx = ( absolute_slot/nb_slot_frame ) % MAX_FRAME_NUMBER;
+ curMsg->proc.frame_tx = ( (absolute_slot + DURATION_RX_TO_TX) /nb_slot_frame ) % MAX_FRAME_NUMBER;
+ curMsg->proc.decoded_frame_rx=-1;
LOG_D(PHY,"Process slot %d thread Idx %d \n", slot_nr, thread_idx);
for (int i=0; iframe_parms.nb_antennas_rx; i++)
@@ -629,7 +641,7 @@ void *UE_thread(void *arg) {
slot_nr*UE->frame_parms.samples_per_slot];
for (int i=0; iframe_parms.nb_antennas_tx; i++)
- txp[i] = (void *)&UE->common_vars.txdata[i][proc->nr_tti_tx*UE->frame_parms.samples_per_slot];
+ txp[i] = (void *)&UE->common_vars.txdata[i][curMsg->proc.nr_tti_tx*UE->frame_parms.samples_per_slot];
int readBlockSize, writeBlockSize;
@@ -678,41 +690,47 @@ void *UE_thread(void *arg) {
LOG_E(PHY,"can't compensate: diff =%d\n", first_symbols);
}
- proc->timestamp_tx = timestamp+
- (DURATION_RX_TO_TX*UE->frame_parms.samples_per_slot)-
- UE->frame_parms.ofdm_symbol_size-UE->frame_parms.nb_prefix_samples0;
+ curMsg->proc.timestamp_tx = timestamp+
+ (DURATION_RX_TO_TX*UE->frame_parms.samples_per_slot)-
+ UE->frame_parms.ofdm_symbol_size-UE->frame_parms.nb_prefix_samples0;
notifiedFIFO_elt_t *res;
+ while (nbSlotProcessing >= RX_NB_TH) {
+ if ( (res=tryPullTpool(&nf, Tpool)) != NULL ) {
+ nbSlotProcessing--;
+ processingData_t *tmp=(processingData_t *)res->msgData;
+
+ if (tmp->proc.decoded_frame_rx != -1)
+ decoded_frame_rx=tmp->proc.decoded_frame_rx;
+
+ pushNotifiedFIFO_nothreadSafe(&freeBlocks,res);
+ }
+
+ usleep(200);
+ }
+
+ if ( decoded_frame_rx != curMsg->proc.frame_rx &&
+ ((decoded_frame_rx+1) % MAX_FRAME_NUMBER) != curMsg->proc.frame_rx )
+ LOG_D(PHY,"Decoded frame index (%d) is not compatible with current context (%d), UE should go back to synch mode\n",
+ decoded_frame_rx, curMsg->proc.frame_rx );
+
+ nbSlotProcessing++;
+ msgToPush->key=slot_nr;
+ pushTpool(Tpool, msgToPush);
+
if (getenv("RFSIMULATOR")) {
// FixMe: Wait previous thread is done, because race conditions seems too bad
// in case of actual RF board, the overlap between threads mitigate the issue
// We must receive one message, that proves the slot processing is done
- while ((res=tryPullTpool(&nf, Tpool)) == NULL)
- usleep(200);
-
- nbSlotProcessing--;
- processingData_t *tmp=(processingData_t *)res->msgData;
-
- if (tmp->proc.decoded_frame_rx != -1)
- decoded_frame_rx=tmp->proc.decoded_frame_rx;
- }
-
- while (nbSlotProcessing >= RX_NB_TH && (res=tryPullTpool(&nf, Tpool)) != NULL ) {
+ res=pullTpool(&nf, Tpool);
nbSlotProcessing--;
processingData_t *tmp=(processingData_t *)res->msgData;
if (tmp->proc.decoded_frame_rx != -1)
decoded_frame_rx=tmp->proc.decoded_frame_rx;
- usleep(200);
+ pushNotifiedFIFO_nothreadSafe(&freeBlocks,res);
}
-
- if ( decoded_frame_rx != proc->frame_rx &&
- ((decoded_frame_rx+1) % MAX_FRAME_NUMBER) != proc->frame_rx )
- LOG_D(PHY,"Decoded frame index (%d) is not compatible with current context (%d), UE should go back to synch mode\n",
- decoded_frame_rx, proc->frame_rx);
-
- pushTpool(Tpool, processingMsg[thread_idx]);
} // while !oai_exit
return NULL;
@@ -722,14 +740,6 @@ void init_UE(int nb_inst) {
int inst;
NR_UE_MAC_INST_t *mac_inst;
pthread_t threads[nb_inst];
- pthread_attr_t attr;
- pthread_attr_init(&attr);
- pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
- pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED);
- pthread_attr_setschedpolicy(&attr, SCHED_RR);
- struct sched_param sched;
- sched.sched_priority = sched_get_priority_max(SCHED_RR)-1;
- pthread_attr_setschedparam(&attr, &sched);
for (inst=0; inst < nb_inst; inst++) {
PHY_VARS_NR_UE *UE = PHY_vars_UE_g[inst][0];
@@ -738,25 +748,19 @@ void init_UE(int nb_inst) {
nr_l2_init_ue();
mac_inst = get_mac_inst(inst);
mac_inst->if_module = UE->if_inst;
-
// Initial bandwidth part configuration -- full carrier bandwidth
mac_inst->initial_bwp_dl.bwp_id = 0;
mac_inst->initial_bwp_dl.location = 0;
mac_inst->initial_bwp_dl.scs = UE->frame_parms.subcarrier_spacing;
mac_inst->initial_bwp_dl.N_RB = UE->frame_parms.N_RB_DL;
mac_inst->initial_bwp_dl.cyclic_prefix = UE->frame_parms.Ncp;
-
mac_inst->initial_bwp_ul.bwp_id = 0;
mac_inst->initial_bwp_ul.location = 0;
mac_inst->initial_bwp_ul.scs = UE->frame_parms.subcarrier_spacing;
mac_inst->initial_bwp_ul.N_RB = UE->frame_parms.N_RB_UL;
mac_inst->initial_bwp_ul.cyclic_prefix = UE->frame_parms.Ncp;
-
LOG_I(PHY,"Intializing UE Threads for instance %d (%p,%p)...\n",inst,PHY_vars_UE_g[inst],PHY_vars_UE_g[inst][0]);
- AssertFatal(0 == pthread_create(&threads[inst],
- &attr,
- UE_thread,
- (void *)UE), "");
+ threadCreate(&threads[inst], UE_thread, (void *)UE, "UEthread", -1, OAI_PRIORITY_RT_MAX);
}
printf("UE threads created by %ld\n", gettid());
diff --git a/executables/nr-uesoftmodem.c b/executables/nr-uesoftmodem.c
index 24f8d4eb0d..8300f10675 100644
--- a/executables/nr-uesoftmodem.c
+++ b/executables/nr-uesoftmodem.c
@@ -64,7 +64,6 @@ unsigned short config_frames[4] = {2,9,11,13};
#endif
#include "intertask_interface.h"
-#include "create_tasks.h"
#include "PHY/INIT/phy_init.h"
#include "system.h"
@@ -98,11 +97,11 @@ extern FD_stats_form *create_form_stats_form( void );
//#include "stats.h"
// current status is that every UE has a DL scope for a SINGLE eNB (eNB_id=0)
// at eNB 0, an UL scope for every UE
-FD_lte_phy_scope_ue *form_ue[NUMBER_OF_UE_MAX];
+FD_phy_scope_nrue *form_nrue[NUMBER_OF_UE_MAX];
//FD_lte_phy_scope_enb *form_enb[MAX_NUM_CCs][NUMBER_OF_UE_MAX];
//FD_stats_form *form_stats=NULL,*form_stats_l2=NULL;
char title[255];
-//unsigned char scope_enb_num_ue = 2;
+unsigned char scope_enb_num_ue = 2;
static pthread_t forms_thread; //xforms
#endif //XFORMS
#include
@@ -311,15 +310,10 @@ void reset_stats(FL_OBJECT *button, long arg) {
}
static void *scope_thread(void *arg) {
- struct sched_param sched_param;
- sched_param.sched_priority = sched_get_priority_min(SCHED_FIFO)+1;
- sched_setscheduler(0, SCHED_FIFO,&sched_param);
- printf("Scope thread has priority %d\n",sched_param.sched_priority);
- //wait the modem is runnign
sleep(5);
while (!oai_exit) {
- phy_scope_UE(form_ue[0],
+ phy_scope_nrUE(form_nrue[0],
PHY_vars_UE_g[0][0],
0,0,1);
usleep(100*1000);
@@ -331,24 +325,16 @@ static void *scope_thread(void *arg) {
void init_scope(void) {
#ifdef XFORMS
- int ret;
int fl_argc=1;
if (do_forms==1) {
char *name="5G-UE-scope";
fl_initialize (&fl_argc, &name, NULL, 0, 0);
int UE_id = 0;
- form_ue[UE_id] = create_lte_phy_scope_ue();
+ form_nrue[UE_id] = create_phy_scope_nrue();
sprintf (title, "NR DL SCOPE UE");
- fl_show_form (form_ue[UE_id]->lte_phy_scope_ue, FL_PLACE_HOTSPOT, FL_FULLBORDER, title);
- fl_set_button(form_ue[UE_id]->button_0,0);
- fl_set_object_label(form_ue[UE_id]->button_0, "IA Receiver OFF");
- ret = pthread_create(&forms_thread, NULL, scope_thread, NULL);
-
- if (ret == 0)
- pthread_setname_np( forms_thread, "xforms" );
-
- printf("Scope thread created, ret=%d\n",ret);
+ fl_show_form (form_nrue[UE_id]->phy_scope_nrue, FL_PLACE_HOTSPOT, FL_FULLBORDER, title);
+ threadCreate(&forms_thread, scope_thread, NULL, "scope", -1, OAI_PRIORITY_RT_LOW);
}
#endif
@@ -541,7 +527,6 @@ void set_default_frame_parms(NR_DL_FRAME_PARMS *frame_parms[MAX_NUM_CCs]) {
frame_parms[CC_id]->nb_antennas_tx = 1;
frame_parms[CC_id]->nb_antennas_rx = 1;
//frame_parms[CC_id]->nushift = 0;
-
// NR: Init to legacy LTE 20Mhz params
frame_parms[CC_id]->numerology_index = 0;
frame_parms[CC_id]->ttis_per_subframe = 1;
@@ -685,7 +670,7 @@ int main( int argc, char **argv ) {
set_taus_seed (0);
tpool_t pool;
Tpool = &pool;
- char params[]="-1,-1,-1,-1";
+ char params[]="-1,-1";
initTpool(params, Tpool, false);
cpuf=get_cpu_freq_GHz();
itti_init(TASK_MAX, THREAD_MAX, MESSAGES_ID_MAX, tasks_info, messages_info);
@@ -712,9 +697,7 @@ int main( int argc, char **argv ) {
frame_parms[CC_id]->nb_antennas_rx = nb_antenna_rx;
frame_parms[CC_id]->nb_antenna_ports_eNB = 1; //initial value overwritten by initial sync later
LOG_I(PHY,"Set nb_rx_antenna %d , nb_tx_antenna %d \n",frame_parms[CC_id]->nb_antennas_rx, frame_parms[CC_id]->nb_antennas_tx);
-
get_band(downlink_frequency[CC_id][0], &frame_parms[CC_id]->eutra_band, &uplink_frequency_offset[CC_id][0], &frame_parms[CC_id]->frame_type);
-
}
NB_UE_INST=1;
@@ -766,6 +749,7 @@ int main( int argc, char **argv ) {
// 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);
+ configure_linux();
mlockall(MCL_CURRENT | MCL_FUTURE);
init_scope();
number_of_cards = 1;
diff --git a/executables/nr-uesoftmodem.h b/executables/nr-uesoftmodem.h
index 8bc07936f6..078a8066c3 100644
--- a/executables/nr-uesoftmodem.h
+++ b/executables/nr-uesoftmodem.h
@@ -236,7 +236,6 @@ extern double cpuf;
extern int setup_ue_buffers(PHY_VARS_NR_UE **phy_vars_ue, openair0_config_t *openair0_cfg);
extern void fill_ue_band_info(void);
extern void init_UE(int);
-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);
extern void print_opp_meas(void);
void *UE_thread(void *arg);
diff --git a/executables/openairinterface5g_limits.h b/executables/openairinterface5g_limits.h
new file mode 100644
index 0000000000..ca29078758
--- /dev/null
+++ b/executables/openairinterface5g_limits.h
@@ -0,0 +1,89 @@
+#ifndef OPENAIRINTERFACE5G_LIMITS_H_
+#define OPENAIRINTERFACE5G_LIMITS_H_
+
+#if 1 /*defined(CBMIMO1) || defined(EXMIMO) || defined(OAI_USRP) || defined(OAI_LMSSDR) || defined(OAI_ADRV9371_ZC706)*/
+ #define NUMBER_OF_eNB_MAX 1
+ #define NUMBER_OF_gNB_MAX 1
+ #define NUMBER_OF_RU_MAX 2
+ #define NUMBER_OF_NR_RU_MAX 2
+ #ifndef PHYSIM
+ #ifndef UE_EXPANSION
+ #define NUMBER_OF_UE_MAX 4
+ #define NUMBER_OF_NR_UE_MAX 4
+ #define NUMBER_OF_CONNECTED_eNB_MAX 1
+ #define NUMBER_OF_CONNECTED_gNB_MAX 1
+ #else
+ #define NUMBER_OF_UE_MAX 256
+ #define NUMBER_OF_NR_UE_MAX 256
+ #define NUMBER_OF_CONNECTED_eNB_MAX 1
+ #define NUMBER_OF_CONNECTED_gNB_MAX 1
+ #endif
+ #else
+ #define NUMBER_OF_UE_MAX 1
+ #define NUMBER_OF_NR_UE_MAX 1
+ #define NUMBER_OF_CONNECTED_eNB_MAX 1
+ #define NUMBER_OF_CONNECTED_gNB_MAX 1
+ #endif
+#else
+ #define NUMBER_OF_eNB_MAX 7
+ #define NUMBER_OF_gNB_MAX 7
+ #define NUMBER_OF_RU_MAX 32
+ #define NUMBER_OF_NR_RU_MAX 32
+ #ifndef UE_EXPANSION
+ #define NUMBER_OF_UE_MAX 20
+ #define NUMBER_OF_NR_UE_MAX 20
+ #define NUMBER_OF_CONNECTED_eNB_MAX 3
+ #define NUMBER_OF_CONNECTED_gNB_MAX 3
+ #else
+ #define NUMBER_OF_UE_MAX 256
+ #define NUMBER_OF_NR_UE_MAX 256
+ #define NUMBER_OF_CONNECTED_eNB_MAX 1
+ #define NUMBER_OF_CONNECTED_gNB_MAX 1
+ #endif
+ #if defined(STANDALONE) && STANDALONE==1
+ #undef NUMBER_OF_eNB_MAX
+ #undef NUMBER_OF_gNB_MAX
+
+ #undef NUMBER_OF_UE_MAX
+ #undef NUMBER_OF_NR_UE_MAX
+
+ #undef NUMBER_OF_RU_MAX
+ #undef NUMBER_OF_NR_RU_MAX
+
+ #define NUMBER_OF_eNB_MAX 3
+ #define NUMBER_OF_gNB_MAX 3
+
+ #define NUMBER_OF_UE_MAX 3
+ #define NUMBER_OF_NR_UE_MAX 3
+
+ #define NUMBER_OF_RU_MAX 3
+ #define NUMBER_OF_NR_RU_MAX 3
+ #endif
+ #if defined(LARGE_SCALE) && LARGE_SCALE
+ #undef NUMBER_OF_eNB_MAX
+ #undef NUMBER_OF_gNB_MAX
+
+ #undef NUMBER_OF_UE_MAX
+ #undef NUMBER_OF_NR_UE_MAX
+
+ #undef NUMBER_OF_CONNECTED_eNB_MAX
+ #undef NUMBER_OF_CONNECTED_gNB_MAX
+
+ #undef NUMBER_OF_RU_MAX
+ #undef NUMBER_OF_NR_RU_MAX
+
+ #define NUMBER_OF_eNB_MAX 2
+ #define NUMBER_OF_gNB_MAX 2
+
+ #define NUMBER_OF_UE_MAX 120
+ #define NUMBER_OF_NR_UE_MAX 120
+
+ #define NUMBER_OF_RU_MAX 16
+ #define NUMBER_OF_NR_RU_MAX 16
+
+ #define NUMBER_OF_CONNECTED_eNB_MAX 1 // to save some memory
+ #define NUMBER_OF_CONNECTED_gNB_MAX 1
+ #endif
+#endif
+
+#endif /* OPENAIRINTERFACE5G_LIMITS_H_ */
diff --git a/executables/stats.h b/executables/stats.h
new file mode 100644
index 0000000000..6c847a2860
--- /dev/null
+++ b/executables/stats.h
@@ -0,0 +1,46 @@
+/*
+ * 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
+ */
+
+/* Header file generated by fdesign on Thu Aug 28 12:13:51 2014 */
+
+#ifndef FD_stats_form_h_
+#define FD_stats_form_h_
+
+#include
+
+/* Callbacks, globals and object handlers */
+
+extern void reset_stats( FL_OBJECT *, long );
+
+/* Forms and Objects */
+
+typedef struct {
+ FL_FORM *stats_form;
+ void *vdata;
+ char *cdata;
+ long ldata;
+ FL_OBJECT *stats_text;
+ FL_OBJECT *stats_button;
+} FD_stats_form;
+
+extern FD_stats_form *create_form_stats_form( void );
+
+#endif /* FD_stats_form_h_ */
diff --git a/executables/threads_t.h b/executables/threads_t.h
new file mode 100644
index 0000000000..0671f40988
--- /dev/null
+++ b/executables/threads_t.h
@@ -0,0 +1,21 @@
+#ifndef _THREADS_T_H_
+#define _THREADS_T_H_
+
+typedef struct threads_s {
+ int main;
+ int sync;
+ int one;
+ int two;
+ int three;
+ int slot1_proc_one;
+ int slot1_proc_two;
+ int slot1_proc_three;
+ //int dlsch_td_one;
+ //int dlsch_td_two;
+ //int dlsch_td_three;
+ //int dlsch_td1_one;
+ //int dlsch_td1_two;
+ //int dlsch_td1_three;
+} threads_t;
+
+#endif /* _THREADS_T_H_ */
diff --git a/openair1/PHY/CODING/nr_polar_init.c b/openair1/PHY/CODING/nr_polar_init.c
index f158d44303..efc78d91fd 100644
--- a/openair1/PHY/CODING/nr_polar_init.c
+++ b/openair1/PHY/CODING/nr_polar_init.c
@@ -53,7 +53,7 @@ static void nr_polar_init(t_nrPolar_params * *polarParams,
// printf("currentPtr %p (polarParams %p)\n",currentPtr,polarParams);
//Else, initialize and add node to the end of the linked list.
- t_nrPolar_params *newPolarInitNode = malloc(sizeof(t_nrPolar_params));
+ t_nrPolar_params *newPolarInitNode = calloc(sizeof(t_nrPolar_params),1);
if (newPolarInitNode != NULL) {
newPolarInitNode->idx = (messageType * messageLength * aggregation_prime);
diff --git a/openair1/PHY/INIT/nr_init_ue.c b/openair1/PHY/INIT/nr_init_ue.c
index f5f6ca1523..63aeba0480 100644
--- a/openair1/PHY/INIT/nr_init_ue.c
+++ b/openair1/PHY/INIT/nr_init_ue.c
@@ -369,7 +369,7 @@ void phy_config_harq_ue(module_id_t Mod_id,
for (num_of_threads=0;num_of_threadsulsch[eNB_id][num_of_threads][num_of_code_words]->Mlimit = max_harq_tx;
+ phy_vars_ue->ulsch[num_of_threads][eNB_id][num_of_code_words]->Mlimit = max_harq_tx;
}
extern uint16_t beta_cqi[16];
diff --git a/openair1/PHY/LTE_TRANSPORT/dlsch_coding.c b/openair1/PHY/LTE_TRANSPORT/dlsch_coding.c
index b44a04eb74..0709cca69b 100644
--- a/openair1/PHY/LTE_TRANSPORT/dlsch_coding.c
+++ b/openair1/PHY/LTE_TRANSPORT/dlsch_coding.c
@@ -41,7 +41,6 @@
#include "common/utils/LOG/vcd_signal_dumper.h"
#include "common/utils/LOG/log.h"
#include
-#include "targets/RT/USER/rt_wrapper.h"
//#define DEBUG_DLSCH_CODING
//#define DEBUG_DLSCH_FREE 1
@@ -329,11 +328,6 @@ int dlsch_encoding_2threads0(te_params *tep) {
extern int oai_exit;
void *te_thread(void *param) {
- cpu_set_t cpuset;
- CPU_ZERO(&cpuset);
- thread_top_init("te_thread",1,200000,250000,500000);
- pthread_setname_np( pthread_self(),"te processing");
- LOG_I(PHY,"thread te created id=%ld\n", syscall(__NR_gettid));
te_params *tep = (te_params *)param;
//wait_sync("te_thread");
diff --git a/openair1/PHY/LTE_TRANSPORT/ulsch_decoding.c b/openair1/PHY/LTE_TRANSPORT/ulsch_decoding.c
index 1dcbec0664..6d16c5fb0e 100644
--- a/openair1/PHY/LTE_TRANSPORT/ulsch_decoding.c
+++ b/openair1/PHY/LTE_TRANSPORT/ulsch_decoding.c
@@ -42,7 +42,6 @@
#include "common/utils/LOG/vcd_signal_dumper.h"
//#define DEBUG_ULSCH_DECODING
-#include "targets/RT/USER/rt_wrapper.h"
#include "transport_proto.h"
extern WORKER_CONF_t get_thread_worker_conf(void);
@@ -356,9 +355,7 @@ extern int oai_exit;
void *td_thread(void *param) {
PHY_VARS_eNB *eNB = ((td_params *)param)->eNB;
L1_proc_t *proc = &eNB->proc;
- cpu_set_t cpuset;
- CPU_ZERO(&cpuset);
- thread_top_init("td_thread",1,200000,250000,500000);
+
pthread_setname_np( pthread_self(),"td processing");
LOG_I(PHY,"thread td created id=%ld\n", syscall(__NR_gettid));
//wait_sync("td_thread");
diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c
index a83242efaf..4bdc30540d 100644
--- a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c
+++ b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c
@@ -36,6 +36,7 @@
//#include "extern.h"
#include "PHY/sse_intrin.h"
#include "T.h"
+#include "openair1/PHY/NR_TRANSPORT/nr_dlsch.h"
#ifndef USER_MODE
#define NOCYGWIN_STATIC static
@@ -84,6 +85,20 @@ unsigned char offset_mumimo_llr_drange[29][3]={{8,8,8},{7,7,7},{7,7,7},{7,7,7},{
extern void print_shorts(char *s,int16_t *x);
+static void nr_dlsch_dual_stream_correlation_core(int **dl_ch_estimates_ext,
+ int **dl_ch_estimates_ext_i,
+ int **dl_ch_rho_ext,
+ unsigned char n_tx,
+ unsigned char n_rx,
+ unsigned char output_shift,
+ int length,
+ int start_point);
+
+static void nr_dlsch_layer_demapping(int16_t **llr_cw,
+ uint8_t Nl,
+ uint8_t mod_order,
+ uint16_t length,
+ int16_t **llr_layers);
int nr_rx_pdsch(PHY_VARS_NR_UE *ue,
PDSCH_t type,
@@ -112,7 +127,7 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue,
uint8_t slot = 0;
#endif
- unsigned char aatx,aarx;
+ unsigned char aatx=0,aarx=0;
unsigned short nb_rb = 0, round;
int avgs = 0;// rb;
@@ -993,10 +1008,10 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue,
if (rx_type==rx_IC_dual_stream) {
nr_dlsch_layer_demapping(pdsch_vars[eNB_id]->llr,
- dlsch[0]->harq_processes[harq_pid]->Nl,
- dlsch[0]->harq_processes[harq_pid]->Qm,
- dlsch[0]->harq_processes[harq_pid]->G,
- pdsch_vars[eNB_id]->layer_llr);
+ dlsch[0]->harq_processes[harq_pid]->Nl,
+ dlsch[0]->harq_processes[harq_pid]->Qm,
+ dlsch[0]->harq_processes[harq_pid]->G,
+ pdsch_vars[eNB_id]->layer_llr);
}
#if UE_TIMING_TRACE
@@ -2048,7 +2063,7 @@ void nr_dlsch_channel_level_median(int **dl_ch_estimates_ext,
}
-void nr_dlsch_dual_stream_correlation_core(int **dl_ch_estimates_ext,
+static void nr_dlsch_dual_stream_correlation_core(int **dl_ch_estimates_ext,
int **dl_ch_estimates_ext_i,
int **dl_ch_rho_ext,
unsigned char n_tx,
@@ -2156,7 +2171,7 @@ void nr_dlsch_detection_mrc_core(int **rxdataF_comp,
__m128i *rxdataF_comp128_0, *rxdataF_comp128_1, *rxdataF_comp128_2, *rxdataF_comp128_3;
__m128i *dl_ch_mag128_0, *dl_ch_mag128_1, *dl_ch_mag128_2, *dl_ch_mag128_3;
__m128i *dl_ch_mag128_0b, *dl_ch_mag128_1b, *dl_ch_mag128_2b, *dl_ch_mag128_3b;
- __m128i *rho128_0, *rho128_1, *rho128_2, *rho128_3;
+ __m128i *rho128_0, *rho128_1, *rho128_2=NULL, *rho128_3=NULL;
__m128i *rho128_i0, *rho128_i1, *rho128_i2, *rho128_i3;
int length_mod4 = 0;
int length2;
@@ -2458,7 +2473,7 @@ unsigned short nr_dlsch_extract_rbs_dual(int **rxdataF,
int prb,nb_rb=0;
unsigned short k;
int i,j,aarx;
- int32_t *dl_ch0,*dl_ch0p,*dl_ch0_ext,*dl_ch1,*dl_ch1p,*dl_ch1_ext,*rxF,*rxF_ext;
+ int32_t *dl_ch0=NULL,*dl_ch0p=NULL,*dl_ch0_ext=NULL,*dl_ch1=NULL,*dl_ch1p=NULL,*dl_ch1_ext=NULL,*rxF=NULL,*rxF_ext=NULL;
k = frame_parms->first_carrier_offset + 516; //0
@@ -2533,11 +2548,12 @@ unsigned short nr_dlsch_extract_rbs_dual(int **rxdataF,
return(nb_rb/frame_parms->nb_antennas_rx);
}
-void nr_dlsch_layer_demapping(int16_t **llr_cw,
- uint8_t Nl,
- uint8_t mod_order,
- uint16_t length,
- int16_t **llr_layers) {
+
+static void nr_dlsch_layer_demapping(int16_t **llr_cw,
+ uint8_t Nl,
+ uint8_t mod_order,
+ uint16_t length,
+ int16_t **llr_layers) {
switch (Nl) {
diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h b/openair1/PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h
index 4885c1c3e4..e7af632327 100644
--- a/openair1/PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h
+++ b/openair1/PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h
@@ -1803,21 +1803,6 @@ int nr_extract_dci_info(PHY_VARS_NR_UE *ue,
uint16_t n_RB_DLBWP,
uint16_t crc_scrambled_values[TOTAL_NBR_SCRAMBLED_VALUES]);
-void nr_dlsch_dual_stream_correlation_core(int **dl_ch_estimates_ext,
- int **dl_ch_estimates_ext_i,
- int **dl_ch_rho_ext,
- unsigned char n_tx,
- unsigned char n_rx,
- unsigned char output_shift,
- int length,
- int start_point);
-
-void nr_dlsch_layer_demapping(int16_t **llr_cw,
- uint8_t Nl,
- uint8_t mod_order,
- uint16_t length,
- int16_t **llr_layers);
-
/**@}*/
#endif
diff --git a/openair1/PHY/TOOLS/nr_phy_scope.c b/openair1/PHY/TOOLS/nr_phy_scope.c
index d1f1d1bea8..f8c0aad3f2 100644
--- a/openair1/PHY/TOOLS/nr_phy_scope.c
+++ b/openair1/PHY/TOOLS/nr_phy_scope.c
@@ -35,8 +35,6 @@ float tput_time_ue[NUMBER_OF_UE_MAX][TPUT_WINDOW_LENGTH] = {{0}};
float tput_ue[NUMBER_OF_UE_MAX][TPUT_WINDOW_LENGTH] = {{0}};
float tput_ue_max[NUMBER_OF_UE_MAX] = {0};
-extern int64_t *pss_corr_ue[3];
-
static void ia_receiver_on_off( FL_OBJECT *button, long arg)
{
@@ -66,14 +64,14 @@ static void dl_traffic_on_off( FL_OBJECT *button, long arg)
}
}
-FD_lte_phy_scope_enb *create_lte_phy_scope_enb( void )
+FD_phy_scope_gnb *create_phy_scope_gnb( void )
{
FL_OBJECT *obj;
- FD_lte_phy_scope_enb *fdui = fl_malloc( sizeof *fdui );
+ FD_phy_scope_gnb *fdui = fl_malloc( sizeof *fdui );
// Define form
- fdui->lte_phy_scope_enb = fl_bgn_form( FL_NO_BOX, 800, 800 );
+ fdui->phy_scope_gnb = fl_bgn_form( FL_NO_BOX, 800, 800 );
// This the whole UI box
obj = fl_add_box( FL_BORDER_BOX, 0, 0, 800, 800, "" );
@@ -146,19 +144,17 @@ FD_lte_phy_scope_enb *create_lte_phy_scope_enb( void )
fl_set_object_callback(fdui->button_0, dl_traffic_on_off, 0 );
fl_end_form( );
- fdui->lte_phy_scope_enb->fdui = fdui;
+ fdui->phy_scope_gnb->fdui = fdui;
return fdui;
}
-/*
-void phy_scope_eNB(FD_lte_phy_scope_enb *form,
- PHY_VARS_eNB *phy_vars_enb,
+void phy_scope_gNB(FD_phy_scope_gnb *form,
+ PHY_VARS_gNB *phy_vars_gnb,
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_gnb->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
@@ -180,16 +176,18 @@ 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;
- uint32_t total_dlsch_bitrate = phy_vars_enb->total_dlsch_bitrate;
+ uint32_t total_dlsch_bitrate = phy_vars_gnb->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
int Qm = 2;
+ if (!RC.nrmac[0]->UE_list.active[UE_id])
+ return;
+
// choose max MCS to compute coded_bits_per_codeword
- if (phy_vars_enb->ulsch[UE_id]!=NULL) {
+ if (phy_vars_gnb->ulsch[UE_id][0]!=NULL) {
for (harq_pid=0; harq_pid<3; harq_pid++) {
- Qm = cmax(phy_vars_enb->ulsch[UE_id]->harq_processes[harq_pid]->Qm,Qm);
+ //Qm = cmax(phy_vars_gnb->ulsch[UE_id][0]->harq_processes->Qm,Qm);
}
}
@@ -199,15 +197,15 @@ void phy_scope_eNB(FD_lte_phy_scope_enb *form,
llr = (float*) calloc(coded_bits_per_codeword,sizeof(float)); // init to zero
bit = malloc(coded_bits_per_codeword*sizeof(float));
- rxsig_t = (int16_t**) phy_vars_enb->common_vars.rxdata[eNB_id];
- //chest_t = (int16_t**) phy_vars_enb->pusch_vars[UE_id]->drs_ch_estimates_time[eNB_id];
- chest_t = (int16_t**) phy_vars_enb->srs_vars[UE_id].srs_ch_estimates[eNB_id];
- chest_f = (int16_t**) phy_vars_enb->pusch_vars[UE_id]->drs_ch_estimates[eNB_id];
- pusch_llr = (int16_t*) phy_vars_enb->pusch_vars[UE_id]->llr;
- pusch_comp = (int32_t*) phy_vars_enb->pusch_vars[UE_id]->rxdataF_comp[0];
- pucch1_comp = (int32_t*) phy_vars_enb->pucch1_stats[UE_id];
- pucch1_thres = (int32_t*) phy_vars_enb->pucch1_stats_thres[UE_id];
- pucch1ab_comp = (int32_t*) phy_vars_enb->pucch1ab_stats[UE_id];
+ rxsig_t = (int16_t**) phy_vars_gnb->common_vars.rxdata;
+ //chest_t = (int16_t**) phy_vars_gnb->pusch_vars[UE_id]->drs_ch_estimates_time[eNB_id];
+ chest_t = (int16_t**) phy_vars_gnb->srs_vars[UE_id].srs_ch_estimates;
+ chest_f = (int16_t**) phy_vars_gnb->pusch_vars[UE_id]->drs_ch_estimates;
+ pusch_llr = (int16_t*) phy_vars_gnb->pusch_vars[UE_id]->llr;
+ pusch_comp = (int32_t*) phy_vars_gnb->pusch_vars[UE_id]->rxdataF_comp;
+ pucch1_comp = (int32_t*) phy_vars_gnb->pucch1_stats[UE_id];
+ pucch1_thres = (int32_t*) phy_vars_gnb->pucch1_stats_thres[UE_id];
+ pucch1ab_comp = (int32_t*) phy_vars_gnb->pucch1ab_stats[UE_id];
// Received signal in time domain of receive antenna 0
if (rxsig_t != NULL) {
@@ -363,7 +361,7 @@ void phy_scope_eNB(FD_lte_phy_scope_enb *form,
memmove( tput_time_enb[UE_id], &tput_time_enb[UE_id][1], (TPUT_WINDOW_LENGTH-1)*sizeof(float) );
memmove( tput_enb[UE_id], &tput_enb[UE_id][1], (TPUT_WINDOW_LENGTH-1)*sizeof(float) );
- tput_time_enb[UE_id][TPUT_WINDOW_LENGTH-1] = (float) frame;
+ tput_time_enb[UE_id][TPUT_WINDOW_LENGTH-1] = (float) 0;
tput_enb[UE_id][TPUT_WINDOW_LENGTH-1] = ((float) total_dlsch_bitrate)/1000.0;
fl_set_xyplot_data(form->pusch_tput,tput_time_enb[UE_id],tput_enb[UE_id],TPUT_WINDOW_LENGTH,"","","");
@@ -377,16 +375,15 @@ void phy_scope_eNB(FD_lte_phy_scope_enb *form,
free(bit);
free(chest_f_abs);
}
-*/
-FD_lte_phy_scope_ue *create_lte_phy_scope_ue( void )
+FD_phy_scope_nrue *create_phy_scope_nrue( void )
{
FL_OBJECT *obj;
- FD_lte_phy_scope_ue *fdui = fl_malloc( sizeof *fdui );
+ FD_phy_scope_nrue *fdui = fl_malloc( sizeof *fdui );
// Define form
- fdui->lte_phy_scope_ue = fl_bgn_form( FL_NO_BOX, 800, 900 );
+ fdui->phy_scope_nrue = fl_bgn_form( FL_NO_BOX, 800, 900 );
// This the whole UI box
obj = fl_add_box( FL_BORDER_BOX, 0, 0, 800, 900, "" );
@@ -477,12 +474,12 @@ FD_lte_phy_scope_ue *create_lte_phy_scope_ue( void )
fl_hide_object(fdui->button_0);
fl_end_form( );
- fdui->lte_phy_scope_ue->fdui = fdui;
+ fdui->phy_scope_nrue->fdui = fdui;
return fdui;
}
-void phy_scope_UE(FD_lte_phy_scope_ue *form,
+void phy_scope_nrUE(FD_phy_scope_nrue *form,
PHY_VARS_NR_UE *phy_vars_ue,
int eNB_id,
int UE_id,
@@ -629,6 +626,7 @@ void phy_scope_UE(FD_lte_phy_scope_ue *form,
if (phy_vars_ue->is_synchronized==0) {
for (ind=0;ind<3;ind++) {
+ /*
if (pss_corr_ue[ind]) {
for (i=0; idlsch[i][0]->Mlimit; j++) {
+ phy_vars_gNB->UE_stats[i].dlsch_NAK[k][j]=0;
+ phy_vars_gNB->UE_stats[i].dlsch_ACK[k][j]=0;
+ phy_vars_gNB->UE_stats[i].dlsch_trials[k][j]=0;
+ }*/
+ phy_vars_gNB->UE_stats[i].dlsch_l2_errors[k]=0;
+ phy_vars_gNB->UE_stats[i].ulsch_errors[k]=0;
+ phy_vars_gNB->UE_stats[i].ulsch_consecutive_errors=0;
+ phy_vars_gNB->UE_stats[i].dlsch_sliding_cnt=0;
+ phy_vars_gNB->UE_stats[i].dlsch_NAK_round0=0;
+ phy_vars_gNB->UE_stats[i].dlsch_mcs_offset=0;
+ }
+ }
+}
+
+static FD_phy_scope_gnb *form_gnb[MAX_NUM_CCs][NUMBER_OF_UE_MAX];
+static void *scope_thread(void *arg) {
+ int ue_cnt=0;
+ while (!oai_exit) {
+ ue_cnt=0;
+
+ for(int UE_id=0; UE_idvdata = fdui->cdata = NULL;
+ fdui->ldata = 0;
+ fdui->stats_form = fl_bgn_form( FL_NO_BOX, 1115, 900 );
+ obj = fl_add_box( FL_UP_BOX, 0, 0, 1115, 900, "" );
+ //fdui->stats_text = obj = fl_add_text( FL_NORMAL_TEXT, 60, 50, 1000, 810, "test" );
+ //fl_set_object_lsize( obj, FL_TINY_SIZE );
+ fdui->stats_text = obj = fl_add_browser( FL_NORMAL_BROWSER, 60, 50, 1000, 810, "test" );
+ fl_set_browser_fontsize(obj,FL_TINY_SIZE);
+ fdui->stats_button = obj = fl_add_button( FL_PUSH_BUTTON, 60, 10, 130, 30, "Reset Stats" );
+ fl_set_object_lalign( obj, FL_ALIGN_CENTER );
+ fl_set_object_color( obj, FL_GREEN, FL_GREEN);
+ fl_end_form( );
+ fdui->stats_form->fdui = fdui;
+ return fdui;
+}
+
+void startScope(scopeParms_t * p) {
+ FD_stats_form *form_stats=NULL,*form_stats_l2=NULL;
+ char title[255];
+ fl_initialize (p->argc, p->argv, NULL, 0, 0);
+ form_stats_l2 = create_form_stats_form();
+ fl_show_form (form_stats_l2->stats_form, FL_PLACE_HOTSPOT, FL_FULLBORDER, "l2 stats");
+ form_stats = create_form_stats_form();
+ fl_show_form (form_stats->stats_form, FL_PLACE_HOTSPOT, FL_FULLBORDER, "stats");
+
+ for(int UE_id=0; UE_idphy_scope_gnb, FL_PLACE_HOTSPOT, FL_FULLBORDER, title);
+ } // CC_id
+ } // UE_id
+
+ pthread_t forms_thread;
+ threadCreate(&forms_thread, scope_thread, NULL, "scope", -1, OAI_PRIORITY_RT_LOW);
+}
diff --git a/openair1/PHY/TOOLS/nr_phy_scope.h b/openair1/PHY/TOOLS/nr_phy_scope.h
index eaf42bafab..9c161988a1 100644
--- a/openair1/PHY/TOOLS/nr_phy_scope.h
+++ b/openair1/PHY/TOOLS/nr_phy_scope.h
@@ -21,19 +21,24 @@
/* Header file generated by fdesign on Tue Nov 13 09:42:50 2012 */
-#ifndef FD_lte_scope_h_
-#define FD_lte_scope_h_
-
+#ifndef FD_nr_scope_h_
+#define FD_nr_scope_h_
+#include
+#include
+#include
+#include
+#include "common/ran_context.h"
+#include
+#include
#include
-//#include "PHY/defs_eNB.h"
-//#include "PHY/defs_UE.h"
+#include "PHY/defs_gNB.h"
+//#include "PHY/defs_nrUE.h"
//#include "PHY/impl_defs_top.h"
#include "PHY/defs_nr_UE.h"
-
/* Forms and Objects */
typedef struct {
- FL_FORM * lte_phy_scope_enb;
+ FL_FORM * phy_scope_gnb;
FL_OBJECT * rxsig_t;
FL_OBJECT * chest_f;
FL_OBJECT * chest_t;
@@ -43,10 +48,10 @@ typedef struct {
FL_OBJECT * pusch_llr;
FL_OBJECT * pusch_tput;
FL_OBJECT * button_0;
-} FD_lte_phy_scope_enb;
+} FD_phy_scope_gnb;
typedef struct {
- FL_FORM * lte_phy_scope_ue;
+ FL_FORM * phy_scope_nrue;
FL_OBJECT * rxsig_t;
FL_OBJECT * chest_f;
FL_OBJECT * chest_t;
@@ -61,24 +66,22 @@ typedef struct {
FL_OBJECT * pdsch_tput;
FL_OBJECT * button_0;
-} FD_lte_phy_scope_ue;
+} FD_phy_scope_nrue;
-FD_lte_phy_scope_enb * create_lte_phy_scope_enb( void );
-FD_lte_phy_scope_ue * create_lte_phy_scope_ue( void );
+extern unsigned char scope_enb_num_ue;
+FD_phy_scope_gnb * create_phy_scope_gnb( void );
+FD_phy_scope_nrue * create_phy_scope_nrue( void );
-/*
-void phy_scope_eNB(FD_lte_phy_scope_enb *form,
- PHY_VARS_gNB *phy_vars_enb,
+
+void phy_scope_gNB(FD_phy_scope_gnb *form,
+ PHY_VARS_gNB *phy_vars_gnb,
int UE_id);
-*/
-void phy_scope_UE(FD_lte_phy_scope_ue *form,
+
+void phy_scope_nrUE(FD_phy_scope_nrue *form,
PHY_VARS_NR_UE *phy_vars_ue,
int eNB_id,
int UE_id,
uint8_t subframe);
-
-
-
-
-#endif /* FD_lte_scope_h_ */
+extern RAN_CONTEXT_t RC;
+#endif
diff --git a/openair1/PHY/defs_L1_NB_IoT.h b/openair1/PHY/defs_L1_NB_IoT.h
index 6945bbe106..3ab8409c35 100644
--- a/openair1/PHY/defs_L1_NB_IoT.h
+++ b/openair1/PHY/defs_L1_NB_IoT.h
@@ -139,7 +139,7 @@ static inline void* malloc16_clear( size_t size )
#include
#include "targets/ARCH/COMMON/common_lib.h"
-#include "targets/COMMON/openairinterface5g_limits.h"
+#include "openairinterface5g_limits.h"
#define NUM_DCI_MAX_NB_IoT 32
diff --git a/openair1/PHY/defs_common.h b/openair1/PHY/defs_common.h
index 3e9ecc10bb..48981ddf1a 100644
--- a/openair1/PHY/defs_common.h
+++ b/openair1/PHY/defs_common.h
@@ -70,7 +70,7 @@
#include "TOOLS/tools_defs.h"
-#include "targets/COMMON/openairinterface5g_limits.h"
+#include "openairinterface5g_limits.h"
#include "common/utils/LOG/log.h"
#include "types.h"
diff --git a/openair1/PHY/defs_eNB.h b/openair1/PHY/defs_eNB.h
index cb4b635cb1..4d2ff771d0 100644
--- a/openair1/PHY/defs_eNB.h
+++ b/openair1/PHY/defs_eNB.h
@@ -497,8 +497,8 @@ typedef struct RRU_config_s {
#include
-#include "targets/ARCH/COMMON/common_lib.h"
-#include "targets/COMMON/openairinterface5g_limits.h"
+#include "common_lib.h"
+#include "openairinterface5g_limits.h"
#define NUMBER_OF_SUBBANDS_MAX 13
diff --git a/openair1/PHY/phy_extern.h b/openair1/PHY/phy_extern.h
index 623a4bb0c6..9baf8bf21d 100644
--- a/openair1/PHY/phy_extern.h
+++ b/openair1/PHY/phy_extern.h
@@ -40,16 +40,9 @@ extern int number_of_cards;
extern short conjugate[8],conjugate2[8];
-#ifndef OCP_FRAMEWORK
-//extern PHY_VARS_eNB ***PHY_vars_eNB_g;
-extern RAN_CONTEXT_t RC;
-extern LTE_DL_FRAME_PARMS *lte_frame_parms_g;
-#else
-#define MAX_UE 10
-#define MAX_eNB 20
-extern PHY_VARS_eNB * PHY_vars_eNB_g[MAX_eNB][MAX_NUM_CCs];
-#endif
+
+extern RAN_CONTEXT_t RC;
extern short primary_synch0[144];
extern short primary_synch1[144];
diff --git a/openair1/PHY/phy_extern_nr_ue.h b/openair1/PHY/phy_extern_nr_ue.h
index 66dbd82fc4..70fbd21ffa 100644
--- a/openair1/PHY/phy_extern_nr_ue.h
+++ b/openair1/PHY/phy_extern_nr_ue.h
@@ -38,15 +38,7 @@ extern short conjugate[8],conjugate2[8];
extern int number_of_cards;
-#ifndef OCP_FRAMEWORK
extern PHY_VARS_NR_UE ***PHY_vars_UE_g;
-extern NR_DL_FRAME_PARMS *lte_frame_parms_g;
-#else
-#define MAX_UE 10
-#define MAX_eNB 20
-
-extern PHY_VARS_NR_UE * PHY_vars_UE_g[MAX_UE][MAX_NUM_CCs];
-#endif
extern short primary_synch0[144];
extern short primary_synch1[144];
diff --git a/openair1/PHY/phy_extern_ue.h b/openair1/PHY/phy_extern_ue.h
index 596686f261..6fd53ac15c 100644
--- a/openair1/PHY/phy_extern_ue.h
+++ b/openair1/PHY/phy_extern_ue.h
@@ -38,15 +38,8 @@ extern int number_of_cards;
extern short conjugate[8],conjugate2[8];
-#ifndef OCP_FRAMEWORK
-extern PHY_VARS_UE ***PHY_vars_UE_g;
-extern LTE_DL_FRAME_PARMS *lte_frame_parms_g;
-#else
-#define MAX_UE 10
-#define MAX_eNB 20
-extern PHY_VARS_UE * PHY_vars_UE_g[MAX_UE][MAX_NUM_CCs];
-#endif
+extern PHY_VARS_UE ***PHY_vars_UE_g;
extern short primary_synch0[144];
extern short primary_synch1[144];
diff --git a/openair1/PHY/phy_vars.h b/openair1/PHY/phy_vars.h
index 897d826ae2..4cf029e968 100644
--- a/openair1/PHY/phy_vars.h
+++ b/openair1/PHY/phy_vars.h
@@ -41,20 +41,11 @@ int16_t *primary_synch2_time;
#include "PHY/LTE_TRANSPORT/transport_vars.h"
#include "PHY/MODULATION/modulation_vars.h"
-//PHY_VARS *PHY_vars;
-#ifndef OCP_FRAMEWORK
+
+
PHY_VARS_UE ***PHY_vars_UE_g;
RAN_CONTEXT_t RC;
-//PHY_VARS_eNB ***PHY_vars_eNB_g;
-//PHY_VARS_RN **PHY_vars_RN_g;
-LTE_DL_FRAME_PARMS *lte_frame_parms_g;
-#else
-PHY_VARS_UE * PHY_vars_UE_g[MAX_UE][MAX_NUM_CCs]={NULL};
-PHY_VARS_eNB * PHY_vars_eNB_g[MAX_eNB][MAX_NUM_CCs]={NULL};
-#endif
-
-
unsigned short rev[2048],rev_times4[8192],rev_half[1024];
unsigned short rev256[256],rev512[512],rev1024[1024],rev4096[4096],rev2048[2048],rev8192[8192];
diff --git a/openair1/PHY/phy_vars_nr_ue.h b/openair1/PHY/phy_vars_nr_ue.h
index 0e7e4f79d1..77163c0bc0 100644
--- a/openair1/PHY/phy_vars_nr_ue.h
+++ b/openair1/PHY/phy_vars_nr_ue.h
@@ -40,16 +40,10 @@ int16_t *primary_synch2_time;
//#include "PHY/CODING/coding_vars.h"
-//PHY_VARS *PHY_vars;
-#ifndef OCP_FRAMEWORK
+
+
PHY_VARS_NR_UE ***PHY_vars_UE_g;
PHY_VARS_eNB ***PHY_vars_eNB_g;
-NR_DL_FRAME_PARMS *lte_frame_parms_g;
-#else
-PHY_VARS_NR_UE * PHY_vars_UE_g[MAX_UE][MAX_NUM_CCs]={NULL};
-
-#endif
-
unsigned short rev[2048],rev_times4[8192],rev_half[1024];
unsigned short rev256[256],rev512[512],rev1024[1024],rev4096[4096],rev2048[2048],rev8192[8192];
diff --git a/openair1/PHY/phy_vars_ue.h b/openair1/PHY/phy_vars_ue.h
index 6cd7957884..1021253ba1 100644
--- a/openair1/PHY/phy_vars_ue.h
+++ b/openair1/PHY/phy_vars_ue.h
@@ -37,17 +37,7 @@ int16_t *primary_synch0_time;
int16_t *primary_synch1_time;
int16_t *primary_synch2_time;
-
-
-//PHY_VARS *PHY_vars;
-#ifndef OCP_FRAMEWORK
PHY_VARS_UE ***PHY_vars_UE_g;
-LTE_DL_FRAME_PARMS *lte_frame_parms_g;
-#else
-PHY_VARS_UE *PHY_vars_UE_g[MAX_UE][MAX_NUM_CCs]= {NULL};
-
-#endif
-
unsigned short rev[2048],rev_times4[8192],rev_half[1024];
unsigned short rev256[256],rev512[512],rev1024[1024],rev4096[4096],rev2048[2048],rev8192[8192];
diff --git a/openair1/PHY/thread_NR_UE.h b/openair1/PHY/thread_NR_UE.h
index cba7a5ae41..c5db3e14d7 100644
--- a/openair1/PHY/thread_NR_UE.h
+++ b/openair1/PHY/thread_NR_UE.h
@@ -32,8 +32,6 @@ typedef struct {
//pthread_t pthread_slot0_dl_processing;
pthread_t pthread_slot1_dl_processing;
/// pthread attributes for fep_slot1 processing thread
- // pthread_attr_t attr_slot0_dl_processing;
- pthread_attr_t attr_slot1_dl_processing;
/// condition variable for UE fep_slot1 thread;
//pthread_cond_t cond_slot0_dl_processing;
pthread_cond_t cond_slot1_dl_processing;
@@ -46,8 +44,6 @@ typedef struct {
//pthread_t pthread_slot0_dl_processing;
pthread_t pthread_dlsch_td;
/// pthread attributes for fep_slot1 processing thread
- // pthread_attr_t attr_slot0_dl_processing;
- pthread_attr_t attr_dlsch_td;
/// condition variable for UE fep_slot1 thread;
//pthread_cond_t cond_slot0_dl_processing;
pthread_cond_t cond_dlsch_td;
diff --git a/openair1/SCHED/phy_procedures_lte_eNb.c b/openair1/SCHED/phy_procedures_lte_eNb.c
index 3b3b9336d4..ba90220d0b 100644
--- a/openair1/SCHED/phy_procedures_lte_eNb.c
+++ b/openair1/SCHED/phy_procedures_lte_eNb.c
@@ -38,6 +38,7 @@
#include "nfapi/oai_integration/vendor_ext.h"
#include "fapi_l1.h"
#include "common/utils/LOG/log.h"
+#include
#include "common/utils/LOG/vcd_signal_dumper.h"
#include "assertions.h"
@@ -1351,12 +1352,11 @@ extern void *td_thread (void *);
void init_td_thread(PHY_VARS_eNB *eNB) {
L1_proc_t *proc = &eNB->proc;
proc->tdp.eNB = eNB;
- proc->instance_cnt_td = -1;
- pthread_attr_init( &proc->attr_td);
- pthread_mutex_init( &proc->mutex_td, NULL);
- pthread_cond_init( &proc->cond_td, NULL);
- pthread_create(&proc->pthread_td, &proc->attr_td, td_thread, (void *)&proc->tdp);
+ proc->instance_cnt_td = -1;
+
+ threadCreate(&proc->pthread_td, td_thread, (void*)&proc->tdp, "TD", -1, OAI_PRIORITY_RT);
}
+
void kill_td_thread(PHY_VARS_eNB *eNB) {
L1_proc_t *proc = &eNB->proc;
proc->instance_cnt_td = 0;
@@ -1368,20 +1368,23 @@ void kill_td_thread(PHY_VARS_eNB *eNB) {
extern void *te_thread (void *);
-void init_te_thread(PHY_VARS_eNB *eNB) {
+void init_te_thread(PHY_VARS_eNB *eNB)
+{
L1_proc_t *proc = &eNB->proc;
for(int i=0; i<3 ; i++) {
proc->tep[i].eNB = eNB;
- proc->tep[i].instance_cnt_te = -1;
- pthread_mutex_init( &proc->tep[i].mutex_te, NULL);
- pthread_cond_init( &proc->tep[i].cond_te, NULL);
- pthread_attr_init( &proc->tep[i].attr_te);
+ proc->tep[i].instance_cnt_te = -1;
+
LOG_I(PHY,"Creating te_thread %d\n",i);
- pthread_create(&proc->tep[i].pthread_te, &proc->tep[i].attr_te, te_thread, (void *)&proc->tep[i]);
+ char txt[128];
+ sprintf(txt,"TE_%d", i);
+ threadCreate(&proc->tep[i].pthread_te, te_thread, (void*)&proc->tep[i], txt, -1, OAI_PRIORITY_RT);
}
}
-void kill_te_thread(PHY_VARS_eNB *eNB) {
+
+void kill_te_thread(PHY_VARS_eNB *eNB)
+{
L1_proc_t *proc = &eNB->proc;
for(int i=0; i<3 ; i++) {
@@ -1393,7 +1396,11 @@ void kill_te_thread(PHY_VARS_eNB *eNB) {
}
}
-void fill_rx_indication(PHY_VARS_eNB *eNB,int UE_id,int frame,int subframe) {
+void fill_rx_indication(PHY_VARS_eNB *eNB,
+ int UE_id,
+ int frame,
+ int subframe)
+{
nfapi_rx_indication_pdu_t *pdu;
int timing_advance_update;
int sync_pos;
diff --git a/openair1/SCHED/ru_procedures.c b/openair1/SCHED/ru_procedures.c
index f30f09859c..2724567f4b 100644
--- a/openair1/SCHED/ru_procedures.c
+++ b/openair1/SCHED/ru_procedures.c
@@ -44,12 +44,11 @@
#include "assertions.h"
+#include "common/utils/system.h"
#include "msc.h"
#include
-#include "targets/RT/USER/rt_wrapper.h"
-
extern int oai_exit;
@@ -131,17 +130,8 @@ static void *feptx_thread(void *param) {
RU_t *ru = (RU_t *)param;
RU_proc_t *proc = &ru->proc;
- cpu_set_t cpuset;
- CPU_ZERO(&cpuset);
-
- thread_top_init("feptx_thread",1,85000,120000,500000);
- pthread_setname_np( pthread_self(),"feptx processing");
- LOG_I(PHY,"thread feptx created id=%ld\n", syscall(__NR_gettid));
- //CPU_SET(6, &cpuset);
- //pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset);
- //wait_sync("feptx_thread");
-
+ LOG_I(PHY,"thread feptx created \n");
while (!oai_exit) {
@@ -162,8 +152,6 @@ static void *feptx_thread(void *param) {
}*/
}
-
-
return(NULL);
}
@@ -438,16 +426,6 @@ static void *fep_thread(void *param) {
RU_t *ru = (RU_t *)param;
RU_proc_t *proc = &ru->proc;
- thread_top_init("fep_thread",1,100000,120000,5000000);
- pthread_setname_np( pthread_self(),"fep processing");
- LOG_I(PHY,"thread fep created id=%ld\n", syscall(__NR_gettid));
-
- cpu_set_t cpuset;
- CPU_ZERO(&cpuset);
- //CPU_SET(2, &cpuset);
- //pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset);
- //wait_sync("fep_thread");
-
while (!oai_exit) {
if (wait_on_condition(&proc->mutex_fep,&proc->cond_fep,&proc->instance_cnt_fep,"fep thread")<0) break;
@@ -483,7 +461,7 @@ void init_feptx_thread(RU_t *ru,pthread_attr_t *attr_feptx) {
pthread_mutex_init( &proc->mutex_feptx, NULL);
pthread_cond_init( &proc->cond_feptx, NULL);
- pthread_create(&proc->pthread_feptx, attr_feptx, feptx_thread, (void*)ru);
+ threadCreate(&proc->pthread_feptx, feptx_thread, (void*)ru, "feptx", -1, OAI_PRIORITY_RT);
}
@@ -497,7 +475,7 @@ void init_fep_thread(RU_t *ru,pthread_attr_t *attr_fep) {
pthread_mutex_init( &proc->mutex_fep, NULL);
pthread_cond_init( &proc->cond_fep, NULL);
- pthread_create(&proc->pthread_fep, attr_fep, fep_thread, (void*)ru);
+ threadCreate(&proc->pthread_fep, fep_thread, (void*)ru, "fep", -1, OAI_PRIORITY_RT);
}
diff --git a/openair1/SCHED_NR/nr_ru_procedures.c b/openair1/SCHED_NR/nr_ru_procedures.c
index 65dfb64734..653e9632b5 100644
--- a/openair1/SCHED_NR/nr_ru_procedures.c
+++ b/openair1/SCHED_NR/nr_ru_procedures.c
@@ -41,6 +41,7 @@
#include "LAYER2/MAC/mac_extern.h"
#include "LAYER2/MAC/mac.h"
#include "common/utils/LOG/log.h"
+#include "common/utils/system.h"
#include "common/utils/LOG/vcd_signal_dumper.h"
#include "T.h"
@@ -49,9 +50,6 @@
#include "msc.h"
#include
-
-#include "targets/RT/USER/rt_wrapper.h"
-
// RU OFDM Modulator gNodeB
extern openair0_config_t openair0_cfg[MAX_CARDS];
@@ -179,7 +177,6 @@ static void *nr_feptx_thread(void *param) {
RU_t *ru = (RU_t *)param;
RU_proc_t *proc = &ru->proc;
- thread_top_init("nr_feptx_thread",0,870000,1000000,1000000);
while (!oai_exit) {
@@ -196,7 +193,7 @@ static void *nr_feptx_thread(void *param) {
return(NULL);
}
-void nr_init_feptx_thread(RU_t *ru,pthread_attr_t *attr_feptx) {
+void nr_init_feptx_thread(RU_t *ru) {
RU_proc_t *proc = &ru->proc;
@@ -205,7 +202,7 @@ void nr_init_feptx_thread(RU_t *ru,pthread_attr_t *attr_feptx) {
pthread_mutex_init( &proc->mutex_feptx, NULL);
pthread_cond_init( &proc->cond_feptx, NULL);
- pthread_create(&proc->pthread_feptx, attr_feptx, nr_feptx_thread, (void*)ru);
+ threadCreate(&proc->pthread_feptx, nr_feptx_thread, (void*)ru, "feptx", -1, OAI_PRIORITY_RT);
}
diff --git a/openair1/SCHED_NR/sched_nr.h b/openair1/SCHED_NR/sched_nr.h
index a120b8c140..7c5a5d0146 100644
--- a/openair1/SCHED_NR/sched_nr.h
+++ b/openair1/SCHED_NR/sched_nr.h
@@ -38,10 +38,13 @@ nr_slot_t nr_slot_select (nfapi_nr_config_request_t *cfg, unsigned char slot);
void nr_set_ssb_first_subcarrier(nfapi_nr_config_request_t *cfg, NR_DL_FRAME_PARMS *fp);
void phy_procedures_gNB_TX(PHY_VARS_gNB *gNB, gNB_L1_rxtx_proc_t *proc, int do_meas);
void nr_common_signal_procedures (PHY_VARS_gNB *gNB,int frame, int slot);
-void nr_init_feptx_thread(RU_t *ru,pthread_attr_t *attr_feptx);
+void nr_init_feptx_thread(RU_t *ru);
void nr_feptx_ofdm(RU_t *ru);
void nr_feptx_ofdm_2thread(RU_t *ru);
void nr_feptx0(RU_t *ru,int first_symbol, int num_symbols);
+void fep_full(RU_t *ru);
+void feptx_prec(RU_t *ru);
+int nr_phy_init_RU(RU_t *ru);
void nr_configure_css_dci_initial(nfapi_nr_dl_config_pdcch_parameters_rel15_t* pdcch_params,
nr_scs_e scs_common,
diff --git a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c
index f26468fb03..0a087d5b8b 100644
--- a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c
+++ b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c
@@ -3155,36 +3155,42 @@ int nr_ue_pdcch_procedures(uint8_t eNB_id,
/*
* This is the NR part
*/
-
- if ((dci_alloc_rx[i].format == format0_0))
- if ((dci_alloc_rx[i].format == format1_0) &&
- (dci_alloc_rx[i].rnti != crc_scrambled_values[_P_RNTI_]) &&
- (dci_alloc_rx[i].rnti != crc_scrambled_values[_SI_RNTI_]) &&
- (dci_alloc_rx[i].rnti != crc_scrambled_values[_RA_RNTI_])) ue->dlsch_received[eNB_id]++;
-
- if ((dci_alloc_rx[i].rnti == crc_scrambled_values[_SI_RNTI_]) && (dci_alloc_rx[i].format == format1_0)) ue->dlsch_SI_received[eNB_id]++;
- if ((dci_alloc_rx[i].rnti == crc_scrambled_values[_P_RNTI_]) && (dci_alloc_rx[i].format == format1_0)) ue->dlsch_p_received[eNB_id]++;
- if ((dci_alloc_rx[i].rnti == crc_scrambled_values[_RA_RNTI_]) && (dci_alloc_rx[i].format == format1_0)) ue->dlsch_ra_received[eNB_id]++;
- if ((dci_alloc_rx[i].format == format2_0)){
- }
- if ((dci_alloc_rx[i].format == format2_1)){
- }
- if ((dci_alloc_rx[i].format == format2_2)){
- }
- if ((dci_alloc_rx[i].format == format2_3)){
- }
- if ((dci_alloc_rx[i].format == format0_1)){ // This format not implemented at a first time. FIXME
- }
- if ((dci_alloc_rx[i].format == format1_1)){ // This format not implemented at a first time. FIXME
- }
-
-
+ if ((dci_alloc_rx[i].format == format0_0)){
+ }
+
+ if (dci_alloc_rx[i].format == format1_0) {
+ if ((dci_alloc_rx[i].rnti != crc_scrambled_values[_P_RNTI_]) &&
+ (dci_alloc_rx[i].rnti != crc_scrambled_values[_SI_RNTI_]) &&
+ (dci_alloc_rx[i].rnti != crc_scrambled_values[_RA_RNTI_]))
+ ue->dlsch_received[eNB_id]++;
+
+ if (dci_alloc_rx[i].rnti == crc_scrambled_values[_SI_RNTI_])
+ ue->dlsch_SI_received[eNB_id]++;
+ if (dci_alloc_rx[i].rnti == crc_scrambled_values[_P_RNTI_])
+ ue->dlsch_p_received[eNB_id]++;
+ if (dci_alloc_rx[i].rnti == crc_scrambled_values[_RA_RNTI_])
+ ue->dlsch_ra_received[eNB_id]++;
+ }
+
+ if ((dci_alloc_rx[i].format == format2_0)){
+ }
+ if ((dci_alloc_rx[i].format == format2_1)){
+ }
+ if ((dci_alloc_rx[i].format == format2_2)){
+ }
+ if ((dci_alloc_rx[i].format == format2_3)){
+ }
+ if ((dci_alloc_rx[i].format == format0_1)){ // This format not implemented at a first time. FIXME
+ }
+ if ((dci_alloc_rx[i].format == format1_1)){ // This format not implemented at a first time. FIXME
+ }
+
uint8_t status=0;
-
+
LOG_D(PHY,"<-NR_PDCCH_PHY_PROCEDURES_UE (nr_ue_pdcch_procedures)-> dci_format=%d, rnti=%d, dci_length=%d, dci_pdu[0]=0x%lx, dci_pdu[1]=0x%lx\n",dci_alloc_rx[i].format,dci_alloc_rx[i].rnti,dci_alloc_rx[i].dci_length,dci_alloc_rx[i].dci_pdu[0],dci_alloc_rx[i].dci_pdu[1]);
-
+
memset(&ue->dci_ind.dci_list[i].dci,0,sizeof(fapi_nr_dci_pdu_rel15_t));
-
+
ue->dci_ind.dci_list[i].rnti = dci_alloc_rx[i].rnti;
ue->dci_ind.dci_list[i].dci_format = dci_alloc_rx[i].format;
ue->dci_ind.dci_list[i].n_CCE = dci_alloc_rx[i].firstCCE;
@@ -3203,15 +3209,15 @@ int nr_ue_pdcch_procedures(uint8_t eNB_id,
pdcch_vars2->n_RB_BWP[nb_searchspace_active],
pdcch_vars2->n_RB_BWP[nb_searchspace_active],
crc_scrambled_values);
-
+
if(status == 0) {
LOG_W(PHY,"<-NR_PDCCH_PHY_PROCEDURES_UE (nr_ue_pdcch_procedures)-> bad DCI %d !!! \n",dci_alloc_rx[i].format);
return(-1);
}
LOG_D(PHY,"<-NR_PDCCH_PHY_PROCEDURES_UE (nr_ue_pdcch_procedures)-> Ending function nr_extract_dci_info()\n");
-
- /*
+
+ /*
nr_generate_ue_ul_dlsch_params_from_dci(ue,
eNB_id,
frame_rx,
diff --git a/openair2/ENB_APP/RRC_config_tools.h b/openair2/ENB_APP/RRC_config_tools.h
index a44da1f90c..488441ff59 100644
--- a/openair2/ENB_APP/RRC_config_tools.h
+++ b/openair2/ENB_APP/RRC_config_tools.h
@@ -30,7 +30,7 @@
#define RRC_CONFIG_TOOLS_H_
#define KHz (1000UL)
-#define MHz (1000 * KHz)
+#define MHz (1000*KHz)
typedef struct eutra_band_s {
int16_t band;
diff --git a/openair2/ENB_APP/enb_app.c b/openair2/ENB_APP/enb_app.c
index 0580f0eb52..2d5134e0d9 100644
--- a/openair2/ENB_APP/enb_app.c
+++ b/openair2/ENB_APP/enb_app.c
@@ -51,14 +51,11 @@
#include "openair1/PHY/INIT/phy_init.h"
extern unsigned char NB_eNB_INST;
+#include
extern RAN_CONTEXT_t RC;
# define ENB_REGISTER_RETRY_DELAY 10
-#include "targets/RT/USER/lte-softmodem.h"
-
-
-
/*------------------------------------------------------------------------------*/
diff --git a/openair2/ENB_APP/flexran_agent.c b/openair2/ENB_APP/flexran_agent.c
index 24ed07ac92..f73e808865 100644
--- a/openair2/ENB_APP/flexran_agent.c
+++ b/openair2/ENB_APP/flexran_agent.c
@@ -28,12 +28,12 @@
#define _GNU_SOURCE
#include "flexran_agent.h"
+#include
#include
#include
void *receive_thread(void *args);
-pthread_t new_thread(void *(*f)(void *), void *b);
Protocol__FlexranMessage *flexran_agent_timeout(void* args);
@@ -147,38 +147,6 @@ error:
}
-/* utility function to create a thread */
-pthread_t new_thread(void *(*f)(void *), void *b) {
- pthread_t t;
- pthread_attr_t att;
-
- if (pthread_attr_init(&att)){
- fprintf(stderr, "pthread_attr_init err\n");
- exit(1);
- }
-
- struct sched_param sched_param_recv_thread;
-
- sched_param_recv_thread.sched_priority = sched_get_priority_max(SCHED_FIFO) - 1;
- pthread_attr_setschedparam(&att, &sched_param_recv_thread);
- pthread_attr_setschedpolicy(&att, SCHED_FIFO);
-
- if (pthread_attr_setdetachstate(&att, PTHREAD_CREATE_DETACHED)) {
- fprintf(stderr, "pthread_attr_setdetachstate err\n");
- exit(1);
- }
- if (pthread_create(&t, &att, f, b)) {
- fprintf(stderr, "pthread_create err\n");
- exit(1);
- }
- if (pthread_attr_destroy(&att)) {
- fprintf(stderr, "pthread_attr_destroy err\n");
- exit(1);
- }
-
- return t;
-}
-
int channel_container_init = 0;
int flexran_agent_start(mid_t mod_id)
{
@@ -235,12 +203,9 @@ int flexran_agent_start(mid_t mod_id)
*/
/*Initialize the continuous stats update mechanism*/
- if (flexran_agent_init_cont_stats_update(mod_id) < 0) {
- LOG_E(FLEXRAN_AGENT, "could not initialize continuous stats updates\n");
- goto error;
- }
-
- new_thread(receive_thread, flexran);
+ flexran_agent_init_cont_stats_update(mod_id);
+ pthread_t t;
+ threadCreate(&t, receive_thread, flexran, "flexran", -1, OAI_PRIORITY_RT);
/* Register and initialize the control modules depending on capabilities.
* After registering, calling flexran_agent_get_*_xface() tells whether a
diff --git a/openair2/LAYER2/PDCP_v10.1.0/pdcp.h b/openair2/LAYER2/PDCP_v10.1.0/pdcp.h
index 860f90bf34..8e67e1f637 100644
--- a/openair2/LAYER2/PDCP_v10.1.0/pdcp.h
+++ b/openair2/LAYER2/PDCP_v10.1.0/pdcp.h
@@ -83,7 +83,6 @@ typedef struct {
uint64_t get_pdcp_optmask(void);
extern pthread_t pdcp_thread;
-extern pthread_attr_t pdcp_thread_attr;
extern pthread_mutex_t pdcp_mutex;
extern pthread_cond_t pdcp_cond;
extern int pdcp_instance_cnt;
diff --git a/openair2/LAYER2/PDCP_v10.1.0/pdcp_netlink.c b/openair2/LAYER2/PDCP_v10.1.0/pdcp_netlink.c
index f47694c2e3..6dd3846d88 100644
--- a/openair2/LAYER2/PDCP_v10.1.0/pdcp_netlink.c
+++ b/openair2/LAYER2/PDCP_v10.1.0/pdcp_netlink.c
@@ -96,8 +96,7 @@ pdcp_netlink_init(
int i;
int nb_inst_enb;
int nb_inst_ue;
- pthread_attr_t attr;
- struct sched_param sched_param;
+
reset_meas(&ip_pdcp_stats_tmp);
nb_inst_enb = 1;
nb_inst_ue = 1;
@@ -137,27 +136,11 @@ pdcp_netlink_init(
}
if ((nb_inst_ue + nb_inst_enb) > 0) {
- if (pthread_attr_init(&attr) != 0) {
- LOG_E(PDCP, "[NETLINK]Failed to initialize pthread attribute for Netlink -> PDCP communication (%d:%s)\n",
- errno, strerror(errno));
- exit(EXIT_FAILURE);
- }
-
- sched_param.sched_priority = 10;
- pthread_attr_setschedpolicy(&attr, SCHED_RR);
- pthread_attr_setschedparam(&attr, &sched_param);
-
/* Create one thread that fetchs packets from the netlink.
* When the netlink fifo is full, packets are silently dropped, this behaviour
* should be avoided if we want a reliable link.
*/
- if (pthread_create(&pdcp_netlink_thread, &attr, pdcp_netlink_thread_fct, NULL) != 0) {
- LOG_E(PDCP, "[NETLINK]Failed to create new thread for Netlink/PDCP communication (%d:%s)\n",
- errno, strerror(errno));
- exit(EXIT_FAILURE);
- }
-
- pthread_setname_np( pdcp_netlink_thread, "PDCP netlink" );
+ threadCreate(&pdcp_netlink_thread, pdcp_netlink_thread_fct, "PDCP netlink", -1, OAI_PRIORITY_RT_LOW );
}
return 0;
diff --git a/openair2/LAYER2/PDCP_v10.1.0/pdcp_thread.c b/openair2/LAYER2/PDCP_v10.1.0/pdcp_thread.c
index 0b6be93d59..f1f6ebb794 100644
--- a/openair2/LAYER2/PDCP_v10.1.0/pdcp_thread.c
+++ b/openair2/LAYER2/PDCP_v10.1.0/pdcp_thread.c
@@ -45,7 +45,6 @@ extern int oai_exit;
extern char UE_flag;
pthread_t pdcp_thread;
-pthread_attr_t pdcp_thread_attr;
pthread_mutex_t pdcp_mutex;
pthread_cond_t pdcp_cond;
int pdcp_instance_cnt;
@@ -101,33 +100,12 @@ static void *pdcp_thread_main(void* param)
int init_pdcp_thread(void)
{
- int error_code;
- struct sched_param p;
-
- pthread_attr_init (&pdcp_thread_attr);
- pthread_attr_setstacksize(&pdcp_thread_attr,OPENAIR_THREAD_STACK_SIZE);
- //attr_dlsch_threads.priority = 1;
-
- p.sched_priority = OPENAIR_THREAD_PRIORITY;
- pthread_attr_setschedparam (&pdcp_thread_attr, &p);
- pthread_attr_setschedpolicy (&pdcp_thread_attr, SCHED_FIFO);
pthread_mutex_init(&pdcp_mutex,NULL);
pthread_cond_init(&pdcp_cond,NULL);
pdcp_instance_cnt = -1;
LOG_I(PDCP,"Allocating PDCP thread\n");
- error_code = pthread_create(&pdcp_thread,
- &pdcp_thread_attr,
- pdcp_thread_main,
- (void*)NULL);
-
- if (error_code!= 0) {
- LOG_I(PDCP,"Could not allocate PDCP thread, error %d\n",error_code);
- return(error_code);
- } else {
- LOG_I(PDCP,"Allocate PDCP thread successful\n");
- pthread_setname_np( pdcp_thread, "PDCP" );
- }
+ threadCreate(&pdcp_thread, pdcp_thread_main, (void*)NULL, "PDCP", -1, OAI_PRIORITY_RT);
return(0);
}
diff --git a/openair2/PHY_INTERFACE/UE_MAC_interface.h b/openair2/PHY_INTERFACE/UE_MAC_interface.h
index 3d6a8ced82..42e790d1e9 100644
--- a/openair2/PHY_INTERFACE/UE_MAC_interface.h
+++ b/openair2/PHY_INTERFACE/UE_MAC_interface.h
@@ -40,8 +40,6 @@
#include "openair1/PHY/defs_RU.h"
#include "targets/COMMON/openairinterface5g_limits.h"
-
-
#define MAX_NUM_DL_PDU 100
#define MAX_NUM_UL_PDU 100
#define MAX_NUM_HI_DCI0_PDU 100
diff --git a/openair2/RRC/LTE/defs_NB_IoT.h b/openair2/RRC/LTE/defs_NB_IoT.h
index 26eca6d781..8f0c4d16e6 100644
--- a/openair2/RRC/LTE/defs_NB_IoT.h
+++ b/openair2/RRC/LTE/defs_NB_IoT.h
@@ -42,7 +42,7 @@
#include "rrc_types_NB_IoT.h"
#include "COMMON/platform_constants.h"
#include "COMMON/platform_types.h"
-#include "targets/COMMON/openairinterface5g_limits.h"
+#include "openairinterface5g_limits.h"
#include "COMMON/mac_rrc_primitives.h"
diff --git a/openair2/RRC/LTE/rrc_UE.c b/openair2/RRC/LTE/rrc_UE.c
index 2e3d0a8bc7..621a0d3b68 100644
--- a/openair2/RRC/LTE/rrc_UE.c
+++ b/openair2/RRC/LTE/rrc_UE.c
@@ -74,6 +74,7 @@
#include "pdcp.h"
#include "plmn_data.h"
#include "msc.h"
+#include
#include "intertask_interface.h"
@@ -4953,7 +4954,6 @@ rrc_ue_process_sidelink_radioResourceConfig(
} else {
//SL_DiscConfig_r12__ext2__discTxResourcesPS_r13__setup_PR_NOTHING, /* No components present */
}
-
break;
case LTE_SL_DiscConfig_r12__ext2__discTxResourcesPS_r13_PR_release:
@@ -4972,58 +4972,37 @@ rrc_ue_process_sidelink_radioResourceConfig(
#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0))
//-----------------------------------------------------------
-void
-rrc_control_socket_init() {
+void rrc_control_socket_init() {
struct sockaddr_in rrc_ctrl_socket_addr;
- pthread_attr_t attr;
- struct sched_param sched_param;
int optval; // flag value for setsockopt
//int n; // message byte size
+
// create the control socket
ctrl_sock_fd = socket(AF_INET, SOCK_DGRAM, 0);
-
if (ctrl_sock_fd == -1) {
- LOG_E(RRC,"[rrc_control_socket_init] :Error opening socket %d (%d:%s)\n",ctrl_sock_fd,errno, strerror(errno));
+ LOG_E(RRC,"[rrc_control_socket_init] :Error opening socket %d (%d:%s)\n", ctrl_sock_fd, errno, strerror(errno));
exit(EXIT_FAILURE);
}
// if (ctrl_sock_fd < 0)
// error("ERROR: Failed on opening socket");
optval = 1;
- setsockopt(ctrl_sock_fd, SOL_SOCKET, SO_REUSEADDR,
- (const void *)&optval, sizeof(int));
- //build the server's address
+ setsockopt(ctrl_sock_fd, SOL_SOCKET, SO_REUSEADDR, (const void *)&optval, sizeof(int));
+ //build the server's address
bzero((char *) &rrc_ctrl_socket_addr, sizeof(rrc_ctrl_socket_addr));
rrc_ctrl_socket_addr.sin_family = AF_INET;
rrc_ctrl_socket_addr.sin_addr.s_addr = htonl(INADDR_ANY);
rrc_ctrl_socket_addr.sin_port = htons(CONTROL_SOCKET_PORT_NO);
// associate the parent socket with a port
- if (bind(ctrl_sock_fd, (struct sockaddr *) &rrc_ctrl_socket_addr,
- sizeof(rrc_ctrl_socket_addr)) < 0) {
+ if (bind(ctrl_sock_fd, (struct sockaddr *) &rrc_ctrl_socket_addr, sizeof(rrc_ctrl_socket_addr)) < 0) {
LOG_E(RRC,"[rrc_control_socket_init] ERROR: Failed on binding the socket\n");
exit(1);
}
- //create thread to listen to incoming packets
- if (pthread_attr_init(&attr) != 0) {
- LOG_E(RRC, "[rrc_control_socket_init]Failed to initialize pthread attribute for ProSe -> RRC communication (%d:%s)\n",
- errno, strerror(errno));
- exit(EXIT_FAILURE);
- }
+ pthread_t rrc_control_socket_thread;
- sched_param.sched_priority = 10;
- pthread_attr_setschedpolicy(&attr, SCHED_RR);
- pthread_attr_setschedparam(&attr, &sched_param);
- pthread_t rrc_control_socket_thread;
-
- if (pthread_create(&rrc_control_socket_thread, &attr, rrc_control_socket_thread_fct, NULL) != 0) {
- LOG_E(RRC, "[rrc_control_socket_init]Failed to create new thread for RRC/ProSeApp communication (%d:%s)\n",
- errno, strerror(errno));
- exit(EXIT_FAILURE);
- }
-
- pthread_setname_np( rrc_control_socket_thread, "RRC Control Socket" );
+ threadCreate(&rrc_control_socket_thread, rrc_control_socket_thread_fct, NULL, "RRC/ProSeApp", -1, OAI_PRIORITY_RT);
}
//--------------------------------------------------------
diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c
index 6b1ded3b1e..749320b357 100644
--- a/openair2/RRC/NR/rrc_gNB.c
+++ b/openair2/RRC/NR/rrc_gNB.c
@@ -116,10 +116,9 @@ mui_t rrc_gNB_mui = 0;
void openair_nr_rrc_on(const protocol_ctxt_t* const ctxt_pP){
- int CC_id;
LOG_I(NR_RRC, PROTOCOL_NR_RRC_CTXT_FMT" gNB:OPENAIR NR RRC IN....\n",PROTOCOL_NR_RRC_CTXT_ARGS(ctxt_pP));
- for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) {
+ for (int CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) {
rrc_config_nr_buffer (&RC.nrrrc[ctxt_pP->module_id]->carrier[CC_id].SI, BCCH, 1);
RC.nrrrc[ctxt_pP->module_id]->carrier[CC_id].SI.Active = 1;
rrc_config_nr_buffer (&RC.nrrrc[ctxt_pP->module_id]->carrier[CC_id].Srb0, CCCH, 1);
diff --git a/openair2/UTIL/ASYNC_IF/link_manager.c b/openair2/UTIL/ASYNC_IF/link_manager.c
index e9a8e98e07..85a4f48a8e 100644
--- a/openair2/UTIL/ASYNC_IF/link_manager.c
+++ b/openair2/UTIL/ASYNC_IF/link_manager.c
@@ -30,6 +30,8 @@
#include "link_manager.h"
#include "common/utils/LOG/log.h"
+#include
+#include
#include
#include
@@ -98,47 +100,21 @@ link_manager_t *create_link_manager(
LOG_D(MAC, "create new link manager\n");
- ret = calloc(1, sizeof(link_manager_t));
- if (ret == NULL)
- goto error;
+ AssertFatal( (ret=calloc(1, sizeof(link_manager_t))) != NULL,"");
ret->send_queue = send_queue;
ret->receive_queue = receive_queue;
ret->socket_link = link;
ret->run = 1;
- if (pthread_attr_init(&attr))
- goto error;
-
- // Make the async interface threads real-time
- //#ifndef LOWLATENCY
- struct sched_param sched_param_recv_thread;
-
- sched_param_recv_thread.sched_priority = sched_get_priority_max(SCHED_RR) - 1;
- pthread_attr_setschedparam(&attr, &sched_param_recv_thread);
- pthread_attr_setschedpolicy(&attr, SCHED_RR);
- //#endif
-
- if (pthread_create(&t, &attr, link_manager_sender_thread, ret))
- goto error;
+ threadCreate(&t, link_manager_sender_thread, ret, "flexranSender", -1, OAI_PRIORITY_RT_LOW);
ret->sender = t;
- if (pthread_create(&t, &attr, link_manager_receiver_thread, ret))
- /* we should destroy the other thread here */
- goto error;
+ threadCreate(&t, link_manager_receiver_thread, ret, "flexranReceiver", -1, OAI_PRIORITY_RT_LOW);
ret->receiver = t;
- if (pthread_attr_destroy(&attr))
- /* to be clean we should destroy the threads at this point,
- * even if in practice we never reach it */
- goto error;
-
return ret;
-error:
- LOG_E(MAC, "%s: an error occured\n", __FUNCTION__);
- free(ret);
- return NULL;
}
void destroy_link_manager(link_manager_t *manager)
diff --git a/openair2/UTIL/CLI/cli_server.c b/openair2/UTIL/CLI/cli_server.c
index d4f97f15ba..1994855b5d 100644
--- a/openair2/UTIL/CLI/cli_server.c
+++ b/openair2/UTIL/CLI/cli_server.c
@@ -90,10 +90,7 @@ int cli_server_init(cli_handler_t handler)
}
/* create telnet listener thread */
- if (pthread_create(&cli_server_listener, NULL, cli_server_listen, NULL)) {
- perror("thread");
- return -1;
- }
+ threadCreate(&cli_server_listener, cli_server_listen, NULL, "telnet", -1, OAI_PRIORITY_RT_LOW);
return 0;
}
diff --git a/openair2/UTIL/OPT/probe.c b/openair2/UTIL/OPT/probe.c
index b032784028..0058d25b12 100644
--- a/openair2/UTIL/OPT/probe.c
+++ b/openair2/UTIL/OPT/probe.c
@@ -90,8 +90,9 @@ what about the implementation
#include
#include
-#include "common/config/config_userapi.h"
#include "opt.h"
+#include "common/config/config_userapi.h"
+#include "common/utils/system.h"
int opt_enabled=0;
@@ -196,15 +197,7 @@ int opt_create_listener_socket(char *ip_address, uint16_t port) {
return -1;
}
- ret = pthread_create(&opt_listener.thread, NULL, opt_listener_thread, NULL);
-
- if (ret != 0) {
- LOG_E(OPT, "Failed to create thread for server socket: %s\n", strerror(errno));
- opt_type = OPT_NONE;
- close(opt_listener.sd);
- opt_listener.sd = -1;
- return -1;
- }
+ threadCreate(&opt_listener.thread, opt_listener_thread, NULL, "flexran", -1, OAI_PRIORITY_RT_LOW);
return 0;
}
diff --git a/openair2/UTIL/OTG/otg_rx_socket.c b/openair2/UTIL/OTG/otg_rx_socket.c
index 88ecd3e904..9e9b6bf4a1 100644
--- a/openair2/UTIL/OTG/otg_rx_socket.c
+++ b/openair2/UTIL/OTG/otg_rx_socket.c
@@ -195,17 +195,7 @@ void server_socket_tcp_ip4()
/* create new thread for the new connection */
- if (pthread_create(&id, NULL, (void *)recv_ip4_tcp, (void*)csock))
- LOG_W(OTG,"SOCKET:: TCP-IP4 ::pthread_create OK!\n");
-
- else
- LOG_W(OTG,"SOCKET:: TCP-IP4 ::Error in pthread_create \n");
-
- if (pthread_detach(id))
- LOG_W(OTG,"SOCKET:: TCP-IP4 ::pthread_detach OK!\n");
- else
- LOG_W(OTG,"SOCKET:: TCP-IP4 ::Error in pthread_detach\n");
-
+ threadCreate(&id, (void *)recv_ip4_tcp, (void*)csock), "OTG", -1, OAI_PRIORITY_RT_LOW);
LOG_I(OTG,"SOCKET:: TCP-IP4 :: Client n=%d finish transmission\n", cmpt_cl);
cmpt_cl+=1;
}
diff --git a/openair3/NAS/COMMON/UTIL/nas_timer.c b/openair3/NAS/COMMON/UTIL/nas_timer.c
index d92c48f483..7ddcb61d1d 100644
--- a/openair3/NAS/COMMON/UTIL/nas_timer.c
+++ b/openair3/NAS/COMMON/UTIL/nas_timer.c
@@ -397,24 +397,14 @@ static void _nas_timer_handler(int signal)
/* Get the timer entry for which the system timer expired */
nas_timer_entry_t *te = _nas_timer_db.head->entry;
- /* Execute the callback function */
- pthread_attr_t attr;
- pthread_attr_init(&attr);
- pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM);
- pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
- int rc = pthread_create (&te->pid, &attr, te->cb, te->args);
- pthread_attr_destroy(&attr);
+ threadCreate (&te->pid, te->cb, te->args, "nas-timer", -1, OAI_PRIORITY_RT_LOW);
- /* Wait for the thread to terminate before releasing the timer entry */
- if (rc == 0) {
void *result = NULL;
(void) pthread_join(te->pid, &result);
- /* TODO: Check returned result ??? */
if (result) {
free(result);
}
- }
}
#endif
diff --git a/openair3/NAS/UE/UEprocess.c b/openair3/NAS/UE/UEprocess.c
index 6a70911e21..7fe1435960 100644
--- a/openair3/NAS/UE/UEprocess.c
+++ b/openair3/NAS/UE/UEprocess.c
@@ -150,39 +150,20 @@ int main(int argc, const char *argv[])
(void) _nas_set_signal_handler (SIGINT, _nas_signal_handler);
(void) _nas_set_signal_handler (SIGTERM, _nas_signal_handler);
- pthread_attr_t attr;
- pthread_attr_init (&attr);
- pthread_attr_setscope (&attr, PTHREAD_SCOPE_SYSTEM);
- pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED);
-
/*
* Start thread use to manage the user connection endpoint
*/
pthread_t user_mngr;
- if (pthread_create (&user_mngr, &attr, _nas_user_mngr, &user_fd) != 0) {
- LOG_TRACE (ERROR, "UE-MAIN - "
- "Failed to create the user management thread");
- user_api_close (user_api_id);
- network_api_close (network_fd);
- exit (EXIT_FAILURE);
- }
+ threadCreate (&user_mngr, , _nas_user_mngr, &user_fd, "UE-nas", -1, OAI_PRIORITY_RT_LOW) ;
/*
* Start thread use to manage the network connection endpoint
*/
pthread_t network_mngr;
- if (pthread_create (&network_mngr, &attr, _nas_network_mngr,
- &network_fd) != 0) {
- LOG_TRACE (ERROR, "UE-MAIN - "
- "Failed to create the network management thread");
- user_api_close (user_api_id);
- network_api_close (network_fd);
- exit (EXIT_FAILURE);
- }
-
- pthread_attr_destroy (&attr);
+ threadCreate (&network_mngr, _nas_network_mngr,
+ &network_fd, "UE-nas-mgr", -1, OAI_PRIORITY_RT_LOW) ;
/*
* Suspend execution of the main process until all connection
diff --git a/openair3/SCTP/sctp_eNB_task.c b/openair3/SCTP/sctp_eNB_task.c
index 4b0945f5ea..32b38a4528 100644
--- a/openair3/SCTP/sctp_eNB_task.c
+++ b/openair3/SCTP/sctp_eNB_task.c
@@ -40,6 +40,7 @@
#include
#include "assertions.h"
+#include "common/utils/system.h"
#include "queue.h"
#include "intertask_interface.h"
diff --git a/targets/ARCH/COMMON/common_lib.h b/targets/ARCH/COMMON/common_lib.h
index e63cef08b2..8094b15cc8 100644
--- a/targets/ARCH/COMMON/common_lib.h
+++ b/targets/ARCH/COMMON/common_lib.h
@@ -58,11 +58,6 @@ typedef volatile int64_t openair0_vtimestamp;
/*!\brief structrue holds the parameters to configure USRP devices*/
typedef struct openair0_device_t openair0_device;
-
-
-
-
-
//#define USRP_GAIN_OFFSET (56.0) // 86 calibrated for USRP B210 @ 2.6 GHz to get equivalent RS EPRE in OAI to SMBV100 output
typedef enum {
@@ -83,9 +78,6 @@ typedef enum {
*/
/*!\brief RF device types
*/
-#ifdef OCP_FRAMEWORK
-#include
-#else
typedef enum {
MIN_RF_DEV_TYPE = 0,
/*!\brief device is ExpressMIMO */
@@ -109,7 +101,6 @@ typedef enum {
MAX_RF_DEV_TYPE
} dev_type_t;
-#endif
/*!\brief transport protocol types
*/
@@ -209,7 +200,7 @@ typedef struct {
//! clock source
clock_source_t clock_source;
//! Manual SDR IP address
-//#if defined(EXMIMO) || defined(OAI_USRP) || defined(OAI_BLADERF) || defined(OAI_LMSSDR)
+ //#if defined(EXMIMO) || defined(OAI_USRP) || defined(OAI_BLADERF) || defined(OAI_LMSSDR)
char *sdr_addrs;
//! Auto calibration flag
int autocal[4];
@@ -235,7 +226,7 @@ typedef struct {
unsigned int sf_read_delay; // read delay in replay mode
unsigned int sf_write_delay; // write delay in replay mode
unsigned int eth_mtu; // ethernet MTU
-#endif
+#endif
//! number of samples per tti
unsigned int samples_per_tti;
@@ -408,6 +399,32 @@ typedef int(*oai_device_initfunc_t)(openair0_device *device, openair0_config_t *
/* type of transport init function, implemented in shared lib */
typedef int(*oai_transport_initfunc_t)(openair0_device *device, openair0_config_t *openair0_cfg, eth_params_t *eth_params);
+#define UE_MAGICDL_FDD 0xA5A5A5A5A5A5A5A5 // UE DL FDD record
+#define UE_MAGICUL_FDD 0x5A5A5A5A5A5A5A5A // UE UL FDD record
+#define UE_MAGICDL_TDD 0xA6A6A6A6A6A6A6A6 // UE DL TDD record
+#define UE_MAGICUL_TDD 0x6A6A6A6A6A6A6A6A // UE UL TDD record
+
+#define ENB_MAGICDL_FDD 0xB5B5B5B5B5B5B5B5 // eNB DL FDD record
+#define ENB_MAGICUL_FDD 0x5B5B5B5B5B5B5B5B // eNB UL FDD record
+#define ENB_MAGICDL_TDD 0xB6B6B6B6B6B6B6B6 // eNB DL TDD record
+#define ENB_MAGICUL_TDD 0x6B6B6B6B6B6B6B6B // eNB UL TDD record
+
+#define OPTION_LZ4 0x00000001 // LZ4 compression (option_value is set to compressed size)
+
+#define sample_t uint32_t // 2*16 bits complex number
+
+typedef struct {
+ uint64_t magic; // Magic value (see defines above)
+ uint32_t size; // Number of samples per antenna to follow this header
+ uint32_t nbAnt; // Total number of antennas following this header
+ // Samples per antenna follow this header,
+ // i.e. nbAnt = 2 => this header+samples_antenna_0+samples_antenna_1
+ // data following this header in bytes is nbAnt*size*sizeof(sample_t)
+ uint64_t timestamp; // Timestamp value of first sample
+ uint32_t option_value; // Option value
+ uint32_t option_flag; // Option flag
+} samplesBlockHeader_t;
+
#ifdef __cplusplus
extern "C"
{
@@ -432,6 +449,7 @@ openair0_timestamp get_usrp_time(openair0_device *device);
*/
int openair0_set_rx_frequencies(openair0_device *device, openair0_config_t *openair0_cfg);
+#define gettid() syscall(__NR_gettid)
/*@}*/
#ifdef __cplusplus
diff --git a/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp b/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp
index 384542a70f..9ac5ddf0da 100644
--- a/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp
+++ b/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp
@@ -304,6 +304,7 @@ static int trx_usrp_start(openair0_device *device) {
if (u_sf_mode != 2) { // not replay mode
#endif
+ uhd::set_thread_priority_safe(1.0);
usrp_state_t *s = (usrp_state_t *)device->priv;
// setup GPIO for TDD, GPIO(4) = ATR_RX
//set data direction register (DDR) to output
@@ -1048,7 +1049,6 @@ extern "C" {
<< use_mmap << std::endl;
} else {
#endif
- uhd::set_thread_priority_safe(1.0);
usrp_state_t *s = (usrp_state_t *)calloc(sizeof(usrp_state_t),1);
if (openair0_cfg[0].clock_source==gpsdo)
@@ -1112,6 +1112,9 @@ extern "C" {
device->type=USRP_X300_DEV;
usrp_master_clock = 184.32e6;
args += boost::str(boost::format(",master_clock_rate=%f") % usrp_master_clock);
+ // USRP recommended: https://files.ettus.com/manual/page_usrp_x3x0_config.html
+ if ( 0 != system("sysctl -w net.core.rmem_max=33554432 net.core.wmem_max=33554432") )
+ LOG_W(HW,"Can't set kernel paramters for X3xx\n");
}
s->usrp = uhd::usrp::multi_usrp::make(args);
diff --git a/targets/ARCH/rfsimulator/simulator.c b/targets/ARCH/rfsimulator/simulator.c
index a17327b03e..099e1c190a 100644
--- a/targets/ARCH/rfsimulator/simulator.c
+++ b/targets/ARCH/rfsimulator/simulator.c
@@ -27,22 +27,15 @@
#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;
+#define sample_t uint32_t // 2*16 bits complex number
typedef struct buffer_s {
int conn_sock;
bool alreadyRead;
uint64_t lastReceivedTS;
bool headerMode;
- transferHeader th;
+ samplesBlockHeader_t th;
char *transferPtr;
uint64_t remainToTransfer;
char *circularBufEnd;
@@ -53,8 +46,8 @@ typedef struct {
int listen_sock, epollfd;
uint64_t nextTimestamp;
uint64_t typeStamp;
- uint64_t initialAhead;
char *ip;
+ int saveIQfile;
buffer_t buf[FD_SETSIZE];
} rfsimulator_state_t;
@@ -63,9 +56,11 @@ void allocCirBuf(rfsimulator_state_t *bridge, int sock) {
AssertFatal ( (ptr->circularBuf=(sample_t *) malloc(sampleToByte(CirSize,1))) != NULL, "");
ptr->circularBufEnd=((char *)ptr->circularBuf)+sampleToByte(CirSize,1);
ptr->conn_sock=sock;
+ ptr->alreadyRead=false;
+ ptr->lastReceivedTS=0;
ptr->headerMode=true;
ptr->transferPtr=(char *)&ptr->th;
- ptr->remainToTransfer=sizeof(transferHeader);
+ ptr->remainToTransfer=sizeof(samplesBlockHeader_t);
int sendbuff=1000*1000*10;
AssertFatal ( setsockopt(sock, SOL_SOCKET, SO_SNDBUF, &sendbuff, sizeof(sendbuff)) == 0, "");
struct epoll_event ev= {0};
@@ -87,12 +82,11 @@ void socketError(rfsimulator_state_t *bridge, int sock) {
LOG_W(HW,"Lost socket \n");
removeCirBuf(bridge, sock);
- if (bridge->typeStamp==MAGICUE)
+ if (bridge->typeStamp==UE_MAGICDL_FDD)
exit(1);
}
}
-
#define helpTxt "\
\x1b[31m\
rfsimulator: error: you have to run one UE and one eNB\n\
@@ -119,9 +113,17 @@ void setblocking(int sock, enum blocking_t active) {
static bool flushInput(rfsimulator_state_t *t);
-void fullwrite(int fd, void *_buf, int count, rfsimulator_state_t *t) {
+void fullwrite(int fd, void *_buf, ssize_t count, rfsimulator_state_t *t) {
+ if (t->saveIQfile != -1) {
+ if (write(t->saveIQfile, _buf, count) != count )
+ LOG_E(HW,"write in save iq file failed (%s)\n",strerror(errno));
+ }
+
+ AssertFatal(fd>=0 && _buf && count >0 && t,
+ "Bug: %d/%p/%zd/%p", fd, _buf, count, t);
+
char *buf = _buf;
- int l;
+ ssize_t l;
setblocking(fd, notBlocking);
while (count) {
@@ -145,7 +147,7 @@ void fullwrite(int fd, void *_buf, int count, rfsimulator_state_t *t) {
int server_start(openair0_device *device) {
rfsimulator_state_t *t = (rfsimulator_state_t *) device->priv;
- t->typeStamp=MAGICeNB;
+ t->typeStamp=ENB_MAGICDL_FDD;
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, "");
@@ -168,7 +170,7 @@ sin_addr:
int start_ue(openair0_device *device) {
rfsimulator_state_t *t = device->priv;
- t->typeStamp=MAGICUE;
+ t->typeStamp=UE_MAGICDL_FDD;
int sock;
AssertFatal((sock = socket(AF_INET, SOCK_STREAM, 0)) >= 0, "");
struct sockaddr_in addr = {
@@ -200,14 +202,16 @@ sin_addr:
return 0;
}
+uint64_t lastW=-1;
int rfsimulator_write(openair0_device *device, openair0_timestamp timestamp, void **samplesVoid, int nsamps, int nbAnt, int flags) {
rfsimulator_state_t *t = device->priv;
+ LOG_D(HW,"sending %d samples at time: %ld\n", nsamps, timestamp);
for (int i=0; ibuf[i];
if (ptr->conn_sock >= 0 ) {
- transferHeader header= {t->typeStamp, nsamps, nbAnt, timestamp};
+ samplesBlockHeader_t header= {t->typeStamp, nsamps, nbAnt, timestamp};
fullwrite(ptr->conn_sock,&header, sizeof(header), t);
sample_t tmpSamples[nsamps][nbAnt];
@@ -222,7 +226,7 @@ int rfsimulator_write(openair0_device *device, openair0_timestamp timestamp, voi
fullwrite(ptr->conn_sock, (void *)tmpSamples, sampleToByte(nsamps,nbAnt), t);
}
}
-
+ lastW=timestamp;
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;
@@ -232,7 +236,7 @@ static 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);
+ int nfds = epoll_wait(t->epollfd, events, FD_SETSIZE, 20);
if ( nfds==-1 ) {
if ( errno==EINTR || errno==EAGAIN )
@@ -263,7 +267,7 @@ static bool flushInput(rfsimulator_state_t *t) {
continue;
}
- int blockSz;
+ ssize_t blockSz;
if ( b->headerMode)
blockSz=b->remainToTransfer;
@@ -272,7 +276,7 @@ static bool flushInput(rfsimulator_state_t *t) {
b->remainToTransfer :
b->circularBufEnd - 1 - b->transferPtr ;
- int sz=recv(fd, b->transferPtr, blockSz, MSG_DONTWAIT);
+ ssize_t sz=recv(fd, b->transferPtr, blockSz, MSG_DONTWAIT);
if ( sz < 0 ) {
if ( errno != EAGAIN ) {
@@ -282,6 +286,7 @@ static bool flushInput(rfsimulator_state_t *t) {
} else if ( sz == 0 )
continue;
+ LOG_D(HW, "Socket rcv %zd bytes\n", sz);
AssertFatal((b->remainToTransfer-=sz) >= 0, "");
b->transferPtr+=sz;
@@ -290,8 +295,8 @@ static bool flushInput(rfsimulator_state_t *t) {
// 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");
+ AssertFatal( (t->typeStamp == UE_MAGICDL_FDD && b->th.magic==ENB_MAGICDL_FDD) ||
+ (t->typeStamp == ENB_MAGICDL_FDD && b->th.magic==UE_MAGICDL_FDD), "Socket Error in protocol");
b->headerMode=false;
b->alreadyRead=true;
@@ -306,23 +311,24 @@ static bool flushInput(rfsimulator_state_t *t) {
}
b->lastReceivedTS=b->th.timestamp;
+ AssertFatal(lastW == -1 || ( abs((double)lastW-b->lastReceivedTS) < (double)CirSize),
+ "Tx/Rx shift too large Tx:%lu, Rx:%lu\n", lastW, b->lastReceivedTS);
b->transferPtr=(char *)&b->circularBuf[b->lastReceivedTS%CirSize];
b->remainToTransfer=sampleToByte(b->th.size, b->th.nbAnt);
}
if ( b->headerMode==false ) {
+ LOG_D(HW,"Set b->lastReceivedTS %ld\n", b->lastReceivedTS);
b->lastReceivedTS=b->th.timestamp+b->th.size-byteToSample(b->remainToTransfer,b->th.nbAnt);
-
+ // First block in UE, resync with the eNB current TS
+ if ( t->nextTimestamp == 0 )
+ t->nextTimestamp=b->lastReceivedTS-b->th.size;
+
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->remainToTransfer=sizeof(samplesBlockHeader_t);
b->th.magic=-1;
}
}
@@ -365,13 +371,14 @@ int rfsimulator_read(openair0_device *device, openair0_timestamp *ptimestamp, vo
do {
have_to_wait=false;
- for ( int sock=0; sockbuf[sock].circularBuf &&
- t->buf[sock].alreadyRead && //>= t->initialAhead &&
- (t->nextTimestamp+nsamps) > t->buf[sock].lastReceivedTS ) {
- have_to_wait=true;
- break;
- }
+ for ( int sock=0; sockbuf[sock].circularBuf && t->buf[sock].alreadyRead )
+ if ( t->buf[sock].lastReceivedTS == 0 ||
+ (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",
@@ -439,6 +446,7 @@ int rfsimulator_set_gains(openair0_device *device, openair0_config_t *openair0_c
__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 ) {
@@ -446,11 +454,26 @@ int device_init(openair0_device *device, openair0_config_t *openair0_cfg) {
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 ?
+ if ( strncasecmp(rfsimulator->ip,"enb",3) == 0 ||
+ strncasecmp(rfsimulator->ip,"server",3) == 0 )
+ rfsimulator->typeStamp = ENB_MAGICDL_FDD;
+ else
+ rfsimulator->typeStamp = UE_MAGICDL_FDD;
+
+ LOG_I(HW,"rfsimulator: running as %s\n", rfsimulator-> typeStamp == ENB_MAGICDL_FDD ? "(eg)NB" : "UE");
+ char *saveF;
+
+ if ((saveF=getenv("saveIQfile")) != NULL) {
+ rfsimulator->saveIQfile=open(saveF,O_APPEND| O_CREAT|O_TRUNC | O_WRONLY, 0666);
+
+ if ( rfsimulator->saveIQfile != -1 )
+ LOG_I(HW,"rfsimulator: will save written IQ samples in %s\n", saveF);
+ else
+ LOG_E(HW, "can't open %s for IQ saving (%s)\n", saveF, strerror(errno));
+ } else
+ rfsimulator->saveIQfile = -1;
+
+ device->trx_start_func = rfsimulator->typeStamp == ENB_MAGICDL_FDD ?
server_start :
start_ue;
device->trx_get_stats_func = rfsimulator_get_stats;
@@ -470,6 +493,5 @@ int device_init(openair0_device *device, openair0_config_t *openair0_cfg) {
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/ARCH/rfsimulator/stored_node.c b/targets/ARCH/rfsimulator/stored_node.c
new file mode 100644
index 0000000000..888b5f6de0
--- /dev/null
+++ b/targets/ARCH/rfsimulator/stored_node.c
@@ -0,0 +1,142 @@
+/*
+ Author: Laurent THOMAS, Open Cells
+ copyleft: OpenAirInterface Software Alliance and it's licence
+*/
+
+#include
+
+
+void fullwrite(int fd, void *_buf, int count) {
+ char *buf = _buf;
+ int l;
+
+ while (count) {
+ l = write(fd, buf, count);
+
+ if (l <= 0) {
+ if (errno==EINTR)
+ continue;
+
+ if(errno==EAGAIN) {
+ continue;
+ } else {
+ AssertFatal(false,"Lost socket\n");
+ }
+ } else {
+ count -= l;
+ buf += l;
+ }
+ }
+}
+
+int server_start(short port) {
+ int listen_sock;
+ AssertFatal((listen_sock = socket(AF_INET, SOCK_STREAM, 0)) >= 0, "");
+ int enable = 1;
+ AssertFatal(setsockopt(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(listen_sock, (struct sockaddr *)&addr, sizeof(addr));
+ AssertFatal(listen(listen_sock, 5) == 0, "");
+ return accept(listen_sock,NULL,NULL);
+}
+
+int client_start(char *IP, short port) {
+ 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(IP);
+ bool connected=false;
+
+ while(!connected) {
+ LOG_I(HW,"rfsimulator: trying to connect to %s:%d\n", IP, port);
+
+ if (connect(sock, (struct sockaddr *)&addr, sizeof(addr)) == 0) {
+ LOG_I(HW,"rfsimulator: connection established\n");
+ connected=true;
+ }
+
+ perror("simulated node");
+ sleep(1);
+ }
+
+ return sock;
+}
+
+enum blocking_t {
+ notBlocking,
+ blocking
+};
+
+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 main(int argc, char *argv[]) {
+ if(argc != 4) {
+ printf("Need parameters: source file, server or destination IP, TCP port\n");
+ exit(1);
+ }
+
+ int fd;
+ AssertFatal((fd=open(argv[1],O_RDONLY)) != -1, "file: %s", argv[1]);
+ off_t fileSize=lseek(fd, 0, SEEK_END);
+ int serviceSock;
+
+ if (strcmp(argv[2],"server")==0) {
+ serviceSock=server_start(atoi(argv[3]));
+ } else {
+ client_start(argv[2],atoi(argv[3]));
+ }
+
+ samplesBlockHeader_t header;
+ int bufSize=100000;
+ void *buff=malloc(bufSize);
+
+ while (1) {
+ //Rewind the file to loop on the samples
+ if ( lseek(fd, 0, SEEK_CUR) >= fileSize )
+ lseek(fd, 0, SEEK_SET);
+
+ // Read one block and send it
+ setblocking(serviceSock, blocking);
+ AssertFatal(read(fd,&header,sizeof(header)), "");
+ fullwrite(serviceSock, &header, sizeof(header));
+ int dataSize=sizeof(sample_t)*header.size*header.nbAnt;
+
+ if (dataSize>bufSize)
+ buff=realloc(buff,dataSize);
+
+ AssertFatal(read(fd,buff,dataSize) == dataSize, "");
+ fullwrite(serviceSock, buff, dataSize);
+ // Purge incoming samples
+ setblocking(serviceSock, notBlocking);
+
+ while(recv(serviceSock,buff, bufSize, MSG_DONTWAIT) > 0) {
+ }
+ }
+
+ return 0;
+}
+
diff --git a/targets/COMMON/openairinterface5g_limits.h b/targets/COMMON/openairinterface5g_limits.h
index b55b4922c5..8c37b10eb7 100644
--- a/targets/COMMON/openairinterface5g_limits.h
+++ b/targets/COMMON/openairinterface5g_limits.h
@@ -14,10 +14,10 @@
// now , if we use --mu option in UE, compiling error will occur.
// This problem will be fixed in the future.
# ifndef UESIM_EXPANSION
-# define NUMBER_OF_UE_MAX 16
-# define NUMBER_OF_NR_UE_MAX 16
-# define NUMBER_OF_CONNECTED_eNB_MAX 3
-# define NUMBER_OF_CONNECTED_gNB_MAX 3
+# define NUMBER_OF_UE_MAX 4
+# define NUMBER_OF_NR_UE_MAX 4
+# define NUMBER_OF_CONNECTED_eNB_MAX 1
+# define NUMBER_OF_CONNECTED_gNB_MAX 1
# else
# define NUMBER_OF_UE_MAX 256
# define NUMBER_OF_NR_UE_MAX 16
diff --git a/targets/RT/USER/lte-uesoftmodem.c b/targets/RT/USER/lte-uesoftmodem.c
index feb11d6a79..f420bf519a 100644
--- a/targets/RT/USER/lte-uesoftmodem.c
+++ b/targets/RT/USER/lte-uesoftmodem.c
@@ -369,15 +369,16 @@ static void *scope_thread(void *arg) {
while (!oai_exit) {
// dump_ue_stats (PHY_vars_UE_g[0][0], &PHY_vars_UE_g[0][0]->proc.proc_rxtx[0],stats_buffer, 0, mode,rx_input_level_dBm);
- //fl_set_object_label(form_stats->stats_text, stats_buffer);
- fl_clear_browser(form_stats->stats_text);
- fl_add_browser_line(form_stats->stats_text, stats_buffer);
- phy_scope_UE(form_ue[0],
- PHY_vars_UE_g[0][0],
- 0,
- 0,7);
- // printf("%s",stats_buffer);
- }
+ //fl_set_object_label(form_stats->stats_text, stats_buffer);
+ fl_clear_browser(form_stats->stats_text);
+ fl_add_browser_line(form_stats->stats_text, stats_buffer);
+
+ phy_scope_UE(form_ue[0],
+ PHY_vars_UE_g[0][0],
+ 0,
+ 0,
+ 7);
+ usleep(10000);
# ifdef ENABLE_XFORMS_WRITE_STATS
@@ -799,7 +800,10 @@ int main( int argc, char **argv ) {
}
cpuf=get_cpu_freq_GHz();
-#ifndef DEADLINE_SCHEDULER
+
+
+#if 0 // #ifndef DEADLINE_SCHEDULER
+
printf("NO deadline scheduler\n");
/* Currently we set affinity for UHD to CPU 0 for eNB/UE and only if number of CPUS >2 */
cpu_set_t cpuset;
diff --git a/targets/RT/USER/nr-softmodem.c b/targets/RT/USER/nr-softmodem.c
index 411281d72a..40d4758847 100644
--- a/targets/RT/USER/nr-softmodem.c
+++ b/targets/RT/USER/nr-softmodem.c
@@ -1238,6 +1238,8 @@ int main( int argc, char **argv )
// wait for end of program
printf("TYPE TO TERMINATE\n");
+ fflush(stdout);
+ fflush(stderr);
//getchar();
#if defined(ENABLE_ITTI)