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:
+6
-7
@@ -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
|
||||
###################################################
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
@@ -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 && 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 && 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 && 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">
|
||||
|
||||
@@ -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
@@ -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
|
||||
)
|
||||
|
||||
|
||||
@@ -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, §_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));
|
||||
@@ -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));
|
||||
|
||||
@@ -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
|
||||
@@ -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, ¶m, 1, prefix), 0);
|
||||
EXPECT_EQ(config_yaml_get(cfg, ¶m, 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, ¶m, 1, prefix), 0);
|
||||
EXPECT_EQ(config_yaml_get(cfg, ¶m, 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, ¶m, 1, prefix), 0);
|
||||
EXPECT_EQ(config_yaml_get(cfg, ¶m, 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, ¶m, 1, prefix), 0);
|
||||
EXPECT_EQ(config_yaml_get(cfg, ¶m, 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, ¶m, 1, prefix), 0);
|
||||
EXPECT_EQ(config_yaml_get(cfg, ¶m, 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, ¶m, 1, prefix1), 0);
|
||||
EXPECT_EQ(config_yaml_get(cfg, ¶m, 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, ¶m, 1, prefix2), 0);
|
||||
EXPECT_EQ(config_yaml_get(cfg, ¶m, 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, ¶m, 1, prefix), 0);
|
||||
EXPECT_EQ(config_yaml_get(cfg, ¶m, 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, ¶m, 1, prefix), 0);
|
||||
EXPECT_EQ(config_yaml_get(cfg, ¶m, 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, ¶m, 1, prefix), 0);
|
||||
EXPECT_EQ(config_yaml_get(cfg, ¶m, 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();
|
||||
|
||||
@@ -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},
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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,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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)));
|
||||
|
||||
@@ -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 ../../..)
|
||||
|
||||
@@ -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 \
|
||||
|
||||
@@ -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)
|
||||
@@ -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**
|
||||
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 ----" && \
|
||||
|
||||
@@ -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 ----" && \
|
||||
|
||||
@@ -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 ----" && \
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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"
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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,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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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__,
|
||||
|
||||
@@ -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" {
|
||||
|
||||
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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) {
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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() {
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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];
|
||||
|
||||
@@ -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];
|
||||
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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++) {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 "
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
Reference in New Issue
Block a user