Compare commits

..

9 Commits

Author SHA1 Message Date
ndomingues
26956bf8e1 Create CI test for 2-Step RA
Signed-off-by: Nuno Domingues <ndomingues@allbesmart.pt>
2026-05-20 10:25:01 +01:00
ndomingues
3a8e3b9408 Demote sharedROs Assert Fatal to LOG_E to get RA 2-Step working
sharedROs feature to be implemented in the future

Signed-off-by: Nuno Domingues <ndomingues@allbesmart.pt>
2026-05-20 10:24:49 +01:00
ndomingues
c9461ac4d4 Improve LOGs to better handle RA 2-Step
Signed-off-by: Nuno Domingues <ndomingues@allbesmart.pt>
2026-05-20 10:24:40 +01:00
ndomingues
d95d911e96 For RA 2-Step consider RA failed if MsgA-PUSCH not detected
Signed-off-by: Nuno Domingues <ndomingues@allbesmart.pt>
2026-05-20 10:24:26 +01:00
ndomingues
97ac8a5cd1 Implementation of the response window timer for 2-Step RA
Signed-off-by: Nuno Domingues <ndomingues@allbesmart.pt>
2026-05-20 10:24:16 +01:00
ndomingues
778fb90f44 Update prach_ConfigurationIndex to get more reliable PRACH detection with USRPs
Signed-off-by: Nuno Domingues <ndomingues@allbesmart.pt>
2026-05-20 10:23:46 +01:00
ndomingues
80735e2b39 Schedule MsgA-PUSCH even if there are UEs connected
Signed-off-by: Nuno Domingues <ndomingues@allbesmart.pt>
2026-05-20 10:22:45 +01:00
ndomingues
ed53bd8f95 Increase RA frame buffer size for 2-step RA to avoid MsgA-PUSCH and ACK/NACK collision
Signed-off-by: Nuno Domingues <ndomingues@allbesmart.pt>
2026-05-20 10:22:26 +01:00
ndomingues
ea35109ba2 Improve find_ra_UE function to return UE identified by RA-RNTI required for MsgA-PUSCH
Signed-off-by: Nuno Domingues <ndomingues@allbesmart.pt>
2026-05-20 10:22:05 +01:00
156 changed files with 3704 additions and 4865 deletions

View File

@@ -5,8 +5,8 @@ project (OpenAirInterface LANGUAGES C CXX)
set(CMAKE_CXX_STANDARD 17)
set(OAI_VERSION 2.4.0)
option(ENABLE_CHANNEL_SIM_CUDA "Enable CUDA accelerated channel simulation" OFF)
if(ENABLE_CHANNEL_SIM_CUDA)
option(CUDA_ENABLE "Enable CUDA accelerated channel simulation" OFF)
if(CUDA_ENABLE)
find_package(CUDA REQUIRED)
find_package(CUDAToolkit REQUIRED)
message(STATUS "CUDA explicitly enabled, building with GPU acceleration support.")
@@ -34,7 +34,7 @@ if(ENABLE_CHANNEL_SIM_CUDA)
message(STATUS "CUDA Explicit Copy path enabled (default ATS was overridden).")
endif()
add_compile_definitions(CHANNEL_SIM_CUDA)
add_compile_definitions(ENABLE_CUDA)
endif()
#########################################################
@@ -155,17 +155,14 @@ add_boolean_option(AVX512 ${AUTODETECT_AVX512} "Whether AVX512 intrinsics is ava
eval_boolean(AUTODETECT_AVX2 DEFINED CPUFLAGS AND CPUFLAGS MATCHES "avx2")
add_boolean_option(AVX2 ${AUTODETECT_AVX2} "Whether AVX2 intrinsics is available on the host processor" ON)
eval_boolean(AUTODETECT_GFNI DEFINED CPUFLAGS AND CPUFLAGS MATCHES "gfni")
add_boolean_option(GFNI ${AUTODETECT_GFNI} "Whether GFNI intrinsics is available on the host processor" ON)
message(STATUS "CPU architecture is ${CMAKE_SYSTEM_PROCESSOR}")
if (CROSS_COMPILE)
message(STATUS "setting as aarch64")
set(C_FLAGS_PROCESSOR "${C_FLAGS_PROCESSOR} -gdwarf-2 -lgcc -lrt")
elseif(CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64")
# The following intrinsics are assumed to be available on any x86 system
# (avx, f16c, fma, mmx, pclmul, sse, sse2, sse3, xop)
set(C_FLAGS_PROCESSOR "${C_FLAGS_PROCESSOR} -DSIMDE_X86_AVX_NATIVE -DSIMDE_X86_AVX_NATIVE -DSIMDE_X86_F16C_NATIVE -DSIMDE_X86_FMA_NATIVE -DSIMDE_X86_MMX_NATIVE -DSIMDE_X86_PCLMUL_NATIVE -DSIMDE_X86_SSE2_NATIVE -DSIMDE_X86_SSE3_NATIVE -DSIMDE_X86_SSE_NATIVE -DSIMDE_X86_XOP_HAVE_COM_ -DSIMDE_X86_XOP_NATIVE")
# (avx, f16c, fma, gnfi, mmx, pclmul, sse, sse2, sse3, xop)
set(C_FLAGS_PROCESSOR "${C_FLAGS_PROCESSOR} -DSIMDE_X86_AVX_NATIVE -DSIMDE_X86_AVX_NATIVE -DSIMDE_X86_F16C_NATIVE -DSIMDE_X86_FMA_NATIVE -DSIMDE_X86_GFNI_NATIVE -DSIMDE_X86_MMX_NATIVE -DSIMDE_X86_PCLMUL_NATIVE -DSIMDE_X86_SSE2_NATIVE -DSIMDE_X86_SSE3_NATIVE -DSIMDE_X86_SSE_NATIVE -DSIMDE_X86_XOP_HAVE_COM_ -DSIMDE_X86_XOP_NATIVE")
message(STATUS "AVX512 intrinsics are ${AVX512}")
if(${AVX512})
set(C_FLAGS_PROCESSOR "${C_FLAGS_PROCESSOR} -DSIMDE_X86_AVX512BW_NATIVE -DSIMDE_X86_AVX512F_NATIVE -DSIMDE_X86_AVX512VL_NATIVE -mavx512bw -march=skylake-avx512 -mtune=skylake-avx512")
@@ -176,17 +173,13 @@ elseif(CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64")
if(${AVX2})
set(C_FLAGS_PROCESSOR "${C_FLAGS_PROCESSOR} -DSIMDE_X86_AVX2_NATIVE -DSIMDE_X86_VPCLMULQDQ_NATIVE")
endif()
message(STATUS "GFNI intrinsics are ${GFNI}")
if(${GFNI})
set(C_FLAGS_PROCESSOR "${C_FLAGS_PROCESSOR} -DSIMDE_X86_GFNI_NATIVE -mgfni")
endif()
if (CPUFLAGS MATCHES "sse4_1")
if (CPUINFO MATCHES "sse4_1")
set(C_FLAGS_PROCESSOR "${C_FLAGS_PROCESSOR} -DSIMDE_X86_SSE4_1_NATIVE")
endif()
if(CPUFLAGS MATCHES "sse4_2")
if(CPUINFO MATCHES "sse4_2")
set(C_FLAGS_PROCESSOR "${C_FLAGS_PROCESSOR} -DSIMDE_X86_SSE4_2_NATIVE")
endif()
if(CPUFLAGS MATCHES "ssse3")
if(CPUINFO MATCHES "ssse3")
set(C_FLAGS_PROCESSOR "${C_FLAGS_PROCESSOR} -DSIMDE_X86_SSSE3_NATIVE")
endif()
elseif (CMAKE_SYSTEM_PROCESSOR STREQUAL "armv7l")
@@ -228,9 +221,9 @@ if(CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
set(commonOpts "${commonOpts} -Wno-packed-bitfield-compat")
endif()
# clang: suppress complaints about unused command line argument (-rdynamic only
# used during linking) and "const member leaves the object uninitialized"
# used during linking)
if(CMAKE_C_COMPILER_ID STREQUAL "Clang" OR CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
set(commonOpts "${commonOpts} -Wno-unused-command-line-argument -Wno-default-const-init-field-unsafe")
set(commonOpts "${commonOpts} -Wno-unused-command-line-argument")
endif()
set(CMAKE_C_FLAGS
@@ -849,7 +842,6 @@ set(PHY_NRLDPC_CODINGIF
)
add_library(dfts MODULE ${OPENAIR1_DIR}/PHY/TOOLS/oai_dfts.c ${OPENAIR1_DIR}/PHY/TOOLS/oai_dfts_neon.c)
target_compile_options(dfts PRIVATE -fno-semantic-interposition)
set(PHY_SRC_COMMON
${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/dci_tools_common.c
@@ -1279,9 +1271,7 @@ set (MAC_NR_SRC
${NR_GNB_MAC_DIR}/gNB_scheduler.c
${NR_GNB_MAC_DIR}/gNB_scheduler_bch.c
${NR_GNB_MAC_DIR}/gNB_scheduler_dlsch.c
${NR_GNB_MAC_DIR}/gNB_scheduler_dlsch_default_policies.c
${NR_GNB_MAC_DIR}/gNB_scheduler_ulsch.c
${NR_GNB_MAC_DIR}/gNB_scheduler_ulsch_default_policies.c
${NR_GNB_MAC_DIR}/gNB_scheduler_primitives.c
${NR_GNB_MAC_DIR}/gNB_scheduler_phytest.c
${NR_GNB_MAC_DIR}/gNB_scheduler_uci.c
@@ -2108,13 +2098,13 @@ target_link_libraries(nr_srssim PRIVATE
m pthread ITTI dl nr_ue_phy_meas physim_common softmodem_common
)
if(ENABLE_CHANNEL_SIM_CUDA)
if(CUDA_ENABLE)
if (TARGET oai_cuda_lib)
target_link_libraries(nr_dlsim PRIVATE oai_cuda_lib)
target_link_libraries(nr_ulsim PRIVATE oai_cuda_lib)
target_compile_definitions(nr_dlsim PRIVATE CHANNEL_SIM_CUDA)
target_compile_definitions(nr_ulsim PRIVATE CHANNEL_SIM_CUDA)
target_compile_definitions(nr_dlsim PRIVATE ENABLE_CUDA)
target_compile_definitions(nr_ulsim PRIVATE ENABLE_CUDA)
endif()
endif()

View File

@@ -8,9 +8,8 @@
<a href="https://gitlab.eurecom.fr/oai/openairinterface5g/-/blob/master/LICENSE"><img src="https://img.shields.io/badge/license-CSSL--v1.0-blue" alt="License"></a>
<a href="https://releases.ubuntu.com/22.04/"><img src="https://img.shields.io/badge/OS-Ubuntu22-Green" alt="Supported OS Ubuntu 22"></a>
<a href="https://releases.ubuntu.com/24.04/"><img src="https://img.shields.io/badge/OS-Ubuntu24-Green" alt="Supported OS Ubuntu 24"></a>
<a href="https://releases.ubuntu.com/26.04/"><img src="https://img.shields.io/badge/OS-Ubuntu26-Green" alt="Supported OS Ubuntu 26"></a>
<a href="https://www.redhat.com/en/technologies/linux-platforms/enterprise-linux"><img src="https://img.shields.io/badge/OS-RHEL9-Green" alt="Supported OS RHEL9"></a>
<a href="https://getfedora.org/en/workstation/"><img src="https://img.shields.io/badge/OS-Fedore44-Green" alt="Supported OS Fedora 44"></a>
<a href="https://getfedora.org/en/workstation/"><img src="https://img.shields.io/badge/OS-Fedore41-Green" alt="Supported OS Fedora 43"></a>
</p>
<p align="center">

View File

@@ -20,13 +20,12 @@ if (params.LockResources != null && params.LockResources.trim().length() > 0)
// Global Parameters. Normally they should be populated when the master job
// triggers the slave job with parameters
def INTERNAL_REPO = "asterix:/home/git/openairinterface5g.git"
def sourceBranch = params.sourceBranch ?: env.GIT_BRANCH
def targetBranch = params.targetBranch ?: 'develop'
def commitID = params.sourceCommit ?: env.GIT_COMMIT
def testRepository = params.customRepository ?: INTERNAL_REPO
def testBranch = params.customBranch ?: "${sourceBranch}-${commitID}"
def mergeWithTarget = params.mergeWithTarget ?: false
def sourceRepository = params.eNB_Repository ?: env.GIT_URL
def sourceBranch = params.eNB_Branch ?: env.GIT_BRANCH
def targetRepository = params.Target_Repository ?: sourceRepository
def targetBranch = params.eNB_TargetBranch ?: 'develop'
def commitID = params.eNB_CommitID ?: env.GIT_COMMIT
def is_MR = params.eNB_mergeRequest ?: false
def flexricOption = ""
def runWithOC = false
@@ -41,22 +40,17 @@ pipeline {
timestamps()
ansiColor('xterm')
lock(extra: lockResources)
skipDefaultCheckout()
}
stages {
stage("Build Init") {
steps {
checkout(
scmGit(branches: [[name: "${branch}"]],
userRemoteConfigs: [[url: "${repository}"]])
)
script {
echo '\u2705 \u001B[94mBuild Init\u001B[0m'
JOB_TIMESTAMP = sh(returnStdout: true, script: 'date --utc --rfc-3339=seconds | sed -e "s#+00:00##"').trim()
}
// update the build name and description
buildName "${params.requestNumber}"
buildName "${params.eNB_MR}"
buildDescription "Branch : ${sourceBranch}"
}
}
@@ -70,12 +64,12 @@ pipeline {
echo "no LockResources given"
allParametersPresent = false
}
if (params.workspace == null) {
echo "no workspace given"
if (params.eNB_SourceCodePath == null) {
echo "no eNB_SourceCodePath given"
allParametersPresent = false
}
if (params.OC_Credentials != null) {
echo "This pipeline is configured to run with Openshift Cluster."
echo "This pipeline is configured to run with Opensift Cluster."
runWithOC = true
if (params.OC_ProjectName == null) {
echo "no OC_ProjectName given"
@@ -90,11 +84,21 @@ pipeline {
}
echo "CI executor node : ${pythonExecutor}"
echo "Testing Repository : ${testRepository}"
echo "Testing Branch : ${testBranch}"
echo "Source Repository : ${sourceRepository}"
echo "Source Branch : ${sourceBranch}"
echo "Target Repository : ${targetRepository}"
echo "Target Branch : ${targetBranch}"
echo "Commit ID : ${commitID}"
if (allParametersPresent) {
echo '\u2705 \u001B[94m All parameters are present\u001B[0m'
if (is_MR) {
sh "git fetch"
sh "./ci-scripts/doGitLabMerge.sh --src-branch ${sourceBranch} --src-commit ${commitID} --target-branch ${targetBranch} --target-commit latest"
} else {
sh "git fetch"
sh "git checkout -f ${commitID}"
}
} else {
echo "\u274C Some parameters are missing"
sh "./ci-scripts/fail.sh"
@@ -117,21 +121,28 @@ pipeline {
}
}
sh """
python3 main.py --mode=InitiateHtml --repository=${testRepository} \
--branch=${testBranch} --commitID=${commitID} \
${mainPythonAllXmlFiles}
python3 main.py --mode=InitiateHtml --ranRepository=${targetRepository} \
--ranBranch=${sourceBranch} --ranCommitID=${commitID} \
--ranAllowMerge=${is_MR} --ranTargetBranch=${targetBranch} \
${flexricOption} ${mainPythonAllXmlFiles}
"""
if (runWithOC) {
withCredentials([usernamePassword(credentialsId: "${params.OC_Credentials}", usernameVariable: 'OC_Username', passwordVariable: 'OC_Password')]) {
sh """
python3 main.py --mode=InitiateHtml --ranRepository=${targetRepository} \
--ranBranch=${sourceBranch} --ranCommitID=${commitID} \
--ranAllowMerge=${is_MR} --ranTargetBranch=${targetBranch} \
${flexricOption} ${mainPythonAllXmlFiles}
"""
for (xmlFile in myXmlTestSuite) {
if (fileExists(xmlFile)) {
try {
timeout (time: 60, unit: 'MINUTES') {
sh """
python3 main.py --mode=TesteNB --repository=${testRepository} \
--branch=${testBranch} \
--ranAllowMerge=${mergeWithTarget} --targetBranch=${targetBranch} \
--workspace=${params.workspace} --XMLTestFile=${xmlFile} \
python3 main.py --mode=TesteNB --ranRepository=${targetRepository} \
--ranBranch=${sourceBranch} --ranCommitID=${commitID} \
--ranAllowMerge=${is_MR} --ranTargetBranch=${targetBranch} \
--eNBSourceCodePath=${params.eNB_SourceCodePath} --XMLTestFile=${xmlFile} \
--OCUserName=${OC_Username} --OCPassword=${OC_Password} --OCProjectName=${OC_ProjectName} \
${flexricOption}
"""
@@ -149,10 +160,10 @@ pipeline {
try {
timeout (time: 60, unit: 'MINUTES') {
sh """
python3 main.py --mode=TesteNB --repository=${testRepository} \
--branch=${testBranch} \
--ranAllowMerge=${mergeWithTarget} --targetBranch=${targetBranch} \
--workspace=${params.workspace} --XMLTestFile=${xmlFile} \
python3 main.py --mode=TesteNB --ranRepository=${targetRepository} \
--ranBranch=${sourceBranch} --ranCommitID=${commitID} \
--ranAllowMerge=${is_MR} --ranTargetBranch=${targetBranch} \
--eNBSourceCodePath=${params.eNB_SourceCodePath} --XMLTestFile=${xmlFile} \
${flexricOption}
"""
}

View File

@@ -880,20 +880,12 @@ def triggerSlaveJob (jobName, gitlabStatusName) {
def localStatus = build job: jobName,
parameters: [
string(name: 'eNB_Repository', value: String.valueOf(GIT_URL)),
string(name: 'targetRepo', value: String.valueOf(GIT_URL)),
string(name: 'SourceRepo', value: String.valueOf(env.gitlabSourceRepoHttpUrl)),
string(name: 'sourceRepo', value: String.valueOf(env.gitlabSourceRepoHttpUrl)),
string(name: 'eNB_Branch', value: String.valueOf(env.gitlabSourceBranch)),
string(name: 'sourceBranch', value: String.valueOf(env.gitlabSourceBranch)),
string(name: 'eNB_CommitID', value: String.valueOf(env.gitlabMergeRequestLastCommit)),
string(name: 'sourceCommit', value: String.valueOf(env.gitlabMergeRequestLastCommit)),
string(name: 'eNB_MR', value: String.valueOf(MR_NUMBER)),
string(name: 'requestNumber', value: String.valueOf(MR_NUMBER)),
booleanParam(name: 'eNB_mergeRequest', value: "MERGE".equals(env.gitlabActionType)),
booleanParam(name: 'mergeWithTarget', value: "MERGE".equals(env.gitlabActionType)),
string(name: 'eNB_TargetBranch', value: String.valueOf(env.gitlabTargetBranch)),
string(name: 'targetBranch', value: String.valueOf(env.gitlabTargetBranch)),
string(name: 'testBranch', value: "${env.gitlabSourceBranch.replace('/', '-')}-${env.gitlabMergeRequestLastCommit}")
string(name: 'eNB_TargetBranch', value: String.valueOf(env.gitlabTargetBranch))
], propagate: false
def localResult = localStatus.getResult()
echo "${jobName} Slave Job status is ${localResult}"
@@ -908,9 +900,13 @@ def triggerSlaveJob (jobName, gitlabStatusName) {
def triggerCN5GSlaveJob (jobName, gitlabStatusName) {
if ("MERGE".equals(env.gitlabActionType)) {
fullRanTag = OAI_Registry + '/oai-gnb:' + "${env.gitlabSourceBranch.replace('/', '-')}-${env.gitlabMergeRequestLastCommit}"
shaOne = sh returnStdout: true, script: 'git log -1 --pretty=format:"%H" ' + env.gitlabMergeRequestLastCommit
shaOne = shaOne.trim()
fullRanTag = OAI_Registry + '/oai-gnb:' + env.gitlabSourceBranch + '-' + shaOne
} else {
fullRanTag = OAI_Registry + '/oai-gnb:develop-' + env.GIT_COMMIT
shaOne = sh returnStdout: true, script: 'git log -1 --pretty=format:"%H" ' + env.GIT_COMMIT
shaOne = shaOne.trim()
fullRanTag = OAI_Registry + '/oai-gnb:develop-' + shaOne
}
// Workaround for the "cancelled" GitLab pipeline notification
// The slave job is triggered with the propagate false so the following commands are executed

View File

@@ -27,26 +27,21 @@ pipeline {
steps {
script {
def missingParams = []
if (!params.sourceRepo?.trim()) { missingParams << 'sourceRepo' }
if (!params.sourceBranch?.trim()) { missingParams << 'sourceBranch' }
if (!params.sourceCommit?.trim()) { missingParams << 'sourceCommit' }
if (params.mergeWithTarget) {
if (!params.targetRepo?.trim()) { missingParams << 'targetRepo' }
if (!params.targetBranch?.trim()) { missingParams << 'targetBranch' }
}
if (!params.SourceRepo?.trim()) { missingParams << 'SourceRepo' }
if (!params.eNB_Branch?.trim()) { missingParams << 'eNB_Branch' }
if (!params.eNB_CommitID?.trim()) { missingParams << 'eNB_CommitID' }
if (!params.eNB_TargetBranch?.trim()) { missingParams << 'eNB_TargetBranch' }
if (!params.eNB_Repository?.trim()) { missingParams << 'eNB_Repository' }
if (missingParams) {
error "Missing required parameters: ${missingParams.join(', ')}"
}
echo "Source Repo : ${params.sourceRepo}"
echo "Source Branch : ${params.sourceBranch}"
echo "Source Commit : ${params.sourceCommit}"
echo "Merge : ${params.mergeWithTarget}"
if (params.mergeWithTarget) {
echo "Target Branch : ${params.targetBranch}"
echo "Target Repo : ${params.targetRepo}"
}
echo "Source Repo : ${params.SourceRepo}"
echo "Source Branch : ${params.eNB_Branch}"
echo "Source Commit : ${params.eNB_CommitID}"
echo "Target Branch : ${params.eNB_TargetBranch}"
echo "Target Repo : ${params.eNB_Repository}"
}
}
}
@@ -56,7 +51,6 @@ pipeline {
git config user.email "jenkins@openairinterface.org"
git config user.name "OAI Jenkins"
git remote remove source || true
git remote remove target || true
git remote remove internal-repo || true
"""
}
@@ -64,38 +58,30 @@ pipeline {
stage('Add source repo & fetch branches') {
steps {
sh """
git remote add source ${params.sourceRepo} || true
git fetch source ${params.sourceBranch}
git remote add source ${params.SourceRepo} || true
git fetch source ${params.eNB_Branch}
git fetch origin ${params.eNB_TargetBranch}
"""
script {
if (params.mergeWithTarget) {
sh """
git remote add target ${params.targetRepo} || true
git fetch target ${params.targetBranch}
"""
}
}
}
}
stage('Create temporary branch for CI') {
steps {
script {
env.NEW_BRANCH = "${params.sourceBranch}-${params.sourceCommit}"
env.NEW_BRANCH = "${params.eNB_Branch}-${params.eNB_CommitID}"
echo "New branch: ${env.NEW_BRANCH}"
}
sh """
# Checkout source commit
git checkout -B ${env.NEW_BRANCH} ${params.sourceCommit}
git checkout -B ${env.NEW_BRANCH} ${params.eNB_CommitID}
"""
}
}
stage('Merge target into source') {
when { expression { return params.mergeWithTarget } }
steps {
sh """
echo "Merging target branch ${params.targetBranch} into source branch ${env.NEW_BRANCH}"
if ! git merge --ff target/${params.targetBranch} \
-m "Merge ${params.targetBranch} into ${params.sourceBranch} for CI"; then
echo "Merging target branch ${params.eNB_TargetBranch} into source branch ${env.NEW_BRANCH}"
if ! git merge --ff origin/${params.eNB_TargetBranch} \
-m "Merge ${params.eNB_TargetBranch} into ${params.eNB_Branch} for CI"; then
echo "Merge conflicts detected. Aborting."
git merge --abort || true
exit 1

View File

@@ -56,7 +56,7 @@ pipeline {
echo "Forced Tag is ${WEEK_TAG}"
}
}
WEEK_SHA = sh returnStdout: true, script: 'git log -n1 --pretty=format:"%H" origin/develop'
WEEK_SHA = sh returnStdout: true, script: 'git log -n1 --pretty=format:"%h" origin/develop | cut -c 1-8'
WEEK_SHA = WEEK_SHA.trim()
withCredentials([

View File

@@ -44,11 +44,8 @@ def ArgsParse(argvs,CiTestObj,RAN,HTML,CONTAINERS,HELP,CLUSTER):
elif re.match(r'^\-\-mode=(.+)$', myArgv, re.IGNORECASE):
matchReg = re.match(r'^\-\-mode=(.+)$', myArgv, re.IGNORECASE)
mode = matchReg.group(1)
elif re.match(r'^\-\-repository=(.+)$|^\-\-ranRepository=(.+)$', myArgv, re.IGNORECASE):
if re.match(r'^\-\-repository=(.+)$', myArgv, re.IGNORECASE):
matchReg = re.match(r'^\-\-repository=(.+)$', myArgv, re.IGNORECASE)
else:
matchReg = re.match(r'^\-\-ranRepository=(.+)$', myArgv, re.IGNORECASE)
elif re.match(r'^\-\-ranRepository(.+)$', myArgv, re.IGNORECASE):
matchReg = re.match(r'^\-\-ranRepository=(.+)$', myArgv, re.IGNORECASE)
CiTestObj.repository = matchReg.group(1)
RAN.repository=matchReg.group(1)
HTML.repository=matchReg.group(1)
@@ -59,40 +56,34 @@ def ArgsParse(argvs,CiTestObj,RAN,HTML,CONTAINERS,HELP,CLUSTER):
doMerge = matchReg.group(1)
if ((doMerge == 'true') or (doMerge == 'True')):
RAN.merge=True
HTML.merge=True
CONTAINERS.merge=True
CLUSTER.merge=True
elif re.match(r'^\-\-branch=(.+)$|^\-\-ranBranch=(.+)$', myArgv, re.IGNORECASE):
if re.match(r'^\-\-branch=(.+)$', myArgv, re.IGNORECASE):
matchReg = re.match(r'^\-\-branch=(.+)$', myArgv, re.IGNORECASE)
else:
matchReg = re.match(r'^\-\-ranBranch=(.+)$', myArgv, re.IGNORECASE)
elif re.match(r'^\-\-ranBranch=(.+)$', myArgv, re.IGNORECASE):
matchReg = re.match(r'^\-\-ranBranch=(.+)$', myArgv, re.IGNORECASE)
CiTestObj.branch = matchReg.group(1)
RAN.branch=matchReg.group(1)
HTML.branch=matchReg.group(1)
CONTAINERS.branch=matchReg.group(1)
CLUSTER.branch=matchReg.group(1)
elif re.match(r'^\-\-commitID=(.*)$|^\-\-ranCommitID=(.*)$', myArgv, re.IGNORECASE):
if re.match(r'^\-\-commitID=(.*)$', myArgv, re.IGNORECASE):
matchReg = re.match(r'^\-\-commitID=(.*)$', myArgv, re.IGNORECASE)
else:
matchReg = re.match(r'^\-\-ranCommitID=(.*)$', myArgv, re.IGNORECASE)
elif re.match(r'^\-\-ranCommitID=(.*)$', myArgv, re.IGNORECASE):
matchReg = re.match(r'^\-\-ranCommitID=(.*)$', myArgv, re.IGNORECASE)
RAN.commitID=matchReg.group(1)
HTML.commitID=matchReg.group(1)
elif re.match(r'^\-\-targetBranch=(.*)$|^\-\-ranTargetBranch=(.*)$', myArgv, re.IGNORECASE):
if re.match(r'^\-\-targetBranch=(.*)$', myArgv, re.IGNORECASE):
matchReg = re.match(r'^\-\-targetBranch=(.*)$', myArgv, re.IGNORECASE)
else:
matchReg = re.match(r'^\-\-ranTargetBranch=(.*)$', myArgv, re.IGNORECASE)
CONTAINERS.commitID=matchReg.group(1)
CLUSTER.commitID=matchReg.group(1)
elif re.match(r'^\-\-ranTargetBranch=(.*)$', myArgv, re.IGNORECASE):
matchReg = re.match(r'^\-\-ranTargetBranch=(.*)$', myArgv, re.IGNORECASE)
RAN.targetBranch=matchReg.group(1)
HTML.targetBranch=matchReg.group(1)
CONTAINERS.targetBranch=matchReg.group(1)
CLUSTER.targetBranch=matchReg.group(1)
elif re.match(r'^\-\-workspace=(.+)$|^\-\-eNBSourceCodePath=(.+)$', myArgv, re.IGNORECASE):
if re.match(r'^\-\-workspace=(.+)$', myArgv, re.IGNORECASE):
matchReg = re.match(r'^\-\-workspace=(.+)$', myArgv, re.IGNORECASE)
else:
elif re.match(r'^\-\-eNBSourceCodePath=(.+)$|^\-\-eNB[1-2]SourceCodePath=(.+)$', myArgv, re.IGNORECASE):
if re.match(r'^\-\-eNBSourceCodePath=(.+)$', myArgv, re.IGNORECASE):
matchReg = re.match(r'^\-\-eNBSourceCodePath=(.+)$', myArgv, re.IGNORECASE)
RAN.workspace=matchReg.group(1)
CONTAINERS.workspace=matchReg.group(1)
CLUSTER.workspace=matchReg.group(1)
RAN.workspace=matchReg.group(1)
CONTAINERS.workspace=matchReg.group(1)
CLUSTER.workspace=matchReg.group(1)
elif re.match(r'^\-\-XMLTestFile=(.+)$', myArgv, re.IGNORECASE):
matchReg = re.match(r'^\-\-XMLTestFile=(.+)$', myArgv, re.IGNORECASE)
CiTestObj.testXMLfiles.append(matchReg.group(1))

View File

@@ -58,6 +58,7 @@ class Cluster:
self.OCRegistry = OCRegistry
self.repository = ""
self.branch = ""
self.commitID = ""
self.merge = False
self.targetBranch = ""
self.cmd = None
@@ -156,7 +157,7 @@ class Cluster:
OC_logout(cmd)
HTML.CreateHtmlTestRow('N/A', 'KO', CONST.OC_LOGIN_FAIL)
return False
tag = self.branch
tag = cls_containerize.CreateTag(self.commitID, self.branch, self.merge)
registry = f'{self.OCRegistry}/{CI_OC_RAN_NAMESPACE}'
success, msg = cls_containerize.Containerize.Pull_Image(cmd, images, tag, tag_prefix, registry, None, None)
OC_logout(cmd)
@@ -173,9 +174,9 @@ class Cluster:
return (image, archiveArtifact(self.cmd, ctx, fn))
def BuildClusterImage(self, ctx, node, HTML):
if self.repository == '' or self.branch == '':
if self.repository == '' or self.branch == '' or self.commitID == '':
HELP.GenericHelp(CONST.Version)
raise ValueError(f'Insufficient Parameter: repository {self.repository} branch {self.branch}')
raise ValueError(f'Insufficient Parameter: repository {self.repository} branch {self.branch} commitID {self.commitID}')
lSourcePath = self.workspace
if node == '' or lSourcePath == '':
raise ValueError('Insufficient Parameter: workspace missing')
@@ -201,7 +202,7 @@ class Cluster:
forceBaseImageBuild = False
if self.merge: # merging MR branch into develop -> temporary image
branchName = self.branch.replace('/','-')
imageTag = f'{branchName}'
imageTag = f'{branchName}-{self.commitID}'
if self.targetBranch == 'develop':
ret = self.cmd.run(f'git diff HEAD..origin/develop -- cmake_targets/build_oai cmake_targets/tools/build_helper docker/Dockerfile.base.rhel9 | grep --colour=never -i INDEX')
result = re.search('index', ret.stdout)
@@ -214,7 +215,7 @@ class Cluster:
forceBaseImageBuild = True
baseTag = 'ci-temp'
else:
imageTag = self.branch
imageTag = f'develop-{self.commitID}'
forceBaseImageBuild = True
# logging to OC Cluster and then switch to corresponding project

View File

@@ -32,15 +32,34 @@ from cls_ci_helper import archiveArtifact
IMAGES = ['oai-enb', 'oai-lte-ru', 'oai-lte-ue', 'oai-gnb', 'oai-nr-cuup', 'oai-gnb-aw2s', 'oai-nr-ue', 'oai-enb-asan', 'oai-gnb-asan', 'oai-lte-ue-asan', 'oai-nr-ue-asan', 'oai-nr-cuup-asan', 'oai-gnb-aerial', 'oai-gnb-fhi72']
DEFAULT_REGISTRY = "gracehopper3-oai.sboai.cs.eurecom.fr"
def CreateWorkspace(host, sourcePath, repository, branch):
def CreateWorkspace(host, sourcePath, repository, commitID, targetBranch, merge):
if commitID == '':
logging.error('need commitID in CreateWorkspace()')
raise ValueError('Insufficient Parameter in CreateWorkspace(): need commitID')
script = "scripts/create_workspace.sh"
options = f"{sourcePath} {repository} {branch}"
options = f"{sourcePath} {repository} {commitID}"
if merge:
if targetBranch == '':
targetBranch = 'develop'
options += f" {targetBranch}"
logging.info(f'execute "{script}" with options "{options}" on node {host}')
with cls_cmd.getConnection(host) as c:
ret = c.exec_script(script, 90, options)
logging.debug(f'"{script}" finished with code {ret.returncode}, output:\n{ret.stdout}')
return ret.returncode == 0
def CreateTag(commitID, branch, merge):
if commitID == 'develop':
return 'develop'
if merge:
# Allowing contributor to have a name/branchName format
branchName = branch.replace('/','-')
tagToUse = f'{branchName}-{commitID}'
else:
tagToUse = f'develop-{commitID}'
return tagToUse
def AnalyzeBuildLogs(image, lf):
committed = False
tagged = False
@@ -155,6 +174,7 @@ class Containerize():
self.repository = ''
self.branch = ''
self.merge = False
self.commitID = ''
self.targetBranch = ''
self.workspace = ''
self.imageKind = ''
@@ -423,7 +443,7 @@ class Containerize():
if self.merge:
orgTag = 'ci-temp'
for image in IMAGES:
tagToUse = tag_prefix + self.branch
tagToUse = tag_prefix + CreateTag(self.commitID, self.branch, self.merge)
imageTag = f"{image}:{tagToUse}"
ret = ssh.run(f'docker image tag {image}:{orgTag} {imagePrefix}/{imageTag}')
if ret.returncode != 0:
@@ -484,7 +504,7 @@ class Containerize():
def Pull_Image_from_Registry(self, HTML, node, images, tag=None, tag_prefix="", registry=DEFAULT_REGISTRY, username="oaicicd", password="oaicicd"):
logging.debug(f'\u001B[1m Pulling image(s) on server: {node}\u001B[0m')
if not tag:
tag = self.branch
tag = CreateTag(self.commitID, self.branch, self.merge)
with cls_cmd.getConnection(node) as cmd:
success, msg = Containerize.Pull_Image(cmd, images, tag, tag_prefix, registry, username, password)
param = f"on node {node}"
@@ -497,7 +517,7 @@ class Containerize():
def Clean_Test_Server_Images(self, HTML, node, images, tag=None):
logging.debug(f'\u001B[1m Cleaning image(s) from server: {node}\u001B[0m')
if not tag:
tag = self.branch
tag = CreateTag(self.commitID, self.branch, self.merge)
status = True
with cls_cmd.getConnection(node) as myCmd:
@@ -516,10 +536,10 @@ class Containerize():
return status
def Create_Workspace(self, node, HTML):
sourcePath = self.workspace
success = CreateWorkspace(node, sourcePath, self.repository, self.branch)
lSourcePath = self.workspace
success = CreateWorkspace(node, lSourcePath, self.repository, self.commitID, self.targetBranch, self.merge)
if success:
HTML.CreateHtmlTestRowQueue('N/A', 'OK', [f"created workspace {sourcePath} on node {node}"])
HTML.CreateHtmlTestRowQueue('N/A', 'OK', [f"created workspace {lSourcePath}"])
else:
HTML.CreateHtmlTestRowQueue('N/A', 'KO', ["cannot create workspace"])
return success

View File

@@ -36,6 +36,8 @@ class HTMLManagement():
self.repository = ''
self.branch = ''
self.commitID = ''
self.merge = False
self.targetBranch = ''
self.nbTestXMLfiles = 0
self.htmlTabRefs = []
@@ -97,15 +99,44 @@ class HTMLManagement():
self.htmlFile.write(' <td><a href="' + self.repository + '">' + self.repository + '</a></td>\n')
self.htmlFile.write(' </tr>\n')
self.htmlFile.write(' <tr>\n')
self.htmlFile.write(' <td bgcolor = "lightcyan" > <span class="glyphicon glyphicon-log-out"></span> Test Branch </td>\n')
self.htmlFile.write(' <td bgcolor = "lightcyan" > <span class="glyphicon glyphicon-wrench"></span> Job Trigger </td>\n')
if (self.merge):
self.htmlFile.write(' <td>Merge-Request</td>\n')
else:
self.htmlFile.write(' <td>Push to Branch</td>\n')
self.htmlFile.write(' </tr>\n')
self.htmlFile.write(' <tr>\n')
if (self.merge):
self.htmlFile.write(' <td bgcolor = "lightcyan" > <span class="glyphicon glyphicon-log-out"></span> Source Branch </td>\n')
else:
self.htmlFile.write(' <td bgcolor = "lightcyan" > <span class="glyphicon glyphicon-tree-deciduous"></span> Branch</td>\n')
self.htmlFile.write(' <td>' + self.branch + '</td>\n')
self.htmlFile.write(' </tr>\n')
commit_message = subprocess.check_output("git log -n1 --pretty=format:\"%s\" " + self.commitID, shell=True, universal_newlines=True)
commit_message = commit_message.strip()
self.htmlFile.write(' <tr>\n')
self.htmlFile.write(' <td bgcolor = "lightcyan" > <span class="glyphicon glyphicon-comment"></span> Commit Message </td>\n')
self.htmlFile.write(' <td>' + commit_message + '</td>\n')
if (self.merge):
self.htmlFile.write(' <td bgcolor = "lightcyan" > <span class="glyphicon glyphicon-tag"></span> Source Commit ID </td>\n')
else:
self.htmlFile.write(' <td bgcolor = "lightcyan" > <span class="glyphicon glyphicon-tag"></span> Commit ID </td>\n')
self.htmlFile.write(' <td>' + self.commitID + '</td>\n')
self.htmlFile.write(' </tr>\n')
if self.merge != '' and self.commitID != 'develop':
commit_message = subprocess.check_output("git log -n1 --pretty=format:\"%s\" " + self.commitID, shell=True, universal_newlines=True)
commit_message = commit_message.strip()
self.htmlFile.write(' <tr>\n')
if (self.merge):
self.htmlFile.write(' <td bgcolor = "lightcyan" > <span class="glyphicon glyphicon-comment"></span> Source Commit Message </td>\n')
else:
self.htmlFile.write(' <td bgcolor = "lightcyan" > <span class="glyphicon glyphicon-comment"></span> Commit Message </td>\n')
self.htmlFile.write(' <td>' + commit_message + '</td>\n')
self.htmlFile.write(' </tr>\n')
if (self.merge):
self.htmlFile.write(' <tr>\n')
self.htmlFile.write(' <td bgcolor = "lightcyan" > <span class="glyphicon glyphicon-log-in"></span> Target Branch </td>\n')
if (self.targetBranch == ''):
self.htmlFile.write(' <td>develop</td>\n')
else:
self.htmlFile.write(' <td>' + self.targetBranch + '</td>\n')
self.htmlFile.write(' </tr>\n')
self.htmlFile.write(' </table>\n')
self.htmlFile.write(' <br>\n')

View File

@@ -0,0 +1,271 @@
# SPDX-License-Identifier: LicenseRef-CSSL-1.0
Active_gNBs = ( "gNB-OAI");
# Asn1_verbosity, choice in: none, info, annoying
Asn1_verbosity = "none";
gNBs =
(
{
////////// Identification parameters:
gNB_ID = 0xe00;
gNB_name = "gNB-OAI";
// Tracking area code, 0x0000 and 0xfffe are reserved values
tracking_area_code = 1;
plmn_list = ({ mcc = 001; mnc = 01; mnc_length = 2; snssaiList = ({ sst = 1; }) });
nr_cellid = 12345678L;
////////// Physical parameters:
do_CSIRS = 1;
do_SRS = 1;
servingCellConfigCommon = (
{
#spCellConfigCommon
physCellId = 0;
# downlinkConfigCommon
#frequencyInfoDL
# this is 3600 MHz + 43 PRBs@30kHz SCS (same as initial BWP)
absoluteFrequencySSB = 641280;
dl_frequencyBand = 78;
# this is 3600 MHz
dl_absoluteFrequencyPointA = 640008;
#scs-SpecificCarrierList
dl_offstToCarrier = 0;
# subcarrierSpacing
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
dl_subcarrierSpacing = 1;
dl_carrierBandwidth = 106;
#initialDownlinkBWP
#genericParameters
# this is RBstart=27,L=48 (275*(L-1))+RBstart
initialDLBWPlocationAndBandwidth = 28875; # 6366 12925 12956 28875 12952
# subcarrierSpacing
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
initialDLBWPsubcarrierSpacing = 1;
#pdcch-ConfigCommon
initialDLBWPcontrolResourceSetZero = 12;
initialDLBWPsearchSpaceZero = 0;
#uplinkConfigCommon
#frequencyInfoUL
ul_frequencyBand = 78;
#scs-SpecificCarrierList
ul_offstToCarrier = 0;
# subcarrierSpacing
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
ul_subcarrierSpacing = 1;
ul_carrierBandwidth = 106;
pMax = 20;
#initialUplinkBWP
#genericParameters
initialULBWPlocationAndBandwidth = 28875;
# subcarrierSpacing
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
initialULBWPsubcarrierSpacing = 1;
#rach-ConfigCommon
#rach-ConfigGeneric
prach_ConfigurationIndex = 148;
#prach_msg1_FDM
#0 = one, 1=two, 2=four, 3=eight
prach_msg1_FDM = 0;
prach_msg1_FrequencyStart = 0;
zeroCorrelationZoneConfig = 13;
preambleReceivedTargetPower = -96;
#preamblTransMax (0...10) = (3,4,5,6,7,8,10,20,50,100,200)
preambleTransMax = 10;
#powerRampingStep
# 0=dB0,1=dB2,2=dB4,3=dB6
powerRampingStep = 1;
#ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR
#1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen
ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4;
#one (0..15) 4,8,12,16,...60,64
ssb_perRACH_OccasionAndCB_PreamblesPerSSB = 14;
#ra_ContentionResolutionTimer
#(0..7) 8,16,24,32,40,48,56,64
ra_ContentionResolutionTimer = 7;
rsrp_ThresholdSSB = 19;
#prach-RootSequenceIndex_PR
#1 = 839, 2 = 139
prach_RootSequenceIndex_PR = 2;
prach_RootSequenceIndex = 1;
# SCS for msg1, can only be 15 for 30 kHz < 6 GHz, takes precendence over the one derived from prach-ConfigIndex
#
msg1_SubcarrierSpacing = 1,
# restrictedSetConfig
# 0=unrestricted, 1=restricted type A, 2=restricted type B
restrictedSetConfig = 0,
msg3_DeltaPreamble = 1;
p0_NominalWithGrant =-90;
# 0=sl1, 1=sl2, 2=sl4, 3=sl8, 4=sl10, 5=sl20, 6=sl40, 7=sl80, 8=sl160, 9=sl320
msgB_ResponseWindow_r16 = 5;
msgA_RSRP_Threshold_r16 = 19;
msgA_CB_PreamblesPerSSB_PerSharedRO_r16 = 1;
msgA_MCS_r16 = 2;
nrofSlotsMsgA_PUSCH_r16 = 1;
# 0=one, 1=two, 2=three, 3=six
nrofMsgA_PO_PerSlot_r16 = 0;
msgA_PUSCH_TimeDomainOffset_r16 = 8;
startSymbolAndLengthMsgA_PO_r16 = 38;
mappingTypeMsgA_PUSCH_r16 = 0;
guardBandMsgA_PUSCH_r16 = 0;
frequencyStartMsgA_PUSCH_r16 = 0;
nrofPRBs_PerMsgA_PO_r16 = 8;
# 0=one, 1=two, 2=four, 3=eight
nrofMsgA_PO_FDM_r16 = 0;
msgA_PUSCH_NrofPorts_r16 = 1;
nrofDMRS_Sequences_r16 = 1;
# 0=enabled, 1=disabled
msgA_TransformPrecoder_r16 = 1;
# pucch-ConfigCommon setup :
# pucchGroupHopping
# 0 = neither, 1= group hopping, 2=sequence hopping
pucchGroupHopping = 0;
hoppingId = 40;
p0_nominal = -90;
ssb_PositionsInBurst_Bitmap = 1;
# ssb_periodicityServingCell
# 0 = ms5, 1=ms10, 2=ms20, 3=ms40, 4=ms80, 5=ms160, 6=spare2, 7=spare1
ssb_periodicityServingCell = 2;
# dmrs_TypeA_position
# 0 = pos2, 1 = pos3
dmrs_TypeA_Position = 0;
# subcarrierSpacing
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
subcarrierSpacing = 1;
#tdd-UL-DL-ConfigurationCommon
# subcarrierSpacing
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
referenceSubcarrierSpacing = 1;
# pattern1
# dl_UL_TransmissionPeriodicity
# 0=ms0p5, 1=ms0p625, 2=ms1, 3=ms1p25, 4=ms2, 5=ms2p5, 6=ms5, 7=ms10
dl_UL_TransmissionPeriodicity = 6;
nrofDownlinkSlots = 7;
nrofDownlinkSymbols = 6;
nrofUplinkSlots = 2;
nrofUplinkSymbols = 4;
ssPBCH_BlockPower = -25;
}
);
# ------- SCTP definitions
SCTP :
{
# Number of streams to use in input/output
SCTP_INSTREAMS = 2;
SCTP_OUTSTREAMS = 2;
};
////////// AMF parameters:
amf_ip_address = ({ ipv4 = "192.168.71.132"; });
NETWORK_INTERFACES :
{
GNB_IPV4_ADDRESS_FOR_NG_AMF = "192.168.71.140/24";
GNB_IPV4_ADDRESS_FOR_NGU = "192.168.71.140/24";
GNB_PORT_FOR_S1U = 2152; # Spec 2152
};
}
);
MACRLCs = (
{
tr_s_preference = "local_L1";
tr_n_preference = "local_RRC";
pusch_TargetSNRx10 = 150;
pucch_TargetSNRx10 = 200;
}
);
L1s = (
{
tr_n_preference = "local_mac";
prach_dtx_threshold = 120;
pucch0_dtx_threshold = 100;
ofdm_offset_divisor = 8; #set this to UINT_MAX for offset 0
}
);
RUs = (
{
local_rf = "yes"
nb_tx = 1
nb_rx = 1
att_tx = 12;
att_rx = 12;
bands = [78];
max_pdschReferenceSignalPower = -27;
max_rxgain = 114;
eNB_instances = [0];
clock_src = "internal";
}
);
rfsimulator :
{
serveraddr = "server";
serverport = 4043;
options = (); #("saviq"); or/and "chanmod"
modelname = "AWGN";
IQfile = "/tmp/rfsimulator.iqs";
};
security = {
# preferred ciphering algorithms
# the first one of the list that an UE supports in chosen
# valid values: nea0, nea1, nea2, nea3
ciphering_algorithms = ( "nea0" );
# preferred integrity algorithms
# the first one of the list that an UE supports in chosen
# valid values: nia0, nia1, nia2, nia3
integrity_algorithms = ( "nia2", "nia0" );
# setting 'drb_ciphering' to "no" disables ciphering for DRBs, no matter
# what 'ciphering_algorithms' configures; same thing for 'drb_integrity'
drb_ciphering = "yes";
drb_integrity = "no";
};
log_config :
{
global_log_level ="info";
hw_log_level ="info";
phy_log_level ="info";
mac_log_level ="info";
rlc_log_level ="info";
pdcp_log_level ="info";
rrc_log_level ="info";
ngap_log_level ="debug";
f1ap_log_level ="debug";
};
e2_agent = {
near_ric_ip_addr = "127.0.0.1";
#sm_dir = "/path/where/the/SMs/are/located/"
sm_dir = "/usr/local/lib/flexric/"
};

View File

@@ -207,40 +207,3 @@ channelmod:
forgetfact: 0
offset: 0
ds_tdl: 0
vrtsim:
role: server
# Channel mode: exactly one of the three modes below should be active.
#
# No channel - plain passthrough, no impairments:
# cirdb: 0
# chanmod: 0
#
# Built-in channel model defined in the channelmod: section above:
# chanmod: 1
# cirdb: 0
#
# External taps emitter publishing over a nanomsg socket.
# Requires a running emit_from_db.py and build with -DOAI_VRTSIM_TAPS_CLIENT=ON:
# cirdb: 0
# chanmod: 0
# taps-socket: "tcp://127.0.0.1:5555"
#
# In-process CIR database: reads precomputed 3GPP TDL taps directly from
# cir_db.bin. No external emitter required. Generate the database offline
# with cir_generator.py. Use cirdb-path to point to the directory containing
# cir_db.bin and cir_db.yaml.
cirdb_file: /cirdb/cir_db.bin
cirdb_yaml: /cirdb/cir_db.yaml
#
# Per-UE channel configuration for multi-UE operation
ue_config:
- antennas: "2x2" # NxM where N=UE-TX, M=gNB-TX; M must equal RU nb_tx
model_id: 0 # 0=TDL-A 1=TDL-B 2=TDL-C 3=TDL-D 4=TDL-E
ds_ns: 1.0 # RMS delay spread in ns
speed_mps: 1.5 # UE speed in m/s
# aoa_deg: 0.0 # angle of arrival in degrees; TDL-D/E only
- antennas: "1x2"
model_id: 0
ds_ns: 1.0
speed_mps: 1.5
# aoa_deg: 0.0

126
ci-scripts/doGitLabMerge.sh Executable file
View File

@@ -0,0 +1,126 @@
#!/bin/bash
# SPDX-License-Identifier: LicenseRef-CSSL-1.0
function usage {
echo "OAI GitLab merge request applying script"
echo ""
echo "Usage:"
echo "------"
echo ""
echo " doGitLabMerge.sh [OPTIONS] [MANDATORY_OPTIONS]"
echo ""
echo "Mandatory Options:"
echo "------------------"
echo ""
echo " --src-branch #### OR -sb ####"
echo " Specify the source branch of the merge request."
echo ""
echo " --src-commit #### OR -sc ####"
echo " Specify the source commit ID (SHA-1) of the merge request."
echo ""
echo " --target-branch #### OR -tb ####"
echo " Specify the target branch of the merge request (usually develop)."
echo ""
echo " --target-commit #### OR -tc ####"
echo " Specify the target commit ID (SHA-1) of the merge request."
echo ""
echo "Options:"
echo "--------"
echo " --help OR -h"
echo " Print this help message."
echo ""
}
if [ $# -ne 8 ] && [ $# -ne 1 ]
then
echo "Syntax Error: not the correct number of arguments"
echo ""
usage
exit 1
fi
checker=0
while [[ $# -gt 0 ]]
do
key="$1"
case $key in
-h|--help)
shift
usage
exit 0
;;
-sb|--src-branch)
SOURCE_BRANCH="$2"
let "checker|=0x1"
shift
shift
;;
-sc|--src-commit)
SOURCE_COMMIT_ID="$2"
let "checker|=0x2"
shift
shift
;;
-tb|--target-branch)
TARGET_BRANCH="$2"
let "checker|=0x4"
shift
shift
;;
-tc|--target-commit)
TARGET_COMMIT_ID="$2"
let "checker|=0x8"
shift
shift
;;
*)
echo "Syntax Error: unknown option: $key"
echo ""
usage
exit 1
esac
done
if [[ $TARGET_COMMIT_ID == "latest" ]]
then
TARGET_COMMIT_ID=`git log -n1 --pretty=format:%H origin/$TARGET_BRANCH`
fi
echo "Source Branch is : $SOURCE_BRANCH"
echo "Source Commit ID is : $SOURCE_COMMIT_ID"
echo "Target Branch is : $TARGET_BRANCH"
echo "Target Commit ID is : $TARGET_COMMIT_ID"
if [ $checker -ne 15 ]
then
echo ""
echo "Syntax Error: missing option"
echo ""
usage
exit 1
fi
git config user.email "jenkins@openairinterface.org"
git config user.name "OAI Jenkins"
git checkout -f $SOURCE_COMMIT_ID > checkout.txt 2>&1
STATUS=`grep -E -c "fatal: reference is not a tree" checkout.txt`
rm -f checkout.txt
if [ $STATUS -ne 0 ]
then
echo "fatal: reference is not a tree --> $SOURCE_COMMIT_ID"
STATUS=-1
exit $STATUS
fi
git merge --ff $TARGET_COMMIT_ID -m "Temporary merge for CI"
STATUS=`git status | grep -E -c "You have unmerged paths.|fix conflicts"`
if [ $STATUS -ne 0 ]
then
echo "There are merge conflicts.. Cannot perform further build tasks"
STATUS=-1
fi
exit $STATUS

View File

@@ -26,7 +26,7 @@ RUN cmake -GNinja -DENABLE_PHYSIM_TESTS=ON -DENABLE_TESTS=ON \
-DSANITIZE_UNDEFINED=OFF -DSANITIZE_ADDRESS=OFF \
-DCMAKE_C_FLAGS=-Werror -DCMAKE_CXX_FLAGS=-Werror \
-DPHYSIM_CHECK_FILES="ThresholdsCuda.cmake" \
-DENABLE_CHANNEL_SIM_CUDA=ON \
-DCUDA_ENABLE=ON \
-DUSE_UNIFIED_MEMORY=ON \
-DUSE_ATS_MEMORY=OFF \
-DCMAKE_RUNTIME_OUTPUT_DIRECTORY=/oai-ran/cmake_targets/ran_build/build \

View File

@@ -26,7 +26,7 @@ RUN cmake -GNinja -DENABLE_PHYSIM_TESTS=ON -DENABLE_TESTS=ON \
-DSANITIZE_UNDEFINED=OFF -DSANITIZE_ADDRESS=OFF \
-DCMAKE_C_FLAGS=-Werror -DCMAKE_CXX_FLAGS=-Werror \
-DPHYSIM_CHECK_FILES="ThresholdsCuda.cmake" \
-DENABLE_CHANNEL_SIM_CUDA=ON \
-DCUDA_ENABLE=ON \
-DUSE_UNIFIED_MEMORY=ON \
-DUSE_ATS_MEMORY=OFF \
-DCMAKE_RUNTIME_OUTPUT_DIRECTORY=/oai-ran/cmake_targets/ran_build/build \

View File

@@ -22,4 +22,4 @@ WORKDIR /oai-ran
COPY . .
WORKDIR /oai-ran/build
RUN cmake -GNinja -DENABLE_TESTS=ON -DENABLE_CHANNEL_SIM_CUDA=ON .. && ninja tests
RUN cmake -GNinja -DENABLE_TESTS=ON -DCUDA_ENABLE=ON .. && ninja tests

View File

@@ -28,15 +28,16 @@ def GenericHelp(vers):
print(' images are available locally, will not remove any images and will run inside the current repo directory')
def GitSrvHelp(repository,branch,commit,mergeallow,targetbranch):
print(' --repository=[OAI RAN Repository URL] -- ' + repository)
print(' --branch=[OAI RAN Repository Branch] -- ' + branch)
print(' --commitID=[OAI RAN Repository Commit SHA-1] -- ' + commit)
print(' --ranRepository=[OAI RAN Repository URL] -- ' + repository)
print(' --ranBranch=[OAI RAN Repository Branch] -- ' + branch)
print(' --ranCommitID=[OAI RAN Repository Commit SHA-1] -- ' + commit)
print(' --ranAllowMerge=[Allow Merge Request (with target branch) (true or false)] -- ' + mergeallow)
print(' --targetBranch=[Target Branch in case of a Merge Request] -- ' + targetbranch)
print(' --ranTargetBranch=[Target Branch in case of a Merge Request] -- ' + targetbranch)
def SrvHelp(sourcepath):
print(' --workspace=[directory for workspaces on remote hosts] -- ' + sourcepath)
def eNBSrvHelp(sourcepath):
print(' --eNBSourceCodePath=[eNB\'s Source Code Path] -- ' + sourcepath)
def XmlHelp(filename):
print(' --XMLTestFile=[XML Test File to be run] -- ' + filename)
print(' Note: multiple xml files can be specified (--XMLFile=File1 ... --XMLTestFile=FileN) when HTML headers are created ("InitiateHtml" mode)')

View File

@@ -148,7 +148,7 @@ def ExecuteActionWithParam(action, ctx, node):
elif action == 'Deploy_Run_OC_PhySim':
oc_release = test.findtext('oc_release')
script = "scripts/oc-deploy-physims.sh"
image_tag = CLUSTER.branch
image_tag = cls_containerize.CreateTag(CLUSTER.commitID, CLUSTER.branch, CLUSTER.merge)
options = f"oaicicd-core-for-ci-ran {oc_release} {image_tag} {CLUSTER.workspace}"
workdir = CLUSTER.workspace
success = cls_oaicitest.Deploy_Physim(ctx, HTML, node, workdir, script, options)
@@ -169,7 +169,7 @@ def ExecuteActionWithParam(action, ctx, node):
CONTAINERS.yamlPath = test.findtext('yaml_path')
CONTAINERS.services = test.findtext('services')
CONTAINERS.num_attempts = int(test.findtext('num_attempts') or 1)
CONTAINERS.deploymentTag = CONTAINERS.branch
CONTAINERS.deploymentTag = cls_containerize.CreateTag(CONTAINERS.commitID, CONTAINERS.branch, CONTAINERS.merge)
if action == 'Deploy_Object':
success = CONTAINERS.DeployObject(ctx, node, HTML)
elif action == 'Stop_Object':
@@ -368,9 +368,9 @@ elif re.match('^TesteNB$', mode, re.IGNORECASE) or re.match('^TestUE$', mode, re
if RAN.repository == '' or RAN.branch == '' or RAN.workspace == '':
HELP.GenericHelp(CONST.Version)
if RAN.repository == '':
HELP.GitSrvHelp(RAN.repository, RAN.branch, RAN.merge, RAN.targetBranch)
HELP.GitSrvHelp(RAN.repository, RAN.branch, RAN.commitID, RAN.merge, RAN.targetBranch)
if RAN.workspace == '':
HELP.SrvHelp(RAN.workspace)
HELP.eNBSrvHelp(RAN.workspace)
sys.exit('Insufficient Parameter')
else:
if CiTestObj.repository == '' or CiTestObj.branch == '':

View File

@@ -35,6 +35,7 @@ class RANManagement():
self.repository = ''
self.branch = ''
self.merge = False
self.commitID = ''
self.targetBranch = ''
self.workspace = ''
self.Initialize_eNB_args = ''

View File

@@ -30,13 +30,15 @@ docker tag oai-nr-ue oai-ci/oai-nr-ue:develop-${SHORT_COMMIT_SHA}
docker tag oai-gnb oai-ci/oai-gnb:develop-${SHORT_COMMIT_SHA}
docker tag oai-nr-cuup oai-ci/oai-nr-cuup:develop-${SHORT_COMMIT_SHA}
python3 main.py --mode=InitiateHtml --repository=NONE --branch=${CURRENT_BRANCH} \
python3 main.py --mode=InitiateHtml --ranRepository=NONE --ranBranch=${CURRENT_BRANCH} \
--ranCommitID=${COMMIT_SHA} --ranAllowMerge=false \
--ranTargetBranch=NONE \
--XMLTestFile=xml_files/${TESTCASE} --local --datefmt="%H:%M:%S"
python3 main.py --mode=TesteNB --repository=NONE --branch=${CURRENT_BRANCH} \
--ranAllowMerge=false \
--targetBranch=NONE \
--workspace=${REPO_PATH} \
python3 main.py --mode=TesteNB --ranRepository=NONE --ranBranch=${CURRENT_BRANCH} \
--ranCommitID=${COMMIT_SHA} --ranAllowMerge=false \
--ranTargetBranch=NONE \
--eNBSourceCodePath=${REPO_PATH} \
--XMLTestFile=${TESTCASE} --local --datefmt="%H:%M:%S"
RET=$?

View File

@@ -6,16 +6,22 @@ function die() {
exit 1
}
[ $# -eq 3 ] || die "usage: $0 <directory> <repository> <branch>"
[ $# -ge 3 -a $# -le 4 ] || die "usage: $0 <directory> <repository> <ref> [<merge-ref>]"
set -ex
dir=$1
repo=$2
branch=$3
ref=$3
merge=$4
rm -rf ${dir}
git clone --depth=1 --branch "${branch}" "${repo}" "${dir}"
git clone --filter=blob:none -n ${repo} ${dir}
cd ${dir}
git config user.email "jenkins@openairinterface.org"
git config user.name "OAI Jenkins"
git config advice.detachedHead false
mkdir -p cmake_targets/log
git checkout -f ${ref}
[ -n "${merge}" ] && git fetch origin ${merge} && git merge --ff FETCH_HEAD -m "Temporary merge for CI"
exit 0

View File

@@ -43,6 +43,7 @@ class TestDeploymentMethods(unittest.TestCase):
self.cont.yamlPath = ''
self.cont.merge = True
self.cont.branch = ''
self.cont.commitID = ''
self.cont.workspace = os.getcwd()
self.cont.num_attempts = 3
self.node = 'localhost'
@@ -137,6 +138,7 @@ class TestDeploymentMethods(unittest.TestCase):
def test_create_workspace(self):
self.cont.workspace = tempfile.mkdtemp()
self.cont.repository = "https://gitlab.eurecom.fr/oai/openairinterface5g.git"
self.cont.commitID = "05f9c975eeecbca1bdff5940affad44465f1301f"
self.cont.branch = "develop"
ws = self.cont.Create_Workspace(self.node, self.html)
with cls_cmd.LocalCmd() as cmd:

View File

@@ -9,17 +9,21 @@ rm -f ${file}
cd ../../
python3 main.py \
--mode=InitiateHtml \
--repository=https://gitlab.eurecom.fr/oai/openairinterface5g.git \
--branch=${branch} \
--ranRepository=https://gitlab.eurecom.fr/oai/openairinterface5g.git \
--ranBranch=${branch} \
--ranCommitID=${commit} \
--ranAllowMerge=true \
--ranTargetBranch=develop \
--XMLTestFile=tests/test-runner/test.xml
python3 main.py \
--mode=TesteNB \
--repository=https://gitlab.eurecom.fr/oai/openairinterface5g.git \
--branch=${branch} \
--ranRepository=https://gitlab.eurecom.fr/oai/openairinterface5g.git \
--ranBranch=${branch} \
--ranCommitID=${commit} \
--ranAllowMerge=true \
--targetBranch=develop \
--workspace=NONE \
--ranTargetBranch=develop \
--eNBSourceCodePath=NONE \
--XMLTestFile=tests/test-runner/test.xml
python3 main.py \

View File

@@ -7,7 +7,7 @@
<testCase>
<class>Create_Workspace</class>
<desc>Create new Workspace</desc>
<desc>Create new Workspace for server 0</desc>
<node>obelix</node>
</testCase>

View File

@@ -7,7 +7,7 @@
<testCase>
<class>Create_Workspace</class>
<desc>Create new Workspace</desc>
<desc>Create new Workspace for server 0</desc>
<node>gracehopper3-oai</node>
</testCase>

View File

@@ -7,7 +7,7 @@
<testCase>
<class>Create_Workspace</class>
<desc>Create new Workspace</desc>
<desc>Create new Workspace for server 0</desc>
<node>jetson3-oai</node>
</testCase>

View File

@@ -34,7 +34,7 @@
<testCase>
<class>Create_Workspace</class>
<desc>Create new Workspace</desc>
<desc>Create new Workspace for server 0</desc>
<node>hutch</node>
</testCase>

View File

@@ -34,7 +34,7 @@
<testCase>
<class>Create_Workspace</class>
<desc>Create new Workspace</desc>
<desc>Create new Workspace for server 0</desc>
<node>hutch</node>
</testCase>

View File

@@ -27,7 +27,7 @@
<testCase>
<class>Create_Workspace</class>
<desc>Create new Workspace</desc>
<desc>Create new Workspace for server 0</desc>
<node>hutch</node>
</testCase>

View File

@@ -27,7 +27,7 @@
<testCase>
<class>Create_Workspace</class>
<desc>Create new Workspace</desc>
<desc>Create new Workspace for server 0</desc>
<node>hutch</node>
</testCase>

View File

@@ -27,7 +27,7 @@
<testCase>
<class>Create_Workspace</class>
<desc>Create new Workspace</desc>
<desc>Create new Workspace for server 0</desc>
<node>hutch</node>
</testCase>

View File

@@ -35,7 +35,7 @@
<testCase>
<class>Create_Workspace</class>
<desc>Create new Workspace</desc>
<desc>Create new Workspace for server 0</desc>
<node>hutch</node>
</testCase>
@@ -54,7 +54,7 @@
<testCase>
<class>Create_Workspace</class>
<desc>Create new Workspace</desc>
<desc>Create new Workspace for server 1</desc>
<node>carabe</node>
</testCase>

View File

@@ -27,7 +27,7 @@
<testCase>
<class>Create_Workspace</class>
<desc>Create new Workspace</desc>
<desc>Create new Workspace for server 0</desc>
<node>hutch</node>
</testCase>

View File

@@ -34,7 +34,7 @@
<testCase>
<class>Create_Workspace</class>
<desc>Create new Workspace</desc>
<desc>Create new Workspace for server 0</desc>
<node>starsky</node>
</testCase>

View File

@@ -28,7 +28,7 @@
<testCase>
<class>Create_Workspace</class>
<desc>Create new Workspace</desc>
<desc>Create new Workspace for server 0</desc>
<node>starsky</node>
</testCase>

View File

@@ -27,7 +27,7 @@
<testCase>
<class>Create_Workspace</class>
<desc>Create new Workspace</desc>
<desc>Create new Workspace for server 0</desc>
<node>starsky</node>
</testCase>

View File

@@ -27,7 +27,7 @@
<testCase>
<class>Create_Workspace</class>
<desc>Create new Workspace</desc>
<desc>Create new Workspace for server 0</desc>
<node>starsky</node>
</testCase>

View File

@@ -27,7 +27,7 @@
<testCase>
<class>Create_Workspace</class>
<desc>Create new Workspace</desc>
<desc>Create new Workspace for server 0</desc>
<node>starsky</node>
</testCase>

View File

@@ -31,7 +31,7 @@
<testCase>
<class>Create_Workspace</class>
<desc>Create new Workspace</desc>
<desc>Create new Workspace for server 0</desc>
<node>gracehopper1-oai</node>
</testCase>

View File

@@ -31,7 +31,7 @@
<testCase>
<class>Create_Workspace</class>
<desc>Create new Workspace</desc>
<desc>Create new Workspace for server 0</desc>
<node>gracehopper1-oai</node>
</testCase>

View File

@@ -27,7 +27,7 @@
<testCase>
<class>Create_Workspace</class>
<desc>Create new Workspace</desc>
<desc>Create new Workspace for server 0</desc>
<node>ofqot</node>
</testCase>

View File

@@ -33,7 +33,7 @@
<testCase>
<class>Create_Workspace</class>
<desc>Create new Workspace</desc>
<desc>Create new Workspace for server 0</desc>
<node>cacofonix</node>
</testCase>

View File

@@ -33,7 +33,7 @@
<testCase>
<class>Create_Workspace</class>
<desc>Create new Workspace</desc>
<desc>Create new Workspace for server 0</desc>
<node>cacofonix</node>
</testCase>

View File

@@ -28,7 +28,7 @@
<testCase>
<class>Create_Workspace</class>
<desc>Create new Workspace</desc>
<desc>Create new Workspace for server 0</desc>
<node>cacofonix</node>
</testCase>

View File

@@ -0,0 +1,85 @@
<!-- SPDX-License-Identifier: LicenseRef-CSSL-1.0 -->
<testCaseList>
<htmlTabRef>monolithic_2step_ra_gnb_rfsim</htmlTabRef>
<htmlTabName>Monolithic 2-Step RA gNB rfsim</htmlTabName>
<htmlTabIcon>wrench</htmlTabIcon>
<testCase>
<class>Pull_Local_Registry</class>
<desc>Pull Images from Local Registry</desc>
<node>localhost</node>
<images>oai-gnb-asan oai-nr-ue-asan</images>
</testCase>
<testCase>
<class>Create_Workspace</class>
<desc>Create new Workspace</desc>
<node>localhost</node>
</testCase>
<testCase>
<class>Deploy_Object</class>
<desc>Deploy OAI gNB</desc>
<node>localhost</node>
<yaml_path>ci-scripts/yaml_files/monolithic_2step_ra_gnb_rfsim</yaml_path>
<services>mysql oai-amf oai-smf oai-upf oai-ext-dn</services>
</testCase>
<testCase>
<class>Deploy_Object</class>
<desc>Deploy OAI NR-UE</desc>
<node>localhost</node>
<yaml_path>ci-scripts/yaml_files/monolithic_2step_ra_gnb_rfsim</yaml_path>
<services>oai-gnb oai-nr-ue</services>
</testCase>
<testCase>
<class>Attach_UE</class>
<desc>Attach OAI UE (Wait for IP)</desc>
<id>rfsim5g_ue</id>
<node>localhost</node>
</testCase>
<testCase>
<class>Ping</class>
<desc>Ping ext-dn from NR-UE</desc>
<id>rfsim5g_ue</id>
<node>localhost</node>
<svr_id>rfsim5g_ext_dn</svr_id>
<svr_node>localhost</svr_node>
<ping_args>-c 20 -i0.2</ping_args>
<ping_packetloss_threshold>0</ping_packetloss_threshold>
</testCase>
<testCase>
<class>Ping</class>
<desc>Ping NR-UE from ext-dn</desc>
<id>rfsim5g_ext_dn</id>
<node>localhost</node>
<svr_id>rfsim5g_ue</svr_id>
<svr_node>localhost</svr_node>
<ping_args>-c 20 -i0.2</ping_args>
<ping_packetloss_threshold>0</ping_packetloss_threshold>
</testCase>
<testCase>
<class>Undeploy_Object</class>
<always_exec>true</always_exec>
<desc>Undeploy all OAI 5G stack</desc>
<node>localhost</node>
<yaml_path>ci-scripts/yaml_files/monolithic_2step_ra_gnb_rfsim</yaml_path>
<analysis>
<services>oai-gnb=RetxCheck=10,0,0,0 oai-gnb=EndsWithBye oai-nr-ue</services>
</analysis>
</testCase>
<testCase>
<class>Clean_Test_Server_Images</class>
<always_exec>true</always_exec>
<desc>Clean Test Images on Test Server</desc>
<node>localhost</node>
<images>oai-gnb-asan oai-nr-ue-asan</images>
</testCase>
</testCaseList>

View File

@@ -97,7 +97,7 @@ services:
cap_drop:
- ALL
environment:
USE_ADDITIONAL_OPTIONS: -E --log_config.global_log_options level,nocolor,time --device.name vrtsim --vrtsim.role server --vrtsim.chanmod 1 --vrtsim.num_ues 1
USE_ADDITIONAL_OPTIONS: -E --log_config.global_log_options level,nocolor,time --device.name vrtsim --vrtsim.role server --vrtsim.chanmod 1
depends_on:
- oai-ext-dn
networks:
@@ -123,7 +123,7 @@ services:
- NET_ADMIN # for interface bringup
- NET_RAW # for ping
environment:
USE_ADDITIONAL_OPTIONS: -E -r 106 --numerology 1 --band 78 -C 3619200000 --ssb 516 --uicc0.imsi 208990100001100 --log_config.global_log_options level,nocolor,time --device.name vrtsim --ue-nb-ant-rx 2 --ue-nb-ant-tx 2
USE_ADDITIONAL_OPTIONS: -E -r 106 --numerology 1 --band 78 -C 3619200000 --ssb 516 --uicc0.imsi 208990100001100 --log_config.global_log_options level,nocolor,time --device.name vrtsim
depends_on:
- oai-gnb
networks:

View File

@@ -111,7 +111,7 @@ services:
cap_drop:
- ALL
environment:
USE_ADDITIONAL_OPTIONS: -E --log_config.global_log_options level,nocolor,time --device.name vrtsim --vrtsim.role server --vrtsim.cirdb 1 --vrtsim.num_ues 1
USE_ADDITIONAL_OPTIONS: -E --log_config.global_log_options level,nocolor,time --device.name vrtsim --vrtsim.role server --vrtsim.cirdb 1 --vrtsim.cirdb_file /cirdb/cir_db.bin --vrtsim.cirdb_yaml /cirdb/cir_db.yaml --vrtsim.cirdb_model_id 0 --vrtsim.cirdb_ds_ns 1 --vrtsim.cirdb_speed_mps 1.5
depends_on:
cir-generator:
condition: service_completed_successfully
@@ -142,7 +142,7 @@ services:
- NET_ADMIN
- NET_RAW
environment:
USE_ADDITIONAL_OPTIONS: -E -r 106 --numerology 1 --band 78 -C 3619200000 --ssb 516 --uicc0.imsi 208990100001100 --log_config.global_log_options level,nocolor,time --device.name vrtsim --vrtsim.role client --ue-nb-ant-rx 2 --ue-nb-ant-tx 2
USE_ADDITIONAL_OPTIONS: -E -r 106 --numerology 1 --band 78 -C 3619200000 --ssb 516 --uicc0.imsi 208990100001100 --log_config.global_log_options level,nocolor,time --device.name vrtsim --vrtsim.role client
depends_on:
- oai-gnb
networks:

View File

@@ -111,7 +111,7 @@ services:
cap_drop:
- ALL
environment:
USE_ADDITIONAL_OPTIONS: -E --log_config.global_log_options level,nocolor,time --device.name vrtsim --vrtsim.role server --vrtsim.cirdb 1 --vrtsim.num_ues 2 --gNBs.[0].min_rxtxtime 8
USE_ADDITIONAL_OPTIONS: -E --log_config.global_log_options level,nocolor,time --device.name vrtsim --vrtsim.role server --vrtsim.num_ues 2 --vrtsim.cirdb 1 --vrtsim.cirdb_file /cirdb/cir_db.bin --vrtsim.cirdb_yaml /cirdb/cir_db.yaml --vrtsim.ue_config.[0].antennas 1x2 --vrtsim.ue_config.[0].model_id 0 --vrtsim.ue_config.[0].ds_ns 10.0 --vrtsim.ue_config.[0].speed_mps 1.5 --vrtsim.ue_config.[1].antennas 2x2 --vrtsim.ue_config.[1].model_id 1 --vrtsim.ue_config.[1].ds_ns 10.0 --vrtsim.ue_config.[1].speed_mps 1.5 --gNBs.[0].min_rxtxtime 8
depends_on:
cir-generator:
condition: service_completed_successfully
@@ -142,7 +142,7 @@ services:
- NET_ADMIN
- NET_RAW
environment:
USE_ADDITIONAL_OPTIONS: -E -r 106 --numerology 1 --band 78 -C 3319680000 --ssb 516 --uicc0.imsi 208990100001100 --log_config.global_log_options level,nocolor,time --device.name vrtsim --vrtsim.role client --vrtsim.ue_id 0 --ue-nb-ant-tx 2 --ue-nb-ant-rx 2
USE_ADDITIONAL_OPTIONS: -E -r 106 --numerology 1 --band 78 -C 3319680000 --ssb 516 --uicc0.imsi 208990100001100 --log_config.global_log_options level,nocolor,time --device.name vrtsim --vrtsim.role client --vrtsim.ue_id 0 --ue-nb-ant-tx 1 --ue-nb-ant-rx 2
depends_on:
- oai-gnb
networks:
@@ -171,7 +171,7 @@ services:
- NET_ADMIN
- NET_RAW
environment:
USE_ADDITIONAL_OPTIONS: -E -r 106 --numerology 1 --band 78 -C 3319680000 --ssb 516 --uicc0.imsi 208990100001101 --log_config.global_log_options level,nocolor,time --device.name vrtsim --vrtsim.role client --vrtsim.ue_id 1 --ue-nb-ant-tx 1 --ue-nb-ant-rx 2
USE_ADDITIONAL_OPTIONS: -E -r 106 --numerology 1 --band 78 -C 3319680000 --ssb 516 --uicc0.imsi 208990100001101 --log_config.global_log_options level,nocolor,time --device.name vrtsim --vrtsim.role client --vrtsim.ue_id 1 --ue-nb-ant-tx 2 --ue-nb-ant-rx 2
depends_on:
- oai-gnb
networks:

View File

@@ -0,0 +1,162 @@
# SPDX-License-Identifier: MIT
services:
mysql:
container_name: "rfsim5g-mysql"
image: mysql:9.6
init: true
volumes:
- ../5g_rfsimulator/oai_db.sql:/docker-entrypoint-initdb.d/oai_db.sql
- ../5g_rfsimulator/mysql-healthcheck.sh:/tmp/mysql-healthcheck.sh
environment:
- TZ=Europe/Paris
- MYSQL_DATABASE=oai_db
- MYSQL_USER=test
- MYSQL_PASSWORD=test
- MYSQL_ROOT_PASSWORD=linux
healthcheck:
test: /bin/bash -c "/tmp/mysql-healthcheck.sh"
start_period: 10s
start_interval: 500ms
interval: 10s
timeout: 5s
retries: 30
networks:
public_net:
ipv4_address: 192.168.71.131
oai-amf:
container_name: "rfsim5g-oai-amf"
image: oaisoftwarealliance/oai-amf:v2.2.1
environment:
- TZ=Europe/paris
volumes:
- ../5g_rfsimulator/mini_nonrf_config.yaml:/openair-amf/etc/config.yaml
depends_on:
- mysql
networks:
public_net:
ipv4_address: 192.168.71.132
oai-smf:
container_name: "rfsim5g-oai-smf"
image: oaisoftwarealliance/oai-smf:v2.2.1
environment:
- TZ=Europe/Paris
volumes:
- ../5g_rfsimulator/mini_nonrf_config.yaml:/openair-smf/etc/config.yaml
depends_on:
- oai-amf
networks:
public_net:
ipv4_address: 192.168.71.133
oai-upf:
container_name: "rfsim5g-oai-upf"
image: oaisoftwarealliance/oai-upf:v2.2.1
init: true
environment:
- TZ=Europe/Paris
volumes:
- ../5g_rfsimulator/mini_nonrf_config.yaml:/openair-upf/etc/config.yaml
depends_on:
- oai-smf
cap_add:
- NET_ADMIN
- SYS_ADMIN
cap_drop:
- ALL
privileged: true
networks:
public_net:
ipv4_address: 192.168.71.134
interface_name: eth0
traffic_net:
ipv4_address: 192.168.72.134
interface_name: eth1
oai-ext-dn:
privileged: true
container_name: rfsim5g-oai-ext-dn
image: oaisoftwarealliance/trf-gen-cn5g:latest
init: true
entrypoint: /bin/bash -c \
"iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE;"\
"ip route add 12.1.1.0/24 via 192.168.72.134 dev eth0; sleep infinity"
depends_on:
- oai-upf
networks:
traffic_net:
ipv4_address: 192.168.72.135
healthcheck:
test: /bin/bash -c "ping -c 2 192.168.72.134"
start_period: 10s
start_interval: 500ms
interval: 10s
timeout: 5s
retries: 5
oai-gnb:
image: ${REGISTRY-oaisoftwarealliance/}${GNB_IMG:-oai-gnb}:${TAG:-develop}
container_name: rfsim5g-oai-gnb
cap_drop:
- ALL
environment:
USE_ADDITIONAL_OPTIONS: --rfsim --log_config.global_log_options level,nocolor,time
ASAN_OPTIONS: detect_leaks=0
networks:
public_net:
ipv4_address: 192.168.71.140
volumes:
- ../../conf_files/gnb.sa.band78.106prb.usrpb210.RA_2-Step.conf:/opt/oai-gnb/etc/gnb.conf
healthcheck:
test: /bin/bash -c "pgrep nr-softmodem"
start_period: 10s
start_interval: 500ms
interval: 10s
timeout: 5s
retries: 5
oai-nr-ue:
image: ${REGISTRY-oaisoftwarealliance/}${NRUE_IMG:-oai-nr-ue}:${TAG:-develop}
container_name: rfsim5g-oai-nr-ue
cap_drop:
- ALL
cap_add:
- NET_ADMIN # for interface bringup
- NET_RAW # for ping
environment:
USE_ADDITIONAL_OPTIONS: --rfsim
--rfsimulator.[0].serveraddr 192.168.71.140 --log_config.global_log_options level,nocolor,time
-C 3619200000 -r 106 --numerology 1 --ssb 516 --band 78
ASAN_OPTIONS: detect_leaks=0
devices:
- /dev/net/tun:/dev/net/tun
volumes:
- ../../conf_files/nrue.uicc.conf:/opt/oai-nr-ue/etc/nr-ue.conf
depends_on:
- oai-gnb
networks:
public_net:
ipv4_address: 192.168.71.150
healthcheck:
test: /bin/bash -c "pgrep nr-uesoftmodem"
start_period: 10s
start_interval: 500ms
interval: 10s
timeout: 5s
retries: 5
networks:
public_net:
driver: bridge
name: rfsim5g-oai-public-net
ipam:
config:
- subnet: 192.168.71.128/26
driver_opts:
com.docker.network.bridge.name: "rfsim5g-public"
traffic_net:
driver: bridge
name: rfsim5g-oai-traffic-net
ipam:
config:
- subnet: 192.168.72.128/26
driver_opts:
com.docker.network.bridge.name: "rfsim5g-traffic"

View File

@@ -88,85 +88,3 @@ function(run_asn1c ASN1C_GRAMMAR ASN1C_PREFIX)
COMMENT "Generating ${ASN1C_COMMENT} from ${GRAMMAR_FILE}"
)
endfunction()
define_property(TEST PROPERTY TEST_DESCRIPTION
BRIEF_DOCS "A human-readable description of this test"
FULL_DOCS "A human-readable description of this test")
define_property(TEST PROPERTY CHECK_COUNT
BRIEF_DOCS "helper property to enumerate checks in environment"
FULL_DOCS "the property counts the number of threshold checks, used to enumerate environment variables given to analyze-timing.sh")
function(add_physim_test test_name test_description test_exec)
# catch all the arguments past the last expected arqument and store them in the options_list
if (NOT TARGET ${test_exec})
message(FATAL_ERROR "test executable ${test_exec} is not an executable")
endif()
set(test_invocation $<TARGET_FILE:${test_exec}> ${ARGN})
add_test(
NAME ${test_name}
COMMAND ${CMAKE_COMMAND}
"-DTEST_CMD=${test_invocation}"
"-DCHECK_SCRIPT=${CMAKE_SOURCE_DIR}/openair1/SIMULATION/tests/analyze-timing.sh"
-P ${CMAKE_SOURCE_DIR}/openair1/SIMULATION/tests/RunTimedTest.cmake
)
set_tests_properties(${test_name} PROPERTIES
LABELS "${test_exec}"
TEST_DESCRIPTION "${test_description}"
# pass test description also through environment variable: for cmake < 3.30,
# in JSON export, we cannot recover the description otherwise
# see also https://gitlab.kitware.com/cmake/cmake/-/issues/21490
ENVIRONMENT "LD_LIBRARY_PATH=${CMAKE_BINARY_DIR};TEST_DESCRIPTION=${test_description}"
)
set_tests_properties(${test_name} PROPERTIES CHECK_COUNT 0)
add_dependencies(tests ${test_exec})
endfunction()
function(check_threshold testname threshold condition)
# check that threshold and condition don't have a colon (;), because that
# would interfere with cmake's list management
string(FIND "${threshold}" ";" pos)
if (pos GREATER -1)
message(FATAL_ERROR "colon not allowed in threshold, but have \"${threshold}\"")
endif()
string(FIND "${condition}" ";" pos)
if (pos GREATER -1)
message(FATAL_ERROR "colon not allowed in condition, but have \"${condition}\"")
endif()
set(THRCOND "${threshold}\;${condition}")
get_test_property(${testname} CHECK_COUNT count)
#message(STATUS "add check ${count} ${THRCOND}")
if (${count} GREATER 10)
message(FATAL_ERROR "only maximum of 10 checks per test allowed")
endif()
# add a new environment variable CHECK_X with this threshold+condition, then
# increase test property regarding check count
set_property(TEST ${testname} APPEND PROPERTY ENVIRONMENT "CHECK_${count}=${THRCOND}")
MATH(EXPR count "${count}+1")
set_tests_properties(${testname} PROPERTIES CHECK_COUNT ${count})
endfunction()
function(check_threshold_range testname threshold)
cmake_parse_arguments(RANGE "" "LOWER;UPPER" "" ${ARGN})
if (NOT RANGE_LOWER AND NOT RANGE_UPPER)
message(FATAL_ERROR "need at least one LOWER or one UPPER threshold")
endif()
if (RANGE_LOWER)
check_threshold(${testname} ${threshold} "> ${RANGE_LOWER}")
endif()
if (RANGE_UPPER)
check_threshold(${testname} ${threshold} "< ${RANGE_UPPER}")
endif()
endfunction()
function(check_threshold_variance testname threshold)
cmake_parse_arguments(VARIANCE "" "AVG;ABS_VAR" "" ${ARGN})
if (NOT VARIANCE_AVG AND NOT VARIANCE_ABS_VAR)
message(FATAL_ERROR "need both AVG and ABS_VAR")
endif()
MATH(EXPR upper "${VARIANCE_AVG}+${VARIANCE_ABS_VAR}")
MATH(EXPR lower "${VARIANCE_AVG}-${VARIANCE_ABS_VAR}")
check_threshold_range(${testname} ${threshold} LOWER ${lower} UPPER ${upper})
endfunction()

View File

@@ -83,13 +83,11 @@ get_distribution_release() {
check_supported_distribution() {
local distribution=$(get_distribution_release)
case "$distribution" in
"ubuntu26.04") return 0 ;;
"ubuntu24.04") return 0 ;;
"ubuntu22.04") return 0 ;;
"debian11") return 0 ;;
"debian12") return 0 ;;
"fedora43") return 0 ;;
"fedora44") return 0 ;;
"rhel9.0") return 0 ;;
"rhel9.1") return 0 ;;
"rhel9.2") return 0 ;;
@@ -98,7 +96,6 @@ check_supported_distribution() {
"rhel9.5") return 0 ;;
"rhel9.6") return 0 ;;
"rhel9.7") return 0 ;;
"rhel9.8") return 0 ;;
"centos9") return 0 ;; # CentOS stream
"rocky9.1") return 0 ;;
"rocky9.2") return 0 ;;
@@ -107,7 +104,6 @@ check_supported_distribution() {
"rocky9.5") return 0 ;;
"rocky9.6") return 0 ;;
"rocky9.7") return 0 ;;
"rocky9.8") return 0 ;;
esac
return 1
}
@@ -145,8 +141,12 @@ install_usrp_uhd_driver_from_source(){
# - 3.15.0.0
git apply $OPENAIR_DIR/cmake_targets/tools/uhd-3.15-tdd-patch.diff
ret=$?;[[ $ret -ne 0 ]] && echo_fatal "Could not apply the TDD patch"
elif [[ "$UHD_VERSION" == "4.10.0.0" || "$UHD_VERSION" == "4.9.0.0" || "$UHD_VERSION" == "4.8.0.0" || "$UHD_VERSION" == "4.7.0.0" || "$UHD_VERSION" == "4.6.0.0" || "$UHD_VERSION" == "4.5.0.0" ]]; then
# Tested patch for versions listed in elif clause
elif [[ "$UHD_VERSION" == "4.8.0.0" || "$UHD_VERSION" == "4.7.0.0" || "$UHD_VERSION" == "4.6.0.0" || "$UHD_VERSION" == "4.5.0.0" ]]; then
# Tested that patch for the following versions:
# - 4.7.0.0
cp $OPENAIR_DIR/cmake_targets/tools/uhd-4.x-tdd-patch.diff $OPENAIR_DIR/cmake_targets/tools/uhd-4.5plus-tdd-patch.diff
sed -i '9,13 s/STATE_OFF/STATE_RX1_OFF/' $OPENAIR_DIR/cmake_targets/tools/uhd-4.5plus-tdd-patch.diff
sed -i '24,28 s/STATE_OFF/STATE_RX2_OFF/' $OPENAIR_DIR/cmake_targets/tools/uhd-4.5plus-tdd-patch.diff
git apply $OPENAIR_DIR/cmake_targets/tools/uhd-4.5plus-tdd-patch.diff
ret=$?;[[ $ret -ne 0 ]] && echo_fatal "Could not apply the TDD patch"
else
@@ -162,8 +162,8 @@ install_usrp_uhd_driver_from_source(){
ret=$?;[[ $ret -ne 0 ]] && echo_fatal "Could not apply the TDD patch"
fi
else
git checkout tags/v4.8.0.0
git apply $OPENAIR_DIR/cmake_targets/tools/uhd-4.5plus-tdd-patch.diff
git checkout tags/v4.0.0.0
git apply $OPENAIR_DIR/cmake_targets/tools/uhd-4.x-tdd-patch.diff
ret=$?;[[ $ret -ne 0 ]] && echo_fatal "Could not apply the TDD patch"
fi
# Printing out the results of the patch to make sure it was properly applied
@@ -199,14 +199,29 @@ check_install_usrp_uhd_driver(){
install_usrp_uhd_driver_from_source
return
fi
# The new USRP repository
# Raphael Defosseux: Adding a loop on adding PPA because in CI the gpg key retrieve may
# timeout due to proxy / network latencies in Eurecom on VM
echo_info "\nAdding PPA repository ettusresearch/uhd\n"
$SUDO add-apt-repository ppa:ettusresearch/uhd -y
x=0
while [ $x -le 5 ]
do
if $SUDO add-apt-repository ppa:ettusresearch/uhd -y
then
echo_info "add-apt-repository successful\n"
break
else
echo_info "add-apt-repository failed, retrying...\n"
sleep 30
fi
x=$((x + 1))
done
$SUDO apt-get update
$SUDO apt-get -y install python3-tk $boost_libs_ubuntu libusb-1.0-0-dev
case "$(get_distribution_release)" in
"ubuntu22.04") $SUDO apt-get -y install libuhd-dev libuhd4.5.0 uhd-host ;;
"ubuntu24.04") $SUDO apt-get -y install libuhd-dev libuhd4.8.0 uhd-host ;;
"ubuntu26.04") $SUDO apt-get -y install libuhd-dev libuhd4.9.0 uhd-host ;;
"ubuntu22.04")
$SUDO apt-get -y install libuhd-dev libuhd4.5.0 uhd-host
;;
esac
elif [[ "$OS_BASEDISTRO" == "fedora" ]]; then
boost_libs_fedora="boost-chrono boost-date-time boost-filesystem boost-program-options boost-thread boost-test boost-regex boost-devel"

View File

@@ -1,34 +0,0 @@
diff --git a/host/lib/usrp/b200/b200_impl.cpp b/host/lib/usrp/b200/b200_impl.cpp
index 6de161e87..432af5784 100644
--- a/host/lib/usrp/b200/b200_impl.cpp
+++ b/host/lib/usrp/b200/b200_impl.cpp
@@ -1410,10 +1410,10 @@ void b200_impl::update_atrs(void)
if (not enb_rx and enb_tx)
fd = txonly;
gpio_atr_3000::sptr atr = perif.atr;
- atr->set_atr_reg(ATR_REG_IDLE, STATE_RX1_OFF);
- atr->set_atr_reg(ATR_REG_RX_ONLY, rxonly);
- atr->set_atr_reg(ATR_REG_TX_ONLY, txonly);
- atr->set_atr_reg(ATR_REG_FULL_DUPLEX, fd);
+ atr->set_atr_reg(ATR_REG_IDLE, STATE_RX1_OFF | (1<<7));
+ atr->set_atr_reg(ATR_REG_RX_ONLY, rxonly | (1<<7));
+ atr->set_atr_reg(ATR_REG_TX_ONLY, txonly | (1<<7));
+ atr->set_atr_reg(ATR_REG_FULL_DUPLEX, fd | (1<<7));
}
if (_radio_perifs.size() > _fe2 and _radio_perifs[_fe2].atr) {
radio_perifs_t& perif = _radio_perifs[_fe2];
@@ -1431,10 +1431,10 @@ void b200_impl::update_atrs(void)
if (not enb_rx and enb_tx)
fd = txonly;
gpio_atr_3000::sptr atr = perif.atr;
- atr->set_atr_reg(ATR_REG_IDLE, STATE_RX2_OFF);
- atr->set_atr_reg(ATR_REG_RX_ONLY, rxonly);
- atr->set_atr_reg(ATR_REG_TX_ONLY, txonly);
- atr->set_atr_reg(ATR_REG_FULL_DUPLEX, fd);
+ atr->set_atr_reg(ATR_REG_IDLE, STATE_RX2_OFF | (1<<7));
+ atr->set_atr_reg(ATR_REG_RX_ONLY, rxonly | (1<<7));
+ atr->set_atr_reg(ATR_REG_TX_ONLY, txonly | (1<<7));
+ atr->set_atr_reg(ATR_REG_FULL_DUPLEX, fd | (1<<7));
}
}

View File

@@ -17,6 +17,7 @@
# define NUMBER_OF_SCH_STATS_MAX 16
# ifndef PHYSIM
# ifndef UE_EXPANSION
# define NUMBER_OF_UE_MAX 40
# define NUMBER_OF_CONNECTED_eNB_MAX 1
@@ -26,5 +27,10 @@
# define NUMBER_OF_CONNECTED_eNB_MAX 1
# define NUMBER_OF_CONNECTED_gNB_MAX 1
# endif
# else
# define NUMBER_OF_UE_MAX 4
# define NUMBER_OF_CONNECTED_eNB_MAX 1
# define NUMBER_OF_CONNECTED_gNB_MAX 1
# endif
#endif /* OPENAIRINTERFACE5G_LIMITS_H_ */

View File

@@ -62,7 +62,7 @@ extern "C" {
#endif
#ifndef malloc16
#define malloc16(x) memalign(64, x + 64)
# define malloc16(x) memalign(32,x+32)
#endif
#define free16(y,x) free(y)
#define openair_free(y,x) free((y))
@@ -76,7 +76,7 @@ extern "C" {
} while (0)
static inline void *malloc16_clear( size_t size ) {
void *ptr = memalign(64, size + 64);
void *ptr = memalign(32, size+32);
DevAssert(ptr);
memset( ptr, 0, size );
return ptr;
@@ -110,7 +110,7 @@ static inline void *malloc_or_fail(size_t size)
# define msg(aRGS...) LOG_D(PHY, ##aRGS)
#endif
#ifndef malloc16
#define malloc16(x) memalign(64, x)
# define malloc16(x) memalign(32,x)
#endif
#define free16(y,x) free(y)

View File

@@ -192,7 +192,7 @@ Now, when installing the pre-requisites, especially the `UHD` driver, you can no
```bash
export BUILD_UHD_FROM_SOURCE=True
export UHD_VERSION=4.10.0.0
export UHD_VERSION=3.15.0.0
./build_oai -I -w USRP
```
@@ -206,7 +206,6 @@ See:
* `cmake_targets/tools/uhd-3.15-tdd-patch.diff`
* `cmake_targets/tools/uhd-4.x-tdd-patch.diff`
* `cmake_targets/tools/uhd-4.5plus-tdd-patch.diff`
* `cmake_targets/tools/build_helper` --> function `install_usrp_uhd_driver_from_source`
### Building PHY Simulators

View File

@@ -10,9 +10,7 @@ out the various configuration options that influence its behavior.
The 5G MAC scheduler is a proportional fair (PF) scheduler, "approximating
wide-band CQI" (for lack of a better term, but CQI is typically used for PF)
through the selection of an MCS to use. For a detailed description of the
scheduler pipeline and how to replace individual policies, see
[Scheduler Architecture](scheduler-architecture.md).
through the selection of an MCS to use.
Concretely, the scheduler loops through all UEs and calculates the PF
coefficient using the currently selected MCS, and the historical achieved rate.
@@ -24,13 +22,9 @@ UEs with retransmissions are allocated first; similarly, UEs that have not been
scheduled for some time in UL are scheduled automatically in UL and have
therefore priority over data with "normal" traffic.
The MCS selection is done in `nr_dl_mcs_select_default()` / `nr_ul_mcs_select_default()` in files
[`gNB_scheduler_dlsch_default_policies.c`](../../openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch_default_policies.c)
and
[`gNB_scheduler_ulsch_default_policies.c`](../../openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch_default_policies.c).
The BLER estimation itself is computed separately in `update_bler_stats()` in
[`gNB_scheduler_primitives.c`](../../openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c),
and the MCS policy reads the result. It considers two thresholds for a "BLER" that is computed from the number of
The MCS selection is done in `get_mcs_from_bler()` in file
[`gNB_scheduler_primitives.c`](../../openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c).
It consider two thresholds for a "BLER" that is computed from the number of
first-round retransmissions over total transmissions in the last window (50ms).
If that ratio is higher than an "upper" threshold (see
`dl/ul_bler_target_upper` in the configuration section below), it is
@@ -39,11 +33,11 @@ lower than a "lower" threshold (see `dl/ul_bler_target_lower`), it is
interpreted as "good channel" and MCS is incremented by 1. This happens each
window.
The actual scheduler implementation can be found in functions `nr_dl_proportional_fair()` and
`nr_ul_proportional_fair()` in files
[`gNB_scheduler_dlsch_default_policies.c`](../../openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch_default_policies.c)
The actual scheduler implementation can be found in functions `pf_dl()` and
`pf_ul()` in files
[`gNB_scheduler_dlsch.c`](../../openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c)
(for DL) and
[`gNB_scheduler_ulsch_default_policies.c`](../../openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch_default_policies.c)
[`gNB_scheduler_ulsch.c`](../../openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c)
(for UL), respectively.
## PDCCH aggregation level
@@ -126,8 +120,9 @@ Example:
UE RNTI 2460 CU-UE-ID 2 in-sync PH 28 dB PCMAX 24 dBm, average RSRP -74 (8 meas), average SINR 40.0 (32 meas)
UE 2460: CQI 15, RI 2, PMI (14,1)
UE 2460: UL-RI 2 TPMI 0
UE 2460: dlsch_rounds 32917/5113/1504/560, dlsch_errors 211, pucch0_DTX 1385 (SNR 19.8+0.2 dB), BLER 0.19557 MCS (1) 23 CCE fail 3, goodput 120.50 Mbps
UE 2460: ulsch_rounds 3756/353/182/179, ulsch_errors 170, ulsch_DTX 285, BLER 0.33021 MCS (1) 27 (Qm 8 deltaMCS 0 dB) NPRB 5 SNR 31.0 (-1.0) dB CCE fail 0, goodput 12.30 Mbps
UE 2460: dlsch_rounds 32917/5113/1504/560, dlsch_errors 211, pucch0_DTX 1385 (SNR 19.8+0.2 dB), BLER 0.19557 MCS (1) 23 CCE fail 3
UE 2460: ulsch_rounds 3756/353/182/179, ulsch_errors 170, ulsch_DTX 285, BLER 0.33021 MCS (1) 27 (Qm 8 dB) NPRB 5 SNR 31.0 (-1.0) dB CCE fail 0
UE 2460: MAC: TX 1530943191 RX 194148 bytes
UE 2460: LCID 1: TX 651 RX 3031 bytes
UE 2460: LCID 2: TX 0 RX 0 bytes
UE 2460: LCID 4: TX 1526169592 RX 16152 bytes
@@ -214,11 +209,11 @@ The fourth and fifth line show HARQ-related information:
* Both ULSCH/DLSCH `CCE fail`: lists the number of failed CCE attempts. If this
number gets high, it signifies that the scheduler tried to scheduled this UE,
but could not allocate the DCI.
* Both ULSCH/DLSCH `goodput`: smoothed (EWMA) goodput in Mbps, reflecting the
actual MAC-layer throughput achieved by the UE.
In the last lines:
* `MAC` shows the amount of MAC PDU bytes scheduled in transmit (`TX`,
`1530943191`) and receive (`RX`, `194148`) directions
* `LCID X` shows the amount of MAC SDU/RLC PDU data for Logical Channel ID with
ID `X` in transmit and receive directions. LCIDs 1 and 2 are mapped to SRBs 1
and 2. LCIDs 4 and onward are mapped to DRBs 1 onward. If you have an LCID 4,

View File

@@ -1,433 +0,0 @@
# gNB MAC Scheduler Architecture
## Overview
The gNB MAC scheduler runs once per DL slot. It allocates PDSCH resources for the
current slot and PUSCH resources for a future UL slot (selected via K2), sending the
UL DCI grant in the current DL slot. The DL and UL schedulers follow the same pipeline
design: a fixed orchestration loop calls a sequence of **pluggable function pointers**,
each handling one stage of the scheduling decision. Any stage can be replaced
independently without touching the rest of the pipeline.
Both schedulers send their DCIs in the same DL slot and share the same physical
CORESET/CCE resources. The UL scheduler runs first (`nr_schedule_ulsch` in
`gNB_scheduler.c`), then the DL scheduler (`nr_schedule_ue_spec`). CCEs are claimed on
a first-come basis via `get_cce_index` + `fill_pdcch_vrb_map`, so UL DCIs take
priority. If CCE space is tight, DL UEs are more likely to be skipped. The two
schedulers use separate FAPI containers (`UL_dci_req` for UL grants, `DL_req` for DL
grants) but the underlying CCE map is shared.
All scheduler code lives under `openair2/LAYER2/NR_MAC_gNB/`. The DL scheduler is in
[`gNB_scheduler_dlsch.c`](../../openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c),
the UL scheduler in
[`gNB_scheduler_ulsch.c`](../../openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c),
and shared primitives in
[`gNB_scheduler_primitives.c`](../../openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c).
Data structures and typedefs are in
[`nr_mac_gNB.h`](../../openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h).
Default policy implementations are in
[`gNB_scheduler_dlsch_default_policies.c`](../../openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch_default_policies.c)
and
[`gNB_scheduler_ulsch_default_policies.c`](../../openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch_default_policies.c).
Function pointers are assigned at startup in
[`main.c`](../../openair2/LAYER2/NR_MAC_gNB/main.c).
## Scheduler Pipeline
Both DL and UL follow the same 7-stage pipeline, plus a DL-only 8th stage.
```
DL UL
┌────────────┐ ┌────────────┐
│ 1.Collect │ │ 1.Collect │ ◄── nr_ulsch_preprocessor
│ Candidates │ │ Candidates │ (iterates over
└─────┬──────┘ └─────┬──────┘ reachable UL slots)
│ │
┌─────┴──────┐ ┌─────┴──────┐
│ 2. RI/PMI │ │ 2. RI/TPMI│ ◄─┐
│ Selection │ │ Selection │ │
└─────┬──────┘ └─────┬──────┘ │
│ │ │
┌─────┴──────┐ ┌─────┴──────┐ │
│ 3. Beam │ │ 3. Beam │ │
│ Selection │ │ Selection │ │
└─────┬──────┘ └─────┬──────┘ │
│ │ │ nr_ul_schedule
┌─────┴──────┐ ┌─────┴──────┐ │ (per UL slot)
│ 4. TDA │ │ 4. TDA │ │
│ Selection │ │ Selection │ │
└─────┬──────┘ └─────┬──────┘ │
│ │ │
┌─────┴──────┐ ┌─────┴──────┐ │
│ 5. MCS │ │ 5. MCS │ │
│ Selection │ │ Selection │ │
└─────┬──────┘ └─────┬──────┘ │
│ │ │
┌─────┴──────┐ ┌─────┴──────┐ │
│ 6. RB │ │ 6. RB │ │
│ Allocation │ │ Allocation │ │
│ (per beam) │ │ (per beam) │ │
└─────┬──────┘ └─────┬──────┘ │
│ │ │
┌─────┴──────┐ ┌─────┴──────┐ │
│ 7.Dispatch│ │ 7.Dispatch│ ◄─┘
│ (fixed) │ │ (fixed) │
└─────┬──────┘ └────────────┘
┌─────┴──────┐
│ 8. LCID │ (DL only)
│ Allocation │
└────────────┘
```
### UL preprocessor split
The UL pipeline is split across two functions. The preprocessor
(`nr_ulsch_preprocessor`) runs a loop over **multiple candidate UL slots**: for each DL
slot there may be several reachable UL slots (depending on K2), and the scheduler must
pick one. The loop iterates until the DCI budget is exhausted or no TDA can reach
further UL slots.
**Only step 1 (candidate collection) lives in the preprocessor loop.** Candidates depend
on `sched_frame`/`sched_slot` (e.g. inactivity checks), so they are rebuilt each
iteration. The preprocessor also runs a lightweight TDA reachability gate
(`get_num_ul_tda == 0 → break`) to short-circuit the loop when no TDA can reach the
target slot.
**Steps 27 live in `nr_ul_schedule`**, called once per UL slot with the collected
candidates. `k2` is passed as a parameter for TDA selection. This mirrors the DL
structure where all stages run in a single function.
Beam selection (step 3) runs before TDA selection (step 4) so that TDA selection can
use the allocated beam to check the correct VRB map and pick the best TDA per beam.
The preprocessor itself is a pluggable function pointer (`pre_processor_ul`), so a
custom implementation can replace the entire outer strategy — including how many UL
slots to target and what to do when the DCI budget is limited.
### Candidate struct
Each candidate is an `nr_{dl,ul}_candidate_t` struct that flows through the pipeline,
accumulating decisions. Its fields are split into three sections:
1. **Identity / scheduling state** — set by collect, read-only afterwards: `UE` pointer,
`rnti`, HARQ state, pending bytes, BLER estimate, current MCS, BWP geometry, QoS.
2. **CSI observations** — set by collect: `cqi` (DL), `beam_rsrp[]`, `beam_sinr[]` (per-SSB).
3. **gNB decisions** — written by the stage indicated below. Some live in the
embedded `sched_pdsch` / `sched_pusch` sub-struct, others are `alloc_`-prefixed
fields on the candidate itself:
- `sched_p{d,u}sch.nrOfLayers`, `.pm_index` (DL) / `.tpmi` (UL) — set by ri_pmi/tpmi_select
- `sched_p{d,u}sch.time_domain_allocation`, `.tda_info`, `alloc_slbitmap` — set by tda_select
- `alloc_beam_idx`, `alloc_dci_beam_idx` (UL), etc. — set by beam_select
- `sched_p{d,u}sch.mcs` — set by mcs_select
- `sched_p{d,u}sch.rbStart`, `.rbSize` — set by rb_alloc
- `alloc_cce_index`, `alloc_aggregation_level`, `alloc_sched_pdcch` — set by commit_alloc
The policy (`rb_alloc`) writes to `sched_p{d,u}sch.rbStart/rbSize/mcs` via the
`COMMIT_ALLOC` / `COMMIT_UL_ALLOC` macro, which also runs CCE validation and sets
`cand->scheduled = true`. Only candidates with that flag set are dispatched.
---
### Stage 1. Candidate Collection (fixed)
**Functions:** `collect_dl_candidates()`, `collect_ul_candidates()`
Iterates over connected UEs and builds an array of `nr_{dl,ul}_candidate_t` structs.
Populates the identity/state and CSI sections. Not a function pointer — fixed scaffolding
that feeds the pipeline.
### Stage 2. RI / PMI Selection
**Function pointers:** `mac->dl_ri_pmi_select` (`nr_dl_ri_pmi_select_fn`),
`mac->ul_ri_tpmi_select` (`nr_ul_ri_tpmi_select_fn`)
Sets rank and precoder index per candidate. In DL, rank and PMI come from the UE's CSI
report (RI + PMI). In UL, the gNB has full authority and reads rank and TPMI from SRS
feedback.
**DL outputs:** `cand->sched_pdsch.nrOfLayers`, `cand->sched_pdsch.pm_index`.
**UL outputs:** `cand->sched_pusch.nrOfLayers`, `cand->sched_pusch.tpmi`.
### Stage 3. Beam Selection
**Function pointers:** `mac->dl_beam_select` (`nr_dl_beam_select_fn`),
`mac->ul_beam_select` (`nr_ul_beam_select_fn`)
Assigns a beam structure index to each candidate. For UL, two beams are needed — one
for the DCI slot, one for the PUSCH slot — since they may fall in different beam periods.
Candidates that fail beam allocation (no beam available) are marked with `skipped=true`.
Placed before TDA selection so that TDA selection can use the allocated beam to check
the correct VRB map and pick the best TDA per beam.
**Outputs:** `cand->alloc_beam_idx` (PUSCH/PDSCH beam), `cand->alloc_dci_beam_idx` (UL DCI beam).
### Stage 4. TDA Selection
**Function pointers:** `mac->dl_tda_select` (`nr_dl_tda_select_fn`),
`mac->ul_tda_select` (`nr_ul_tda_select_fn`)
Picks the Time Domain Allocation for each candidate. For UL retransmissions, also
validates feasibility: if the TDA differs from the original transmission (e.g. because
targeting a different UL slot), the TBS must be preservable with the new symbol/DMRS
layout. Infeasible retx candidates are marked with `skipped=true`.
**Outputs:** `cand->sched_p{d,u}sch.time_domain_allocation`, `.tda_info`, `cand->alloc_slbitmap`. UL retx
candidates get `cand->retx_rbSize` set.
**Returns:** number of surviving candidates.
### Stage 5. MCS Selection
**Function pointers:** `mac->dl_mcs_select` (`nr_dl_mcs_select_fn`),
`mac->ul_mcs_select` (`nr_ul_mcs_select_fn`)
Runs for **all surviving candidates** — including those that may ultimately not be
scheduled due to CCE failure. Sets `sched_p{d,u}sch.mcs` from BLER stats or SINR, and persists
the decision to `{ul,dl}_bler_stats.mcs` so continuity is maintained across slots even
for unscheduled UEs.
Placed after beam selection so custom implementations can use `alloc_beam_idx` and
`beam_rsrp/sinr` for beam-aware MCS adaptation.
### Stage 6. RB Allocation (per beam)
**Function pointers:** `mac->dl_rb_alloc` (`nr_dl_rb_alloc_fn`),
`mac->ul_rb_alloc` (`nr_ul_rb_alloc_fn`)
The core resource allocation decision and the most likely stage to be replaced. Called
once per beam with candidates filtered to that beam. Decides which UEs to schedule and
how many PRBs each gets. MCS is already set on `sched_p{d,u}sch.mcs` by the previous
stage; the policy may refine it (e.g. downward PHR adjustment).
Each allocation must go through the `COMMIT_ALLOC` / `COMMIT_UL_ALLOC` macro, which
writes `sched_p{d,u}sch.rbStart/rbSize/mcs` onto the candidate, runs CCE validation
(and PUCCH validation on DL), and sets `cand->scheduled = true`. UEs that fail CCE are
skipped transparently.
**Outputs:** `cand->scheduled` flag on accepted candidates.
**Returns:** number of scheduled UEs.
### Stage 7. Dispatch (fixed)
Not a function pointer. Iterates over candidates with `scheduled == true`, reads the `alloc_*` fields
from each candidate, applies CCE results to `sched_ctrl`, marks the VRB map, and calls
`apply_{dl,ul}_{new_transmission,retransmission}` to build the final
`NR_sched_{pusch,pdsch}_t` and trigger FAPI message preparation.
### Stage 8. Per-LCID Byte Allocation (DL only)
**Function pointer:** `mac->dl_lcid_alloc` (`nr_dl_lcid_alloc_fn`)
Called inside `generate_dl_mac_pdu` for initial DL transmissions. Decides how many bytes
each logical channel gets within the available TBS. The candidate flows from the dispatch
stage into `post_process_dlsch``generate_dl_mac_pdu`, giving this stage access to the
full candidate context (per-LCID pending bytes, QoS, priority).
The function pointer receives the MAC instance, the candidate, the TBS available after
MAC CEs, and writes an output array `lcid_alloc[NR_MAX_NUM_LCID]` specifying the byte
budget per LCID. The MAC PDU builder then executes the plan: it iterates over LCs in
config order, requests up to `lcid_alloc[lcid]` bytes from RLC for each, and builds the
MAC subheaders. RLC may return fewer bytes than budgeted; the builder handles this
transparently.
**Inputs:** `candidate->pending_bytes_per_lcid[]`, `candidate->fiveQI`, `candidate->priority`,
`candidate->nssai`, `tbs_available`.
**Outputs:** `lcid_alloc[NR_MAX_NUM_LCID]` — byte budget per LCID.
Not invoked for retransmissions (which reuse the stored transport block) or for phy-test
mode (which fills random data). In these cases the candidate pointer is NULL.
---
## Default Implementations
All function pointers are assigned in
[`main.c`](../../openair2/LAYER2/NR_MAC_gNB/main.c) at startup.
The `COMMIT_ALLOC` / `COMMIT_UL_ALLOC` macros are defined in
[`mac_proto.h`](../../openair2/LAYER2/NR_MAC_gNB/mac_proto.h).
### `nr_dl_ri_pmi_select_default`, `nr_ul_ri_tpmi_select_default`
DL reads rank and PMI from the UE's CSI report (`csi_ri`, `csi_pm_index` on
`sched_ctrl`). Retransmissions reuse rank/PMI from the original HARQ process.
UL reads rank and TPMI from SRS feedback (`srs_feedback` on `sched_ctrl`).
Both write `cand->sched_p{d,u}sch.nrOfLayers` and the respective precoder index.
### `nr_dl_tda_select_default`, `nr_ul_tda_select_default`
Assigns the same TDA to all candidates in a slot (picks the first valid one for the
scheduled frame/slot). For UL retransmissions, calls `check_ul_retx_feasibility` to
verify TBS preservation under the new symbol/DMRS layout.
### `nr_dl_beam_select_default`, `nr_ul_beam_select_default`
Uses OAI's beam management framework (`NR_beam_info_t`). For UL, allocates both a DCI
beam and a PUSCH beam. Candidates that fail beam allocation are compacted out.
### `nr_dl_mcs_select_default`, `nr_ul_mcs_select_default`
BLER-based (when `harq_round_max > 1`): calls `nr_adapt_mcs_from_bler` for candidates
with a fresh BLER estimate; holds current MCS otherwise. SINR-based (when
`harq_round_max == 1`): maps measured PUSCH SINR to MCS via lookup table. In both
cases, persists to `{dl,ul}_bler_stats.mcs`.
### `nr_dl_proportional_fair`, `nr_ul_proportional_fair`
Proportional-fair scheduler with three phases:
- **Phase 1 — Retransmissions:** find the largest free block >= `retx_rbSize`.
- **Phase 2 — Minimal-grant UEs:** in DL, targets UEs with no pending RLC data
(`pending_bytes == 0`) that still need a TA command or beam-switch MAC CE. In UL,
targets inactive UEs (`sched_inactive`) that need scheduling for TA/SR. Both get a
minimum grant (`min_rb`).
- **Phase 3 — New data:** sort by PF weight (`pending_bytes / avg_throughput`), allocate
the largest free block to each UE in order.
The UL policy also checks PHR (Power Headroom) and adjusts MCS/RBs accordingly.
All phases use `COMMIT_ALLOC` / `COMMIT_UL_ALLOC` to validate CCE (and PUCCH on DL).
### `nr_dl_lcid_alloc_default`
Greedy fill: sets each LCID's budget to its full `pending_bytes_per_lcid` value. The
execution loop in `generate_dl_mac_pdu` then fills LCIDs in LC config order until the
TBS is exhausted, reproducing the original first-come-first-served behavior. A custom
implementation could use the candidate's QoS fields (`fiveQI`, `priority`, `nssai`)
to implement weighted fair queuing, strict priority with rate limiting, or slice-aware
allocation across LCIDs.
### `nr_dlsch_preprocessor`, `nr_ulsch_preprocessor`
Top-level orchestrators that run the full pipeline above. In phy-test mode, replaced by
`nr_preprocessor_phytest` / `nr_ul_preprocessor_phytest` which bypass the staged pipeline.
---
## Function Pointer Reference
### DL
| Field on `gNB_MAC_INST` | Typedef | Default | Stage |
|--------------------------|---------------------------|-------------------------------|-------|
| `pre_processor_dl` | `nr_pp_impl_dl` | `nr_dlsch_preprocessor` | Orchestrator |
| `dl_ri_pmi_select` | `nr_dl_ri_pmi_select_fn` | `nr_dl_ri_pmi_select_default` | 2. RI/PMI |
| `dl_beam_select` | `nr_dl_beam_select_fn` | `nr_dl_beam_select_default` | 3. Beam |
| `dl_tda_select` | `nr_dl_tda_select_fn` | `nr_dl_tda_select_default` | 4. TDA |
| `dl_mcs_select` | `nr_dl_mcs_select_fn` | `nr_dl_mcs_select_default` | 5. MCS |
| `dl_rb_alloc` | `nr_dl_rb_alloc_fn` | `nr_dl_proportional_fair` | 6. RB alloc |
| `dl_lcid_alloc` | `nr_dl_lcid_alloc_fn` | `nr_dl_lcid_alloc_default` | 8. LCID alloc |
### UL
| Field on `gNB_MAC_INST` | Typedef | Default | Stage |
|--------------------------|---------------------------|--------------------------------|-------|
| `pre_processor_ul` | `nr_pp_impl_ul` | `nr_ulsch_preprocessor` | Orchestrator |
| `ul_ri_tpmi_select` | `nr_ul_ri_tpmi_select_fn` | `nr_ul_ri_tpmi_select_default` | 2. RI/TPMI |
| `ul_beam_select` | `nr_ul_beam_select_fn` | `nr_ul_beam_select_default` | 3. Beam |
| `ul_tda_select` | `nr_ul_tda_select_fn` | `nr_ul_tda_select_default` | 4. TDA |
| `ul_mcs_select` | `nr_ul_mcs_select_fn` | `nr_ul_mcs_select_default` | 5. MCS |
| `ul_rb_alloc` | `nr_ul_rb_alloc_fn` | `nr_ul_proportional_fair` | 6. RB alloc |
---
## Key Data Structures
All defined in `nr_mac_gNB.h`.
### Candidate (`nr_{dl,ul}_candidate_t`)
Flows through the pipeline accumulating decisions. Three sections:
**Identity / scheduling state** (set by collect, read-only after):
`UE` pointer, `rnti`, `is_retx`, `retx_harq_pid`, `retx_rbSize`, `pending_bytes`,
`pending_bytes_per_lcid[NR_MAX_NUM_LCID]`, `avg_throughput`, `bler`, `current_mcs`,
`max_mcs`, `bwp_start`, `bwp_size`, `fiveQI`, `priority`, `nssai`.
**CSI observations** (set by collect, read-only after):
`cqi` (DL CQI), `beam_rsrp[]`, `beam_sinr[]` (per-SSB L1-RSRP/SINR, `INT16_MIN` = no data).
**gNB decisions** (written by the named stage — some in `sched_p{d,u}sch`, some `alloc_*`):
`sched_p{d,u}sch.nrOfLayers`, `.pm_index`/`.tpmi`, `.time_domain_allocation`, `.tda_info`,
`.mcs`, `.rbStart`, `.rbSize`;
`alloc_slbitmap`, `alloc_beam_idx`, `alloc_dci_beam_idx` (UL),
`alloc_cce_index`, `alloc_aggregation_level`, `alloc_sched_pdcch`.
### Sched Params (`nr_{dl,ul}_sched_params_t`)
Per-beam context passed to `rb_alloc`. Contains the MAC instance, slot info, VRB map,
available RBs, BLER thresholds, TDA info, and serving cell config.
---
## Writing a Custom Scheduler
### Replacing the RB allocation policy
Write a function matching the typedef:
```c
int my_ul_rb_alloc(const nr_ul_sched_params_t *params,
nr_ul_candidate_t *candidates,
int n_candidates)
{
int n_scheduled = 0;
for (int i = 0; i < n_candidates; i++) {
nr_ul_candidate_t *cand = &candidates[i];
// ... decide rbStart, rbSize, mcs ...
// COMMIT_UL_ALLOC writes sched_pusch fields, validates CCE, sets cand->scheduled:
COMMIT_UL_ALLOC(params, cand, rbStart, rbSize, mcs, n_scheduled);
}
return n_scheduled;
}
```
Register it in `openair2/LAYER2/NR_MAC_gNB/main.c`:
```c
RC.nrmac[i]->ul_rb_alloc = my_ul_rb_alloc;
```
### Replacing the per-LCID allocation policy (DL)
Write a function matching the typedef:
```c
void my_lcid_alloc(const gNB_MAC_INST *mac,
const nr_dl_candidate_t *candidate,
int tbs_available,
int lcid_alloc[NR_MAX_NUM_LCID])
{
memset(lcid_alloc, 0, NR_MAX_NUM_LCID * sizeof(int));
// ... use candidate->pending_bytes_per_lcid[], candidate->fiveQI,
// candidate->priority, tbs_available to decide budgets ...
for (int lcid = 0; lcid < NR_MAX_NUM_LCID; lcid++)
lcid_alloc[lcid] = my_budget_for(lcid);
}
```
Register it:
```c
RC.nrmac[i]->dl_lcid_alloc = my_lcid_alloc;
```
### Replacing other stages
Any function pointer can be replaced independently:
```c
RC.nrmac[i]->ul_ri_tpmi_select = my_ri_tpmi_select;
RC.nrmac[i]->ul_mcs_select = my_mcs_select;
RC.nrmac[i]->ul_beam_select = my_beam_select;
```
### Recommendations
- **Always use `COMMIT_ALLOC` / `COMMIT_UL_ALLOC`** to accept an allocation. It writes
`sched_p{d,u}sch` fields onto the candidate, validates CCE (and PUCCH on DL), and sets
`cand->scheduled`.
- **Do not mark the VRB map** — `commit_alloc` / `commit_ul_alloc` handles that inside the macro.
- `sched_p{d,u}sch.mcs` is already set by `mcs_select` when your policy runs. You may
refine it downward (e.g. PHR); pass the final value to `COMMIT_ALLOC` / `COMMIT_UL_ALLOC`.
- Candidates are non-const: the policy is allowed to write `sched_p{d,u}sch` and `alloc_*`
fields. Do not modify identity/state or CSI fields.

View File

@@ -169,6 +169,7 @@ generate DL shared channel (user data)
#### nr_feptx_prec()
tx precoding
<<<<<<< HEAD:doc/SW_archi.md
#### nr_feptx0
do the inverse DFT

View File

@@ -67,7 +67,7 @@ RUN /bin/bash -c "if [[ -v NEEDED_GIT_PROXY ]]; then git config --global http.pr
# Copying only the needed files to create ran-base
WORKDIR /oai-ran/cmake_targets/tools
COPY cmake_targets/tools/build_helper \
cmake_targets/tools/uhd-4.5plus-tdd-patch.diff \
cmake_targets/tools/uhd-4.x-tdd-patch.diff \
./
WORKDIR /oai-ran/cmake_targets

View File

@@ -55,7 +55,7 @@ RUN wget https://github.com/mikefarah/yq/releases/download/${YQ_VERSION}/yq_linu
# Copying only the needed files to create ran-base
WORKDIR /oai-ran/cmake_targets/tools
COPY cmake_targets/tools/build_helper \
cmake_targets/tools/uhd-4.5plus-tdd-patch.diff \
cmake_targets/tools/uhd-4.x-tdd-patch.diff \
./
WORKDIR /oai-ran/cmake_targets

View File

@@ -60,7 +60,7 @@ RUN /bin/bash -c "if [[ -v NEEDED_GIT_PROXY ]]; then git config --global http.pr
# Copying only the needed files to create ran-base
WORKDIR /oai-ran/cmake_targets/tools
COPY cmake_targets/tools/build_helper \
cmake_targets/tools/uhd-4.5plus-tdd-patch.diff \
cmake_targets/tools/uhd-4.x-tdd-patch.diff \
./
WORKDIR /oai-ran/cmake_targets

View File

@@ -63,7 +63,7 @@ RUN chmod +x /tini
# Copying only the needed files to create ran-base
WORKDIR /oai-ran/cmake_targets/tools
COPY cmake_targets/tools/build_helper \
cmake_targets/tools/uhd-4.5plus-tdd-patch.diff \
cmake_targets/tools/uhd-4.x-tdd-patch.diff \
./
WORKDIR /oai-ran/cmake_targets

View File

@@ -558,8 +558,8 @@ static int UE_dl_preprocessing(PHY_VARS_NR_UE *UE,
if (phy_data->dlsch[0].active
&& (phy_data->dlsch[0].rnti_type == TYPE_C_RNTI_ || phy_data->dlsch[0].rnti_type == TYPE_RA_RNTI_)) {
// indicate to tx thread to wait for DLSCH decoding
if (phy_data->dlsch_config.k1_feedback) { // if feedback is 0 there is no HARQ associated with this DLSCH
const int ack_nack_slot = (proc->nr_slot_rx + phy_data->dlsch_config.k1_feedback) % fp->slots_per_frame;
if (phy_data->dlsch[0].dlsch_config.k1_feedback) { // if feedback is 0 there is no HARQ associated with this DLSCH
const int ack_nack_slot = (proc->nr_slot_rx + phy_data->dlsch[0].dlsch_config.k1_feedback) % fp->slots_per_frame;
tx_wait_for_dlsch[ack_nack_slot]++;
}
}

View File

@@ -256,7 +256,7 @@ int main(int argc, char **argv)
init_opt();
int ret_loader = load_nrLDPC_coding_interface(NULL, &nrLDPC_coding_interface, 32);
int ret_loader = load_nrLDPC_coding_interface(NULL, &nrLDPC_coding_interface);
AssertFatal(ret_loader == 0, "error loading LDPC library\n");
// strdup to put the sring in the core file for post mortem identification

View File

@@ -118,7 +118,6 @@ typedef struct {
typedef struct {
uint8_t harq_pid;
uint8_t cw_idx;
uint8_t ack_nack;
uint32_t pdu_length;
uint8_t* pdu;
@@ -467,17 +466,6 @@ typedef struct {
typedef enum{vrb_to_prb_mapping_non_interleaved = 0, vrb_to_prb_mapping_interleaved = 1} vrb_to_prb_mapping_t;
typedef struct {
uint8_t mcs;
bool new_data_indicator;
uint8_t rv;
uint16_t targetCodeRate;
uint8_t qamModOrder;
uint32_t TBS;
uint8_t ldpcBaseGraph;
uint8_t Nl;
} fapi_nr_dl_cw_info_t;
typedef struct {
uint16_t BWPSize;
uint16_t BWPStart;
@@ -494,8 +482,15 @@ typedef struct {
uint8_t prb_bundling_size_ind;
uint8_t rate_matching_ind;
uint8_t zp_csi_rs_trigger;
uint8_t n_codewords;
fapi_nr_dl_cw_info_t cw_info[2];
uint8_t mcs;
bool new_data_indicator;
uint8_t rv;
uint16_t targetCodeRate;
uint8_t qamModOrder;
uint32_t TBS;
uint8_t tb2_mcs;
bool tb2_new_data_indicator;
uint8_t tb2_rv;
uint8_t harq_process_nbr;
vrb_to_prb_mapping_t vrb_to_prb_mapping;
uint8_t dai;
@@ -528,6 +523,7 @@ typedef struct {
uint16_t dlDataScramblingId;
uint16_t pduBitmap;
uint32_t k1_feedback;
uint8_t ldpcBaseGraph;
uint8_t numCsiRsForRateMatching;
fapi_nr_dl_config_csirs_pdu_rel15_t csiRsForRateMatching[NFAPI_MAX_NUM_CSI_RATEMATCH];
} fapi_nr_dl_config_dlsch_pdu_rel15_t;

View File

@@ -334,7 +334,7 @@ one_measurement_t test_ldpc(short max_iterations,
n_iter = ldpc_toCompare.LDPCdecoder(&decParams[j],
(int8_t *)channel_output_fixed[j],
estimated_output[j],
(int8_t *)estimated_output[j],
&decoder_profiler,
&dec_abort);
stop_meas(&ret.time_decoder);

View File

@@ -458,9 +458,8 @@ static int init_op_data_objs_dec(struct rte_bbdev_op_data *bufs,
bool large_input = false;
int j = 0;
for (int h = 0; h < nrLDPC_slot_decoding_parameters->nb_TBs; ++h) {
nrLDPC_TB_decoding_parameters_t *p = &nrLDPC_slot_decoding_parameters->TBs[h];
for (int i = 0; i < p->C; ++i) {
uint32_t data_len = i < p->first_rE2 ? p->E : p->E2;
for (int i = 0; i < nrLDPC_slot_decoding_parameters->TBs[h].C; ++i) {
uint32_t data_len = nrLDPC_slot_decoding_parameters->TBs[h].segments[i].E;
char *data;
struct rte_mbuf *m_head = rte_pktmbuf_alloc(mbuf_pool);
AssertFatal(m_head != NULL,
@@ -603,19 +602,20 @@ static void set_ldpc_dec_op(struct rte_bbdev_dec_op **ops,
bool special_case_tb_mode = !active_dev.is_t2 && (nrLDPC_slot_decoding_parameters->nb_TBs == 1)
&& (nb_segments_decoding(nrLDPC_slot_decoding_parameters) == 1);
for (int h = 0; h < nrLDPC_slot_decoding_parameters->nb_TBs; ++h) {
nrLDPC_TB_decoding_parameters_t *p = &nrLDPC_slot_decoding_parameters->TBs[h];
for (int i = 0; i < p->C; ++i) {
ops[j]->ldpc_dec.basegraph = p->BG;
ops[j]->ldpc_dec.z_c = p->Z;
ops[j]->ldpc_dec.q_m = p->Qm;
ops[j]->ldpc_dec.n_filler = p->F;
ops[j]->ldpc_dec.n_cb = (p->BG == 1) ? (66 * p->Z) : (50 * p->Z);
ops[j]->ldpc_dec.iter_max = p->max_ldpc_iterations;
ops[j]->ldpc_dec.rv_index = p->rv_index;
for (int i = 0; i < nrLDPC_slot_decoding_parameters->TBs[h].C; ++i) {
ops[j]->ldpc_dec.basegraph = nrLDPC_slot_decoding_parameters->TBs[h].BG;
ops[j]->ldpc_dec.z_c = nrLDPC_slot_decoding_parameters->TBs[h].Z;
ops[j]->ldpc_dec.q_m = nrLDPC_slot_decoding_parameters->TBs[h].Qm;
ops[j]->ldpc_dec.n_filler = nrLDPC_slot_decoding_parameters->TBs[h].F;
ops[j]->ldpc_dec.n_cb = (nrLDPC_slot_decoding_parameters->TBs[h].BG == 1) ? (66 * nrLDPC_slot_decoding_parameters->TBs[h].Z)
: (50 * nrLDPC_slot_decoding_parameters->TBs[h].Z);
ops[j]->ldpc_dec.iter_max = nrLDPC_slot_decoding_parameters->TBs[h].max_ldpc_iterations;
ops[j]->ldpc_dec.rv_index = nrLDPC_slot_decoding_parameters->TBs[h].rv_index;
ops[j]->ldpc_dec.op_flags = RTE_BBDEV_LDPC_ITERATION_STOP_ENABLE | RTE_BBDEV_LDPC_HQ_COMBINE_OUT_ENABLE;
if (p->d_to_be_cleared) {
if (*nrLDPC_slot_decoding_parameters->TBs[h].segments[i].d_to_be_cleared) {
*nrLDPC_slot_decoding_parameters->TBs[h].segments[i].d_to_be_cleared = false;
if (active_dev.is_t2)
*p->processedSegments = 0;
*nrLDPC_slot_decoding_parameters->TBs[h].processedSegments = 0;
} else {
ops[j]->ldpc_dec.op_flags |= RTE_BBDEV_LDPC_HQ_COMBINE_IN_ENABLE;
if (active_dev.support_internal_harq_memory) {
@@ -625,12 +625,12 @@ static void set_ldpc_dec_op(struct rte_bbdev_dec_op **ops,
}
if (!active_dev.is_t2)
*p->processedSegments = 0;
*nrLDPC_slot_decoding_parameters->TBs[h].processedSegments = 0;
if (!special_case_tb_mode) {
ops[j]->ldpc_dec.code_block_mode = 1;
ops[j]->ldpc_dec.cb_params.e = i < p->first_rE2 ? p->E : p->E2;
if (p->C > 1) {
ops[j]->ldpc_dec.cb_params.e = nrLDPC_slot_decoding_parameters->TBs[h].segments[i].E;
if (nrLDPC_slot_decoding_parameters->TBs[h].C > 1) {
ops[j]->ldpc_dec.op_flags |= RTE_BBDEV_LDPC_CRC_TYPE_24B_DROP;
ops[j]->ldpc_dec.op_flags |= RTE_BBDEV_LDPC_CRC_TYPE_24B_CHECK;
}
@@ -646,12 +646,12 @@ static void set_ldpc_dec_op(struct rte_bbdev_dec_op **ops,
ops[j]->ldpc_dec.tb_params.c = 1;
ops[j]->ldpc_dec.tb_params.r = 0;
ops[j]->ldpc_dec.tb_params.cab = 1;
ops[j]->ldpc_dec.tb_params.ea = i < p->first_rE2 ? p->E : p->E2;
ops[j]->ldpc_dec.tb_params.eb = i < p->first_rE2 ? p->E : p->E2;
ops[j]->ldpc_dec.tb_params.ea = nrLDPC_slot_decoding_parameters->TBs[h].segments[i].E;
ops[j]->ldpc_dec.tb_params.eb = nrLDPC_slot_decoding_parameters->TBs[h].segments[i].E;
}
// Calculate offset in the HARQ combined buffers
// Unique segment offset
uint32_t segment_offset = (p->harq_unique_pid * NR_LDPC_MAX_NUM_CB) + i;
uint32_t segment_offset = (nrLDPC_slot_decoding_parameters->TBs[h].harq_unique_pid * NR_LDPC_MAX_NUM_CB) + i;
// Prune to avoid shooting above maximum id
uint32_t pruned_segment_offset = segment_offset % active_dev.num_harq_codeblock;
// Segment offset to byte offset
@@ -673,7 +673,6 @@ static void set_ldpc_dec_op(struct rte_bbdev_dec_op **ops,
ops[j]->ldpc_dec.input = inputs[j];
++j;
}
p->d_to_be_cleared = false;
}
}
@@ -730,16 +729,14 @@ static int retrieve_ldpc_dec_op(struct rte_bbdev_dec_op **ops, nrLDPC_slot_decod
{
int j = 0;
for (int h = 0; h < nrLDPC_slot_decoding_parameters->nb_TBs; ++h) {
nrLDPC_TB_decoding_parameters_t *p = &nrLDPC_slot_decoding_parameters->TBs[h];
size_t data_off = 0;
for (int i = 0; i < p->C; ++i) {
for (int i = 0; i < nrLDPC_slot_decoding_parameters->TBs[h].C; ++i) {
struct rte_bbdev_op_data *hard_output = &ops[j]->ldpc_dec.hard_output;
struct rte_mbuf *m = hard_output->data;
uint16_t data_len = rte_pktmbuf_data_len(m) - hard_output->offset;
uint8_t *data = rte_pktmbuf_mtod_offset(m, uint8_t *, hard_output->offset);
memcpy(p->c + data_off, data, data_len);
memcpy(nrLDPC_slot_decoding_parameters->TBs[h].segments[i].c, data, data_len);
uint32_t segment_offset = (p->harq_unique_pid * NR_LDPC_MAX_NUM_CB) + i;
uint32_t segment_offset = (nrLDPC_slot_decoding_parameters->TBs[h].harq_unique_pid * NR_LDPC_MAX_NUM_CB) + i;
uint32_t pruned_segment_offset = segment_offset % active_dev.num_harq_codeblock;
struct rte_bbdev_op_data *harq_output = &ops[j]->ldpc_dec.harq_combined_output;
if (!active_dev.support_internal_harq_memory) {
@@ -752,7 +749,6 @@ static int retrieve_ldpc_dec_op(struct rte_bbdev_dec_op **ops, nrLDPC_slot_decod
active_dev.harq_buffers[pruned_segment_offset].offset = harq_output->offset;
active_dev.harq_buffers[pruned_segment_offset].length = harq_output->length;
++j;
data_off += p->K >> 3;
}
}
return 0;
@@ -827,7 +823,7 @@ static int pmd_lcore_ldpc_dec(void *arg)
// Start timer
// We report timing only once in (0,0) since the timers are merged at the end
start_meas(&nrLDPC_slot_decoding_parameters->TBs[0].ts_ldpc_decode);
start_meas(&nrLDPC_slot_decoding_parameters->TBs[0].segments[0].ts_ldpc_decode);
uint16_t enq = 0, deq = 0;
while (enq < num_segments) {
@@ -844,7 +840,7 @@ static int pmd_lcore_ldpc_dec(void *arg)
// Stop timer
// We report timing only once in (0,0) since the timers are merged at the end
stop_meas(&nrLDPC_slot_decoding_parameters->TBs[0].ts_ldpc_decode);
stop_meas(&nrLDPC_slot_decoding_parameters->TBs[0].segments[0].ts_ldpc_decode);
if (deq == enq) {
ret = retrieve_ldpc_dec_op(ops_deq, nrLDPC_slot_decoding_parameters);
@@ -853,24 +849,24 @@ static int pmd_lcore_ldpc_dec(void *arg)
/* get the max of iter_count for all dequeued ops */
int j = 0;
for (int h = 0; h < nrLDPC_slot_decoding_parameters->nb_TBs; ++h) {
nrLDPC_TB_decoding_parameters_t *p = &nrLDPC_slot_decoding_parameters->TBs[h];
for (int i = 0; i < p->C; ++i) {
bool *status = &p->decodeSuccess[i];
for (int i = 0; i < nrLDPC_slot_decoding_parameters->TBs[h].C; ++i) {
bool *status = &nrLDPC_slot_decoding_parameters->TBs[h].segments[i].decodeSuccess;
tp->iter_count = RTE_MAX(ops_enq[j]->ldpc_dec.iter_count, tp->iter_count);
// Check if CRC is available otherwise rely on ops_enq[j]->status to detect decoding success
// CRC is NOT available if the CRC type is 24_B which is when C is greater than 1
if (p->C > 1) {
if (nrLDPC_slot_decoding_parameters->TBs[h].C > 1) {
*status = (ops_enq[j]->status == 0);
} else {
uint8_t *decoded_bytes = p->c;
uint8_t crc_type = crcType(p->C, p->A);
uint32_t len_with_crc = lenWithCrc(p->C, p->A);
uint8_t *decoded_bytes = nrLDPC_slot_decoding_parameters->TBs[h].segments[i].c;
uint8_t crc_type = crcType(nrLDPC_slot_decoding_parameters->TBs[h].C, nrLDPC_slot_decoding_parameters->TBs[h].A);
uint32_t len_with_crc = lenWithCrc(nrLDPC_slot_decoding_parameters->TBs[h].C, nrLDPC_slot_decoding_parameters->TBs[h].A);
*status = check_crc(decoded_bytes, len_with_crc, crc_type);
}
if (*status) {
*p->processedSegments = *p->processedSegments + 1;
*nrLDPC_slot_decoding_parameters->TBs[h].processedSegments =
*nrLDPC_slot_decoding_parameters->TBs[h].processedSegments + 1;
}
++j;
}
@@ -1061,7 +1057,7 @@ static int normalize_dpdk_dev(const char *input, char *output, size_t out_len)
}
// OAI CODE
int32_t nrLDPC_coding_init(int max_num_pxsch)
int32_t nrLDPC_coding_init()
{
pthread_mutex_init(&encode_mutex, NULL);
pthread_mutex_init(&decode_mutex, NULL);
@@ -1287,24 +1283,28 @@ int32_t nrLDPC_coding_decoder(nrLDPC_slot_decoding_parameters_t *nrLDPC_slot_dec
int8_t llr_decimal = (active_dev.info.drv.capabilities)[RTE_BBDEV_OP_LDPC_DEC].cap.ldpc_dec.llr_decimals;
int offset = 0;
for (int h = 0; h < nrLDPC_slot_decoding_parameters->nb_TBs; ++h) {
nrLDPC_TB_decoding_parameters_t *p = &nrLDPC_slot_decoding_parameters->TBs[h];
size_t data_off = 0;
for (int r = 0; r < p->C; r++) {
uint32_t E = r < p->first_rE2 ? p->E : p->E2;
for (int r = 0; r < nrLDPC_slot_decoding_parameters->TBs[h].C; r++) {
if (active_dev.is_t2) {
// For the T2, we simply saturate the LLRs.
uint16_t z_ol[LDPC_MAX_CB_SIZE] __attribute__((aligned(16)));
memcpy(z_ol, p->llr + data_off, E * sizeof(uint16_t));
memcpy(z_ol,
nrLDPC_slot_decoding_parameters->TBs[h].segments[r].llr,
nrLDPC_slot_decoding_parameters->TBs[h].segments[r].E * sizeof(uint16_t));
simde__m128i *pv_ol128 = (simde__m128i *)z_ol;
simde__m128i *pl_ol128 = (simde__m128i *)&l_ol[offset];
for (int i = 0, j = 0; j < ((E + 15) >> 4); i += 2, j++) {
for (int i = 0, j = 0; j < ((nrLDPC_slot_decoding_parameters->TBs[h].segments[r].E + 15) >> 4); i += 2, j++) {
pl_ol128[j] = simde_mm_packs_epi16(pv_ol128[i], pv_ol128[i + 1]);
}
} else {
llr_scaling(p->llr + data_off, E, &l_ol[offset], llr_size, llr_decimal, p->nb_layers, p->Qm);
llr_scaling(nrLDPC_slot_decoding_parameters->TBs[h].segments[r].llr,
nrLDPC_slot_decoding_parameters->TBs[h].segments[r].E,
&l_ol[offset],
llr_size,
llr_decimal,
nrLDPC_slot_decoding_parameters->TBs[h].nb_layers,
nrLDPC_slot_decoding_parameters->TBs[h].Qm);
}
offset += LDPC_MAX_CB_SIZE;
data_off += E;
}
}

View File

@@ -8,12 +8,43 @@
#include "common/utils/time_meas.h"
#include "openair1/PHY/CODING/coding_defs.h"
#include "openair1/PHY/CODING/nrLDPC_decoder/nrLDPCdecoder_defs.h"
#include "common/utils/threadPool/thread-pool.h"
#ifndef __NRLDPC_CODING_INTERFACE__H__
#define __NRLDPC_CODING_INTERFACE__H__
/**
* \typedef nrLDPC_segment_decoding_parameters_t
* \struct nrLDPC_segment_decoding_parameters_s
* \brief decoding parameter of segments
* \var E input llr segment size
* \var R code rate indication
* \var llr segment input llr array
* \var d Pointers to code blocks before LDPC decoding (38.212 V15.4.0 section 5.3.2)
* \var d_to_be_cleared
* pointer to the flag used to clear d properly
* when true, clear d after rate dematching
* \var c Pointers to code blocks after LDPC decoding (38.212 V15.4.0 section 5.2.2)
* \var decodeSuccess
* flag indicating that the decoding of the segment was successful
* IT MUST BE FILLED BY THE IMPLEMENTATION
* \var ts_deinterleave deinterleaving time stats
* \var ts_rate_unmatch rate unmatching time stats
* \var ts_ldpc_decode decoding time stats
*/
typedef struct nrLDPC_segment_decoding_parameters_s{
int E;
uint8_t R;
short *llr;
int16_t *d;
bool *d_to_be_cleared;
uint8_t *c;
bool decodeSuccess;
time_stats_t ts_deinterleave;
time_stats_t ts_rate_unmatch;
time_stats_t ts_ldpc_decode;
} nrLDPC_segment_decoding_parameters_t;
/**
* \typedef nrLDPC_TB_decoding_parameters_t
* \struct nrLDPC_TB_decoding_parameters_s
@@ -65,20 +96,7 @@ typedef struct nrLDPC_TB_decoding_parameters_s{
uint32_t F;
uint32_t C;
int E;
uint8_t R;
int E2;
uint8_t R2;
int first_rE2;
short *llr;
uint8_t *c;
int16_t *d;
bool d_to_be_cleared;
bool decodeSuccess[NR_LDPC_MAX_NUM_CB];
time_stats_t ts_deinterleave;
time_stats_t ts_rate_unmatch;
time_stats_t ts_seg_prep;
time_stats_t ts_ldpc_decode;
nrLDPC_segment_decoding_parameters_t *segments;
} nrLDPC_TB_decoding_parameters_t;
/**
@@ -119,7 +137,6 @@ typedef struct nrLDPC_segment_encoding_parameters_s{
time_stats_t ts_interleave;
time_stats_t ts_rate_match;
time_stats_t ts_ldpc_encode;
time_stats_t ts_output;
} nrLDPC_segment_encoding_parameters_t;
/**
@@ -194,15 +211,13 @@ typedef struct nrLDPC_slot_encoding_parameters_s{
int nb_TBs;
tpool_t *threadPool;
time_stats_t *tinput;
time_stats_t *tinput_memcpy;
time_stats_t *tprep;
time_stats_t *tparity;
time_stats_t *toutput;
time_stats_t *tconcat;
nrLDPC_TB_encoding_parameters_t *TBs;
} nrLDPC_slot_encoding_parameters_t;
typedef int32_t(nrLDPC_coding_init_t)(int);
typedef int32_t(nrLDPC_coding_init_t)(void);
typedef int32_t(nrLDPC_coding_shutdown_t)(void);
/**
@@ -224,7 +239,7 @@ typedef struct nrLDPC_coding_interface_s {
nrLDPC_coding_encoder_t *nrLDPC_coding_encoder;
} nrLDPC_coding_interface_t;
int load_nrLDPC_coding_interface(char *version, nrLDPC_coding_interface_t *interface, int);
int load_nrLDPC_coding_interface(char *version, nrLDPC_coding_interface_t *interface);
int free_nrLDPC_coding_interface(nrLDPC_coding_interface_t *interface);
#endif

View File

@@ -21,7 +21,7 @@
/* arg is used to initialize the config module so that the loader works as expected */
char *arguments_phy_simulators[64]={"ldpctest",NULL};
int load_nrLDPC_coding_interface(char *version, nrLDPC_coding_interface_t *itf, int max_num_pxsch)
int load_nrLDPC_coding_interface(char *version, nrLDPC_coding_interface_t *itf)
{
char *ptr = (char *)config_get_if();
char libname[64] = "ldpc";
@@ -46,7 +46,7 @@ int load_nrLDPC_coding_interface(char *version, nrLDPC_coding_interface_t *itf,
itf->nrLDPC_coding_decoder = (nrLDPC_coding_decoder_t *)shlib_fdesc[2].fptr;
itf->nrLDPC_coding_encoder = (nrLDPC_coding_encoder_t *)shlib_fdesc[3].fptr;
AssertFatal(itf->nrLDPC_coding_init(max_num_pxsch) == 0, "error starting LDPC library %s %s\n", libname, version);
AssertFatal(itf->nrLDPC_coding_init() == 0, "error starting LDPC library %s %s\n", libname, version);
return 0;
}

View File

@@ -66,7 +66,6 @@
typedef struct nrLDPC_decoding_parameters_s {
t_nrLDPC_dec_params decoderParms;
int r;
uint8_t Qm;
uint8_t Kc;
@@ -84,16 +83,15 @@ typedef struct nrLDPC_decoding_parameters_s {
int E;
short *llr;
int16_t *d;
bool d_to_be_cleared;
bool *d_to_be_cleared;
uint8_t *c;
bool *decodeSuccess;
task_ans_t *ans;
time_stats_t ts_deinterleave;
time_stats_t ts_rate_unmatch;
time_stats_t ts_seg_prep;
time_stats_t ts_ldpc_decode;
time_stats_t *p_ts_deinterleave;
time_stats_t *p_ts_rate_unmatch;
time_stats_t *p_ts_ldpc_decode;
} nrLDPC_decoding_parameters_t;
static void nr_process_decode_segment(void *arg)
@@ -119,7 +117,7 @@ static void nr_process_decode_segment(void *arg)
//////////////////////////// ulsch_llr =====> ulsch_harq->e //////////////////////////////
start_meas(&rdata->ts_deinterleave);
start_meas(rdata->p_ts_deinterleave);
/// code blocks after bit selection in rate matching for LDPC code (38.212 V15.4.0 section 5.4.2.1)
int16_t harq_e[E];
@@ -128,9 +126,9 @@ static void nr_process_decode_segment(void *arg)
//////////////////////////////////////////////////////////////////////////////////////////
stop_meas(&rdata->ts_deinterleave);
stop_meas(rdata->p_ts_deinterleave);
start_meas(&rdata->ts_rate_unmatch);
start_meas(rdata->p_ts_rate_unmatch);
//////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////// nr_rate_matching_ldpc_rx ////////////////////////////////
@@ -145,28 +143,21 @@ static void nr_process_decode_segment(void *arg)
harq_e,
rdata->C,
rv_index,
rdata->d_to_be_cleared,
*rdata->d_to_be_cleared,
E,
rdata->F,
K - rdata->F - 2 * (p_decoderParms->Z))
== -1) {
stop_meas(&rdata->ts_rate_unmatch);
LOG_E(PHY,
"nrLDPC_coding_segment_decoder.c: Problem in rate_matching BG %d, Z %d, C %d, rv_index %d, E %d, F %d, K%d, K-F-2*Z %d\n",
p_decoderParms->BG,
p_decoderParms->Z,
rdata->C,
rv_index,
E,
rdata->F,
K,
K - rdata->F - 2 * (p_decoderParms->Z));
stop_meas(rdata->p_ts_rate_unmatch);
LOG_E(PHY, "nrLDPC_coding_segment_decoder.c: Problem in rate_matching\n");
// Task completed
completed_task_ans(rdata->ans);
return;
}
stop_meas(&rdata->ts_rate_unmatch);
stop_meas(rdata->p_ts_rate_unmatch);
*rdata->d_to_be_cleared = false;
p_decoderParms->crc_type = crcType(rdata->C, A);
p_decoderParms->Kprime = lenWithCrc(rdata->C, A);
@@ -175,8 +166,8 @@ static void nr_process_decode_segment(void *arg)
int16_t z[68 * 384 + 16] __attribute__((aligned(16)));
start_meas(rdata->p_ts_ldpc_decode);
start_meas(&rdata->ts_seg_prep);
memset(z, 0, 2 * rdata->Z * sizeof(*z));
// set Filler bits
memset(z + Kprime, 127, rdata->F * sizeof(*z));
@@ -191,7 +182,6 @@ static void nr_process_decode_segment(void *arg)
for (int i = 0, j = 0; j < ((Kc * rdata->Z) >> 4) + 1; i += 2, j++) {
pl[j] = simde_mm_packs_epi16(pv[i], pv[i + 1]);
}
stop_meas(&rdata->ts_seg_prep);
//////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////
@@ -199,18 +189,16 @@ static void nr_process_decode_segment(void *arg)
//////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////// pl =====> llrProcBuf //////////////////////////////////
start_meas(&rdata->ts_ldpc_decode);
int decodeIterations = LDPCdecoder(p_decoderParms, l, (uint8_t *)llrProcBuf, p_procTime, rdata->abort_decode);
AssertFatal(rdata->c, "rdata->c is null, A %d, K %d\n", rdata->A, rdata->K);
int decodeIterations = LDPCdecoder(p_decoderParms, l, llrProcBuf, p_procTime, rdata->abort_decode);
if (decodeIterations < p_decoderParms->numMaxIter) {
memcpy(rdata->c, llrProcBuf, K >> 3);
*rdata->decodeSuccess = true;
} else {
LOG_D(PHY, "Decoding failed: K %d, Z %d, rv_index %d\n", K, rdata->Z, rdata->rv_index);
memset(rdata->c, 0, K >> 3);
*rdata->decodeSuccess = false;
}
stop_meas(&rdata->ts_ldpc_decode);
stop_meas(rdata->p_ts_ldpc_decode);
// Task completed
completed_task_ans(rdata->ans);
@@ -227,28 +215,20 @@ int nrLDPC_prepare_TB_decoding(nrLDPC_slot_decoding_parameters_t *nrLDPC_slot_de
decParams.BG = nrLDPC_TB_decoding_parameters->BG;
decParams.Z = nrLDPC_TB_decoding_parameters->Z;
decParams.numMaxIter = nrLDPC_TB_decoding_parameters->max_ldpc_iterations;
decParams.outMode = nrLDPC_outMode_BIT;
decParams.outMode = 0;
for (int r = 0; r < nrLDPC_TB_decoding_parameters->C; r++) {
nrLDPC_decoding_parameters_t *rdata = &((nrLDPC_decoding_parameters_t *)t_info->buf)[t_info->len];
DevAssert(t_info->len < t_info->cap);
rdata->ans = t_info->ans;
t_info->len += 1;
int llr_offset;
if (r < nrLDPC_TB_decoding_parameters->first_rE2) {
decParams.R = nrLDPC_TB_decoding_parameters->R;
rdata->E = nrLDPC_TB_decoding_parameters->E;
llr_offset = r * rdata->E;
} else {
decParams.R = nrLDPC_TB_decoding_parameters->R2;
rdata->E = nrLDPC_TB_decoding_parameters->E2;
llr_offset = nrLDPC_TB_decoding_parameters->first_rE2 * nrLDPC_TB_decoding_parameters->E
+ (r - nrLDPC_TB_decoding_parameters->first_rE2) * rdata->E;
}
rdata->r = r;
decParams.R = nrLDPC_TB_decoding_parameters->segments[r].R;
rdata->decoderParms = decParams;
rdata->llr = nrLDPC_TB_decoding_parameters->segments[r].llr;
rdata->Kc = decParams.BG == 2 ? 52 : 68;
rdata->C = nrLDPC_TB_decoding_parameters->C;
rdata->E = nrLDPC_TB_decoding_parameters->segments[r].E;
rdata->A = nrLDPC_TB_decoding_parameters->A;
rdata->Qm = nrLDPC_TB_decoding_parameters->Qm;
rdata->K = nrLDPC_TB_decoding_parameters->K;
@@ -257,30 +237,18 @@ int nrLDPC_prepare_TB_decoding(nrLDPC_slot_decoding_parameters_t *nrLDPC_slot_de
rdata->rv_index = nrLDPC_TB_decoding_parameters->rv_index;
rdata->tbslbrm = nrLDPC_TB_decoding_parameters->tbslbrm;
rdata->abort_decode = nrLDPC_TB_decoding_parameters->abort_decode;
rdata->d = nrLDPC_TB_decoding_parameters->d + r * rdata->Kc * rdata->Z;
rdata->d_to_be_cleared = nrLDPC_TB_decoding_parameters->d_to_be_cleared;
rdata->c = nrLDPC_TB_decoding_parameters->c + r * (rdata->K >> 3);
AssertFatal(rdata->c != NULL,
"rdata->c is null, r %d, K %d, A %d, rv_index %d, TB_decoding_parameters->c %p\n",
r,
rdata->K,
rdata->A,
rdata->rv_index,
nrLDPC_TB_decoding_parameters->c);
rdata->llr = nrLDPC_TB_decoding_parameters->llr + llr_offset; // rdata->Kc*rdata->Z;
rdata->decodeSuccess = &nrLDPC_TB_decoding_parameters->decodeSuccess[r];
memset(&rdata->ts_deinterleave, 0, sizeof(rdata->ts_deinterleave));
memset(&rdata->ts_rate_unmatch, 0, sizeof(rdata->ts_rate_unmatch));
memset(&rdata->ts_seg_prep, 0, sizeof(rdata->ts_seg_prep));
memset(&rdata->ts_ldpc_decode, 0, sizeof(rdata->ts_ldpc_decode));
reset_meas(&rdata->ts_deinterleave);
reset_meas(&rdata->ts_rate_unmatch);
reset_meas(&rdata->ts_seg_prep);
reset_meas(&rdata->ts_ldpc_decode);
rdata->d = nrLDPC_TB_decoding_parameters->segments[r].d;
rdata->d_to_be_cleared = nrLDPC_TB_decoding_parameters->segments[r].d_to_be_cleared;
rdata->c = nrLDPC_TB_decoding_parameters->segments[r].c;
rdata->decodeSuccess = &nrLDPC_TB_decoding_parameters->segments[r].decodeSuccess;
rdata->p_ts_deinterleave = &nrLDPC_TB_decoding_parameters->segments[r].ts_deinterleave;
rdata->p_ts_rate_unmatch = &nrLDPC_TB_decoding_parameters->segments[r].ts_rate_unmatch;
rdata->p_ts_ldpc_decode = &nrLDPC_TB_decoding_parameters->segments[r].ts_ldpc_decode;
task_t t = {.func = &nr_process_decode_segment, .args = rdata};
pushTpool(nrLDPC_slot_decoding_parameters->threadPool, t);
LOG_D(PHY, "Added a block to decode, in pipe: %d, rdata->c %p\n", r, rdata->c);
LOG_D(PHY, "Added a block to decode, in pipe: %d\n", r);
}
return nrLDPC_TB_decoding_parameters->C;
}
@@ -314,20 +282,12 @@ int32_t nrLDPC_coding_decoder(nrLDPC_slot_decoding_parameters_t *nrLDPC_slot_dec
// Execute thread pool tasks
join_task_ans(t_info.ans);
size_t r_t_info = 0;
for (int pusch_id = 0; pusch_id < nrLDPC_slot_decoding_parameters->nb_TBs; pusch_id++) {
nrLDPC_TB_decoding_parameters_t *nrLDPC_TB_decoding_parameters = &nrLDPC_slot_decoding_parameters->TBs[pusch_id];
*nrLDPC_TB_decoding_parameters->processedSegments = 0;
for (int r = 0; r < nrLDPC_TB_decoding_parameters->C; r++) {
if (nrLDPC_TB_decoding_parameters->decodeSuccess[r])
if (nrLDPC_TB_decoding_parameters->segments[r].decodeSuccess) {
*nrLDPC_TB_decoding_parameters->processedSegments = *nrLDPC_TB_decoding_parameters->processedSegments + 1;
nrLDPC_decoding_parameters_t *rdata = &((nrLDPC_decoding_parameters_t *)t_info.buf)[r_t_info];
r_t_info += 1;
merge_meas(&nrLDPC_TB_decoding_parameters->ts_deinterleave, &rdata->ts_deinterleave);
merge_meas(&nrLDPC_TB_decoding_parameters->ts_rate_unmatch, &rdata->ts_rate_unmatch);
merge_meas(&nrLDPC_TB_decoding_parameters->ts_seg_prep, &rdata->ts_seg_prep);
merge_meas(&nrLDPC_TB_decoding_parameters->ts_ldpc_decode, &rdata->ts_ldpc_decode);
}
}
}
return 0;

View File

@@ -339,11 +339,9 @@ static int nrLDPC_launch_TB_encoding(nrLDPC_slot_encoding_parameters_t *nrLDPC_s
encoder_implemparams_t common_segment_params = {
.n_segments = nrLDPC_TB_encoding_parameters->C,
.tinput = nrLDPC_slot_encoding_parameters->tinput,
.tinput_memcpy = nrLDPC_slot_encoding_parameters->tinput_memcpy,
.tprep = nrLDPC_slot_encoding_parameters->tprep,
.tparity = nrLDPC_slot_encoding_parameters->tparity,
.toutput = nrLDPC_slot_encoding_parameters->toutput,
.tconcat = nrLDPC_slot_encoding_parameters->tconcat,
.Kb = nrLDPC_TB_encoding_parameters->Kb,
.Zc = nrLDPC_TB_encoding_parameters->Z,
.BG = nrLDPC_TB_encoding_parameters->BG,
@@ -426,15 +424,14 @@ int nrLDPC_coding_encoder(nrLDPC_slot_encoding_parameters_t *nrLDPC_slot_encodin
join_task_ans(&ans);
// Write output
time_stats_t *tconcat = nrLDPC_slot_encoding_parameters->tconcat;
if (tconcat != NULL)
start_meas(tconcat);
nbTasks = 0;
for (int dlsch_id = 0; dlsch_id < nrLDPC_slot_encoding_parameters->nb_TBs; dlsch_id++) {
nrLDPC_TB_encoding_parameters_t *nrLDPC_TB_encoding_parameters = &nrLDPC_slot_encoding_parameters->TBs[dlsch_id];
uint32_t C = nrLDPC_TB_encoding_parameters->C;
size_t n_seg = (C / 8 + ((C & 7) == 0 ? 0 : 1));
time_stats_t *toutput = nrLDPC_slot_encoding_parameters->toutput;
for (int j = 0; j < n_seg; j++) {
unsigned int macro_segment = j * 8;
unsigned int macro_segment_end = (C > macro_segment + 8) ? macro_segment + 8 : C;
@@ -451,6 +448,7 @@ int nrLDPC_coding_encoder(nrLDPC_slot_encoding_parameters_t *nrLDPC_slot_encodin
}
}
if(toutput != NULL) start_meas(toutput);
uint32_t Eoffset=0;
for (int s=0; s<macro_segment; s++)
@@ -464,11 +462,11 @@ int nrLDPC_coding_encoder(nrLDPC_slot_encoding_parameters_t *nrLDPC_slot_encodin
macro_segment_end - macro_segment,
nrLDPC_TB_encoding_parameters->output,
Eoffset);
if(toutput != NULL) stop_meas(toutput);
}
nbTasks += n_seg;
}
if (tconcat != NULL)
stop_meas(tconcat);
return 0;
}

View File

@@ -1296,7 +1296,7 @@ static inline void nrLDPC_bnProc(t_nrLDPC_lut* p_lut, int8_t* bnProcBuf, int8_t*
\param llrOut Pointer to output LLRs
\param numLLR Number of LLRs
*/
static inline void nrLDPC_llr2bit(uint8_t* out, int8_t* llrOut, uint16_t numLLR)
static inline void nrLDPC_llr2bit(int8_t* out, int8_t* llrOut, uint16_t numLLR)
{
simde__m256i* p_llrOut = (simde__m256i*) llrOut;
simde__m256i* p_out = (simde__m256i*) out;
@@ -1313,7 +1313,7 @@ static inline void nrLDPC_llr2bit(uint8_t* out, int8_t* llrOut, uint16_t numLLR)
// Remaining LLRs that do not fit in multiples of 32 bytes
int8_t* p_llrOut8 = (int8_t*)p_llrOut;
uint8_t* p_out8 = (uint8_t*)p_out;
int8_t* p_out8 = (int8_t*)p_out;
for (uint32_t i = 0; i < Mr; i++)
p_out8[i] = p_llrOut8[i] < 0;
@@ -1328,7 +1328,7 @@ static inline void nrLDPC_llr2bit(uint8_t* out, int8_t* llrOut, uint16_t numLLR)
\param llrOut Pointer to output LLRs
\param numLLR Number of LLRs
*/
static inline void nrLDPC_llr2bitPacked(uint8_t* out, int8_t* llrOut, uint16_t numLLR)
static inline void nrLDPC_llr2bitPacked(int8_t* out, int8_t* llrOut, uint16_t numLLR)
{
/** Vector of indices for shuffling input */
const uint8_t constShuffle_256_epi8[32] __attribute__ ((aligned(32))) = {7,6,5,4,3,2,1,0,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0,15,14,13,12,11,10,9,8};

View File

@@ -136,7 +136,7 @@
*/
static inline uint32_t nrLDPC_decoder_core(int8_t* p_llr,
uint8_t* p_out,
int8_t* p_out,
uint32_t numLLR,
t_nrLDPC_lut* p_lut,
t_nrLDPC_dec_params* p_decParams,
@@ -155,7 +155,7 @@ int32_t LDPCshutdown()
int32_t LDPCdecoder(t_nrLDPC_dec_params* p_decParams,
int8_t* p_llr,
uint8_t* p_out,
int8_t* p_out,
t_nrLDPC_time_stats* p_profiler,
decode_abort_t* ab)
{
@@ -185,7 +185,7 @@ int32_t LDPCdecoder(t_nrLDPC_dec_params* p_decParams,
\param p_profilernrLDPC profiler statistics
*/
static inline uint32_t nrLDPC_decoder_core(int8_t* p_llr,
uint8_t* p_out,
int8_t* p_out,
uint32_t numLLR,
t_nrLDPC_lut* p_lut,
t_nrLDPC_dec_params* p_decParams,
@@ -828,7 +828,7 @@ static inline uint32_t nrLDPC_decoder_core(int8_t* p_llr,
} else {
if (numIter > 0) {
int8_t llrOut[NR_LDPC_MAX_NUM_LLR] __attribute__((aligned(64))) = {0};
int8_t* p_llrOut = outMode == nrLDPC_outMode_LLRINT8 ? (int8_t*)p_out : llrOut;
int8_t* p_llrOut = outMode == nrLDPC_outMode_LLRINT8 ? p_out : llrOut;
nrLDPC_llrRes2llrOut(p_lut, p_llrOut, llrRes, Z, BG);
if (outMode == nrLDPC_outMode_BIT)
nrLDPC_llr2bitPacked(p_out, p_llrOut, numLLR);
@@ -837,8 +837,6 @@ static inline uint32_t nrLDPC_decoder_core(int8_t* p_llr,
if (p_decParams->check_crc((uint8_t*)p_out, p_decParams->Kprime, p_decParams->crc_type)) {
LOG_D(PHY, "Segment CRC OK, exiting LDPC decoder\n");
break;
} else {
LOG_D(PHY, "Segment CRC NOK, Kprime %d, BG %d, Z %d\n", p_decParams->Kprime, BG, Z);
}
}
}
@@ -847,7 +845,7 @@ static inline uint32_t nrLDPC_decoder_core(int8_t* p_llr,
}
if (!p_decParams->check_crc) {
int8_t llrOut[NR_LDPC_MAX_NUM_LLR] __attribute__((aligned(64))) = {0};
int8_t* p_llrOut = outMode == nrLDPC_outMode_LLRINT8 ? (int8_t*)p_out : llrOut;
int8_t* p_llrOut = outMode == nrLDPC_outMode_LLRINT8 ? p_out : llrOut;
// Assign results from processing buffer to output
NR_LDPC_PROFILER_DETAIL(start_meas(&p_profiler->llrRes2llrOut));
nrLDPC_llrRes2llrOut(p_lut, p_llrOut, llrRes, Z, BG);

View File

@@ -39,11 +39,9 @@ typedef struct {
unsigned int first_seg; // optim8segmulti
unsigned char gen_code; // orig
time_stats_t *tinput;
time_stats_t *tinput_memcpy;
time_stats_t *tprep;
time_stats_t *tparity;
time_stats_t *toutput;
time_stats_t *tconcat;
/// Size in bits of the code segments
uint32_t K;
/// Number of lifting sizes to fit the payload
@@ -73,7 +71,7 @@ typedef int32_t(LDPC_shutdownfunc_t)(void);
*/
typedef int32_t(LDPC_decoderfunc_t)(t_nrLDPC_dec_params *p_decParams,
int8_t *p_llr,
uint8_t *p_out,
int8_t *p_out,
t_nrLDPC_time_stats *time_stats,
decode_abort_t *ab);
typedef int32_t(LDPC_encoderfunc_t)(uint8_t **, uint8_t *, encoder_implemparams_t *);

View File

@@ -80,11 +80,9 @@
#include "ldpc_BG2_Zc80_byte.c"
#include "ldpc_BG2_Zc72_byte.c"
static void encode_parity_check_part_optim(uint8_t *cc, uint8_t *d, short BG, short Zc, int simd_size, int ncols, time_stats_t *tinput_memcpy)
static void encode_parity_check_part_optim(uint8_t *cc, uint8_t *d, short BG, short Zc, int simd_size, int ncols)
{
unsigned char c[2 * 22 * Zc * simd_size] __attribute__((aligned(64))); //double size matrix of c
if (tinput_memcpy)
start_meas(tinput_memcpy);
for (int i1 = 0; i1 < ncols; i1++) {
memcpy(&c[2 * i1 * Zc], &cc[i1 * Zc], Zc * sizeof(unsigned char));
memcpy(&c[(2 * i1 + 1) * Zc], &cc[i1 * Zc], Zc * sizeof(unsigned char));
@@ -97,8 +95,6 @@ static void encode_parity_check_part_optim(uint8_t *cc, uint8_t *d, short BG, sh
memcpy(&c[(2 * ncols * Zc * i1)], &c[i1], (2 * ncols * Zc * sizeof(unsigned char)) - i1);
}
}
if (tinput_memcpy)
stop_meas(tinput_memcpy);
if (BG == 1) {
switch (Zc) {
case 176:

View File

@@ -169,23 +169,23 @@ int LDPCencoder(uint8_t **input, uint8_t *output, encoder_implemparams_t *impp)
if(impp->tinput != NULL) stop_meas(impp->tinput);
if ((BG == 1 && Zc >= 176) || (BG == 2 && Zc >= 72)) {
if ((BG==1 && Zc>=176) || (BG==2 && Zc>=72)) {
// extend matrix
if(impp->tprep != NULL) start_meas(impp->tprep);
if(impp->tprep != NULL) stop_meas(impp->tprep);
//parity check part
if(impp->tparity != NULL) start_meas(impp->tparity);
encode_parity_check_part_optim(cc, dd, BG, Zc, simd_size, ncols, impp->tinput_memcpy);
encode_parity_check_part_optim(cc, dd, BG, Zc, simd_size, ncols);
if(impp->tparity != NULL) stop_meas(impp->tparity);
} else {
}
else {
if (encode_parity_check_part_orig(cc, dd, BG, Zc, Kb, block_length)!=0) {
printf("Problem with encoder\n");
return(-1);
}
}
if (impp->toutput != NULL)
start_meas(impp->toutput);
memcpy(output,&cc[2*Zc],(block_length-(2*Zc)));
memcpy(output+block_length-(2*Zc),dd,((nrows-no_punctured_columns) * Zc-removed_bit));
if (impp->toutput != NULL)
stop_meas(impp->toutput);
return 0;
}

View File

@@ -119,6 +119,8 @@ void phy_init_nr_gNB(PHY_VARS_gNB *gNB)
nr_init_fde(); // Init array for frequency equalization of transform precoding of PUSCH
int ret_loader = load_nrLDPC_coding_interface(NULL, &gNB->nrLDPC_coding_interface);
AssertFatal(ret_loader == 0, "error loading LDPC library\n");
gNB->max_nb_pdsch = MAX_MOBILES_PER_GNB;
init_delay_table(fp->ofdm_symbol_size, MAX_DELAY_COMP, NR_MAX_OFDM_SYMBOL_SIZE, fp->delay_table);
@@ -139,9 +141,6 @@ void phy_init_nr_gNB(PHY_VARS_gNB *gNB)
/// Transport init necessary for NR synchro
init_nr_transport(gNB);
int ret_loader = load_nrLDPC_coding_interface(NULL, &gNB->nrLDPC_coding_interface, 16 * gNB->max_nb_pusch);
AssertFatal(ret_loader == 0, "error loading LDPC library\n");
init_DLSCH_struct(gNB);
/* Do NOT allocate per-antenna rxdataF: the gNB gets a pointer to the

View File

@@ -329,6 +329,11 @@ void free_nr_ue_dl_harq(NR_DL_UE_HARQ_t harq_list[2][NR_MAX_HARQ_PROCESSES], int
for (int j=0; j < 2; j++) {
for (int i=0; i<number_of_processes; i++) {
for (int r=0; r<a_segments; r++) {
free_and_zero(harq_list[j][i].c[r]);
free_and_zero(harq_list[j][i].d[r]);
}
free_and_zero(harq_list[j][i].b);
free_and_zero(harq_list[j][i].c);
free_and_zero(harq_list[j][i].d);
@@ -381,9 +386,14 @@ void nr_init_dl_harq_processes(NR_DL_UE_HARQ_t harq_list[2][NR_MAX_HARQ_PROCESSE
init_downlink_harq_status(harq_list[j] + i);
harq_list[j][i].b = malloc16_clear(a_segments * 1056);
harq_list[j][i].c = malloc16(a_segments * sizeof(*harq_list[j][i].c) * 1056);
harq_list[j][i].d = malloc16(a_segments * sizeof(*harq_list[j][i].d) * 3 * 8448);
harq_list[j][i].c = malloc16(a_segments*sizeof(uint8_t *));
harq_list[j][i].d = malloc16(a_segments*sizeof(int16_t *));
const int sz=5*8448*sizeof(int16_t);
init_abort(&harq_list[j][i].abort_decode);
for (int r=0; r<a_segments; r++) {
harq_list[j][i].c[r] = malloc16_clear(1056);
harq_list[j][i].d[r] = malloc16_clear(sz);
}
harq_list[j][i].status = 0;
harq_list[j][i].DLround = 0;
}

View File

@@ -320,8 +320,8 @@ void fft_shift(const c16_t *in,
const int first_carrier_offset = fft_size_out - num_samp_half;
for (int s = start_symb; s < start_symb + num_symb; s++) {
// Copy negative freq component
uint32_t out_offset = s * fft_size_out + first_carrier_offset;
uint32_t in_offset = s * in_symb_sz;
uint16_t out_offset = s * fft_size_out + first_carrier_offset;
uint16_t in_offset = s * in_symb_sz;
memcpy(out + out_offset, in + in_offset, num_samp_half * sizeof(int32_t));
// Copy positive freq component
out_offset = s * fft_size_out;

View File

@@ -789,11 +789,9 @@ void nr_generate_pdsch(PHY_VARS_gNB *gNB, int n_dlsch, NR_gNB_DLSCH_t *dlsch_arr
{
time_stats_t *dlsch_encoding_stats = &gNB->dlsch_encoding_stats;
time_stats_t *tinput = &gNB->tinput;
time_stats_t *tinput_memcpy = &gNB->tinput_memcpy;
time_stats_t *tprep = &gNB->tprep;
time_stats_t *tparity = &gNB->tparity;
time_stats_t *toutput = &gNB->toutput;
time_stats_t *tconcat = &gNB->tconcat;
time_stats_t *dlsch_rate_matching_stats = &gNB->dlsch_rate_matching_stats;
time_stats_t *dlsch_interleaving_stats = &gNB->dlsch_interleaving_stats;
time_stats_t *dlsch_segmentation_stats = &gNB->dlsch_segmentation_stats;
@@ -856,11 +854,9 @@ void nr_generate_pdsch(PHY_VARS_gNB *gNB, int n_dlsch, NR_gNB_DLSCH_t *dlsch_arr
slot,
output,
tinput,
tinput_memcpy,
tprep,
tparity,
toutput,
tconcat,
dlsch_rate_matching_stats,
dlsch_interleaving_stats,
dlsch_segmentation_stats)

View File

@@ -20,11 +20,9 @@ int nr_dlsch_encoding(PHY_VARS_gNB *gNB,
uint8_t slot,
unsigned char *output,
time_stats_t *tinput,
time_stats_t *tinput_memcpy,
time_stats_t *tprep,
time_stats_t *tparity,
time_stats_t *toutput,
time_stats_t *tconcat,
time_stats_t *dlsch_rate_matching_stats,
time_stats_t *dlsch_interleaving_stats,
time_stats_t *dlsch_segmentation_stats);

View File

@@ -91,11 +91,9 @@ int nr_dlsch_encoding(PHY_VARS_gNB *gNB,
uint8_t slot,
unsigned char *output,
time_stats_t *tinput,
time_stats_t *tinput_memcpy,
time_stats_t *tprep,
time_stats_t *tparity,
time_stats_t *toutput,
time_stats_t *tconcat,
time_stats_t *dlsch_rate_matching_stats,
time_stats_t *dlsch_interleaving_stats,
time_stats_t *dlsch_segmentation_stats)

View File

@@ -47,8 +47,13 @@ void free_gNB_ulsch(NR_gNB_ULSCH_t *ulsch, uint16_t N_RB_UL)
free_and_zero(ulsch->harq_process->b);
ulsch->harq_process->b = NULL;
}
for (int r = 0; r < a_segments; r++) {
free_and_zero(ulsch->harq_process->c[r]);
free_and_zero(ulsch->harq_process->d[r]);
}
free_and_zero(ulsch->harq_process->c);
free_and_zero(ulsch->harq_process->d);
free_and_zero(ulsch->harq_process->d_to_be_cleared);
free_and_zero(ulsch->harq_process);
ulsch->harq_process = NULL;
}
@@ -74,9 +79,14 @@ NR_gNB_ULSCH_t new_gNB_ulsch(uint8_t max_ldpc_iterations, uint16_t N_RB_UL)
init_abort(&harq->abort_decode);
ulsch.harq_process = harq;
harq->b = malloc16_clear(ulsch_bytes * sizeof(*harq->b));
// Allocate one contiguous buffer fr all c/d arrays to simplify addressing for GPU LDPC offload
harq->c = malloc16_clear(a_segments * 8448 * sizeof(*harq->c));
harq->d = malloc16_clear(a_segments * 68 * 384 * sizeof(*harq->d));
harq->c = malloc16_clear(a_segments * sizeof(*harq->c));
harq->d = malloc16_clear(a_segments * sizeof(*harq->d));
for (int r = 0; r < a_segments; r++) {
harq->c[r] = malloc16_clear(8448 * sizeof(*harq->c[r]));
harq->d[r] = malloc16_clear(68 * 384 * sizeof(*harq->d[r]));
}
harq->d_to_be_cleared = calloc(a_segments, sizeof(bool));
AssertFatal(harq->d_to_be_cleared != NULL, "out of memory\n");
return (ulsch);
}
@@ -213,6 +223,9 @@ int nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB,
set_abort(&harq_process->abort_decode, false);
}
nrLDPC_segment_decoding_parameters_t segments[nb_pusch][max_num_segments];
memset(segments, 0, sizeof(segments));
for (uint8_t pusch_id = 0; pusch_id < nb_pusch; pusch_id++) {
uint8_t ULSCH_id = ULSCH_ids[pusch_id];
NR_gNB_ULSCH_t *ulsch = &phy_vars_gNB->ulsch[ULSCH_id];
@@ -225,79 +238,66 @@ int nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB,
}
nrLDPC_TB_decoding_parameters_t *TB_parameters = &TBs[pusch_id];
TB_parameters->segments = segments[pusch_id];
TB_parameters->llr = ulsch_llr;
TB_parameters->d = harq_process->d;
TB_parameters->c = harq_process->c;
TB_parameters->E = nr_get_E(TB_parameters->G, TB_parameters->C, TB_parameters->Qm, TB_parameters->nb_layers, 0);
TB_parameters->first_rE2 = TB_parameters->C;
TB_parameters->E2 = TB_parameters->E;
TB_parameters->R = nr_get_R_ldpc_decoder(TB_parameters->rv_index,
TB_parameters->E,
TB_parameters->BG,
TB_parameters->Z,
&harq_process->llrLen,
harq_process->round);
for (int r = 0; r < TB_parameters->C; r++)
TB_parameters->decodeSuccess[r] = false;
TB_parameters->d_to_be_cleared = harq_process->harq_to_be_cleared;
reset_meas(&TB_parameters->ts_deinterleave);
reset_meas(&TB_parameters->ts_rate_unmatch);
reset_meas(&TB_parameters->ts_seg_prep);
reset_meas(&TB_parameters->ts_ldpc_decode);
uint32_t r_offset = 0;
for (int r = 0; r < TB_parameters->C; r++) {
int Etmp = nr_get_E(TB_parameters->G, TB_parameters->C, TB_parameters->Qm, TB_parameters->nb_layers, r);
if (TB_parameters->E != Etmp) {
TB_parameters->E2 = Etmp;
TB_parameters->R2 = nr_get_R_ldpc_decoder(TB_parameters->rv_index,
TB_parameters->E2,
TB_parameters->BG,
TB_parameters->Z,
&harq_process->llrLen,
harq_process->round);
TB_parameters->first_rE2 = r;
break;
nrLDPC_segment_decoding_parameters_t *segment_parameters = &TB_parameters->segments[r];
segment_parameters->E = nr_get_E(TB_parameters->G, TB_parameters->C, TB_parameters->Qm, TB_parameters->nb_layers, r);
segment_parameters->R = nr_get_R_ldpc_decoder(TB_parameters->rv_index,
segment_parameters->E,
TB_parameters->BG,
TB_parameters->Z,
&harq_process->llrLen,
harq_process->round);
segment_parameters->llr = ulsch_llr + r_offset;
segment_parameters->d = harq_process->d[r];
segment_parameters->d_to_be_cleared = &harq_process->d_to_be_cleared[r];
segment_parameters->c = harq_process->c[r];
segment_parameters->decodeSuccess = false;
reset_meas(&segment_parameters->ts_deinterleave);
reset_meas(&segment_parameters->ts_rate_unmatch);
reset_meas(&segment_parameters->ts_ldpc_decode);
r_offset += segment_parameters->E;
}
if (harq_process->harq_to_be_cleared) {
for (int r = 0; r < TB_parameters->C; r++) {
harq_process->d_to_be_cleared[r] = true;
}
harq_process->harq_to_be_cleared = false;
}
}
int ret_decoder = phy_vars_gNB->nrLDPC_coding_interface.nrLDPC_coding_decoder(&slot_parameters);
// post decode
for (uint8_t pusch_id = 0; pusch_id < nb_pusch; pusch_id++) {
uint8_t ULSCH_id = ULSCH_ids[pusch_id];
NR_gNB_ULSCH_t *ulsch = &phy_vars_gNB->ulsch[ULSCH_id];
NR_UL_gNB_HARQ_t *harq_process = ulsch->harq_process;
nrLDPC_TB_decoding_parameters_t *TB_parameters = &TBs[pusch_id];
nrLDPC_TB_decoding_parameters_t TB_parameters = TBs[pusch_id];
uint32_t offset = 0, r_offset = 0;
bool crcok = true;
LOG_D(PHY, "C = %d\n", TB_parameters->C);
for (int r = 0; r < TB_parameters->C; r++) {
LOG_D(PHY, "Segment %d %d\n", r, TB_parameters->decodeSuccess[r]);
if (TB_parameters->decodeSuccess[r] == false) {
LOG_D(PHY, "Segment %d/%d in error\n", r, TB_parameters->C);
crcok = false;
break;
}
}
if (crcok) {
for (int r = 0; r < TB_parameters->C; r++) {
// Copy c to b in case of decoding success
uint32_t offset = 0;
for (int r = 0; r < TB_parameters.C; r++) {
nrLDPC_segment_decoding_parameters_t nrLDPC_segment_decoding_parameters = TB_parameters.segments[r];
// Copy c to b in case of decoding success
if (nrLDPC_segment_decoding_parameters.decodeSuccess) {
memcpy(harq_process->b + offset,
harq_process->c + r_offset,
harq_process->c[r],
(harq_process->K >> 3) - (harq_process->F >> 3) - ((harq_process->C > 1) ? 3 : 0));
offset += ((harq_process->K >> 3) - (harq_process->F >> 3) - ((harq_process->C > 1) ? 3 : 0));
r_offset += (harq_process->K >> 3);
} else {
LOG_D(PHY, "uplink segment error %d/%d\n", r, harq_process->C);
LOG_D(PHY, "ULSCH %d in error\n", ULSCH_id);
}
} else {
LOG_D(PHY, "ULSCH %d in error\n", ULSCH_id);
offset += ((harq_process->K >> 3) - (harq_process->F >> 3) - ((harq_process->C > 1) ? 3 : 0));
merge_meas(&phy_vars_gNB->ts_deinterleave, &nrLDPC_segment_decoding_parameters.ts_deinterleave);
merge_meas(&phy_vars_gNB->ts_rate_unmatch, &nrLDPC_segment_decoding_parameters.ts_rate_unmatch);
merge_meas(&phy_vars_gNB->ts_ldpc_decode, &nrLDPC_segment_decoding_parameters.ts_ldpc_decode);
}
merge_meas(&phy_vars_gNB->ts_deinterleave, &TB_parameters->ts_deinterleave);
merge_meas(&phy_vars_gNB->ts_rate_unmatch, &TB_parameters->ts_rate_unmatch);
merge_meas(&phy_vars_gNB->ts_seg_prep, &TB_parameters->ts_seg_prep);
merge_meas(&phy_vars_gNB->ts_ldpc_decode, &TB_parameters->ts_ldpc_decode);
harq_process->harq_to_be_cleared = false;
}
return ret_decoder;

View File

@@ -866,17 +866,14 @@ static void inner_rx(PHY_VARS_gNB *gNB,
int output_shift,
uint32_t nvar,
c16_t *rxFext_slot,
c16_t *chFext_slot,
time_stats_t *pusch_extr,
time_stats_t *pusch_ch_comp,
time_stats_t *ulsch_llr)
c16_t *chFext_slot)
{
int nb_layer = rel15_ul->nrOfLayers;
int nb_rx_ant = frame_parms->nb_antennas_rx;
int dmrs_symbol_flag = (rel15_ul->ul_dmrs_symb_pos >> symbol) & 0x01;
int buffer_length = ceil_mod(rel15_ul->rb_size * NR_NB_SC_PER_RB, 16);
c16_t rxFext[nb_rx_ant][buffer_length] __attribute__((aligned(64)));
c16_t chFext[nb_layer][nb_rx_ant][buffer_length] __attribute__((aligned(64)));
c16_t rxFext[nb_rx_ant][buffer_length] __attribute__((aligned(32)));
c16_t chFext[nb_layer][nb_rx_ant][buffer_length] __attribute__((aligned(32)));
memset(rxFext, 0, sizeof(rxFext));
memset(chFext, 0, sizeof(chFext));
@@ -890,7 +887,6 @@ static void inner_rx(PHY_VARS_gNB *gNB,
for (int aarx = 0; aarx < nb_rx_ant; aarx++) {
for (int aatx = 0; aatx < nb_layer; aatx++) {
start_meas(pusch_extr);
nr_ulsch_extract_rbs(rxF[aarx],
(c16_t *)pusch_vars->ul_ch_estimates[aatx * nb_rx_ant + aarx],
rxFext[aarx],
@@ -900,7 +896,6 @@ static void inner_rx(PHY_VARS_gNB *gNB,
dmrs_symbol_flag,
rel15_ul,
frame_parms);
stop_meas(pusch_extr);
#if T_TRACER
// Data Recording application supports only 1 layer and 1 Tx antenna, so only record the first layer and first Tx antenna
if (aatx == 0 && aarx == 0) {
@@ -916,11 +911,10 @@ static void inner_rx(PHY_VARS_gNB *gNB,
#endif
}
}
start_meas(pusch_ch_comp);
c16_t rho[nb_layer][nb_layer][buffer_length] __attribute__((aligned(64)));
c16_t rxF_ch_maga[nb_layer][buffer_length] __attribute__((aligned(64)));
c16_t rxF_ch_magb[nb_layer][buffer_length] __attribute__((aligned(64)));
c16_t rxF_ch_magc[nb_layer][buffer_length] __attribute__((aligned(64)));
c16_t rho[nb_layer][nb_layer][buffer_length] __attribute__((aligned(32)));
c16_t rxF_ch_maga[nb_layer][buffer_length] __attribute__((aligned(32)));
c16_t rxF_ch_magb[nb_layer][buffer_length] __attribute__((aligned(32)));
c16_t rxF_ch_magc[nb_layer][buffer_length] __attribute__((aligned(32)));
memset(rho, 0, sizeof(rho));
memset(rxF_ch_maga, 0, sizeof(rxF_ch_maga));
@@ -942,7 +936,6 @@ static void inner_rx(PHY_VARS_gNB *gNB,
rel15_ul,
symbol,
output_shift);
stop_meas(pusch_ch_comp);
if (nb_layer == 1 && rel15_ul->transform_precoding == transformPrecoder_enabled && rel15_ul->qam_mod_order <= 6) {
if (rel15_ul->qam_mod_order > 2)
@@ -965,7 +958,7 @@ static void inner_rx(PHY_VARS_gNB *gNB,
buffer_length);
pusch_vars->ul_valid_re_per_slot[symbol] -= pusch_vars->ptrs_re_per_slot;
}
start_meas(ulsch_llr);
if (nb_layer == 2) {
if (rel15_ul->qam_mod_order <= 6) {
nr_ulsch_compute_ML_llr((c16_t *)&pusch_vars->rxdataF_comp[0][symbol * buffer_length],
@@ -1005,7 +998,6 @@ static void inner_rx(PHY_VARS_gNB *gNB,
pusch_vars->ul_valid_re_per_slot[symbol],
symbol,
rel15_ul->qam_mod_order);
stop_meas(ulsch_llr);
}
typedef struct puschSymbolProc_s {
@@ -1020,11 +1012,6 @@ typedef struct puschSymbolProc_s {
int16_t *scramblingSequence;
uint32_t nvar;
int beam_nb;
time_stats_t pusch_extr;
time_stats_t pusch_ch_comp;
time_stats_t ulsch_llr;
time_stats_t ul_demap;
time_stats_t ul_unscram;
task_ans_t *ans;
c16_t *pusch_ch_est_dmrs_interpl_slot_mem;
c16_t *rxFext_slot_mem;
@@ -1061,14 +1048,10 @@ static void nr_pusch_symbol_processing(void *arg)
pusch_vars->log2_maxh,
rdata->nvar,
rdata->rxFext_slot_mem,
rdata->pusch_ch_est_dmrs_interpl_slot_mem,
&rdata->pusch_extr,
&rdata->pusch_ch_comp,
&rdata->ulsch_llr);
rdata->pusch_ch_est_dmrs_interpl_slot_mem);
int nb_re_pusch = pusch_vars->ul_valid_re_per_slot[symbol];
// layer de-mapping
start_meas(&rdata->ul_demap);
int16_t *llr_ptr = llrs[0];
if (rel15_ul->nrOfLayers != 1) {
llr_ptr = &rdata->llr[pusch_vars->llr_offset[symbol] * rel15_ul->nrOfLayers];
@@ -1078,21 +1061,12 @@ static void nr_pusch_symbol_processing(void *arg)
llr_ptr[i * rel15_ul->nrOfLayers * rel15_ul->qam_mod_order + l * rel15_ul->qam_mod_order + m] =
llrss[l][i * rel15_ul->qam_mod_order + m];
}
stop_meas(&rdata->ul_demap);
// unscrambling
start_meas(&rdata->ul_unscram);
int16_t *llr16 = (int16_t*)&rdata->llr[pusch_vars->llr_offset[symbol] * rel15_ul->nrOfLayers];
int16_t *s = rdata->scramblingSequence + pusch_vars->llr_offset[symbol] * rel15_ul->nrOfLayers;
const int end = nb_re_pusch * rel15_ul->qam_mod_order * rel15_ul->nrOfLayers;
int i = 0;
for (; (i + 8) <= end; i += 8) {
simde__m128i llr128 = simde_mm_loadu_si128((simde__m128i *)&llr_ptr[i]);
simde__m128i s128 = simde_mm_loadu_si128((simde__m128i *)&s[i]);
simde_mm_storeu_si128(llr16 + i, simde_mm_mullo_epi16(llr128, s128));
}
for (; i < end; i++)
for (int i = 0; i < end; i++)
llr16[i] = llr_ptr[i] * s[i];
stop_meas(&rdata->ul_unscram);
}
// Task running in // completed
@@ -1143,13 +1117,13 @@ int nr_rx_pusch_tp(PHY_VARS_gNB *gNB,
// int nb_layer (= rel15_ul->nrOfLayers) is limited to 1 for data recording application.
// Initialize memory for DMRS signals
c16_t pusch_dmrs_slot_mem[1 * buffer_length_slot] __attribute__((aligned(64)));
c16_t pusch_dmrs_slot_mem[1 * buffer_length_slot] __attribute__((aligned(32)));
// Initialize memory for channel estimates based on DMRS positions
c16_t pusch_ch_est_dmrs_pos_slot_mem[buffer_length_slot * 1 * 1] __attribute__((aligned(64)));
c16_t pusch_ch_est_dmrs_pos_slot_mem[buffer_length_slot * 1 * 1] __attribute__((aligned(32)));
// memory to store slot grid with channel coefficients based on DMRS positions after interpolation
c16_t pusch_ch_est_dmrs_interpl_slot_mem[buffer_length_slot * 1 * 1] __attribute__((aligned(64)));
c16_t pusch_ch_est_dmrs_interpl_slot_mem[buffer_length_slot * 1 * 1] __attribute__((aligned(32)));
// memory to store extracted data including PUSCH + DMRS
c16_t rxFext_slot_mem[1 * buffer_length_slot] __attribute__((aligned(64)));
c16_t rxFext_slot_mem[1 * buffer_length_slot] __attribute__((aligned(32)));
#if T_TRACER
// Initialize memory for DMRS signals
@@ -1298,7 +1272,7 @@ int nr_rx_pusch_tp(PHY_VARS_gNB *gNB,
*ret_unav_res = unav_res;
// initialize scrambling sequence //
int16_t scramblingSequence[G + 96] __attribute__((aligned(64)));
int16_t scramblingSequence[G + 96] __attribute__((aligned(32)));
nr_codeword_unscrambling_init(scramblingSequence, G, 0, rel15_ul->data_scrambling_id, rel15_ul->rnti);
@@ -1325,13 +1299,12 @@ int nr_rx_pusch_tp(PHY_VARS_gNB *gNB,
else // average of channel estimates stored in first symbol
dmrs_symbol = get_next_dmrs_symbol_in_slot(rel15_ul->ul_dmrs_symb_pos, rel15_ul->start_symbol_index, end_symbol);
int size_est = nb_re_pusch * frame_parms->symbols_per_slot;
__attribute__((aligned(64))) int ul_ch_estimates_ext[rel15_ul->nrOfLayers * frame_parms->nb_antennas_rx][size_est];
__attribute__((aligned(32))) int ul_ch_estimates_ext[rel15_ul->nrOfLayers * frame_parms->nb_antennas_rx][size_est];
memset(ul_ch_estimates_ext, 0, sizeof(ul_ch_estimates_ext));
int buffer_length = rel15_ul->rb_size * NR_NB_SC_PER_RB;
c16_t temp_rxFext[frame_parms->nb_antennas_rx][buffer_length] __attribute__((aligned(64)));
for (int aarx = 0; aarx < frame_parms->nb_antennas_rx; aarx++)
for (int nl = 0; nl < rel15_ul->nrOfLayers; nl++) {
start_meas(&gNB->pusch_extraction_stats);
c16_t temp_rxFext[frame_parms->nb_antennas_rx][buffer_length] __attribute__((aligned(32)));
for (int aarx = 0; aarx < frame_parms->nb_antennas_rx; aarx++)
for (int nl = 0; nl < rel15_ul->nrOfLayers; nl++)
nr_ulsch_extract_rbs(gNB->common_vars.rxdataF[beam_nb][aarx],
(c16_t *)pusch_vars->ul_ch_estimates[nl * frame_parms->nb_antennas_rx + aarx],
temp_rxFext[aarx],
@@ -1341,8 +1314,6 @@ int nr_rx_pusch_tp(PHY_VARS_gNB *gNB,
(rel15_ul->ul_dmrs_symb_pos >> meas_symbol) & 0x01,
rel15_ul,
frame_parms);
stop_meas(&gNB->pusch_extraction_stats);
}
uint8_t shift_ch_ext = rel15_ul->nrOfLayers > 1 ? log2_approx(max_ch >> 11) : 0;
@@ -1422,11 +1393,6 @@ int nr_rx_pusch_tp(PHY_VARS_gNB *gNB,
rdata->beam_nb = beam_nb;
rdata->rxFext_slot_mem = rxFext_slot_mem;
rdata->pusch_ch_est_dmrs_interpl_slot_mem = pusch_ch_est_dmrs_interpl_slot_mem;
reset_meas(&rdata->pusch_extr);
reset_meas(&rdata->pusch_ch_comp);
reset_meas(&rdata->ulsch_llr);
reset_meas(&rdata->ul_demap);
reset_meas(&rdata->ul_unscram);
if (rel15_ul->pdu_bit_map & PUSCH_PDU_BITMAP_PUSCH_PTRS) {
nr_pusch_symbol_processing(rdata);
@@ -1467,15 +1433,6 @@ int nr_rx_pusch_tp(PHY_VARS_gNB *gNB,
#endif
join_task_ans(&ans);
for (int i = 0; i < sz_arr; ++i) {
// retrieve measurements
puschSymbolProc_t *rdata = &arr[i];
merge_meas(&gNB->pusch_extraction_stats, &rdata->pusch_extr);
merge_meas(&gNB->pusch_channel_compensation_stats, &rdata->pusch_ch_comp);
merge_meas(&gNB->ulsch_llr_stats, &rdata->ulsch_llr);
merge_meas(&gNB->ulsch_layer_demapping_stats, &rdata->ul_demap);
merge_meas(&gNB->ulsch_unscrambling_stats, &rdata->ul_unscram);
}
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

View File

@@ -31,7 +31,7 @@ void nr_fill_srs(PHY_VARS_gNB *gNB, frame_t frame, slot_t slot, nfapi_nr_srs_pdu
{
NR_gNB_SRS_job_t srs = {.frame = frame, .slot = slot, .srs_pdu = *srs_pdu};
if (gNB->common_vars.beam_id) {
const uint8_t l0 = srs_pdu->time_start_position; // L2 already sends the absolute symbol index
const uint8_t l0 = gNB->frame_parms.symbols_per_slot - 1 - srs_pdu->time_start_position;
int bitmap = SL_to_bitmap(l0, 1 << srs_pdu->num_symbols);
int fapi_beam_idx = srs_pdu->beamforming.prgs_list[0].dig_bf_interface_list[0].beam_idx;
srs.beam_nb = beam_index_allocation(gNB->enable_analog_das,
@@ -57,7 +57,7 @@ int nr_get_srs_signal(PHY_VARS_gNB *gNB,
const NR_DL_FRAME_PARMS *frame_parms = &gNB->frame_parms;
const uint16_t n_symbols = (slot % RU_RX_SLOT_DEPTH) * frame_parms->symbols_per_slot; // number of symbols until this slot
const uint8_t l0 = srs_pdu->time_start_position; // starting symbol in this slot (L2 sends absolute symbol index)
const uint8_t l0 = frame_parms->symbols_per_slot - 1 - srs_pdu->time_start_position; // starting symbol in this slot
const uint64_t symbol_offset = (n_symbols + l0) * frame_parms->ofdm_symbol_size;
const uint64_t subcarrier_offset = frame_parms->first_carrier_offset + srs_pdu->bwp_start * NR_NB_SC_PER_RB;

View File

@@ -1349,94 +1349,127 @@ void nr_pdsch_ptrs_processing(int nbRx,
int nl,
c16_t rxdataF_comp[][nl][nbRx][rx_size_symbol],
NR_DL_FRAME_PARMS *frame_parms,
fapi_nr_dl_config_dlsch_pdu_rel15_t *dlsch_config,
NR_DL_UE_HARQ_t *dlsch0_harq,
NR_DL_UE_HARQ_t *dlsch1_harq,
uint8_t nr_slot_rx,
unsigned char symbol,
int nb_rb,
uint16_t rnti,
uint16_t *ptrsSymbPos,
uint8_t *ptrsSymbIdx)
NR_UE_DLSCH_t dlsch[2])
{
//#define DEBUG_DL_PTRS 1
int32_t *ptrs_re_symbol = NULL;
int8_t ret = 0;
/* harq specific variables */
int symbInSlot = dlsch_config->start_symbol + dlsch_config->number_symbols;
int startSymbIndex = dlsch_config->start_symbol;
int nbSymb = dlsch_config->number_symbols;
int L_ptrs = dlsch_config->PTRSTimeDensity;
int K_ptrs = dlsch_config->PTRSFreqDensity;
int dmrsSymbPos = dlsch_config->dlDmrsSymbPos;
int ptrsReOffset = dlsch_config->PTRSReOffset;
int nscid = dlsch_config->nscid;
uint8_t symbInSlot = 0;
uint16_t *startSymbIndex = NULL;
uint16_t *nbSymb = NULL;
uint8_t *L_ptrs = NULL;
uint8_t *K_ptrs = NULL;
uint16_t *dmrsSymbPos = NULL;
uint16_t *ptrsSymbPos = NULL;
uint8_t *ptrsSymbIdx = NULL;
uint8_t *ptrsReOffset = NULL;
int nscid = 0;
if(dlsch0_harq->status == NR_ACTIVE) {
symbInSlot = dlsch[0].dlsch_config.start_symbol + dlsch[0].dlsch_config.number_symbols;
startSymbIndex = &dlsch[0].dlsch_config.start_symbol;
nbSymb = &dlsch[0].dlsch_config.number_symbols;
L_ptrs = &dlsch[0].dlsch_config.PTRSTimeDensity;
K_ptrs = &dlsch[0].dlsch_config.PTRSFreqDensity;
dmrsSymbPos = &dlsch[0].dlsch_config.dlDmrsSymbPos;
ptrsReOffset = &dlsch[0].dlsch_config.PTRSReOffset;
ptrsSymbPos = &dlsch[0].ptrs_symbols;
ptrsSymbIdx = &dlsch[0].ptrs_symbol_index;
nscid = dlsch[0].dlsch_config.nscid;
}
if(dlsch1_harq) {
symbInSlot = dlsch[1].dlsch_config.start_symbol + dlsch[1].dlsch_config.number_symbols;
startSymbIndex = &dlsch[1].dlsch_config.start_symbol;
nbSymb = &dlsch[1].dlsch_config.number_symbols;
L_ptrs = &dlsch[1].dlsch_config.PTRSTimeDensity;
K_ptrs = &dlsch[1].dlsch_config.PTRSFreqDensity;
dmrsSymbPos = &dlsch[1].dlsch_config.dlDmrsSymbPos;
ptrsReOffset = &dlsch[1].dlsch_config.PTRSReOffset;
ptrsSymbPos = &dlsch[1].ptrs_symbols;
ptrsSymbIdx = &dlsch[1].ptrs_symbol_index;
nscid = dlsch[1].dlsch_config.nscid;
}
/* loop over antennas */
for (int aarx = 0; aarx < frame_parms->nb_antennas_rx; aarx++) {
for (int aarx=0; aarx<frame_parms->nb_antennas_rx; aarx++) {
c16_t *phase_per_symbol = (c16_t*)ptrs_phase_per_slot[aarx];
ptrs_re_symbol = (int32_t*)ptrs_re_per_slot[aarx];
ptrs_re_symbol[symbol] = 0;
phase_per_symbol[symbol].i = 0; // Imag
/* set DMRS estimates to 0 angle with magnitude 1 */
if(is_dmrs_symbol(symbol, dmrsSymbPos)) {
if(is_dmrs_symbol(symbol,*dmrsSymbPos)) {
/* set DMRS real estimation to 32767 */
phase_per_symbol[symbol].r=INT16_MAX; // 32767
#ifdef DEBUG_DL_PTRS
printf("[PHY][PTRS]: DMRS Symbol %d -> %4d + j*%4d\n", symbol, phase_per_symbol[symbol].r,phase_per_symbol[symbol].i);
#endif
} else { // real ptrs value is set to 0
}
else { // real ptrs value is set to 0
phase_per_symbol[symbol].r = 0; // Real
}
if (symbol == startSymbIndex) {
*ptrsSymbPos = 0;
set_ptrs_symb_idx(ptrsSymbPos, nbSymb, startSymbIndex, 1 << L_ptrs, dmrsSymbPos);
}
/* if not PTRS symbol set current ptrs symbol index to zero*/
*ptrsSymbIdx = 0;
/* Check if current symbol contains PTRS */
if (is_ptrs_symbol(symbol, *ptrsSymbPos)) {
*ptrsSymbIdx = symbol;
/*------------------------------------------------------------------------------------------------------- */
/* 1) Estimate common phase error per PTRS symbol */
/*------------------------------------------------------------------------------------------------------- */
const uint32_t *gold =
if(dlsch0_harq->status == NR_ACTIVE) {
if(symbol == *startSymbIndex) {
*ptrsSymbPos = 0;
set_ptrs_symb_idx(ptrsSymbPos,
*nbSymb,
*startSymbIndex,
1<< *L_ptrs,
*dmrsSymbPos);
}
/* if not PTRS symbol set current ptrs symbol index to zero*/
*ptrsSymbIdx = 0;
/* Check if current symbol contains PTRS */
if(is_ptrs_symbol(symbol, *ptrsSymbPos)) {
*ptrsSymbIdx = symbol;
/*------------------------------------------------------------------------------------------------------- */
/* 1) Estimate common phase error per PTRS symbol */
/*------------------------------------------------------------------------------------------------------- */
const uint32_t *gold =
nr_gold_pdsch(frame_parms->N_RB_DL, frame_parms->symbols_per_slot, frame_parms->Nid_cell, nscid, nr_slot_rx, symbol);
nr_ptrs_cpe_estimation(K_ptrs,
ptrsReOffset,
nb_rb,
rnti,
frame_parms->ofdm_symbol_size,
rxdataF_comp[symbol][0][aarx],
gold,
(int16_t *)&phase_per_symbol[symbol],
&ptrs_re_symbol[symbol]);
}
nr_ptrs_cpe_estimation(*K_ptrs,
*ptrsReOffset,
nb_rb,
rnti,
frame_parms->ofdm_symbol_size,
rxdataF_comp[symbol][0][aarx],
gold,
(int16_t *)&phase_per_symbol[symbol],
&ptrs_re_symbol[symbol]);
}
}// HARQ 0
/* For last OFDM symbol at each antenna perform interpolation and compensation for the slot*/
if (symbol == (symbInSlot -1)) {
if(symbol == (symbInSlot -1)) {
/*------------------------------------------------------------------------------------------------------- */
/* 2) Interpolate PTRS estimated value in TD */
/*------------------------------------------------------------------------------------------------------- */
/* If L-PTRS is > 0 then we need interpolation */
if (L_ptrs > 0) {
ret = nr_ptrs_process_slot(dmrsSymbPos, *ptrsSymbPos, (int16_t*)phase_per_symbol, startSymbIndex, nbSymb);
if(*L_ptrs > 0) {
ret = nr_ptrs_process_slot(*dmrsSymbPos, *ptrsSymbPos, (int16_t*)phase_per_symbol, *startSymbIndex, *nbSymb);
if(ret != 0) {
LOG_W(PHY,"[PTRS] Compensation is skipped due to error in PTRS slot processing !!\n");
}
}
#ifdef DEBUG_DL_PTRS
LOG_M("ptrsEst.m","est", ptrs_phase_per_slot[aarx], frame_parms->symbols_per_slot, 1, 1);
LOG_M("rxdataF_bf_ptrs_comp.m", "bf_ptrs_cmp", rxdataF_comp[0][aarx] + startSymbIndex * rx_size_symbol, rx_size_symbol * nbSymb, 1, 1);
LOG_M("ptrsEst.m","est",ptrs_phase_per_slot[aarx],frame_parms->symbols_per_slot,1,1 );
LOG_M("rxdataF_bf_ptrs_comp.m", "bf_ptrs_cmp", rxdataF_comp[0][aarx] + (*startSymbIndex) * rx_size_symbol, rx_size_symbol * (*nbSymb), 1, 1);
#endif
/*------------------------------------------------------------------------------------------------------- */
/* 3) Compensated DMRS based estimated signal with PTRS estimation */
/*--------------------------------------------------------------------------------------------------------*/
for(uint8_t i = startSymbIndex; i < symbInSlot; i++) {
for(uint8_t i = *startSymbIndex; i < symbInSlot; i++) {
/* DMRS Symbol has 0 phase so no need to rotate the respective symbol */
/* Skip rotation if the slot processing is wrong */
if((!is_dmrs_symbol(i, dmrsSymbPos)) && (ret == 0)) {
if((!is_dmrs_symbol(i, *dmrsSymbPos)) && (ret == 0)) {
#ifdef DEBUG_DL_PTRS
printf("[PHY][DL][PTRS]: Rotate Symbol %2d with %d + j* %d\n", i, phase_per_symbol[i].r, phase_per_symbol[i].i);
printf("[PHY][DL][PTRS]: Rotate Symbol %2d with %d + j* %d\n", i, phase_per_symbol[i].r,phase_per_symbol[i].i);
#endif
rotate_cpx_vector(rxdataF_comp[i][0][aarx], &phase_per_symbol[i], rxdataF_comp[i][0][aarx], nb_rb * NR_NB_SC_PER_RB, 15);
}// if not DMRS Symbol

View File

@@ -121,13 +121,13 @@ void nr_pdsch_ptrs_processing(int nbRx,
int nl,
c16_t rxdataF_comp[][nl][nbRx][rx_size_symbol],
NR_DL_FRAME_PARMS *frame_parms,
fapi_nr_dl_config_dlsch_pdu_rel15_t *dlsch_config,
NR_DL_UE_HARQ_t *dlsch0_harq,
NR_DL_UE_HARQ_t *dlsch1_harq,
uint8_t nr_slot_rx,
unsigned char symbol,
int nb_rb,
uint16_t rnti,
uint16_t *ptrsSymbPos,
uint8_t *ptrsSymbIdx);
NR_UE_DLSCH_t dlsch[2]);
int nr_sl_psbch_rsrp_measurements(PHY_VARS_NR_UE *ue,
sl_nr_ue_phy_params_t *sl_phy_params,

View File

@@ -167,7 +167,7 @@ static void send_ssb_rsrp_meas(PHY_VARS_NR_UE *ue,
nr_downlink_indication_t dl_indication = {0};
fapi_nr_rx_indication_t rx_ind = {0};
nr_fill_dl_indication(&dl_indication, NULL, &rx_ind, proc, ue, NULL);
nr_fill_rx_indication(&rx_ind, FAPI_NR_MEAS_IND, ue, 0, 0, NULL, 1, proc, &l1_measurements, NULL);
nr_fill_rx_indication(&rx_ind, FAPI_NR_MEAS_IND, ue, NULL, NULL, 1, proc, &l1_measurements, NULL);
ue->if_inst->dl_indication(&dl_indication);
}

View File

@@ -961,6 +961,6 @@ void nr_ue_csi_rs_procedures(PHY_VARS_NR_UE *ue,
nr_downlink_indication_t dl_indication;
fapi_nr_rx_indication_t rx_ind = {0};
nr_fill_dl_indication(&dl_indication, NULL, &rx_ind, proc, ue, NULL);
nr_fill_rx_indication(&rx_ind, FAPI_NR_MEAS_IND, ue, 0, 0, NULL, 1, proc, (void *)&l1_measurements, NULL);
nr_fill_rx_indication(&rx_ind, FAPI_NR_MEAS_IND, ue, NULL, NULL, 1, proc, (void *)&l1_measurements, NULL);
ue->if_inst->dl_indication(&dl_indication);
}

View File

@@ -43,149 +43,177 @@ void nr_dlsch_unscrambling(int16_t *llr, uint32_t size, uint8_t q, uint32_t Nid,
void nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue,
const UE_nr_rxtx_proc_t *proc,
NR_UE_DLSCH_t *dlsch,
int cw_idx,
fapi_nr_dl_config_dlsch_pdu_rel15_t *dlsch_config,
int16_t *dlsch_llr,
uint8_t *b,
int16_t **dlsch_llr,
uint8_t **b,
int *G,
int nb_dlsch,
int number_rbs,
int G)
uint8_t *DLSCH_ids)
{
nrLDPC_TB_decoding_parameters_t TB_parameters = {0};
nrLDPC_TB_decoding_parameters_t TBs[nb_dlsch];
memset(TBs, 0, sizeof(TBs));
nrLDPC_slot_decoding_parameters_t slot_parameters = {
.frame = proc->frame_rx,
.slot = proc->nr_slot_rx,
.nb_TBs = 1,
.nb_TBs = nb_dlsch,
.threadPool = &get_nrUE_params()->Tpool,
.TBs = &TB_parameters
.TBs = TBs
};
uint8_t dmrs_Type = dlsch_config->dmrsConfigType;
int harq_pid = dlsch_config->harq_process_nbr;
AssertFatal(dmrs_Type == 0 || dmrs_Type == 1, "Illegal dmrs_type %d\n", dmrs_Type);
fapi_nr_dl_cw_info_t *cw_info = &dlsch->cw_info;
NR_DL_UE_HARQ_t *harq_process = &phy_vars_ue->dl_harq_processes[cw_idx][dlsch_config->harq_process_nbr];
LOG_D(PHY, "Round %d RV idx %d\n", harq_process->DLround, cw_info->rv);
uint8_t nb_re_dmrs;
if (dmrs_Type == NFAPI_NR_DMRS_TYPE1)
nb_re_dmrs = 6 * dlsch_config->n_dmrs_cdm_groups;
else
nb_re_dmrs = 4 * dlsch_config->n_dmrs_cdm_groups;
uint16_t dmrs_length = get_num_dmrs(dlsch_config->dlDmrsSymbPos);
int max_num_segments = 0;
TB_parameters.harq_unique_pid = 2 * harq_pid + cw_idx;
TB_parameters.G = G;
TB_parameters.nb_rb = number_rbs;
TB_parameters.Qm = cw_info->qamModOrder;
TB_parameters.mcs = cw_info->mcs;
TB_parameters.nb_layers = cw_info->Nl;
TB_parameters.BG = cw_info->ldpcBaseGraph;
TB_parameters.A = cw_info->TBS;
TB_parameters.processedSegments = &harq_process->processedSegments;
for (uint8_t pdsch_id = 0; pdsch_id < nb_dlsch; pdsch_id++) {
uint8_t DLSCH_id = DLSCH_ids[pdsch_id];
fapi_nr_dl_config_dlsch_pdu_rel15_t *dlsch_config = &dlsch[DLSCH_id].dlsch_config;
uint8_t dmrs_Type = dlsch_config->dmrsConfigType;
int harq_pid = dlsch_config->harq_process_nbr;
NR_DL_UE_HARQ_t *harq_process = &phy_vars_ue->dl_harq_processes[DLSCH_id][harq_pid];
float Coderate = (float)cw_info->targetCodeRate / 10240.0f;
AssertFatal(dmrs_Type == 0 || dmrs_Type == 1, "Illegal dmrs_type %d\n", dmrs_Type);
uint8_t nb_re_dmrs;
LOG_D(PHY,
LOG_D(PHY, "Round %d RV idx %d\n", harq_process->DLround, dlsch->dlsch_config.rv);
if (dmrs_Type == NFAPI_NR_DMRS_TYPE1)
nb_re_dmrs = 6 * dlsch_config->n_dmrs_cdm_groups;
else
nb_re_dmrs = 4 * dlsch_config->n_dmrs_cdm_groups;
uint16_t dmrs_length = get_num_dmrs(dlsch_config->dlDmrsSymbPos);
if (!harq_process) {
LOG_E(PHY, "dlsch_decoding_slot.c: NULL harq_process pointer\n");
return;
}
nrLDPC_TB_decoding_parameters_t *TB_parameters = &TBs[pdsch_id];
/* Neither harq_pid nor DLSCH_id are unique in the instance
* but their combination is.
* Since DLSCH_id < 2
* then 2 * harq_pid + DLSCH_id is unique.
*/
TB_parameters->harq_unique_pid = 2 * harq_pid + DLSCH_id;
// ------------------------------------------------------------------
TB_parameters->G = G[DLSCH_id];
TB_parameters->nb_rb = number_rbs;
TB_parameters->Qm = dlsch_config->qamModOrder;
TB_parameters->mcs = dlsch_config->mcs;
TB_parameters->nb_layers = dlsch[DLSCH_id].Nl;
TB_parameters->BG = dlsch_config->ldpcBaseGraph;
TB_parameters->A = dlsch_config->TBS;
// ------------------------------------------------------------------
TB_parameters->processedSegments = &harq_process->processedSegments;
float Coderate = (float)dlsch->dlsch_config.targetCodeRate / 10240.0f;
LOG_D(
PHY,
"%d.%d DLSCH %d Decoding, harq_pid %d TBS %d G %d nb_re_dmrs %d length dmrs %d mcs %d Nl %d nb_symb_sch %d nb_rb %d Qm %d "
"Coderate %f\n",
slot_parameters.frame,
slot_parameters.slot,
cw_idx,
DLSCH_id,
harq_pid,
cw_info->TBS,
G,
dlsch_config->TBS,
TB_parameters->G,
nb_re_dmrs,
dmrs_length,
TB_parameters.mcs,
TB_parameters.nb_layers,
TB_parameters->mcs,
TB_parameters->nb_layers,
dlsch_config->number_symbols,
TB_parameters.nb_rb,
TB_parameters.Qm,
TB_parameters->nb_rb,
TB_parameters->Qm,
Coderate);
if (harq_process->first_rx == 1) {
// This is a new packet, so compute quantities regarding segmentation
nr_segmentation(NULL,
NULL,
lenWithCrc(1, TB_parameters.A), // We give a max size in case of 1 segment
&TB_parameters.C,
&TB_parameters.K,
&TB_parameters.Z, // [hna] Z is Zc
&TB_parameters.F,
TB_parameters.BG);
harq_process->C = TB_parameters.C;
harq_process->K = TB_parameters.K;
harq_process->Z = TB_parameters.Z;
harq_process->F = TB_parameters.F;
if (harq_process->first_rx == 1) {
// This is a new packet, so compute quantities regarding segmentation
nr_segmentation(NULL,
NULL,
lenWithCrc(1, TB_parameters->A), // We give a max size in case of 1 segment
&TB_parameters->C,
&TB_parameters->K,
&TB_parameters->Z, // [hna] Z is Zc
&TB_parameters->F,
TB_parameters->BG);
harq_process->C = TB_parameters->C;
harq_process->K = TB_parameters->K;
harq_process->Z = TB_parameters->Z;
harq_process->F = TB_parameters->F;
if (harq_process->C > MAX_NUM_NR_DLSCH_SEGMENTS_PER_LAYER * TB_parameters.nb_layers) {
LOG_E(PHY, "nr_segmentation.c: too many segments %d, A %d\n", harq_process->C, TB_parameters.A);
return;
if (harq_process->C > MAX_NUM_NR_DLSCH_SEGMENTS_PER_LAYER * TB_parameters->nb_layers) {
LOG_E(PHY, "nr_segmentation.c: too many segments %d, A %d\n", harq_process->C, TB_parameters->A);
return;
}
if (LOG_DEBUGFLAG(DEBUG_DLSCH_DECOD) && (!slot_parameters.frame % 100))
LOG_I(PHY, "K %d C %d Z %d nl %d \n", harq_process->K, harq_process->C, harq_process->Z, TB_parameters->nb_layers);
// clear HARQ buffer
for (int i = 0; i < harq_process->C; i++)
memset(harq_process->d[i], 0, 5 * 8448 * sizeof(int16_t));
} else {
// This is not a new packet, so retrieve previously computed quantities regarding segmentation
TB_parameters->C = harq_process->C;
TB_parameters->K = harq_process->K;
TB_parameters->Z = harq_process->Z;
TB_parameters->F = harq_process->F;
}
max_num_segments = max(max_num_segments, TB_parameters->C);
if (LOG_DEBUGFLAG(DEBUG_DLSCH_DECOD) && (!slot_parameters.frame % 100))
LOG_I(PHY, "K %d C %d Z %d nl %d \n", harq_process->K, harq_process->C, harq_process->Z, TB_parameters.nb_layers);
} else {
// This is not a new packet, so retrieve previously computed quantities regarding segmentation
TB_parameters.C = harq_process->C;
TB_parameters.K = harq_process->K;
TB_parameters.Z = harq_process->Z;
TB_parameters.F = harq_process->F;
if (LOG_DEBUGFLAG(DEBUG_DLSCH_DECOD))
LOG_I(PHY, "Segmentation: C %d, K %d\n", harq_process->C, harq_process->K);
TB_parameters->max_ldpc_iterations = dlsch[DLSCH_id].max_ldpc_iterations;
TB_parameters->rv_index = dlsch_config->rv;
TB_parameters->tbslbrm = dlsch_config->tbslbrm;
TB_parameters->abort_decode = &harq_process->abort_decode;
set_abort(&harq_process->abort_decode, false);
}
if (LOG_DEBUGFLAG(DEBUG_DLSCH_DECOD))
LOG_I(PHY, "Segmentation: C %d, K %d\n", harq_process->C, harq_process->K);
nrLDPC_segment_decoding_parameters_t segments[nb_dlsch][max_num_segments];
memset(segments, 0, sizeof(segments));
bool d_to_be_cleared[nb_dlsch][max_num_segments];
memset(d_to_be_cleared, 0, sizeof(d_to_be_cleared));
TB_parameters.max_ldpc_iterations = dlsch->max_ldpc_iterations;
TB_parameters.rv_index = cw_info->rv;
TB_parameters.tbslbrm = dlsch_config->tbslbrm;
TB_parameters.abort_decode = &harq_process->abort_decode;
set_abort(&harq_process->abort_decode, false);
for (uint8_t pdsch_id = 0; pdsch_id < nb_dlsch; pdsch_id++) {
uint8_t DLSCH_id = DLSCH_ids[pdsch_id];
fapi_nr_dl_config_dlsch_pdu_rel15_t *dlsch_config = &dlsch[DLSCH_id].dlsch_config;
int harq_pid = dlsch_config->harq_process_nbr;
NR_DL_UE_HARQ_t *harq_process = &phy_vars_ue->dl_harq_processes[DLSCH_id][harq_pid];
TB_parameters.llr = dlsch_llr;
LOG_D(NR_PHY,
"Decoding C %d, Qm %d, TB_parameters.llr %p\n",
TB_parameters.C,
TB_parameters.Qm,
TB_parameters.llr);
TB_parameters.c = harq_process->c;
TB_parameters.d = harq_process->d;
TB_parameters.E = nr_get_E(TB_parameters.G, TB_parameters.C, TB_parameters.Qm, TB_parameters.nb_layers, 0);
TB_parameters.E2 = TB_parameters.E;
TB_parameters.first_rE2 = TB_parameters.C;
for (int r = 1; r < TB_parameters.C; r++) {
int Er = nr_get_E(TB_parameters.G, TB_parameters.C, TB_parameters.Qm, TB_parameters.nb_layers, r);
if (Er != TB_parameters.E) {
TB_parameters.E2 = Er;
TB_parameters.first_rE2 = r;
break;
}
}
TB_parameters.R = nr_get_R_ldpc_decoder(TB_parameters.rv_index,
TB_parameters.E,
TB_parameters.BG,
TB_parameters.Z,
&harq_process->llrLen,
harq_process->DLround);
TB_parameters.d_to_be_cleared = harq_process->first_rx == 1;
for (int r = 0; r < TB_parameters.C; r++)
TB_parameters.decodeSuccess[r] = false;
reset_meas(&TB_parameters.ts_deinterleave);
reset_meas(&TB_parameters.ts_rate_unmatch);
reset_meas(&TB_parameters.ts_seg_prep);
reset_meas(&TB_parameters.ts_ldpc_decode);
nrLDPC_TB_decoding_parameters_t *TB_parameters = &TBs[pdsch_id];
TB_parameters->segments = segments[pdsch_id];
for (int r = 0; r < TB_parameters.C; r++) {
int Etmp = nr_get_E(TB_parameters.G, TB_parameters.C, TB_parameters.Qm, TB_parameters.nb_layers, r);
if (Etmp != TB_parameters.E) {
TB_parameters.E2 = Etmp;
TB_parameters.R2 = nr_get_R_ldpc_decoder(TB_parameters.rv_index,
TB_parameters.E2,
TB_parameters.BG,
TB_parameters.Z,
&harq_process->llrLen,
harq_process->DLround);
TB_parameters.first_rE2 = r;
break;
uint32_t r_offset = 0;
for (int r = 0; r < TB_parameters->C; r++) {
if (harq_process->first_rx == 1)
d_to_be_cleared[pdsch_id][r] = true;
else
d_to_be_cleared[pdsch_id][r] = false;
nrLDPC_segment_decoding_parameters_t *segment_parameters = &TB_parameters->segments[r];
segment_parameters->E = nr_get_E(TB_parameters->G,
TB_parameters->C,
TB_parameters->Qm,
TB_parameters->nb_layers,
r);
segment_parameters->R = nr_get_R_ldpc_decoder(TB_parameters->rv_index,
segment_parameters->E,
TB_parameters->BG,
TB_parameters->Z,
&harq_process->llrLen,
harq_process->DLround);
segment_parameters->llr = dlsch_llr[DLSCH_id] + r_offset;
segment_parameters->d = harq_process->d[r];
segment_parameters->d_to_be_cleared = &d_to_be_cleared[pdsch_id][r];
segment_parameters->c = harq_process->c[r];
segment_parameters->decodeSuccess = false;
reset_meas(&segment_parameters->ts_deinterleave);
reset_meas(&segment_parameters->ts_rate_unmatch);
reset_meas(&segment_parameters->ts_ldpc_decode);
r_offset += segment_parameters->E;
}
}
@@ -196,104 +224,114 @@ void nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue,
return;
}
uint32_t offset = 0, r_offset = 0;
bool crcok = true;
for (int r = 0; r < TB_parameters.C; r++)
if (TB_parameters.decodeSuccess[r] == false) {
LOG_D(PHY, "downlink segment error %d/%d\n", r, harq_process->C);
crcok = false;
break;
}
if (crcok) {
for (int r = 0; r < TB_parameters.C; r++) {
memcpy(b + offset,
harq_process->c + r_offset,
(harq_process->K >> 3) - (harq_process->F >> 3) - ((harq_process->C > 1) ? 3 : 0));
// post decode
for (uint8_t pdsch_id = 0; pdsch_id < nb_dlsch; pdsch_id++) {
uint8_t DLSCH_id = DLSCH_ids[pdsch_id];
fapi_nr_dl_config_dlsch_pdu_rel15_t *dlsch_config = &dlsch[DLSCH_id].dlsch_config;
int harq_pid = dlsch_config->harq_process_nbr;
NR_DL_UE_HARQ_t *harq_process = &phy_vars_ue->dl_harq_processes[DLSCH_id][harq_pid];
nrLDPC_TB_decoding_parameters_t *TB_parameters = &TBs[pdsch_id];
uint32_t offset = 0;
for (int r = 0; r < TB_parameters->C; r++) {
nrLDPC_segment_decoding_parameters_t *segment_parameters = &TB_parameters->segments[r];
if (segment_parameters->decodeSuccess) {
memcpy(b[DLSCH_id] + offset,
harq_process->c[r],
(harq_process->K >> 3) - (harq_process->F >> 3) - ((harq_process->C > 1) ? 3 : 0));
} else {
fapi_nr_dl_config_dlsch_pdu_rel15_t *dlsch_config = &dlsch[DLSCH_id].dlsch_config;
LOG_D(PHY, "frame=%d, slot=%d, first_rx=%d, rv_index=%d\n", proc->frame_rx, proc->nr_slot_rx, harq_process->first_rx, dlsch_config->rv);
LOG_D(PHY, "downlink segment error %d/%d\n", r, harq_process->C);
LOG_D(PHY, "DLSCH %d in error\n", DLSCH_id);
}
offset += (harq_process->K >> 3) - (harq_process->F >> 3) - ((harq_process->C > 1) ? 3 : 0);
r_offset += (harq_process->K >> 3);
merge_meas(&phy_vars_ue->phy_cpu_stats.cpu_time_stats[DLSCH_DEINTERLEAVING_STATS], &segment_parameters->ts_deinterleave);
merge_meas(&phy_vars_ue->phy_cpu_stats.cpu_time_stats[DLSCH_RATE_UNMATCHING_STATS], &segment_parameters->ts_rate_unmatch);
merge_meas(&phy_vars_ue->phy_cpu_stats.cpu_time_stats[DLSCH_LDPC_DECODING_STATS], &segment_parameters->ts_ldpc_decode);
}
} else {
LOG_D(PHY, "frame=%d, slot=%d, first_rx=%d, rv_index=%d\n", proc->frame_rx, proc->nr_slot_rx, harq_process->first_rx, cw_info->rv);
}
merge_meas(&phy_vars_ue->phy_cpu_stats.cpu_time_stats[DLSCH_DEINTERLEAVING_STATS], &TB_parameters.ts_deinterleave);
merge_meas(&phy_vars_ue->phy_cpu_stats.cpu_time_stats[DLSCH_RATE_UNMATCHING_STATS], &TB_parameters.ts_rate_unmatch);
merge_meas(&phy_vars_ue->phy_cpu_stats.cpu_time_stats[DLSCH_LDPC_DECODING_STATS], &TB_parameters.ts_ldpc_decode);
merge_meas(&phy_vars_ue->phy_cpu_stats.cpu_time_stats[DLSCH_SEG_PREP_STATS], &TB_parameters.ts_seg_prep);
kpiStructure.nb_total++;
kpiStructure.blockSize = dlsch_config->TBS;
kpiStructure.dl_mcs = dlsch_config->mcs;
kpiStructure.nofRBs = number_rbs;
kpiStructure.nb_total++;
kpiStructure.blockSize = cw_info->TBS;
kpiStructure.dl_mcs = cw_info->mcs;
kpiStructure.nofRBs = number_rbs;
harq_process->decodeResult = harq_process->processedSegments == harq_process->C;
harq_process->decodeResult = harq_process->processedSegments == harq_process->C;
if (harq_process->decodeResult && harq_process->C > 1) {
/* check global CRC */
// we have regrouped the transport block
if (!check_crc(b, lenWithCrc(1, cw_info->TBS), crcType(1, cw_info->TBS))) {
LOG_E(PHY,
" Frame %d.%d LDPC global CRC fails, but individual LDPC CRC succeeded. %d segs\n",
proc->frame_rx,
proc->nr_slot_rx,
harq_process->C);
harq_process->decodeResult = false;
}
}
if (harq_process->decodeResult) {
// We search only a reccuring OAI error that propagates all 0 packets with a 0 CRC, so we
const int sz = cw_info->TBS / 8;
if (b[sz] == 0 && b[sz + 1] == 0) {
// do the check only if the 2 first bytes of the CRC are 0 (it can be CRC16 or CRC24)
int i = 0;
while (b[i] == 0 && i < sz)
i++;
if (i == sz) {
if (harq_process->decodeResult && harq_process->C > 1) {
/* check global CRC */
int A = dlsch->dlsch_config.TBS;
// we have regrouped the transport block
if (!check_crc(b[DLSCH_id], lenWithCrc(1, A), crcType(1, A))) {
LOG_E(PHY,
"received all 0 pdu (TBS %d, mcs %d, C %d, nb_rb %d, decodedSegments %d) consider it false reception, even if the "
"TS 38.212 7.2.1 says only we should attach the "
"corresponding CRC, and nothing prevents to have a all 0 packet\n",
cw_info->TBS,
cw_info->mcs,
harq_process->C,
number_rbs,
harq_process->processedSegments);
" Frame %d.%d LDPC global CRC fails, but individual LDPC CRC succeeded. %d segs\n",
proc->frame_rx,
proc->nr_slot_rx,
harq_process->C);
harq_process->decodeResult = false;
}
}
if (harq_process->decodeResult) {
// We search only a reccuring OAI error that propagates all 0 packets with a 0 CRC, so we
const int sz = dlsch->dlsch_config.TBS / 8;
if (b[DLSCH_id][sz] == 0 && b[DLSCH_id][sz + 1] == 0) {
// do the check only if the 2 first bytes of the CRC are 0 (it can be CRC16 or CRC24)
int i = 0;
while (b[DLSCH_id][i] == 0 && i < sz)
i++;
if (i == sz) {
LOG_E(PHY,
"received all 0 pdu, consider it false reception, even if the TS 38.212 7.2.1 says only we should attach the "
"corresponding CRC, and nothing prevents to have a all 0 packet\n");
harq_process->decodeResult = false;
}
}
}
if (harq_process->decodeResult) {
LOG_D(PHY, "DLSCH received ok \n");
harq_process->status = NR_SCH_IDLE;
dlsch->last_iteration_cnt = dlsch->max_ldpc_iterations - 1;
} else {
LOG_D(PHY, "DLSCH received nok \n");
kpiStructure.nb_nack++;
dlsch->last_iteration_cnt = dlsch->max_ldpc_iterations;
UEdumpScopeData(phy_vars_ue, proc->nr_slot_rx, proc->frame_rx, "DLSCH_NACK");
}
uint8_t dmrs_Type = dlsch_config->dmrsConfigType;
uint8_t nb_re_dmrs;
if (dmrs_Type == NFAPI_NR_DMRS_TYPE1)
nb_re_dmrs = 6 * dlsch_config->n_dmrs_cdm_groups;
else
nb_re_dmrs = 4 * dlsch_config->n_dmrs_cdm_groups;
uint16_t dmrs_length = get_num_dmrs(dlsch_config->dlDmrsSymbPos);
float Coderate = (float)dlsch->dlsch_config.targetCodeRate / 10240.0f;
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 "
"nb_symb_sch %d "
"nb_rb %d Qm %d Coderate %f\n",
proc->frame_rx,
proc->nr_slot_rx,
harq_pid,
harq_process->DLround,
harq_process->decodeResult,
dlsch->dlsch_config.TBS,
dlsch->dlsch_config.TBS / 8,
G[DLSCH_id],
nb_re_dmrs,
dmrs_length,
dlsch->dlsch_config.mcs,
dlsch->Nl,
dlsch_config->number_symbols,
number_rbs,
dlsch_config->qamModOrder,
Coderate);
}
if (harq_process->decodeResult) {
LOG_D(PHY, "%d.%d DLSCH received ok \n", proc->frame_rx, proc->nr_slot_rx);
harq_process->status = NR_SCH_IDLE;
dlsch->last_iteration_cnt = dlsch->max_ldpc_iterations - 1;
} else {
LOG_D(PHY, "%d.%d DLSCH received nok \n", proc->frame_rx, proc->nr_slot_rx);
kpiStructure.nb_nack++;
dlsch->last_iteration_cnt = dlsch->max_ldpc_iterations;
UEdumpScopeData(phy_vars_ue, proc->nr_slot_rx, proc->frame_rx, "DLSCH_NACK");
}
LOG_D(PHY,
"%d.%d DLSCH Decoded, harq_pid %d, cw_idx %d round %d, result: %d TBS %d (%d) G %d nb_re_dmrs %d length dmrs %d mcs %d Nl %d "
"nb_symb_sch %d "
"nb_rb %d Qm %d Coderate %f\n",
proc->frame_rx,
proc->nr_slot_rx,
harq_pid,
cw_idx,
harq_process->DLround,
harq_process->decodeResult,
cw_info->TBS,
cw_info->TBS / 8,
G,
nb_re_dmrs,
dmrs_length,
cw_info->mcs,
cw_info->Nl,
dlsch_config->number_symbols,
number_rbs,
cw_info->qamModOrder,
Coderate);
}

View File

@@ -856,12 +856,12 @@ static void nr_dlsch_layer_demapping(const uint8_t Nl,
const uint8_t mod_order,
const int llrLayerSize,
const int16_t llr_layers[NR_SYMBOLS_PER_SLOT][Nl][llrLayerSize],
const fapi_nr_dl_config_dlsch_pdu_rel15_t *dlsch_config,
const NR_UE_DLSCH_t *dlsch,
const uint32_t re_len[NR_SYMBOLS_PER_SLOT],
int16_t *llr)
{
const int s0 = dlsch_config->start_symbol;
const int s1 = dlsch_config->number_symbols;
const int s0 = dlsch->dlsch_config.start_symbol;
const int s1 = dlsch->dlsch_config.number_symbols;
int k = 0;
switch (Nl) {
@@ -901,28 +901,28 @@ static int nr_dlsch_llr(const NR_UE_DLSCH_t *dlsch,
const c16_t dl_ch_magb[rx_size_symbol],
const c16_t dl_ch_magr[rx_size_symbol],
const int nb_antennas_rx,
const c16_t rxdataF_comp[dlsch->cw_info.Nl][nb_antennas_rx][rx_size_symbol],
const c16_t rxdataF_comp[dlsch->Nl][nb_antennas_rx][rx_size_symbol],
const int llrSize,
int16_t layer_llr[dlsch->cw_info.Nl][llrSize])
int16_t layer_llr[dlsch->Nl][llrSize])
{
switch (dlsch->cw_info.qamModOrder) {
switch (dlsch->dlsch_config.qamModOrder) {
case 2 :
for (int l = 0; l < dlsch->cw_info.Nl; l++)
for (int l = 0; l < dlsch[0].Nl; l++)
nr_qpsk_llr(rxdataF_comp[l][0], layer_llr[l], len);
break;
case 4 :
for (int l = 0; l < dlsch->cw_info.Nl; l++)
for (int l = 0; l < dlsch[0].Nl; l++)
nr_16qam_llr(rxdataF_comp[l][0], dl_ch_mag, layer_llr[l], len);
break;
case 6 :
for(int l=0; l < dlsch->cw_info.Nl; l++)
for(int l=0; l < dlsch[0].Nl; l++)
nr_64qam_llr(rxdataF_comp[l][0], dl_ch_mag, dl_ch_magb, layer_llr[l], len);
break;
case 8:
for(int l=0; l < dlsch->cw_info.Nl; l++)
for(int l=0; l < dlsch[0].Nl; l++)
nr_256qam_llr(rxdataF_comp[l][0],
dl_ch_mag,
dl_ch_magb,
@@ -943,32 +943,30 @@ static int nr_dlsch_llr(const NR_UE_DLSCH_t *dlsch,
/* Main Function */
int nr_rx_pdsch(PHY_VARS_NR_UE *ue,
const UE_nr_rxtx_proc_t *proc,
NR_UE_DLSCH_t *dlsch,
NR_UE_DLSCH_t dlsch[2],
const freq_alloc_bitmap_t *freq_alloc,
fapi_nr_dl_config_dlsch_pdu_rel15_t *dlsch_config,
NR_DL_UE_HARQ_t *dlsch_harq,
unsigned char symbol,
bool first_symbol_flag,
unsigned char harq_pid,
uint32_t pdsch_est_size,
int32_t dl_ch_estimates[][pdsch_est_size],
int16_t *llr,
int16_t *llr[2],
uint32_t dl_valid_re[NR_SYMBOLS_PER_SLOT],
c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP],
int32_t *log2_maxh,
int rx_size_symbol,
int nbRx,
c16_t rxdataF_comp[][dlsch->cw_info.Nl][nbRx][rx_size_symbol],
c16_t dl_ch_mag[][dlsch->cw_info.Nl][nbRx][rx_size_symbol],
c16_t dl_ch_magb[][dlsch->cw_info.Nl][nbRx][rx_size_symbol],
c16_t dl_ch_magr[][dlsch->cw_info.Nl][nbRx][rx_size_symbol],
c16_t rxdataF_comp[][dlsch->Nl][nbRx][rx_size_symbol],
c16_t dl_ch_mag[][dlsch->Nl][nbRx][rx_size_symbol],
c16_t dl_ch_magb[][dlsch->Nl][nbRx][rx_size_symbol],
c16_t dl_ch_magr[][dlsch->Nl][nbRx][rx_size_symbol],
c16_t ptrs_phase_per_slot[][NR_SYMBOLS_PER_SLOT],
int32_t ptrs_re_per_slot[][NR_SYMBOLS_PER_SLOT],
uint32_t nvar,
pdsch_scope_req_t *scope_req)
{
NR_DL_FRAME_PARMS *fp = &ue->frame_parms;
const int nl = dlsch->cw_info.Nl;
const int nl = dlsch[0].Nl;
const int n_rx = fp->nb_antennas_rx;
const int matrixSz = n_rx * nl;
__attribute__((aligned(32))) int32_t dl_ch_estimates_ext[matrixSz][rx_size_symbol];
@@ -980,8 +978,72 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue,
const int gNB_id = proc->gNB_id;
uint8_t slot = 0;
int32_t codeword_TB0 = -1;
int32_t codeword_TB1 = -1;
uint32_t nb_re_pdsch = -1;
DevAssert(dlsch_harq);
NR_DL_UE_HARQ_t *dlsch0_harq, *dlsch1_harq = NULL;
dlsch0_harq = &ue->dl_harq_processes[0][harq_pid];
if (NR_MAX_NB_LAYERS > 4)
dlsch1_harq = &ue->dl_harq_processes[1][harq_pid];
if (dlsch0_harq && dlsch1_harq){
LOG_D(PHY,
"AbsSubframe %d.%d / Sym %d harq_pid %d, harq status %d.%d \n",
frame,
nr_slot_rx,
symbol,
harq_pid,
dlsch0_harq->status,
dlsch1_harq->status);
if ((dlsch0_harq->status == NR_ACTIVE) && (dlsch1_harq->status == NR_ACTIVE)){
codeword_TB0 = dlsch0_harq->codeword; // SV: where is this set? revisit for DL MIMO.
codeword_TB1 = dlsch1_harq->codeword;
dlsch0_harq = &ue->dl_harq_processes[codeword_TB0][harq_pid];
dlsch1_harq = &ue->dl_harq_processes[codeword_TB1][harq_pid];
DEBUG_HARQ("[DEMOD] I am assuming both TBs are active, in cw0 %d and cw1 %d \n", codeword_TB0, codeword_TB1);
} else if ((dlsch0_harq->status == NR_ACTIVE) && (dlsch1_harq->status != NR_ACTIVE) ) {
codeword_TB0 = dlsch0_harq->codeword;
dlsch0_harq = &ue->dl_harq_processes[codeword_TB0][harq_pid];
dlsch1_harq = NULL;
DEBUG_HARQ("[DEMOD] I am assuming only TB0 is active, in cw %d \n", codeword_TB0);
} else if ((dlsch0_harq->status != NR_ACTIVE) && (dlsch1_harq->status == NR_ACTIVE)){
codeword_TB1 = dlsch1_harq->codeword;
dlsch0_harq = NULL;
dlsch1_harq = &ue->dl_harq_processes[codeword_TB1][harq_pid];
DEBUG_HARQ("[DEMOD] I am assuming only TB1 is active, it is in cw %d\n", codeword_TB1);
LOG_E(PHY, "[DEMOD] slot %d TB0 not active and TB1 active case is not supported\n", nr_slot_rx);
return -1;
} else {
LOG_E(PHY, "[DEMOD] slot %d: no active DLSCH (2 layers case)\n", nr_slot_rx);
return (-1);
}
} else if (dlsch0_harq) {
if (dlsch0_harq->status == NR_ACTIVE) {
codeword_TB0 = dlsch0_harq->codeword;
dlsch0_harq = &ue->dl_harq_processes[0][harq_pid];
DEBUG_HARQ("[DEMOD] I am assuming only TB0 is active\n");
} else {
LOG_E(PHY, "[DEMOD] slot %d nr_rx_pdsch no active DLSCH (one layer case)\n", nr_slot_rx);
return (-1);
}
} else {
LOG_E(PHY, "[DEMOD] slot %d Inconsistent call to nr_rx_pdsch (no layer 0)\n", nr_slot_rx);
return -1;
}
DEBUG_HARQ("[DEMOD] cw for TB0 = %d, cw for TB1 = %d\n", codeword_TB0, codeword_TB1);
fapi_nr_dl_config_dlsch_pdu_rel15_t *dlsch_config = &dlsch[0].dlsch_config;
DevAssert(dlsch0_harq);
if (gNB_id > 2) {
LOG_E(PHY, "Illegal gNB_id %d\n", gNB_id);
@@ -1166,7 +1228,7 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue,
fp,
symbol,
nb_re_pdsch,
dlsch->cw_info.qamModOrder,
dlsch_config->qamModOrder,
nb_rb_pdsch,
*log2_maxh); // log2_maxh+I0_shift
stop_meas_nr_ue_phy(ue, DLSCH_CHANNEL_COMPENSATION_STATS);
@@ -1223,7 +1285,7 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue,
dl_ch_magb[symbol],
dl_ch_magr[symbol],
dl_ch_estimates_ext,
dlsch->cw_info.qamModOrder,
dlsch_config->qamModOrder,
*log2_maxh,
symbol,
nb_re_pdsch,
@@ -1249,14 +1311,14 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue,
int nbSymb = 0;
int pduBitmap = 0;
if(dlsch_harq->status == NR_ACTIVE) {
if(dlsch0_harq->status == NR_ACTIVE) {
startSymbIdx = dlsch_config->start_symbol;
nbSymb = dlsch_config->number_symbols;
pduBitmap = dlsch_config->pduBitmap;
}
/* Check for PTRS bitmap and process it respectively */
if((pduBitmap & 0x1) && (dlsch->rnti_type == TYPE_C_RNTI_)) {
if((pduBitmap & 0x1) && (dlsch[0].rnti_type == TYPE_C_RNTI_)) {
nr_pdsch_ptrs_processing(nbRx,
ptrs_phase_per_slot,
ptrs_re_per_slot,
@@ -1264,13 +1326,13 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue,
nl,
rxdataF_comp,
fp,
dlsch_config,
dlsch0_harq,
dlsch1_harq,
nr_slot_rx,
symbol,
freq_alloc->num_rbs,
dlsch->rnti,
&dlsch->ptrs_symbols,
&dlsch->ptrs_symbol_index);
dlsch[0].rnti,
dlsch);
dl_valid_re[symbol] -= ptrs_re_per_slot[0][symbol];
}
/* at last symbol in a slot calculate LLR's for whole slot */
@@ -1278,7 +1340,7 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue,
/* create LLR layer buffer */
int max_symb_re = 0;
GET_ARRAY_MAX(dl_valid_re, NR_SYMBOLS_PER_SLOT, max_symb_re);
const int llr_per_symbol = max_symb_re * dlsch->cw_info.qamModOrder;
const int llr_per_symbol = max_symb_re * dlsch->dlsch_config.qamModOrder;
__attribute__((aligned(32))) int16_t layer_llr[NR_SYMBOLS_PER_SLOT][nl][llr_per_symbol];
// Generate LLR from PTRS compensated signal
@@ -1297,9 +1359,14 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue,
}
stop_meas_nr_ue_phy(ue, DLSCH_LLR_STATS);
start_meas_nr_ue_phy(ue, DLSCH_LAYER_DEMAPPING);
nr_dlsch_layer_demapping(nl, dlsch->cw_info.qamModOrder, llr_per_symbol, layer_llr, dlsch_config, dl_valid_re, llr);
nr_dlsch_layer_demapping(nl, dlsch_config->qamModOrder, llr_per_symbol, layer_llr, dlsch, dl_valid_re, llr[0]);
stop_meas_nr_ue_phy(ue, DLSCH_LAYER_DEMAPPING);
/*
for (int i=0; i < 2; i++){
snprintf(filename, 50, "llr%d_symb_%d_nr_slot_rx_%d.m", i, symbol, nr_slot_rx);
write_output(filename,"llr", &llr[i][0], (NR_SYMBOLS_PER_SLOT*nb_rb_pdsch*NR_NB_SC_PER_RB*dlsch1_harq->Qm) - 4*(nb_rb_pdsch*4*dlsch1_harq->Qm), 1, 0);
}
*/
if (UEScopeHasTryLock(ue)) {
metadata mt = {.frame = proc->frame_rx, .slot = proc->nr_slot_rx };
int total_valid_res = 0;

View File

@@ -452,8 +452,7 @@ nr_initial_sync_t nr_initial_sync(UE_nr_rxtx_proc_t *proc,
nr_fill_rx_indication(&rx_ind,
FAPI_NR_RX_PDU_TYPE_SSB,
ue,
0,
0,
NULL,
NULL,
number_pdus,
proc,

View File

@@ -405,7 +405,7 @@ int nr_pbch_decode(PHY_VARS_NR_UE *ue,
if (decoderState) {
if (ue) { // decoding failed in synced state
nr_fill_dl_indication(&dl_indication, NULL, &rx_ind, proc, ue, NULL);
nr_fill_rx_indication(&rx_ind, FAPI_NR_RX_PDU_TYPE_SSB, ue, 0, 0, NULL, number_pdus, proc, NULL, NULL);
nr_fill_rx_indication(&rx_ind, FAPI_NR_RX_PDU_TYPE_SSB, ue, NULL, NULL, number_pdus, proc, NULL, NULL);
if (ue->if_inst && ue->if_inst->dl_indication)
ue->if_inst->dl_indication(&dl_indication);
}
@@ -465,7 +465,7 @@ int nr_pbch_decode(PHY_VARS_NR_UE *ue,
if (ue) {
nr_fill_dl_indication(&dl_indication, NULL, &rx_ind, proc, ue, NULL);
nr_fill_rx_indication(&rx_ind, FAPI_NR_RX_PDU_TYPE_SSB, ue, 0, 0, NULL, number_pdus, proc, (void *)result, NULL);
nr_fill_rx_indication(&rx_ind, FAPI_NR_RX_PDU_TYPE_SSB, ue, NULL, NULL, number_pdus, proc, (void *)result, NULL);
if (ue->if_inst && ue->if_inst->dl_indication)
ue->if_inst->dl_indication(&dl_indication);

View File

@@ -61,17 +61,19 @@ int get_max_pdcch_monOcc(const NR_UE_PDCCH_CONFIG *phy_pdcch_config, int nb_symb
@param[in] dlsch_llr Pointers to LLR values computed by dlsch_demodulation
@param[in] b
@param[in] G array of Gs
@param[in] nb_dlsch number of active downlink shared channels
@param[in] DLSCH_ids array of active downlink shared channels
@returns 0 on success, 1 on unsuccessful decoding
*/
void nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue,
const UE_nr_rxtx_proc_t *proc,
NR_UE_DLSCH_t *dlsch,
int cw_idx,
fapi_nr_dl_config_dlsch_pdu_rel15_t *dlsch_config,
int16_t *dlsch_llr,
uint8_t *b,
short **dlsch_llr,
uint8_t **b,
int *G,
int nb_dlsch,
int number_rbs,
int G);
uint8_t *DLSCH_ids);
int nr_ulsch_pre_encoding(PHY_VARS_NR_UE *ue,
const NR_UE_ULSCH_t *ulsch,
@@ -261,25 +263,23 @@ void nr_sl_rf_card_config_freq(PHY_VARS_NR_UE *ue,
*/
int nr_rx_pdsch(PHY_VARS_NR_UE *ue,
const UE_nr_rxtx_proc_t *proc,
NR_UE_DLSCH_t *dlsch,
NR_UE_DLSCH_t dlsch[2],
const freq_alloc_bitmap_t *freq_alloc,
fapi_nr_dl_config_dlsch_pdu_rel15_t *dlsch_config,
NR_DL_UE_HARQ_t *dlsch_harq,
unsigned char symbol,
bool first_symbol_flag,
unsigned char harq_pid,
uint32_t pdsch_est_size,
int32_t dl_ch_estimates[][pdsch_est_size],
int16_t *llr,
int16_t *llr[2],
uint32_t dl_valid_re[NR_SYMBOLS_PER_SLOT],
c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP],
int32_t *log2_maxh,
int rx_size_symbol,
int nbRx,
c16_t rxdataF_comp[][dlsch->cw_info.Nl][nbRx][rx_size_symbol],
c16_t dl_ch_mag[][dlsch->cw_info.Nl][nbRx][rx_size_symbol],
c16_t dl_ch_magb[][dlsch->cw_info.Nl][nbRx][rx_size_symbol],
c16_t dl_ch_magr[][dlsch->cw_info.Nl][nbRx][rx_size_symbol],
c16_t rxdataF_comp[][dlsch->Nl][nbRx][rx_size_symbol],
c16_t dl_ch_mag[][dlsch->Nl][nbRx][rx_size_symbol],
c16_t dl_ch_magb[][dlsch->Nl][nbRx][rx_size_symbol],
c16_t dl_ch_magr[][dlsch->Nl][nbRx][rx_size_symbol],
c16_t ptrs_phase_per_slot[][NR_SYMBOLS_PER_SLOT],
int32_t ptrs_re_per_slot[][NR_SYMBOLS_PER_SLOT],
uint32_t nvar,

View File

@@ -69,11 +69,11 @@ typedef struct {
NR_SCH_status_t status;
/// Pointer to the payload (38.212 V15.4.0 section 5.1)
uint8_t *b;
/// Pointer to transport block segments
uint8_t *c;
/// Pointers to transport block segments
uint8_t **c;
/// soft bits for each received segment ("d"-sequence)(for definition see 36-212 V8.6 2009-03, p.15)
/// Accumulates the soft bits for each round to increase decoding success (HARQ)
int16_t *d;
int16_t **d;
/// Index of current HARQ round for this DLSCH
uint8_t DLround;
/// Number of code segments
@@ -97,13 +97,16 @@ typedef struct {
} NR_DL_UE_HARQ_t;
typedef struct {
fapi_nr_dl_cw_info_t cw_info;
/// RNTI
uint16_t rnti;
/// RNTI type
uint8_t rnti_type;
/// Active flag for DLSCH demodulation
bool active;
/// Structure to hold dlsch config from MAC
fapi_nr_dl_config_dlsch_pdu_rel15_t dlsch_config;
/// Number of MIMO layers (streams)
uint8_t Nl;
/// Maximum number of LDPC iterations
uint8_t max_ldpc_iterations;
/// number of iterations used in last turbo decoding

View File

@@ -48,19 +48,19 @@ target_link_libraries(benchmark_channel_pipeline PRIVATE UTIL SIMU PHY_COMMON LO
add_executable(test_channel_pipeline test_channel_pipeline.cpp test_channel_pipeline_tools.c)
target_link_libraries(test_channel_pipeline PRIVATE UTIL SIMU PHY_COMMON LOG CONFIG_LIB shlib_loader m channel_pipeline GTest::gtest thread-pool)
if (ENABLE_CHANNEL_SIM_CUDA)
target_compile_definitions(test_channel_pipeline PRIVATE CHANNEL_SIM_CUDA)
if (CUDA_ENABLE)
target_compile_definitions(test_channel_pipeline PRIVATE CUDA_ENABLE)
add_dependencies(tests test_channel_pipeline)
add_test(NAME test_channel_pipeline COMMAND test_channel_pipeline)
set_tests_properties(test_channel_pipeline PROPERTIES LABELS "cuda")
target_compile_definitions(benchmark_channel_pipeline PRIVATE CHANNEL_SIM_CUDA)
target_compile_definitions(benchmark_channel_pipeline PRIVATE CUDA_ENABLE)
add_dependencies(tests benchmark_channel_pipeline)
add_test(NAME benchmark_channel_pipeline COMMAND benchmark_channel_pipeline)
set_tests_properties(benchmark_channel_pipeline PROPERTIES LABELS "cuda")
endif()
if (ENABLE_CHANNEL_SIM_CUDA)
if(CUDA_ENABLE)
add_executable(test_multipath test_multipath.c)
target_link_libraries(test_multipath PRIVATE UTIL SIMU LOG CONFIG_LIB shlib_loader m oai_cuda_lib)
@@ -88,9 +88,9 @@ add_dependencies(tests test_channel_scalability)
add_test(NAME test_channel_scalability COMMAND test_channel_scalability)
if (TARGET oai_cuda_lib)
target_compile_definitions(test_multipath PRIVATE CHANNEL_SIM_CUDA)
target_compile_definitions(test_noise PRIVATE CHANNEL_SIM_CUDA)
target_compile_definitions(test_channel_simulation PRIVATE CHANNEL_SIM_CUDA)
target_compile_definitions(test_channel_scalability PRIVATE CHANNEL_SIM_CUDA)
target_compile_definitions(test_multipath PRIVATE ENABLE_CUDA)
target_compile_definitions(test_noise PRIVATE ENABLE_CUDA)
target_compile_definitions(test_channel_simulation PRIVATE ENABLE_CUDA)
target_compile_definitions(test_channel_scalability PRIVATE ENABLE_CUDA)
endif()
endif()

View File

@@ -25,7 +25,7 @@ extern "C" void exit_function(const char *file, const char *function, const int
exit(EXIT_FAILURE);
}
#ifdef CHANNEL_SIM_CUDA
#ifdef CUDA_ENABLE
static void BM_channel_convolution_gpu(benchmark::State &state)
{
int nb_rx = state.range(0);
@@ -203,7 +203,7 @@ static void BM_channel_convolution_tpool(benchmark::State &state)
}
}
#ifdef CHANNEL_SIM_CUDA
#ifdef CUDA_ENABLE
BENCHMARK(BM_channel_convolution_gpu)
->ArgsProduct({
{1, 2, 4, 16, 64}, // nb_rx

View File

@@ -26,7 +26,7 @@ class ChannelConvolutionTest : public ::testing::TestWithParam<std::tuple<int, i
protected:
void SetUp() override
{
#ifdef CHANNEL_SIM_CUDA
#ifdef CUDA_ENABLE
gpu_context = cuda_channel_pipeline_init(614400 * 4);
#endif
tpool = init_tpool(8);
@@ -35,7 +35,7 @@ class ChannelConvolutionTest : public ::testing::TestWithParam<std::tuple<int, i
void TearDown() override
{
#ifdef CHANNEL_SIM_CUDA
#ifdef CUDA_ENABLE
cuda_channel_pipeline_shutdown(gpu_context);
#endif
destroy_tpool(tpool);
@@ -46,7 +46,7 @@ class ChannelConvolutionTest : public ::testing::TestWithParam<std::tuple<int, i
void *tpool = nullptr;
};
#ifdef CHANNEL_SIM_CUDA
#ifdef CUDA_ENABLE
TEST_P(ChannelConvolutionTest, CompareCpuGpu)
{
int nb_rx = std::get<0>(GetParam());

View File

@@ -128,21 +128,25 @@ typedef struct {
uint8_t round;
bool new_rx;
/////////////////////// ulsch decoding ///////////////////////
/// flag used to clear d properly
/// flag used to clear d properly (together with d_to_be_cleared below)
/// set to true in nr_fill_ulsch() when new_data_indicator is received
bool harq_to_be_cleared;
/// Pointer to the payload (38.212 V15.4.0 section 5.1)
uint8_t *b;
/// Pointer to aggregated code blocks after code block segmentation and CRC attachment (38.212 V15.4.0 section 5.2.2)
uint8_t *c;
/// Pointers to code blocks after code block segmentation and CRC attachment (38.212 V15.4.0 section 5.2.2)
uint8_t **c;
/// Number of bits in each code block (38.212 V15.4.0 section 5.2.2)
uint32_t K;
/// Number of "Filler" bits added in the code block segmentation (38.212 V15.4.0 section 5.2.2)
uint32_t F;
/// Number of code blocks after code block segmentation (38.212 V15.4.0 section 5.2.2)
uint32_t C;
/// Pointers to aggregated code blocks after LDPC coding (38.212 V15.4.0 section 5.3.2)
int16_t *d;
/// Pointers to code blocks after LDPC coding (38.212 V15.4.0 section 5.3.2)
int16_t **d;
/// flag used to clear d properly (together with harq_to_be_cleared above)
/// set to true in nr_ulsch_decoding() when harq_to_be_cleared is true
/// when true, clear d in the next call to function nr_rate_matching_ldpc_rx()
bool *d_to_be_cleared;
/// LDPC lifting size (38.212 V15.4.0 table 5.3.2-1)
uint32_t Z;
/// Number of bits in each code block after rate matching for LDPC code (38.212 V15.4.0 section 5.4.2.1)
@@ -440,12 +444,10 @@ typedef struct PHY_VARS_gNB_s {
time_stats_t dlsch_resource_mapping_stats;
time_stats_t dlsch_precoding_stats;
time_stats_t tinput;
time_stats_t tinput_memcpy;
time_stats_t tprep;
time_stats_t tparity;
time_stats_t toutput;
time_stats_t tconcat;
time_stats_t dlsch_rate_matching_stats;
time_stats_t dlsch_interleaving_stats;
time_stats_t dlsch_segmentation_stats;
@@ -460,16 +462,11 @@ typedef struct PHY_VARS_gNB_s {
time_stats_t ulsch_decoding_stats;
time_stats_t ts_deinterleave;
time_stats_t ts_rate_unmatch;
time_stats_t ts_seg_prep;
time_stats_t ts_ldpc_decode;
time_stats_t ulsch_deinterleaving_stats;
time_stats_t ulsch_channel_estimation_stats;
time_stats_t pusch_channel_estimation_antenna_processing_stats;
time_stats_t ulsch_llr_stats;
time_stats_t ulsch_layer_demapping_stats;
time_stats_t ulsch_unscrambling_stats;
time_stats_t pusch_extraction_stats;
time_stats_t pusch_channel_compensation_stats;
time_stats_t rx_srs_stats;
time_stats_t generate_srs_stats;
time_stats_t get_srs_signal_stats;
@@ -520,7 +517,7 @@ typedef struct LDPCDecode_s {
NR_UL_gNB_HARQ_t *ulsch_harq;
t_nrLDPC_dec_params decoderParms;
NR_gNB_ULSCH_t *ulsch;
int16_t *ulsch_llr;
short* ulsch_llr;
int ulsch_id;
int harq_pid;
int rv_index;

View File

@@ -521,9 +521,8 @@ typedef struct nr_phy_data_tx_s {
typedef struct nr_phy_data_s {
NR_UE_PDCCH_CONFIG phy_pdcch_config;
fapi_nr_dl_config_dlsch_pdu_rel15_t dlsch_config;
NR_UE_DLSCH_t dlsch[2];
int n_dlsch_codewords;
// Sidelink Rx action decided by MAC
sl_nr_rx_config_type_enum_t sl_rx_action;
NR_UE_CSI_RS csirs_vars;
@@ -536,7 +535,7 @@ enum stream_status_e { STREAM_STATUS_UNSYNC, STREAM_STATUS_SYNCING, STREAM_STATU
*/
typedef struct nr_rxtx_thread_data_s {
UE_nr_rxtx_proc_t proc;
PHY_VARS_NR_UE *UE;
PHY_VARS_NR_UE *UE;
int writeBlockSize;
nr_phy_data_t phy_data;
dynamic_barrier_t* next_barrier;

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