Merge branch 'integration_2024_w49' into 'develop'

Integration: `2024.w49`

See merge request oai/openairinterface5g!3148

* !3065 NAS Service Request enc/dec implementation
* !3129 Refactor UL MAC PDU decoding
* !3136 Use ninja -k option in CI
* !3137 T tracer: add macpdu traces for the NR UE
* !2392 Documentation: add multi-UE deployment with RFsimulator
* !3145 a lib has been added but missed dependancies
* !3050 doc: Add instructions for 5G NR gNB frequency configuration
* !3141 CI: Allow restart of the container if deployment fails
* !3138 Align YAML config getlist with libconfig implementation
* !3140 remove un-necessary global variables
* !3146 Updates to match more fapi-compliant tx_data.request
* !3025 New threadpool, fixed in NR UE
* CI: Remove USRP mgmt_addr from LTE-2x2 conf files
* !3147 Fronthaul xran library update to F release (2. and final step towards M-plane integration)
* !3142 Add CI test to trigger RLF with high pathloss in channelmod
This commit is contained in:
Robert Schmidt
2024-12-10 13:33:23 +00:00
191 changed files with 4099 additions and 2845 deletions
+6 -7
View File
@@ -1569,6 +1569,10 @@ set(libnas_emm_msg_OBJS
${NAS_SRC}COMMON/EMM/MSG/UplinkNasTransport.c
)
set(libnas_fgs_msg_OBJS
${NAS_SRC}COMMON/EMM/MSG/fgs_service_request.c
)
set(libnas_esm_msg_OBJS
${NAS_SRC}COMMON/ESM/MSG/ActivateDedicatedEpsBearerContextAccept.c
${NAS_SRC}COMMON/ESM/MSG/ActivateDedicatedEpsBearerContextReject.c
@@ -1682,7 +1686,6 @@ set (libnas_utils_OBJS
${NAS_SRC}COMMON/UTIL/nas_timer.c
${NAS_SRC}COMMON/UTIL/socket.c
${NAS_SRC}COMMON/UTIL/stty.c
${NAS_SRC}COMMON/UTIL/TLVEncoder.c
${NAS_SRC}COMMON/UTIL/TLVDecoder.c
${NAS_SRC}COMMON/UTIL/OctetString.c
)
@@ -1793,6 +1796,7 @@ add_library(LIB_NAS_SIMUE
${libnas_api_OBJS}
${libnas_ue_api_OBJS}
${libnas_emm_msg_OBJS}
${libnas_fgs_msg_OBJS}
${libnas_esm_msg_OBJS}
${libnas_ies_OBJS}
${libnas_utils_OBJS}
@@ -1839,6 +1843,7 @@ include_directories(${NAS_SRC}UE)
include_directories(${NAS_SRC}UE/API/USER)
include_directories(${NAS_SRC}UE/API/USIM)
include_directories(${NAS_SRC}UE/EMM)
include_directories(${NAS_SRC}UE/EMM/MSG)
include_directories(${NAS_SRC}UE/EMM/SAP)
include_directories(${NAS_SRC}UE/ESM)
include_directories(${NAS_SRC}UE/ESM/SAP)
@@ -1905,12 +1910,6 @@ add_executable(measurement_display
${OPENAIR_DIR}/common/utils/threadPool/measurement_display.c)
target_link_libraries (measurement_display minimal_lib)
add_executable(test5Gnas
${OPENAIR_DIR}/openair3/TEST/test5Gnas.c
)
target_link_libraries (test5Gnas LIB_5GNAS_GNB minimal_lib )
# lte-softmodem is both eNB and UE implementation
###################################################
+46 -43
View File
@@ -145,10 +145,6 @@ def AnalyzeBuildLogs(buildRoot, images, globalStatus):
collectInfo[image] = files
return collectInfo
def GetContainerName(ssh, svcName, file):
ret = ssh.run(f"docker compose -f {file} config --format json {svcName} | jq -r '.services.\"{svcName}\".container_name'", silent=True)
return ret.stdout
def GetImageName(ssh, svcName, file):
ret = ssh.run(f"docker compose -f {file} config --format json {svcName} | jq -r '.services.\"{svcName}\".image'", silent=True)
if ret.returncode != 0:
@@ -156,17 +152,18 @@ def GetImageName(ssh, svcName, file):
else:
return ret.stdout.strip()
def GetContainerHealth(ssh, containerName):
if containerName is None:
return False
if 'db_init' in containerName or 'db-init' in containerName: # exits with 0, there cannot be healthy
return True
def GetServiceHealth(ssh, svcName, file):
if svcName is None:
return False, f"Service {svcName} not found in {file}"
image = GetImageName(ssh, svcName, file)
if 'db_init' in svcName or 'db-init' in svcName: # exits with 0, there cannot be healthy
return True, f"Service {svcName} healthy, image {image}"
for _ in range(8):
result = ssh.run(f'docker inspect --format="{{{{.State.Health.Status}}}}" {containerName}', silent=True)
result = ssh.run(f"docker compose -f {file} ps --format json {svcName} | jq -r 'if type==\"array\" then .[0].Health else .Health end'", silent=True)
if result.stdout == 'healthy':
return True
return True, f"Service {svcName} healthy, image {image}"
time.sleep(5)
return False
return False, f"Failed to deploy: service {svcName}"
def ExistEnvFilePrint(ssh, wd, prompt='env vars in existing'):
ret = ssh.run(f'cat {wd}/.env', silent=True, reportNonZero=False)
@@ -218,9 +215,9 @@ def GetServices(ssh, requested, file):
else:
return requested
def CopyinContainerLog(ssh, lSourcePath, yaml, containerName, filename):
def CopyinServiceLog(ssh, lSourcePath, yaml, svcName, wd_yaml, filename):
remote_filename = f"{lSourcePath}/cmake_targets/log/{filename}"
ssh.run(f'docker logs {containerName} &> {remote_filename}')
ssh.run(f'docker compose -f {wd_yaml} logs {svcName} --no-log-prefix &> {remote_filename}')
local_dir = f"{os.getcwd()}/../cmake_targets/log/{yaml}"
local_filename = f"{local_dir}/{filename}"
return ssh.copyin(remote_filename, local_filename)
@@ -336,6 +333,7 @@ class Containerize():
self.imageToCopy = ''
#checkers from xml
self.ran_checkers={}
self.num_attempts = 1
self.flexricTag = ''
@@ -843,50 +841,55 @@ class Containerize():
def DeployObject(self, HTML):
svr = self.eNB_serverId[self.eNB_instance]
num_attempts = self.num_attempts
lIpAddr, lSourcePath = self.GetCredentials(svr)
logging.debug('\u001B[1m Deploying OAI Object on server: ' + lIpAddr + '\u001B[0m')
logging.debug(f'Deploying OAI Object on server: {lIpAddr}')
yaml = self.yamlPath[self.eNB_instance].strip('/')
# creating the log folder by default
local_dir = f"{os.getcwd()}/../cmake_targets/log/{yaml.split('/')[-1]}"
os.system(f'mkdir -p {local_dir}')
wd = f'{lSourcePath}/{yaml}'
wd_yaml = f'{wd}/docker-compose.y*ml'
yaml_dir = yaml.split('/')[-1]
with cls_cmd.getConnection(lIpAddr) as ssh:
services = GetServices(ssh, self.services[self.eNB_instance], f"{wd}/docker-compose.y*ml")
services = GetServices(ssh, self.services[self.eNB_instance], wd_yaml)
if services == [] or services == ' ' or services == None:
msg = "Cannot determine services to start"
msg = 'Cannot determine services to start'
logging.error(msg)
HTML.CreateHtmlTestRowQueue('N/A', 'KO', [msg])
return False
ExistEnvFilePrint(ssh, wd)
WriteEnvFile(ssh, services, wd, self.deploymentTag, self.flexricTag)
logging.info(f"will start services {services}")
status = ssh.run(f'docker compose -f {wd}/docker-compose.y*ml up -d -- {services}')
if status.returncode != 0:
msg = f"cannot deploy services {services}: {status.stdout}"
logging.error(msg)
HTML.CreateHtmlTestRowQueue('N/A', 'KO', [msg])
return False
imagesInfo = []
fstatus = True
for svc in services.split():
containerName = GetContainerName(ssh, svc, f"{wd}/docker-compose.y*ml")
healthy = GetContainerHealth(ssh, containerName)
if not healthy:
imagesInfo += [f"Failed to deploy: service {svc}"]
fstatus = False
else:
image = GetImageName(ssh, svc, f"{wd}/docker-compose.y*ml")
logging.info(f"service {svc} healthy, container {containerName}, image {image}")
imagesInfo += [f"service {svc} healthy, image {image}"]
if fstatus:
if num_attempts <= 0:
raise ValueError(f'Invalid value for num_attempts: {num_attempts}, must be greater than 0')
for attempt in range(num_attempts):
imagesInfo = []
healthInfo = []
logging.info(f'will start services {services}')
status = ssh.run(f'docker compose -f {wd_yaml} up -d -- {services}')
if status.returncode != 0:
msg = f'cannot deploy services {services}: {status.stdout}'
logging.error(msg)
HTML.CreateHtmlTestRowQueue('N/A', 'NOK', [msg])
return False
for svc in services.split():
health, msg = GetServiceHealth(ssh, svc, f'{wd_yaml}')
logging.info(msg)
imagesInfo.append(msg)
healthInfo.append(health)
deployed = all(healthInfo)
if deployed:
break
elif (attempt < num_attempts - 1):
logging.warning(f'Failed to deploy on attempt {attempt}, restart services {services}')
for svc in services.split():
CopyinServiceLog(ssh, lSourcePath, yaml_dir, svc, wd_yaml, f'{svc}-{HTML.testCase_id}-attempt{attempt}.log')
ssh.run(f'docker compose -f {wd_yaml} down -- {services}')
if deployed:
HTML.CreateHtmlTestRowQueue('N/A', 'OK', ['\n'.join(imagesInfo)])
else:
HTML.CreateHtmlTestRowQueue('N/A', 'KO', ['\n'.join(imagesInfo)])
return fstatus
return deployed
def UndeployObject(self, HTML, RAN):
svr = self.eNB_serverId[self.eNB_instance]
@@ -902,7 +905,7 @@ class Containerize():
if services is not None:
all_serv = " ".join([s for s, _ in services])
ssh.run(f'docker compose -f {wd}/docker-compose.y*ml stop -- {all_serv}')
copyin_res = all(CopyinContainerLog(ssh, lSourcePath, yaml_dir, c, f'{s}-{HTML.testCase_id}.log') for s, c in services)
copyin_res = all(CopyinServiceLog(ssh, lSourcePath, yaml_dir, s, f"{wd}/docker-compose.y*ml", f'{s}-{HTML.testCase_id}.log') for s, c in services)
else:
logging.warning('could not identify services to stop => no log file')
ssh.run(f'docker compose -f {wd}/docker-compose.y*ml down -v')
@@ -230,7 +230,7 @@ RUs = (
max_pdschReferenceSignalPower = -27;
max_rxgain = 75;
eNB_instances = [0];
sdr_addrs = "mgmt_addr=172.21.19.13,addr=192.168.80.250";
sdr_addrs = "addr=192.168.80.250";
}
);
@@ -230,7 +230,7 @@ RUs = (
max_pdschReferenceSignalPower = -27;
max_rxgain = 75;
eNB_instances = [0];
sdr_addrs = "mgmt_addr=172.21.19.13,addr=192.168.80.250";
sdr_addrs = "addr=192.168.80.250";
}
);
@@ -230,7 +230,7 @@ RUs = (
max_pdschReferenceSignalPower = -27;
max_rxgain = 75;
eNB_instances = [0];
sdr_addrs = "mgmt_addr=172.21.19.13,addr=192.168.80.250";
sdr_addrs = "addr=192.168.80.250";
}
);
@@ -263,11 +263,6 @@ fhi_72 = {
ru_addr = ("98:ae:71:01:c5:eb", "98:ae:71:01:c5:eb");
mtu = 9600;
fh_config = ({
Tadv_cp_dl = 125;
T2a_cp_dl = (285, 429);
T2a_cp_ul = (285, 429);
T2a_up = (125, 428);
Ta3 = (130, 170);
T1a_cp_dl = (285, 470);
T1a_cp_ul = (285, 429);
T1a_up = (125, 350);
@@ -271,11 +271,6 @@ fhi_72 = {
ru_addr = ("70:b3:d5:e1:5b:81", "70:b3:d5:e1:5b:81");
mtu = 9600;
fh_config = ({
Tadv_cp_dl = 125;
T2a_cp_dl = (259, 500);
T2a_cp_ul = (25, 500);
T2a_up = (134, 375);
Ta3 = (152, 160);
T1a_cp_dl = (419, 470);
T1a_cp_ul = (285, 336);
T1a_up = (294, 345);
+4 -4
View File
@@ -11,10 +11,10 @@ Ref :
feptx_prec : 13.0
feptx_ofdm : 33.0
feptx_total : 55.0
L1 Tx processing : 220.0
DLSCH encoding : 130.0
L1 Rx processing : 387.0
PUSCH inner-receiver : 150.0
L1 Tx processing : 200.0
DLSCH encoding : 100.0
L1 Rx processing : 330.0
PUSCH inner-receiver : 120.0
Schedule Response : 3.0
DL & UL scheduling timing : 6.0
UL Indication : 3.0
+1
View File
@@ -349,6 +349,7 @@ def ExecuteActionWithParam(action):
string_field = test.findtext('services')
if string_field is not None:
CONTAINERS.services[CONTAINERS.eNB_instance] = string_field
CONTAINERS.num_attempts = int(test.findtext('num_attempts') or 1)
CONTAINERS.deploymentTag = cls_containerize.CreateTag(CONTAINERS.ranCommitID, CONTAINERS.ranBranch, CONTAINERS.ranAllowMerge)
if action == 'Deploy_Object':
success = CONTAINERS.DeployObject(HTML)
+10
View File
@@ -47,6 +47,7 @@ class TestDeploymentMethods(unittest.TestCase):
self.cont.eNBUserName = None
self.cont.eNBPassword = None
self.cont.eNBSourceCodePath = os.getcwd()
self.cont.num_attempts = 3
def test_deploy(self):
self.cont.yamlPath[0] = 'tests/simple-dep/'
@@ -65,6 +66,15 @@ class TestDeploymentMethods(unittest.TestCase):
self.assertFalse(deploy)
self.cont.yamlPath = old
def test_deployfails_2svc(self):
# fails reliably
old = self.cont.yamlPath
self.cont.yamlPath[0] = 'tests/simple-fail-2svc/'
deploy = self.cont.DeployObject(self.html)
self.cont.UndeployObject(self.html, self.ran)
self.assertFalse(deploy)
self.cont.yamlPath = old
def test_deploy_ran(self):
self.cont.yamlPath[0] = 'yaml_files/5g_rfsimulator_tdd_dora'
self.cont.services[0] = "oai-gnb"
@@ -0,0 +1,23 @@
services:
test1:
image: ubuntu:jammy
container_name: test_container1
cap_drop:
- ALL
entrypoint: /bin/bash -c "false"
healthcheck:
test: /bin/bash -c "true"
interval: 1s
timeout: 1s
retries: 1
test2:
image: ubuntu:jammy
container_name: test_container2
cap_drop:
- ALL
entrypoint: /bin/bash -c "sleep infinity"
healthcheck:
test: /bin/bash -c "true"
interval: 1s
timeout: 1s
retries: 1
+19 -7
View File
@@ -39,6 +39,12 @@
040002
030021
030022
040021
000030
040022
040023
020022
040024
100021
222222
</TestCaseRequestedList>
@@ -74,6 +80,12 @@
<eNB_serverId>0</eNB_serverId>
</testCase>
<testCase id="000030">
<class>IdleSleep</class>
<desc>Sleep</desc>
<idle_sleep_time_in_sec>5</idle_sleep_time_in_sec>
</testCase>
<testCase id="000023">
<class>Attach_UE</class>
<desc>Attach OAI UE (Wait for IP)</desc>
@@ -149,9 +161,9 @@
<testCase id="040021">
<class>Custom_Command</class>
<desc>Simulate a disruption of DL radio channel (ploss 55)(5 sec)</desc>
<desc>Simulate a disruption of DL radio channel (ploss 55)</desc>
<node>cacofonix</node>
<command>echo channelmod modify 0 ploss 55 | nc 192.168.71.181 8091 &amp;&amp; sleep 5</command>
<command>echo channelmod modify 0 ploss 55 | nc 192.168.71.181 8091</command>
<command_fail>yes</command_fail>
</testCase>
@@ -165,9 +177,9 @@
<testCase id="040023">
<class>Custom_Command</class>
<desc>Restoration of the original DL channel conditions (ploss 0)(5 sec)</desc>
<desc>Restoration of the original DL channel conditions (ploss 20)</desc>
<node>cacofonix</node>
<command>echo channelmod modify 0 ploss 0 | nc 192.168.71.181 8091 &amp;&amp; sleep 5</command>
<command>echo channelmod modify 0 ploss 20 | nc 192.168.71.181 8091</command>
<command_fail>yes</command_fail>
</testCase>
@@ -175,7 +187,7 @@
<class>Custom_Command</class>
<desc>Get UE sync state (UE ID 0)</desc>
<node>cacofonix</node>
<command>echo ciUE sync_state 0 | nc 192.168.71.181 8091 | grep -E UE_CONNECTED &amp;&amp; sleep 10</command>
<command>echo ciUE sync_state 0 | nc 192.168.71.181 8091 | grep -E UE_CONNECTED</command>
<command_fail>yes</command_fail>
</testCase>
@@ -184,8 +196,8 @@
<always_exec>true</always_exec>
<desc>Undeploy all OAI 5G stack</desc>
<yaml_path>ci-scripts/yaml_files/5g_f1_rfsimulator</yaml_path>
<d_retx_th>30,30,100,100</d_retx_th>
<u_retx_th>30,30,100,100</u_retx_th>
<d_retx_th>30,100,100,100</d_retx_th>
<u_retx_th>30,100,100,100</u_retx_th>
<eNB_instance>0</eNB_instance>
<eNB_serverId>0</eNB_serverId>
</testCase>
@@ -89,6 +89,7 @@
<yaml_path>ci-scripts/yaml_files/5g_sa_n310_2x2_100MHz</yaml_path>
<eNB_instance>0</eNB_instance>
<eNB_serverId>0</eNB_serverId>
<num_attempts>3</num_attempts>
</testCase>
<testCase id="000001">
@@ -89,6 +89,7 @@
<yaml_path>ci-scripts/yaml_files/5g_sa_n310_2x2_60MHz</yaml_path>
<eNB_instance>0</eNB_instance>
<eNB_serverId>0</eNB_serverId>
<num_attempts>3</num_attempts>
</testCase>
<testCase id="000001">
@@ -89,6 +89,7 @@
<yaml_path>ci-scripts/yaml_files/5g_sa_n310_4x4_60MHz</yaml_path>
<eNB_instance>0</eNB_instance>
<eNB_serverId>0</eNB_serverId>
<num_attempts>3</num_attempts>
</testCase>
<testCase id="000001">
@@ -80,6 +80,7 @@
<yaml_path>ci-scripts/yaml_files/5g_sa_n310_gnb</yaml_path>
<eNB_instance>0</eNB_instance>
<eNB_serverId>0</eNB_serverId>
<num_attempts>3</num_attempts>
</testCase>
<testCase id="800814">
<class>Create_Workspace</class>
@@ -93,6 +94,7 @@
<yaml_path>ci-scripts/yaml_files/5g_sa_n310_nrue</yaml_path>
<eNB_instance>1</eNB_instance>
<eNB_serverId>1</eNB_serverId>
<num_attempts>3</num_attempts>
</testCase>
<testCase id="000001">
-1
View File
@@ -145,7 +145,6 @@ set(util_SRC
${OPENAIR_NAS_DIR}/COMMON/UTIL/OctetString.c
${OPENAIR_NAS_DIR}/COMMON/UTIL/parser.c
${OPENAIR_NAS_DIR}/COMMON/UTIL/TLVDecoder.c
${OPENAIR_NAS_DIR}/COMMON/UTIL/TLVEncoder.c
${OPENAIR_NAS_DIR}/COMMON/UTIL/socket.c
${OPENAIR_NAS_DIR}/COMMON/UTIL/stty.c
)
+10 -4
View File
@@ -48,6 +48,7 @@ CMAKE_BUILD_TYPE="RelWithDebInfo"
CMAKE_CMD="$CMAKE"
OPTIONAL_LIBRARIES="telnetsrv enbscope uescope nrscope ldpc_cuda ldpc_t2 websrv oai_iqplayer imscope"
TARGET_LIST=""
BUILD_TOOL_OPT="-j$(nproc)"
function print_help() {
echo_info "
@@ -56,6 +57,8 @@ for a number of distributions (Ubuntu 22-24, Fedora, RHEL9).
Options:
--arch-native
Passes -march=native to the compiler.
--build-tool-opt
Pass options to build tool (ninja/make), e.g. -k (\"keep going\")
-c | --clean
Erase all files to make a rebuild from start
-C | --clean-all
@@ -160,6 +163,9 @@ function main() {
--arch-native)
echo_fatal "Error: specify --arch-native on the command line to cmake directly: ./build_oai --cmake-opt \"-DCMAKE_C_FLAGS=-march=native -DCMAKE_CXX_FLAGS=-march=native\""
shift;;
--build-tool-opt)
BUILD_TOOL_OPT+=" $2"
shift 2;;
-c | --clean)
CLEAN=1
shift;;
@@ -490,7 +496,7 @@ function main() {
CMAKE_CMD="$CMAKE_CMD ../../.."
echo_info "Running \"$CMAKE_CMD\""
eval $CMAKE_CMD
compilations $BUILD_DIR all.txt $TARGET_LIST
compilations $BUILD_DIR all.txt "$TARGET_LIST" "${BUILD_TOOL_OPT}"
###################
# Doxygen Support #
###################
@@ -513,9 +519,9 @@ function main() {
cd $DIR/nas_sim_tools/build
${CMAKE_CMD% *} ..
compilations nas_sim_tools usim.txt usim
compilations nas_sim_tools nvram.txt nvram
compilations nas_sim_tools conf2uedata.txt conf2uedata
compilations nas_sim_tools usim.txt "usim" "${BUILD_TOOL_OPT}"
compilations nas_sim_tools nvram.txt "nvram" "${BUILD_TOOL_OPT}"
compilations nas_sim_tools conf2uedata.txt "conf2uedata" "${BUILD_TOOL_OPT}"
# generate USIM data
if [ -f conf2uedata ]; then
@@ -31,7 +31,6 @@ set(CONF2UEDATA_LIB_SRC
${OPENAIR_DIR}/openair3/NAS/UE/API/USIM/aka_functions.c
${OPENAIR_DIR}/common/utils/mem/memory.c
${OPENAIR_DIR}/openair3/NAS/COMMON/UTIL/OctetString.c
${OPENAIR_DIR}/openair3/NAS/COMMON/UTIL/TLVEncoder.c
${OPENAIR_DIR}/common/utils/utils.c
)
+7 -7
View File
@@ -208,20 +208,20 @@ check_errors() {
}
compilations() {
[[ $# -gt 2 ]] || echo_fatal "compilations needs more than three arguments"
[[ $# -eq 4 ]] || echo_fatal "compilations <dir> <logfile> <targets> <build-tool-opt>"
local dir=$1
shift 1
local logfile=$1
shift 1
local targets=$@
local logfile=$2
local targets=$3
local build_tool_opt=$4
local verbose=$([ "$VERBOSE_COMPILE" == "1" ] && echo "-v" || echo "")
echo cd $OPENAIR_DIR/cmake_targets/$dir/build
cd $OPENAIR_DIR/cmake_targets/$dir/build
echo_info "Running \"$CMAKE --build . $verbose --target $targets -- -j$(nproc)\"" $green
cmd="$CMAKE --build . ${verbose} --target ${targets} -- ${build_tool_opt}"
echo_info "Running \"${cmd}\"" $green
echo "Log file for compilation is being written to: $dlog/$logfile"
set +e
{
$CMAKE --build . $verbose --target $targets -- -j$(nproc)
eval ${cmd}
ret=$?
} > $dlog/$logfile 2>&1
# Print the errors and warnings for CI purposes
@@ -0,0 +1,493 @@
diff --git a/fhi_lib/app/src/common.h b/fhi_lib/app/src/common.h
index ac5f471..bbd39fe 100644
--- a/fhi_lib/app/src/common.h
+++ b/fhi_lib/app/src/common.h
@@ -28,7 +28,7 @@
#include <rte_common.h>
#include <rte_mbuf.h>
-#define VERSIONX "oran_f_release_v1.0"
+#define VERSIONX "oran_f_release_v1.1"
#define APP_O_DU 0
#define APP_O_RU 1
diff --git a/fhi_lib/lib/Makefile b/fhi_lib/lib/Makefile
index eccc4ae..8ddb22e 100644
--- a/fhi_lib/lib/Makefile
+++ b/fhi_lib/lib/Makefile
@@ -23,12 +23,18 @@ MYCUSTOMSPACE1='------------------------------------------------------------'
##############################################################
# Tools configuration
##############################################################
-ifeq ($(WIRELESS_SDK_TOOLCHAIN),icc)
-CC := icc
-CPP := icpc
-AS := as
-AR := ar
-LD := icc
+ifeq ($(WIRELESS_SDK_TOOLCHAIN),gcc)
+ CC := gcc
+ CPP := g++
+ AS := as
+ AR := ar
+ LD := gcc
+else ifeq ($(WIRELESS_SDK_TOOLCHAIN),icc)
+ CC := icc
+ CPP := icpc
+ AS := as
+ AR := ar
+ LD := icc
else ifeq ($(WIRELESS_SDK_TOOLCHAIN),icx)
CC := icx
CPP := icpx
@@ -72,7 +78,7 @@ ifeq ($(RTE_SDK),)
endif
RTE_TARGET ?= x86_64-native-linux-icc
-RTE_INC := $(shell PKG_CONFIG_PATH=/usr/lib64/pkgconfig:$(RTE_SDK)/build/meson-uninstalled pkgconf --cflags-only-I libdpdk)
+RTE_INC := $(shell PKG_CONFIG_PATH=$(PKG_CONFIG_PATH):/usr/lib64/pkgconfig:$(RTE_SDK)/build/meson-uninstalled pkgconf --cflags-only-I libdpdk)
API_DIR := $(PROJECT_DIR)/api
SRC_DIR := $(PROJECT_DIR)/src
@@ -110,8 +116,7 @@ CPP_SRC = $(SRC_DIR)/xran_compression.cpp \
$(SRC_DIR)/xran_bfp_cplane32.cpp \
$(SRC_DIR)/xran_bfp_cplane64.cpp \
$(SRC_DIR)/xran_bfp_uplane_9b16rb.cpp \
- $(SRC_DIR)/xran_bfp_uplane.cpp \
- $(SRC_DIR)/xran_mod_compression.cpp
+ $(SRC_DIR)/xran_bfp_uplane.cpp
CPP_SRC_SNC = $(SRC_DIR)/xran_compression_snc.cpp \
$(SRC_DIR)/xran_bfp_cplane8_snc.cpp \
@@ -127,7 +132,7 @@ CC_FLAGS += -std=gnu11 -Wall -Wno-deprecated-declarations \
-fPIC \
-Wall \
-Wimplicit-function-declaration \
- -g -O3 -mcmodel=large
+ -g -O -mavx512bw -march=skylake-avx512 -mtune=skylake-avx512#--wd1786 -mcmodel=large
ifeq ($(WIRELESS_SDK_TOOLCHAIN),icc)
CC_FLAGS += -wd1786 -restrict
@@ -138,8 +143,9 @@ CC_FLAGS += -march=icelake-server -mintrinsic-promote -Wno-unused-function -Wno-
endif
CPP_FLAGS := -D__STDC_LIMIT_MACROS -D__STDC_CONSTANT_MACROS -D_GNU_SOURCE -D_REENTRANT -pipe \
- -falign-functions=16 \
- -Werror -Wno-unused-variable -std=c++14 -mcmodel=large -fPIC
+ -fPIC \
+ -falign-functions=16 \
+ -Werror -Wno-unused-variable -std=c++14 -mcmodel=large -mavx512bw -march=skylake-avx512 -mtune=skylake-avx512
ifeq ($(WIRELESS_SDK_TOOLCHAIN),icc)
CPP_FLAGS += -fp-model fast=2 -no-prec-div -no-prec-sqrt -fast-transcendentals -restrict
@@ -186,8 +192,8 @@ CPP_SNC_OBJTARGETS := $(addprefix $(PROJECT_OBJ_DIR)/,$(CPP_OBJS_SNC))
AS_OBJTARGETS := $(addprefix $(PROJECT_OBJ_DIR)/,$(AS_OBJS))
#-qopt-report=5 -qopt-matmul -qopt-report-phase=all
-CPP_COMP := -O3 -DNDEBUG -xcore-avx512 -fPIE -fasm-blocks
-CPP_COMP_SNC := -O3 -DNDEBUG -march=icelake-server -fPIE -fasm-blocks
+CPP_COMP := -O3 -DNDEBUG -fPIE
+CPP_COMP_SNC := -O3 -DNDEBUG -march=icelake-server -fPIE
CC_FLAGS_FULL := $(CC_FLAGS) $(INC) $(DEF)
CPP_FLAGS_FULL := $(CPP_FLAGS) $(CPP_COMP) $(INC) $(DEF)
CPP_FLAGS_FULL_SNC := $(CPP_FLAGS) $(CPP_COMP_SNC) $(INC) $(DEF)
diff --git a/fhi_lib/lib/api/xran_fh_o_du.h b/fhi_lib/lib/api/xran_fh_o_du.h
index bacf597..90a42a2 100644
--- a/fhi_lib/lib/api/xran_fh_o_du.h
+++ b/fhi_lib/lib/api/xran_fh_o_du.h
@@ -1193,6 +1193,31 @@ int32_t xran_reg_physide_cb_by_dev_id(void *pHandle, xran_fh_tti_callback_fn Cb,
*/
int32_t xran_get_slot_idx (uint32_t PortId, uint32_t *nFrameIdx, uint32_t *nSubframeIdx, uint32_t *nSlotIdx, uint64_t *nSecond);
+/**
+ * @ingroup xran
+ *
+ * Function returns Frame, Subframe, Slot Number based on rx_tti
+ *
+ * @param tti
+ * tti for which to compute Frame, Subframe, Slot
+ *
+ * @param nFrameIdx
+ * Pointer to Frame number [0-99]
+ *
+ * @param nSubframeIdx
+ * Pointer to Subframe number [0-10]
+ *
+ * @param nSlotIdx
+ * Pointer to Slot number [0-7]
+ *
+ * @param nSecond
+ * Pointer to current UTC second
+ *
+ * @return
+ * current TTI number [0-7999]
+ */
+int32_t xran_get_slot_idx_from_tti(uint32_t tti, uint32_t *nFrameIdx, uint32_t *nSubframeIdx, uint32_t *nSlotIdx, uint64_t *nSecond);
+
/**
* @ingroup xran
*
diff --git a/fhi_lib/lib/api/xran_up_api.h b/fhi_lib/lib/api/xran_up_api.h
index 46e0e1d..409ef4b 100644
--- a/fhi_lib/lib/api/xran_up_api.h
+++ b/fhi_lib/lib/api/xran_up_api.h
@@ -80,6 +80,7 @@ int32_t xran_extract_iq_samples(struct rte_mbuf *mbuf,
uint8_t *subframe_id,
uint8_t *slot_id,
uint8_t *symb_id,
+ uint8_t *filter_id,
union ecpri_seq_id *seq_id,
uint16_t *num_prbu,
uint16_t *start_prbu,
@@ -89,7 +90,8 @@ int32_t xran_extract_iq_samples(struct rte_mbuf *mbuf,
int8_t expect_comp,
enum xran_comp_hdr_type staticComp,
uint8_t *compMeth,
- uint8_t *iqWidth);
+ uint8_t *iqWidth,
+ uint8_t *is_prach);
int xran_prepare_iq_symbol_portion(
struct rte_mbuf *mbuf,
diff --git a/fhi_lib/lib/ethernet/ethdi.c b/fhi_lib/lib/ethernet/ethdi.c
index f5b2fd6..e949fe7 100644
--- a/fhi_lib/lib/ethernet/ethdi.c
+++ b/fhi_lib/lib/ethernet/ethdi.c
@@ -325,8 +325,8 @@ xran_ethdi_init_dpdk_io(char *name, const struct xran_io_cfg *io_cfg,
char bbdev_wdev[32] = "";
char bbdev_vdev[32] = "";
char iova_mode[32] = "--iova-mode=pa";
- char socket_mem[32] = "--socket-mem=8192";
- char socket_limit[32] = "--socket-limit=8192";
+ char socket_mem[32] = "--socket-mem=0";
+ char socket_limit[32] = "--socket-limit=0";
char ring_name[32] = "";
int32_t xran_port = -1;
queueid_t qi = 0;
@@ -336,7 +336,7 @@ xran_ethdi_init_dpdk_io(char *name, const struct xran_io_cfg *io_cfg,
cpu = sched_getcpu();
node = numa_node_of_cpu(cpu);
- char *argv[] = { name, core_mask, "-n2", iova_mode, socket_mem, socket_limit, "--proc-type=auto",
+ char *argv[] = { name, core_mask, "-n2", iova_mode, socket_mem, socket_limit, "--proc-type=auto", "--no-telemetry",
"--file-prefix", name, "-a0000:00:00.0", bbdev_wdev, bbdev_vdev};
if (io_cfg == NULL)
@@ -481,11 +481,13 @@ xran_ethdi_init_dpdk_io(char *name, const struct xran_io_cfg *io_cfg,
ctx->tx_ring[i] = rte_ring_create(ring_name, NUM_MBUFS_RING_TRX,
rte_lcore_to_socket_id(*lcore_id), RING_F_SC_DEQ);
PANIC_ON(ctx->tx_ring[i] == NULL, "failed to allocate rx ring");
+ printf("Created ring %s on core %d\n",ring_name,*lcore_id);
for(qi = 0; qi < io_cfg->num_rxq; qi++) {
snprintf(ring_name, RTE_DIM(ring_name), "%s_%d_%d", "rx_ring_cp", i, qi);
ctx->rx_ring[i][qi] = rte_ring_create(ring_name, NUM_MBUFS_RING_TRX,
rte_lcore_to_socket_id(*lcore_id), RING_F_SP_ENQ);
PANIC_ON(ctx->rx_ring[i][qi] == NULL, "failed to allocate rx ring");
+ printf("Created ring %s on core %d\n",ring_name,*lcore_id);
}
}
} else {
@@ -555,7 +557,7 @@ xran_ethdi_init_dpdk_io(char *name, const struct xran_io_cfg *io_cfg,
ctx->up_dl_pkt_gen_ring[i] = rte_ring_create(ring_name, NUM_MBUFS_RING,
rte_lcore_to_socket_id(*lcore_id), /*RING_F_SC_DEQ*/0);
PANIC_ON(ctx->up_dl_pkt_gen_ring[i] == NULL, "failed to allocate dl gen ring");
- printf("created %s\n", ring_name);
+ printf("created %s on core %d\n", ring_name, *lcore_id);
}
return 1;
diff --git a/fhi_lib/lib/src/xran_bfp_ref.cpp b/fhi_lib/lib/src/xran_bfp_ref.cpp
index e6d3067..8e0abee 100644
--- a/fhi_lib/lib/src/xran_bfp_ref.cpp
+++ b/fhi_lib/lib/src/xran_bfp_ref.cpp
@@ -29,6 +29,7 @@
#include <complex>
#include <algorithm>
#include <limits.h>
+#include <limits>
static int16_t saturateAbs(int16_t inVal)
{
diff --git a/fhi_lib/lib/src/xran_bfp_uplane.cpp b/fhi_lib/lib/src/xran_bfp_uplane.cpp
index 59b6850..322d238 100644
--- a/fhi_lib/lib/src/xran_bfp_uplane.cpp
+++ b/fhi_lib/lib/src/xran_bfp_uplane.cpp
@@ -90,7 +90,7 @@ namespace BFP_UPlane
{
const __m512i* rawData = reinterpret_cast<const __m512i*>(dataIn.dataExpanded);
/// Abs
- const auto rawDataAbs = _mm512_abs_epi16(rawData[0]);
+ const auto rawDataAbs = _mm512_abs_epi16(_mm512_loadu_epi16(rawData));
/// No need to do a full horizontal max operation here, just do a max IQ step,
/// compute the exponents and then use a reduce max over all exponent values. This
/// is the fastest way to handle a single RB.
@@ -116,7 +116,7 @@ namespace BFP_UPlane
/// Get AVX512 pointer aligned to desired RB
const __m512i* rawDataIn = reinterpret_cast<const __m512i*>(dataIn.dataExpanded + numREOffset);
/// Apply the exponent shift
- const auto compData = _mm512_srai_epi16(*rawDataIn, thisExp);
+ const auto compData = _mm512_srai_epi16(_mm512_loadu_epi16(rawDataIn), thisExp);
/// Pack compressed data network byte order
const auto compDataBytePacked = networkBytePack(compData);
/// Store exponent first
@@ -201,7 +201,7 @@ namespace BFP_UPlane
/// Get AVX512 pointer aligned to desired RB
const __m512i* rawDataIn = reinterpret_cast<const __m512i*>(dataIn.dataExpanded + numREOffset);
/// Apply the exponent shift
- const auto compData = _mm512_srai_epi16(*rawDataIn, thisExp);
+ const auto compData = _mm512_srai_epi16(_mm512_loadu_epi16(rawDataIn), thisExp);
/// Store exponent first
dataOut->dataCompressed[thisRBExpAddr] = thisExp;
/// Now have 1 RB worth of bytes separated into 3 chunks (1 per lane)
@@ -432,4 +432,4 @@ BlockFloatCompander::BFPExpandUserPlaneAvx512(const CompressedData& dataIn, Expa
BFP_UPlane::expandByAllocN<BlockFloatCompander::networkByteUnpack12b>(dataIn, dataOut, k_totNumBytesPerRB12, k_maxExpShift12);
break;
}
-}
\ No newline at end of file
+}
diff --git a/fhi_lib/lib/src/xran_common.c b/fhi_lib/lib/src/xran_common.c
index dc40ad9..4ac1fbf 100644
--- a/fhi_lib/lib/src/xran_common.c
+++ b/fhi_lib/lib/src/xran_common.c
@@ -714,11 +714,14 @@ process_mbuf(struct rte_mbuf *pkt, void* handle, struct xran_eaxc_info *p_cid)
uint8_t compMeth = 0;
uint8_t iqWidth = 0;
+ uint8_t is_prach = 0;
+
int ret = MBUF_FREE;
uint32_t mb_free = 0;
int32_t valid_res = 0;
int expect_comp = (p_dev_ctx->fh_cfg.ru_conf.compMeth != XRAN_COMPMETHOD_NONE);
enum xran_comp_hdr_type staticComp = p_dev_ctx->fh_cfg.ru_conf.xranCompHdrType;
+ uint8_t filter_id;
if(first_call == 0)
return ret;
@@ -733,9 +736,9 @@ process_mbuf(struct rte_mbuf *pkt, void* handle, struct xran_eaxc_info *p_cid)
return MBUF_FREE;
num_bytes = xran_extract_iq_samples(pkt, &iq_samp_buf,
- &CC_ID, &Ant_ID, &frame_id, &subframe_id, &slot_id, &symb_id, &seq,
+ &CC_ID, &Ant_ID, &frame_id, &subframe_id, &slot_id, &symb_id, &filter_id, &seq,
&num_prbu, &start_prbu, &sym_inc, &rb, &sect_id,
- expect_comp, staticComp, &compMeth, &iqWidth);
+ expect_comp, staticComp, &compMeth, &iqWidth, &is_prach);
if (num_bytes <= 0)
{
print_err("num_bytes is wrong [%d]\n", num_bytes);
@@ -781,10 +784,9 @@ process_mbuf(struct rte_mbuf *pkt, void* handle, struct xran_eaxc_info *p_cid)
else
{
- valid_res = xran_pkt_validate(p_dev_ctx,
- pkt, iq_samp_buf, num_bytes,
- CC_ID, Ant_ID, frame_id, subframe_id, slot_id, symb_id,
- &seq, num_prbu, start_prbu, sym_inc, rb, sect_id);
+ pCnt->rx_counter++;
+ pCnt->Rx_on_time++;
+ pCnt->Total_msgs_rcvd++;
#ifndef FCN_ADAPT
if(valid_res != 0)
{
@@ -807,8 +809,7 @@ process_mbuf(struct rte_mbuf *pkt, void* handle, struct xran_eaxc_info *p_cid)
PrachCfg = &(p_dev_ctx->PrachCPConfig);
}
- if (Ant_ID >= PrachCfg->eAxC_offset && p_dev_ctx->fh_cfg.prachEnable)
- {
+ if (/*Ant_ID >= PrachCfg->eAxC_offset &&*/p_dev_ctx->fh_cfg.prachEnable && is_prach) {
/* PRACH packet has ruportid = num_eAxc + ant_id */
Ant_ID -= PrachCfg->eAxC_offset;
symbol_total_bytes[p_dev_ctx->xran_port_id][CC_ID][Ant_ID] += num_bytes;
@@ -1412,7 +1413,7 @@ int generate_cpmsg_prach(void *pHandle, struct xran_cp_gen_params *params, struc
if(XRAN_FILTERINDEX_PRACH_ABC == pPrachCPConfig->filterIdx)
{
timeOffset = timeOffset >> nNumerology; //original number is Tc, convert to Ts based on mu
- if ((slot_id == 0) || (slot_id == (SLOTNUM_PER_SUBFRAME(pxran_lib_ctx->interval_us_local) >> 1)))
+ if (startSymId > 0 && ((slot_id == 0) || (slot_id == (SLOTNUM_PER_SUBFRAME(pxran_lib_ctx->interval_us_local) >> 1))))
timeOffset += 16;
}
else
@@ -1547,8 +1548,7 @@ int32_t ring_processing_func(void* args)
for (i = 0; i < ctx->io_cfg.num_vfs && i < XRAN_VF_MAX; i++){
for(qi = 0; qi < ctx->rxq_per_port[i]; qi++) {
- if (process_ring(ctx->rx_ring[i][qi], i, qi))
- return 0;
+ process_ring(ctx->rx_ring[i][qi],i,qi);
}
}
diff --git a/fhi_lib/lib/src/xran_compression.cpp b/fhi_lib/lib/src/xran_compression.cpp
index 112caae..7c74342 100644
--- a/fhi_lib/lib/src/xran_compression.cpp
+++ b/fhi_lib/lib/src/xran_compression.cpp
@@ -62,7 +62,7 @@ xranlib_compress(const struct xranlib_compress_request *request,
return xranlib_5gnr_mod_compression(&mod_request, &mod_response);
}
else{
- if(_may_i_use_cpu_feature(_FEATURE_AVX512IFMA52)) {
+ if(false) {
return xranlib_compress_avxsnc(request,response);
} else {
return xranlib_compress_avx512(request,response);
@@ -89,7 +89,7 @@ xranlib_decompress(const struct xranlib_decompress_request *request,
return xranlib_5gnr_mod_decompression(&mod_request, &mod_response);
}
else{
- if(_may_i_use_cpu_feature(_FEATURE_AVX512IFMA52)) {
+ if(false) {
return xranlib_decompress_avxsnc(request,response);
} else {
return xranlib_decompress_avx512(request,response);
@@ -101,7 +101,7 @@ int32_t
xranlib_compress_bfw(const struct xranlib_compress_request *request,
struct xranlib_compress_response *response)
{
- if(_may_i_use_cpu_feature(_FEATURE_AVX512IFMA52)) {
+ if(false) {
return xranlib_compress_avxsnc_bfw(request,response);
} else {
return xranlib_compress_avx512_bfw(request,response);
@@ -112,7 +112,7 @@ int32_t
xranlib_decompress_bfw(const struct xranlib_decompress_request *request,
struct xranlib_decompress_response *response)
{
- if(_may_i_use_cpu_feature(_FEATURE_AVX512IFMA52)) {
+ if(false) {
return xranlib_decompress_avxsnc_bfw(request,response);
} else {
return xranlib_decompress_avx512_bfw(request,response);
diff --git a/fhi_lib/lib/src/xran_main.c b/fhi_lib/lib/src/xran_main.c
index 7c472d7..7bab6a8 100644
--- a/fhi_lib/lib/src/xran_main.c
+++ b/fhi_lib/lib/src/xran_main.c
@@ -306,7 +306,7 @@ xran_init_prach(struct xran_fh_config* pConf, struct xran_device_ctx * p_xran_de
printf("PRACH start symbol %u lastsymbol %u\n", p_xran_dev_ctx->prach_start_symbol[0], p_xran_dev_ctx->prach_last_symbol[0]);
}
- pPrachCPConfig->eAxC_offset = xran_get_num_eAxc(p_xran_dev_ctx);
+ pPrachCPConfig->eAxC_offset = pPRACHConfig->eAxC_offset;
print_dbg("PRACH eAxC_offset %d\n", pPrachCPConfig->eAxC_offset);
/* Save some configs for app */
@@ -1570,6 +1570,7 @@ int32_t handle_ecpri_ethertype(struct rte_mbuf* pkt_q[], uint16_t xport_id, stru
{
case ECPRI_IQ_DATA:
pkt_data[num_data++] = pkt;
+ uint8_t *pkt_bytes=rte_pktmbuf_mtod(pkt,uint8_t*);
break;
// For RU emulation
case ECPRI_RT_CONTROL_DATA:
@@ -1587,7 +1588,7 @@ int32_t handle_ecpri_ethertype(struct rte_mbuf* pkt_q[], uint16_t xport_id, stru
break;
default:
if (p_dev_ctx->fh_init.io_cfg.id == O_DU) {
- print_err("Invalid eCPRI message type - %d", ecpri_hdr->cmnhdr.bits.ecpri_mesg_type);
+ rte_pktmbuf_free(pkt);
}
break;
}
@@ -2347,8 +2348,7 @@ ring_processing_func_per_port(void* args)
for (i = 0; i < ctx->io_cfg.num_vfs && i < XRAN_VF_MAX; i = i+1) {
if (ctx->vf2xran_port[i] == port_id) {
for(qi = 0; qi < ctx->rxq_per_port[port_id]; qi++){
- if (process_ring(ctx->rx_ring[i][qi], i, qi))
- return 0;
+ process_ring(ctx->rx_ring[i][qi],i,qi);
}
}
}
@@ -2414,9 +2414,6 @@ xran_spawn_workers(void)
nWorkerCore = nWorkerCore << 1;
}
- extern int _may_i_use_cpu_feature(unsigned __int64);
- icx_cpu = _may_i_use_cpu_feature(_FEATURE_AVX512IFMA52);
-
printf("O-XU %d\n", eth_ctx->io_cfg.id);
printf("HW %d\n", icx_cpu);
printf("Num cores %d\n", total_num_cores);
@@ -4034,6 +4031,24 @@ xran_get_slot_idx (uint32_t PortId, uint32_t *nFrameIdx, uint32_t *nSubframeIdx,
return tti;
}
+int32_t
+xran_get_slot_idx_from_tti(uint32_t tti, uint32_t *nFrameIdx, uint32_t *nSubframeIdx, uint32_t *nSlotIdx, uint64_t *nSecond)
+{
+ struct xran_device_ctx * p_xran_dev_ctx = xran_dev_get_ctx_by_id(0);
+ if (!p_xran_dev_ctx)
+ {
+ print_err("Null xRAN context on port id %u!!\n", 0);
+ return 0;
+ }
+
+ *nSlotIdx = (uint32_t)XranGetSlotNum(tti, SLOTNUM_PER_SUBFRAME(p_xran_dev_ctx->interval_us_local));
+ *nSubframeIdx = (uint32_t)XranGetSubFrameNum(tti,SLOTNUM_PER_SUBFRAME(p_xran_dev_ctx->interval_us_local), SUBFRAMES_PER_SYSTEMFRAME);
+ *nFrameIdx = (uint32_t)XranGetFrameNum(tti,0/*xran_getSfnSecStart()*/,SUBFRAMES_PER_SYSTEMFRAME, SLOTNUM_PER_SUBFRAME(p_xran_dev_ctx->interval_us_local));
+ *nSecond = timing_get_current_second();
+
+ return tti;
+}
+
int32_t
xran_set_debug_stop(int32_t value, int32_t count)
{
diff --git a/fhi_lib/lib/src/xran_mod_compression.cpp b/fhi_lib/lib/src/xran_mod_compression.cpp
index 7d4a5d0..b9b44ac 100644
--- a/fhi_lib/lib/src/xran_mod_compression.cpp
+++ b/fhi_lib/lib/src/xran_mod_compression.cpp
@@ -747,9 +747,9 @@ int xranlib_5gnr_mod_compression(const struct xranlib_5gnr_mod_compression_reque
#ifdef C_Module_Used
return (xranlib_5gnr_mod_compression_c(request, response));
#else
- if(_may_i_use_cpu_feature(_FEATURE_AVX512IFMA52))
+ if (false) {
return (xranlib_5gnr_mod_compression_snc(request, response));
- else
+ } else {
return (xranlib_5gnr_mod_compression_avx512(request, response));
#endif
}
diff --git a/fhi_lib/lib/src/xran_up_api.c b/fhi_lib/lib/src/xran_up_api.c
index fe22a1f..f6c4830 100644
--- a/fhi_lib/lib/src/xran_up_api.c
+++ b/fhi_lib/lib/src/xran_up_api.c
@@ -336,6 +336,7 @@ int32_t xran_extract_iq_samples(struct rte_mbuf *mbuf,
uint8_t *subframe_id,
uint8_t *slot_id,
uint8_t *symb_id,
+ uint8_t *filter_id,
union ecpri_seq_id *seq_id,
uint16_t *num_prbu,
uint16_t *start_prbu,
@@ -345,7 +346,8 @@ int32_t xran_extract_iq_samples(struct rte_mbuf *mbuf,
int8_t expect_comp,
enum xran_comp_hdr_type staticComp,
uint8_t *compMeth,
- uint8_t *iqWidth)
+ uint8_t *iqWidth,
+ uint8_t *is_prach)
{
#if XRAN_MLOG_VAR
uint32_t mlogVar[10];
@@ -381,6 +383,7 @@ int32_t xran_extract_iq_samples(struct rte_mbuf *mbuf,
return 0; /* packet too short */
radio_hdr->sf_slot_sym.value = rte_be_to_cpu_16(radio_hdr->sf_slot_sym.value);
+ *is_prach = (radio_hdr->data_feature.filter_id > 0);
if (frame_id)
*frame_id = radio_hdr->frame_id;
@@ -394,6 +397,9 @@ int32_t xran_extract_iq_samples(struct rte_mbuf *mbuf,
if (symb_id)
*symb_id = radio_hdr->sf_slot_sym.symb_id;
+ if (filter_id)
+ *filter_id = radio_hdr->data_feature.filter_id;
+
/* Process data section hdr */
struct data_section_hdr *data_hdr =
(void *)rte_pktmbuf_adj(mbuf, sizeof(*radio_hdr));
+2 -2
View File
@@ -265,7 +265,7 @@ extern "C" int config_yaml_get(configmodule_interface_t *cfg, paramdef_t *cfgopt
}
}
config_yaml::GetParams(cfg, node, cfgoptions, numoptions);
return 0;
return numoptions;
}
extern "C" int config_yaml_getlist(configmodule_interface_t *cfg,
@@ -286,10 +286,10 @@ extern "C" int config_yaml_getlist(configmodule_interface_t *cfg,
return -1;
}
ParamList->numelt = node.size();
if (!node.IsSequence()) {
return -1;
}
ParamList->numelt = node.size();
if (ParamList->numelt > 0 && params != NULL) {
ParamList->paramarray = static_cast<paramdef_t **>(config_allocate_new(cfg, ParamList->numelt * sizeof(paramdef_t *), true));
+1
View File
@@ -9,3 +9,4 @@ configure_file(test_list.yaml test_list.yaml COPYONLY)
configure_file(test_string.yaml test_string.yaml COPYONLY)
configure_file(test_list_of_mappings.yml test_list_of_mappings.yml COPYONLY)
configure_file(test_int_array.yaml test_int_array.yaml COPYONLY)
configure_file(test_read_mapping_as_list.yaml test_read_mapping_as_list.yaml COPYONLY)
@@ -0,0 +1,4 @@
fhi_72:
element1: value1
element2: value2
element3: value3
+38 -11
View File
@@ -125,7 +125,7 @@ TEST(yaml_config, test_high_recusion) {
p.type = TYPE_UINT16;
p.u16ptr = &value;
char prefix[] = "test.test1.test2.test3.test4";
EXPECT_EQ(config_yaml_get(cfg, &p, 1, prefix), 0);
EXPECT_EQ(config_yaml_get(cfg, &p, 1, prefix), 1);
EXPECT_EQ(value, i);
}
@@ -175,7 +175,7 @@ TEST(yaml_config, test_string_auto_alloc) {
// Test automatic allocation of strings
char prefix[] = "test";
EXPECT_EQ(config_yaml_get(cfg, &param, 1, prefix), 0);
EXPECT_EQ(config_yaml_get(cfg, &param, 1, prefix), 1);
EXPECT_NE(param.strptr, nullptr);
EXPECT_EQ(strcmp(*param.strptr, "testvalue"), 0);
EXPECT_EQ(cfg->numptrs, 2);
@@ -200,7 +200,7 @@ TEST(yaml_config, test_string_no_realloc) {
char prefix[] = "test";
char* non_null_pointer_to_pointer = nullptr;
param.strptr = &non_null_pointer_to_pointer;
EXPECT_EQ(config_yaml_get(cfg, &param, 1, prefix), 0);
EXPECT_EQ(config_yaml_get(cfg, &param, 1, prefix), 1);
EXPECT_EQ(param.strptr, &non_null_pointer_to_pointer);
EXPECT_EQ(strcmp(*param.strptr, "testvalue"), 0);
EXPECT_EQ(cfg->numptrs, 1);
@@ -225,7 +225,7 @@ TEST(yaml_config, test_string_pointer_available) {
char prefix[] = "test";
char *container = (char *)malloc(sizeof(char) * 30);
param.strptr = &container;
EXPECT_EQ(config_yaml_get(cfg, &param, 1, prefix), 0);
EXPECT_EQ(config_yaml_get(cfg, &param, 1, prefix), 1);
EXPECT_EQ(param.strptr, &container);
EXPECT_EQ(strcmp(*param.strptr, "testvalue"), 0);
EXPECT_EQ(cfg->numptrs, 0);
@@ -253,7 +253,7 @@ TEST(yaml_config, test_string_default_value) {
param.defstrval = default_value;
param.strptr = nullptr;
sprintf(param.optname, "%s", "stringvalue_missing");
EXPECT_EQ(config_yaml_get(cfg, &param, 1, prefix), 0);
EXPECT_EQ(config_yaml_get(cfg, &param, 1, prefix), 1);
EXPECT_NE(param.strptr, nullptr);
EXPECT_EQ(strcmp(*param.strptr, "default"), 0);
EXPECT_EQ(cfg->numptrs, 2) << " 2 pointers required, 1 for the string, one for the pointer-to string";
@@ -276,7 +276,7 @@ TEST(yaml_config, test_stringlist) {
// Test automatic allocation of string lists
char prefix[] = "test";
EXPECT_EQ(config_yaml_get(cfg, &param, 1, prefix), 0);
EXPECT_EQ(config_yaml_get(cfg, &param, 1, prefix), 1);
EXPECT_NE(param.strptr, nullptr);
for (auto i = 0; i < param.numelt; i++) {
std::cout << (param.strlistptr)[i] << std::endl;
@@ -302,7 +302,7 @@ TEST(yaml_config, test_list_of_mappings) {
// Test automatic allocation of string lists
char prefix1[] = "test.list.[0]";
EXPECT_EQ(config_yaml_get(cfg, &param, 1, prefix1), 0);
EXPECT_EQ(config_yaml_get(cfg, &param, 1, prefix1), 1);
EXPECT_NE(param.strptr, nullptr);
EXPECT_STREQ("value1", param.strlistptr[0]);
EXPECT_STREQ("value2", param.strlistptr[1]);
@@ -310,7 +310,7 @@ TEST(yaml_config, test_list_of_mappings) {
char prefix2[] = "test.list.[1]";
param.strlistptr = nullptr;
EXPECT_EQ(config_yaml_get(cfg, &param, 1, prefix2), 0);
EXPECT_EQ(config_yaml_get(cfg, &param, 1, prefix2), 1);
EXPECT_NE(param.strptr, nullptr);
EXPECT_STREQ("value4", param.strlistptr[0]);
EXPECT_STREQ("value5", param.strlistptr[1]);
@@ -334,7 +334,7 @@ TEST(yaml_config, test_int_array) {
// Test automatic allocation of int arrays
char prefix[] = "test";
EXPECT_EQ(config_yaml_get(cfg, &param, 1, prefix), 0);
EXPECT_EQ(config_yaml_get(cfg, &param, 1, prefix), 1);
EXPECT_NE(param.iptr, nullptr);
ASSERT_EQ(param.numelt, 4);
EXPECT_EQ(1, param.iptr[0]);
@@ -345,7 +345,7 @@ TEST(yaml_config, test_int_array) {
param.uptr = nullptr;
param.numelt = 0;
sprintf(param.optname, "%s", "array2");
EXPECT_EQ(config_yaml_get(cfg, &param, 1, prefix), 0);
EXPECT_EQ(config_yaml_get(cfg, &param, 1, prefix), 1);
EXPECT_NE(param.uptr, nullptr);
ASSERT_EQ(param.numelt, 3);
EXPECT_EQ(1U, param.uptr[0]);
@@ -355,7 +355,7 @@ TEST(yaml_config, test_int_array) {
param.uptr = nullptr;
param.numelt = 0;
sprintf(param.optname, "%s", "non-existent-array");
EXPECT_EQ(config_yaml_get(cfg, &param, 1, prefix), 0);
EXPECT_EQ(config_yaml_get(cfg, &param, 1, prefix), 1);
EXPECT_EQ(param.uptr, nullptr);
ASSERT_EQ(param.numelt, 0);
@@ -364,6 +364,33 @@ TEST(yaml_config, test_int_array) {
end_configmodule(cfg);
}
TEST(yaml_config, test_read_mapping_as_list) {
configmodule_interface_t *cfg = static_cast<configmodule_interface_t*>(calloc(1, sizeof(*cfg)));
cfg->cfgP[0] = strdup("test_read_mapping_as_list.yaml");
EXPECT_EQ(config_yaml_init(cfg), 0);
char cfgstring[] = "fhi_72";
paramlist_def_t pl = {0};
strncpy(pl.listname, cfgstring, sizeof(pl.listname) - 1);
config_yaml_getlist(cfg, &pl, NULL, 0, /* prefix */ NULL);
EXPECT_NE(pl.numelt, 0);
EXPECT_EQ(pl.numelt, 3);
paramdef_t params[4] = {0};
for (auto i = 0U; i < sizeofArray(params); i++) {
sprintf(params[i].optname, "%s%d", "element_", i+1);
params[i].type = TYPE_STRING;
params[i].paramflags = PARAMFLAG_MANDATORY;
}
params[sizeofArray(params) - 1].paramflags = 0;
int ret = config_yaml_get(cfg, params, sizeofArray(params), cfgstring);
EXPECT_EQ(ret, 4);
config_yaml_end(cfg);
free(cfg->cfgP[0]);
end_configmodule(cfg);
}
int main(int argc, char** argv)
{
logInit();
+3 -3
View File
@@ -69,13 +69,13 @@ typedef struct {
static log_mem_cnt_t log_mem_d[2];
static int log_mem_flag = 0;
volatile int log_mem_side=0;
static volatile int log_mem_side = 0;
static pthread_mutex_t log_mem_lock;
static pthread_cond_t log_mem_notify;
static pthread_t log_mem_thread;
static int log_mem_file_cnt=0;
volatile int log_mem_write_flag=0;
volatile int log_mem_write_side=0;
static volatile int log_mem_write_flag = 0;
static volatile int log_mem_write_side = 0;
static char * log_mem_filename;
static mapping log_level_names[] = {{"error", OAILOG_ERR},
+20
View File
@@ -87,6 +87,10 @@ ID = ENB_PHY_INITIATE_RA_PROCEDURE
DESC = eNodeB initiates a random access procedure after detecting enough energy for one of the preambles
GROUP = ALL:PHY:ENB:WIRESHARK
FORMAT = int,eNB_ID : int,frame : int,subframe : int,preamble : int,energy : int,delay
ID = UE_PHY_INITIATE_RA_PROCEDURE
DESC = UE initiates a random access procedure with a given preamble (can be used for both LTE and NR)
GROUP = ALL:PHY:UE:WIRESHARK
FORMAT = int,frame : int,subframe_or_slot : int,preamble : int,power
ID = GNB_PHY_DL_TICK
DESC = gNodeB downlink tick - one tick per ms at start of downlink processing
GROUP = ALL:PHY:GRAPHIC:GNB
@@ -99,6 +103,10 @@ ID = GNB_PHY_MIB
DESC = NR MIB data
GROUP = ALL:PHY:GNB:WIRESHARK
FORMAT = int,gNB_ID : int,frame : int,slot : buffer,data
ID = NRUE_PHY_MIB
DESC = NR MIB data as received by an UE
GROUP = ALL:PHY:UE:WIRESHARK
FORMAT = int,frame : int,slot : int,ssb_index : buffer,data
ID = GNB_PHY_PUCCH_PUSCH_IQ
DESC = gNodeB input data in the frequency domain for a slot where some PUCCH or PUSCH detection was done
GROUP = ALL:PHY:GRAPHIC:HEAVY:GNB
@@ -181,6 +189,18 @@ ID = GNB_MAC_RETRANSMISSION_DL_PDU_WITH_DATA
DESC = NR MAC downlink retransmitted PDU for an UE
GROUP = ALL:MAC:GNB:WIRESHARK
FORMAT = int,gNB_ID : int,CC_id : int,rnti : int,frame : int,slot : int,harq_pid : int,round : buffer,data
ID = NRUE_MAC_DL_PDU_WITH_DATA
DESC = NR MAC downlink PDU for an UE
GROUP = ALL:MAC:UE:WIRESHARK
FORMAT = int,rnti : int,frame : int,slot : int,harq_pid : buffer,data
ID = NRUE_MAC_UL_PDU_WITH_DATA
DESC = NR MAC uplink PDU for an UE
GROUP = ALL:MAC:UE:WIRESHARK
FORMAT = int,rnti : int,frame : int,slot : int,harq_pid : buffer,data
ID = NRUE_MAC_DL_RAR_PDU_WITH_DATA
DESC = NR MAC downlink PDU for RAR
GROUP = ALL:MAC:UE:WIRESHARK
FORMAT = int,rnti : int,frame : int,slot : buffer,data
#RLC logs
ID = ENB_RLC_DL
+252 -53
View File
@@ -44,6 +44,10 @@ typedef struct {
int preamble_frame;
int preamble_subframe;
int preamble_preamble;
/* UE RA preamble */
int ue_preamble_frame;
int ue_preamble_subframe;
int ue_preamble_preamble;
/* RAR */
int rar_rnti;
int rar_frame;
@@ -82,6 +86,27 @@ typedef struct {
int nr_rar_frame;
int nr_rar_slot;
int nr_rar_data;
/* NR UE mib */
int nr_ue_mib_frame;
int nr_ue_mib_slot;
int nr_ue_mib_data;
/* NR UE ul */
int nr_ue_ul_rnti;
int nr_ue_ul_frame;
int nr_ue_ul_slot;
int nr_ue_ul_harq_pid;
int nr_ue_ul_data;
/* NR UE dl */
int nr_ue_dl_rnti;
int nr_ue_dl_frame;
int nr_ue_dl_slot;
int nr_ue_dl_harq_pid;
int nr_ue_dl_data;
/* NR UE RAR */
int nr_ue_rar_rnti;
int nr_ue_rar_frame;
int nr_ue_rar_slot;
int nr_ue_rar_data;
/* config */
int no_mib;
@@ -235,6 +260,15 @@ void preamble(void *_d, event e)
e.e[d->preamble_preamble].i, NO_SR_RNTI);
}
void ue_preamble(void *_d, event e)
{
ev_data *d = _d;
trace_lte(d, DIRECTION_UPLINK, NO_RNTI, 0,
e.e[d->ue_preamble_frame].i, e.e[d->ue_preamble_subframe].i,
NULL, 0,
e.e[d->ue_preamble_preamble].i, NO_SR_RNTI);
}
void rar(void *_d, event e)
{
ev_data *d = _d;
@@ -347,7 +381,7 @@ void nr_dl(void *_d, event e)
{
ev_data *d = _d;
if (e.e[d->dl_rnti].i == 0xffff) {
if (e.e[d->nr_dl_rnti].i == 0xffff) {
if (d->no_sib) return;
if (d->max_sib && d->cur_sib == d->max_sib) return;
@@ -356,7 +390,7 @@ void nr_dl(void *_d, event e)
}
trace_nr(d, NR_DIRECTION_DOWNLINK,
e.e[d->dl_rnti].i != 0xffff ? NR_C_RNTI : NR_SI_RNTI,
e.e[d->nr_dl_rnti].i != 0xffff ? NR_C_RNTI : NR_SI_RNTI,
e.e[d->nr_dl_rnti].i, e.e[d->nr_dl_frame].i, e.e[d->nr_dl_slot].i,
e.e[d->nr_dl_harq_pid].i, e.e[d->nr_dl_data].b,
e.e[d->nr_dl_data].bsize, NO_PREAMBLE);
@@ -387,6 +421,21 @@ void nr_mib(void *_d, event e)
e.e[d->nr_mib_data].b, e.e[d->nr_mib_data].bsize, NO_PREAMBLE);
}
void nr_ue_mib(void *_d, event e)
{
ev_data *d = _d;
if (d->no_mib) return;
if (d->max_mib && d->cur_mib == d->max_mib) return;
d->cur_mib++;
trace_nr(d, NR_DIRECTION_DOWNLINK, NR_NO_RNTI, 0,
e.e[d->nr_ue_mib_frame].i, e.e[d->nr_ue_mib_slot].i, 0 /* harq pid */,
e.e[d->nr_ue_mib_data].b, e.e[d->nr_ue_mib_data].bsize, NO_PREAMBLE);
}
void nr_rar(void *_d, event e)
{
ev_data *d = _d;
@@ -396,61 +445,120 @@ void nr_rar(void *_d, event e)
e.e[d->nr_rar_data].b, e.e[d->nr_rar_data].bsize, NO_PREAMBLE);
}
void nr_ue_ul(void *_d, event e)
{
ev_data *d = _d;
trace_nr(d, NR_DIRECTION_UPLINK, NR_C_RNTI, e.e[d->nr_ue_ul_rnti].i,
e.e[d->nr_ue_ul_frame].i, e.e[d->nr_ue_ul_slot].i,
e.e[d->nr_ue_ul_harq_pid].i, e.e[d->nr_ue_ul_data].b,
e.e[d->nr_ue_ul_data].bsize, NO_PREAMBLE);
}
void nr_ue_dl(void *_d, event e)
{
ev_data *d = _d;
if (e.e[d->nr_ue_dl_rnti].i == 0xffff) {
if (d->no_sib) return;
if (d->max_sib && d->cur_sib == d->max_sib) return;
d->cur_sib++;
}
trace_nr(d, NR_DIRECTION_DOWNLINK,
e.e[d->nr_ue_dl_rnti].i != 0xffff ? NR_C_RNTI : NR_SI_RNTI,
e.e[d->nr_ue_dl_rnti].i, e.e[d->nr_ue_dl_frame].i,
e.e[d->nr_ue_dl_slot].i, e.e[d->nr_ue_dl_harq_pid].i,
e.e[d->nr_ue_dl_data].b, e.e[d->nr_ue_dl_data].bsize, NO_PREAMBLE);
}
void nr_ue_rar(void *_d, event e)
{
ev_data *d = _d;
trace_nr(d, DIRECTION_DOWNLINK, RA_RNTI, e.e[d->nr_ue_rar_rnti].i,
e.e[d->nr_ue_rar_frame].i, e.e[d->nr_ue_rar_slot].i, 0,
e.e[d->nr_ue_rar_data].b, e.e[d->nr_ue_rar_data].bsize,
NO_PREAMBLE);
}
/****************************************************************************/
/****************************************************************************/
void setup_data(ev_data *d, void *database, int ul_id, int dl_id, int mib_id,
int preamble_id, int rar_id, int sr_id,
int preamble_id, int ue_preamble_id, int rar_id, int sr_id,
int nr_ul_id, int nr_dl_id, int nr_dl_retx_id, int nr_mib_id,
int nr_rar_id)
int nr_rar_id, int nr_ue_mib_id, int nr_ue_ul_id,
int nr_ue_dl_id, int nr_ue_rar_id)
{
database_event_format f;
int i;
d->ul_rnti = -1;
d->ul_frame = -1;
d->ul_subframe = -1;
d->ul_data = -1;
d->dl_rnti = -1;
d->dl_frame = -1;
d->dl_subframe = -1;
d->dl_data = -1;
d->mib_frame = -1;
d->mib_subframe = -1;
d->mib_data = -1;
d->preamble_frame = -1;
d->preamble_subframe = -1;
d->preamble_preamble = -1;
d->rar_rnti = -1;
d->rar_frame = -1;
d->rar_subframe = -1;
d->rar_data = -1;
d->sr_rnti = -1;
d->sr_frame = -1;
d->sr_subframe = -1;
d->ul_rnti = -1;
d->ul_frame = -1;
d->ul_subframe = -1;
d->ul_data = -1;
d->dl_rnti = -1;
d->dl_frame = -1;
d->dl_subframe = -1;
d->dl_data = -1;
d->mib_frame = -1;
d->mib_subframe = -1;
d->mib_data = -1;
d->preamble_frame = -1;
d->preamble_subframe = -1;
d->preamble_preamble = -1;
d->ue_preamble_frame = -1;
d->ue_preamble_subframe = -1;
d->ue_preamble_preamble = -1;
d->rar_rnti = -1;
d->rar_frame = -1;
d->rar_subframe = -1;
d->rar_data = -1;
d->sr_rnti = -1;
d->sr_frame = -1;
d->sr_subframe = -1;
d->nr_ul_rnti = -1;
d->nr_ul_frame = -1;
d->nr_ul_slot = -1;
d->nr_ul_harq_pid = -1;
d->nr_ul_data = -1;
d->nr_dl_rnti = -1;
d->nr_dl_frame = -1;
d->nr_dl_slot = -1;
d->nr_dl_harq_pid = -1;
d->nr_dl_data = -1;
d->nr_dl_retx_rnti = -1;
d->nr_dl_retx_frame = -1;
d->nr_dl_retx_slot = -1;
d->nr_dl_retx_harq_pid = -1;
d->nr_dl_retx_data = -1;
d->nr_mib_frame = -1;
d->nr_mib_slot = -1;
d->nr_mib_data = -1;
d->nr_rar_rnti = -1;
d->nr_rar_frame = -1;
d->nr_rar_slot = -1;
d->nr_rar_data = -1;
d->nr_ul_rnti = -1;
d->nr_ul_frame = -1;
d->nr_ul_slot = -1;
d->nr_ul_harq_pid = -1;
d->nr_ul_data = -1;
d->nr_dl_rnti = -1;
d->nr_dl_frame = -1;
d->nr_dl_slot = -1;
d->nr_dl_harq_pid = -1;
d->nr_dl_data = -1;
d->nr_dl_retx_rnti = -1;
d->nr_dl_retx_frame = -1;
d->nr_dl_retx_slot = -1;
d->nr_dl_retx_harq_pid = -1;
d->nr_dl_retx_data = -1;
d->nr_mib_frame = -1;
d->nr_mib_slot = -1;
d->nr_mib_data = -1;
d->nr_rar_rnti = -1;
d->nr_rar_frame = -1;
d->nr_rar_slot = -1;
d->nr_rar_data = -1;
d->nr_ue_mib_frame = -1;
d->nr_ue_mib_slot = -1;
d->nr_ue_mib_data = -1;
d->nr_ue_ul_rnti = -1;
d->nr_ue_ul_frame = -1;
d->nr_ue_ul_slot = -1;
d->nr_ue_ul_harq_pid = -1;
d->nr_ue_ul_data = -1;
d->nr_ue_dl_rnti = -1;
d->nr_ue_dl_frame = -1;
d->nr_ue_dl_slot = -1;
d->nr_ue_dl_harq_pid = -1;
d->nr_ue_dl_data = -1;
d->nr_ue_rar_rnti = -1;
d->nr_ue_rar_frame = -1;
d->nr_ue_rar_slot = -1;
d->nr_ue_rar_data = -1;
#define G(var_name, var_type, var) \
if (!strcmp(f.name[i], var_name)) { \
@@ -508,6 +616,18 @@ void setup_data(ev_data *d, void *database, int ul_id, int dl_id, int mib_id,
if (d->preamble_frame == -1 || d->preamble_subframe == -1 ||
d->preamble_preamble == -1) goto error;
/* ue preamble: frame, subframe, preamble */
f = get_format(database, ue_preamble_id);
for (i = 0; i < f.count; i++) {
G("frame", "int", d->ue_preamble_frame);
G("subframe_or_slot", "int", d->ue_preamble_subframe);
G("preamble", "int", d->ue_preamble_preamble);
}
if (d->ue_preamble_frame == -1 || d->ue_preamble_subframe == -1 ||
d->ue_preamble_preamble == -1) goto error;
/* rar: rnti, frame, subframe, data */
f = get_format(database, rar_id);
@@ -605,6 +725,64 @@ void setup_data(ev_data *d, void *database, int ul_id, int dl_id, int mib_id,
d->nr_rar_data == -1)
goto error;
/* NR UE MIB: frame, slot, data */
f = get_format(database, nr_ue_mib_id);
for (i = 0; i < f.count; i++) {
G("frame", "int", d->nr_ue_mib_frame);
G("slot", "int", d->nr_ue_mib_slot);
G("data", "buffer", d->nr_ue_mib_data);
}
if (d->nr_ue_mib_frame == -1 || d->nr_ue_mib_slot== -1 ||
d->nr_ue_mib_data == -1)
goto error;
/* NR UE ul: rnti, frame, slot, harq_pid, data */
f = get_format(database, nr_ue_ul_id);
for (i = 0; i < f.count; i++) {
G("rnti", "int", d->nr_ue_ul_rnti);
G("frame", "int", d->nr_ue_ul_frame);
G("slot", "int", d->nr_ue_ul_slot);
G("harq_pid", "int", d->nr_ue_ul_harq_pid);
G("data", "buffer", d->nr_ue_ul_data);
}
if (d->nr_ue_ul_rnti == -1 || d->nr_ue_ul_frame == -1 ||
d->nr_ue_ul_slot == -1 || d->nr_ue_ul_harq_pid == -1 ||
d->nr_ue_ul_data == -1)
goto error;
/* NR UE dl: rnti, frame, slot, harq_pid, data */
f = get_format(database, nr_ue_dl_id);
for (i = 0; i < f.count; i++) {
G("rnti", "int", d->nr_ue_dl_rnti);
G("frame", "int", d->nr_ue_dl_frame);
G("slot", "int", d->nr_ue_dl_slot);
G("harq_pid", "int", d->nr_ue_dl_harq_pid);
G("data", "buffer", d->nr_ue_dl_data);
}
if (d->nr_ue_dl_rnti == -1 || d->nr_ue_dl_frame == -1 ||
d->nr_ue_dl_slot == -1 || d->nr_ue_dl_harq_pid == -1 ||
d->nr_ue_dl_data == -1)
goto error;
/* NR UE rar: rnti, frame, slot, data */
f = get_format(database, nr_ue_rar_id);
for (i = 0; i < f.count; i++) {
G("rnti", "int", d->nr_ue_rar_rnti);
G("frame", "int", d->nr_ue_rar_frame);
G("slot", "int", d->nr_ue_rar_slot);
G("data", "buffer", d->nr_ue_rar_data);
}
if (d->nr_ue_rar_rnti == -1 || d->nr_ue_rar_frame == -1 ||
d->nr_ue_rar_slot == -1 || d->nr_ue_rar_data == -1) goto error;
#undef G
return;
error:
@@ -672,8 +850,9 @@ int main(int n, char **v)
event_handler *h;
int in;
int i;
int ul_id, dl_id, mib_id, preamble_id, rar_id;
int ul_id, dl_id, mib_id, preamble_id, ue_preamble_id, rar_id;
int nr_ul_id, nr_dl_id, nr_dl_retx_id, nr_mib_id, nr_rar_id;
int nr_ue_mib_id, nr_ue_ul_id, nr_ue_dl_id, nr_ue_rar_id;
int sr_id;
ev_data d;
char *ip = DEFAULT_IP;
@@ -748,6 +927,7 @@ int main(int n, char **v)
on_off(database, "ENB_MAC_UE_DL_PDU_WITH_DATA", is_on, 1);
on_off(database, "ENB_PHY_MIB", is_on, 1);
on_off(database, "ENB_PHY_INITIATE_RA_PROCEDURE", is_on, 1);
on_off(database, "UE_PHY_INITIATE_RA_PROCEDURE", is_on, 1);
on_off(database, "ENB_MAC_UE_DL_RAR_PDU_WITH_DATA", is_on, 1);
on_off(database, "ENB_MAC_SCHEDULING_REQUEST", is_on, 1);
@@ -756,6 +936,10 @@ int main(int n, char **v)
on_off(database, "GNB_MAC_RETRANSMISSION_DL_PDU_WITH_DATA", is_on, 1);
on_off(database, "GNB_PHY_MIB", is_on, 1);
on_off(database, "GNB_MAC_DL_RAR_PDU_WITH_DATA", is_on, 1);
on_off(database, "NRUE_PHY_MIB", is_on, 1);
on_off(database, "NRUE_MAC_UL_PDU_WITH_DATA", is_on, 1);
on_off(database, "NRUE_MAC_DL_PDU_WITH_DATA", is_on, 1);
on_off(database, "NRUE_MAC_DL_RAR_PDU_WITH_DATA", is_on, 1);
/* activate selected traces */
if (socket_send(in, &mt, 1) == -1 ||
@@ -772,6 +956,7 @@ int main(int n, char **v)
dl_id = event_id_from_name(database, "ENB_MAC_UE_DL_PDU_WITH_DATA");
mib_id = event_id_from_name(database, "ENB_PHY_MIB");
preamble_id = event_id_from_name(database, "ENB_PHY_INITIATE_RA_PROCEDURE");
ue_preamble_id = event_id_from_name(database, "UE_PHY_INITIATE_RA_PROCEDURE");
rar_id = event_id_from_name(database, "ENB_MAC_UE_DL_RAR_PDU_WITH_DATA");
sr_id = event_id_from_name(database, "ENB_MAC_SCHEDULING_REQUEST");
@@ -780,14 +965,20 @@ int main(int n, char **v)
nr_dl_retx_id = event_id_from_name(database, "GNB_MAC_RETRANSMISSION_DL_PDU_WITH_DATA");
nr_mib_id = event_id_from_name(database, "GNB_PHY_MIB");
nr_rar_id = event_id_from_name(database, "GNB_MAC_DL_RAR_PDU_WITH_DATA");
nr_ue_mib_id = event_id_from_name(database, "NRUE_PHY_MIB");
nr_ue_ul_id = event_id_from_name(database, "NRUE_MAC_UL_PDU_WITH_DATA");
nr_ue_dl_id = event_id_from_name(database, "NRUE_MAC_DL_PDU_WITH_DATA");
nr_ue_rar_id = event_id_from_name(database, "NRUE_MAC_DL_RAR_PDU_WITH_DATA");
setup_data(&d, database, ul_id, dl_id, mib_id, preamble_id, rar_id, sr_id,
nr_ul_id, nr_dl_id, nr_dl_retx_id, nr_mib_id, nr_rar_id);
setup_data(&d, database, ul_id, dl_id, mib_id, preamble_id, ue_preamble_id,
rar_id, sr_id, nr_ul_id, nr_dl_id, nr_dl_retx_id, nr_mib_id,
nr_rar_id, nr_ue_mib_id, nr_ue_ul_id, nr_ue_dl_id, nr_ue_rar_id);
register_handler_function(h, ul_id, ul, &d);
register_handler_function(h, dl_id, dl, &d);
register_handler_function(h, mib_id, mib, &d);
register_handler_function(h, preamble_id, preamble, &d);
register_handler_function(h, ue_preamble_id, ue_preamble, &d);
register_handler_function(h, rar_id, rar, &d);
register_handler_function(h, sr_id, sr, &d);
@@ -796,6 +987,10 @@ int main(int n, char **v)
register_handler_function(h, nr_dl_retx_id, nr_dl_retx, &d);
register_handler_function(h, nr_mib_id, nr_mib, &d);
register_handler_function(h, nr_rar_id, nr_rar, &d);
register_handler_function(h, nr_ue_mib_id, nr_ue_mib, &d);
register_handler_function(h, nr_ue_ul_id, nr_ue_ul, &d);
register_handler_function(h, nr_ue_dl_id, nr_ue_dl, &d);
register_handler_function(h, nr_ue_rar_id, nr_ue_rar, &d);
d.socket = socket(AF_INET, SOCK_DGRAM, 0);
@@ -817,11 +1012,15 @@ int main(int n, char **v)
if (e.type == -1) break;
if (!(e.type == ul_id || e.type == dl_id || e.type == mib_id ||
e.type == preamble_id || e.type == rar_id || e.type == sr_id ||
if (!(e.type == ul_id || e.type == dl_id ||
e.type == mib_id ||
e.type == preamble_id || e.type == ue_preamble_id ||
e.type == rar_id || e.type == sr_id ||
e.type == nr_ul_id || e.type == nr_dl_id ||
e.type == nr_dl_retx_id || e.type == nr_mib_id ||
e.type == nr_rar_id)) continue;
e.type == nr_rar_id || e.type == nr_ue_mib_id ||
e.type == nr_ue_ul_id || e.type == nr_ue_dl_id ||
e.type == nr_ue_rar_id)) continue;
handle_event(h, e);
}
+1 -1
View File
@@ -21,7 +21,7 @@
#ifndef ACTOR_H
#define ACTOR_H
#include "thread-pool.h"
#include "notified_fifo.h"
#define INIT_ACTOR(ptr, name, core_affinity) init_actor((Actor_t *)ptr, name, core_affinity);
+2
View File
@@ -43,6 +43,8 @@
#include "common/config/config_userapi.h"
#include "load_module_shlib.h"
loader_data_t loader_data;
void loader_init(void) {
paramdef_t LoaderParams[] = LOADER_PARAMS_DESC;
+3 -12
View File
@@ -32,9 +32,6 @@
#ifndef LOAD_SHLIB_H
#define LOAD_SHLIB_H
typedef struct {
char *fname;
int (*fptr)(void);
@@ -68,11 +65,10 @@ typedef int(*checkverfunc_t)(char * mainexec_version, char ** shlib_version);
/* the function array when calling load_module_shlib (farray param NULL) */
typedef int(*getfarrayfunc_t)(loader_shlibfunc_t **funcarray);
#ifdef LOAD_MODULE_SHLIB_MAIN
#define LOADER_CONFIG_PREFIX "loader"
#define DEFAULT_PATH ""
#define DEFAULT_MAXSHLIBS 10
loader_data_t loader_data;
extern loader_data_t loader_data;
/*----------------------------------------------------------------------------------------------------------------------------------------------------------*/
/* LOADER parameters */
@@ -85,13 +81,8 @@ loader_data_t loader_data;
}
// clang-format on
/*-------------------------------------------------------------------------------------------------------------*/
#else /* LOAD_MODULE_SHLIB_MAIN */
extern int load_module_version_shlib(char *modname, char *version, loader_shlibfunc_t *farray, int numf, void *initfunc_arg);
extern void * get_shlibmodule_fptr(char *modname, char *fname);
extern loader_data_t loader_data;
#endif /* LOAD_MODULE_SHLIB_MAIN */
int load_module_version_shlib(char *modname, char *version, loader_shlibfunc_t *farray, int numf, void *initfunc_arg);
void *get_shlibmodule_fptr(char *modname, char *fname);
#define load_module_shlib(M, F, N, I) load_module_version_shlib(M, NULL, F, N, I)
void loader_reset();
#endif
@@ -434,7 +434,7 @@ typedef struct timer_elm_s {
void itti_send_terminate_message(task_id_t task_id) {
}
sem_t itti_sem_block;
static sem_t itti_sem_block;
void itti_wait_tasks_unblock()
{
int rc = sem_post(&itti_sem_block);
-1
View File
@@ -53,7 +53,6 @@
#include <sys/resource.h>
#include "common/utils/load_module_shlib.h"
#include "common/config/config_userapi.h"
#include "common/utils/threadPool/thread-pool.h"
#include "executables/softmodem-common.h"
#include <readline/history.h>
#include "common/oai_version.h"
+1 -1
View File
@@ -1,6 +1,6 @@
if (ENABLE_TESTS)
add_subdirectory(test)
endif()
add_library(thread-pool thread-pool.c)
add_library(thread-pool thread-pool.c task_ans.c)
target_link_libraries(thread-pool PRIVATE utils)
target_include_directories(thread-pool PUBLIC .)
@@ -0,0 +1,245 @@
/*
* 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
*/
#ifndef BOUNDED_NOTIFIED_FIFO_H
#define BOUNDED_NOTIFIED_FIFO_H
#include "assertions.h"
#include <stdint.h>
#include <memory.h>
#include "task.h"
#include <pthread.h>
#include "pthread_utils.h"
// For working correctly, maintain the default elements to a 2^N e.g., 2^5=32
#define DEFAULT_ELM 256
typedef struct seq_ring_buf_s {
task_t* array;
size_t cap;
uint32_t head;
uint32_t tail;
_Atomic uint64_t sz;
} seq_ring_task_t;
static size_t size_seq_ring_task(seq_ring_task_t* r)
{
DevAssert(r != NULL);
return r->head - r->tail;
}
static uint32_t mask(uint32_t cap, uint32_t val)
{
return val & (cap - 1);
}
static bool full(seq_ring_task_t* r)
{
return size_seq_ring_task(r) == r->cap - 1;
}
static void enlarge_buffer(seq_ring_task_t* r)
{
DevAssert(r != NULL);
DevAssert(full(r));
const uint32_t factor = 2;
task_t* tmp_buffer = calloc(r->cap * factor, sizeof(task_t));
DevAssert(tmp_buffer != NULL);
const uint32_t head_pos = mask(r->cap, r->head);
const uint32_t tail_pos = mask(r->cap, r->tail);
if (head_pos > tail_pos) {
memcpy(tmp_buffer, r->array + tail_pos, (head_pos - tail_pos) * sizeof(task_t));
} else {
memcpy(tmp_buffer, r->array + tail_pos, (r->cap - tail_pos) * sizeof(task_t));
memcpy(tmp_buffer + (r->cap - tail_pos), r->array, head_pos * sizeof(task_t));
}
r->cap *= factor;
free(r->array);
r->array = tmp_buffer;
r->tail = 0;
r->head = r->cap / 2 - 1;
}
static void init_seq_ring_task(seq_ring_task_t* r)
{
DevAssert(r != NULL);
task_t* tmp_buffer = calloc(DEFAULT_ELM, sizeof(task_t));
DevAssert(tmp_buffer != NULL);
seq_ring_task_t tmp = {.array = tmp_buffer, .head = 0, .tail = 0, .cap = DEFAULT_ELM};
memcpy(r, &tmp, sizeof(seq_ring_task_t));
r->sz = 0;
}
static void free_seq_ring_task(seq_ring_task_t* r)
{
DevAssert(r != NULL);
free(r->array);
}
static void push_back_seq_ring_task(seq_ring_task_t* r, task_t t)
{
DevAssert(r != NULL);
if (full(r))
enlarge_buffer(r);
const uint32_t pos = mask(r->cap, r->head);
r->array[pos] = t;
r->head += 1;
r->sz += 1;
}
static task_t pop_seq_ring_task(seq_ring_task_t* r)
{
DevAssert(r != NULL);
DevAssert(size_seq_ring_task(r) > 0);
const uint32_t pos = mask(r->cap, r->tail);
task_t t = r->array[pos];
r->tail += 1;
r->sz -= 1;
return t;
}
#undef DEFAULT_ELM
typedef struct {
pthread_mutex_t mtx;
pthread_cond_t cv;
seq_ring_task_t r;
size_t idx;
} not_q_t;
typedef struct {
task_t t;
bool success;
} ret_try_t;
static void init_not_q(not_q_t* q, size_t idx)
{
DevAssert(q != NULL);
q->idx = idx;
init_seq_ring_task(&q->r);
mutexinit(q->mtx);
condinit(q->cv);
}
static void free_not_q(not_q_t* q)
{
DevAssert(q != NULL);
free_seq_ring_task(&q->r);
mutexdestroy(q->mtx);
conddestroy(q->cv);
}
static bool try_push_not_q(not_q_t* q, task_t t)
{
DevAssert(q != NULL);
if (mutextrylock(q->mtx) != 0)
return false;
push_back_seq_ring_task(&q->r, t);
const size_t sz = size_seq_ring_task(&q->r);
DevAssert(sz > 0);
mutexunlock(q->mtx);
condsignal(q->cv);
return true;
}
static void push_not_q(not_q_t* q, task_t t)
{
DevAssert(q != NULL);
DevAssert(t.func != NULL);
mutexlock(q->mtx);
push_back_seq_ring_task(&q->r, t);
DevAssert(size_seq_ring_task(&q->r) > 0);
mutexunlock(q->mtx);
condsignal(q->cv);
}
static ret_try_t try_pop_not_q(not_q_t* q)
{
DevAssert(q != NULL);
ret_try_t ret = {.success = false};
int rc = mutextrylock(q->mtx);
DevAssert(rc == 0 || rc == EBUSY);
if (rc == EBUSY)
return ret;
size_t sz = size_seq_ring_task(&q->r);
if (sz == 0) {
mutexunlock(q->mtx);
return ret;
}
DevAssert(sz > 0);
ret.t = pop_seq_ring_task(&q->r);
mutexunlock(q->mtx);
ret.success = true;
return ret;
}
static bool pop_not_q(not_q_t* q, ret_try_t* out)
{
DevAssert(q != NULL);
DevAssert(out != NULL);
mutexlock(q->mtx);
while (size_seq_ring_task(&q->r) == 0) {
condwait(q->cv, q->mtx);
}
out->t = pop_seq_ring_task(&q->r);
mutexunlock(q->mtx);
return true;
}
#endif
+223
View File
@@ -0,0 +1,223 @@
/*
* 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
*/
#ifndef NOTIFIED_FIFO_H
#define NOTIFIED_FIFO_H
#include "pthread_utils.h"
#include <stdint.h>
#include <pthread.h>
#include "time_meas.h"
#include <memory.h>
#include <stdalign.h>
#include "assertions.h"
/// @brief Element on the notifiedFifo_t
/// next: internal FIFO chain, do not set it
/// key: a long int that the client can use to identify a job or a group of messages
/// ResponseFifo: if the client defines a response FIFO, the job will be posted back after processing
/// processingFunc: any function (of type void processingFunc(void *)) that a worker will process
/// msgData: the data passed to `processingFunc`. It can be added automatically, or you can set it to a buffer you are managing
/// malloced: a boolean that enables internal free in the case of no return FIFO or abort feature
typedef struct notifiedFIFO_elt_s {
struct notifiedFIFO_elt_s *next;
uint64_t key; // To filter out elements
struct notifiedFIFO_s *reponseFifo;
void (*processingFunc)(void *);
bool malloced;
oai_cputime_t creationTime;
oai_cputime_t startProcessingTime;
oai_cputime_t endProcessingTime;
oai_cputime_t returnTime;
// use alignas(32) to align msgData to 32b
// user data behind it will be aligned to 32b as well
// important! this needs to be the last member in the struct
alignas(32) void *msgData;
} notifiedFIFO_elt_t;
typedef struct notifiedFIFO_s {
notifiedFIFO_elt_t *outF;
notifiedFIFO_elt_t *inF;
pthread_mutex_t lockF;
pthread_cond_t notifF;
bool abortFIFO; // if set, the FIFO always returns NULL -> abort condition
} notifiedFIFO_t;
/// @brief Creates a new job.
/// @param size The data part of the job will have this size
/// @param key the job can be identified
/// @param reponseFifo response fifo
/// @param processingFunc function to call
/// @return new notifiedFIFO_elt_t element with extra memory allocated at the end equal to size.
static inline notifiedFIFO_elt_t *newNotifiedFIFO_elt(int size,
uint64_t key,
notifiedFIFO_t *reponseFifo,
void (*processingFunc)(void *))
{
notifiedFIFO_elt_t *ret = (notifiedFIFO_elt_t *)memalign(32, sizeof(notifiedFIFO_elt_t) + size);
AssertFatal(NULL != ret, "out of memory\n");
ret->next = NULL;
ret->key = key;
ret->reponseFifo = reponseFifo;
ret->processingFunc = processingFunc;
// We set user data piece aligend 32 bytes to be able to process it with SIMD
// msgData is aligned to 32bytes, so everything after will be as well
ret->msgData = ((uint8_t *)ret) + sizeof(notifiedFIFO_elt_t);
ret->malloced = true;
return ret;
}
/// @brief Get pointer to the data carried by notifiedFIFO_elt_t
/// @param elt
/// @return void pointer to the data allocated with the message
static inline void *NotifiedFifoData(notifiedFIFO_elt_t *elt)
{
return elt->msgData;
}
/// @brief Delete a notifiedFIFO_elt_t if its allocated
/// @param elt
static inline void delNotifiedFIFO_elt(notifiedFIFO_elt_t *elt)
{
if (elt->malloced) {
elt->malloced = false;
free(elt);
}
}
static inline void initNotifiedFIFO_nothreadSafe(notifiedFIFO_t *nf)
{
nf->inF = NULL;
nf->outF = NULL;
nf->abortFIFO = false;
}
static inline void initNotifiedFIFO(notifiedFIFO_t *nf)
{
mutexinit(nf->lockF);
condinit(nf->notifF);
initNotifiedFIFO_nothreadSafe(nf);
// No delete function: the creator has only to free the memory
}
static inline void pushNotifiedFIFO_nothreadSafe(notifiedFIFO_t *nf, notifiedFIFO_elt_t *msg)
{
msg->next = NULL;
if (nf->outF == NULL)
nf->outF = msg;
if (nf->inF != NULL)
nf->inF->next = msg;
nf->inF = msg;
}
static inline void pushNotifiedFIFO(notifiedFIFO_t *nf, notifiedFIFO_elt_t *msg)
{
mutexlock(nf->lockF);
if (!nf->abortFIFO) {
pushNotifiedFIFO_nothreadSafe(nf, msg);
condsignal(nf->notifF);
}
mutexunlock(nf->lockF);
}
static inline notifiedFIFO_elt_t *pullNotifiedFIFO_nothreadSafe(notifiedFIFO_t *nf)
{
if (nf->outF == NULL)
return NULL;
if (nf->abortFIFO)
return NULL;
notifiedFIFO_elt_t *ret = nf->outF;
AssertFatal(nf->outF != nf->outF->next, "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 = NULL;
while ((ret = pullNotifiedFIFO_nothreadSafe(nf)) == NULL && !nf->abortFIFO)
condwait(nf->notifF, nf->lockF);
mutexunlock(nf->lockF);
return ret;
}
static inline notifiedFIFO_elt_t *pollNotifiedFIFO(notifiedFIFO_t *nf)
{
int tmp = mutextrylock(nf->lockF);
if (tmp != 0)
return NULL;
if (nf->abortFIFO) {
mutexunlock(nf->lockF);
return NULL;
}
notifiedFIFO_elt_t *ret = pullNotifiedFIFO_nothreadSafe(nf);
mutexunlock(nf->lockF);
return ret;
}
static inline time_stats_t exec_time_stats_NotifiedFIFO(const notifiedFIFO_elt_t *elt)
{
time_stats_t ts = {0};
if (elt->startProcessingTime == 0 && elt->endProcessingTime == 0)
return ts; /* no measurements done */
ts.in = elt->startProcessingTime;
ts.diff = elt->endProcessingTime - ts.in;
ts.p_time = ts.diff;
ts.diff_square = ts.diff * ts.diff;
ts.max = ts.diff;
ts.trials = 1;
return ts;
}
// This functions aborts all messages in the queue, and marks the queue as
// "aborted", such that every call to it will return NULL
static inline void abortNotifiedFIFO(notifiedFIFO_t *nf)
{
mutexlock(nf->lockF);
nf->abortFIFO = true;
notifiedFIFO_elt_t **elt = &nf->outF;
while (*elt != NULL) {
notifiedFIFO_elt_t *p = *elt;
*elt = (*elt)->next;
delNotifiedFIFO_elt(p);
}
if (nf->outF == NULL)
nf->inF = NULL;
condbroadcast(nf->notifF);
mutexunlock(nf->lockF);
}
#endif
+45
View File
@@ -0,0 +1,45 @@
/*
* 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
*/
#ifndef PTHREAD_UTILS_H
#define PTHREAD_UTILS_H
#include <pthread.h>
#define mutexinit(mutex) {int ret=pthread_mutex_init(&mutex,NULL); \
AssertFatal(ret==0,"ret=%d\n",ret);}
#define condinit(signal) {int ret=pthread_cond_init(&signal,NULL); \
AssertFatal(ret==0,"ret=%d\n",ret);}
#define mutexlock(mutex) {int ret=pthread_mutex_lock(&mutex); \
AssertFatal(ret==0,"ret=%d\n",ret);}
#define mutextrylock(mutex) pthread_mutex_trylock(&mutex)
#define mutexunlock(mutex) {int ret=pthread_mutex_unlock(&mutex); \
AssertFatal(ret==0,"ret=%d\n",ret);}
#define condwait(condition, mutex) {int ret=pthread_cond_wait(&condition, &mutex); \
AssertFatal(ret==0,"ret=%d\n",ret);}
#define condbroadcast(signal) {int ret=pthread_cond_broadcast(&signal); \
AssertFatal(ret==0,"ret=%d\n",ret);}
#define condsignal(signal) {int ret=pthread_cond_signal(&signal); \
AssertFatal(ret==0,"ret=%d\n",ret);}
#define mutexdestroy(mutex) { int ret = pthread_mutex_destroy(&mutex);\
AssertFatal(ret==0,"ret=%d\n",ret);}
#define conddestroy(condition) { int ret = pthread_cond_destroy(&condition);\
AssertFatal(ret==0,"ret=%d\n",ret);}
#endif
@@ -19,29 +19,12 @@
* contact@openairinterface.org
*/
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#ifndef TASK_WORK_STEALING_THREAD_POOL_H
#define TASK_WORK_STEALING_THREAD_POOL_H
#include "TLVEncoder.h"
int errorCodeEncoder = 0;
const char *const errorCodeStringEncoder[] = {
"No error",
"Buffer NULL",
"Buffer too short",
"Octet string too long for IEI",
"Wrong message type",
"Protocol not supported",
};
void tlv_encode_perror(void)
{
if (errorCodeEncoder >= 0)
// No error or TLV_DECODE_ERR_OK
return;
printf("error: (%d, %s)\n", errorCodeEncoder, errorCodeStringEncoder[errorCodeEncoder * -1]);
}
typedef struct {
void* args;
void (*func)(void* args);
} task_t;
#endif
+62
View File
@@ -0,0 +1,62 @@
/*
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenAirInterface Software Alliance licenses this file to You under
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
* except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.openairinterface.org/?page_id=698
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*-------------------------------------------------------------------------------
* For more information about the OpenAirInterface (OAI) Software Alliance:
* contact@openairinterface.org
*/
#include "task_ans.h"
#include "assertions.h"
#include <limits.h>
#include <stddef.h>
#include <stdint.h>
#include <stdlib.h>
#include <time.h>
void completed_task_ans(task_ans_t* task)
{
DevAssert(task != NULL);
if (atomic_load_explicit(&task->status, memory_order_acquire) != 0)
AssertFatal(0, "Task already finished?");
atomic_store_explicit(&task->status, 1, memory_order_release);
}
void join_task_ans(task_ans_t* arr, size_t len)
{
DevAssert(len < INT_MAX);
DevAssert(arr != NULL);
// Spin lock inspired by:
// The Art of Writing Efficient Programs:
// An advanced programmer's guide to efficient hardware utilization
// and compiler optimizations using C++ examples
const struct timespec ns = {0, 1};
uint64_t i = 0;
int j = len - 1;
for (; j != -1; i++) {
for (; j != -1; --j) {
int const task_completed = 1;
if (atomic_load_explicit(&arr[j].status, memory_order_acquire) != task_completed)
break;
}
if (i % 8 == 0) {
nanosleep(&ns, NULL);
}
}
}
+74
View File
@@ -0,0 +1,74 @@
/*
* 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
*/
#ifndef TASK_ANSWER_THREAD_POOL_H
#define TASK_ANSWER_THREAD_POOL_H
#ifdef __cplusplus
extern "C" {
#endif
#ifndef __cplusplus
#include <stdalign.h>
#include <stdatomic.h>
#else
#include <atomic>
#define _Atomic(X) std::atomic<X>
#define _Alignas(X) alignas(X)
#endif
#include <stddef.h>
#include <stdint.h>
#if defined(__i386__) || defined(__x86_64__)
#define LEVEL1_DCACHE_LINESIZE 64
#elif defined(__aarch64__)
// This is not always true for ARM
// in linux, you can obtain the size at runtime using sysconf (_SC_LEVEL1_DCACHE_LINESIZE)
// or from the bash with the command $ getconf LEVEL1_DCACHE_LINESIZE
// in c++ using std::hardware_destructive_interference_size
#define LEVEL1_DCACHE_LINESIZE 64
#else
#error Unknown CPU architecture
#endif
typedef struct {
// Avoid false sharing
_Alignas(LEVEL1_DCACHE_LINESIZE) _Atomic(int) status;
} task_ans_t;
typedef struct {
uint8_t* buf;
size_t len;
size_t cap; // capacity
task_ans_t* ans;
} thread_info_tm_t;
void join_task_ans(task_ans_t* arr, size_t len);
void completed_task_ans(task_ans_t* task);
#ifdef __cplusplus
}
#endif
#endif
+17 -14
View File
@@ -27,8 +27,10 @@
#include <unistd.h>
#include <ctype.h>
#include <sys/sysinfo.h>
#include <threadPool/thread-pool.h>
#include "thread-pool.h"
#include "log.h"
#include "task_ans.h"
#include "notified_fifo.h"
void displayList(notifiedFIFO_t *nf)
{
@@ -47,6 +49,7 @@ struct testData {
int id;
int sleepTime;
char txt[50];
task_ans_t* task_ans;
};
void processing(void *arg)
@@ -57,6 +60,7 @@ void processing(void *arg)
in->sleepTime = rand() % 1000;
usleep(in->sleepTime);
// printf("done: %d, %s, in thr %ld\n",in->id, in->txt,pthread_self() );
completed_task_ans(in->task_ans);
}
int main()
@@ -102,8 +106,6 @@ int main()
tpool_t pool;
char params[] = "1,2,3,4,5";
initTpool(params, &pool, true);
notifiedFIFO_t worker_back;
initNotifiedFIFO(&worker_back);
//sleep(1);
int cumulProcessTime = 0;
@@ -112,21 +114,22 @@ int main()
int nb_jobs = 4;
for (int i = 0; i < 1000; i++) {
int parall = nb_jobs;
task_ans_t task_ans[parall];
memset(task_ans, 0, sizeof(task_ans));
struct testData test_data[parall];
memset(test_data, 0, sizeof(test_data));
for (int j = 0; j < parall; j++) {
notifiedFIFO_elt_t *work = newNotifiedFIFO_elt(sizeof(struct testData), i, &worker_back, processing);
struct testData *x = (struct testData *)NotifiedFifoData(work);
task_t task = {.args = &test_data[j], .func = processing};
struct testData *x = (struct testData *)task.args;
x->id = i;
pushTpool(&pool, work);
x->task_ans = &task_ans[j];
pushTpool(&pool, task);
}
join_task_ans(task_ans, parall);
int sleepmax = 0;
while (parall) {
tmp = pullTpool(&worker_back, &pool);
if (tmp) {
parall--;
struct testData *dd = NotifiedFifoData(tmp);
if (dd->sleepTime > sleepmax)
sleepmax = dd->sleepTime;
delNotifiedFIFO_elt(tmp);
for (int j = 0; j < parall; j++) {
if (test_data[j].sleepTime > sleepmax) {
sleepmax = test_data[j].sleepTime;
}
}
cumulProcessTime += sleepmax;
+150 -121
View File
@@ -1,163 +1,192 @@
/*
* 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
*
* Author and copyright: Laurent Thomas, open-cells.com
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*-------------------------------------------------------------------------------
* For more information about the OpenAirInterface (OAI) Software Alliance:
* contact@openairinterface.org
*/
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenAirInterface Software Alliance licenses this file to You under
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
* except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.openairinterface.org/?page_id=698
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*-------------------------------------------------------------------------------
* For more information about the OpenAirInterface (OAI) Software Alliance:
* contact@openairinterface.org
*/
#define _GNU_SOURCE
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <ctype.h>
#include <threadPool/thread-pool.h>
#include "thread-pool.h"
#include "bounded_notified_fifo.h"
#include <sys/sysinfo.h>
typedef struct {
tpool_t* tpool;
int idx;
} task_thread_args_t;
static inline notifiedFIFO_elt_t *pullNotifiedFifoRemember( notifiedFIFO_t *nf, struct one_thread *thr) {
mutexlock(nf->lockF);
while(!nf->outF && !thr->terminate)
condwait(nf->notifF, nf->lockF);
if (thr->terminate) {
mutexunlock(nf->lockF);
return NULL;
void pushTpool(tpool_t* tpool, task_t task)
{
DevAssert(tpool != NULL);
if (tpool->len_thr == 0) {
task.func(task.args);
return;
}
notifiedFIFO_elt_t *ret=nf->outF;
nf->outF=nf->outF->next;
size_t const index = tpool->index++;
size_t const len_thr = tpool->len_thr;
if (nf->outF==NULL)
nf->inF=NULL;
not_q_t* q_arr = (not_q_t*)tpool->q_arr;
// For abort feature
thr->runningOnKey=ret->key;
thr->dropJob = false;
mutexunlock(nf->lockF);
return ret;
for (size_t i = 0; i < len_thr; ++i) {
if (try_push_not_q(&q_arr[(i + index) % len_thr], task)) {
return;
}
}
push_not_q(&q_arr[index % len_thr], task);
}
void *one_thread(void *arg) {
struct one_thread *myThread=(struct one_thread *) arg;
struct thread_pool *tp=myThread->pool;
static void* worker_thread(void* arg)
{
DevAssert(arg != NULL);
// Infinite loop to process requests
do {
notifiedFIFO_elt_t *elt=pullNotifiedFifoRemember(&tp->incomingFifo, myThread);
if (elt == NULL) {
AssertFatal(myThread->terminate, "pullNotifiedFifoRemember() returned NULL although thread not aborted\n");
task_thread_args_t* args = (task_thread_args_t*)arg;
int const idx = args->idx;
tpool_t* tpool = args->tpool;
uint32_t const len = tpool->len_thr;
uint32_t const num_it = 2 * (tpool->len_thr + idx);
not_q_t* q_arr = (not_q_t*)tpool->q_arr;
init_not_q(&q_arr[idx], idx);
// Synchronize all threads
pthread_barrier_wait(&tpool->barrier);
for (;;) {
ret_try_t ret = {.success = false};
for (uint32_t i = idx; i < num_it; ++i) {
ret = try_pop_not_q(&q_arr[i % len]);
if (ret.success == true)
break;
}
if (ret.success == false) {
if (pop_not_q(&q_arr[idx], &ret) == false)
break;
}
if (ret.t.func == NULL && ret.t.args == NULL) {
pushTpool(tpool, (task_t){.args = NULL, .func = NULL});
break;
}
ret.t.func(ret.t.args);
}
if (tp->measurePerf) elt->startProcessingTime=rdtsc_oai();
elt->processingFunc(NotifiedFifoData(elt));
if (tp->measurePerf) elt->endProcessingTime=rdtsc_oai();
if (elt->reponseFifo) {
// Check if the job is still alive, else it has been aborted
mutexlock(tp->incomingFifo.lockF);
if (myThread->dropJob)
delNotifiedFIFO_elt(elt);
else
pushNotifiedFIFO(elt->reponseFifo, elt);
myThread->runningOnKey=-1;
mutexunlock(tp->incomingFifo.lockF);
}
else
delNotifiedFIFO_elt(elt);
} while (!myThread->terminate);
free(args);
return NULL;
}
void initNamedTpool(char *params,tpool_t *pool, bool performanceMeas, char *name) {
memset(pool,0,sizeof(*pool));
char *measr=getenv("OAI_THREADPOOLMEASUREMENTS");
pool->measurePerf=performanceMeas;
// force measurement if the output is defined
pool->measurePerf |= measr!=NULL;
void initNamedTpool(char* params, tpool_t* tpool, bool performanceMeas, char* name)
{
(void)performanceMeas;
if (measr) {
mkfifo(measr,0666);
AssertFatal(-1 != (pool->dummyKeepReadingTraceFd=
open(measr, O_RDONLY| O_NONBLOCK)),"");
AssertFatal(-1 != (pool->traceFd=
open(measr, O_WRONLY|O_APPEND|O_NOATIME|O_NONBLOCK)),"");
} else
pool->traceFd=-1;
DevAssert(tpool != NULL);
memset(tpool, 0, sizeof(*tpool));
pool->activated=true;
initNotifiedFIFO(&pool->incomingFifo);
char *saveptr, * curptr;
char *parms_cpy=strdup(params);
pool->nbThreads=0;
curptr=strtok_r(parms_cpy,",",&saveptr);
struct one_thread * ptr;
char *tname = (name == NULL ? "Tpool" : name);
while ( curptr!=NULL ) {
int c=toupper(curptr[0]);
char* tname = (name == NULL ? "Tpool" : name);
char *saveptr, *curptr;
char* parms_cpy = strdup(params);
curptr = strtok_r(parms_cpy, ",", &saveptr);
int core_id[128] = {0};
int num_workers = 0;
while (curptr != NULL) {
int c = toupper(curptr[0]);
switch (c) {
case 'N':
pool->activated=false;
break;
default:
ptr=pool->allthreads;
pool->allthreads=(struct one_thread *)malloc(sizeof(struct one_thread));
pool->allthreads->next=ptr;
pool->allthreads->coreID=atoi(curptr);
pool->allthreads->id=pool->nbThreads;
pool->allthreads->pool=pool;
pool->allthreads->dropJob = false;
pool->allthreads->terminate = false;
//Configure the thread scheduler policy for Linux
// set the thread name for debugging
sprintf(pool->allthreads->name,"%s%d_%d",tname,pool->nbThreads,pool->allthreads->coreID);
// we set the maximum priority for thread pool threads (which is close
// but not equal to Linux maximum). See also the corresponding commit
// message; initially introduced for O-RAN 7.2 fronthaul split
threadCreate(&pool->allthreads->threadID, one_thread, (void *)pool->allthreads,
pool->allthreads->name, pool->allthreads->coreID, OAI_PRIORITY_RT_MAX);
pool->nbThreads++;
core_id[num_workers++] = atoi(curptr);
}
curptr=strtok_r(NULL,",",&saveptr);
curptr = strtok_r(NULL, ",", &saveptr);
}
free(parms_cpy);
if (pool->activated && pool->nbThreads==0) {
printf("No servers created in the thread pool, exit\n");
exit(1);
if (num_workers) {
tpool->q_arr = calloc(num_workers, sizeof(not_q_t));
AssertFatal(tpool->q_arr != NULL, "Memory exhausted");
tpool->t_arr = calloc(num_workers, sizeof(pthread_t));
AssertFatal(tpool->t_arr != NULL, "Memory exhausted");
}
tpool->len_thr = num_workers;
tpool->index = 0;
const pthread_barrierattr_t* barrier_attr = NULL;
int rc = pthread_barrier_init(&tpool->barrier, barrier_attr, num_workers + 1);
DevAssert(rc == 0);
for (size_t i = 0; i < num_workers; ++i) {
task_thread_args_t* args = malloc(sizeof(task_thread_args_t));
AssertFatal(args != NULL, "Memory exhausted");
args->idx = i;
args->tpool = tpool;
char name[64];
sprintf(name, "%s%ld_%d", tname, i, core_id[i]);
threadCreate(&tpool->t_arr[i], worker_thread, args, name, core_id[i], OAI_PRIORITY_RT_MAX);
}
// Syncronize thread pool threads. All the threads started
pthread_barrier_wait(&tpool->barrier);
}
void initFloatingCoresTpool(int nbThreads,tpool_t *pool, bool performanceMeas, char *name) {
void initFloatingCoresTpool(int nbThreads, tpool_t* pool, bool performanceMeas, char* name)
{
char threads[1024] = "n";
if (nbThreads) {
strcpy(threads,"-1");
for (int i=1; i < nbThreads; i++)
strncat(threads,",-1", sizeof(threads)-1);
strcpy(threads, "-1");
for (int i = 1; i < nbThreads; i++)
strncat(threads, ",-1", sizeof(threads) - 1);
}
threads[sizeof(threads)-1]=0;
threads[sizeof(threads) - 1] = 0;
initNamedTpool(threads, pool, performanceMeas, name);
}
void abortTpool(tpool_t* tpool)
{
if (tpool->len_thr > 0) {
not_q_t* q_arr = (not_q_t*)tpool->q_arr;
pushTpool(tpool, (task_t){.args = NULL, .func = NULL});
for (uint32_t i = 0; i < tpool->len_thr; ++i) {
int rc = pthread_join(tpool->t_arr[i], NULL);
DevAssert(rc == 0);
}
for (uint32_t i = 0; i < tpool->len_thr; ++i) {
free_not_q(&q_arr[i]);
}
free(tpool->q_arr);
free(tpool->t_arr);
}
int rc = pthread_barrier_destroy(&tpool->barrier);
DevAssert(rc == 0);
}
+52 -317
View File
@@ -1,26 +1,23 @@
/*
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenAirInterface Software Alliance licenses this file to You under
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
* except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.openairinterface.org/?page_id=698
*
* Author and copyright: Laurent Thomas, open-cells.com
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*-------------------------------------------------------------------------------
* For more information about the OpenAirInterface (OAI) Software Alliance:
* contact@openairinterface.org
*/
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenAirInterface Software Alliance licenses this file to You under
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
* except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.openairinterface.org/?page_id=698
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*-------------------------------------------------------------------------------
* For more information about the OpenAirInterface (OAI) Software Alliance:
* contact@openairinterface.org
*/
#ifndef THREAD_POOL_H
#define THREAD_POOL_H
@@ -35,316 +32,54 @@
#include "assertions.h"
#include "common/utils/time_meas.h"
#include "common/utils/system.h"
#include "task.h"
#include "pthread_utils.h"
#ifdef DEBUG
#define THREADINIT PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP
#else
#define THREADINIT PTHREAD_MUTEX_INITIALIZER
#endif
#define mutexinit(mutex) {int ret=pthread_mutex_init(&mutex,NULL); \
AssertFatal(ret==0,"ret=%d\n",ret);}
#define condinit(signal) {int ret=pthread_cond_init(&signal,NULL); \
AssertFatal(ret==0,"ret=%d\n",ret);}
#define mutexlock(mutex) {int ret=pthread_mutex_lock(&mutex); \
AssertFatal(ret==0,"ret=%d\n",ret);}
#define mutextrylock(mutex) pthread_mutex_trylock(&mutex)
#define mutexunlock(mutex) {int ret=pthread_mutex_unlock(&mutex); \
AssertFatal(ret==0,"ret=%d\n",ret);}
#define condwait(condition, mutex) {int ret=pthread_cond_wait(&condition, &mutex); \
AssertFatal(ret==0,"ret=%d\n",ret);}
#define condbroadcast(signal) {int ret=pthread_cond_broadcast(&signal); \
AssertFatal(ret==0,"ret=%d\n",ret);}
#define condsignal(signal) {int ret=pthread_cond_signal(&signal); \
AssertFatal(ret==0,"ret=%d\n",ret);}
#define tpool_nbthreads(tpool) (tpool.nbThreads)
typedef struct notifiedFIFO_elt_s {
struct notifiedFIFO_elt_s *next;
uint64_t key; //To filter out elements
struct notifiedFIFO_s *reponseFifo;
void (*processingFunc)(void *);
bool malloced;
oai_cputime_t creationTime;
oai_cputime_t startProcessingTime;
oai_cputime_t endProcessingTime;
oai_cputime_t returnTime;
// use alignas(32) to align msgData to 32b
// user data behind it will be aligned to 32b as well
// important! this needs to be the last member in the struct
alignas(32) void *msgData;
} notifiedFIFO_elt_t;
typedef struct notifiedFIFO_s {
notifiedFIFO_elt_t *outF;
notifiedFIFO_elt_t *inF;
pthread_mutex_t lockF;
pthread_cond_t notifF;
bool abortFIFO; // if set, the FIFO always returns NULL -> abort condition
} notifiedFIFO_t;
typedef struct {
pthread_t* t_arr;
size_t len_thr;
// You can use this allocator or use any piece of memory
static inline notifiedFIFO_elt_t *newNotifiedFIFO_elt(int size,
uint64_t key,
notifiedFIFO_t *reponseFifo,
void (*processingFunc)(void *)) {
notifiedFIFO_elt_t *ret = (notifiedFIFO_elt_t *)memalign(32, sizeof(notifiedFIFO_elt_t) + size);
AssertFatal(NULL != ret, "out of memory\n");
ret->next=NULL;
ret->key=key;
ret->reponseFifo=reponseFifo;
ret->processingFunc=processingFunc;
// We set user data piece aligend 32 bytes to be able to process it with SIMD
// msgData is aligned to 32bytes, so everything after will be as well
ret->msgData = ((uint8_t *)ret) + sizeof(notifiedFIFO_elt_t);
ret->malloced=true;
return ret;
}
_Atomic(uint64_t) index;
static inline void *NotifiedFifoData(notifiedFIFO_elt_t *elt) {
return elt->msgData;
}
void* q_arr;
static inline void delNotifiedFIFO_elt(notifiedFIFO_elt_t *elt) {
if (elt->malloced) {
elt->malloced = false;
free(elt);
}
/* it is allowed to call delNotifiedFIFO_elt when the memory is managed by
* the caller */
}
static inline void initNotifiedFIFO_nothreadSafe(notifiedFIFO_t *nf) {
nf->inF=NULL;
nf->outF=NULL;
nf->abortFIFO = false;
}
static inline void initNotifiedFIFO(notifiedFIFO_t *nf) {
mutexinit(nf->lockF);
condinit (nf->notifF);
initNotifiedFIFO_nothreadSafe(nf);
// No delete function: the creator has only to free the memory
}
static inline void pushNotifiedFIFO_nothreadSafe(notifiedFIFO_t *nf, notifiedFIFO_elt_t *msg) {
msg->next=NULL;
if (nf->outF == NULL)
nf->outF = msg;
if (nf->inF != NULL)
nf->inF->next = msg;
nf->inF = msg;
}
static inline void pushNotifiedFIFO(notifiedFIFO_t *nf, notifiedFIFO_elt_t *msg) {
mutexlock(nf->lockF);
if (!nf->abortFIFO) {
pushNotifiedFIFO_nothreadSafe(nf,msg);
condsignal(nf->notifF);
}
mutexunlock(nf->lockF);
}
static inline notifiedFIFO_elt_t *pullNotifiedFIFO_nothreadSafe(notifiedFIFO_t *nf) {
if (nf->outF == NULL)
return NULL;
if (nf->abortFIFO)
return NULL;
notifiedFIFO_elt_t *ret=nf->outF;
AssertFatal(nf->outF != nf->outF->next,"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 = NULL;
while((ret=pullNotifiedFIFO_nothreadSafe(nf)) == NULL && !nf->abortFIFO)
condwait(nf->notifF, nf->lockF);
mutexunlock(nf->lockF);
return ret;
}
static inline notifiedFIFO_elt_t *pollNotifiedFIFO(notifiedFIFO_t *nf) {
int tmp=mutextrylock(nf->lockF);
if (tmp != 0 )
return NULL;
if (nf->abortFIFO) {
mutexunlock(nf->lockF);
return NULL;
}
notifiedFIFO_elt_t *ret=pullNotifiedFIFO_nothreadSafe(nf);
mutexunlock(nf->lockF);
return ret;
}
static inline time_stats_t exec_time_stats_NotifiedFIFO(const notifiedFIFO_elt_t* elt)
{
time_stats_t ts = {0};
if (elt->startProcessingTime == 0 && elt->endProcessingTime == 0)
return ts; /* no measurements done */
ts.in = elt->startProcessingTime;
ts.diff = elt->endProcessingTime - ts.in;
ts.p_time = ts.diff;
ts.diff_square = ts.diff * ts.diff;
ts.max = ts.diff;
ts.trials = 1;
return ts;
}
// This functions aborts all messages in the queue, and marks the queue as
// "aborted", such that every call to it will return NULL
static inline void abortNotifiedFIFO(notifiedFIFO_t *nf) {
mutexlock(nf->lockF);
nf->abortFIFO = true;
notifiedFIFO_elt_t **elt = &nf->outF;
while(*elt != NULL) {
notifiedFIFO_elt_t *p = *elt;
*elt = (*elt)->next;
delNotifiedFIFO_elt(p);
}
if (nf->outF == NULL)
nf->inF = NULL;
condbroadcast(nf->notifF);
mutexunlock(nf->lockF);
}
struct one_thread {
pthread_t threadID;
int id;
int coreID;
char name[256];
uint64_t runningOnKey;
bool dropJob;
bool terminate;
struct thread_pool *pool;
struct one_thread *next;
};
typedef struct thread_pool {
bool activated;
bool measurePerf;
int traceFd;
int dummyKeepReadingTraceFd;
uint64_t cpuCyclesMicroSec;
int nbThreads;
notifiedFIFO_t incomingFifo;
struct one_thread *allthreads;
pthread_barrier_t barrier;
} tpool_t;
static inline void pushTpool(tpool_t *t, notifiedFIFO_elt_t *msg) {
if (t->measurePerf) msg->creationTime=rdtsc_oai();
/// @brief Push job to threadpool. May run task inline in case there are no worker threads
/// defined for threadpool
/// @param tpool threadpool to use
/// @param task task description
void pushTpool(tpool_t *tpool, task_t task);
if ( t->activated)
pushNotifiedFIFO(&t->incomingFifo, msg);
else {
if (t->measurePerf)
msg->startProcessingTime=rdtsc_oai();
/// @brief Abort tpool, stop all threads and return
/// @param t
void abortTpool(tpool_t *t);
msg->processingFunc(NotifiedFifoData(msg));
if (t->measurePerf)
msg->endProcessingTime=rdtsc_oai();
if (msg->reponseFifo)
pushNotifiedFIFO(msg->reponseFifo, msg);
else
delNotifiedFIFO_elt(msg);
}
}
static inline notifiedFIFO_elt_t *pullTpool(notifiedFIFO_t *responseFifo, tpool_t *t) {
notifiedFIFO_elt_t *msg= pullNotifiedFIFO(responseFifo);
if (msg == NULL)
return NULL;
AssertFatal(t->traceFd != 0, "Thread pool used while not initialized");
if (t->measurePerf)
msg->returnTime=rdtsc_oai();
if (t->traceFd > 0) {
ssize_t b = write(t->traceFd, msg, sizeof(*msg));
AssertFatal(b == sizeof(*msg), "error in write(): %d, %s\n", errno, strerror(errno));
}
return msg;
}
static inline notifiedFIFO_elt_t *tryPullTpool(notifiedFIFO_t *responseFifo, tpool_t *t) {
notifiedFIFO_elt_t *msg= pollNotifiedFIFO(responseFifo);
AssertFatal(t->traceFd != 0, "Thread pool used while not initialized");
if (msg == NULL)
return NULL;
if (t->measurePerf)
msg->returnTime=rdtsc_oai();
if (t->traceFd > 0) {
ssize_t b = write(t->traceFd, msg, sizeof(*msg));
AssertFatal(b == sizeof(*msg), "error in write(): %d, %s\n", errno, strerror(errno));
}
return msg;
}
static inline int abortTpool(tpool_t *t) {
int nbRemoved=0;
/* disables threading: if a message comes in now, we cannot have a race below
* as each thread will simply execute the message itself */
t->activated = false;
notifiedFIFO_t *nf=&t->incomingFifo;
mutexlock(nf->lockF);
nf->abortFIFO = true;
notifiedFIFO_elt_t **start=&nf->outF;
/* mark threads to abort them */
struct one_thread *thread = t->allthreads;
while (thread != NULL) {
thread->dropJob = true;
thread->terminate = true;
nbRemoved++;
thread = thread->next;
}
/* clear FIFOs */
while(*start!=NULL) {
notifiedFIFO_elt_t **request=start;
*start=(*start)->next;
delNotifiedFIFO_elt(*request);
*request = NULL;
nbRemoved++;
}
if (t->incomingFifo.outF==NULL)
t->incomingFifo.inF=NULL;
condbroadcast(t->incomingFifo.notifF);
mutexunlock(nf->lockF);
/* join threads that are still runing */
thread = t->allthreads;
while (thread != NULL) {
pthread_cancel(thread->threadID);
struct one_thread *next = thread->next;
free(thread);
thread = next;
}
return nbRemoved;
}
/// @brief Initialize a threadPool.
/// @param params A string in a form of "<int>,<int>,<int>,...,<int>" or "n"
/// if params is "n" threadpool is disabled and all functions are called inline.
/// else if params is a list of comma separated integers, the number of threads
/// is equal to the list length and each thread is pinned to a core indicated by
/// the integer value. If -1 is specified thread is not pinned to any core.
/// @param pool Theadpool
/// @param performanceMeas unused
/// @param name Name of the theadpool, will be used as pthread names for the pool worker threads
void initNamedTpool(char *params,tpool_t *pool, bool performanceMeas, char *name);
/// @brief Initialize a threadpool with floating core worker threads only
/// @param nbThreads number of floating core worker threads
/// @param pool Threadpool
/// @param performanceMeas unused
/// @param name Name of the theadpool, will be used as pthread names for the pool worker threads
void initFloatingCoresTpool(int nbThreads,tpool_t *pool, bool performanceMeas, char *name);
/// Convenience macro
#define initTpool(PARAMPTR,TPOOLPTR, MEASURFLAG) initNamedTpool(PARAMPTR,TPOOLPTR, MEASURFLAG, NULL)
#endif
+2 -193
View File
@@ -1,198 +1,7 @@
# Thread pool
The **thread pool** is a working server, made of a set of worker threads that can be mapped on CPU cores. Each thread pool has an **input queue** ("**FIFO**"), from which its workers pick **jobs** (FIFO element) to execute. When a job is done, the worker sends a message to an output queue, if it has been defined.
The **thread pool** is a working server, made of a set of worker threads that can be mapped on CPU cores.
All the thread pool functions are thread safe. The functions executed by worker threads are provided by the thread pool client, so the client has to handle the concurrency/parallel execution of his functions.
## license
Author:
Laurent Thomas, Open cells project
The owner share this piece code to Openairsoftware alliance as per OSA license terms
With contributions from Robert Schmidt, OSA
# Jobs
A job is a message of type `notifiedFIFO_elt_t`:
* `next`: internal FIFO chain, do not set it
* `key`: a `long int` that the client can use to identify a job or a group of messages
* `ResponseFifo`: if the client defines a response FIFO, the job will be posted back after processing
* `processingFunc`: any function (of type `void processingFunc(void *)`) that a worker will process
* `msgData`: the data passed to `processingFunc`. It can be added automatically, or you can set it to a buffer you are managing
* `malloced`: a boolean that enables internal free in the case of no return FIFO or abort feature
The job messages can be created and destroyed with `newNotifiedFIFO_elt()` and `delNotifiedFIFO_elt()`, or managed by the client:
* `newNotifiedFIFO_elt()`: Creates a job, that will later be used in queues/FIFO
* `delNotifiedFIFO_elt()`: Deletes a job
* `NotifiedFifoData()`: gives a pointer to the beginning of free usage memory in a job (you can put any data there, up to 'size' parameter you passed to `newNotifiedFIFO_elt()`)
These 3 calls are not mandatory, you can also use your own memory to save the `malloc()`/`free()` that are behind these calls.
## API details
### `notifiedFIFO_elt_t *newNotifiedFIFO_elt(int size, uint64_t key, notifiedFIFO_t *reponseFifo, void (*processingFunc)(void *))`
Creates a new job. The data part of the job will have size `size`, the job can be identified via `key`. `reponseFifo` is a FIFO queue to which the job should be pushed after being processed by a thread pool (see below for details) using function `processingFunc()`.
The function returns a pointer to an allocated job.
### `void delNotifiedFIFO_elt(notifiedFIFO_elt_t *elt)`
Free the memory allocated for a job `elt`.
### `void *NotifiedFifoData(notifiedFIFO_elt_t *elt)`
Returns a pointer (`void *`) to the data segment of an allocated job.
# Queues of jobs (`FIFO`)
Queues can be used to enqueue messages/jobs, of type `notifiedFIFO_t`.
* `initNotifiedFIFO()`: Create a queue
* No delete function is required, the creator has only to free the data of type `notifiedFIFO_t`
* `pushNotifiedFIFO()`: Add a job to a queue
* `pullNotifiedFIFO()`: Pull a job from a queue. This call is blocking until a job arrived.
* `pollNotifiedFIFO()`: Pull a job from a queue. This call is not blocking, so it returns always very shortly
* `abortNotifiedFIFO()`: Aborts a FIFO, such that it will always return `NULL`
Note that in 99.9% of cases, `pull()` is better than `poll()`.
The above push/pull/poll functions are built on not-thread-safe versions of these functions that are described below.
## Low level: fast and simple, but not thread-safe
* `initNotifiedFIFO_nothreadSafe()`: Create a queue
* `pushNotifiedFIFO_nothreadSafe()`: Add a element in a queue
* `pullNotifiedFIFO_nothreadSafe()`: Pull a element from a queue
As these queues are not thread safe, there is NO blocking mechanism, neither `pull()` versus `poll()` calls
There is no delete for a message queue: you only have to abandon the memory you allocated to call `initNotifiedFIFO_nothreadSafe(notifiedFIFO_t *nf)`
If you malloced the memory under `nf` parameter, you have to free it.
## FIFO queue abort
It is possible to *abort* the FIFO queue. In this case, any pulling/polling of jobs in the queue will return `NULL`. This can be used when stopping a program, to release multiple queues that might depend on each other (a proper design would try to avoid such dependencies, though).
## API details
### `void initNotifiedFIFO(notifiedFIFO_t *nf)`
### `void initNotifiedFIFO_nothreadSafe(notifiedFIFO_t *nf)`
Initializes a FIFO queue pointed to by `nf` ("notified FIFO").
### `void pushNotifiedFIFO(notifiedFIFO_t *nf, notifiedFIFO_elt_t *msg)`
### `void pushNotifiedFIFO_nothreadSafe(notifiedFIFO_t *nf, notifiedFIFO_elt_t *msg)`
Pushes a job `msg` to the FIFO queue `nf`.
### `notifiedFIFO_elt_t *pullNotifiedFIFO(notifiedFIFO_t *nf)`
Pulls a job from a FIFO queue `nf`. The returned pointer points to the job. This call is blocking, i.e., a caller will be blocked until there is a message.
If the FIFO has been aborted, the returned pointer will be `NULL`. In other words, if the call to this functions returns `NULL`, the FIFO has been deactivated.
### `notifiedFIFO_elt_t *pollNotifiedFIFO(notifiedFIFO_t *nf)`
### `notifiedFIFO_elt_t *pullNotifiedFIFO_nothreadSafe(notifiedFIFO_t *nf)`
Like `pullNotifiedFIFO()`, but non-blocking: they check if the queue `nf` contains a job, and return it. Otherwise, they return `NULL`. Note the slight difference in naming: the thread-safe function is called *poll*, not *pull*.
Note that unlike for `pullNotifiedFIFO()`, returning `NULL` does not inform whether the queue has been aborted; the caller should manually check the `abortFIFO` flag of `nf` in this case.
### `void abortNotifiedFIFO(notifiedFIFO_t *nf)`
Aborts the entire FIFO queue `nf`: all jobs will be dropped, and the FIFO is marked as aborted, such that a call to `pullNotifiedFIFO()` returns `NULL`.
Returns the total number of jobs that were waiting or under execution.
# Thread pools
## Initialization
The clients can create one or more thread pools with
* `initTpool(char *params, tpool_t *pool, bool performanceMeas)` or
* `initNamedTpool(char *params,tpool_t *pool, bool performanceMeas , char *name)`
The threads are governed by the Linux real time scheduler, and their name is set automatically to `Tpool<thread index>_<core id>` if `initTpool()` is used or to `<name><thread index>_<core id>` when `initNamedTpool()` is used.
## Adding jobs
The client create their jobs messages as a `notifiedFIFO_elt_t`. They then push it with `pushTpool()` which internally calls `push_notifiedFIFO()`.
If they need a return value (e.g., result of a computation), they have to create response queues with `init_notifiedFIFO()` and set this FIFO pointer in the `notifiedFIFO_elt_t` before pushing the job. This way, multiple result queues can be used in one thread pool.
## Abort
`abortTpool()` kills all jobs in the Tpool, and terminates the pool.
## API details
Each thread pool (there can be several in the same process) should be initialized once using one of the two API's:
### `void initNamedTpool(char *params, tpool_t *pool, bool performanceMeas, char *name)`
### `void initTpool(char *params, tpool_t *pool, bool performanceMeas)`
The `params` string describes a list of cores, separated by "," that run a worker thread. If the core exists on the CPU, the thread pool initialization sets the affinity between this thread and the related core. The following options are available:
* `N`: if an `N` is in the parameter list, no threads are created, and the threadpool will be disabled (jobs will be treated by each calling thread independently).
* A number that represent a valid CPU core on the target CPU, i.e., if there are `M` cores, a number within `[0,M-1]`: A thread is created and pinned to the core (with set affinity)
* `-1`: The thread will not be mapped onto a specific core (a "floating" thread)
Example: `-1,-1,-1`: the thread pool is made of 3 floating threads.
Be careful with a fixed allocation: it is hard to be more clever than Linux kernel!
`pool` is a pointer to the thread pool object.
`performanceMeas` is a flag to enable measurements (see also below).
`name` is used to build the thread names.
### `void pushTpool(tpool_t *t, notifiedFIFO_elt_t *msg)`
Adds a job for processing in the thread pool.
The job data you can set are, inside `msg`:
* `key`: an arbitrary key to find a job in a response queue.
* `reponseFifo`: if non-`NULL`, the message will be sent back on this queue when the job is done. If `NULL`, the thread pool automatically frees the job when it is done.
* `processingFunc`: the function to execute for this job.
The `processingFunc` prototype is `void <func>(void *memory)`. The data part of the job (the pointer returned by `NotifiedFifoData(msg)`) is passed to the function. The job data will be updated by `processingFunc`, and the job will be pushed into return queue (the parameter `reponseFifo`).
### `notifiedFIFO_elt_t *pullTpool(notifiedFIFO_t *responseFifo, tpool_t *t)`
Collects a job result in a return queue that has been defined in `msg` when calling `pushTpool()`, and that has been updated by `processingFunc()`. Returns the corresponding job pointer of type `notifiedFIFO_elt_t *`.
Multiple return queues might be useful. Consider the following example in the eNB: I created one single thread pool (because it depends mainly on CPU hardware), but i use two return queues: one for turbo encode, one for turbo decode. Thus, when performing Turbo encoding/decoding, jobs are pushed into a single thread pool, but will end up in different result queues, such that DL/UL processing can be separated more easily.
### `notifiedFIFO_elt_t *tryPullTpool(notifiedFIFO_t *responseFifo, tpool_t *t)`
The same as `pullTpool()` in a non-blocking fashion (an alternative name would have been `pollTpool()`).
### `int abortTpool(tpool_t *t)`
Aborts the complete Tpool: cancel every work in the input queue, marks to drop existing jobs in processing, and terminates all worker threads. It is afterwards still possible to call functions such as `pushTpool()`, but each calling thread will execute the job itself.
Returns the total number of jobs that were aborted, i.e., waiting for execution or being executed.
## Performance measurements
A performance measurement is integrated: the pool will automacillay fill timestamps if you set the environement variable `OAI_THREADPOOLMEASUREMENTS` to a valid file name. The following measurements will be written to Linux pipe on a per-job basis:
* `creationTime`: time the request is push to the pool;
* `startProcessingTime`: time a worker start to run on the job
* `endProcessingTime`: time the worker finished the job
* `returnTime`: time the client reads the result
The `measurement_display` tool to read the Linux pipe and display it in ASCII is provided.
In the cmake build directory, type `make/ninja measurement_display`. Use as
follows:
```
sudo OAI_THREADPOOLMEASUREMENTS=tpool.meas ./nr-softmodem ...
./measurement_display tpool.meas
```
See header file doxygen comments for detailed description of the API
+1 -1
View File
@@ -27,7 +27,7 @@
#include "assertions.h"
#include <pthread.h>
#include "common/config/config_userapi.h"
#include <common/utils/threadPool/thread-pool.h>
#include "common/utils/threadPool/notified_fifo.h"
// global var for openair performance profiler
int cpu_meas_enabled = 0;
double cpu_freq_GHz __attribute__ ((aligned(32)));
+1 -1
View File
@@ -62,7 +62,7 @@ add_library(websrv MODULE
websrv_utils.c
../../../openair1/PHY/TOOLS/nr_phy_scope.c
)
target_link_libraries(websrv PRIVATE ulfius jansson asn1_nr_rrc_hdrs)
target_link_libraries(websrv PRIVATE ulfius jansson asn1_nr_rrc_hdrs UTIL)
target_compile_definitions(websrv PUBLIC WEBSRVSCOPE)
# put websrv into build root and not under build/common/utils/websrv/
set_target_properties(websrv PROPERTIES LIBRARY_OUTPUT_DIRECTORY ../../..)
-1
View File
@@ -1332,7 +1332,6 @@ INPUT = \
@CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/UTIL/parser.h \
@CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/UTIL/device.h \
@CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/UTIL/device.c \
@CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/UTIL/TLVEncoder.c \
@CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/UTIL/OctetString.h \
@CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/UTIL/nas_timer.c \
@CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/UTIL/TLVDecoder.c \
+119
View File
@@ -0,0 +1,119 @@
<table style="border-collapse: collapse; border: none;">
<tr style="border-collapse: collapse; border: none;">
<td style="border-collapse: collapse; border: none;">
<a href="http://www.openairinterface.org/">
<img src="./images/oai_final_logo.png" alt="" border=3 height=50 width=150>
</img>
</a>
</td>
<td style="border-collapse: collapse; border: none; vertical-align: center;">
<b><font size = "5">OAI 5G NR SA tutorial to deploy multiple OAI nrUE</font></b>
</td>
</tr>
</table>
**Table of Contents**
[[_TOC_]]
# Scenario
This tutorial is about how to configure and run multiple OAI nrUE in the same end-to-end OAI 5G setup with RFsimulator.
# Pre-requisites
This tutorial is assuming that OAI CN5G and OAI RAN are already deployed. To learn how to deploy and run a basic setup with OAI nrUE, please refer to [NR_SA_Tutorial_OAI_nrUE.md](NR_SA_Tutorial_OAI_nrUE.md).
Also, it is suggested to get some knowledge on how the channel simulation with OAI RFsimulator works. Please refer to the following documentation to learn about the relevant topics discussed:
- RFsimulator tutorial [rfsimulator/README.md](../radio/rfsimulator/README.md)
- Channel simulation with OAI [channel_simulation.md](../openair1/SIMULATION/TOOLS/DOC/channel_simulation.md)
- Telnet server usage [telnetusage.md](../common/utils/telnetsrv/DOC/telnetusage.md).
# Run multiple UEs in RFsimulator
## Multiple nrUEs with namespaces
Important notes:
* This should be run on the same host as the OAI gNB
* Use the script [multi_ue.sh](../tools/scripts/multi-ue.sh) to make namespaces for multiple UEs.
* For each UE, a namespace shall be created, each one has a different address that will be used as rfsim server address
* Each UE shall have a different IMSI, which shall be present in the relevant tables of the MySQL database
* Each UE shall run a telnet server on a different port, with command line option `--telnetsrv.listenport`
1. For the first UE, create the namespace ue1 (`-c1`), then execute shell inside (`-o1`, "open"):
```bash
sudo ./multi-ue.sh -c1
sudo ./multi-ue.sh -o1
```
2. After entering the bash environment, run the following command to deploy your first UE
```bash
sudo ./nr-uesoftmodem -O ../../../targets/PROJECTS/GENERIC-NR-5GC/CONF/ue.conf -r 106 --numerology 1 --band 78 -C 3619200000 --rfsim --uicc0.imsi 001010000000001 --rfsimulator.options chanmod --rfsimulator.serveraddr 10.201.1.100 --telnetsrv --telnetsrv.listenport 9095
```
3. For the second UE, create the namespace ue2 (`-c1`), then execute shell inside (`-o1`, "open"):
```bash
sudo ./multi-ue.sh -c2
sudo ./multi-ue.sh -o2
```
4. After entering the bash environment, run the following command to deploy your second UE:
```bash
sudo ./nr-uesoftmodem -O ../../../targets/PROJECTS/GENERIC-NR-5GC/CONF/ue.conf -r 106 --numerology 1 --band 78 -C 3619200000 --rfsim --uicc0.imsi 001010000000002 --rfsimulator.options chanmod --rfsimulator.serveraddr 10.202.1.100 --telnetsrv --telnetsrv.listenport 9096
```
in the command above, please note that the IMSI and the telnet port changed.
## Running Multiple UEs with Docker
1. Make sure OAI nrUE image is pulled:
```bash
docker pull oaisoftwarealliance/oai-nr-ue:latest
```
2. Configure your setup by editing the Docker compose file e.g. in [docker-compose.yaml](../ci-scripts/yaml_files/5g_rfsimulator/docker-compose.yaml).
3. Deploy the UEs, e.g. for 3 UEs:
```bash
docker compose up -d oai-nr-ue{1,2,3}
```
4. Check the logs to ensure each UE has gotten an IP address, e.g.:
```bash
docker logs oai-nr-ue1
```
or
```bash
docker exec -it oai-nr-ue1 ip a show oaitun_ue1
```
5. Test the connectivity of each UE to the core network:
```bash
docker exec -it oai-nr-ue1 ping -c1 192.168.70.135
```
7. After testing, undeploy the UEs to allow them time to deregister, and then bring down the rest of the network:
```bash
docker compose stop oai-nr-ue{1,2,3}
docker compose down -v
```
# Further reading
For more details and scenarios, refer to the following files:
* [RFSIM deployment in the CI](../ci-scripts/yaml_files/5g_rfsimulator/README.md)
* [E1 deployment in the CI](../ci-scripts/yaml_files/5g_rfsimulator_e1/README.md)
* [Docker documentation](../docker/README.md)
+16 -7
View File
@@ -78,8 +78,10 @@ Tested libxran releases:
| Vendor |
|-----------------------------------------|
| `oran_e_maintenance_release_v1.0` |
| `oran_f_release_v1.0` |
**Note**: The libxran driver of OAI identifies the above version as "5.1.0" (E is fifth letter, then 1.0).
**Note**: The libxran driver of OAI identifies the above E release version as "5.1.0" (E is fifth letter, then 1.0), and the above F release as "6.1.0".
## Configure your server
@@ -379,19 +381,22 @@ cd ~/openairinterface5g/
## Build ORAN Fronthaul Interface Library
Download ORAN FHI DU library and checkout the correct version.
Download ORAN FHI DU library, checkout the correct version, and apply the correct patch (available in `oai_folder/cmake_targets/tools/oran_fhi_integration_patches`).
### E release
```bash
git clone https://gerrit.o-ran-sc.org/r/o-du/phy.git ~/phy
cd ~/phy
git checkout oran_e_maintenance_release_v1.0
git apply ~/openairinterface5g/cmake_targets/tools/oran_fhi_integration_patches/E/oaioran_E.patch
```
Apply the patch (available in `oai_folder/cmake_targets/tools/oran_fhi_integration_patches/E`):
### F release
```bash
git clone https://gerrit.o-ran-sc.org/r/o-du/phy.git ~/phy
cd ~/phy
git apply ~/openairinterface5g/cmake_targets/tools/oran_fhi_integration_patches/E/oaioran_E.patch
git checkout oran_f_release_v1.0
git apply ~/openairinterface5g/cmake_targets/tools/oran_fhi_integration_patches/F/oaioran_F.patch
```
Compile the fronthaul interface library by calling `make` and the option
@@ -404,7 +409,8 @@ environment variables `RTE_SDK` for the path to the source tree of DPDK, and
```bash
cd ~/phy/fhi_lib/lib
make clean
RTE_SDK=~/dpdk-stable-20.11.9/ XRAN_DIR=~/phy/fhi_lib make XRAN_LIB_SO=1
RTE_SDK=~/dpdk-stable-20.11.9/ XRAN_DIR=~/phy/fhi_lib make XRAN_LIB_SO=1 # E release
WIRELESS_SDK_TOOLCHAIN=gcc RTE_SDK=~/dpdk-stable-20.11.9/ XRAN_DIR=~/phy/fhi_lib make XRAN_LIB_SO=1 # F release
...
[AR] build/libxran.so
./build/libxran.so
@@ -911,6 +917,7 @@ Edit the sample OAI gNB configuration file and check following parameters:
cannot preallocate memory on NUMA nodes other than 0; in this case, set
this to 0 (no pre-allocation) and so that DPDK will allocate it on-demand
on the right NUMA node.
* `owdm_enable`: used for eCPRI One-Way Delay Measurements; it depends if the RU supports it; if not set to 1 (enabled), default value is 0 (disabled)
* `fh_config`: parameters that need to match RU parameters
* timing parameters (starting with `T`) depend on the RU: `Tadv_cp_dl` is a
single number, the rest pairs of numbers `(x, y)` specifying minimum and
@@ -928,7 +935,9 @@ Layer mapping (eAxC offsets) happens as follows:
- For PUSCH/PDSCH, the layers are mapped to `[0,1,...,Nrx-1]/[0,1,...,Ntx-1]` where `Nrx/Ntx` is the
respective RX/TX number of antennas.
- For PRACH, the layers are mapped to `[No,No+1,...No+Nrx-1]` where `No` is the
`fhi_72.fh_config.[0].prach_config.eAxC_offset`. Please be aware that the following equation must be fullfilled: `No >= max(Nrx,Ntx)`.
`fhi_72.fh_config.[0].prach_config.eAxC_offset`. xran assumes PRACH offset `No >= max(Nrx,Ntx)`.
However, we made a workaround that xran supports PRACH eAxC IDs same as PUSCH eAxC IDs. This is achieved with `is_prach` and `filter_id` parameters in the patch.
Please note that this approach only applies to the RUs that support this functionality, e.g. LITEON RU.
**Note**
+2
View File
@@ -43,6 +43,7 @@ There is some general information in the [OpenAirInterface Gitlab Wiki](https://
* [OAI 5GC](./NR_SA_Tutorial_OAI_CN5G.md)
* [OAI gNB with COTS UE](./NR_SA_Tutorial_COTS_UE.md)
* [OAI NR-UE](./NR_SA_Tutorial_OAI_nrUE.md)
* [Multiple OAI NR-UE with RFsimulator](./NR_SA_Tutorial_OAI_multi_UE.md)
- [RUNMODEM.md](./RUNMODEM.md): Generic information on how to
* Run simulators
* Run with hardware
@@ -64,6 +65,7 @@ There is some general information in the [OpenAirInterface Gitlab Wiki](https://
- [How to setup OAI with Nvidia Aerial and Foxconn](./Aerial_FAPI_Split_Tutorial.md)
- [How to setup OAI with AMD T2 Telco card](./LDPC_T2_OFFLOAD_SETUP.md)
- [How to do a handover](./handover-tutorial.md)
- [How to setup gNB frequency](./gNB_frequency_setup.md)
Legacy unmaintained files:
- [`L2NFAPI_NOS1.md`](./L2NFAPI_NOS1.md), [`L2NFAPI_S1.md`](./L2NFAPI_S1.md):
+80
View File
@@ -0,0 +1,80 @@
# 5G gNB Frequency Configuration
Configuring the frequency settings for a 5G gNB involves specifying multiple parameters in the gNB configuration file. This guide outlines the necessary parameters and provides step-by-step instructions for configuration.
[TOC]
## Configuration parameters
To configure the gNB with the required frequency and bandwidth, modify following parameters in the configuration file:
### `gNBs` Section
* `absoluteFrequencySSB`: ARFCN (frequency number) of the middle frequency of the SSB. This value must align with the NR frequency raster defined in TS 38.104, Section 5.4.3.1.
* Steps to compute this value are provided below.
* `dl_absoluteFrequencyPointA`: ARFCN (frequency number) for Point A, lowest subcarrier of the reference resource block (Common RB 0).
* Steps to compute this value are provided below.
* `dl_frequencyBand`: downlink NR frequency band number.
* `dl_subcarrierSpacing`: downlink subcarrier spacing.
* *Allowed values:* `0` = 15 kHz, `1` = 30 kHz, `2` = 60 kHz, `3` = 120 kHz
* `dl_carrierBandwidth`: number of PRBs for downlink.
* `initialDLBWPlocationAndBandwidth`: resource indicator value (RIV) of the initial BWP.
* Steps to compute this value are provided below.
* `initialDLBWPsubcarrierSpacing`: initial downlink BWP subcarrier spacing.
* *Allowed values:* `0` = 15 kHz, `1` = 30 kHz, `2` = 60 kHz, `3` = 120 kHz
* `initialDLBWPcontrolResourceSetZero`: CORESET0 index (valid configurations, based on SCS and frequency bandwith, are given in TS 38.213, Table 13.1 to Table 13.14).
* `ul_frequencyBand`: uplink NR frequency band number.
* `ul_absoluteFrequencyPointA`: ARFCN (frequency number) for Point A, lowest subcarrier of the reference resource block (Common RB 0).
* **Set only for FDD configurations.**
* Frequency separation between DL and UL channels for a specific 5G NR band is defined in 38.101-1 5.4.4-1 for FR1 bands and in 38.101-5 5.4.4-1 for FR1 NTN bands. `ul_absoluteFrequencyPointA` is calculated by substracting the given frequency offset from the `dl_absoluteFrequencyPointA`.
* `ul_carrierBandwidth`: number of PRBs for uplink.
* `initialULBWPlocationAndBandwidth`: resource indicator value (RIV) of the initial BWP.
* Steps to compute this value are provided below.
* `initialULBWPsubcarrierSpacing`: initial uplink BWP subcarrier spacing.
* *Allowed values:* `0` = 15 kHz, `1` = 30 kHz, `2` = 60 kHz, `3` = 120 kHz
* `subcarrierSpacing`: general subcarrier spacing for both DL and UL.
* *Allowed values:* `0` = 15 kHz, `1` = 30 kHz, `2` = 60 kHz, `3` = 120 kHz
### `RUs` Section
* `bands`: NR frequency band number for RU(s).
## Determining the ARFCN value for `absoluteFrequencySSB` and `dl_absoluteFrequencyPointA`
Follow these steps to find the ARFCN values for `absoluteFrequencySSB`, `dl_absoluteFrequencyPointA`, `initialDLBWPlocationAndBandwidth`, and `initialULBWPlocationAndBandwidth`:
1. Convert RU center frequency to ARFCN value
* Example tool: [5G NR ARFCN Calculator](https://5g-tools.com/5g-nr-arfcn-calculator/)
* Input the center frequency of the RU (in MHz) into the tool to calculate the ARFCN value.
2. Enter parameters into the online tool for NR Point A computation
* Example tool: [NR Reference Point A Tool](https://www.sqimway.com/nr_refA.php)
* Enter the NR frequency band, ARFCN value for center frequency (use the value calculated in step 1), subcarrier spacing, CORESET0 index (`initialDLBWPcontrolResourceSetZero` in the gNB config file) and bandwidth into the tool.
3. Obtain required values
* From the tool's output, use the following results for your configuration:
* Arfcn GSCN: This corresponds to `absoluteFrequencySSB` - value for `absoluteFrequencySSB` can be selected freely from the table, if `Coreset(0) check` is "ok".
* Point A Arfcnc: This corresponds to `dl_absoluteFrequencyPointA`.
* locationAndBandwidth full: Use this value for both `initialDLBWPlocationAndBandwidth` and `initialULBWPlocationAndBandwidth`.
4. Set `dl_absoluteFrequencyPointA`, `absoluteFrequencySSB`, `initialDLBWPlocationAndBandwidth`, and `initialULBWPlocationAndBandwidth` in the gNB configuration file
## Example calculation
1. Convert RU center frequency to ARFCN value
* Center frequency = 3450 MHz
* Center frequency ARFCN = 630000
2. Enter parameters into the online tool for NR Point A computation
* Open the [NR Reference Point A Tool](https://www.sqimway.com/nr_refA.php) and input the following values:
* Frequency band = n78
* NR Arfcn scan (center frequency) = 630000
* SCS = 30 kHz
* Bandwidth = 100 MHz
* Control ResourceSet Zero = 11
3. Obtain required values
* The tool provides following output values:
* Arfcn GSCN (`absoluteFrequencySSB`) = 630048
* Point A Arfcnc (`dl_absoluteFrequencyPointA`) = 626724
* locationAndBandwidth full (`initialDLBWPlocationAndBandwidth`) = 1099
* locationAndBandwidth full (`initialULBWPlocationAndBandwidth`) = 1099
+3 -3
View File
@@ -43,10 +43,10 @@ RUN wget http://fast.dpdk.org/rel/dpdk-20.11.9.tar.xz && \
## Build Fronthaul library
RUN git clone https://gerrit.o-ran-sc.org/r/o-du/phy.git /opt/phy && \
cd /opt/phy && \
git checkout oran_e_maintenance_release_v1.0 &&\
git apply /oai-ran/cmake_targets/tools/oran_fhi_integration_patches/E/oaioran_E.patch && \
git checkout oran_f_release_v1.0 &&\
git apply /oai-ran/cmake_targets/tools/oran_fhi_integration_patches/F/oaioran_F.patch && \
cd /opt/phy/fhi_lib/lib && \
RTE_SDK=/oai-ran/dpdk-stable-20.11.9/ XRAN_DIR=/opt/phy/fhi_lib make XRAN_LIB_SO=1
WIRELESS_SDK_TOOLCHAIN=gcc RTE_SDK=/oai-ran/dpdk-stable-20.11.9/ XRAN_DIR=/opt/phy/fhi_lib make XRAN_LIB_SO=1
FROM ran-base AS ran-build-fhi72
ARG E2AP_VERSION=E2AP_V3
+3 -3
View File
@@ -56,10 +56,10 @@ RUN wget http://fast.dpdk.org/rel/dpdk-20.11.9.tar.xz && \
## Build Fronthaul library
RUN git clone https://gerrit.o-ran-sc.org/r/o-du/phy.git /opt/phy && \
cd /opt/phy && \
git checkout oran_e_maintenance_release_v1.0 &&\
git apply /oai-ran/cmake_targets/tools/oran_fhi_integration_patches/E/oaioran_E.patch && \
git checkout oran_f_release_v1.0 &&\
git apply /oai-ran/cmake_targets/tools/oran_fhi_integration_patches/F/oaioran_F.patch && \
cd /opt/phy/fhi_lib/lib && \
RTE_SDK=/oai-ran/dpdk-stable-20.11.9/ XRAN_DIR=/opt/phy/fhi_lib make XRAN_LIB_SO=1
WIRELESS_SDK_TOOLCHAIN=gcc RTE_SDK=/oai-ran/dpdk-stable-20.11.9/ XRAN_DIR=/opt/phy/fhi_lib make XRAN_LIB_SO=1
FROM ran-base AS ran-build-fhi72
## Build and install OAI
+1
View File
@@ -44,6 +44,7 @@ RUN /bin/sh oaienv && \
--build-e2 --cmake-opt -DXAPP_MULTILANGUAGE=OFF --cmake-opt \
-DKPM_VERSION=$KPM_VERSION --cmake-opt -DE2AP_VERSION=$E2AP_VERSION \
--build-lib 'telnetsrv enbscope uescope nrscope' \
--build-tool-opt -k10 \
-w USRP -t Ethernet \
--noavx512" && \
echo "---- ldd on executables ----" && \
+1
View File
@@ -38,6 +38,7 @@ RUN /bin/sh oaienv && \
CXXFLAGS="-Werror -fstack-protector-strong" CFLAGS="-Werror -fstack-protector-strong" ./build_oai -c --ninja \
--eNB --gNB --RU --UE --nrUE \
--build-lib "telnetsrv enbscope uescope nrscope" \
--build-tool-opt -k10 \
-w USRP -t Ethernet \
--noavx512 && \
echo "---- ldd on executables ----" && \
+1
View File
@@ -45,6 +45,7 @@ RUN /bin/sh oaienv && \
-w USRP -t Ethernet \
--build-e2 --cmake-opt -DXAPP_MULTILANGUAGE=OFF --cmake-opt -DKPM_VERSION=$KPM_VERSION --cmake-opt -DE2AP_VERSION=$E2AP_VERSION \
--noavx512 \
--build-tool-opt -k10 \
--cmake-opt -DCMAKE_C_FLAGS="-Werror" --cmake-opt -DCMAKE_CXX_FLAGS="-Werror" $BUILD_OPTION && \
# Mainly to see if the sanitize option was perfectly executed
echo "---- ldd on executables ----" && \
+1 -1
View File
@@ -48,7 +48,7 @@ RUN /bin/sh oaienv && \
-DCMAKE_C_FLAGS="-Werror" -DCMAKE_CXX_FLAGS="-Werror" && \
echo "====== Start of log for cross-build executables ======" && \
# making always passing so we can analyze the all.txt file
ninja dlsim ulsim ldpctest polartest smallblocktest nr_pbchsim nr_dlschsim nr_ulschsim nr_dlsim nr_ulsim nr_pucchsim nr_prachsim lte-softmodem nr-softmodem nr-cuup oairu lte-uesoftmodem nr-uesoftmodem params_libconfig coding rfsimulator telnetsrv > ../../log/all.txt 2>&1; \
ninja -k10 dlsim ulsim ldpctest polartest smallblocktest nr_pbchsim nr_dlschsim nr_ulschsim nr_dlsim nr_ulsim nr_pucchsim nr_prachsim lte-softmodem nr-softmodem nr-cuup oairu lte-uesoftmodem nr-uesoftmodem params_libconfig coding rfsimulator telnetsrv > ../../log/all.txt 2>&1; \
# displaying errors and warnings
grep -E -A3 "warning:|error:" ../../log/all.txt || true && \
# will fail only if string "errors:" is found
+4 -1
View File
@@ -40,4 +40,7 @@ RUN /bin/sh oaienv && \
mkdir -p log && \
export CC=/usr/bin/clang && \
export CXX=/usr/bin/clang++ && \
CFLAGS="-Werror" CXXFLAGS="-Werror -Wno-vla-cxx-extension" ./build_oai --phy_simulators --gNB --eNB --nrUE --UE --ninja --noavx512 --disable-T-Tracer -c
CFLAGS="-Werror" CXXFLAGS="-Werror -Wno-vla-cxx-extension" \
./build_oai --phy_simulators --gNB --eNB --nrUE --UE \
--ninja --build-tool-opt -k10 \
--noavx512 --disable-T-Tracer -c
+1 -1
View File
@@ -54,7 +54,7 @@ RUN /bin/sh oaienv && \
RUN /bin/sh oaienv && \
cd cmake_targets && \
mkdir -p log && \
./build_oai -c -w AERIAL --gNB --ninja \
./build_oai -c -w AERIAL --gNB --ninja --build-tool-opt -k10 \
--cmake-opt -DCMAKE_C_FLAGS="-Werror" --cmake-opt -DCMAKE_CXX_FLAGS="-Werror"
+1 -1
View File
@@ -38,7 +38,7 @@ RUN dnf install -y libasan libubsan
RUN /bin/sh oaienv && \
cd cmake_targets && \
mkdir -p log && \
./build_oai --phy_simulators --ninja --sanitize --noavx512 -c --cmake-opt -DCMAKE_C_FLAGS=-Werror --cmake-opt -DCMAKE_CXX_FLAGS=-Werror
./build_oai --phy_simulators --ninja --build-tool-opt -k10 --sanitize --noavx512 -c --cmake-opt -DCMAKE_C_FLAGS=-Werror --cmake-opt -DCMAKE_CXX_FLAGS=-Werror
#start from scratch for target executable
FROM registry.access.redhat.com/ubi9/ubi:latest AS oai-physim
+2 -2
View File
@@ -52,12 +52,12 @@ int create_tasks(uint32_t enb_nb) {
rrc_enb_init();
itti_mark_task_ready(TASK_RRC_ENB);
if (get_softmodem_params()->emulate_l1 || EPC_MODE_ENABLED) {
if (get_softmodem_params()->emulate_l1 || !IS_SOFTMODEM_NOS1) {
rc = itti_create_task(TASK_SCTP, sctp_eNB_task, NULL);
AssertFatal(rc >= 0, "Create task for SCTP failed\n");
}
if (EPC_MODE_ENABLED) {
if (!IS_SOFTMODEM_NOS1) {
rc = itti_create_task(TASK_S1AP, s1ap_eNB_task, NULL);
AssertFatal(rc >= 0, "Create task for S1AP failed\n");
rc = itti_create_task(TASK_GTPV1_U, gtpv1uTask, NULL);
+5 -6
View File
@@ -52,12 +52,11 @@ int create_tasks_mbms(uint32_t enb_nb) {
if (enb_nb == 0) return 0;
if(!EPC_MODE_ENABLED){
if (IS_SOFTMODEM_NOS1) {
rc = itti_create_task(TASK_SCTP, sctp_eNB_task, NULL);
AssertFatal(rc >= 0, "Create task for SCTP failed\n");
}
LOG_I(MME_APP, "Creating MME_APP eNB Task\n");
rc = itti_create_task (TASK_MME_APP, MME_app_task, NULL);
AssertFatal(rc >= 0, "Create task for MME APP failed\n");
@@ -71,12 +70,12 @@ int create_tasks_mbms(uint32_t enb_nb) {
rc = itti_create_task (TASK_MCE_APP, MCE_app_task, NULL);
AssertFatal(rc >= 0, "Create task for MCE APP failed\n");
if(!EPC_MODE_ENABLED){
// rc = itti_create_task(TASK_SCTP, sctp_eNB_task, NULL);
// AssertFatal(rc >= 0, "Create task for SCTP failed\n");
if (IS_SOFTMODEM_NOS1) {
// rc = itti_create_task(TASK_SCTP, sctp_eNB_task, NULL);
// AssertFatal(rc >= 0, "Create task for SCTP failed\n");
rc = itti_create_task(TASK_GTPV1_U, gtpv1uTask, NULL);
AssertFatal(rc >= 0, "Create task for GTPV1U failed\n");
}
}
if (is_m3ap_MCE_enabled()) {
rc = itti_create_task(TASK_M3AP_MCE, m3ap_MCE_task, NULL);
+2 -2
View File
@@ -39,7 +39,7 @@ int create_tasks_ue(uint32_t ue_nb)
LOG_D(ENB_APP, "%s(ue_nb:%d)\n", __FUNCTION__, ue_nb);
itti_wait_ready(1);
if (EPC_MODE_ENABLED) {
if (!IS_SOFTMODEM_NOS1) {
# if defined(NAS_BUILT_IN_UE)
if (ue_nb > 0) {
@@ -57,7 +57,7 @@ int create_tasks_ue(uint32_t ue_nb)
}
# endif
} /* EPC_MODE_ENABLED */
}
if (ue_nb > 0) {
if (itti_create_task (TASK_RRC_UE, rrc_ue_task, NULL) < 0) {
+2 -7
View File
@@ -117,13 +117,10 @@ 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
@@ -455,9 +452,7 @@ int main ( int argc, char **argv )
printf("Reading in command-line options\n");
get_options(uniqCfg);
EPC_MODE_ENABLED = !IS_SOFTMODEM_NOS1;
if (CONFIG_ISFLAGSET(CONFIG_ABORT) ) {
if (CONFIG_ISFLAGSET(CONFIG_ABORT)) {
fprintf(stderr,"Getting configuration failed\n");
exit(-1);
}
@@ -470,7 +465,7 @@ int main ( int argc, char **argv )
printf("configuring for RAU/RRU\n");
cpuf=get_cpu_freq_GHz();
printf("ITTI init, useMME: %i\n",EPC_MODE_ENABLED);
printf("ITTI init, useMME: %i\n", !IS_SOFTMODEM_NOS1);
itti_init(TASK_MAX, tasks_info);
init_opt();
-3
View File
@@ -114,11 +114,9 @@ FILE *input_fd=NULL;
int otg_enabled=0;
#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] = {{130,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] = {{130,0,0,0},{20,0,0,0}};
#endif
@@ -543,7 +541,6 @@ int main( int argc, char **argv ) {
}
printf("sf_ahead = %d\n", sf_ahead);
EPC_MODE_ENABLED = !IS_SOFTMODEM_NOS1;
printf("Running with %d UE instances\n",NB_UE_INST);
#if T_TRACER
-1
View File
@@ -28,7 +28,6 @@
#undef MALLOC
#include "assertions.h"
#include "PHY/types.h"
#include <threadPool/thread-pool.h>
/* 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"
-5
View File
@@ -107,11 +107,9 @@ char *uecap_file;
runmode_t mode = normal_txrx;
#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
@@ -490,9 +488,6 @@ int main( int argc, char **argv ) {
lock_memory_to_ram();
get_options(uniqCfg);
EPC_MODE_ENABLED = !IS_SOFTMODEM_NOS1;
if (CONFIG_ISFLAGSET(CONFIG_ABORT) ) {
fprintf(stderr,"Getting configuration failed\n");
exit(-1);
+11 -8
View File
@@ -40,6 +40,7 @@
#include "openair1/PHY/TOOLS/phy_scope_interface.h"
#include "PHY/MODULATION/nr_modulation.h"
#include "instrumentation.h"
#include "common/utils/threadPool/notified_fifo.h"
/*
* NR SLOT PROCESSING SEQUENCE
@@ -101,8 +102,10 @@
static void *NRUE_phy_stub_standalone_pnf_task(void *arg);
static void start_process_slot_tx(void* arg) {
notifiedFIFO_elt_t *newTx = arg;
pushTpool(&(get_nrUE_params()->Tpool), newTx);
task_t task;
task.args = arg;
task.func = processSlotTX;
pushTpool(&(get_nrUE_params()->Tpool), task);
}
static size_t dump_L1_UE_meas_stats(PHY_VARS_NR_UE *ue, char *output, size_t max_len)
@@ -487,7 +490,7 @@ static void RU_write(nr_rxtx_thread_data_t *rxtxD, bool sl_tx_action)
void processSlotTX(void *arg)
{
TracyCZone(ctx, true);
nr_rxtx_thread_data_t *rxtxD = (nr_rxtx_thread_data_t *) arg;
nr_rxtx_thread_data_t *rxtxD = arg;
const UE_nr_rxtx_proc_t *proc = &rxtxD->proc;
PHY_VARS_NR_UE *UE = rxtxD->UE;
nr_phy_data_tx_t phy_data = {0};
@@ -550,6 +553,7 @@ void processSlotTX(void *arg)
int next_slot = (proc->nr_slot_tx + 1) % slots_per_frame;
dynamic_barrier_join(&UE->process_slot_tx_barriers[next_slot]);
RU_write(rxtxD, sl_tx_action);
free(rxtxD);
TracyCZoneEnd(ctx);
}
@@ -823,7 +827,7 @@ void *UE_thread(void *arg)
while (!oai_exit) {
if (syncRunning) {
notifiedFIFO_elt_t *res=tryPullTpool(&nf,&(get_nrUE_params()->Tpool));
notifiedFIFO_elt_t *res = pollNotifiedFIFO(&nf);
if (res) {
syncRunning = false;
@@ -1003,7 +1007,7 @@ void *UE_thread(void *arg)
nr_ue_rrc_timer_trigger(UE->Mod_id, curMsg.proc.frame_tx, curMsg.proc.gNB_id);
// RX slot processing. We launch and forget.
notifiedFIFO_elt_t *newRx = newNotifiedFIFO_elt(sizeof(nr_rxtx_thread_data_t), curMsg.proc.nr_slot_rx, NULL, UE_dl_processing);
notifiedFIFO_elt_t *newRx = newNotifiedFIFO_elt(sizeof(nr_rxtx_thread_data_t), curMsg.proc.nr_slot_tx, NULL, UE_dl_processing);
nr_rxtx_thread_data_t *curMsgRx = (nr_rxtx_thread_data_t *)NotifiedFifoData(newRx);
*curMsgRx = (nr_rxtx_thread_data_t){.proc = curMsg.proc, .UE = UE};
int ret = UE_dl_preprocessing(UE, &curMsgRx->proc, tx_wait_for_dlsch, &curMsgRx->phy_data, &stats_printed);
@@ -1013,8 +1017,7 @@ void *UE_thread(void *arg)
// Start TX slot processing here. It runs in parallel with RX slot processing
// in current code, DURATION_RX_TO_TX constant is the limit to get UL data to encode from a RX slot
notifiedFIFO_elt_t *newTx = newNotifiedFIFO_elt(sizeof(nr_rxtx_thread_data_t), curMsg.proc.nr_slot_tx, NULL, processSlotTX);
nr_rxtx_thread_data_t *curMsgTx = (nr_rxtx_thread_data_t *)NotifiedFifoData(newTx);
nr_rxtx_thread_data_t *curMsgTx = calloc(1, sizeof(*curMsgTx));
curMsgTx->proc = curMsg.proc;
curMsgTx->writeBlockSize = writeBlockSize;
curMsgTx->proc.timestamp_tx = writeTimestamp;
@@ -1026,7 +1029,7 @@ void *UE_thread(void *arg)
dynamic_barrier_update(&UE->process_slot_tx_barriers[slot],
tx_wait_for_dlsch[slot] + sync_to_previous_thread,
start_process_slot_tx,
newTx);
curMsgTx);
stream_status = STREAM_STATUS_SYNCED;
tx_wait_for_dlsch[slot] = 0;
}
-1
View File
@@ -33,7 +33,6 @@
#include "SCHED_NR_UE/defs.h"
#include "common/ran_context.h"
#include "common/config/config_userapi.h"
//#include "common/utils/threadPool/thread-pool.h"
#include "common/utils/load_module_shlib.h"
//#undef FRAME_LENGTH_COMPLEX_SAMPLES //there are two conflicting definitions, so we better make sure we don't use it at all
#include "common/utils/nr/nr_common.h"
+2 -1
View File
@@ -2,6 +2,7 @@
#define NR_UESOFTMODEM_H
#include <executables/nr-softmodem-common.h>
#include <executables/softmodem-common.h>
#include "common/utils/threadPool/thread-pool.h"
#include "PHY/defs_nr_UE.h"
#define CONFIG_HLP_IF_FREQ "IF frequency for RF, if needed\n"
@@ -78,7 +79,7 @@ typedef struct {
uint64_t optmask; // mask to store boolean config options
uint32_t ofdm_offset_divisor; // Divisor for sample offset computation for each OFDM symbol
int max_ldpc_iterations; // number of maximum LDPC iterations
tpool_t Tpool; // thread pool
tpool_t Tpool;
int UE_scan_carrier;
int UE_fo_compensation;
uint64_t if_freq;
-1
View File
@@ -46,7 +46,6 @@ static softmodem_params_t softmodem_params;
char *parallel_config=NULL;
char *worker_config=NULL;
int usrp_tx_thread = 0;
char *nfapi_str=NULL;
uint8_t nfapi_mode=0;
static mapping softmodem_funcs[] = MAPPING_SOFTMODEM_FUNCTIONS;
-1
View File
@@ -349,7 +349,6 @@ void configure_rru(void *, void *arg);
struct timespec timespec_add(struct timespec lhs, struct timespec rhs);
struct timespec timespec_sub(struct timespec lhs, struct timespec rhs);
extern uint8_t nfapi_mode;
extern int16_t vnf_pnf_sfnslot_delta;
#ifdef __cplusplus
}
#endif
+13 -83
View File
@@ -380,84 +380,32 @@ static int32_t aerial_pack_tx_data_request(void *pMessageBuf,
}
nfapi_nr_p7_message_header_t *pMessageHeader = pMessageBuf;
uint8_t *end = pPackedBuf + packedBufLen;
uint8_t *data_end = pDataBuf + dataBufLen;
uint8_t *pWritePackedMessage = pPackedBuf;
uint8_t *pDataPackedMessage = pDataBuf;
uint8_t *pPackMessageEnd = pPackedBuf + packedBufLen;
uint8_t *pPackedLengthField = &pWritePackedMessage[4];
uint8_t *pPacketBodyField = &pWritePackedMessage[8];
uint8_t *pPacketBodyFieldStart = &pWritePackedMessage[8];
uint8_t *pPackedDataField = &pDataPackedMessage[0];
uint8_t *pPackedDataFieldStart = &pDataPackedMessage[0];
// PHY API message header
// Number of messages [0]
// Opaque handle [1]
// PHY API Message structure
// Message type ID [2,3]
// Message Length [4,5,6,7]
// Message Body [8,...]
if (!(push8(1, &pWritePackedMessage, pPackMessageEnd) && push8(0, &pWritePackedMessage, pPackMessageEnd)
&& push16(pMessageHeader->message_id, &pWritePackedMessage, pPackMessageEnd))) {
NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 Pack header failed\n");
return -1;
}
uint8_t **ppWriteBody = &pPacketBodyField;
uint8_t **ppWriteData = &pPackedDataField;
const uint32_t dataBufLen32 = (dataBufLen + 3) / 4;
nfapi_nr_tx_data_request_t *pNfapiMsg = (nfapi_nr_tx_data_request_t *)pMessageHeader;
if (!(push16(pNfapiMsg->SFN, ppWriteBody, end) && push16(pNfapiMsg->Slot, ppWriteBody, end)
&& push16(pNfapiMsg->Number_of_PDUs, ppWriteBody, end))) {
return 0;
}
// Actual payloads are packed in a separate buffer
for (int i = 0; i < pNfapiMsg->Number_of_PDUs; i++) {
nfapi_nr_pdu_t *value = (nfapi_nr_pdu_t *)&pNfapiMsg->pdu_list[i];
// recalculate PDU_Length for Aerial (leave only the size occupied in the payload buffer afterward)
// assuming there is only 1 TLV present
value->PDU_length = value->TLVs[0].length;
if (!(push32(value->PDU_length, ppWriteBody, end) && // cuBB expects TX_DATA.request PDUSize to be 32 bit
push16(value->PDU_index, ppWriteBody, end) && push32(value->num_TLV, ppWriteBody, end))) {
return 0;
}
uint16_t k = 0;
uint16_t total_number_of_tlvs = value->num_TLV;
for (; k < total_number_of_tlvs; ++k) {
// For Aerial, the TLV tag is always 2
if (!(push16(/*value->TLVs[k].tag*/ 2, ppWriteBody, end) && push16(/*value->TLVs[k].length*/ 4, ppWriteBody, end))) {
return 0;
}
// value
if (!push32(0, ppWriteBody, end)) {
return 0;
}
}
}
// Actual payloads are packed in a separate buffer
for (int i = 0; i < pNfapiMsg->Number_of_PDUs; i++) {
nfapi_nr_pdu_t *value = (nfapi_nr_pdu_t *)&pNfapiMsg->pdu_list[i];
uint16_t k = 0;
uint16_t total_number_of_tlvs = value->num_TLV;
for (; k < total_number_of_tlvs; ++k) {
for (uint32_t k = 0; k < value->num_TLV; ++k) {
// Ensure tag is 2
value->TLVs[k].tag = 2;
uint32_t num_values_to_push = ((value->TLVs[k].length + 3) / 4);
if (value->TLVs[k].length > 0) {
if (value->TLVs[k].length % 4 != 0) {
if (!pusharray32(value->TLVs[k].value.direct,
(dataBufLen + 3) / 4,
((value->TLVs[k].length + 3) / 4) - 1,
ppWriteData,
data_end)) {
if (!pusharray32(value->TLVs[k].value.direct, dataBufLen32, num_values_to_push - 1, ppWriteData, data_end)) {
return 0;
}
int bytesToAdd = 4 - (4 - (value->TLVs[k].length % 4)) % 4;
if (bytesToAdd != 4) {
for (int j = 0; j < bytesToAdd; j++) {
uint8_t toPush = (uint8_t)(value->TLVs[k].value.direct[((value->TLVs[k].length + 3) / 4) - 1] >> (j * 8));
uint8_t toPush = (uint8_t)(value->TLVs[k].value.direct[num_values_to_push - 1] >> (j * 8));
if (!push8(toPush, ppWriteData, data_end)) {
return 0;
}
@@ -465,11 +413,7 @@ static int32_t aerial_pack_tx_data_request(void *pMessageBuf,
}
} else {
// no padding needed
if (!pusharray32(value->TLVs[k].value.direct,
(dataBufLen + 3) / 4,
((value->TLVs[k].length + 3) / 4),
ppWriteData,
data_end)) {
if (!pusharray32(value->TLVs[k].value.direct, dataBufLen32, num_values_to_push, ppWriteData, data_end)) {
return 0;
}
}
@@ -484,26 +428,12 @@ static int32_t aerial_pack_tx_data_request(void *pMessageBuf,
uintptr_t dataEnd = (uintptr_t)pPackedDataField;
data_len[0] = dataEnd - dataHead;
// check for a valid message length
uintptr_t msgHead = (uintptr_t)pPacketBodyFieldStart;
uintptr_t msgEnd = (uintptr_t)pPacketBodyField;
uint32_t packedMsgLen = msgEnd - msgHead;
uint16_t packedMsgLen16;
if (packedMsgLen > packedBufLen + dataBufLen) {
NFAPI_TRACE(NFAPI_TRACE_ERROR, "Packed message length error %d, buffer supplied %d\n", packedMsgLen, packedBufLen);
return 0;
} else {
packedMsgLen16 = (uint16_t)packedMsgLen;
}
// Update the message length in the header
pMessageHeader->message_length = packedMsgLen16;
if (!fapi_nr_p7_message_pack(pMessageBuf, pPackedBuf, packedBufLen, config)) {
return -1;
}
// Update the message length in the header
if (!push32(packedMsgLen, &pPackedLengthField, pPackMessageEnd))
return 0;
return (packedMsgLen16);
return (int32_t)(pMessageHeader->message_length);
}
+3 -7
View File
@@ -78,16 +78,12 @@ extern int nfapi_sync_var;
extern int sync_var;
nfapi_tx_request_pdu_t *tx_request_pdu[1023][10][10]; // [frame][subframe][max_num_pdus]
uint8_t nr_tx_pdus[32][16][4096];
nfapi_nr_pdu_t *tx_data_request[1023][20][10]; //[frame][slot][max_num_pdus]
uint8_t tx_pdus[32][8][4096];
nfapi_ue_release_request_body_t release_rntis;
nfapi_nr_pnf_param_response_t g_pnf_param_resp;
nfapi_pnf_p7_config_t *p7_config_g = NULL;
static nfapi_pnf_p7_config_t *p7_config_g = NULL;
void *pnf_allocate(size_t size) {
return malloc(size);
@@ -1727,8 +1723,8 @@ int pnf_nr_sim_pack_vendor_extention_tlv(void *ve, uint8_t **ppWritePackedMsg, u
return -1;
}
nfapi_dl_config_request_t dummy_dl_config_req;
nfapi_tx_request_t dummy_tx_req;
static nfapi_dl_config_request_t dummy_dl_config_req;
static nfapi_tx_request_t dummy_tx_req;
int start_request(nfapi_pnf_config_t *config, nfapi_pnf_phy_config_t *phy, nfapi_start_request_t *req) {
printf("[PNF] Received NFAPI_START_REQ phy_id:%d\n", req->header.phy_id);
+19 -5
View File
@@ -1509,7 +1509,7 @@ uint8_t unpack_ul_dci_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg
return 1;
}
static uint8_t pack_tx_data_pdu_list_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end)
static uint8_t pack_tx_data_pdu_list_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end, uint32_t *payload_offset)
{
nfapi_nr_pdu_t *value = (nfapi_nr_pdu_t *)tlv;
if (!(push32(value->PDU_length, ppWritePackedMsg, end) && push16(value->PDU_index, ppWritePackedMsg, end)
@@ -1517,8 +1517,15 @@ static uint8_t pack_tx_data_pdu_list_value(void *tlv, uint8_t **ppWritePackedMsg
return 0;
for (int i = 0; i < value->num_TLV; ++i) {
if (!(push16(value->TLVs[i].tag, ppWritePackedMsg, end) && push32(value->TLVs[i].length, ppWritePackedMsg, end)))
if (!push16(value->TLVs[i].tag, ppWritePackedMsg, end))
return 0;
#ifdef ENABLE_AERIAL
if (!push16(value->TLVs[i].length, ppWritePackedMsg, end))
return 0;
#else
if (!push32(value->TLVs[i].length, ppWritePackedMsg, end))
return 0;
#endif
const uint32_t byte_len = (value->TLVs[i].length + 3) / 4;
switch (value->TLVs[i].tag) {
case 0: {
@@ -1537,7 +1544,14 @@ static uint8_t pack_tx_data_pdu_list_value(void *tlv, uint8_t **ppWritePackedMsg
break;
}
case 2: {
// Currently Tag = 2 is only used for Aerial
if (!push32(*payload_offset, ppWritePackedMsg, end)) {
return 0;
}
*payload_offset += value->TLVs[i].length;
break;
}
default: {
NFAPI_TRACE(NFAPI_TRACE_ERROR, "FIXME : Invalid tag value %d \n", value->TLVs[i].tag);
break;
@@ -1555,9 +1569,9 @@ uint8_t pack_tx_data_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end
if (!(push16(pNfapiMsg->SFN, ppWritePackedMsg, end) && push16(pNfapiMsg->Slot, ppWritePackedMsg, end)
&& push16(pNfapiMsg->Number_of_PDUs, ppWritePackedMsg, end)))
return 0;
uint32_t payload_offset = 0;
for (int i = 0; i < pNfapiMsg->Number_of_PDUs; i++) {
if (!pack_tx_data_pdu_list_value(&pNfapiMsg->pdu_list[i], ppWritePackedMsg, end)) {
if (!pack_tx_data_pdu_list_value(&pNfapiMsg->pdu_list[i], ppWritePackedMsg, end, &payload_offset)) {
NFAPI_TRACE(NFAPI_TRACE_ERROR,
"%s():%d. Error packing TX_DATA.request PDU #%d, PDU length = %d PDU IDX = %d\n",
__FUNCTION__,
-4
View File
@@ -59,10 +59,6 @@ static uint32_t rand_range(uint32_t min, uint32_t max)
return ((rand() % (max + 1 - min)) + min);
}
extern "C" nfapi_pnf_param_response_t g_pnf_param_resp;
extern "C" {
+1 -1
View File
@@ -2068,7 +2068,7 @@ void vnf_handle_timing_info(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7)
}
}
int16_t vnf_pnf_sfnslot_delta;
static int16_t vnf_pnf_sfnslot_delta;
void vnf_nr_handle_timing_info(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7)
{
+1
View File
@@ -64,6 +64,7 @@ typedef struct {
nrLDPC_params_per_cb_t perCB[NR_LDPC_MAX_NUM_CB];
// Redundancy version index
uint8_t rv;
task_ans_t *ans;
} encoder_implemparams_t;
typedef int32_t(LDPC_initfunc_t)(void);
+257 -257
View File
@@ -24,263 +24,263 @@
#include "PHY/LTE_ESTIMATION/lte_estimation.h"
// This is 4096/(1:4096) in simde__m128i format
simde__m128i inv_ch[4096];/* = {512,512,512,512,512,512,512,512,
256,256,256,256,256,256,256,256,
170,170,170,170,170,170,170,170,
128,128,128,128,128,128,128,128,
102,102,102,102,102,102,102,102,
85,85,85,85,85,85,85,85,
73,73,73,73,73,73,73,73,
64,64,64,64,64,64,64,64,
56,56,56,56,56,56,56,56,
51,51,51,51,51,51,51,51,
46,46,46,46,46,46,46,46,
42,42,42,42,42,42,42,42,
39,39,39,39,39,39,39,39,
36,36,36,36,36,36,36,36,
34,34,34,34,34,34,34,34,
32,32,32,32,32,32,32,32,
30,30,30,30,30,30,30,30,
28,28,28,28,28,28,28,28,
26,26,26,26,26,26,26,26,
25,25,25,25,25,25,25,25,
24,24,24,24,24,24,24,24,
23,23,23,23,23,23,23,23,
22,22,22,22,22,22,22,22,
21,21,21,21,21,21,21,21,
20,20,20,20,20,20,20,20,
19,19,19,19,19,19,19,19,
18,18,18,18,18,18,18,18,
18,18,18,18,18,18,18,18,
17,17,17,17,17,17,17,17,
17,17,17,17,17,17,17,17,
16,16,16,16,16,16,16,16,
16,16,16,16,16,16,16,16,
15,15,15,15,15,15,15,15,
15,15,15,15,15,15,15,15,
14,14,14,14,14,14,14,14,
14,14,14,14,14,14,14,14,
13,13,13,13,13,13,13,13,
13,13,13,13,13,13,13,13,
13,13,13,13,13,13,13,13,
12,12,12,12,12,12,12,12,
12,12,12,12,12,12,12,12,
12,12,12,12,12,12,12,12,
11,11,11,11,11,11,11,11,
11,11,11,11,11,11,11,11,
11,11,11,11,11,11,11,11,
11,11,11,11,11,11,11,11,
10,10,10,10,10,10,10,10,
10,10,10,10,10,10,10,10,
10,10,10,10,10,10,10,10,
10,10,10,10,10,10,10,10,
10,10,10,10,10,10,10,10,
9,9,9,9,9,9,9,9,
9,9,9,9,9,9,9,9,
9,9,9,9,9,9,9,9,
9,9,9,9,9,9,9,9,
9,9,9,9,9,9,9,9,
8,8,8,8,8,8,8,8,
8,8,8,8,8,8,8,8,
8,8,8,8,8,8,8,8,
8,8,8,8,8,8,8,8,
8,8,8,8,8,8,8,8,
8,8,8,8,8,8,8,8,
8,8,8,8,8,8,8,8,
8,8,8,8,8,8,8,8,
7,7,7,7,7,7,7,7,
7,7,7,7,7,7,7,7,
7,7,7,7,7,7,7,7,
7,7,7,7,7,7,7,7,
7,7,7,7,7,7,7,7,
7,7,7,7,7,7,7,7,
7,7,7,7,7,7,7,7,
7,7,7,7,7,7,7,7,
7,7,7,7,7,7,7,7,
6,6,6,6,6,6,6,6,
6,6,6,6,6,6,6,6,
6,6,6,6,6,6,6,6,
6,6,6,6,6,6,6,6,
6,6,6,6,6,6,6,6,
6,6,6,6,6,6,6,6,
6,6,6,6,6,6,6,6,
6,6,6,6,6,6,6,6,
6,6,6,6,6,6,6,6,
6,6,6,6,6,6,6,6,
6,6,6,6,6,6,6,6,
6,6,6,6,6,6,6,6,
5,5,5,5,5,5,5,5,
5,5,5,5,5,5,5,5,
5,5,5,5,5,5,5,5,
5,5,5,5,5,5,5,5,
5,5,5,5,5,5,5,5,
5,5,5,5,5,5,5,5,
5,5,5,5,5,5,5,5,
5,5,5,5,5,5,5,5,
5,5,5,5,5,5,5,5,
5,5,5,5,5,5,5,5,
5,5,5,5,5,5,5,5,
5,5,5,5,5,5,5,5,
5,5,5,5,5,5,5,5,
5,5,5,5,5,5,5,5,
5,5,5,5,5,5,5,5,
5,5,5,5,5,5,5,5,
5,5,5,5,5,5,5,5,
4,4,4,4,4,4,4,4,
4,4,4,4,4,4,4,4,
4,4,4,4,4,4,4,4,
4,4,4,4,4,4,4,4,
4,4,4,4,4,4,4,4,
4,4,4,4,4,4,4,4,
4,4,4,4,4,4,4,4,
4,4,4,4,4,4,4,4,
4,4,4,4,4,4,4,4,
4,4,4,4,4,4,4,4,
4,4,4,4,4,4,4,4,
4,4,4,4,4,4,4,4,
4,4,4,4,4,4,4,4,
4,4,4,4,4,4,4,4,
4,4,4,4,4,4,4,4,
4,4,4,4,4,4,4,4,
4,4,4,4,4,4,4,4,
4,4,4,4,4,4,4,4,
4,4,4,4,4,4,4,4,
4,4,4,4,4,4,4,4,
4,4,4,4,4,4,4,4,
4,4,4,4,4,4,4,4,
4,4,4,4,4,4,4,4,
4,4,4,4,4,4,4,4,
4,4,4,4,4,4,4,4,
4,4,4,4,4,4,4,4,
3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
};*/
static simde__m128i inv_ch[4096]; /* = {512,512,512,512,512,512,512,512,
256,256,256,256,256,256,256,256,
170,170,170,170,170,170,170,170,
128,128,128,128,128,128,128,128,
102,102,102,102,102,102,102,102,
85,85,85,85,85,85,85,85,
73,73,73,73,73,73,73,73,
64,64,64,64,64,64,64,64,
56,56,56,56,56,56,56,56,
51,51,51,51,51,51,51,51,
46,46,46,46,46,46,46,46,
42,42,42,42,42,42,42,42,
39,39,39,39,39,39,39,39,
36,36,36,36,36,36,36,36,
34,34,34,34,34,34,34,34,
32,32,32,32,32,32,32,32,
30,30,30,30,30,30,30,30,
28,28,28,28,28,28,28,28,
26,26,26,26,26,26,26,26,
25,25,25,25,25,25,25,25,
24,24,24,24,24,24,24,24,
23,23,23,23,23,23,23,23,
22,22,22,22,22,22,22,22,
21,21,21,21,21,21,21,21,
20,20,20,20,20,20,20,20,
19,19,19,19,19,19,19,19,
18,18,18,18,18,18,18,18,
18,18,18,18,18,18,18,18,
17,17,17,17,17,17,17,17,
17,17,17,17,17,17,17,17,
16,16,16,16,16,16,16,16,
16,16,16,16,16,16,16,16,
15,15,15,15,15,15,15,15,
15,15,15,15,15,15,15,15,
14,14,14,14,14,14,14,14,
14,14,14,14,14,14,14,14,
13,13,13,13,13,13,13,13,
13,13,13,13,13,13,13,13,
13,13,13,13,13,13,13,13,
12,12,12,12,12,12,12,12,
12,12,12,12,12,12,12,12,
12,12,12,12,12,12,12,12,
11,11,11,11,11,11,11,11,
11,11,11,11,11,11,11,11,
11,11,11,11,11,11,11,11,
11,11,11,11,11,11,11,11,
10,10,10,10,10,10,10,10,
10,10,10,10,10,10,10,10,
10,10,10,10,10,10,10,10,
10,10,10,10,10,10,10,10,
10,10,10,10,10,10,10,10,
9,9,9,9,9,9,9,9,
9,9,9,9,9,9,9,9,
9,9,9,9,9,9,9,9,
9,9,9,9,9,9,9,9,
9,9,9,9,9,9,9,9,
8,8,8,8,8,8,8,8,
8,8,8,8,8,8,8,8,
8,8,8,8,8,8,8,8,
8,8,8,8,8,8,8,8,
8,8,8,8,8,8,8,8,
8,8,8,8,8,8,8,8,
8,8,8,8,8,8,8,8,
8,8,8,8,8,8,8,8,
7,7,7,7,7,7,7,7,
7,7,7,7,7,7,7,7,
7,7,7,7,7,7,7,7,
7,7,7,7,7,7,7,7,
7,7,7,7,7,7,7,7,
7,7,7,7,7,7,7,7,
7,7,7,7,7,7,7,7,
7,7,7,7,7,7,7,7,
7,7,7,7,7,7,7,7,
6,6,6,6,6,6,6,6,
6,6,6,6,6,6,6,6,
6,6,6,6,6,6,6,6,
6,6,6,6,6,6,6,6,
6,6,6,6,6,6,6,6,
6,6,6,6,6,6,6,6,
6,6,6,6,6,6,6,6,
6,6,6,6,6,6,6,6,
6,6,6,6,6,6,6,6,
6,6,6,6,6,6,6,6,
6,6,6,6,6,6,6,6,
6,6,6,6,6,6,6,6,
5,5,5,5,5,5,5,5,
5,5,5,5,5,5,5,5,
5,5,5,5,5,5,5,5,
5,5,5,5,5,5,5,5,
5,5,5,5,5,5,5,5,
5,5,5,5,5,5,5,5,
5,5,5,5,5,5,5,5,
5,5,5,5,5,5,5,5,
5,5,5,5,5,5,5,5,
5,5,5,5,5,5,5,5,
5,5,5,5,5,5,5,5,
5,5,5,5,5,5,5,5,
5,5,5,5,5,5,5,5,
5,5,5,5,5,5,5,5,
5,5,5,5,5,5,5,5,
5,5,5,5,5,5,5,5,
5,5,5,5,5,5,5,5,
4,4,4,4,4,4,4,4,
4,4,4,4,4,4,4,4,
4,4,4,4,4,4,4,4,
4,4,4,4,4,4,4,4,
4,4,4,4,4,4,4,4,
4,4,4,4,4,4,4,4,
4,4,4,4,4,4,4,4,
4,4,4,4,4,4,4,4,
4,4,4,4,4,4,4,4,
4,4,4,4,4,4,4,4,
4,4,4,4,4,4,4,4,
4,4,4,4,4,4,4,4,
4,4,4,4,4,4,4,4,
4,4,4,4,4,4,4,4,
4,4,4,4,4,4,4,4,
4,4,4,4,4,4,4,4,
4,4,4,4,4,4,4,4,
4,4,4,4,4,4,4,4,
4,4,4,4,4,4,4,4,
4,4,4,4,4,4,4,4,
4,4,4,4,4,4,4,4,
4,4,4,4,4,4,4,4,
4,4,4,4,4,4,4,4,
4,4,4,4,4,4,4,4,
4,4,4,4,4,4,4,4,
4,4,4,4,4,4,4,4,
3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3,
3,3,3,3,3,3,3,3,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,
};*/
void init_fde() {
for (int i=1;i<4096;i++) inv_ch[i] = simde_mm_set1_epi16(4096/i);
@@ -29,8 +29,7 @@
#define k1 1024
#define k2 (1024-k1)
int32_t rx_power_avg_eNB[3];
static int32_t rx_power_avg_eNB[3];
void dump_I0_stats(FILE *fd,PHY_VARS_eNB *eNB) {
+29 -38
View File
@@ -42,7 +42,6 @@
#include "common/utils/LOG/log.h"
#include "executables/lte-softmodem.h"
#include <syscall.h>
#include <common/utils/threadPool/thread-pool.h>
//#define DEBUG_DLSCH_CODING
//#define DEBUG_DLSCH_FREE 1
@@ -284,6 +283,9 @@ static void TPencode(void * arg) {
rdata->r,
hadlsch->nb_rb);
stop_meas(rdata->rm_stats);
// Task completed in parallel
completed_task_ans(rdata->ans);
}
int dlsch_encoding(PHY_VARS_eNB *eNB,
@@ -321,8 +323,6 @@ int dlsch_encoding(PHY_VARS_eNB *eNB,
num_pdcch_symbols,
frame,subframe,beamforming_mode);
int nbEncode = 0;
// if (hadlsch->Ndi == 1) { // this is a new packet
if (hadlsch->round == 0) { // this is a new packet
// Add 24-bit crc (polynomial A) to payload
@@ -349,13 +349,14 @@ int dlsch_encoding(PHY_VARS_eNB *eNB,
return(-1);
}
notifiedFIFO_t respEncode;
initNotifiedFIFO(&respEncode);
for (int r=0, r_offset=0; r<hadlsch->C; r++) {
union turboReqUnion id= {.s={dlsch->rnti,frame,subframe,r,0}};
notifiedFIFO_elt_t *req = newNotifiedFIFO_elt(sizeof(turboEncode_t), id.p, &respEncode, TPencode);
turboEncode_t * rdata=(turboEncode_t *) NotifiedFifoData(req);
turboEncode_t arr[hadlsch->C];
task_ans_t ans[hadlsch->C];
memset(ans, 0, hadlsch->C * sizeof(task_ans_t));
for (int r = 0, r_offset = 0; r < hadlsch->C; r++) {
turboEncode_t *rdata = &arr[r];
rdata->ans = &ans[r];
rdata->input=hadlsch->c[r];
rdata->Kr_bytes= ( r<hadlsch->Cminus ? hadlsch->Kminus : hadlsch->Kplus) >>3;
rdata->filler=(r==0) ? hadlsch->F : 0;
@@ -369,8 +370,8 @@ int dlsch_encoding(PHY_VARS_eNB *eNB,
rdata->r_offset=r_offset;
rdata->G=G;
pushTpool(proc->threadPool, req);
nbEncode++;
task_t t = {.func = TPencode, .args = rdata};
pushTpool(proc->threadPool, t);
int Qm=hadlsch->Qm;
int C=hadlsch->C;
@@ -382,14 +383,9 @@ int dlsch_encoding(PHY_VARS_eNB *eNB,
else
r_offset += Nl*Qm * ((GpmodC==0?0:1) + (Gp/C));
}
// Wait all other threads finish to process
while (nbEncode) {
notifiedFIFO_elt_t *res = pullTpool(&respEncode, proc->threadPool);
if (res == NULL)
break; // Tpool has been stopped
delNotifiedFIFO_elt(res);
nbEncode--;
}
join_task_ans(ans, hadlsch->C);
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_DLSCH_ENCODING, VCD_FUNCTION_OUT);
return(0);
}
@@ -454,14 +450,14 @@ int dlsch_encoding_fembms_pmch(PHY_VARS_eNB *eNB,
&hadlsch->F)<0)
return(-1);
}
int nbEncode = 0;
notifiedFIFO_t respEncode;
initNotifiedFIFO(&respEncode);
for (int r=0, r_offset=0; r<hadlsch->C; r++) {
union turboReqUnion id= {.s={dlsch->rnti,frame,subframe,r,0}};
notifiedFIFO_elt_t *req = newNotifiedFIFO_elt(sizeof(turboEncode_t), id.p, &respEncode, TPencode);
turboEncode_t * rdata=(turboEncode_t *) NotifiedFifoData(req);
turboEncode_t arr[hadlsch->C];
task_ans_t ans[hadlsch->C];
memset(ans, 0, hadlsch->C * sizeof(task_ans_t));
for (int r = 0, r_offset = 0; r < hadlsch->C; r++) {
turboEncode_t *rdata = &arr[r];
rdata->ans = &ans[r];
rdata->input=hadlsch->c[r];
rdata->Kr_bytes= ( r<hadlsch->Cminus ? hadlsch->Kminus : hadlsch->Kplus) >>3;
rdata->filler=(r==0) ? hadlsch->F : 0;
@@ -475,8 +471,8 @@ int dlsch_encoding_fembms_pmch(PHY_VARS_eNB *eNB,
rdata->r_offset=r_offset;
rdata->G=G;
pushTpool(proc->threadPool, req);
nbEncode++;
task_t t = {.func = TPencode, .args = rdata};
pushTpool(proc->threadPool, t);
int Qm=hadlsch->Qm;
int C=hadlsch->C;
@@ -488,14 +484,9 @@ int dlsch_encoding_fembms_pmch(PHY_VARS_eNB *eNB,
else
r_offset += Nl*Qm * ((GpmodC==0?0:1) + (Gp/C));
}
// Wait all other threads finish to process
while (nbEncode) {
notifiedFIFO_elt_t *res = pullTpool(&respEncode, proc->threadPool);
if (res == NULL)
break; // Tpool has been stopped
delNotifiedFIFO_elt(res);
nbEncode--;
}
join_task_ans(ans, hadlsch->C);
return(0);
}
+12 -14
View File
@@ -3025,22 +3025,20 @@ inline int check_skip_dc(int rb,LTE_DL_FRAME_PARMS *frame_parms) {
return(0);
}
static uint64_t qam4_tm2_p2_0[8][16] __attribute__((aligned(32)));
static uint64_t qam4_tm2_p2_1[8][16] __attribute__((aligned(32)));
static uint64_t qam4_tm2_p2_b0[8][4][16] __attribute__((aligned(32)));
static uint64_t qam4_tm2_p2_b1[8][4][16] __attribute__((aligned(32)));
uint64_t qam4_tm2_p2_0[8][16] __attribute__ ((aligned(32)));
uint64_t qam4_tm2_p2_1[8][16] __attribute__ ((aligned(32)));
uint64_t qam4_tm2_p2_b0[8][4][16] __attribute__ ((aligned(32)));
uint64_t qam4_tm2_p2_b1[8][4][16] __attribute__ ((aligned(32)));
uint64_t qam16_tm2_p2_0[8][256] __attribute__ ((aligned(32)));
uint64_t qam16_tm2_p2_1[8][256] __attribute__ ((aligned(32)));
uint64_t qam16_tm2_p2_b0[8][4][256] __attribute__ ((aligned(32)));
uint64_t qam16_tm2_p2_b1[8][4][256] __attribute__ ((aligned(32)));
uint64_t qam64_tm2_p2_0[8][4096] __attribute__ ((aligned(32)));
uint64_t qam64_tm2_p2_1[8][4096] __attribute__ ((aligned(32)));
uint64_t qam64_tm2_p2_b0[8][4][4096] __attribute__ ((aligned(32)));
uint64_t qam64_tm2_p2_b1[8][4][4096] __attribute__ ((aligned(32)));
static uint64_t qam16_tm2_p2_0[8][256] __attribute__((aligned(32)));
static uint64_t qam16_tm2_p2_1[8][256] __attribute__((aligned(32)));
static uint64_t qam16_tm2_p2_b0[8][4][256] __attribute__((aligned(32)));
static uint64_t qam16_tm2_p2_b1[8][4][256] __attribute__((aligned(32)));
static uint64_t qam64_tm2_p2_0[8][4096] __attribute__((aligned(32)));
static uint64_t qam64_tm2_p2_1[8][4096] __attribute__((aligned(32)));
static uint64_t qam64_tm2_p2_b0[8][4][4096] __attribute__((aligned(32)));
static uint64_t qam64_tm2_p2_b1[8][4][4096] __attribute__((aligned(32)));
void init_modulation_LUT_qam4_tm2_p2() {
+1 -2
View File
@@ -235,8 +235,7 @@ void init_mpdcch2ss1tab_normal_regular_subframe_evenNRBDL(PHY_VARS_eNB *eNB) {
extern uint8_t *generate_dci0(uint8_t *dci, uint8_t *e, uint8_t DCI_LENGTH, uint16_t coded_bits, uint16_t rnti);
uint16_t mpdcch_dmrs_tab[12 * 6];
static uint16_t mpdcch_dmrs_tab[12 * 6];
void init_mpdcch_dmrs_tab(uint16_t oss) {
int re = 5 * oss;
+1 -1
View File
@@ -41,7 +41,7 @@ const uint16_t NCS_restricted[15] = {15, 18, 22, 26, 32, 38, 46, 55, 68, 82, 100
const uint16_t NCS_4[7] = {2, 4, 6, 8, 10, 12, 15};
int16_t ru[2*839]; // quantized roots of unity
uint32_t ZC_inv[839]; // multiplicative inverse for roots u
static uint32_t ZC_inv[839]; // multiplicative inverse for roots u
uint16_t du[838];
extern PRACH_TDD_PREAMBLE_MAP tdd_preamble_map[64][7];
+1 -2
View File
@@ -44,8 +44,7 @@ extern const uint16_t NCS_unrestricted[16];
extern const uint16_t NCS_restricted[15];
extern const uint16_t NCS_4[7];
extern int16_t ru[2*839]; // quantized roots of unity
extern uint32_t ZC_inv[839]; // multiplicative inverse for roots u
extern int16_t ru[2 * 839]; // quantized roots of unity
extern uint16_t du[838];
+8 -6
View File
@@ -36,6 +36,7 @@
#include "nfapi_interface.h"
#include "transport_common_proto.h"
// Functions below implement 36-211 and 36-212
/** @addtogroup _PHY_TRANSPORT_
@@ -520,12 +521,13 @@ void rx_ulsch(PHY_VARS_eNB *eNB,
@param llr8_flag If 1, indicate that the 8-bit turbo decoder should be used
@returns 0 on success
*/
unsigned int ulsch_decoding(PHY_VARS_eNB *phy_vars_eNB,
L1_rxtx_proc_t *proc,
uint8_t UE_id,
uint8_t control_only_flag,
uint8_t Nbundled,
uint8_t llr8_flag);
unsigned int ulsch_decoding(PHY_VARS_eNB *phy_vars_eNB,
L1_rxtx_proc_t *proc,
uint8_t UE_id,
uint8_t control_only_flag,
uint8_t Nbundled,
uint8_t llr8_flag,
thread_info_tm_t *t_info);
void generate_phich_top(PHY_VARS_eNB *phy_vars_eNB,
L1_rxtx_proc_t *proc,
+30 -18
View File
@@ -239,8 +239,10 @@ void processULSegment(void * arg) {
1,
r,
&E)==-1) {
LOG_E(PHY,"ulsch_decoding.c: Problem in rate matching\n");
return;
// Task completed in parallel
completed_task_ans(rdata->ans);
LOG_E(PHY, "ulsch_decoding.c: Problem in rate matching\n");
return;
}
stop_meas(&eNB->ulsch_rate_unmatching_stats);
int max_Ncb = 3*ulsch_harq->RTC[r]*32 ;
@@ -284,6 +286,9 @@ void processULSegment(void * arg) {
&eNB->ulsch_tc_intl1_stats,
&eNB->ulsch_tc_intl2_stats,
&ulsch_harq->abort_decode);
// Task completed in parallel
completed_task_ans(rdata->ans);
}
/*!
@@ -295,7 +300,12 @@ void processULSegment(void * arg) {
@returns 0 on success
*/
static int ulsch_decoding_data(PHY_VARS_eNB *eNB, L1_rxtx_proc_t *proc, int UE_id, int harq_pid, int llr8_flag)
static int ulsch_decoding_data(PHY_VARS_eNB *eNB,
L1_rxtx_proc_t *proc,
int UE_id,
int harq_pid,
int llr8_flag,
thread_info_tm_t *t_info)
{
unsigned int r_offset=0;
int offset = 0;
@@ -330,13 +340,11 @@ static int ulsch_decoding_data(PHY_VARS_eNB *eNB, L1_rxtx_proc_t *proc, int UE_i
E = ulsch_harq->Qm * (Gp/ulsch_harq->C);
else
E = ulsch_harq->Qm * ((GpmodC==0?0:1) + (Gp/ulsch_harq->C));
union turboReqUnion id= {.s={ulsch->rnti,proc->frame_rx,proc->subframe_rx,0,0}};
notifiedFIFO_elt_t *req=newNotifiedFIFO_elt(sizeof(turboDecode_t),
id.p,
proc->respDecode,
processULSegment);
turboDecode_t * rdata=(turboDecode_t *) NotifiedFifoData(req);
turboDecode_t *rdata = &((turboDecode_t *)t_info->buf)[t_info->len];
DevAssert(t_info->len < t_info->cap);
rdata->ans = &t_info->ans[t_info->len];
t_info->len += 1;
rdata->eNB=eNB;
rdata->frame=proc->frame_rx;
@@ -355,7 +363,10 @@ static int ulsch_decoding_data(PHY_VARS_eNB *eNB, L1_rxtx_proc_t *proc, int UE_i
rdata->function=td;
int Fbytes=(r==0) ? rdata->Fbits>>3 : 0;
int sz=Kr_bytes - Fbytes - ((ulsch_harq->C>1)?3:0);
pushTpool(proc->threadPool,req);
task_t t = {.func = &processULSegment, .args = rdata};
pushTpool(proc->threadPool, t);
proc->nbDecode++;
LOG_D(PHY,"Added a block to decode, in pipe: %d\n",proc->nbDecode);
r_offset+=E;
@@ -390,12 +401,13 @@ static inline unsigned int lte_gold_unscram(unsigned int *x1, unsigned int *x2,
// printf("n=%d : c %x\n",n,x1^x2);
}
unsigned int ulsch_decoding(PHY_VARS_eNB *eNB,
L1_rxtx_proc_t *proc,
uint8_t UE_id,
uint8_t control_only_flag,
uint8_t Nbundled,
uint8_t llr8_flag)
unsigned int ulsch_decoding(PHY_VARS_eNB *eNB,
L1_rxtx_proc_t *proc,
uint8_t UE_id,
uint8_t control_only_flag,
uint8_t Nbundled,
uint8_t llr8_flag,
thread_info_tm_t *t_info)
{
int16_t *ulsch_llr = eNB->pusch_vars[UE_id]->llr;
LTE_DL_FRAME_PARMS *frame_parms = &eNB->frame_parms;
@@ -1082,7 +1094,7 @@ unsigned int ulsch_decoding(PHY_VARS_eNB *eNB,
LOG_D(PHY,"frame %d subframe %d O_ACK:%d o_ACK[]=%d:%d:%d:%d\n",frame,subframe,ulsch_harq->O_ACK,ulsch_harq->o_ACK[0],ulsch_harq->o_ACK[1],ulsch_harq->o_ACK[2],ulsch_harq->o_ACK[3]);
// Do ULSCH Decoding for data portion
ret = ulsch_decoding_data(eNB, proc, UE_id, harq_pid, llr8_flag);
ret = ulsch_decoding_data(eNB, proc, UE_id, harq_pid, llr8_flag, t_info);
return(ret);
}
@@ -560,7 +560,7 @@ void ulsch_channel_level(int32_t **drs_ch_estimates_ext,
simde_m_empty();
}
int ulsch_power_LUT[750];
static int ulsch_power_LUT[750];
void init_ulsch_power_LUT(void) {
int i;
+2 -13
View File
@@ -35,22 +35,11 @@
#include "LAYER2/MAC/mac.h"
#include "common/utils/LOG/vcd_signal_dumper.h"
#include "transport_proto_ue.h"
#include "openair1/PHY/LTE_TRANSPORT/dci_tools_common_extern.h"
#include "PHY/LTE_TRANSPORT/transport_vars.h"
#include "assertions.h"
extern uint16_t RIV2nb_rb_LUT6[32];
extern uint16_t RIV2first_rb_LUT6[32];
extern uint16_t RIV2nb_rb_LUT25[512];
extern uint16_t RIV2first_rb_LUT25[512];
extern uint16_t RIV2nb_rb_LUT50[1600];
extern uint16_t RIV2first_rb_LUT50[1600];
extern uint16_t RIV2nb_rb_LUT100[6000];
extern uint16_t RIV2first_rb_LUT100[600];
extern uint16_t RIV_max6,RIV_max25,RIV_max50,RIV_max100;
int8_t delta_PUSCH_msg2[8] = {-6,-4,-2,0,2,4,6,8};
static int8_t delta_PUSCH_msg2[8] = {-6, -4, -2, 0, 2, 4, 6, 8};
int generate_ue_ulsch_params_from_rar(PHY_VARS_UE *ue,
UE_rxtx_proc_t *proc,
@@ -409,6 +409,7 @@ static void nr_pusch_antenna_processing(void *arg)
*(rdata->noise_amp2) = noise_amp2;
*(rdata->nest_count) = nest_count;
}
completed_task_ans(rdata->ans);
}
@@ -503,14 +504,13 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB,
start_meas(&gNB->pusch_channel_estimation_antenna_processing_stats);
int numAntennas = gNB->dmrs_num_antennas_per_thread;
int num_jobs = CEILIDIV(gNB->frame_parms.nb_antennas_rx, numAntennas);
puschAntennaProc_t rdatas[num_jobs];
memset(rdatas, 0, sizeof(rdatas));
task_ans_t ans[num_jobs];
memset(ans, 0, sizeof(ans));
for (int job_id = 0; job_id < num_jobs; job_id++) {
union puschAntennaReqUnion id = {.s = {ul_id, 0}};
id.p = 1 + job_id * numAntennas;
notifiedFIFO_elt_t *req = newNotifiedFIFO_elt(sizeof(puschAntennaProc_t),
id.p,
&respPuschAarx,
&nr_pusch_antenna_processing); // create a job for Tpool
puschAntennaProc_t *rdata = (puschAntennaProc_t *)NotifiedFifoData(req); // data for the job
puschAntennaProc_t *rdata = &rdatas[job_id];
task_t task = {.func = nr_pusch_antenna_processing, .args = rdata};
// Local init in the current loop
rdata->Ns = Ns;
@@ -531,22 +531,18 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB,
rdata->pusch_vars = &gNB->pusch_vars[ul_id];
rdata->chest_freq = gNB->chest_freq;
rdata->rxdataF = gNB->common_vars.rxdataF;
rdata->ans = &ans[job_id];
// Call the nr_pusch_antenna_processing function
if (job_id == num_jobs - 1) {
// Run the last job inline
nr_pusch_antenna_processing(rdata);
delNotifiedFIFO_elt(req);
} else {
pushTpool(&gNB->threadPool, req);
pushTpool(&gNB->threadPool, task);
}
LOG_D(PHY, "Added Antenna (count %d/%d) to process, in pipe\n", job_id, num_jobs);
} // Antenna Loop
while (num_jobs - 1 > 0) {
notifiedFIFO_elt_t *req = pullTpool(&respPuschAarx, &gNB->threadPool);
num_jobs--;
delNotifiedFIFO_elt(req);
}
join_task_ans(ans, num_jobs - 1);
stop_meas(&gNB->pusch_channel_estimation_antenna_processing_stats);
for (int aarx = 0; aarx < gNB->frame_parms.nb_antennas_rx; aarx++) {
+18 -16
View File
@@ -117,7 +117,7 @@ NR_gNB_DLSCH_t new_gNB_dlsch(NR_DL_FRAME_PARMS *frame_parms, uint16_t N_RB)
return(dlsch);
}
void ldpc8blocks(void *p)
static void ldpc8blocks(void *p)
{
encoder_implemparams_t *impp=(encoder_implemparams_t *) p;
NR_DL_gNB_HARQ_t *harq = (NR_DL_gNB_HARQ_t *)impp->harq;
@@ -232,6 +232,9 @@ void ldpc8blocks(void *p)
#endif
r_offset += E;
}
// Task running in // completed
completed_task_ans(impp->ans);
}
int nr_dlsch_encoding(PHY_VARS_gNB *gNB,
@@ -369,24 +372,23 @@ int nr_dlsch_encoding(PHY_VARS_gNB *gNB,
}
ldpc_interface_offload.LDPCencoder(harq->c, &impp.output, &impp);
} else {
notifiedFIFO_t nf;
initNotifiedFIFO(&nf);
int nbJobs = 0;
for (int j = 0; j < (impp.n_segments / 8 + ((impp.n_segments & 7) == 0 ? 0 : 1)); j++) {
notifiedFIFO_elt_t *req = newNotifiedFIFO_elt(sizeof(impp), j, &nf, ldpc8blocks);
encoder_implemparams_t *perJobImpp = (encoder_implemparams_t *)NotifiedFifoData(req);
size_t const n_seg = (impp.n_segments / 8 + ((impp.n_segments & 7) == 0 ? 0 : 1));
encoder_implemparams_t arr[n_seg];
task_ans_t ans[n_seg];
memset(ans, 0, n_seg * sizeof(task_ans_t));
for (int j = 0; j < n_seg; j++) {
encoder_implemparams_t *perJobImpp = &arr[j];
*perJobImpp = impp;
perJobImpp->macro_num = j;
pushTpool(&gNB->threadPool, req);
nbJobs++;
}
while (nbJobs) {
notifiedFIFO_elt_t *req = pullTpool(&nf, &gNB->threadPool);
if (req == NULL)
break; // Tpool has been stopped
delNotifiedFIFO_elt(req);
nbJobs--;
perJobImpp->ans = &ans[j];
task_t t = {.func = ldpc8blocks, .args = perJobImpp};
pushTpool(&gNB->threadPool, t);
}
join_task_ans(ans, n_seg);
}
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_gNB_DLSCH_ENCODING, VCD_FUNCTION_OUT);
return 0;
+2 -1
View File
@@ -62,7 +62,8 @@ int nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB,
uint32_t frame,
uint8_t nr_tti_rx,
uint8_t harq_pid,
uint32_t G);
uint32_t G,
thread_info_tm_t *t_info);
/*! \brief Perform PUSCH unscrambling. TS 38.211 V15.4.0 subclause 6.3.1.1
@param llr, Pointer to llr bits
+22 -5
View File
@@ -50,6 +50,10 @@
//#define DEBUG_ULSCH_DECODING
//#define gNB_DEBUG_TRACE
#include <stdint.h>
#include <time.h>
#include <stdalign.h>
#define OAI_UL_LDPC_MAX_NUM_LLR 27000//26112 // NR_LDPC_NCOL_BG1*NR_LDPC_ZMAX = 68*384
//#define DEBUG_CRC
#ifdef DEBUG_CRC
@@ -181,6 +185,9 @@ static void nr_processULSegment(void *arg)
LOG_E(PHY, "ulsch_decoding.c: Problem in rate_matching\n");
rdata->decodeIterations = max_ldpc_iterations + 1;
set_abort(&ulsch_harq->abort_decode, true);
// Task completed
completed_task_ans(rdata->ans);
return;
}
@@ -220,6 +227,9 @@ static void nr_processULSegment(void *arg)
if (rdata->decodeIterations <= p_decoderParms->numMaxIter)
memcpy(ulsch_harq->c[r],llrProcBuf, Kr>>3);
// Task completed
completed_task_ans(rdata->ans);
}
int decode_offload(PHY_VARS_gNB *phy_vars_gNB,
@@ -320,7 +330,8 @@ int nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB,
uint32_t frame,
uint8_t nr_tti_rx,
uint8_t harq_pid,
uint32_t G)
uint32_t G,
thread_info_tm_t *t_info)
{
if (!ulsch_llr) {
LOG_E(PHY, "ulsch_decoding.c: NULL ulsch_llr pointer\n");
@@ -430,9 +441,12 @@ int nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB,
set_abort(&harq_process->abort_decode, false);
for (int r = 0; r < harq_process->C; r++) {
int E = nr_get_E(G, harq_process->C, Qm, n_layers, r);
union ldpcReqUnion id = {.s = {ulsch->rnti, frame, nr_tti_rx, 0, 0}};
notifiedFIFO_elt_t *req = newNotifiedFIFO_elt(sizeof(ldpcDecode_t), id.p, &phy_vars_gNB->respDecode, &nr_processULSegment);
ldpcDecode_t *rdata = (ldpcDecode_t *)NotifiedFifoData(req);
ldpcDecode_t *rdata = &((ldpcDecode_t *)t_info->buf)[t_info->len];
DevAssert(t_info->len < t_info->cap);
rdata->ans = &t_info->ans[t_info->len];
t_info->len += 1;
decParams.R = nr_get_R_ldpc_decoder(pusch_pdu->pusch_data.rv_index,
E,
decParams.BG,
@@ -457,7 +471,10 @@ int nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB,
rdata->ulsch = ulsch;
rdata->ulsch_id = ULSCH_id;
rdata->tbslbrm = pusch_pdu->maintenance_parms_v3.tbSizeLbrmBytes;
pushTpool(&phy_vars_gNB->threadPool, req);
task_t t = {.func = &nr_processULSegment, .args = rdata};
pushTpool(&phy_vars_gNB->threadPool, t);
LOG_D(PHY, "Added a block to decode, in pipe: %d\n", r);
r_offset += E;
offset += ((harq_process->K >> 3) - (harq_process->F >> 3) - ((harq_process->C > 1) ? 3 : 0));
@@ -1179,6 +1179,7 @@ typedef struct puschSymbolProc_s {
int16_t *scramblingSequence;
uint32_t nvar;
int beam_nb;
task_ans_t *ans;
} puschSymbolProc_t;
static void nr_pusch_symbol_processing(void *arg)
@@ -1227,6 +1228,9 @@ static void nr_pusch_symbol_processing(void *arg)
for (int i = 0; i < end; i++)
llr16[i] = llr_ptr[i] * s[i];
}
// Task running in // completed
completed_task_ans(rdata->ans);
}
static uint32_t average_u32(const uint32_t *x, uint16_t size)
@@ -1483,8 +1487,13 @@ int nr_rx_pusch_tp(PHY_VARS_gNB *gNB,
start_meas(&gNB->rx_pusch_symbol_processing_stats);
int numSymbols = gNB->num_pusch_symbols_per_thread;
int total_res = 0;
int const loop_iter = rel15_ul->nr_of_symbols / numSymbols;
puschSymbolProc_t arr[loop_iter];
task_ans_t arr_ans[loop_iter];
memset(arr_ans, 0, loop_iter * sizeof(task_ans_t));
int sz_arr = 0;
for(uint8_t symbol = rel15_ul->start_symbol_index; symbol < end_symbol; symbol += numSymbols) {
int res_per_task = 0;
for (int s = 0; s < numSymbols; s++) {
@@ -1496,10 +1505,9 @@ int nr_rx_pusch_tp(PHY_VARS_gNB *gNB,
}
total_res += res_per_task;
if (res_per_task > 0) {
union puschSymbolReqUnion id = {.s={ulsch_id,frame,slot,0}};
id.p=1+symbol;
notifiedFIFO_elt_t *req = newNotifiedFIFO_elt(sizeof(puschSymbolProc_t), id.p, &gNB->respPuschSymb, &nr_pusch_symbol_processing); // create a job for Tpool
puschSymbolProc_t *rdata = (puschSymbolProc_t*)NotifiedFifoData(req); // data for the job
puschSymbolProc_t *rdata = &arr[sz_arr];
rdata->ans = &arr_ans[sz_arr];
++sz_arr;
rdata->gNB = gNB;
rdata->frame_parms = frame_parms;
@@ -1517,7 +1525,8 @@ int nr_rx_pusch_tp(PHY_VARS_gNB *gNB,
if (rel15_ul->pdu_bit_map & PUSCH_PDU_BITMAP_PUSCH_PTRS) {
nr_pusch_symbol_processing(rdata);
} else {
pushTpool(&gNB->threadPool, req);
task_t t = {.func = &nr_pusch_symbol_processing, .args = rdata};
pushTpool(&gNB->threadPool, t);
nbSymb++;
}
@@ -1525,12 +1534,9 @@ int nr_rx_pusch_tp(PHY_VARS_gNB *gNB,
}
} // symbol loop
while (nbSymb) {
notifiedFIFO_elt_t *req = pullTpool(&gNB->respPuschSymb, &gNB->threadPool);
nbSymb--;
delNotifiedFIFO_elt(req);
if (nbSymb > 0) {
join_task_ans(arr_ans, sz_arr);
}
stop_meas(&gNB->rx_pusch_symbol_processing_stats);
// Copy the data to the scope. This cannot be performed in one call to gNBscopeCopy because the data is not contiguous in the
+2 -2
View File
@@ -873,8 +873,8 @@ static simde__m256i pucch2_11bit[2048 * 2];
static simde__m256i *pucch2_lut[9] =
{pucch2_3bit, pucch2_4bit, pucch2_5bit, pucch2_6bit, pucch2_7bit, pucch2_8bit, pucch2_9bit, pucch2_10bit, pucch2_11bit};
simde__m64 pucch2_polar_4bit[16];
simde__m128i pucch2_polar_llr_num_lut[256],pucch2_polar_llr_den_lut[256];
static simde__m64 pucch2_polar_4bit[16];
static simde__m128i pucch2_polar_llr_num_lut[256], pucch2_polar_llr_den_lut[256];
void init_pucch2_luts() {
@@ -70,15 +70,13 @@ void nr_dlsch_unscrambling(int16_t *llr, uint32_t size, uint8_t q, uint32_t Nid,
}
static bool nr_ue_postDecode(PHY_VARS_NR_UE *phy_vars_ue,
notifiedFIFO_elt_t *req,
notifiedFIFO_t *nf_p,
const bool last,
ldpcDecode_ue_t *rdata,
bool last,
int b_size,
uint8_t b[b_size],
int *num_seg_ok,
const UE_nr_rxtx_proc_t *proc)
{
ldpcDecode_ue_t *rdata = (ldpcDecode_ue_t*) NotifiedFifoData(req);
NR_DL_UE_HARQ_t *harq_process = rdata->harq_process;
NR_UE_DLSCH_t *dlsch = (NR_UE_DLSCH_t *) rdata->dlsch;
int r = rdata->segment_r;
@@ -257,6 +255,7 @@ static void nr_processDLSegment(void *arg)
memcpy(harq_process->c[r], LDPCoutput, Kr >> 3);
stop_meas(&rdata->ts_ldpc_decode);
}
completed_task_ans(rdata->ans);
}
uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue,
@@ -369,16 +368,17 @@ uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue,
Kr = harq_process->K;
Kr_bytes = Kr>>3;
offset = 0;
notifiedFIFO_t nf;
initNotifiedFIFO(&nf);
ldpcDecode_ue_t arr[harq_process->C];
task_ans_t ans[harq_process->C];
memset(ans, 0, harq_process->C * sizeof(task_ans_t));
set_abort(&harq_process->abort_decode, false);
for (r=0; r<harq_process->C; r++) {
//printf("start rx segment %d\n",r);
uint32_t E = nr_get_E(G, harq_process->C, dlsch->dlsch_config.qamModOrder, dlsch->Nl, r);
decParams.R = nr_get_R_ldpc_decoder(dlsch->dlsch_config.rv, E, decParams.BG, decParams.Z, &harq_process->llrLen, harq_process->DLround);
union ldpcReqUnion id = {.s = {dlsch->rnti, frame, nr_slot_rx, 0, 0}};
notifiedFIFO_elt_t *req = newNotifiedFIFO_elt(sizeof(ldpcDecode_ue_t), id.p, &nf, &nr_processDLSegment);
ldpcDecode_ue_t * rdata=(ldpcDecode_ue_t *) NotifiedFifoData(req);
ldpcDecode_ue_t *rdata = &arr[r];
rdata->ans = &ans[r];
rdata->phy_vars_ue = phy_vars_ue;
rdata->harq_process = harq_process;
@@ -398,7 +398,8 @@ uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue,
reset_meas(&rdata->ts_deinterleave);
reset_meas(&rdata->ts_rate_unmatch);
reset_meas(&rdata->ts_ldpc_decode);
pushTpool(&get_nrUE_params()->Tpool,req);
task_t t = {.args = rdata, .func = nr_processDLSegment};
pushTpool(&get_nrUE_params()->Tpool, t);
LOG_D(PHY, "Added a block to decode, in pipe: %d\n", r);
r_offset += E;
offset += (Kr_bytes - (harq_process->F>>3) - ((harq_process->C>1)?3:0));
@@ -406,13 +407,11 @@ uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue,
}
int num_seg_ok = 0;
int nbDecode = harq_process->C;
while (nbDecode) {
notifiedFIFO_elt_t *req=pullTpool(&nf, &get_nrUE_params()->Tpool);
if (req == NULL)
break; // Tpool has been stopped
nr_ue_postDecode(phy_vars_ue, req, &nf, nbDecode == 1, b_size, b, &num_seg_ok, proc);
delNotifiedFIFO_elt(req);
nbDecode--;
if (nbDecode > 0) {
join_task_ans(ans, nbDecode);
for (size_t i = 0; i < nbDecode; ++i) {
nr_ue_postDecode(phy_vars_ue, &arr[i], i == nbDecode - 1, b_size, b, &num_seg_ok, proc);
}
}
LOG_D(PHY,
"%d.%d DLSCH Decoded, harq_pid %d, round %d, result: %d TBS %d (%d) G %d nb_re_dmrs %d length dmrs %d mcs %d Nl %d "
+29 -25
View File
@@ -288,6 +288,8 @@ void nr_scan_ssb(void *arg)
}
}
}
completed_task_ans(ssbInfo->ans);
}
nr_initial_sync_t nr_initial_sync(UE_nr_rxtx_proc_t *proc,
@@ -299,18 +301,18 @@ nr_initial_sync_t nr_initial_sync(UE_nr_rxtx_proc_t *proc,
{
NR_DL_FRAME_PARMS *fp = &ue->frame_parms;
notifiedFIFO_t nf;
initNotifiedFIFO(&nf);
// Perform SSB scanning in parallel. One GSCN per thread.
LOG_I(NR_PHY,
"Starting cell search with center freq: %ld, bandwidth: %d. Scanning for %d number of GSCN.\n",
fp->dl_CarrierFreq,
fp->N_RB_DL,
numGscn);
task_ans_t ans[numGscn];
memset(ans, 0, sizeof(ans));
nr_ue_ssb_scan_t ssb_info[numGscn];
for (int s = 0; s < numGscn; s++) {
notifiedFIFO_elt_t *req = newNotifiedFIFO_elt(sizeof(nr_ue_ssb_scan_t), gscnInfo[s].gscn, &nf, &nr_scan_ssb);
nr_ue_ssb_scan_t *ssbInfo = (nr_ue_ssb_scan_t *)NotifiedFifoData(req);
nr_ue_ssb_scan_t *ssbInfo = &ssb_info[s];
*ssbInfo = (nr_ue_ssb_scan_t){.gscnInfo = gscnInfo[s],
.fp = &ue->frame_parms,
.proc = proc,
@@ -329,32 +331,34 @@ nr_initial_sync_t nr_initial_sync(UE_nr_rxtx_proc_t *proc,
ssbInfo->gscnInfo.gscn,
ssbInfo->gscnInfo.ssbFirstSC,
ssbInfo->gscnInfo.ssRef);
pushTpool(&get_nrUE_params()->Tpool, req);
ssbInfo->ans = &ans[s];
task_t t = {.func = nr_scan_ssb, .args = ssbInfo};
pushTpool(&get_nrUE_params()->Tpool, t);
}
// Collect the scan results
nr_ue_ssb_scan_t res = {0};
while (numGscn) {
notifiedFIFO_elt_t *req = pullTpool(&nf, &get_nrUE_params()->Tpool);
nr_ue_ssb_scan_t *ssbInfo = (nr_ue_ssb_scan_t *)NotifiedFifoData(req);
if (ssbInfo->syncRes.cell_detected) {
LOG_A(NR_PHY,
"Cell Detected with GSCN: %d, SSB SC offset: %d, SSB Ref: %lf, PSS Corr peak: %d dB, PSS Corr Average: %d\n",
ssbInfo->gscnInfo.gscn,
ssbInfo->gscnInfo.ssbFirstSC,
ssbInfo->gscnInfo.ssRef,
ssbInfo->pssCorrPeakPower,
ssbInfo->pssCorrAvgPower);
if (!res.syncRes.cell_detected) { // take the first cell detected
res = *ssbInfo;
if (numGscn > 0) {
join_task_ans(ans, numGscn);
for (int i = 0; i < numGscn; i++) {
nr_ue_ssb_scan_t *ssbInfo = &ssb_info[i];
if (ssbInfo->syncRes.cell_detected) {
LOG_I(NR_PHY,
"Cell Detected with GSCN: %d, SSB SC offset: %d, SSB Ref: %lf, PSS Corr peak: %d dB, PSS Corr Average: %d\n",
ssbInfo->gscnInfo.gscn,
ssbInfo->gscnInfo.ssbFirstSC,
ssbInfo->gscnInfo.ssRef,
ssbInfo->pssCorrPeakPower,
ssbInfo->pssCorrAvgPower);
if (!res.syncRes.cell_detected) { // take the first cell detected
res = *ssbInfo;
}
}
for (int ant = 0; ant < fp->nb_antennas_rx; ant++) {
free(ssbInfo->rxdata[ant]);
}
free(ssbInfo->rxdata);
}
for (int ant = 0; ant < fp->nb_antennas_rx; ant++) {
free(ssbInfo->rxdata[ant]);
}
free(ssbInfo->rxdata);
delNotifiedFIFO_elt(req);
numGscn--;
}
// Set globals based on detected cell
+2 -2
View File
@@ -47,10 +47,10 @@ if(ENABLE_UESCOPE OR ENABLE_ENBSCOPE OR ENABLE_NRSCOPE)
target_link_libraries(xforms_common PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs)
add_library(enbscope MODULE lte_enb_scope.c $<TARGET_OBJECTS:xforms_common>)
target_link_libraries(enbscope PUBLIC forms PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs)
target_link_libraries(enbscope PUBLIC forms PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs UTIL)
add_library(uescope MODULE lte_ue_scope.c $<TARGET_OBJECTS:xforms_common>)
target_link_libraries(uescope PUBLIC forms PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs)
target_link_libraries(uescope PUBLIC forms PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs UTIL)
add_library(nrscope MODULE nr_phy_scope.c)
target_link_libraries(nrscope PUBLIC forms PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs UTIL)
+6 -3
View File
@@ -39,8 +39,9 @@
#include "time_meas.h"
#include "defs_common.h"
#include "nfapi_nr_interface_scf.h"
#include <common/utils/threadPool/thread-pool.h>
#include <executables/rt_profiling.h>
#include "common/utils/threadPool/task_ans.h"
#include "common/utils/threadPool/thread-pool.h"
#define MAX_BANDS_PER_RRU 4
#define MAX_RRU_CONFIG_SIZE 1024
@@ -175,7 +176,8 @@ typedef struct {
struct RU_t_s *ru;
int startSymbol;
int endSymbol;
int slot;
int slot;
task_ans_t *ans;
} feprx_cmd_t;
typedef struct {
@@ -184,6 +186,7 @@ typedef struct {
int slot;
int startSymbol;
int numSymbols;
task_ans_t *ans;
} feptx_cmd_t;
typedef struct {
@@ -426,7 +429,7 @@ typedef enum {
typedef struct RU_t_s {
/// ThreadPool for RU
/// ThreadPool for RU
tpool_t *threadPool;
/// index of this ru
uint32_t idx;
+3 -1
View File
@@ -66,7 +66,7 @@
#include "PHY/LTE_TRANSPORT/transport_eNB.h"
#include "openair2/PHY_INTERFACE/IF_Module.h"
#include "common/openairinterface5g_limits.h"
#include "common/utils/threadPool/task_ans.h"
#define PBCH_A 24
#define MAX_NUM_RU_PER_eNB 64
@@ -786,6 +786,7 @@ typedef struct TurboDecode_s {
int offset;
int maxIterations;
int decodeIterations;
task_ans_t *ans;
} turboDecode_t;
#define TURBO_SIMD_SOFTBITS 96+12+3+3*6144
@@ -802,6 +803,7 @@ typedef struct turboEncode_s {
time_stats_t *rm_stats;
time_stats_t *te_stats;
time_stats_t *i_stats;
task_ans_t *ans;
} turboEncode_t;

Some files were not shown because too many files have changed in this diff Show More