mirror of
https://gitlab.eurecom.fr/oai/openairinterface5g.git
synced 2026-07-20 08:00:31 +00:00
Compare commits
127 Commits
ue-trs-sup
...
rs
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
578979121d | ||
|
|
0d1f7470ae | ||
|
|
f9f925cdb2 | ||
|
|
b5719c49a4 | ||
|
|
8f935bd32d | ||
|
|
e83df8ad0c | ||
|
|
93ef3a0d60 | ||
|
|
a51770341e | ||
|
|
9a6b332912 | ||
|
|
c574fa68c5 | ||
|
|
ad85919ba7 | ||
|
|
5cd9d6206e | ||
|
|
1c4c8d3e1b | ||
|
|
347dda4dc5 | ||
|
|
a8cb7d807c | ||
|
|
18f2ff3608 | ||
|
|
1dfb4fc4c3 | ||
|
|
cb0e501293 | ||
|
|
726293c3d4 | ||
|
|
c9958bef59 | ||
|
|
470a5316e8 | ||
|
|
6afbb081a9 | ||
|
|
40028ef0ce | ||
|
|
b506115bf9 | ||
|
|
a47d958636 | ||
|
|
aaf2e2aed9 | ||
|
|
28cff29178 | ||
|
|
aab585900b | ||
|
|
528da705df | ||
|
|
a53545da38 | ||
|
|
dc3011c298 | ||
|
|
d7531cfe15 | ||
|
|
77db1ac9c0 | ||
|
|
137fa62d6c | ||
|
|
78108290ab | ||
|
|
5a4c1c5fd9 | ||
|
|
ac6c40b1f2 | ||
|
|
c2e43c025d | ||
|
|
e518d49517 | ||
|
|
68d9258b54 | ||
|
|
22365c3d28 | ||
|
|
f4c8158825 | ||
|
|
63c550802a | ||
|
|
04c5113bc1 | ||
|
|
84299bcd27 | ||
|
|
076c722eb9 | ||
|
|
19e3cbd66a | ||
|
|
3192251471 | ||
|
|
2e54a90ad0 | ||
|
|
c803643fad | ||
|
|
10f94ac56e | ||
|
|
7da624fc80 | ||
|
|
b5179e3c50 | ||
|
|
8698186d47 | ||
|
|
7d099f7918 | ||
|
|
92b3d5fa87 | ||
|
|
7e444cb544 | ||
|
|
7c62ed582f | ||
|
|
607f9c0f33 | ||
|
|
b54afbbc36 | ||
|
|
db3b89b5da | ||
|
|
bc2029b62a | ||
|
|
973db30ea2 | ||
|
|
abb7cbe2bd | ||
|
|
9feed9f4d1 | ||
|
|
92805a4624 | ||
|
|
8a5960461e | ||
|
|
dc28488e0a | ||
|
|
2d05db4819 | ||
|
|
fc25f6b075 | ||
|
|
458fd3623a | ||
|
|
06fa702c7c | ||
|
|
0a147851b7 | ||
|
|
da5e5892e4 | ||
|
|
0c782e3ee3 | ||
|
|
410f1a18d7 | ||
|
|
8ed54d7077 | ||
|
|
fd6c9efa72 | ||
|
|
e5f30d9033 | ||
|
|
ac6443d9ae | ||
|
|
e41766d7f6 | ||
|
|
418ef390ca | ||
|
|
f3acdef63a | ||
|
|
6fc2d06077 | ||
|
|
428ed54db4 | ||
|
|
a2719bd9d7 | ||
|
|
5f4aff8a1d | ||
|
|
9e4308030b | ||
|
|
228dad1ec2 | ||
|
|
d39a40dba2 | ||
|
|
181b5d89f8 | ||
|
|
870454d13d | ||
|
|
dd424a2e0c | ||
|
|
e83867a505 | ||
|
|
76b7972bc0 | ||
|
|
ebd5fc9a5f | ||
|
|
782ede870e | ||
|
|
9a858c4387 | ||
|
|
9d35b9028c | ||
|
|
8a0be83745 | ||
|
|
7c29d27487 | ||
|
|
5fd1f07e7e | ||
|
|
c0835cca75 | ||
|
|
f39fb4a84b | ||
|
|
2d9ed6adc4 | ||
|
|
b5c460b17f | ||
|
|
2214ecd81a | ||
|
|
c555682fdc | ||
|
|
c89fe9737f | ||
|
|
36ed4d9ff1 | ||
|
|
d59a0a1a37 | ||
|
|
04a9145fe1 | ||
|
|
cc8124837a | ||
|
|
3a3629f88a | ||
|
|
db3a2b42cd | ||
|
|
8a6f1a6775 | ||
|
|
12c6d8d3e4 | ||
|
|
220ef3cdeb | ||
|
|
7026366b5d | ||
|
|
b29e7bc2c6 | ||
|
|
4e6e0e529d | ||
|
|
5fcf815c56 | ||
|
|
e557ffdc57 | ||
|
|
30bd2c183b | ||
|
|
e17823649a | ||
|
|
116c893d45 | ||
|
|
683d1b594f |
@@ -5,8 +5,8 @@ project (OpenAirInterface LANGUAGES C CXX)
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
set(OAI_VERSION 2.4.0)
|
||||
|
||||
option(CUDA_ENABLE "Enable CUDA accelerated channel simulation" OFF)
|
||||
if(CUDA_ENABLE)
|
||||
option(ENABLE_CHANNEL_SIM_CUDA "Enable CUDA accelerated channel simulation" OFF)
|
||||
if(ENABLE_CHANNEL_SIM_CUDA)
|
||||
find_package(CUDA REQUIRED)
|
||||
find_package(CUDAToolkit REQUIRED)
|
||||
message(STATUS "CUDA explicitly enabled, building with GPU acceleration support.")
|
||||
@@ -34,7 +34,7 @@ if(CUDA_ENABLE)
|
||||
message(STATUS "CUDA Explicit Copy path enabled (default ATS was overridden).")
|
||||
endif()
|
||||
|
||||
add_compile_definitions(ENABLE_CUDA)
|
||||
add_compile_definitions(CHANNEL_SIM_CUDA)
|
||||
endif()
|
||||
|
||||
#########################################################
|
||||
@@ -155,14 +155,17 @@ 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, 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")
|
||||
# (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")
|
||||
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")
|
||||
@@ -173,13 +176,17 @@ 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()
|
||||
if (CPUINFO MATCHES "sse4_1")
|
||||
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")
|
||||
set(C_FLAGS_PROCESSOR "${C_FLAGS_PROCESSOR} -DSIMDE_X86_SSE4_1_NATIVE")
|
||||
endif()
|
||||
if(CPUINFO MATCHES "sse4_2")
|
||||
if(CPUFLAGS MATCHES "sse4_2")
|
||||
set(C_FLAGS_PROCESSOR "${C_FLAGS_PROCESSOR} -DSIMDE_X86_SSE4_2_NATIVE")
|
||||
endif()
|
||||
if(CPUINFO MATCHES "ssse3")
|
||||
if(CPUFLAGS MATCHES "ssse3")
|
||||
set(C_FLAGS_PROCESSOR "${C_FLAGS_PROCESSOR} -DSIMDE_X86_SSSE3_NATIVE")
|
||||
endif()
|
||||
elseif (CMAKE_SYSTEM_PROCESSOR STREQUAL "armv7l")
|
||||
@@ -221,9 +228,14 @@ 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)
|
||||
# used during linking) and "const member leaves the object uninitialized"
|
||||
if(CMAKE_C_COMPILER_ID STREQUAL "Clang" OR CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
|
||||
set(commonOpts "${commonOpts} -Wno-unused-command-line-argument")
|
||||
set(commonOpts "${commonOpts} -Wno-unused-command-line-argument -Wno-default-const-init-field-unsafe")
|
||||
endif()
|
||||
|
||||
if (ENABLE_LDPC_CUDA)
|
||||
# TODO only on specific targets!!
|
||||
set(commonOpts "${commonOpts} -DLDPC_CUDA")
|
||||
endif()
|
||||
|
||||
set(CMAKE_C_FLAGS
|
||||
@@ -842,6 +854,7 @@ 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
|
||||
@@ -1086,15 +1099,30 @@ target_link_libraries(PHY_UE PRIVATE asn1_lte_rrc_hdrs asn1_nr_rrc_hdrs UTIL)
|
||||
add_library(PHY_NR_COMMON ${PHY_NR_SRC_COMMON})
|
||||
target_link_libraries(PHY_NR_COMMON PUBLIC UTIL)
|
||||
|
||||
add_library(PHY_NR ${PHY_NR_SRC})
|
||||
if (ENABLE_LDPC_CUDA)
|
||||
find_package(CUDA REQUIRED)
|
||||
if (NOT CUDA_FOUND)
|
||||
message(FATAL_ERROR "no CUDA found")
|
||||
endif()
|
||||
#SET(CUDA_NVCC_FLAGS "${CUDA_NVCC_FLAGS};-arch=sm_80 -g -ggdb") # A100
|
||||
#SET(CUDA_NVCC_FLAGS "${CUDA_NVCC_FLAGS};-arch=sm_90") # GH200
|
||||
#SET(CUDA_NVCC_FLAGS "${CUDA_NVCC_FLAGS};-arch=sm_87") # Jetson
|
||||
#SET(CUDA_NVCC_FLAGS "${CUDA_NVCC_FLAGS};-arch=sm_89") # L40S
|
||||
SET(CUDA_NVCC_FLAGS "${CUDA_NVCC_FLAGS};-arch=sm_121") # GB10
|
||||
set(CUDA_VERBOS_BUILD_ON)
|
||||
cuda_add_library(PHY_NR ${PHY_NR_SRC} ${PHY_NR_SRC_CU})
|
||||
cuda_add_library(PHY_NR_UE ${PHY_NR_UE_SRC} ${PHY_NR_UE_SRC_CU})
|
||||
else()
|
||||
add_library(PHY_NR ${PHY_NR_SRC})
|
||||
add_library(PHY_NR_UE ${PHY_NR_UE_SRC})
|
||||
endif()
|
||||
target_link_libraries(PHY_NR nr_phy_common nr_common nr_fapi_p5 polar smallblock ds)
|
||||
|
||||
add_library(PHY_NR_NO_AVX_256 ${PHY_NR_SRC})
|
||||
target_link_libraries(PHY_NR_NO_AVX_256 nr_phy_common nr_common)
|
||||
target_compile_definitions(PHY_NR_NO_AVX_256 PUBLIC USE_128BIT)
|
||||
|
||||
add_library(PHY_NR_UE ${PHY_NR_UE_SRC})
|
||||
target_link_libraries(PHY_NR_UE PRIVATE asn1_nr_rrc_hdrs nr_phy_common nr_common UTIL polar smallblock)
|
||||
target_link_libraries(PHY_NR_UE asn1_nr_rrc_hdrs nr_phy_common nr_common UTIL polar smallblock)
|
||||
|
||||
add_library(PHY_RU ${PHY_SRC_RU})
|
||||
target_link_libraries(PHY_RU PRIVATE asn1_lte_rrc_hdrs UTIL)
|
||||
@@ -1271,7 +1299,9 @@ 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
|
||||
@@ -1381,7 +1411,6 @@ endif()
|
||||
add_library(L2_LTE_NR
|
||||
# temporary solution until 4G/5G code completely untangled (as evidenced by deletion of the following file)
|
||||
${MAC_DIR}/dummy_functions.c
|
||||
${ENB_APP_SRC}
|
||||
)
|
||||
|
||||
target_link_libraries(L2_LTE_NR PRIVATE f1ap s1ap nr_rrc)
|
||||
@@ -2007,12 +2036,19 @@ add_executable(ldpctest
|
||||
)
|
||||
target_link_libraries(ldpctest PRIVATE
|
||||
-Wl,--start-group UTIL SIMU PHY_COMMON PHY_NR_COMMON -Wl,--end-group
|
||||
m pthread dl ${T_LIB}
|
||||
m pthread dl ${T_LIB} ${CUDA_LIBRARIES}
|
||||
# link 'check_crc' to make it resolved in the LDPC coding libraries
|
||||
# 'check_crc' is not used in ldpctest so it is not linked in the executable by default
|
||||
# --whole-archive links 'check_crc' in the executable even though it is note used, see 'man ld'
|
||||
-Wl,--whole-archive crc_byte -Wl,--no-whole-archive
|
||||
)
|
||||
if (ENABLE_LDPC_CUDA)
|
||||
# ldpctest.c uses cudaHostAlloc(), so include dir/link libr to make available
|
||||
# TODO don't write it directly into ldpctest, but separate compilation unit?
|
||||
find_package(CUDA REQUIRED)
|
||||
target_link_libraries(ldpctest PRIVATE ${CUDA_LIBRARIES})
|
||||
target_include_directories(ldpctest PRIVATE ${CUDA_INCLUDE_DIRS})
|
||||
endif()
|
||||
|
||||
add_library(physim_common OBJECT ${OPENAIR1_DIR}/SIMULATION/NR_PHY/nr_unitary_common.c)
|
||||
target_link_libraries(physim_common PRIVATE UTIL)
|
||||
@@ -2099,13 +2135,13 @@ target_link_libraries(nr_srssim PRIVATE
|
||||
m pthread ITTI dl nr_ue_phy_meas physim_common softmodem_common
|
||||
)
|
||||
|
||||
if(CUDA_ENABLE)
|
||||
if(ENABLE_CHANNEL_SIM_CUDA)
|
||||
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 ENABLE_CUDA)
|
||||
target_compile_definitions(nr_ulsim PRIVATE ENABLE_CUDA)
|
||||
target_compile_definitions(nr_dlsim PRIVATE CHANNEL_SIM_CUDA)
|
||||
target_compile_definitions(nr_ulsim PRIVATE CHANNEL_SIM_CUDA)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
|
||||
@@ -8,8 +8,9 @@
|
||||
<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-Fedore41-Green" alt="Supported OS Fedora 43"></a>
|
||||
<a href="https://getfedora.org/en/workstation/"><img src="https://img.shields.io/badge/OS-Fedore44-Green" alt="Supported OS Fedora 44"></a>
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
|
||||
64
ci-scripts/Jenkinsfile
vendored
64
ci-scripts/Jenkinsfile
vendored
@@ -20,12 +20,13 @@ 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 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 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 flexricOption = ""
|
||||
def runWithOC = false
|
||||
@@ -50,7 +51,7 @@ pipeline {
|
||||
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.eNB_MR}"
|
||||
buildName "${params.requestNumber}"
|
||||
buildDescription "Branch : ${sourceBranch}"
|
||||
}
|
||||
}
|
||||
@@ -64,12 +65,12 @@ pipeline {
|
||||
echo "no LockResources given"
|
||||
allParametersPresent = false
|
||||
}
|
||||
if (params.eNB_SourceCodePath == null) {
|
||||
echo "no eNB_SourceCodePath given"
|
||||
if (params.workspace == null) {
|
||||
echo "no workspace given"
|
||||
allParametersPresent = false
|
||||
}
|
||||
if (params.OC_Credentials != null) {
|
||||
echo "This pipeline is configured to run with Opensift Cluster."
|
||||
echo "This pipeline is configured to run with Openshift Cluster."
|
||||
runWithOC = true
|
||||
if (params.OC_ProjectName == null) {
|
||||
echo "no OC_ProjectName given"
|
||||
@@ -84,21 +85,11 @@ pipeline {
|
||||
}
|
||||
|
||||
echo "CI executor node : ${pythonExecutor}"
|
||||
echo "Source Repository : ${sourceRepository}"
|
||||
echo "Source Branch : ${sourceBranch}"
|
||||
echo "Target Repository : ${targetRepository}"
|
||||
echo "Target Branch : ${targetBranch}"
|
||||
echo "Commit ID : ${commitID}"
|
||||
echo "Testing Repository : ${testRepository}"
|
||||
echo "Testing Branch : ${testBranch}"
|
||||
|
||||
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"
|
||||
@@ -121,28 +112,21 @@ pipeline {
|
||||
}
|
||||
}
|
||||
sh """
|
||||
python3 main.py --mode=InitiateHtml --ranRepository=${targetRepository} \
|
||||
--ranBranch=${sourceBranch} --ranCommitID=${commitID} \
|
||||
--ranAllowMerge=${is_MR} --ranTargetBranch=${targetBranch} \
|
||||
${flexricOption} ${mainPythonAllXmlFiles}
|
||||
python3 main.py --mode=InitiateHtml --repository=${testRepository} \
|
||||
--branch=${testBranch} --commitID=${commitID} \
|
||||
${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 --ranRepository=${targetRepository} \
|
||||
--ranBranch=${sourceBranch} --ranCommitID=${commitID} \
|
||||
--ranAllowMerge=${is_MR} --ranTargetBranch=${targetBranch} \
|
||||
--eNBSourceCodePath=${params.eNB_SourceCodePath} --XMLTestFile=${xmlFile} \
|
||||
python3 main.py --mode=TesteNB --repository=${testRepository} \
|
||||
--branch=${testBranch} \
|
||||
--ranAllowMerge=${mergeWithTarget} --targetBranch=${targetBranch} \
|
||||
--workspace=${params.workspace} --XMLTestFile=${xmlFile} \
|
||||
--OCUserName=${OC_Username} --OCPassword=${OC_Password} --OCProjectName=${OC_ProjectName} \
|
||||
${flexricOption}
|
||||
"""
|
||||
@@ -160,10 +144,10 @@ pipeline {
|
||||
try {
|
||||
timeout (time: 60, unit: 'MINUTES') {
|
||||
sh """
|
||||
python3 main.py --mode=TesteNB --ranRepository=${targetRepository} \
|
||||
--ranBranch=${sourceBranch} --ranCommitID=${commitID} \
|
||||
--ranAllowMerge=${is_MR} --ranTargetBranch=${targetBranch} \
|
||||
--eNBSourceCodePath=${params.eNB_SourceCodePath} --XMLTestFile=${xmlFile} \
|
||||
python3 main.py --mode=TesteNB --repository=${testRepository} \
|
||||
--branch=${testBranch} \
|
||||
--ranAllowMerge=${mergeWithTarget} --targetBranch=${targetBranch} \
|
||||
--workspace=${params.workspace} --XMLTestFile=${xmlFile} \
|
||||
${flexricOption}
|
||||
"""
|
||||
}
|
||||
|
||||
@@ -87,9 +87,6 @@ pipeline {
|
||||
// since a bit, in push events, gitlabUserEmail is not populated
|
||||
gitCommitAuthorEmailAddr = env.gitlabUserEmail
|
||||
echo "GitLab Usermail is ${gitCommitAuthorEmailAddr}"
|
||||
// GitLab-Jenkins plugin integration is lacking to perform the merge by itself
|
||||
// Doing it manually --> it may have merge conflicts
|
||||
|
||||
// Validate MR commits: checks for missing Signed-off-by and merge commits
|
||||
def mrValidationLog = "signedCommit_${env.BUILD_NUMBER}.log"
|
||||
def mrValidationExitCode = sh(
|
||||
@@ -104,7 +101,6 @@ pipeline {
|
||||
if (mrValidationExitCode >= 2) {
|
||||
error("${mrValidationMessage}")
|
||||
}
|
||||
sh "./ci-scripts/doGitLabMerge.sh --src-branch ${env.gitlabSourceBranch} --src-commit ${env.gitlabMergeRequestLastCommit} --target-branch ${env.gitlabTargetBranch} --target-commit ${GIT_COMMIT}"
|
||||
} else {
|
||||
echo "Git Branch is ${GIT_BRANCH}"
|
||||
echo "Git Commit is ${GIT_COMMIT}"
|
||||
@@ -115,29 +111,19 @@ pipeline {
|
||||
}
|
||||
}
|
||||
}
|
||||
post {
|
||||
failure {
|
||||
script {
|
||||
def message = "OAI " + JOB_NAME + " build (" + BUILD_ID + "): Merge Conflicts -- Cannot perform CI"
|
||||
addGitLabMRComment comment: message
|
||||
currentBuild.result = 'FAILURE'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
stage ("Local-Repo-Push") {
|
||||
steps {
|
||||
script {
|
||||
catchError(buildResult: 'FAILURE', stageResult: 'FAILURE') {
|
||||
triggerSlaveJob ('RAN-Local-Repo-Push', 'Local-Repo-Push')
|
||||
}
|
||||
triggerSlaveJob ('RAN-Local-Repo-Push', 'Local-Repo-Push')
|
||||
}
|
||||
}
|
||||
post {
|
||||
failure {
|
||||
script {
|
||||
echo "Push to local repository KO"
|
||||
failingStages += '\n * RAN-Local-Repo-Push'
|
||||
def message = "OAI " + JOB_NAME + " build (" + BUILD_ID + "): Cannot perform CI - merge validation failed (merge conflict, git operation failure, or internal CI error)."
|
||||
addGitLabMRComment comment: message
|
||||
currentBuild.result = 'FAILURE'
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -894,12 +880,19 @@ 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)),
|
||||
string(name: 'eNB_TargetBranch', value: String.valueOf(env.gitlabTargetBranch))
|
||||
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))
|
||||
], propagate: false
|
||||
def localResult = localStatus.getResult()
|
||||
echo "${jobName} Slave Job status is ${localResult}"
|
||||
@@ -914,14 +907,13 @@ def triggerSlaveJob (jobName, gitlabStatusName) {
|
||||
|
||||
def triggerCN5GSlaveJob (jobName, gitlabStatusName) {
|
||||
if ("MERGE".equals(env.gitlabActionType)) {
|
||||
shortenShaOne = sh returnStdout: true, script: 'git log -1 --pretty=format:"%h" --abbrev=8 ' + env.gitlabMergeRequestLastCommit
|
||||
shortenShaOne = shortenShaOne.trim()
|
||||
branchName = env.gitlabSourceBranch.replaceAll("/", "-").trim()
|
||||
fullRanTag = OAI_Registry + '/oai-gnb:' + env.gitlabSourceBranch + '-' + shortenShaOne
|
||||
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 {
|
||||
shortenShaOne = sh returnStdout: true, script: 'git log -1 --pretty=format:"%h" --abbrev=8 ' + env.GIT_COMMIT
|
||||
shortenShaOne = shortenShaOne.trim()
|
||||
fullRanTag = OAI_Registry + '/oai-gnb:develop-' + shortenShaOne
|
||||
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
|
||||
|
||||
@@ -27,21 +27,26 @@ pipeline {
|
||||
steps {
|
||||
script {
|
||||
def missingParams = []
|
||||
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 (!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 (missingParams) {
|
||||
error "Missing required parameters: ${missingParams.join(', ')}"
|
||||
}
|
||||
|
||||
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}"
|
||||
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}"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -51,6 +56,7 @@ 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
|
||||
"""
|
||||
}
|
||||
@@ -58,31 +64,38 @@ pipeline {
|
||||
stage('Add source repo & fetch branches') {
|
||||
steps {
|
||||
sh """
|
||||
git remote add source ${params.SourceRepo} || true
|
||||
git fetch source ${params.eNB_Branch}
|
||||
git fetch origin ${params.eNB_TargetBranch}
|
||||
git remote add source ${params.sourceRepo} || true
|
||||
git fetch source ${params.sourceBranch}
|
||||
"""
|
||||
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 {
|
||||
def shortCommit = params.eNB_CommitID.take(8)
|
||||
env.NEW_BRANCH = "${params.eNB_Branch}-${shortCommit}"
|
||||
env.NEW_BRANCH = "${params.sourceBranch}-${params.sourceCommit}"
|
||||
echo "New branch: ${env.NEW_BRANCH}"
|
||||
}
|
||||
sh """
|
||||
# Checkout source commit
|
||||
git checkout -B ${env.NEW_BRANCH} ${params.eNB_CommitID}
|
||||
git checkout -B ${env.NEW_BRANCH} ${params.sourceCommit}
|
||||
"""
|
||||
}
|
||||
}
|
||||
stage('Merge target into source') {
|
||||
when { expression { return params.mergeWithTarget } }
|
||||
steps {
|
||||
sh """
|
||||
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 "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 "Merge conflicts detected. Aborting."
|
||||
git merge --abort || true
|
||||
exit 1
|
||||
|
||||
@@ -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 | cut -c 1-8'
|
||||
WEEK_SHA = sh returnStdout: true, script: 'git log -n1 --pretty=format:"%H" origin/develop'
|
||||
WEEK_SHA = WEEK_SHA.trim()
|
||||
|
||||
withCredentials([
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# SPDX-License-Identifier: LicenseRef-CSSL-1.0
|
||||
|
||||
#---------------------------------------------------------------------
|
||||
# Python for CI of OAI-eNB + COTS-UE
|
||||
# Python for CI testing
|
||||
#
|
||||
# Required Python Version
|
||||
# Python 3.x
|
||||
@@ -44,74 +44,55 @@ 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'^\-\-eNBRepository=(.+)$|^\-\-ranRepository(.+)$', myArgv, re.IGNORECASE):
|
||||
if re.match(r'^\-\-eNBRepository=(.+)$', myArgv, re.IGNORECASE):
|
||||
matchReg = re.match(r'^\-\-eNBRepository=(.+)$', myArgv, re.IGNORECASE)
|
||||
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)
|
||||
CiTestObj.ranRepository = matchReg.group(1)
|
||||
RAN.ranRepository=matchReg.group(1)
|
||||
HTML.ranRepository=matchReg.group(1)
|
||||
CONTAINERS.ranRepository=matchReg.group(1)
|
||||
CLUSTER.ranRepository=matchReg.group(1)
|
||||
elif re.match(r'^\-\-eNB_AllowMerge=(.+)$|^\-\-ranAllowMerge=(.+)$', myArgv, re.IGNORECASE):
|
||||
if re.match(r'^\-\-eNB_AllowMerge=(.+)$', myArgv, re.IGNORECASE):
|
||||
matchReg = re.match(r'^\-\-eNB_AllowMerge=(.+)$', myArgv, re.IGNORECASE)
|
||||
else:
|
||||
matchReg = re.match(r'^\-\-ranAllowMerge=(.+)$', myArgv, re.IGNORECASE)
|
||||
CiTestObj.repository = matchReg.group(1)
|
||||
RAN.repository=matchReg.group(1)
|
||||
HTML.repository=matchReg.group(1)
|
||||
CONTAINERS.repository=matchReg.group(1)
|
||||
CLUSTER.repository=matchReg.group(1)
|
||||
elif re.match(r'^\-\-ranAllowMerge=(.+)$', myArgv, re.IGNORECASE):
|
||||
matchReg = re.match(r'^\-\-ranAllowMerge=(.+)$', myArgv, re.IGNORECASE)
|
||||
doMerge = matchReg.group(1)
|
||||
if ((doMerge == 'true') or (doMerge == 'True')):
|
||||
CiTestObj.ranAllowMerge = True
|
||||
RAN.ranAllowMerge=True
|
||||
HTML.ranAllowMerge=True
|
||||
CONTAINERS.ranAllowMerge=True
|
||||
CLUSTER.ranAllowMerge=True
|
||||
elif re.match(r'^\-\-eNBBranch=(.+)$|^\-\-ranBranch=(.+)$', myArgv, re.IGNORECASE):
|
||||
if re.match(r'^\-\-eNBBranch=(.+)$', myArgv, re.IGNORECASE):
|
||||
matchReg = re.match(r'^\-\-eNBBranch=(.+)$', myArgv, re.IGNORECASE)
|
||||
RAN.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)
|
||||
CiTestObj.ranBranch = matchReg.group(1)
|
||||
RAN.ranBranch=matchReg.group(1)
|
||||
HTML.ranBranch=matchReg.group(1)
|
||||
CONTAINERS.ranBranch=matchReg.group(1)
|
||||
CLUSTER.ranBranch=matchReg.group(1)
|
||||
elif re.match(r'^\-\-eNBCommitID=(.*)$|^\-\-ranCommitID=(.*)$', myArgv, re.IGNORECASE):
|
||||
if re.match(r'^\-\-eNBCommitID=(.*)$', myArgv, re.IGNORECASE):
|
||||
matchReg = re.match(r'^\-\-eNBCommitID=(.*)$', 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)
|
||||
CiTestObj.ranCommitID = matchReg.group(1)
|
||||
RAN.ranCommitID=matchReg.group(1)
|
||||
HTML.ranCommitID=matchReg.group(1)
|
||||
CONTAINERS.ranCommitID=matchReg.group(1)
|
||||
CLUSTER.ranCommitID=matchReg.group(1)
|
||||
elif re.match(r'^\-\-eNBTargetBranch=(.*)$|^\-\-ranTargetBranch=(.*)$', myArgv, re.IGNORECASE):
|
||||
if re.match(r'^\-\-eNBTargetBranch=(.*)$', myArgv, re.IGNORECASE):
|
||||
matchReg = re.match(r'^\-\-eNBTargetBranch=(.*)$', myArgv, re.IGNORECASE)
|
||||
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)
|
||||
CiTestObj.ranTargetBranch = matchReg.group(1)
|
||||
RAN.ranTargetBranch=matchReg.group(1)
|
||||
HTML.ranTargetBranch=matchReg.group(1)
|
||||
CONTAINERS.ranTargetBranch=matchReg.group(1)
|
||||
CLUSTER.ranTargetBranch=matchReg.group(1)
|
||||
elif re.match(r'^\-\-eNBIPAddress=(.+)$|^\-\-eNB[1-2]IPAddress=(.+)$', myArgv, re.IGNORECASE):
|
||||
print("parameters --eNB*IPAddress ignored")
|
||||
elif re.match(r'^\-\-eNBUserName=(.+)$|^\-\-eNB[1-2]UserName=(.+)$', myArgv, re.IGNORECASE):
|
||||
print("parameters --eNB*UserName ignored")
|
||||
elif re.match(r'^\-\-eNBPassword=(.+)$|^\-\-eNB[1-2]Password=(.+)$', myArgv, re.IGNORECASE):
|
||||
print("parameter --eNB*Password ignored")
|
||||
elif re.match(r'^\-\-eNBSourceCodePath=(.+)$|^\-\-eNB[1-2]SourceCodePath=(.+)$', myArgv, re.IGNORECASE):
|
||||
if re.match(r'^\-\-eNBSourceCodePath=(.+)$', myArgv, re.IGNORECASE):
|
||||
RAN.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:
|
||||
matchReg = re.match(r'^\-\-eNBSourceCodePath=(.+)$', myArgv, re.IGNORECASE)
|
||||
RAN.eNBSourceCodePath=matchReg.group(1)
|
||||
CONTAINERS.eNBSourceCodePath=matchReg.group(1)
|
||||
CLUSTER.eNBSourceCodePath=matchReg.group(1)
|
||||
elif re.match(r'^\-\-eNB1SourceCodePath=(.+)$', myArgv, re.IGNORECASE):
|
||||
print("parameter --eNB1SourceCodePath ignored")
|
||||
elif re.match(r'^\-\-eNB2SourceCodePath=(.+)$', myArgv, re.IGNORECASE):
|
||||
print("parameter --eNB2SourceCodePath ignored")
|
||||
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))
|
||||
|
||||
@@ -50,17 +50,16 @@ def OC_logout(cmd):
|
||||
|
||||
class Cluster:
|
||||
def __init__(self):
|
||||
self.eNBSourceCodePath = ""
|
||||
self.workspace = ""
|
||||
self.OCUserName = ""
|
||||
self.OCPassword = ""
|
||||
self.OCProjectName = ""
|
||||
self.OCUrl = OCUrl
|
||||
self.OCRegistry = OCRegistry
|
||||
self.ranRepository = ""
|
||||
self.ranBranch = ""
|
||||
self.ranCommitID = ""
|
||||
self.ranAllowMerge = False
|
||||
self.ranTargetBranch = ""
|
||||
self.repository = ""
|
||||
self.branch = ""
|
||||
self.merge = False
|
||||
self.targetBranch = ""
|
||||
self.cmd = None
|
||||
|
||||
def _recreate_entitlements(self):
|
||||
@@ -101,7 +100,7 @@ class Cluster:
|
||||
def _start_build(self, name):
|
||||
# will return "immediately" but build runs in background
|
||||
# if multiple builds are started at the same time, this can take some time, however
|
||||
ret = self.cmd.run(f'oc start-build {name} --from-dir={self.eNBSourceCodePath} --exclude=""')
|
||||
ret = self.cmd.run(f'oc start-build {name} --from-dir={self.workspace} --exclude=""')
|
||||
regres = re.search(r'build.build.openshift.io/(?P<jobname>[a-zA-Z0-9\-]+) started', ret.stdout)
|
||||
if ret.returncode != 0 or ret.stdout.count('Uploading finished') != 1 or regres is None:
|
||||
logging.error(f"error during oc start-build: {ret.stdout}")
|
||||
@@ -157,7 +156,7 @@ class Cluster:
|
||||
OC_logout(cmd)
|
||||
HTML.CreateHtmlTestRow('N/A', 'KO', CONST.OC_LOGIN_FAIL)
|
||||
return False
|
||||
tag = cls_containerize.CreateTag(self.ranCommitID, self.ranBranch, self.ranAllowMerge)
|
||||
tag = self.branch
|
||||
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)
|
||||
@@ -174,12 +173,12 @@ class Cluster:
|
||||
return (image, archiveArtifact(self.cmd, ctx, fn))
|
||||
|
||||
def BuildClusterImage(self, ctx, node, HTML):
|
||||
if self.ranRepository == '' or self.ranBranch == '' or self.ranCommitID == '':
|
||||
if self.repository == '' or self.branch == '':
|
||||
HELP.GenericHelp(CONST.Version)
|
||||
raise ValueError(f'Insufficient Parameter: ranRepository {self.ranRepository} ranBranch {ranBranch} ranCommitID {self.ranCommitID}')
|
||||
lSourcePath = self.eNBSourceCodePath
|
||||
raise ValueError(f'Insufficient Parameter: repository {self.repository} branch {self.branch}')
|
||||
lSourcePath = self.workspace
|
||||
if node == '' or lSourcePath == '':
|
||||
raise ValueError('Insufficient Parameter: eNBSourceCodePath missing')
|
||||
raise ValueError('Insufficient Parameter: workspace missing')
|
||||
ocUserName = self.OCUserName
|
||||
ocPassword = self.OCPassword
|
||||
ocProjectName = self.OCProjectName
|
||||
@@ -200,22 +199,22 @@ class Cluster:
|
||||
|
||||
baseTag = 'develop'
|
||||
forceBaseImageBuild = False
|
||||
if self.ranAllowMerge: # merging MR branch into develop -> temporary image
|
||||
branchName = self.ranBranch.replace('/','-')
|
||||
imageTag = f'{branchName}-{self.ranCommitID[0:8]}'
|
||||
if self.ranTargetBranch == 'develop':
|
||||
if self.merge: # merging MR branch into develop -> temporary image
|
||||
branchName = self.branch.replace('/','-')
|
||||
imageTag = f'{branchName}'
|
||||
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)
|
||||
if result is not None:
|
||||
forceBaseImageBuild = True
|
||||
baseTag = 'ci-temp'
|
||||
# if the branch name contains integration_20xx_wyy, let rebuild ran-base
|
||||
result = re.search('integration_20([0-9]{2})_w([0-9]{2})', self.ranBranch)
|
||||
result = re.search('integration_20([0-9]{2})_w([0-9]{2})', self.branch)
|
||||
if not forceBaseImageBuild and result is not None:
|
||||
forceBaseImageBuild = True
|
||||
baseTag = 'ci-temp'
|
||||
else:
|
||||
imageTag = f'develop-{self.ranCommitID[0:8]}'
|
||||
imageTag = self.branch
|
||||
forceBaseImageBuild = True
|
||||
|
||||
# logging to OC Cluster and then switch to corresponding project
|
||||
|
||||
@@ -32,35 +32,15 @@ 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, ranRepository, ranCommitID, ranTargetBranch, ranAllowMerge):
|
||||
if ranCommitID == '':
|
||||
logging.error('need ranCommitID in CreateWorkspace()')
|
||||
raise ValueError('Insufficient Parameter in CreateWorkspace(): need ranCommitID')
|
||||
|
||||
def CreateWorkspace(host, sourcePath, repository, branch):
|
||||
script = "scripts/create_workspace.sh"
|
||||
options = f"{sourcePath} {ranRepository} {ranCommitID}"
|
||||
if ranAllowMerge:
|
||||
if ranTargetBranch == '':
|
||||
ranTargetBranch = 'develop'
|
||||
options += f" {ranTargetBranch}"
|
||||
options = f"{sourcePath} {repository} {branch}"
|
||||
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(ranCommitID, ranBranch, ranAllowMerge):
|
||||
if ranCommitID == 'develop':
|
||||
return 'develop'
|
||||
shortCommit = ranCommitID[0:8]
|
||||
if ranAllowMerge:
|
||||
# Allowing contributor to have a name/branchName format
|
||||
branchName = ranBranch.replace('/','-')
|
||||
tagToUse = f'{branchName}-{shortCommit}'
|
||||
else:
|
||||
tagToUse = f'develop-{shortCommit}'
|
||||
return tagToUse
|
||||
|
||||
def AnalyzeBuildLogs(image, lf):
|
||||
committed = False
|
||||
tagged = False
|
||||
@@ -75,7 +55,7 @@ def AnalyzeBuildLogs(image, lf):
|
||||
committed = committed or lineHasCommit
|
||||
if re.search(r'error:|Errors|ERROR', line):
|
||||
errors.append(f"=> {line.strip()}")
|
||||
status = (committed or tagged) and len(errors) == 0
|
||||
status = (committed or tagged)
|
||||
logging.info(f"Analyzing {image}, file {lf}: {status=}, {len(errors)} errors")
|
||||
for e in errors:
|
||||
logging.info(e)
|
||||
@@ -172,14 +152,12 @@ class Containerize():
|
||||
|
||||
def __init__(self):
|
||||
|
||||
self.ranRepository = ''
|
||||
self.ranBranch = ''
|
||||
self.ranAllowMerge = False
|
||||
self.ranCommitID = ''
|
||||
self.ranTargetBranch = ''
|
||||
self.eNBSourceCodePath = ''
|
||||
self.repository = ''
|
||||
self.branch = ''
|
||||
self.merge = False
|
||||
self.targetBranch = ''
|
||||
self.workspace = ''
|
||||
self.imageKind = ''
|
||||
self.proxyCommit = None
|
||||
self.yamlPath = ''
|
||||
self.services = ''
|
||||
self.deploymentTag = ''
|
||||
@@ -193,16 +171,27 @@ class Containerize():
|
||||
#-----------------------------------------------------------
|
||||
|
||||
def BuildImage(self, ctx, node, HTML):
|
||||
lSourcePath = self.eNBSourceCodePath
|
||||
lSourcePath = self.workspace
|
||||
logging.debug('Building on server: ' + node)
|
||||
cmd = cls_cmd.getConnection(node)
|
||||
log_files = []
|
||||
|
||||
dockerfileprefix = '.ubuntu'
|
||||
|
||||
baseImage = 'ran-base'
|
||||
baseTag = 'develop'
|
||||
buildImage = 'ran-build'
|
||||
forceBaseImageBuild = False
|
||||
imageTag = 'develop'
|
||||
|
||||
result = re.search('native_cuda_armv8', self.imageKind)
|
||||
if result is not None:
|
||||
baseImage = 'ran-base-cuda'
|
||||
buildImage = 'ran-build-cuda'
|
||||
dockerfileprefix = '.cuda.ubuntu'
|
||||
# we always build the ran-build image with all targets
|
||||
# Creating a tupple with the imageName, the DockerFile prefix pattern, targetName and sanitized option
|
||||
imageNames = [('ran-build', 'build', 'ran-build', '')]
|
||||
imageNames = [(buildImage, 'build', f'{buildImage}', '')]
|
||||
result = re.search('eNB', self.imageKind)
|
||||
if result is not None:
|
||||
imageNames.append(('oai-enb', 'eNB', 'oai-enb', ''))
|
||||
@@ -242,23 +231,23 @@ class Containerize():
|
||||
imageNames.append(('oai-gnb', 'gNB', 'oai-gnb', ''))
|
||||
imageNames.append(('oai-nr-cuup', 'nr-cuup', 'oai-nr-cuup', ''))
|
||||
imageNames.append(('oai-nr-ue', 'nrUE', 'oai-nr-ue', ''))
|
||||
|
||||
result = re.search('native_cuda_armv8', self.imageKind)
|
||||
if result is not None:
|
||||
imageNames.append(('oai-gnb', 'gNB', 'oai-gnb', ''))
|
||||
imageNames.append(('oai-nr-ue', 'nrUE', 'oai-nr-ue', ''))
|
||||
|
||||
cmd.cd(lSourcePath)
|
||||
|
||||
baseImage = 'ran-base'
|
||||
baseTag = 'develop'
|
||||
forceBaseImageBuild = False
|
||||
imageTag = 'develop'
|
||||
if (self.ranAllowMerge):
|
||||
if (self.merge):
|
||||
imageTag = 'ci-temp'
|
||||
if self.ranTargetBranch == 'develop':
|
||||
if self.targetBranch == 'develop':
|
||||
cmd.run(f'git diff HEAD..origin/develop -- cmake_targets/build_oai cmake_targets/tools/build_helper docker/Dockerfile.base{dockerfileprefix} | grep --colour=never -i INDEX')
|
||||
result = re.search('index', cmd.getBefore())
|
||||
if result is not None:
|
||||
forceBaseImageBuild = True
|
||||
baseTag = 'ci-temp'
|
||||
# if the branch name contains integration_20xx_wyy, let rebuild ran-base
|
||||
result = re.search('integration_20([0-9]{2})_w([0-9]{2})', self.ranBranch)
|
||||
result = re.search('integration_20([0-9]{2})_w([0-9]{2})', self.branch)
|
||||
if not forceBaseImageBuild and result is not None:
|
||||
forceBaseImageBuild = True
|
||||
baseTag = 'ci-temp'
|
||||
@@ -276,17 +265,17 @@ class Containerize():
|
||||
# On when the base image docker file is being modified.
|
||||
if forceBaseImageBuild:
|
||||
cmd.run(f"docker image rm {baseImage}:{baseTag}")
|
||||
logfile = f'{lSourcePath}/cmake_targets/log/ran-base.docker.log'
|
||||
logfile = f'{lSourcePath}/cmake_targets/log/{baseImage}.docker.log'
|
||||
option = f" --build-arg UBUNTU_IMAGE={DEFAULT_REGISTRY}/{ubuntuImage}"
|
||||
cmd.run(f"docker build --target {baseImage} --tag {baseImage}:{baseTag} --file docker/Dockerfile.base{dockerfileprefix} {option} . &> {logfile}", timeout=1600)
|
||||
t = ("ran-base", archiveArtifact(cmd, ctx, logfile))
|
||||
t = (baseImage, archiveArtifact(cmd, ctx, logfile))
|
||||
log_files.append(t)
|
||||
|
||||
# First verify if the base image was properly created.
|
||||
ret = cmd.run(f"docker image inspect --format=\'Size = {{{{.Size}}}} bytes\' {baseImage}:{baseTag}")
|
||||
|
||||
allImagesSize = {}
|
||||
if ret.returncode != 0:
|
||||
logging.error('\u001B[1m Could not build properly ran-base\u001B[0m')
|
||||
logging.error(f'\u001B[1m Could not build properly {baseImage}\u001B[0m')
|
||||
# Recover the name of the failed container?
|
||||
cmd.run(f"docker ps --quiet --filter \"status=exited\" -n1 | xargs --no-run-if-empty docker rm -f")
|
||||
cmd.run(f"docker image prune --force")
|
||||
@@ -299,10 +288,10 @@ class Containerize():
|
||||
if result is not None:
|
||||
size = float(result.group("size")) / 1000000
|
||||
imageSizeStr = f'{size:.1f}'
|
||||
logging.debug(f'\u001B[1m ran-base size is {imageSizeStr} Mbytes\u001B[0m')
|
||||
allImagesSize['ran-base'] = f'{imageSizeStr} Mbytes'
|
||||
logging.debug(f'\u001B[1m {baseImage} size is {imageSizeStr} Mbytes\u001B[0m')
|
||||
allImagesSize[baseImage] = f'{imageSizeStr} Mbytes'
|
||||
else:
|
||||
logging.debug('ran-base size is unknown')
|
||||
logging.debug(f'{baseImage} size is unknown')
|
||||
|
||||
# Build the target image(s)
|
||||
status = True
|
||||
@@ -313,11 +302,11 @@ class Containerize():
|
||||
cmd.run(f'sed -i -e "s#{baseImage}:latest#{baseImage}:{baseTag}#" docker/Dockerfile.{pattern}{dockerfileprefix}')
|
||||
# target images should use the proper ran-build image
|
||||
if image != 'ran-build' and "-asan" in name:
|
||||
cmd.run(f'sed -i -e "s#ran-build:latest#ran-build-asan:{imageTag}#" docker/Dockerfile.{pattern}{dockerfileprefix}')
|
||||
cmd.run(f'sed -i -e "s#{buildImage}:latest#{buildImage}-asan:{imageTag}#" docker/Dockerfile.{pattern}{dockerfileprefix}')
|
||||
elif "fhi72" in name or name == "oai-nr-oru":
|
||||
cmd.run(f'sed -i -e "s#ran-build-fhi72:latest#ran-build-fhi72:{imageTag}#" docker/Dockerfile.{pattern}{dockerfileprefix}')
|
||||
elif image != 'ran-build':
|
||||
cmd.run(f'sed -i -e "s#ran-build:latest#ran-build:{imageTag}#" docker/Dockerfile.{pattern}{dockerfileprefix}')
|
||||
cmd.run(f'sed -i -e "s#{buildImage}:latest#{buildImage}:{imageTag}#" docker/Dockerfile.{pattern}{dockerfileprefix}')
|
||||
if image == 'oai-gnb-aerial':
|
||||
cmd.run('cp -f /opt/nvidia-ipc/nvipc_src.2026.01.07.tar.gz .')
|
||||
logfile = f'{lSourcePath}/cmake_targets/log/{name}.docker.log'
|
||||
@@ -376,90 +365,8 @@ class Containerize():
|
||||
logging.error('\u001B[1m Building OAI Images Failed\u001B[0m')
|
||||
return status
|
||||
|
||||
def BuildProxy(self, ctx, node, HTML):
|
||||
lSourcePath = self.eNBSourceCodePath
|
||||
logging.debug('Building on server: ' + node)
|
||||
ssh = cls_cmd.getConnection(node)
|
||||
|
||||
oldRanCommidID = self.ranCommitID
|
||||
oldRanRepository = self.ranRepository
|
||||
oldRanAllowMerge = self.ranAllowMerge
|
||||
oldRanTargetBranch = self.ranTargetBranch
|
||||
self.ranCommitID = self.proxyCommit
|
||||
self.ranRepository = 'https://github.com/EpiSci/oai-lte-5g-multi-ue-proxy.git'
|
||||
self.ranAllowMerge = False
|
||||
self.ranTargetBranch = 'master'
|
||||
|
||||
# Let's remove any previous run artifacts if still there
|
||||
ssh.run('docker image prune --force')
|
||||
# Remove any previous proxy image
|
||||
ssh.run('docker image rm oai-lte-multi-ue-proxy:latest')
|
||||
|
||||
tag = self.proxyCommit
|
||||
logging.debug('building L2sim proxy image for tag ' + tag)
|
||||
# check if the corresponding proxy image with tag exists. If not, build it
|
||||
ret = ssh.run(f'docker image inspect --format=\'Size = {{{{.Size}}}} bytes\' proxy:{tag}')
|
||||
buildProxy = ret.returncode != 0 # if no image, build new proxy
|
||||
if buildProxy:
|
||||
ssh.run(f'rm -Rf {lSourcePath}')
|
||||
success = CreateWorkspace(node, lSourcePath, self.ranRepository, self.ranCommitID, self.ranTargetBranch, self.ranAllowMerge)
|
||||
if not success:
|
||||
raise Exception("could not clone proxy repository")
|
||||
|
||||
fullpath = f'{lSourcePath}/proxy_build.log'
|
||||
|
||||
ssh.run(f'docker build --target oai-lte-multi-ue-proxy --tag proxy:{tag} --file {lSourcePath}/docker/Dockerfile.ubuntu18.04 {lSourcePath} > {fullpath} 2>&1')
|
||||
archiveArtifact(ssh, ctx, fullpath)
|
||||
|
||||
ssh.run('docker image prune --force')
|
||||
ret = ssh.run(f'docker image inspect --format=\'Size = {{{{.Size}}}} bytes\' proxy:{tag}')
|
||||
if ret.returncode != 0:
|
||||
logging.error('\u001B[1m Build of L2sim proxy failed\u001B[0m')
|
||||
ssh.close()
|
||||
HTML.CreateHtmlTestRow('commit ' + tag, 'KO', CONST.ALL_PROCESSES_OK)
|
||||
return False
|
||||
else:
|
||||
logging.debug('L2sim proxy image for tag ' + tag + ' already exists, skipping build')
|
||||
|
||||
# retag the build images to that we pick it up later
|
||||
ssh.run(f'docker image tag proxy:{tag} oai-lte-multi-ue-proxy:latest')
|
||||
|
||||
# we assume that the host on which this is built will also run the proxy. The proxy
|
||||
# currently requires the following command, and the docker-compose up mechanism of
|
||||
# the CI does not allow to run arbitrary commands. Note that the following actually
|
||||
# belongs to the deployment, not the build of the proxy...
|
||||
logging.warning('the following command belongs to deployment, but no mechanism exists to exec it there!')
|
||||
ssh.run('sudo ifconfig lo: 127.0.0.2 netmask 255.0.0.0 up')
|
||||
|
||||
# to prevent accidentally overwriting data that might be used later
|
||||
self.ranCommitID = oldRanCommidID
|
||||
self.ranRepository = oldRanRepository
|
||||
self.ranAllowMerge = oldRanAllowMerge
|
||||
self.ranTargetBranch = oldRanTargetBranch
|
||||
|
||||
ret = ssh.run(f'docker image inspect --format=\'Size = {{{{.Size}}}} bytes\' proxy:{tag}')
|
||||
result = re.search(r'Size *= *(?P<size>[0-9\-]+) *bytes', ret.stdout)
|
||||
# Cleaning any created tmp volume
|
||||
ssh.run('docker volume prune --force')
|
||||
ssh.close()
|
||||
|
||||
allImagesSize = {}
|
||||
if result is not None:
|
||||
imageSize = float(result.group('size')) / 1000000
|
||||
logging.debug('\u001B[1m proxy size is ' + ('%.0f' % imageSize) + ' Mbytes\u001B[0m')
|
||||
allImagesSize['proxy'] = str(round(imageSize,1)) + ' Mbytes'
|
||||
logging.info('\u001B[1m Building L2sim Proxy Image Pass\u001B[0m')
|
||||
HTML.CreateHtmlTestRow('commit ' + tag, 'OK', CONST.ALL_PROCESSES_OK)
|
||||
return True
|
||||
else:
|
||||
logging.error('proxy size is unknown')
|
||||
allImagesSize['proxy'] = 'unknown'
|
||||
logging.error('\u001B[1m Build of L2sim proxy failed\u001B[0m')
|
||||
HTML.CreateHtmlTestRow('commit ' + tag, 'KO', CONST.ALL_PROCESSES_OK)
|
||||
return False
|
||||
|
||||
def BuildRunTests(self, ctx, node, dockerfile, runtime_opt, ctest_opt, HTML):
|
||||
lSourcePath = self.eNBSourceCodePath
|
||||
lSourcePath = self.workspace
|
||||
logging.debug('Building on server: ' + node)
|
||||
cmd = cls_cmd.getConnection(node)
|
||||
cmd.cd(lSourcePath)
|
||||
@@ -467,8 +374,8 @@ class Containerize():
|
||||
# check that ran-base image exists as we expect it
|
||||
baseImage = 'ran-base'
|
||||
baseTag = 'develop'
|
||||
if self.ranAllowMerge:
|
||||
if self.ranTargetBranch == 'develop':
|
||||
if self.merge:
|
||||
if self.targetBranch == 'develop':
|
||||
cmd.run(f'git diff HEAD..origin/develop -- cmake_targets/build_oai cmake_targets/tools/build_helper docker/Dockerfile.base.ubuntu | grep --colour=never -i INDEX')
|
||||
result = re.search('index', cmd.getBefore())
|
||||
if result is not None:
|
||||
@@ -511,7 +418,7 @@ class Containerize():
|
||||
return False
|
||||
|
||||
def Push_Image_to_Local_Registry(self, node, HTML, tag_prefix=""):
|
||||
lSourcePath = self.eNBSourceCodePath
|
||||
lSourcePath = self.workspace
|
||||
logging.debug('Pushing images to server: ' + node)
|
||||
ssh = cls_cmd.getConnection(node)
|
||||
imagePrefix = DEFAULT_REGISTRY
|
||||
@@ -524,10 +431,10 @@ class Containerize():
|
||||
return False
|
||||
|
||||
orgTag = 'develop'
|
||||
if self.ranAllowMerge:
|
||||
if self.merge:
|
||||
orgTag = 'ci-temp'
|
||||
for image in IMAGES:
|
||||
tagToUse = tag_prefix + CreateTag(self.ranCommitID, self.ranBranch, self.ranAllowMerge)
|
||||
tagToUse = tag_prefix + self.branch
|
||||
imageTag = f"{image}:{tagToUse}"
|
||||
ret = ssh.run(f'docker image tag {image}:{orgTag} {imagePrefix}/{imageTag}')
|
||||
if ret.returncode != 0:
|
||||
@@ -540,7 +447,7 @@ class Containerize():
|
||||
HTML.CreateHtmlTestRow(msg, 'KO', CONST.ALL_PROCESSES_OK)
|
||||
return False
|
||||
# Creating a develop tag on the local private registry
|
||||
if not self.ranAllowMerge:
|
||||
if not self.merge:
|
||||
devTag = f"{tag_prefix}develop"
|
||||
ssh.run(f'docker image tag {image}:{orgTag} {imagePrefix}/{image}:{devTag}')
|
||||
ssh.run(f'docker push {imagePrefix}/{image}:{devTag}')
|
||||
@@ -588,7 +495,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 = CreateTag(self.ranCommitID, self.ranBranch, self.ranAllowMerge)
|
||||
tag = self.branch
|
||||
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}"
|
||||
@@ -601,7 +508,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 = CreateTag(self.ranCommitID, self.ranBranch, self.ranAllowMerge)
|
||||
tag = self.branch
|
||||
|
||||
status = True
|
||||
with cls_cmd.getConnection(node) as myCmd:
|
||||
@@ -620,17 +527,17 @@ class Containerize():
|
||||
return status
|
||||
|
||||
def Create_Workspace(self, node, HTML):
|
||||
lSourcePath = self.eNBSourceCodePath
|
||||
success = CreateWorkspace(node, lSourcePath, self.ranRepository, self.ranCommitID, self.ranTargetBranch, self.ranAllowMerge)
|
||||
sourcePath = self.workspace
|
||||
success = CreateWorkspace(node, sourcePath, self.repository, self.branch)
|
||||
if success:
|
||||
HTML.CreateHtmlTestRowQueue('N/A', 'OK', [f"created workspace {lSourcePath}"])
|
||||
HTML.CreateHtmlTestRowQueue('N/A', 'OK', [f"created workspace {sourcePath} on node {node}"])
|
||||
else:
|
||||
HTML.CreateHtmlTestRowQueue('N/A', 'KO', ["cannot create workspace"])
|
||||
return success
|
||||
|
||||
def DeployObject(self, ctx, node, HTML):
|
||||
num_attempts = self.num_attempts
|
||||
lSourcePath = self.eNBSourceCodePath
|
||||
lSourcePath = self.workspace
|
||||
yaml = self.yamlPath.strip('/')
|
||||
wd = f'{lSourcePath}/{yaml}'
|
||||
wd_yaml = f'{wd}/docker-compose.y*ml'
|
||||
@@ -674,7 +581,7 @@ class Containerize():
|
||||
return deployed
|
||||
|
||||
def StopObject(self, ctx, node, HTML):
|
||||
lSourcePath = self.eNBSourceCodePath
|
||||
lSourcePath = self.workspace
|
||||
if not self.services:
|
||||
raise ValueError(f'no services provided')
|
||||
logging.info(f'\u001B[1m Stopping objects "{self.services}" from server: {node}\u001B[0m')
|
||||
@@ -703,7 +610,7 @@ class Containerize():
|
||||
return success
|
||||
|
||||
def UndeployObject(self, ctx, node, HTML, to_analyze):
|
||||
lSourcePath = self.eNBSourceCodePath
|
||||
lSourcePath = self.workspace
|
||||
logging.info(f'\u001B[1m Undeploying all objects from server {node}\u001B[0m')
|
||||
yaml = self.yamlPath.strip('/')
|
||||
wd = f'{lSourcePath}/{yaml}'
|
||||
@@ -741,7 +648,7 @@ class Containerize():
|
||||
def AnalyzeRTStatsObject(self, HTML, node, ctx, thresholds, service=None):
|
||||
logging.info(f'Analyzing realtime stats from server: {node}')
|
||||
yaml = self.yamlPath.strip('/')
|
||||
wd = f'{self.eNBSourceCodePath}/{yaml}'
|
||||
wd = f'{self.workspace}/{yaml}'
|
||||
wd_yaml = f'{wd}/docker-compose.y*ml'
|
||||
|
||||
with cls_cmd.getConnection(node) as cmd:
|
||||
|
||||
@@ -33,11 +33,9 @@ class HTMLManagement():
|
||||
self.htmlHeaderCreated = False
|
||||
self.htmlFooterCreated = False
|
||||
|
||||
self.ranRepository = ''
|
||||
self.ranBranch = ''
|
||||
self.ranCommitID = ''
|
||||
self.ranAllowMerge = False
|
||||
self.ranTargetBranch = ''
|
||||
self.repository = ''
|
||||
self.branch = ''
|
||||
self.commitID = ''
|
||||
|
||||
self.nbTestXMLfiles = 0
|
||||
self.htmlTabRefs = []
|
||||
@@ -96,47 +94,18 @@ class HTMLManagement():
|
||||
self.htmlFile.write(' </tr>\n')
|
||||
self.htmlFile.write(' <tr>\n')
|
||||
self.htmlFile.write(' <td bgcolor = "lightcyan" > <span class="glyphicon glyphicon-cloud-upload"></span> GIT Repository </td>\n')
|
||||
self.htmlFile.write(' <td><a href="' + self.ranRepository + '">' + self.ranRepository + '</a></td>\n')
|
||||
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-wrench"></span> Job Trigger </td>\n')
|
||||
if (self.ranAllowMerge):
|
||||
self.htmlFile.write(' <td>Merge-Request</td>\n')
|
||||
else:
|
||||
self.htmlFile.write(' <td>Push to Branch</td>\n')
|
||||
self.htmlFile.write(' <td bgcolor = "lightcyan" > <span class="glyphicon glyphicon-log-out"></span> Test 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')
|
||||
if (self.ranAllowMerge):
|
||||
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.ranBranch + '</td>\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')
|
||||
self.htmlFile.write(' </tr>\n')
|
||||
self.htmlFile.write(' <tr>\n')
|
||||
if (self.ranAllowMerge):
|
||||
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.ranCommitID + '</td>\n')
|
||||
self.htmlFile.write(' </tr>\n')
|
||||
if self.ranAllowMerge != '' and self.ranCommitID != 'develop':
|
||||
commit_message = subprocess.check_output("git log -n1 --pretty=format:\"%s\" " + self.ranCommitID, shell=True, universal_newlines=True)
|
||||
commit_message = commit_message.strip()
|
||||
self.htmlFile.write(' <tr>\n')
|
||||
if (self.ranAllowMerge):
|
||||
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.ranAllowMerge):
|
||||
self.htmlFile.write(' <tr>\n')
|
||||
self.htmlFile.write(' <td bgcolor = "lightcyan" > <span class="glyphicon glyphicon-log-in"></span> Target Branch </td>\n')
|
||||
if (self.ranTargetBranch == ''):
|
||||
self.htmlFile.write(' <td>develop</td>\n')
|
||||
else:
|
||||
self.htmlFile.write(' <td>' + self.ranTargetBranch + '</td>\n')
|
||||
self.htmlFile.write(' </tr>\n')
|
||||
self.htmlFile.write(' </table>\n')
|
||||
|
||||
self.htmlFile.write(' <br>\n')
|
||||
|
||||
@@ -282,12 +282,8 @@ def Deploy_Physim(ctx, HTML, node, workdir, script, options):
|
||||
class OaiCiTest():
|
||||
|
||||
def __init__(self):
|
||||
self.ranRepository = ''
|
||||
self.ranBranch = ''
|
||||
self.ranCommitID = ''
|
||||
self.ranAllowMerge = False
|
||||
self.ranTargetBranch = ''
|
||||
|
||||
self.repository = ''
|
||||
self.branch = ''
|
||||
self.testXMLfiles = []
|
||||
self.ping_args = ''
|
||||
self.ping_packetloss_threshold = ''
|
||||
@@ -503,8 +499,6 @@ class OaiCiTest():
|
||||
logging.warning(f'Iperf3 server on port {port} detected and terminated')
|
||||
cmd_svr.run(f'{cn.getCmdPrefix()} timeout -vk3 {t} iperf3 -s -B {svrIP} -p {port} -1 {jsonReport} >> /dev/null &', timeout=t)
|
||||
client_ret = cmd_ue.run(f'{ue.getCmdPrefix()} timeout -vk3 {t} {iperf_ue} -c {svrIP} {iperf_opt} {jsonReport} {serverReport} -O 5 >> {client_filename}', timeout=t, reportNonZero=False)
|
||||
if client_ret.returncode != 0:
|
||||
return (False, f'{ue_header}\nIperf client command failed on {bindIP} -> {svrIP}:{port} (return code: {client_ret.returncode})')
|
||||
dest_filename = archiveArtifact(cmd_ue, ctx, client_filename)
|
||||
if udpIperf:
|
||||
status, msg = Iperf_analyzeV3UDP(dest_filename, self.iperf_bitrate_threshold, self.iperf_packetloss_threshold, target_bitrate)
|
||||
@@ -513,6 +507,10 @@ class OaiCiTest():
|
||||
else:
|
||||
status, msg = Iperf_analyzeV3TCPJson(dest_filename, self.iperf_tcp_rate_target)
|
||||
|
||||
# add some diagnostic messages if the actual iperf command returned non-zero
|
||||
if client_ret.returncode != 0:
|
||||
msg = f'{msg}\nIperf client command failed on {bindIP} -> {svrIP}:{port} (return code: {client_ret.returncode})'
|
||||
|
||||
return (status, f'{ue_header}\n{msg}')
|
||||
|
||||
def Iperf(self, ctx, node, HTML, infra_file="ci_infra.yaml"):
|
||||
|
||||
@@ -207,3 +207,40 @@ 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
|
||||
|
||||
@@ -30,7 +30,7 @@ channelmod:
|
||||
- model_name: rfsimu_channel_ue0
|
||||
type: AWGN
|
||||
ploss_dB: 20
|
||||
nose_power_dB: -2
|
||||
noise_power_dB: -2
|
||||
forgetfact: 0
|
||||
offset: 0
|
||||
ds_tdl: 0
|
||||
|
||||
@@ -1,126 +0,0 @@
|
||||
#!/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
|
||||
@@ -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" \
|
||||
-DCUDA_ENABLE=ON \
|
||||
-DENABLE_CHANNEL_SIM_CUDA=ON \
|
||||
-DUSE_UNIFIED_MEMORY=ON \
|
||||
-DUSE_ATS_MEMORY=OFF \
|
||||
-DCMAKE_RUNTIME_OUTPUT_DIRECTORY=/oai-ran/cmake_targets/ran_build/build \
|
||||
|
||||
@@ -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" \
|
||||
-DCUDA_ENABLE=ON \
|
||||
-DENABLE_CHANNEL_SIM_CUDA=ON \
|
||||
-DUSE_UNIFIED_MEMORY=ON \
|
||||
-DUSE_ATS_MEMORY=OFF \
|
||||
-DCMAKE_RUNTIME_OUTPUT_DIRECTORY=/oai-ran/cmake_targets/ran_build/build \
|
||||
|
||||
@@ -22,4 +22,4 @@ WORKDIR /oai-ran
|
||||
COPY . .
|
||||
|
||||
WORKDIR /oai-ran/build
|
||||
RUN cmake -GNinja -DENABLE_TESTS=ON -DCUDA_ENABLE=ON .. && ninja tests
|
||||
RUN cmake -GNinja -DENABLE_TESTS=ON -DENABLE_CHANNEL_SIM_CUDA=ON .. && ninja tests
|
||||
|
||||
@@ -28,16 +28,15 @@ 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(' --ranRepository=[OAI RAN Repository URL] -- ' + repository)
|
||||
print(' --ranBranch=[OAI RAN Repository Branch] -- ' + branch)
|
||||
print(' --ranCommitID=[OAI RAN Repository Commit SHA-1] -- ' + commit)
|
||||
print(' --repository=[OAI RAN Repository URL] -- ' + repository)
|
||||
print(' --branch=[OAI RAN Repository Branch] -- ' + branch)
|
||||
print(' --commitID=[OAI RAN Repository Commit SHA-1] -- ' + commit)
|
||||
print(' --ranAllowMerge=[Allow Merge Request (with target branch) (true or false)] -- ' + mergeallow)
|
||||
print(' --ranTargetBranch=[Target Branch in case of a Merge Request] -- ' + targetbranch)
|
||||
print(' --targetBranch=[Target Branch in case of a Merge Request] -- ' + targetbranch)
|
||||
|
||||
def eNBSrvHelp(sourcepath):
|
||||
print(' --eNBSourceCodePath=[eNB\'s Source Code Path] -- ' + sourcepath)
|
||||
def SrvHelp(sourcepath):
|
||||
print(' --workspace=[directory for workspaces on remote hosts] -- ' + 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)')
|
||||
|
||||
|
||||
@@ -65,21 +65,16 @@ def ExecuteActionWithParam(action, ctx, node):
|
||||
global HTML
|
||||
global CONTAINERS
|
||||
global CLUSTER
|
||||
if action == 'Build_eNB' or action == 'Build_Image' or action == 'Build_Proxy' or action == "Build_Cluster_Image" or action == "Build_Run_Tests":
|
||||
if action == 'Build_eNB' or action == 'Build_Image' or action == "Build_Cluster_Image" or action == "Build_Run_Tests":
|
||||
RAN.Build_eNB_args=test.findtext('Build_eNB_args')
|
||||
CONTAINERS.imageKind=test.findtext('kind')
|
||||
proxy_commit = test.findtext('proxy_commit')
|
||||
dockerfile = test.findtext('dockerfile') or ''
|
||||
runtime_opt = test.findtext('runtime-opt') or ''
|
||||
ctest_opt = test.findtext('ctest-opt') or ''
|
||||
if proxy_commit is not None:
|
||||
CONTAINERS.proxyCommit = proxy_commit
|
||||
if action == 'Build_eNB':
|
||||
success = cls_native.Native.Build(ctx, node, HTML, RAN.eNBSourceCodePath, RAN.Build_eNB_args)
|
||||
success = cls_native.Native.Build(ctx, node, HTML, RAN.workspace, RAN.Build_eNB_args)
|
||||
elif action == 'Build_Image':
|
||||
success = CONTAINERS.BuildImage(ctx, node, HTML)
|
||||
elif action == 'Build_Proxy':
|
||||
success = CONTAINERS.BuildProxy(ctx, node, HTML)
|
||||
elif action == 'Build_Cluster_Image':
|
||||
success = CLUSTER.BuildClusterImage(ctx, node, HTML)
|
||||
elif action == 'Build_Run_Tests':
|
||||
@@ -153,16 +148,16 @@ 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 = cls_containerize.CreateTag(CLUSTER.ranCommitID, CLUSTER.ranBranch, CLUSTER.ranAllowMerge)
|
||||
options = f"oaicicd-core-for-ci-ran {oc_release} {image_tag} {CLUSTER.eNBSourceCodePath}"
|
||||
workdir = CLUSTER.eNBSourceCodePath
|
||||
image_tag = CLUSTER.branch
|
||||
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)
|
||||
|
||||
elif action == 'Build_Deploy_PhySim':
|
||||
ctest_opt = test.findtext('ctest-opt') or ''
|
||||
script = test.findtext('script')
|
||||
options = f"{CONTAINERS.eNBSourceCodePath} {ctest_opt}"
|
||||
workdir = CONTAINERS.eNBSourceCodePath
|
||||
options = f"{CONTAINERS.workspace} {ctest_opt}"
|
||||
workdir = CONTAINERS.workspace
|
||||
success = cls_oaicitest.Deploy_Physim(ctx, HTML, node, workdir, script, options)
|
||||
|
||||
elif action == 'DeployCoreNetwork' or action == 'UndeployCoreNetwork':
|
||||
@@ -174,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 = cls_containerize.CreateTag(CONTAINERS.ranCommitID, CONTAINERS.ranBranch, CONTAINERS.ranAllowMerge)
|
||||
CONTAINERS.deploymentTag = CONTAINERS.branch
|
||||
if action == 'Deploy_Object':
|
||||
success = CONTAINERS.DeployObject(ctx, node, HTML)
|
||||
elif action == 'Stop_Object':
|
||||
@@ -195,7 +190,7 @@ def ExecuteActionWithParam(action, ctx, node):
|
||||
success = CONTAINERS.Create_Workspace(node, HTML)
|
||||
|
||||
elif action == 'LicenceAndFormattingCheck':
|
||||
success = SCA.StaticCodeAnalysis.LicenceAndFormattingCheck(ctx, node, HTML, RAN.eNBSourceCodePath, RAN.ranBranch, RAN.ranAllowMerge, RAN.ranTargetBranch)
|
||||
success = SCA.StaticCodeAnalysis.LicenceAndFormattingCheck(ctx, node, HTML, RAN.workspace, RAN.branch, RAN.merge, RAN.targetBranch)
|
||||
|
||||
elif action == 'Push_Local_Registry':
|
||||
tag_prefix = test.findtext('tag_prefix') or ""
|
||||
@@ -219,14 +214,14 @@ def ExecuteActionWithParam(action, ctx, node):
|
||||
elif action == 'Custom_Command':
|
||||
command = test.findtext('command')
|
||||
# Allow referencing repository workspace path in XML via %%workspace%%
|
||||
command = command.replace("%%workspace%%", CONTAINERS.eNBSourceCodePath)
|
||||
command = command.replace("%%workspace%%", CONTAINERS.workspace)
|
||||
success = cls_oaicitest.Custom_Command(HTML, node, command)
|
||||
|
||||
elif action == 'Custom_Script':
|
||||
script = test.findtext('script')
|
||||
args = test.findtext('args')
|
||||
# Allow referencing repository workspace path in XML via %%workspace%%
|
||||
script = script.replace("%%workspace%%", CONTAINERS.eNBSourceCodePath)
|
||||
script = script.replace("%%workspace%%", CONTAINERS.workspace)
|
||||
success = cls_oaicitest.Custom_Script(HTML, node, script, args)
|
||||
|
||||
elif action == 'Pull_Cluster_Image':
|
||||
@@ -370,15 +365,15 @@ elif re.match('^TesteNB$', mode, re.IGNORECASE) or re.match('^TestUE$', mode, re
|
||||
logging.info('\u001B[1m Starting Scenario: ' + CiTestObj.testXMLfiles[0] + '\u001B[0m')
|
||||
logging.info('\u001B[1m----------------------------------------\u001B[0m')
|
||||
if re.match('^TesteNB$', mode, re.IGNORECASE):
|
||||
if RAN.ranRepository == '' or RAN.ranBranch == '' or RAN.eNBSourceCodePath == '':
|
||||
if RAN.repository == '' or RAN.branch == '' or RAN.workspace == '':
|
||||
HELP.GenericHelp(CONST.Version)
|
||||
if RAN.ranRepository == '':
|
||||
HELP.GitSrvHelp(RAN.ranRepository, RAN.ranBranch, RAN.ranCommitID, RAN.ranAllowMerge, RAN.ranTargetBranch)
|
||||
if RAN.eNBSourceCodePath == '':
|
||||
HELP.eNBSrvHelp(RAN.eNBSourceCodePath)
|
||||
if RAN.repository == '':
|
||||
HELP.GitSrvHelp(RAN.repository, RAN.branch, RAN.merge, RAN.targetBranch)
|
||||
if RAN.workspace == '':
|
||||
HELP.SrvHelp(RAN.workspace)
|
||||
sys.exit('Insufficient Parameter')
|
||||
else:
|
||||
if CiTestObj.ranRepository == '' or CiTestObj.ranBranch == '':
|
||||
if CiTestObj.repository == '' or CiTestObj.branch == '':
|
||||
HELP.GenericHelp(CONST.Version)
|
||||
sys.exit('UE: Insufficient Parameter')
|
||||
|
||||
|
||||
@@ -71,7 +71,7 @@ fi
|
||||
# Check unsigned commits
|
||||
# ----------------------------
|
||||
unsignedCommits=$(
|
||||
for c in $(git rev-list "$TARGET_BRANCH".."$SOURCE_BRANCH"); do
|
||||
for c in $(git rev-list "$TARGET_BRANCH".."$SOURCE_BRANCH" --no-merges); do
|
||||
if ! git log -1 --format=%B "$c" | grep -q "Signed-off-by:"; then
|
||||
git log -1 --format='%h' "$c"
|
||||
fi
|
||||
|
||||
@@ -32,12 +32,11 @@ class RANManagement():
|
||||
|
||||
def __init__(self):
|
||||
|
||||
self.ranRepository = ''
|
||||
self.ranBranch = ''
|
||||
self.ranAllowMerge = False
|
||||
self.ranCommitID = ''
|
||||
self.ranTargetBranch = ''
|
||||
self.eNBSourceCodePath = ''
|
||||
self.repository = ''
|
||||
self.branch = ''
|
||||
self.merge = False
|
||||
self.targetBranch = ''
|
||||
self.workspace = ''
|
||||
self.Initialize_eNB_args = ''
|
||||
self.imageKind = ''
|
||||
self.eNBOptions = ['', '', '']
|
||||
@@ -57,7 +56,7 @@ class RANManagement():
|
||||
raise ValueError(f"{node=}")
|
||||
logging.debug('Starting eNB/gNB on server: ' + node)
|
||||
|
||||
lSourcePath = self.eNBSourceCodePath
|
||||
lSourcePath = self.workspace
|
||||
cmd = cls_cmd.getConnection(node)
|
||||
|
||||
# Initialize_eNB_args usually start with -O and followed by the location in repository
|
||||
@@ -103,7 +102,7 @@ class RANManagement():
|
||||
|
||||
def TerminateeNB(self, ctx, node, HTML, to_analyze):
|
||||
logging.debug('Stopping eNB/gNB on server: ' + node)
|
||||
lSourcePath = self.eNBSourceCodePath
|
||||
lSourcePath = self.workspace
|
||||
cmd = cls_cmd.getConnection(node)
|
||||
ret = cmd.run('ps -aux | grep --color=never -e softmodem | grep -v grep')
|
||||
result = re.search('-softmodem', ret.stdout)
|
||||
@@ -138,7 +137,7 @@ class RANManagement():
|
||||
|
||||
def AnalyzeRTStats(self, HTML, node, ctx, thresholds):
|
||||
logging.info(f'Analyzing realtime stats from server: {node}')
|
||||
lSourcePath = self.eNBSourceCodePath
|
||||
lSourcePath = self.workspace
|
||||
|
||||
logdir = f'{lSourcePath}/cmake_targets'
|
||||
with cls_cmd.getConnection(node) as cmd:
|
||||
|
||||
@@ -30,15 +30,13 @@ 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 --ranRepository=NONE --ranBranch=${CURRENT_BRANCH} \
|
||||
--ranCommitID=${COMMIT_SHA} --ranAllowMerge=false \
|
||||
--ranTargetBranch=NONE \
|
||||
python3 main.py --mode=InitiateHtml --repository=NONE --branch=${CURRENT_BRANCH} \
|
||||
--XMLTestFile=xml_files/${TESTCASE} --local --datefmt="%H:%M:%S"
|
||||
|
||||
python3 main.py --mode=TesteNB --ranRepository=NONE --ranBranch=${CURRENT_BRANCH} \
|
||||
--ranCommitID=${COMMIT_SHA} --ranAllowMerge=false \
|
||||
--ranTargetBranch=NONE \
|
||||
--eNBSourceCodePath=${REPO_PATH} \
|
||||
python3 main.py --mode=TesteNB --repository=NONE --branch=${CURRENT_BRANCH} \
|
||||
--ranAllowMerge=false \
|
||||
--targetBranch=NONE \
|
||||
--workspace=${REPO_PATH} \
|
||||
--XMLTestFile=${TESTCASE} --local --datefmt="%H:%M:%S"
|
||||
RET=$?
|
||||
|
||||
|
||||
@@ -6,22 +6,16 @@ function die() {
|
||||
exit 1
|
||||
}
|
||||
|
||||
[ $# -ge 3 -a $# -le 4 ] || die "usage: $0 <directory> <repository> <ref> [<merge-ref>]"
|
||||
[ $# -eq 3 ] || die "usage: $0 <directory> <repository> <branch>"
|
||||
|
||||
set -ex
|
||||
|
||||
dir=$1
|
||||
repo=$2
|
||||
ref=$3
|
||||
merge=$4
|
||||
branch=$3
|
||||
|
||||
rm -rf ${dir}
|
||||
git clone --filter=blob:none -n ${repo} ${dir}
|
||||
git clone --depth=1 --branch "${branch}" "${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
|
||||
|
||||
@@ -24,7 +24,7 @@ class TestBuild(unittest.TestCase):
|
||||
self._d = tempfile.mkdtemp()
|
||||
logging.warning(f"temporary directory: {self._d}")
|
||||
self.node = 'localhost'
|
||||
self.cont.eNBSourceCodePath = self._d
|
||||
self.cont.workspace = self._d
|
||||
self.ctx = TestCaseCtx.Default(tempfile.mkdtemp())
|
||||
|
||||
def tearDown(self):
|
||||
@@ -33,10 +33,5 @@ class TestBuild(unittest.TestCase):
|
||||
cmd.run(f"rm -rf {self._d}")
|
||||
cmd.run(f'rm -rf {self.ctx.logPath}')
|
||||
|
||||
def test_build_proxy(self):
|
||||
self.cont.proxyCommit = "b64d9bce986b38ca59e8582864ade3fcdd05c0dc"
|
||||
success = self.cont.BuildProxy(self.ctx, self.node, self.html)
|
||||
self.assertTrue(success)
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
|
||||
@@ -41,10 +41,9 @@ class TestDeploymentMethods(unittest.TestCase):
|
||||
self.ci = cls_oaicitest.OaiCiTest()
|
||||
self.cont = cls_containerize.Containerize()
|
||||
self.cont.yamlPath = ''
|
||||
self.cont.ranAllowMerge = True
|
||||
self.cont.ranBranch = ''
|
||||
self.cont.ranCommitID = ''
|
||||
self.cont.eNBSourceCodePath = os.getcwd()
|
||||
self.cont.merge = True
|
||||
self.cont.branch = ''
|
||||
self.cont.workspace = os.getcwd()
|
||||
self.cont.num_attempts = 3
|
||||
self.node = 'localhost'
|
||||
self.ctx = TestCaseCtx.Default(tempfile.mkdtemp())
|
||||
@@ -136,13 +135,12 @@ class TestDeploymentMethods(unittest.TestCase):
|
||||
self.assertTrue(undeploy)
|
||||
|
||||
def test_create_workspace(self):
|
||||
self.cont.eNBSourceCodePath = tempfile.mkdtemp()
|
||||
self.cont.ranRepository = "https://gitlab.eurecom.fr/oai/openairinterface5g.git"
|
||||
self.cont.ranCommitID = "05f9c975eeecbca1bdff5940affad44465f1301f"
|
||||
self.cont.ranBranch = "develop"
|
||||
self.cont.workspace = tempfile.mkdtemp()
|
||||
self.cont.repository = "https://gitlab.eurecom.fr/oai/openairinterface5g.git"
|
||||
self.cont.branch = "develop"
|
||||
ws = self.cont.Create_Workspace(self.node, self.html)
|
||||
with cls_cmd.LocalCmd() as cmd:
|
||||
cmd.run(f"rm -rf {self.cont.eNBSourceCodePath}")
|
||||
cmd.run(f"rm -rf {self.cont.workspace}")
|
||||
self.assertTrue(ws)
|
||||
|
||||
def test_undeploy_loganalysis(self):
|
||||
|
||||
@@ -22,7 +22,7 @@ class TestDeploymentMethods(unittest.TestCase):
|
||||
self.html = cls_oai_html.HTMLManagement()
|
||||
self.html.testCaseId = "000000"
|
||||
self.cont = cls_containerize.Containerize()
|
||||
self.cont.eNBSourceCodePath = os.getcwd()
|
||||
self.cont.workspace = os.getcwd()
|
||||
|
||||
def test_pull_clean_local_reg(self):
|
||||
# the pull function has the authentication at the internal cluster hardcoded
|
||||
|
||||
@@ -9,21 +9,17 @@ rm -f ${file}
|
||||
cd ../../
|
||||
python3 main.py \
|
||||
--mode=InitiateHtml \
|
||||
--ranRepository=https://gitlab.eurecom.fr/oai/openairinterface5g.git \
|
||||
--ranBranch=${branch} \
|
||||
--ranCommitID=${commit} \
|
||||
--ranAllowMerge=true \
|
||||
--ranTargetBranch=develop \
|
||||
--repository=https://gitlab.eurecom.fr/oai/openairinterface5g.git \
|
||||
--branch=${branch} \
|
||||
--XMLTestFile=tests/test-runner/test.xml
|
||||
|
||||
python3 main.py \
|
||||
--mode=TesteNB \
|
||||
--ranRepository=https://gitlab.eurecom.fr/oai/openairinterface5g.git \
|
||||
--ranBranch=${branch} \
|
||||
--ranCommitID=${commit} \
|
||||
--repository=https://gitlab.eurecom.fr/oai/openairinterface5g.git \
|
||||
--branch=${branch} \
|
||||
--ranAllowMerge=true \
|
||||
--ranTargetBranch=develop \
|
||||
--eNBSourceCodePath=NONE \
|
||||
--targetBranch=develop \
|
||||
--workspace=NONE \
|
||||
--XMLTestFile=tests/test-runner/test.xml
|
||||
|
||||
python3 main.py \
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
# SPDX-License-Identifier: LicenseRef-CSSL-1.0
|
||||
- Build_Proxy
|
||||
- Build_Cluster_Image
|
||||
- Pull_Cluster_Image
|
||||
- Build_eNB
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
|
||||
<testCase>
|
||||
<class>Create_Workspace</class>
|
||||
<desc>Create new Workspace for server 0</desc>
|
||||
<desc>Create new Workspace</desc>
|
||||
<node>obelix</node>
|
||||
</testCase>
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
|
||||
<testCase>
|
||||
<class>Create_Workspace</class>
|
||||
<desc>Create new Workspace for server 0</desc>
|
||||
<desc>Create new Workspace</desc>
|
||||
<node>gracehopper3-oai</node>
|
||||
</testCase>
|
||||
|
||||
|
||||
28
ci-scripts/xml_files/container_image_build_cuda_jetson.xml
Normal file
28
ci-scripts/xml_files/container_image_build_cuda_jetson.xml
Normal file
@@ -0,0 +1,28 @@
|
||||
<!-- SPDX-License-Identifier: LicenseRef-CSSL-1.0 -->
|
||||
|
||||
<testCaseList>
|
||||
<htmlTabRef>build-cuda-tab</htmlTabRef>
|
||||
<htmlTabName>Build Container Images for ARM with CUDA</htmlTabName>
|
||||
<htmlTabIcon>wrench</htmlTabIcon>
|
||||
|
||||
<testCase>
|
||||
<class>Create_Workspace</class>
|
||||
<desc>Create new Workspace for server 0</desc>
|
||||
<node>jetson3-oai</node>
|
||||
</testCase>
|
||||
|
||||
<testCase>
|
||||
<class>Build_Image</class>
|
||||
<desc>Build all Images</desc>
|
||||
<node>jetson3-oai</node>
|
||||
<kind>native_cuda_armv8</kind>
|
||||
</testCase>
|
||||
|
||||
<testCase>
|
||||
<class>Push_Local_Registry</class>
|
||||
<desc>Push Images to Local Registry</desc>
|
||||
<node>jetson3-oai</node>
|
||||
<tag_prefix>armv8_cuda_</tag_prefix>
|
||||
</testCase>
|
||||
|
||||
</testCaseList>
|
||||
@@ -7,7 +7,7 @@
|
||||
|
||||
<testCase>
|
||||
<class>Create_Workspace</class>
|
||||
<desc>Create new Workspace for server 0</desc>
|
||||
<desc>Create new Workspace</desc>
|
||||
<node>jetson3-oai</node>
|
||||
</testCase>
|
||||
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
<!-- SPDX-License-Identifier: LicenseRef-CSSL-1.0 -->
|
||||
|
||||
<testCaseList>
|
||||
<htmlTabRef>l2sim-4glte-5gnr-proxy-build</htmlTabRef>
|
||||
<htmlTabName>Build L2sim proxy image</htmlTabName>
|
||||
<htmlTabIcon>wrench</htmlTabIcon>
|
||||
|
||||
<testCase>
|
||||
<class>Build_Proxy</class>
|
||||
<desc>Build L2sim Proxy Image</desc>
|
||||
<node>localhost</node>
|
||||
<proxy_commit>b64d9bce986b38ca59e8582864ade3fcdd05c0dc</proxy_commit>
|
||||
</testCase>
|
||||
|
||||
</testCaseList>
|
||||
@@ -34,7 +34,7 @@
|
||||
|
||||
<testCase>
|
||||
<class>Create_Workspace</class>
|
||||
<desc>Create new Workspace for server 0</desc>
|
||||
<desc>Create new Workspace</desc>
|
||||
<node>hutch</node>
|
||||
</testCase>
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
|
||||
<testCase>
|
||||
<class>Create_Workspace</class>
|
||||
<desc>Create new Workspace for server 0</desc>
|
||||
<desc>Create new Workspace</desc>
|
||||
<node>hutch</node>
|
||||
</testCase>
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
|
||||
<testCase>
|
||||
<class>Create_Workspace</class>
|
||||
<desc>Create new Workspace for server 0</desc>
|
||||
<desc>Create new Workspace</desc>
|
||||
<node>hutch</node>
|
||||
</testCase>
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
|
||||
<testCase>
|
||||
<class>Create_Workspace</class>
|
||||
<desc>Create new Workspace for server 0</desc>
|
||||
<desc>Create new Workspace</desc>
|
||||
<node>hutch</node>
|
||||
</testCase>
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
|
||||
<testCase>
|
||||
<class>Create_Workspace</class>
|
||||
<desc>Create new Workspace for server 0</desc>
|
||||
<desc>Create new Workspace</desc>
|
||||
<node>hutch</node>
|
||||
</testCase>
|
||||
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
|
||||
<testCase>
|
||||
<class>Create_Workspace</class>
|
||||
<desc>Create new Workspace for server 0</desc>
|
||||
<desc>Create new Workspace</desc>
|
||||
<node>hutch</node>
|
||||
</testCase>
|
||||
|
||||
@@ -54,7 +54,7 @@
|
||||
|
||||
<testCase>
|
||||
<class>Create_Workspace</class>
|
||||
<desc>Create new Workspace for server 1</desc>
|
||||
<desc>Create new Workspace</desc>
|
||||
<node>carabe</node>
|
||||
</testCase>
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
|
||||
<testCase>
|
||||
<class>Create_Workspace</class>
|
||||
<desc>Create new Workspace for server 0</desc>
|
||||
<desc>Create new Workspace</desc>
|
||||
<node>hutch</node>
|
||||
</testCase>
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
|
||||
<testCase>
|
||||
<class>Create_Workspace</class>
|
||||
<desc>Create new Workspace for server 0</desc>
|
||||
<desc>Create new Workspace</desc>
|
||||
<node>starsky</node>
|
||||
</testCase>
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
|
||||
<testCase>
|
||||
<class>Create_Workspace</class>
|
||||
<desc>Create new Workspace for server 0</desc>
|
||||
<desc>Create new Workspace</desc>
|
||||
<node>starsky</node>
|
||||
</testCase>
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
|
||||
<testCase>
|
||||
<class>Create_Workspace</class>
|
||||
<desc>Create new Workspace for server 0</desc>
|
||||
<desc>Create new Workspace</desc>
|
||||
<node>starsky</node>
|
||||
</testCase>
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
|
||||
<testCase>
|
||||
<class>Create_Workspace</class>
|
||||
<desc>Create new Workspace for server 0</desc>
|
||||
<desc>Create new Workspace</desc>
|
||||
<node>starsky</node>
|
||||
</testCase>
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
|
||||
<testCase>
|
||||
<class>Create_Workspace</class>
|
||||
<desc>Create new Workspace for server 0</desc>
|
||||
<desc>Create new Workspace</desc>
|
||||
<node>starsky</node>
|
||||
</testCase>
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
|
||||
<testCase>
|
||||
<class>Create_Workspace</class>
|
||||
<desc>Create new Workspace for server 0</desc>
|
||||
<desc>Create new Workspace</desc>
|
||||
<node>gracehopper1-oai</node>
|
||||
</testCase>
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
|
||||
<testCase>
|
||||
<class>Create_Workspace</class>
|
||||
<desc>Create new Workspace for server 0</desc>
|
||||
<desc>Create new Workspace</desc>
|
||||
<node>gracehopper1-oai</node>
|
||||
</testCase>
|
||||
|
||||
|
||||
192
ci-scripts/xml_files/container_sa_b200_nrue_cuda_jetson.xml
Normal file
192
ci-scripts/xml_files/container_sa_b200_nrue_cuda_jetson.xml
Normal file
@@ -0,0 +1,192 @@
|
||||
<!-- SPDX-License-Identifier: LicenseRef-CSSL-1.0 -->
|
||||
|
||||
<testCaseList>
|
||||
<htmlTabRef>JETSON-5G-NRUE-CUDA</htmlTabRef>
|
||||
<htmlTabName>30 MHz TDD SA JETSON with CUDA</htmlTabName>
|
||||
<htmlTabIcon>tasks</htmlTabIcon>
|
||||
<testCase>
|
||||
<class>DeployCoreNetwork</class>
|
||||
<desc>Initialize 5G Core</desc>
|
||||
<cn_id>oc-cn5g-00104</cn_id>
|
||||
</testCase>
|
||||
|
||||
<testCase>
|
||||
<class>Pull_Local_Registry</class>
|
||||
<desc>Pull Images from Local Registry</desc>
|
||||
<node>jetson2-oai</node>
|
||||
<images>oai-nr-ue</images>
|
||||
<tag_prefix>armv8_cuda_</tag_prefix>
|
||||
</testCase>
|
||||
|
||||
<testCase>
|
||||
<class>Pull_Local_Registry</class>
|
||||
<desc>Pull Images from Local Registry</desc>
|
||||
<node>gracehopper1-oai</node>
|
||||
<images>oai-gnb-aerial</images>
|
||||
<tag_prefix>arm_</tag_prefix>
|
||||
</testCase>
|
||||
|
||||
<testCase>
|
||||
<class>Create_Workspace</class>
|
||||
<desc>Create new Workspace</desc>
|
||||
<node>jetson2-oai</node>
|
||||
</testCase>
|
||||
|
||||
<testCase>
|
||||
<class>Create_Workspace</class>
|
||||
<desc>Create new Workspace</desc>
|
||||
<node>gracehopper1-oai</node>
|
||||
</testCase>
|
||||
|
||||
<testCase>
|
||||
<class>Custom_Script</class>
|
||||
<desc>Configure 30 MHz bandwidth on WNC RU</desc>
|
||||
<node>gracehopper1-oai</node>
|
||||
<script>scripts/set-wnc-bandwidth.sh</script>
|
||||
<args>30</args>
|
||||
</testCase>
|
||||
|
||||
<testCase>
|
||||
<class>Deploy_Object</class>
|
||||
<desc>Deploy PNF/Nvidia CUBB in a container</desc>
|
||||
<node>gracehopper1-oai</node>
|
||||
<yaml_path>ci-scripts/yaml_files/sa_gnb_aerial_30MHz</yaml_path>
|
||||
<services>nv-cubb</services>
|
||||
</testCase>
|
||||
|
||||
<testCase>
|
||||
<class>Deploy_Object</class>
|
||||
<desc>Deploy VNF in a container</desc>
|
||||
<node>gracehopper1-oai</node>
|
||||
<yaml_path>ci-scripts/yaml_files/sa_gnb_aerial_30MHz</yaml_path>
|
||||
<services>oai-gnb-aerial</services>
|
||||
</testCase>
|
||||
|
||||
<testCase>
|
||||
<class>Deploy_Object</class>
|
||||
<desc>Deploy nrUE (TDD/Band78/40MHz/N310) in a container</desc>
|
||||
<yaml_path>ci-scripts/yaml_files/sa_b200_jetson_cuda_nrue</yaml_path>
|
||||
<node>jetson2-oai</node>
|
||||
<num_attempts>3</num_attempts>
|
||||
</testCase>
|
||||
|
||||
<testCase>
|
||||
<class>Attach_UE</class>
|
||||
<desc>Attach OAIUE</desc>
|
||||
<id>oai_ue_jetson2</id>
|
||||
</testCase>
|
||||
|
||||
<testCase>
|
||||
<class>Custom_Command</class>
|
||||
<desc>Configure IP route</desc>
|
||||
<node>jetson2-oai</node>
|
||||
<command>sudo ip route add 172.21.6.105 via 13.1.1.100 dev oaitun_ue1</command>
|
||||
</testCase>
|
||||
|
||||
<testCase>
|
||||
<class>Ping</class>
|
||||
<desc>Ping: 20pings in 20sec</desc>
|
||||
<id>oai_ue_jetson2</id>
|
||||
<svr_id>oc-cn5g-00104</svr_id>
|
||||
<ping_args>-c 20</ping_args>
|
||||
<ping_packetloss_threshold>1</ping_packetloss_threshold>
|
||||
<ping_rttavg_threshold>25</ping_rttavg_threshold>
|
||||
</testCase>
|
||||
|
||||
<testCase>
|
||||
<class>Iperf</class>
|
||||
<desc>iperf (UL/10Mbps/UDP)(30 sec)</desc>
|
||||
<iperf_args>-u -b 10M -t 30 -i 1</iperf_args>
|
||||
<id>oai_ue_jetson2</id>
|
||||
<svr_id>oc-cn5g-00104</svr_id>
|
||||
<iperf_packetloss_threshold>25</iperf_packetloss_threshold>
|
||||
<iperf_bitrate_threshold>80</iperf_bitrate_threshold>
|
||||
</testCase>
|
||||
|
||||
<testCase>
|
||||
<class>Iperf</class>
|
||||
<desc>iperf (DL/10Mbps/UDP)(30 sec)</desc>
|
||||
<iperf_args>-u -b 10M -t 30 -i 1 -R</iperf_args>
|
||||
<id>oai_ue_jetson2</id>
|
||||
<svr_id>oc-cn5g-00104</svr_id>
|
||||
<iperf_packetloss_threshold>25</iperf_packetloss_threshold>
|
||||
<iperf_bitrate_threshold>80</iperf_bitrate_threshold>
|
||||
</testCase>
|
||||
|
||||
<testCase>
|
||||
<class>Iperf</class>
|
||||
<desc>iperf (UL/30Mbps/UDP)(30 sec)</desc>
|
||||
<may_fail>true</may_fail>
|
||||
<iperf_args>-u -b 30M -t 30 -i 1</iperf_args>
|
||||
<id>oai_ue_jetson2</id>
|
||||
<svr_id>oc-cn5g-00104</svr_id>
|
||||
<iperf_packetloss_threshold>25</iperf_packetloss_threshold>
|
||||
<iperf_bitrate_threshold>80</iperf_bitrate_threshold>
|
||||
</testCase>
|
||||
|
||||
<testCase>
|
||||
<class>Iperf</class>
|
||||
<desc>iperf (DL/30Mbps/UDP)(30 sec)</desc>
|
||||
<may_fail>true</may_fail>
|
||||
<iperf_args>-u -b 30M -t 30 -i 1 -R</iperf_args>
|
||||
<id>oai_ue_jetson2</id>
|
||||
<svr_id>oc-cn5g-00104</svr_id>
|
||||
<iperf_packetloss_threshold>25</iperf_packetloss_threshold>
|
||||
<iperf_bitrate_threshold>80</iperf_bitrate_threshold>
|
||||
</testCase>
|
||||
|
||||
<testCase>
|
||||
<class>Undeploy_Object</class>
|
||||
<always_exec>true</always_exec>
|
||||
<desc>Undeploy nr UE</desc>
|
||||
<node>jetson2-oai</node>
|
||||
<yaml_path>ci-scripts/yaml_files/sa_b200_jetson_cuda_nrue</yaml_path>
|
||||
<analysis>
|
||||
<services>oai-nr-ue</services>
|
||||
</analysis>
|
||||
</testCase>
|
||||
|
||||
<testCase>
|
||||
<class>Undeploy_Object</class>
|
||||
<always_exec>true</always_exec>
|
||||
<desc>Undeploy gNB</desc>
|
||||
<node>gracehopper1-oai</node>
|
||||
<yaml_path>ci-scripts/yaml_files/sa_gnb_aerial_30MHz</yaml_path>
|
||||
<analysis>
|
||||
<services>oai-gnb-aerial=RetxCheck=20,100,100,100 oai-gnb-aerial=EndsWithBye</services>
|
||||
</analysis>
|
||||
</testCase>
|
||||
|
||||
<testCase>
|
||||
<class>Custom_Script</class>
|
||||
<always_exec>true</always_exec>
|
||||
<desc>Configure 100 MHz bandwidth on WNC RU</desc>
|
||||
<node>gracehopper1-oai</node>
|
||||
<script>scripts/set-wnc-bandwidth.sh</script>
|
||||
<args>100</args>
|
||||
</testCase>
|
||||
|
||||
<testCase>
|
||||
<class>Clean_Test_Server_Images</class>
|
||||
<always_exec>true</always_exec>
|
||||
<desc>Clean Test Images on Test Server</desc>
|
||||
<node>gracehopper1-oai</node>
|
||||
<images>oai-gnb-aerial</images>
|
||||
</testCase>
|
||||
|
||||
<testCase>
|
||||
<class>Clean_Test_Server_Images</class>
|
||||
<always_exec>true</always_exec>
|
||||
<desc>Clean Test Images on Test Server</desc>
|
||||
<node>jetson2-oai</node>
|
||||
<images>oai-nr-ue</images>
|
||||
</testCase>
|
||||
|
||||
<testCase>
|
||||
<class>UndeployCoreNetwork</class>
|
||||
<always_exec>true</always_exec>
|
||||
<desc>Terminate 5G Core</desc>
|
||||
<cn_id>oc-cn5g-00104</cn_id>
|
||||
</testCase>
|
||||
|
||||
</testCaseList>
|
||||
@@ -27,7 +27,7 @@
|
||||
|
||||
<testCase>
|
||||
<class>Create_Workspace</class>
|
||||
<desc>Create new Workspace for server 0</desc>
|
||||
<desc>Create new Workspace</desc>
|
||||
<node>ofqot</node>
|
||||
</testCase>
|
||||
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
|
||||
<testCase>
|
||||
<class>Create_Workspace</class>
|
||||
<desc>Create new Workspace for server 0</desc>
|
||||
<desc>Create new Workspace</desc>
|
||||
<node>cacofonix</node>
|
||||
</testCase>
|
||||
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
|
||||
<testCase>
|
||||
<class>Create_Workspace</class>
|
||||
<desc>Create new Workspace for server 0</desc>
|
||||
<desc>Create new Workspace</desc>
|
||||
<node>cacofonix</node>
|
||||
</testCase>
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
|
||||
<testCase>
|
||||
<class>Create_Workspace</class>
|
||||
<desc>Create new Workspace for server 0</desc>
|
||||
<desc>Create new Workspace</desc>
|
||||
<node>cacofonix</node>
|
||||
</testCase>
|
||||
|
||||
|
||||
@@ -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
|
||||
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
|
||||
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
|
||||
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
|
||||
depends_on:
|
||||
- oai-gnb
|
||||
networks:
|
||||
|
||||
@@ -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.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
|
||||
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
|
||||
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
|
||||
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
|
||||
depends_on:
|
||||
- oai-gnb
|
||||
networks:
|
||||
|
||||
@@ -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.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
|
||||
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
|
||||
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 1 --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 2 --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 2 --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 1 --ue-nb-ant-rx 2
|
||||
depends_on:
|
||||
- oai-gnb
|
||||
networks:
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
services:
|
||||
oai-nr-ue:
|
||||
image: ${REGISTRY-oaisoftwarealliance/}${NRUE_IMG:-oai-nr-ue}:${TAG:-develop}
|
||||
network_mode: host
|
||||
runtime: nvidia
|
||||
container_name: oai-nr-ue
|
||||
cap_drop:
|
||||
- ALL
|
||||
cap_add:
|
||||
- NET_ADMIN # for interface bringup
|
||||
- NET_RAW # for ping
|
||||
- SYS_NICE # for performance
|
||||
- IPC_LOCK # for memory locking
|
||||
devices:
|
||||
- /dev/net/tun:/dev/net/tun
|
||||
- /dev/bus/usb/:/dev/bus/usb/
|
||||
ulimits:
|
||||
core: -1 # for core dumps
|
||||
environment:
|
||||
TZ: Europe/Paris
|
||||
USE_B2XX: 'yes'
|
||||
USE_ADDITIONAL_OPTIONS: --usrp-args type=b200 -C 3350010000 -r 78 --numerology 1 --band 78 --ssb 345 --ue-fo-compensation --uicc0.imsi 001040000000001 --uicc0.pdu_sessions.[0].dnn oai.ipv4 --thread-pool 5,6,7,8,9 --ue-txgain 15 --ue-rxgain 90 --loader.ldpc.shlibversion _cuda -A 60
|
||||
cpuset: "3-11"
|
||||
volumes:
|
||||
- ../../conf_files/ue.sa.conf:/opt/oai-nr-ue/etc/nr-ue.conf
|
||||
healthcheck:
|
||||
test: /bin/bash -c "pgrep nr-uesoftmodem"
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
deploy:
|
||||
resources:
|
||||
reservations:
|
||||
devices:
|
||||
- driver: nvidia
|
||||
count: all
|
||||
capabilities: [gpu]
|
||||
|
||||
@@ -18,7 +18,7 @@ HWs=""
|
||||
BUILD_DIR=ran_build
|
||||
CMAKE_BUILD_TYPE="RelWithDebInfo"
|
||||
CMAKE_CMD="$CMAKE"
|
||||
OPTIONAL_LIBRARIES="telnetsrv enbscope uescope nrscope ldpc_aal websrv oai_iqplayer imscope imscope_record"
|
||||
OPTIONAL_LIBRARIES="telnetsrv enbscope uescope nrscope ldpc_aal ldpc_cuda websrv oai_iqplayer imscope imscope_record"
|
||||
TARGET_LIST=""
|
||||
BUILD_TOOL_OPT="-j$(nproc)"
|
||||
|
||||
|
||||
@@ -88,3 +88,85 @@ 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()
|
||||
|
||||
@@ -83,11 +83,13 @@ 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 ;;
|
||||
@@ -96,6 +98,7 @@ 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 ;;
|
||||
@@ -104,6 +107,7 @@ check_supported_distribution() {
|
||||
"rocky9.5") return 0 ;;
|
||||
"rocky9.6") return 0 ;;
|
||||
"rocky9.7") return 0 ;;
|
||||
"rocky9.8") return 0 ;;
|
||||
esac
|
||||
return 1
|
||||
}
|
||||
@@ -141,12 +145,8 @@ 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.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
|
||||
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
|
||||
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.0.0.0
|
||||
git apply $OPENAIR_DIR/cmake_targets/tools/uhd-4.x-tdd-patch.diff
|
||||
git checkout tags/v4.8.0.0
|
||||
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"
|
||||
fi
|
||||
# Printing out the results of the patch to make sure it was properly applied
|
||||
@@ -199,29 +199,14 @@ 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"
|
||||
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 add-apt-repository ppa:ettusresearch/uhd -y
|
||||
$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
|
||||
;;
|
||||
"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 ;;
|
||||
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"
|
||||
|
||||
34
cmake_targets/tools/uhd-4.5plus-tdd-patch.diff
Normal file
34
cmake_targets/tools/uhd-4.5plus-tdd-patch.diff
Normal file
@@ -0,0 +1,34 @@
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
# 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
|
||||
@@ -27,10 +26,5 @@
|
||||
# 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_ */
|
||||
|
||||
@@ -1454,7 +1454,7 @@ ID = UE_PHY_PDCCH_ENERGY
|
||||
ID = UE_PHY_PDSCH_IQ
|
||||
DESC = UE PDSCH received IQ data
|
||||
GROUP = ALL:PHY:GRAPHIC:HEAVY:UE
|
||||
FORMAT = int,eNB_ID : int,frame : int,subframe : int,nb_rb : int,N_RB_UL : int,symbols_per_tti : buffer,pdsch_comp
|
||||
FORMAT = int,eNB_ID : int,frame : int,subframe : int,nb_rb : int,N_RB_DL : int,symbols_per_tti : buffer,pdsch_comp
|
||||
ID = UE_PHY_PDSCH_ENERGY
|
||||
DESC = UE PDSCH 1 energy and threshold
|
||||
GROUP = ALL:PHY:GRAPHIC:HEAVY:UE
|
||||
|
||||
@@ -229,8 +229,7 @@ static void ue_main_gui(ue_gui *e, gui *g, event_handler *h, void *database,
|
||||
e->pdsch_iq_ue_xy_plot = w;
|
||||
widget_add_child(g, line, w, -1);
|
||||
xy_plot_set_range(g, w, -500, 500, -500, 500);
|
||||
l = new_iqlog(h, database, "UE_PHY_PDSCH_IQ", "nb_rb",
|
||||
"N_RB_UL", "symbols_per_tti", "pusch_comp");
|
||||
l = new_iqlog(h, database, "UE_PHY_PDSCH_IQ", "nb_rb", "N_RB_DL", "symbols_per_tti", "pdsch_comp");
|
||||
v = new_view_xy(100*12*14,10,g,w,new_color(g,"#000"),XY_FORCED_MODE);
|
||||
logger_add_view(l, v);
|
||||
e->pdsch_iq_ue_logger = l;
|
||||
|
||||
@@ -71,7 +71,9 @@ static inline const char *rnti_types(nr_rnti_type_t rr)
|
||||
#define MAX_GSCN_BAND 620 // n78 has the highest GSCN range of 619
|
||||
#define NR_SYMBOLS_PER_SLOT 14
|
||||
#define NR_SYMBOLS_PER_SLOT_EXTENDED_CP 12
|
||||
#define NR_MAX_NB_LAYERS 4 // 8
|
||||
#define NR_MAX_NB_LAYERS 4
|
||||
#define MAX_NUM_NR_DLSCH_SEGMENTS (MAX_NUM_NR_DLSCH_SEGMENTS_PER_LAYER * NR_MAX_NB_LAYERS)
|
||||
#define MAX_NUM_NR_ULSCH_SEGMENTS (MAX_NUM_NR_ULSCH_SEGMENTS_PER_LAYER * NR_MAX_NB_LAYERS)
|
||||
#define NR_MAX_CSI_PORTS 12
|
||||
|
||||
// Since the IQ samples are represented by SQ15 R+I (see https://en.wikipedia.org/wiki/Q_(number_format)) we need to compensate when
|
||||
|
||||
@@ -62,7 +62,7 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef malloc16
|
||||
# define malloc16(x) memalign(32,x+32)
|
||||
#define malloc16(x) memalign(64, x + 64)
|
||||
#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(32, size+32);
|
||||
void *ptr = memalign(64, size + 64);
|
||||
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(32,x)
|
||||
#define malloc16(x) memalign(64, x)
|
||||
#endif
|
||||
|
||||
#define free16(y,x) free(y)
|
||||
|
||||
@@ -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=3.15.0.0
|
||||
export UHD_VERSION=4.10.0.0
|
||||
./build_oai -I -w USRP
|
||||
```
|
||||
|
||||
@@ -206,6 +206,7 @@ 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
|
||||
|
||||
@@ -10,7 +10,9 @@ 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.
|
||||
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).
|
||||
|
||||
Concretely, the scheduler loops through all UEs and calculates the PF
|
||||
coefficient using the currently selected MCS, and the historical achieved rate.
|
||||
@@ -22,9 +24,13 @@ 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 `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
|
||||
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
|
||||
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
|
||||
@@ -33,11 +39,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 `pf_dl()` and
|
||||
`pf_ul()` in files
|
||||
[`gNB_scheduler_dlsch.c`](../../openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c)
|
||||
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)
|
||||
(for DL) and
|
||||
[`gNB_scheduler_ulsch.c`](../../openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c)
|
||||
[`gNB_scheduler_ulsch_default_policies.c`](../../openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch_default_policies.c)
|
||||
(for UL), respectively.
|
||||
|
||||
## PDCCH aggregation level
|
||||
@@ -120,9 +126,8 @@ 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
|
||||
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: 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: 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
|
||||
@@ -209,11 +214,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,
|
||||
|
||||
433
doc/MAC/scheduler-architecture.md
Normal file
433
doc/MAC/scheduler-architecture.md
Normal file
@@ -0,0 +1,433 @@
|
||||
# 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 2–7 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.
|
||||
417
doc/NR_SA_Tutorial_OAI_nrUE_GPU_offload.md
Normal file
417
doc/NR_SA_Tutorial_OAI_nrUE_GPU_offload.md
Normal file
@@ -0,0 +1,417 @@
|
||||
# OAI 5G NR SA tutorial with OAI nrUE with GPU Offload
|
||||
|
||||
This tutorial explains how OAI nrUE can use GPU to offload LDPC decoder. In the future we might offload more functions on the GPU.
|
||||
|
||||
**Table of Contents**
|
||||
|
||||
[[_TOC_]]
|
||||
|
||||
## Current Status
|
||||
|
||||
The nrUE GPU offload functionality have been tested on below platforms:
|
||||
|
||||
|Platform |Version | OS/Linux Kernel |
|
||||
|---------------|------------|---------------------------------------|
|
||||
|Jetson AGX Orin|L4T 36.4.7 | U22/5.15.148-tegra (64K page variant) |
|
||||
|DGX Spark |7.4.0 | U24/6.14.0-1013-nvidia-64k |
|
||||
|
||||
The above versions are tested versions, you are free to try on newer versions as well.
|
||||
|
||||
You can use another UE platform with GPU as well but it is preferred to use unified memory GPU variant.
|
||||
|
||||
### KPIs
|
||||
|
||||
The below throughput numbers are similar for TCP/UDP, the gNB was configured for 5 ms TDD pattern (6D3U and Special slot 10D0U) for Nvidia Aerial Testbed.
|
||||
|
||||
The UE was in SISO mode.
|
||||
|
||||
Testbed Architecture:
|
||||
|
||||
UE <--> Over the Air 1.5m to 2m distance <--> WNC RU <--> gNB/DU server
|
||||
|
||||
| Platform | Radio | Bandwidth | DL Throughput | UL Throughput |
|
||||
| ----------- | --------- | --------- | ------------- | ------------- |
|
||||
| Jetson Orin | B210 | 10 MHz | 12 Mbps | 7.5 Mbps |
|
||||
| Jetson Orin | B210 | 20 MHz | 20 Mbps | 9.5 Mbps |
|
||||
| Jetson Orin | B210 | 30 MHz | 61 Mbps | 33 Mbps |
|
||||
| Jetson Orin | B210 | 40 MHz | 69 Mbps | 46 Mbps |
|
||||
| DGX Spark | B210 | 40 MHz | 86 Mbps | 46 Mbps |
|
||||
| DGX Spark | N310/x410 | 100 MHz | 231 Mbps | 118 Mbps |
|
||||
|
||||
Stability or long running test with peak throughput for nrUE was performed for 5hrs.
|
||||
|
||||
All the numbers are with LDPC GPU offload.
|
||||
|
||||
`NOTE`: At the time of writing we only tested the UE in SISO.
|
||||
We are working supporting multi antenna use case.
|
||||
|
||||
## Aerial Testbed Configuration
|
||||
|
||||
If you are using aerial testbed with OAI then depending on the bandwidth you want to use, you will have to adapt the value of `ds_offset_dl` in cuphycontroller configuration file.
|
||||
|
||||
For our testing environment we adapted the `ds_offset_dl` values as below:
|
||||
|
||||
| Bandwidth | ds_offset_dl |
|
||||
| ----------- | -------------|
|
||||
| 10 MHz | 14 |
|
||||
| 20 MHz | 12 |
|
||||
| 30 MHz | 10 |
|
||||
| 40 MHz | 9 |
|
||||
| 100 MHz | 6 |
|
||||
|
||||
On the WNC radio we have the below configuration:
|
||||
|
||||
```
|
||||
transmit-power 24
|
||||
transmit-power-scale 0.0
|
||||
compress tx static bfp iq-bitwidth 9
|
||||
compress rx static bfp iq-bitwidth 9
|
||||
compress prach static bfp iq-bitwidth 9
|
||||
```
|
||||
|
||||
You can adjust the scaling on the RU or you can adjust it in aerial configuration file.
|
||||
|
||||
**NOTE**: You might have to adjust these values for your environment, so that the UE can detect the cell and perform random-access.
|
||||
|
||||
## Configure the nrUE Hardware Platform
|
||||
|
||||
### Configure Jetson AGX Orin
|
||||
|
||||
At the time of writing this tutorial AGX Orin only had Jetpack 6.X release which has U22/5.15.148-tegra, for GPU offload on ARM systems it is preferred to use 64K page size kernel.
|
||||
|
||||
To change the kernel to 64K page size variant you will have to manually build the kernel. Probably for Jetpack 7.X it will be easier. Before building the kernel make sure AGX Orin has the up to date kernel for your current distribution.
|
||||
|
||||
NVIDIA-SMI Version: 540.4.0
|
||||
CUDA Version: 12.6
|
||||
CPU: Cortex-A78AE (12)
|
||||
OS: U22
|
||||
Kernel: 5.15.148-tegra
|
||||
NVCC: Build cuda_12.6.r12.6/compiler.34714021_0
|
||||
UHD: UHD_4.9.0.HEAD-0-g006d7f76 (v4.9.0.0)
|
||||
|
||||
#### Update kernel to 64K page size
|
||||
|
||||
Login to Jetson AGX Orin
|
||||
|
||||
```bash
|
||||
sudo apt update
|
||||
sudo apt upgrade
|
||||
# reboot
|
||||
```
|
||||
|
||||
**CAUTION**: While building the kernel if you make a mistake you have to flash again the Jetson. We are just providing these steps to help you build the kernel with 64K page size. If you have questions or issues building the kernel you can check the [official nvidia documentation](https://docs.nvidia.com/jetson/archives/r36.4.4/DeveloperGuide/SD/Kernel/KernelCustomization.html#sd-kernel-kernelcustomization)
|
||||
|
||||
prepare the kernel source code:
|
||||
|
||||
```bash
|
||||
sudo apt install git-core build-essential bc
|
||||
cd ~/
|
||||
wget https://developer.nvidia.com/downloads/embedded/l4t/r36_release_v4.4/sources/public_sources.tbz2
|
||||
# Build Jetson Linux Kernel
|
||||
tar -xf public_sources.tbz2
|
||||
cd ~/Linux_for_Tegra/source
|
||||
tar -xf kernel_src.tbz2
|
||||
tar -xf kernel_oot_modules_src.tbz2
|
||||
tar -xf nvidia_kernel_display_driver_source.tbz2
|
||||
```
|
||||
|
||||
the default kernel configuration file used is `kernel/kernel-jammy-src/arch/arm64/configs/defconfig` it is mentioned in `kernel_src_build_env.sh`.
|
||||
Add `CONFIG_ARM64_64K_PAGES=y` in `kernel/kernel-jammy-src/arch/arm64/configs/defconfig`.
|
||||
|
||||
Build the kernel, out-of-tree modules and dtbs:
|
||||
|
||||
```bash
|
||||
make -C kernel
|
||||
sudo -E make install -C kernel
|
||||
cp kernel/kernel-jammy-src/arch/arm64/boot/Image
|
||||
/boot/Image
|
||||
# Building the NVIDIA Out-of-Tree Modules
|
||||
cd ~/Linux_for_Tegra/source
|
||||
make modules
|
||||
sudo -E make modules_install
|
||||
sudo nv-update-initrd
|
||||
make dtbs
|
||||
cp kernel-devicetree/generic-dts/dtbs/* /boot/dtbs/
|
||||
```
|
||||
|
||||
#### Configure operating system
|
||||
|
||||
```bash
|
||||
jetson_clocks
|
||||
touch /etc/sysctl.d/rt.conf
|
||||
## add below content using vim/vi/nano
|
||||
kernel.sched_rt_runtime_us=-1
|
||||
kernel.timer_migration=0
|
||||
sudo cpufreq-set -c 0 -g performance
|
||||
sudo cpufreq-set -c 5 -g performance
|
||||
sudo cpufreq-set -c 9 -g performance
|
||||
```
|
||||
|
||||
### Configure DGX Spark
|
||||
|
||||
To setup DGX spark you would need to follow the below steps
|
||||
|
||||
NVIDIA-SMI Version: 580.95.05
|
||||
CUDA Version: 13.0
|
||||
OS: Ubuntu 24
|
||||
Kernel: 6.14.0-1013-nvidia-64k (You can use a higher version)
|
||||
NVCC: Build cuda_13.0.r13.0/compiler.36424714_0
|
||||
UHD: UHD_4.9.0.HEAD-0-g006d7f76 (v4.9.0.0)
|
||||
Efficient cores (Cortex-A725): 0,1,2,3,4,10,11,12,13,14
|
||||
Performance cores (Cortex-X925): 5,6,7,8,9,15,16,17,18,19
|
||||
|
||||
You can use `sudo cpupower -c 0-19 frequency-info` to check the above core distribution.
|
||||
|
||||
|
||||
```bash
|
||||
sudo apt update
|
||||
sudo apt upgrade
|
||||
#reboot
|
||||
sudo /etc/apt/apt.conf.d/20auto-upgrades
|
||||
APT::Periodic::Update-Package-Lists "0";
|
||||
APT::Periodic::Unattended-Upgrade "0";
|
||||
# Install 64K kernel corresponding to your running kernel
|
||||
sudo apt install linux-image-6.14.0-1013-nvidia-64k
|
||||
# You can also fix the kernel so it is not changed with apt upgrade
|
||||
sudo sed -i 's/^GRUB_DEFAULT=.*/GRUB_DEFAULT="Advanced options for DGX OS
|
||||
GNU\/Linux>DGX OS GNU\/Linux, with Linux 6.14.0-1013-nvidia-64k"/'
|
||||
/etc/default/grub
|
||||
#Configure the command line to isolate the cores
|
||||
cat <<"EOF" | sudo tee /etc/default/grub.d/cmdline.cfg
|
||||
GRUB_CMDLINE_LINUX="$GRUB_CMDLINE_LINUX pci=realloc=off pci=pcie_bus_safe
|
||||
default_hugepagesz=512M hugepagesz=512M hugepages=24 tsc=reliable
|
||||
processor.max_cstate=0 audit=0 idle=poll rcu_nocb_poll nosoftlockup
|
||||
irqaffinity=0-3 isolcpus=managed_irq,domain,4-19
|
||||
nohz_full=4-19 rcu_nocbs=4-19 earlycon module_blacklist=nouveau
|
||||
acpi_power_meter.force_cap_on=y numa_balancing=disable init_on_alloc=0
|
||||
preempt=none ras=off iommu=off mitgations=off kpti=off skew_tick=1 nowatchdog
|
||||
mce=ignore_ce transparent_hugepage=never"
|
||||
EOF
|
||||
touch /etc/sysctl.d/rt.conf
|
||||
## add below content using vim/vi/nano
|
||||
kernel.sched_rt_runtime_us=-1
|
||||
kernel.timer_migration=0
|
||||
sudo update-grub
|
||||
sudo reboot
|
||||
# after reboot you can make a script to set the gpu clock speed to maximum
|
||||
nvidia-smi -lgc 2000
|
||||
sudo cpupower frequency-set --governor performance
|
||||
sudo cpupower idle-set -D 0
|
||||
```
|
||||
|
||||
### Configuration for Ethernet based USRP
|
||||
|
||||
If you want to use Ethernet based USRP like N3XX/X3XX/X4XX you would need to run the below commands:
|
||||
|
||||
```bash
|
||||
sudo sysctl -w net.core.wmem_max=62500000
|
||||
sudo sysctl -w net.core.rmem_max=62500000
|
||||
sudo sysctl -w net.core.wmem_default=62500000
|
||||
sudo sysctl -w net.core.rmem_default=62500000
|
||||
sudo ethtool -G <usrp-interface> tx <maximum-value> rx <maximum-value>
|
||||
```
|
||||
|
||||
*NOTE*: Currently we finalizing container images for OAI-NR-UE with GPU offload, we will provide it soon for container based deployments.
|
||||
|
||||
## Using nrUE with B2XX
|
||||
|
||||
### Build OAI-nrUE
|
||||
|
||||
```bash
|
||||
mkdir ~/oai-nr-ue
|
||||
git clone https://gitlab.eurecom.fr/oai/openairinterface5g.git ~/oai-nr-ue
|
||||
cd ~/oai-nr-ue
|
||||
git checkout ldpc_offload_cuda
|
||||
cd ~/oai-nr-ue/openairinterface5g/cmake_targets
|
||||
#Install third-party dependencies
|
||||
./build_oai -I -w USRP
|
||||
# Install nrue with USRP support, default nvcc location is /usr/local/bin/nvcc
|
||||
./build_oai --ninja --build-lib ldpc_cuda --gNB --nrUE -w USRP -C --cmake-opt -DCMAKE_CUDA_COMPILER=<nvcc-location>
|
||||
```
|
||||
|
||||
## Start the nrUE process
|
||||
|
||||
Create a UE configuration file based on the PLMN, slicing information, DNN and DNN type you have configured for the UE in the core network.
|
||||
|
||||
```bash
|
||||
cd ~/oai-nr-ue/
|
||||
# touch nr-ue.conf
|
||||
```
|
||||
|
||||
Sample UE configuration file, you can use the below configuration file and adjust the values as per your testing environment:
|
||||
|
||||
```bash
|
||||
cat nr-ue.conf
|
||||
|
||||
uicc0 = {
|
||||
imsi = "001010000000001";
|
||||
key = "fec86ba6eb707ed08905757b1bb44b8f";
|
||||
opc= "C42449363BBAD02B66D16BC975D77CC1";
|
||||
pdu_sessions = ({ dnn = "oai"; nssai_sst = 1; });
|
||||
}
|
||||
```
|
||||
|
||||
To start the `nr-uesoftmodem` you would need to know the center frequency, bandwidth, band and ssb. This information is printed in the OAI-gNB logs. You can search for the line `[NR_MAC] Command line parameters for OAI UE` for example:
|
||||
|
||||
```bash
|
||||
[NR_MAC] Command line parameters for OAI UE: -C 3350010000 -r 106 --numerology 1 --band 78 --ssb 513
|
||||
```
|
||||
|
||||
Once you have this information you can start the `nr-uesoftmodem` process:
|
||||
|
||||
**Command for Jetson AGX Orin**:
|
||||
|
||||
**MANDATORY**: Before starting the UE process it is important to configure the gNB configuration file with `min_rxtxtime` as 6 or higher integer value.
|
||||
|
||||
```bash
|
||||
cd ~/oai-nr-ue/openairinterface5g/cmake_targets/
|
||||
sudo ./nr-uesoftmodem -O ~/oai-nr-ue/nr-ue.conf -C 3350010000 -r 106 --ssb 513 --numerology 1 --band 78 --thread-pool -1 --num-dl-actors 6 --num-ul-actors 2 -E --loader.ldpc.shlibversion _cuda --usrp-tx-thread-config 1 --ue-fo-compensation
|
||||
```
|
||||
|
||||
**Command for DGX Spark**:
|
||||
|
||||
**MANDATORY**: Before starting the UE process it is important to configure the gNB configuration file with `min_rxtxtime` as 6 or higher integer value.
|
||||
|
||||
```bash
|
||||
cd ~/oai-nr-ue/openairinterface5g/cmake_targets/
|
||||
|
||||
sudo taskset -c "5-9,15-19" ./nr-uesoftmodem -O ~/oai-nr-ue/nr-ue.conf -C 3350010000 -r 106 --ssb 513 --numerology 1 --band 78 --thread-pool -1 -E --loader.ldpc.shlibversion _cuda --ue-fo-compensation
|
||||
```
|
||||
|
||||
In the above command task-set allows running the UE only on the performance cores.
|
||||
|
||||
Understand the command which you just used:
|
||||
|
||||
The main RF/cell settings are:
|
||||
|
||||
- `-O`: load the UE config file.
|
||||
- `-C 3900000000`: set DL carrier to 3.9 GHz.
|
||||
- `-r 106`: use 106 PRBs
|
||||
- `--numerology 1`: numerology 1, meaning 30 kHz subcarrier spacing.
|
||||
- `--band 77`: NR band n77.
|
||||
- `--ssb 516`: expect the SSB to start at sub-carrier 516.
|
||||
- `--ue-fo-compensation`: enable initial frequency-offset compensation, useful OTA when clocks are not perfectly aligned.
|
||||
- `--usrp-tx-thread-config 1`: enable an extra USRP TX processing thread
|
||||
- `-E`: enable threequarter_fs, meaning the UE uses three-quarter sampling rate mode. In OAI this reduces sample rate / transport load where supported.
|
||||
|
||||
The parallelism/offload settings are:
|
||||
|
||||
- `--thread-pool -1`: create a thread-pool worker with no CPU affinity.
|
||||
- `--num-dl-actors 6`: use 6 DL actor threads, parallel RX/PDSCH processing workers.
|
||||
- `--num-ul-actors 2`: use 2 UL actor threads, parallel TX/PUSCH/PUCCH preparation and transmit workers.
|
||||
- `--loader.ldpc.shlibversion_cuda`: load the CUDA-backed LDPC shared library variant.
|
||||
|
||||
When the UE starts it starts with highest gains, but sometimes you would need to adjust the tx/rx gains based on the UEs position from the RU/gNB. To manipulate the gains you can use the below options:
|
||||
|
||||
- `--ue-rxgain x`: set UE RX gain.
|
||||
- `--ue-txgain x`: set UE TX gain.
|
||||
- `-A 50`: apply a command-line sample advance of 50 samples to compensate RF timing offset.
|
||||
|
||||
Once the UE connects you will see the tunnel interface `oaitun_ue1` with ip-address in the subnet which is configured at SMF. You can open another terminal and from there you can do traffic test.
|
||||
|
||||
## Using nrUE with X3XX/N3XX/x4XX
|
||||
|
||||
### Build OAI-nrUE
|
||||
|
||||
For Ethernet based USRPs it is recommended to use DPDK mostly when you want to test for 60-100 MHz bandwidth. If you don't want to use DPDK then you can build the `nr-uesoftmodem` using the previous section.
|
||||
|
||||
```bash
|
||||
mkdir ~/oai-nr-ue
|
||||
git clone https://gitlab.eurecom.fr/oai/openairinterface5g.git ~/oai-nr-ue
|
||||
cd ~/oai-nr-ue
|
||||
git checkout ldpc_offload_cuda
|
||||
cd ~/oai-nr-ue/openairinterface5g/cmake_targets
|
||||
#Install third-party dependencies
|
||||
./build_oai -I
|
||||
#Build and Install DPDK
|
||||
cd ~/
|
||||
wget https://fast.dpdk.org/rel/dpdk-24.11.4.tar.xz
|
||||
sudo apt install wget xz-utils libnuma-dev meson libibverbs-dev rdma-core python3-pyelftools
|
||||
meson setup build -Dplatform=generic
|
||||
ninja -C build
|
||||
sudo ninja install -C build
|
||||
#Build and Install UHD
|
||||
sudo apt install autoconf automake build-essential ccache cmake cpufrequtils doxygen ethtool g++ git inetutils-tools libboost-all-dev libncurses-dev libusb-1.0-0 libusb-1.0-0-dev libusb-dev python3-dev python3-mako python3-numpy python3-requests python3-scipy python3-setuptools python3-ruamel.yaml
|
||||
git clone https://github.com/EttusResearch/uhd ~/uhd && cd uhd
|
||||
git checkout v4.9.0.0
|
||||
cd host && mkdir build && cd build
|
||||
cmake ../ -GNinja
|
||||
ninja
|
||||
sudo ninja install
|
||||
# Install nrue with USRP support, default nvcc location is /usr/local/bin/nvcc
|
||||
./build_oai --ninja --build-lib ldpc_cuda --gNB --nrUE -w USRP -C --cmake-opt -DCMAKE_CUDA_COMPILER=<nvcc-location>
|
||||
```
|
||||
|
||||
Create the DPDK interfaces for the UHD, use the below script and modify it for your environment. We are using VLAN 80 for DPDK in our environment:
|
||||
|
||||
```bash
|
||||
vim setup_sriov_usrp.sh
|
||||
```
|
||||
|
||||
```bash
|
||||
#!/bin/sh
|
||||
set -xeu
|
||||
|
||||
pci_addr()
|
||||
{
|
||||
PF_IF=$1
|
||||
VF_INDEX=$2
|
||||
SYSFS_PATH="/sys/class/net/${PF_IF}/device/virtfn${VF_INDEX}"
|
||||
|
||||
if [ ! -e "$SYSFS_PATH" ]; then
|
||||
echo "VF $VF_INDEX not found for interface $PF_IF"
|
||||
exit 1
|
||||
fi
|
||||
PCI_ADDR=$(basename "$(readlink "$SYSFS_PATH")")
|
||||
echo "$PCI_ADDR"
|
||||
}
|
||||
IF_NAME=enP2p1s0f1np1 ## interface to reach to the USRP on the UHD host
|
||||
HOST_MAC_ADD=00:11:22:33:44:67
|
||||
VLAN=80
|
||||
MTU=9000
|
||||
NUM_VFs=1
|
||||
sudo ethtool -G $IF_NAME rx 8160 tx 8160
|
||||
sudo sh -c "echo 0 > /sys/class/net/$IF_NAME/device/sriov_numvfs"
|
||||
sudo sh -c "echo $NUM_VFs > /sys/class/net/$IF_NAME/device/sriov_numvfs"
|
||||
HOST_PCI_ADDR=$(pci_addr $IF_NAME 0)
|
||||
# this next 2 lines is for C/U planes
|
||||
sudo ip link set $IF_NAME vf 0 mac $HOST_MAC_ADD vlan $VLAN spoofchk off mtu $MTU
|
||||
sleep 1
|
||||
sudo dpdk-devbind.py --unbind $HOST_PCI_ADDR
|
||||
sudo modprobe mlx5_core
|
||||
sudo dpdk-devbind.py --bind mlx5_core $HOST_PCI_ADDR
|
||||
echo "Successfully configured interface for USRP:
|
||||
- Mac-address: $HOST_MAC_ADD, VLAN: $VLAN, PCI: $HOST_PCI_ADDR"
|
||||
exit 0
|
||||
```
|
||||
|
||||
Create `/etc/uhd/uhd.conf` configuration file for allowing UHD to use dpdk for reaching to the USRP:
|
||||
|
||||
```txt
|
||||
[use_dpdk=1]
|
||||
dpdk_mtu=9000
|
||||
dpdk_driver=/usr/local/lib/aarch64-linux-gnu/dpdk/pmds-25.0/
|
||||
dpdk_corelist=5,6,7,8,9
|
||||
[dpdk_mac=00:11:22:33:44:67]
|
||||
dpdk_lcore=6
|
||||
dpdk_ipv4=192.168.80.25/24
|
||||
```
|
||||
|
||||
The ip-address 192.168.80.25/24 is the UHD host ip-address. Make sure you adjust the `dpdk_driver` location.
|
||||
|
||||
|
||||
### Start the nrUE process
|
||||
|
||||
Create a UE configuration file based on the PLMN, slicing information, DNN and DNN type you have configured for the UE in the core network. It is similar to previous section.
|
||||
|
||||
To start the `nr-uesoftmodem` process:
|
||||
|
||||
**Command for DGX Spark**:
|
||||
|
||||
```bash
|
||||
sudo devlink dev reload pci/<HOST_PCI_ADDR> && sudo taskset -c "5-19" ./nr-uesoftmodem --ue-fo-compensation --thread-pool 15,16,17,18,19 --loader.ldpc.shlibversion _cuda -O ~/oai-nr-ue/nr-ue.conf --usrp-args "addr=192.168.80.251,use_dpdk=1" -C 3350010000 -r 273 --numerology 1 --band 78 --ssb 1515 --usrp-tx-thread-config 1
|
||||
```
|
||||
|
||||
DPDK deployment have some issues currently and we need to reload the pci interface before every run. The devlink command `sudo devlink dev reload pci/<HOST_PCI_ADDR>` is doing that.
|
||||
|
||||
If you need to adjust the tx/rx gains then you will need to take the parameters from previous section.
|
||||
@@ -169,7 +169,6 @@ generate DL shared channel (user data)
|
||||
|
||||
#### nr_feptx_prec()
|
||||
tx precoding
|
||||
<<<<<<< HEAD:doc/SW_archi.md
|
||||
|
||||
#### nr_feptx0
|
||||
do the inverse DFT
|
||||
|
||||
76
docker/Dockerfile.base.cuda.ubuntu
Normal file
76
docker/Dockerfile.base.cuda.ubuntu
Normal file
@@ -0,0 +1,76 @@
|
||||
# SPDX-License-Identifier: LicenseRef-CSSL-1.0
|
||||
|
||||
#---------------------------------------------------------------------
|
||||
#
|
||||
# Dockerfile for the Open-Air-Interface BUILD service
|
||||
# Valid for Ubuntu 24.04
|
||||
#
|
||||
#---------------------------------------------------------------------
|
||||
|
||||
|
||||
FROM nvidia/cuda:12.2.0-devel-ubuntu22.04 AS ran-base-cuda
|
||||
|
||||
ARG NEEDED_GIT_PROXY
|
||||
ARG TARGETARCH
|
||||
ENV DEBIAN_FRONTEND=noninteractive
|
||||
ENV TZ=Europe/Paris
|
||||
ENV BUILD_UHD_FROM_SOURCE=True
|
||||
ENV UHD_VERSION=4.8.0.0
|
||||
|
||||
#install developers pkg/repo
|
||||
RUN apt-get update && \
|
||||
apt-get upgrade --yes && \
|
||||
apt-get install --yes \
|
||||
#gcc needed for build_oai
|
||||
build-essential \
|
||||
ccache \
|
||||
psmisc \
|
||||
git \
|
||||
#use gcc-12 to avoid problems of default gcc-11 in FlexRIC
|
||||
gcc-12 \
|
||||
g++-12 \
|
||||
xxd \
|
||||
libpcre2-dev \
|
||||
python3-dev \
|
||||
bison \
|
||||
flex \
|
||||
m4 \
|
||||
# python3-pip for conf template generation
|
||||
python3-pip \
|
||||
wget \
|
||||
flatbuffers-compiler \
|
||||
libflatbuffers-dev \
|
||||
libnanomsg-dev && \
|
||||
update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-12 100 --slave /usr/bin/g++ g++ /usr/bin/g++-12 && \
|
||||
pip3 install --ignore-installed pyyaml
|
||||
|
||||
# Add "Tini - A tiny but valid init for containers", https://github.com/krallin/tini
|
||||
# it will be copied into target containers, to print exit numbers and handle signals properly
|
||||
ENV TINI_VERSION=v0.19.0
|
||||
RUN wget https://github.com/krallin/tini/releases/download/${TINI_VERSION}/tini-${TARGETARCH} -O /tini && chmod +x /tini
|
||||
|
||||
ENV YQ_VERSION=v4.2.0
|
||||
RUN wget https://github.com/mikefarah/yq/releases/download/${YQ_VERSION}/yq_linux_${TARGETARCH} -O /usr/local/bin/yq &&\
|
||||
chmod +x /usr/local/bin/yq
|
||||
|
||||
# In some network environments, GIT proxy is required
|
||||
RUN /bin/bash -c "if [[ -v NEEDED_GIT_PROXY ]]; then git config --global http.proxy $NEEDED_GIT_PROXY; fi"
|
||||
|
||||
# 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.x-tdd-patch.diff \
|
||||
./
|
||||
|
||||
WORKDIR /oai-ran/cmake_targets
|
||||
COPY cmake_targets/build_oai .
|
||||
|
||||
WORKDIR /oai-ran
|
||||
COPY oaienv .
|
||||
|
||||
#run build_oai -I to get the builder image
|
||||
RUN /bin/sh oaienv && \
|
||||
cd cmake_targets && \
|
||||
mkdir -p log && \
|
||||
./build_oai -I -w USRP -w BLADERF --install-optional-packages
|
||||
|
||||
@@ -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.x-tdd-patch.diff \
|
||||
cmake_targets/tools/uhd-4.5plus-tdd-patch.diff \
|
||||
./
|
||||
|
||||
WORKDIR /oai-ran/cmake_targets
|
||||
|
||||
@@ -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.x-tdd-patch.diff \
|
||||
cmake_targets/tools/uhd-4.5plus-tdd-patch.diff \
|
||||
./
|
||||
|
||||
WORKDIR /oai-ran/cmake_targets
|
||||
|
||||
@@ -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.x-tdd-patch.diff \
|
||||
cmake_targets/tools/uhd-4.5plus-tdd-patch.diff \
|
||||
./
|
||||
|
||||
WORKDIR /oai-ran/cmake_targets
|
||||
|
||||
@@ -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.x-tdd-patch.diff \
|
||||
cmake_targets/tools/uhd-4.5plus-tdd-patch.diff \
|
||||
./
|
||||
|
||||
WORKDIR /oai-ran/cmake_targets
|
||||
|
||||
58
docker/Dockerfile.build.cuda.ubuntu
Normal file
58
docker/Dockerfile.build.cuda.ubuntu
Normal file
@@ -0,0 +1,58 @@
|
||||
# SPDX-License-Identifier: LicenseRef-CSSL-1.0
|
||||
|
||||
#---------------------------------------------------------------------
|
||||
#
|
||||
# Dockerfile for the Open-Air-Interface BUILD service
|
||||
# Valid for Ubuntu 24.04
|
||||
#
|
||||
#---------------------------------------------------------------------
|
||||
|
||||
FROM ran-base-cuda:latest AS ran-build-cuda
|
||||
ARG BUILD_OPTION
|
||||
|
||||
ARG E2AP_VERSION=E2AP_V3
|
||||
ARG KPM_VERSION=KPM_V3_00
|
||||
|
||||
RUN rm -Rf /oai-ran
|
||||
WORKDIR /oai-ran
|
||||
COPY . .
|
||||
|
||||
# build all targets so final targets can be created afterwards
|
||||
RUN \
|
||||
# Mount CCache cache direrctory
|
||||
--mount=type=cache,target=/root/.cache/ccache/ \
|
||||
# Mount CPM package cache
|
||||
--mount=type=cache,target=/root/.cache/cpm/ \
|
||||
/bin/sh oaienv && \
|
||||
cd cmake_targets && \
|
||||
mkdir -p log && \
|
||||
./build_oai -c --ninja \
|
||||
--eNB --gNB --RU --UE --nrUE \
|
||||
--build-lib "telnetsrv enbscope uescope nrscope ldpc_cuda" \
|
||||
-w USRP -t Ethernet -w BLADERF \
|
||||
--build-e2 --cmake-opt -DKPM_VERSION=$KPM_VERSION --cmake-opt -DE2AP_VERSION=$E2AP_VERSION \
|
||||
--cmake-opt -DOAI_VRTSIM_TAPS_CLIENT=ON \
|
||||
--cmake-opt -DCUDA_TOOLKIT_ROOT_DIR=/usr/local/cuda-12.2 \
|
||||
--noavx512 \
|
||||
--build-tool-opt -k10 \
|
||||
--cmake-opt -DCMAKE_C_FLAGS="-Werror" --cmake-opt -DCMAKE_CXX_FLAGS="-Werror" $BUILD_OPTION && \
|
||||
# Mainly to see if the sanitize option was perfectly executed
|
||||
echo "---- ldd on executables ----" && \
|
||||
ldd ran_build/build/*softmodem* ran_build/build/nr-cuup ran_build/build/oairu && \
|
||||
echo "---- ldd on shared libraries ----" && \
|
||||
ldd ran_build/build/*.so
|
||||
|
||||
## Build FlexRIC for SM Models
|
||||
RUN \
|
||||
# Mount CCache cache direrctory
|
||||
--mount=type=cache,target=/root/.cache/ccache/ \
|
||||
mkdir -p openair2/E2AP/flexric/build && \
|
||||
cd openair2/E2AP/flexric/build && \
|
||||
cmake -GNinja -DCMAKE_BUILD_TYPE=Release \
|
||||
-DKPM_VERSION=$KPM_VERSION \
|
||||
-DCMAKE_C_COMPILER=gcc-12 \
|
||||
-DCMAKE_CXX_COMPILER=g++-12 .. \
|
||||
-DE2AP_VERSION=$E2AP_VERSION .. && \
|
||||
ninja && \
|
||||
ninja install
|
||||
|
||||
115
docker/Dockerfile.gNB.cuda.ubuntu
Normal file
115
docker/Dockerfile.gNB.cuda.ubuntu
Normal file
@@ -0,0 +1,115 @@
|
||||
# SPDX-License-Identifier: LicenseRef-CSSL-1.0
|
||||
|
||||
#---------------------------------------------------------------------
|
||||
#
|
||||
# Dockerfile for the Open-Air-Interface BUILD service
|
||||
# Valid for Ubuntu 24.04
|
||||
#
|
||||
#---------------------------------------------------------------------
|
||||
|
||||
ARG UBUNTU_IMAGE=ubuntu:noble
|
||||
FROM ran-base-cuda:latest AS gnb-base
|
||||
FROM ran-build-cuda:latest AS gnb-build
|
||||
|
||||
|
||||
#start from scratch for target executable
|
||||
FROM nvidia/cuda:12.2.0-runtime-ubuntu22.04 AS oai-gnb
|
||||
ARG BUILD_OPTION
|
||||
ENV DEBIAN_FRONTEND=noninteractive
|
||||
ENV TZ=Europe/Paris
|
||||
|
||||
RUN apt-get update && \
|
||||
apt-get upgrade --yes && \
|
||||
apt-get install --yes \
|
||||
software-properties-common \
|
||||
procps \
|
||||
libsctp1 \
|
||||
libboost-chrono1.74.0 \
|
||||
libboost-date-time1.74.0 \
|
||||
libboost-filesystem1.74.0 \
|
||||
libboost-regex1.74.0 \
|
||||
libboost-serialization1.74.0 \
|
||||
libboost-thread1.74.0 \
|
||||
libboost-system1.74.0 \
|
||||
libboost-program-options1.74.0 \
|
||||
tzdata \
|
||||
libconfig9 \
|
||||
openssl \
|
||||
net-tools \
|
||||
iperf \
|
||||
iperf3 \
|
||||
iproute2 \
|
||||
iputils-ping \
|
||||
gdb \
|
||||
python3 \
|
||||
python3-six \
|
||||
python3-requests \
|
||||
libusb-1.0-0 \
|
||||
libyaml-cpp-dev \
|
||||
libnanomsg5 && \
|
||||
# if the --sanitize option was used to build, additional packages are required
|
||||
/bin/bash -c 'if [[ "$BUILD_OPTION" = "--sanitize" ]]; then DEBIAN_FRONTEND=noninteractive apt-get install --yes \
|
||||
libasan8 \
|
||||
libubsan1; fi' && \
|
||||
apt-get clean -y && \
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
|
||||
WORKDIR /opt/oai-gnb/bin
|
||||
COPY --from=gnb-build \
|
||||
/oai-ran/cmake_targets/ran_build/build/nr-softmodem ./
|
||||
COPY ./docker/scripts/gnb_entrypoint.sh ./entrypoint.sh
|
||||
COPY ./docker/scripts/check-prach-io.sh ./check-prach-io.sh
|
||||
|
||||
COPY --from=gnb-build \
|
||||
/oai-ran/cmake_targets/ran_build/build/liboai_eth_transpro.so \
|
||||
/oai-ran/cmake_targets/ran_build/build/librfsimulator.so \
|
||||
/oai-ran/cmake_targets/ran_build/build/liboai_usrpdevif.so \
|
||||
/oai-ran/cmake_targets/ran_build/build/libcoding.so \
|
||||
/oai-ran/cmake_targets/ran_build/build/libparams_libconfig.so \
|
||||
/oai-ran/cmake_targets/ran_build/build/libdfts.so \
|
||||
/oai-ran/cmake_targets/ran_build/build/libldpc*.so \
|
||||
/oai-ran/cmake_targets/ran_build/build/libtelnetsrv.so \
|
||||
/oai-ran/cmake_targets/ran_build/build/libtelnetsrv_ci.so \
|
||||
/oai-ran/cmake_targets/ran_build/build/libparams_yaml.so \
|
||||
/oai-ran/cmake_targets/ran_build/build/libtelnetsrv_bearer.so \
|
||||
/oai-ran/cmake_targets/ran_build/build/libtelnetsrv_5Gue.so \
|
||||
/oai-ran/cmake_targets/ran_build/build/libtelnetsrv_rrc.so \
|
||||
/oai-ran/cmake_targets/ran_build/build/libtelnetsrv_o1.so \
|
||||
/oai-ran/cmake_targets/ran_build/build/libvrtsim.so \
|
||||
/usr/local/lib/
|
||||
|
||||
# Now we are copying from builder-image the UHD files.
|
||||
COPY --from=gnb-base /usr/local/bin/uhd_find_devices /usr/local/bin
|
||||
COPY --from=gnb-base /usr/local/lib/libuhd.so.4.8.0 /usr/local/lib
|
||||
COPY --from=gnb-base /usr/local/lib/uhd/utils/uhd_images_downloader.py /opt/oai-gnb/bin
|
||||
## Copy E2 SM models
|
||||
COPY --from=gnb-build /usr/local/lib/flexric /usr/local/lib/flexric
|
||||
|
||||
RUN /bin/bash -c "ln -s /usr/local/lib/liboai_usrpdevif.so /usr/local/lib/liboai_device.so" && \
|
||||
ldconfig && \
|
||||
echo "---- ldd on nr-softmodem ----" && \
|
||||
ldd /opt/oai-gnb/bin/nr-softmodem && \
|
||||
echo "---- ldd on shared libraries ----" && \
|
||||
ldd /usr/local/lib/liboai_eth_transpro.so \
|
||||
/usr/local/lib/librfsimulator.so \
|
||||
/usr/local/lib/liboai_usrpdevif.so \
|
||||
/usr/local/lib/libcoding.so \
|
||||
/usr/local/lib/libparams_libconfig.so \
|
||||
/usr/local/lib/libdfts.so \
|
||||
/usr/local/lib/libldpc*.so \
|
||||
/usr/local/lib/libtelnetsrv.so \
|
||||
/usr/local/lib/libtelnetsrv_ci.so \
|
||||
/usr/local/lib/libuhd.so.4.8.0
|
||||
|
||||
WORKDIR /opt/oai-gnb
|
||||
#EXPOSE 2152/udp # S1U, GTP/UDP
|
||||
#EXPOSE 22100/tcp # ?
|
||||
#EXPOSE 36412/udp # S1C, SCTP/UDP
|
||||
#EXPOSE 36422/udp # X2C, SCTP/UDP
|
||||
#EXPOSE 50000/udp # IF5 / ORI (control)
|
||||
#EXPOSE 50001/udp # IF5 / ECPRI (data)
|
||||
|
||||
COPY --from=gnb-base /usr/local/bin/yq /usr/local/bin/yq
|
||||
COPY --from=gnb-base /tini /tini
|
||||
ENTRYPOINT ["/tini", "-v", "--", "/opt/oai-gnb/bin/entrypoint.sh"]
|
||||
CMD ["/opt/oai-gnb/bin/nr-softmodem"]
|
||||
107
docker/Dockerfile.nrUE.cuda.ubuntu
Normal file
107
docker/Dockerfile.nrUE.cuda.ubuntu
Normal file
@@ -0,0 +1,107 @@
|
||||
# SPDX-License-Identifier: LicenseRef-CSSL-1.0
|
||||
|
||||
#---------------------------------------------------------------------
|
||||
#
|
||||
# Dockerfile for the Open-Air-Interface BUILD service
|
||||
# Valid for Ubuntu 24.04
|
||||
#
|
||||
#---------------------------------------------------------------------
|
||||
|
||||
FROM ran-base-cuda:latest AS nr-ue-base
|
||||
FROM ran-build-cuda:latest AS nr-ue-build
|
||||
|
||||
#start from scratch for target executable
|
||||
FROM nvidia/cuda:12.2.0-runtime-ubuntu22.04 AS oai-nr-ue
|
||||
ARG BUILD_OPTION
|
||||
ENV DEBIAN_FRONTEND=noninteractive
|
||||
ENV TZ=Europe/Paris
|
||||
|
||||
RUN apt-get update && \
|
||||
apt-get upgrade --yes && \
|
||||
apt-get install --yes \
|
||||
arping \
|
||||
software-properties-common \
|
||||
procps \
|
||||
libsctp1 \
|
||||
libboost-chrono1.74.0 \
|
||||
libboost-date-time1.74.0 \
|
||||
libboost-filesystem1.74.0 \
|
||||
libboost-regex1.74.0 \
|
||||
libboost-serialization1.74.0 \
|
||||
libboost-thread1.74.0 \
|
||||
libboost-system1.74.0 \
|
||||
libboost-program-options1.74.0 \
|
||||
tzdata \
|
||||
libconfig9 \
|
||||
openssl \
|
||||
net-tools \
|
||||
gdb \
|
||||
python3 \
|
||||
python3-six \
|
||||
python3-requests \
|
||||
libusb-1.0-0 \
|
||||
iputils-ping \
|
||||
iproute2 \
|
||||
iperf3 \
|
||||
iperf \
|
||||
libyaml-cpp-dev \
|
||||
libnanomsg5 && \
|
||||
# if the --sanitize option was used to build, additional packages are required
|
||||
/bin/bash -c 'if [[ "$BUILD_OPTION" = "--sanitize" ]]; then DEBIAN_FRONTEND=noninteractive apt-get install --yes \
|
||||
libasan8 \
|
||||
libubsan1; fi' && \
|
||||
apt-get clean -y && \
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
|
||||
WORKDIR /opt/oai-nr-ue/bin
|
||||
COPY --from=nr-ue-build \
|
||||
/oai-ran/cmake_targets/ran_build/build/nr-uesoftmodem \
|
||||
./
|
||||
|
||||
COPY ./docker/scripts/nr_ue_entrypoint.sh ./entrypoint.sh
|
||||
WORKDIR /opt/oai-nr-ue/etc
|
||||
|
||||
COPY --from=nr-ue-build \
|
||||
/oai-ran/cmake_targets/ran_build/build/liboai_eth_transpro.so \
|
||||
/oai-ran/cmake_targets/ran_build/build/librfsimulator.so \
|
||||
/oai-ran/cmake_targets/ran_build/build/liboai_usrpdevif.so \
|
||||
/oai-ran/cmake_targets/ran_build/build/libcoding.so \
|
||||
/oai-ran/cmake_targets/ran_build/build/libparams_libconfig.so \
|
||||
/oai-ran/cmake_targets/ran_build/build/libdfts.so \
|
||||
/oai-ran/cmake_targets/ran_build/build/libldpc*.so \
|
||||
/oai-ran/cmake_targets/ran_build/build/libtelnetsrv.so \
|
||||
/oai-ran/cmake_targets/ran_build/build/libtelnetsrv_ciUE.so \
|
||||
/oai-ran/cmake_targets/ran_build/build/libtelnetsrv_5Gue.so \
|
||||
/oai-ran/cmake_targets/ran_build/build/libparams_yaml.so \
|
||||
/oai-ran/cmake_targets/ran_build/build/libvrtsim.so \
|
||||
/usr/local/lib/
|
||||
|
||||
# Now we are copying from builder-image the UHD files.
|
||||
COPY --from=nr-ue-base /usr/local/bin/uhd_find_devices /usr/local/bin
|
||||
COPY --from=nr-ue-base /usr/local/lib/libuhd.so.4.8.0 /usr/local/lib
|
||||
COPY --from=nr-ue-base /usr/local/lib/uhd/utils/uhd_images_downloader.py /opt/oai-nr-ue/bin
|
||||
|
||||
RUN /bin/bash -c "ln -s /usr/local/lib/liboai_usrpdevif.so /usr/local/lib/liboai_device.so" && \
|
||||
ldconfig && \
|
||||
echo "---- ldd on nr-uesoftmodem ----" && \
|
||||
ldd /opt/oai-nr-ue/bin/nr-uesoftmodem && \
|
||||
echo "---- ldd on shared libraries ----" && \
|
||||
ldd /usr/local/lib/liboai_eth_transpro.so \
|
||||
/usr/local/lib/librfsimulator.so \
|
||||
/usr/local/lib/liboai_usrpdevif.so \
|
||||
/usr/local/lib/libcoding.so \
|
||||
/usr/local/lib/libparams_libconfig.so \
|
||||
/usr/local/lib/libdfts.so \
|
||||
/usr/local/lib/libldpc*.so \
|
||||
/usr/local/lib/libtelnetsrv.so \
|
||||
/usr/local/lib/libtelnetsrv_ciUE.so \
|
||||
/usr/local/lib/libtelnetsrv_5Gue.so \
|
||||
/usr/local/lib/libuhd.so.4.8.0
|
||||
|
||||
WORKDIR /opt/oai-nr-ue
|
||||
|
||||
COPY --from=nr-ue-base /usr/local/bin/yq /usr/local/bin/yq
|
||||
COPY --from=nr-ue-base /tini /tini
|
||||
CMD ["/opt/oai-nr-ue/bin/nr-uesoftmodem"]
|
||||
ENTRYPOINT ["/tini", "-v", "--", "/opt/oai-nr-ue/bin/entrypoint.sh"]
|
||||
|
||||
@@ -70,6 +70,7 @@ unsigned short config_frames[4] = {2,9,11,13};
|
||||
#include "openair1/SCHED_NR/sched_nr.h"
|
||||
#include "openair2/SDAP/nr_sdap/nr_sdap.h"
|
||||
|
||||
RAN_CONTEXT_t RC;
|
||||
pthread_cond_t nfapi_sync_cond;
|
||||
pthread_mutex_t nfapi_sync_mutex;
|
||||
int nfapi_sync_var=-1; //!< protected by mutex \ref nfapi_sync_mutex
|
||||
|
||||
@@ -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[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;
|
||||
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;
|
||||
tx_wait_for_dlsch[ack_nack_slot]++;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -256,7 +256,7 @@ int main(int argc, char **argv)
|
||||
|
||||
init_opt();
|
||||
|
||||
int ret_loader = load_nrLDPC_coding_interface(NULL, &nrLDPC_coding_interface);
|
||||
int ret_loader = load_nrLDPC_coding_interface(NULL, &nrLDPC_coding_interface, 32);
|
||||
AssertFatal(ret_loader == 0, "error loading LDPC library\n");
|
||||
|
||||
// strdup to put the sring in the core file for post mortem identification
|
||||
|
||||
@@ -118,6 +118,7 @@ typedef struct {
|
||||
|
||||
typedef struct {
|
||||
uint8_t harq_pid;
|
||||
uint8_t cw_idx;
|
||||
uint8_t ack_nack;
|
||||
uint32_t pdu_length;
|
||||
uint8_t* pdu;
|
||||
@@ -466,6 +467,17 @@ 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;
|
||||
@@ -482,15 +494,8 @@ typedef struct {
|
||||
uint8_t prb_bundling_size_ind;
|
||||
uint8_t rate_matching_ind;
|
||||
uint8_t zp_csi_rs_trigger;
|
||||
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 n_codewords;
|
||||
fapi_nr_dl_cw_info_t cw_info[2];
|
||||
uint8_t harq_process_nbr;
|
||||
vrb_to_prb_mapping_t vrb_to_prb_mapping;
|
||||
uint8_t dai;
|
||||
@@ -523,7 +528,6 @@ 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;
|
||||
|
||||
@@ -16,6 +16,9 @@
|
||||
#include "openair1/PHY/defs_nr_common.h"
|
||||
#include "coding_unitary_defs.h"
|
||||
#include "common/utils/LOG/log.h"
|
||||
#ifdef LDPC_CUDA
|
||||
#include <cuda_runtime.h>
|
||||
#endif
|
||||
|
||||
#define MAX_BLOCK_LENGTH 8448
|
||||
|
||||
@@ -24,7 +27,14 @@
|
||||
#endif
|
||||
|
||||
#define NR_LDPC_PROFILER_DETAIL
|
||||
#define NR_LDPC_ENABLE_PARITY_CHECK
|
||||
|
||||
ldpc_interface_t ldpc_orig, ldpc_toCompare;
|
||||
static double modulated_input[MAX_NUM_NR_DLSCH_SEGMENTS_PER_LAYER * 4][68 * 384];
|
||||
#define MAX_TRIALS 20000
|
||||
static int8_t Failure_Mask[MAX_TRIALS][(MAX_NUM_NR_DLSCH_SEGMENTS_PER_LAYER * 4)] = {0};
|
||||
|
||||
int PARALLEL_PATH = 0;//control decoder path
|
||||
|
||||
// 4-bit quantizer
|
||||
int8_t quantize4bit(double D, double x)
|
||||
@@ -78,6 +88,9 @@ typedef struct {
|
||||
n_iter_stats_t dec_iter;
|
||||
} one_measurement_t;
|
||||
|
||||
uint8_t *estimated_output_dev,*estimated_output;
|
||||
int8_t *channel_output_fixed_dev,*channel_output_fixed;
|
||||
|
||||
one_measurement_t test_ldpc(short max_iterations,
|
||||
int nom_rate,
|
||||
int denom_rate,
|
||||
@@ -85,14 +98,16 @@ one_measurement_t test_ldpc(short max_iterations,
|
||||
unsigned char qbits,
|
||||
short Kprime,
|
||||
unsigned int ntrials,
|
||||
int n_segments)
|
||||
int n_segments,
|
||||
int gen_code)
|
||||
{
|
||||
static int init_done = 0;
|
||||
one_measurement_t ret = {0};
|
||||
reset_meas(&ret.time_optim);
|
||||
reset_meas(&ret.time_decoder);
|
||||
// clock initiate
|
||||
// time_stats_t time,time_optim,tinput,tprep,tparity,toutput, time_decoder;
|
||||
time_stats_t time, tinput, tprep, tparity, toutput;
|
||||
time_stats_t time, tinput, tinput_memcpy, tprep, tparity, toutput;
|
||||
double n_iter_mean = 0;
|
||||
double n_iter_std = 0;
|
||||
int n_iter_max = 0;
|
||||
@@ -100,14 +115,17 @@ one_measurement_t test_ldpc(short max_iterations,
|
||||
double sigma;
|
||||
sigma = 1.0 / sqrt(2 * SNR);
|
||||
cpu_meas_enabled = 1;
|
||||
uint8_t *test_input[MAX_NUM_NR_DLSCH_SEGMENTS_PER_LAYER * NR_MAX_NB_LAYERS];
|
||||
uint8_t estimated_output[MAX_NUM_DLSCH_SEGMENTS][Kprime];
|
||||
memset(estimated_output, 0, sizeof(estimated_output));
|
||||
uint8_t *channel_input[MAX_NUM_DLSCH_SEGMENTS];
|
||||
#ifdef LDPC_CUDA
|
||||
uint8_t **test_input,*test_input_p;
|
||||
#else
|
||||
uint8_t *test_input[n_segments * NR_MAX_NB_LAYERS];
|
||||
#endif
|
||||
uint8_t *channel_input[n_segments];
|
||||
uint8_t *channel_input_optim;
|
||||
|
||||
// double channel_output[68 * 384];
|
||||
double modulated_input[MAX_NUM_DLSCH_SEGMENTS][68 * 384] = {0};
|
||||
int8_t channel_output_fixed[MAX_NUM_DLSCH_SEGMENTS][68 * 384] = {0};
|
||||
|
||||
memset(modulated_input,0,sizeof(modulated_input));
|
||||
short BG = 0, nrows = 0; //,ncols;
|
||||
int i1, Kb = 0;
|
||||
int R_ind = 0;
|
||||
@@ -115,7 +133,8 @@ one_measurement_t test_ldpc(short max_iterations,
|
||||
int code_rate_vec[8] = {15, 13, 25, 12, 23, 34, 56, 89};
|
||||
// double code_rate_actual_vec[8] = {0.2, 0.33333, 0.4, 0.5, 0.66667, 0.73333, 0.81481, 0.88};
|
||||
|
||||
t_nrLDPC_dec_params decParams[MAX_NUM_DLSCH_SEGMENTS] = {0};
|
||||
t_nrLDPC_dec_params decParams[n_segments];
|
||||
memset(decParams,0,sizeof(decParams));
|
||||
|
||||
t_nrLDPC_time_stats decoder_profiler = {0};
|
||||
|
||||
@@ -123,6 +142,7 @@ one_measurement_t test_ldpc(short max_iterations,
|
||||
|
||||
reset_meas(&time);
|
||||
reset_meas(&tinput);
|
||||
reset_meas(&tinput_memcpy);
|
||||
reset_meas(&tprep);
|
||||
reset_meas(&tparity);
|
||||
reset_meas(&toutput);
|
||||
@@ -240,18 +260,26 @@ one_measurement_t test_ldpc(short max_iterations,
|
||||
printf("To: %d\n", (Kb + nrows - no_punctured_columns) * Zc - removed_bit);
|
||||
printf("number of undecoded bits: %d\n", (Kb + nrows - no_punctured_columns - 2) * Zc - removed_bit);
|
||||
|
||||
// ldpc_toCompare.LDPCinit();
|
||||
// generate input block
|
||||
for (int j = 0; j < MAX_NUM_DLSCH_SEGMENTS; j++) {
|
||||
#ifdef LDPC_CUDA
|
||||
cudaHostAlloc((void**)&test_input_p,n_segments*sizeof(uint8_t*),cudaHostAllocMapped);
|
||||
test_input=(uint8_t **)test_input_p;
|
||||
#endif
|
||||
for (int j = 0; j < n_segments; j++) {
|
||||
#ifdef LDPC_CUDA
|
||||
cudaHostAlloc((void**)&test_input[j],((K + 7) & ~7) / 8,cudaHostAllocMapped);
|
||||
#else
|
||||
test_input[j] = malloc16(((K + 7) & ~7) / 8);
|
||||
memset(test_input[j], 0, ((K + 7) & ~7) / 8);
|
||||
#endif
|
||||
channel_input[j] = malloc16(68 * 384);
|
||||
memset(channel_input[j], 0, 68 * 384);
|
||||
}
|
||||
channel_input_optim = malloc16(68 * 384);
|
||||
memset(channel_input_optim, 0, 68 * 384);
|
||||
channel_input_optim = malloc16(68 * 384 * sizeof(uint32_t));
|
||||
|
||||
// Fill input segments with random values
|
||||
for (int j = 0; j < MAX_NUM_DLSCH_SEGMENTS; j++) {
|
||||
for (int j = 0; j < n_segments; j++) {
|
||||
int i = 0;
|
||||
for (i = 0; i < ((Kprime + 7) & ~7) / 8; i++)
|
||||
test_input[j][i] = (uint8_t)rand();
|
||||
@@ -263,13 +291,21 @@ one_measurement_t test_ldpc(short max_iterations,
|
||||
}
|
||||
|
||||
encoder_implemparams_t impp = {.Zc = Zc, .Kb = Kb, .BG = BG, .K = K};
|
||||
impp.gen_code = 1;
|
||||
|
||||
impp.gen_code = gen_code;
|
||||
impp.tparity = &tparity;
|
||||
impp.tinput = &tinput;
|
||||
impp.tinput_memcpy = &tinput_memcpy;
|
||||
impp.toutput = &toutput;
|
||||
if (ntrials == 0)
|
||||
ldpc_orig.LDPCencoder(test_input, channel_input[0], &impp);
|
||||
impp.gen_code = 0;
|
||||
decode_abort_t dec_abort;
|
||||
init_abort(&dec_abort);
|
||||
|
||||
if (init_done == 0) {
|
||||
ldpc_toCompare.LDPCinit();
|
||||
init_done = 1;
|
||||
}
|
||||
for (int trial = 0; trial < ntrials; trial++) {
|
||||
unsigned int segment_bler = 0;
|
||||
//// encoder
|
||||
@@ -280,37 +316,41 @@ one_measurement_t test_ldpc(short max_iterations,
|
||||
stop_meas(&time);
|
||||
|
||||
impp.n_segments = n_segments;
|
||||
|
||||
start_meas(&ret.time_optim);
|
||||
impp.first_seg = 0;
|
||||
ldpc_toCompare.LDPCencoder(test_input, channel_input_optim, &impp);
|
||||
|
||||
stop_meas(&ret.time_optim);
|
||||
|
||||
if (ntrials == 1)
|
||||
for (int j = 0; j < n_segments; j++)
|
||||
for (int i = 0; i < K + (nrows - no_punctured_columns) * Zc - removed_bit; i++) {
|
||||
if (channel_input[j][i] != ((channel_input_optim[i] >> j) & 0x1)) {
|
||||
printf("differ in seg %d pos %d (%u,%u)\n", j, i, channel_input[j][i], (channel_input_optim[i] >> j) & 0x1);
|
||||
return ret;
|
||||
}
|
||||
if (((channel_input[j][i] != ((channel_input_optim[i] >> j) & 0x1)))) {
|
||||
printf("differ in seg %d pos %d (%u,%u)\n", j, i, channel_input[j][i], (((uint32_t*)channel_input_optim)[i] >> j) & 0x1);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int bit=0;
|
||||
for (int j = 0; j < n_segments; j++) {
|
||||
for (int i = 2 * Zc; i < (Kb + nrows - no_punctured_columns) * Zc - removed_bit; i++) {
|
||||
#ifdef DEBUG_CODER
|
||||
if ((i & 0xf) == 0)
|
||||
printf("\ne %d..%d: ", i, i + 15);
|
||||
#endif
|
||||
bit = ((channel_input_optim[i - 2 * Zc] >> j) & 0x1);
|
||||
|
||||
if (((channel_input_optim[i - 2 * Zc] >> j) & 0x1) == 0)
|
||||
if (bit == 0)
|
||||
modulated_input[j][i] = 1.0; /// sqrt(2); //QPSK
|
||||
else
|
||||
modulated_input[j][i] = -1.0; /// sqrt(2);
|
||||
|
||||
channel_output_fixed[j][i] =
|
||||
channel_output_fixed[j*(384*68) + i] =
|
||||
(int8_t)quantize(sigma / 4.0 / 4.0, modulated_input[j][i] + sigma * gaussdouble(0.0, 1.0), qbits);
|
||||
|
||||
// Uncoded BER
|
||||
uint8_t channel_output_uncoded = channel_output_fixed[j][i] < 0 ? 1 /* QPSK demod */ : 0;
|
||||
uint8_t channel_output_uncoded = channel_output_fixed[(j*384*68)+i] < 0 ? 1 /* QPSK demod */ : 0;
|
||||
if (channel_output_uncoded != ((channel_input_optim[i - 2 * Zc] >> j) & 0x1))
|
||||
ret.errors_bit_uncoded++;
|
||||
}
|
||||
@@ -326,25 +366,36 @@ one_measurement_t test_ldpc(short max_iterations,
|
||||
decParams[j].numMaxIter = max_iterations;
|
||||
decParams[j].outMode = nrLDPC_outMode_BIT;
|
||||
decParams[j].Kprime = Kprime;
|
||||
ldpc_toCompare.LDPCinit();
|
||||
decParams[j].n_segments = n_segments;
|
||||
//decParams[j].LastTrial = (trial == ntrials - 1) ? 1 : 0;
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
//Decoder
|
||||
for (int j = 0; j < n_segments; j++) {
|
||||
start_meas(&ret.time_decoder);
|
||||
set_abort(&dec_abort, false);
|
||||
|
||||
n_iter = ldpc_toCompare.LDPCdecoder(&decParams[j],
|
||||
(int8_t *)channel_output_fixed[j],
|
||||
(int8_t *)estimated_output[j],
|
||||
&decoder_profiler,
|
||||
&dec_abort);
|
||||
{
|
||||
n_iter = ldpc_toCompare.LDPCdecoder(&decParams[j],
|
||||
&channel_output_fixed[j*384*68],
|
||||
&estimated_output[j*Kprime],
|
||||
&decoder_profiler,
|
||||
&dec_abort);
|
||||
}
|
||||
stop_meas(&ret.time_decoder);
|
||||
|
||||
// count errors
|
||||
if (memcmp(estimated_output[j], test_input[j], ((Kprime + 7) & ~7) / 8) != 0) {
|
||||
if (memcmp(&estimated_output[j*(Kprime>>3)], test_input[j], ((Kprime + 7) & ~7) / 8) != 0) {
|
||||
segment_bler++;
|
||||
if(trial < 200){
|
||||
Failure_Mask[trial][j] = 1;
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < Kprime; i++) {
|
||||
unsigned char estoutputbit = (estimated_output[j][i / 8] & (1 << (i & 7))) >> (i & 7);
|
||||
unsigned char estoutputbit = (estimated_output[j*(Kprime>>3) + (i / 8)] & (1 << (i & 7))) >> (i & 7);
|
||||
unsigned char inputbit = (test_input[j][i / 8] & (1 << (i & 7))) >> (i & 7); // Further correct for multiple segments
|
||||
if (estoutputbit != inputbit)
|
||||
ret.errors_bit++;
|
||||
@@ -367,17 +418,30 @@ one_measurement_t test_ldpc(short max_iterations,
|
||||
sqrt(n_iter_std / (double)ntrials / (double)n_segments - pow(n_iter_mean / (double)ntrials / (double)n_segments - 1, 2));
|
||||
ret.dec_iter.n_iter_max = n_iter_max - 1;
|
||||
|
||||
ret.dec_iter.n_iter_mean = n_iter_mean / (double)ntrials / (double)n_segments - 1;
|
||||
ret.dec_iter.n_iter_std =
|
||||
sqrt(n_iter_std / (double)ntrials / (double)n_segments - pow(n_iter_mean / (double)ntrials / (double)n_segments - 1, 2));
|
||||
ret.dec_iter.n_iter_max = n_iter_max - 1;
|
||||
|
||||
ret.errors_bit_uncoded = ret.errors_bit_uncoded / (double)((Kb + nrows - no_punctured_columns - 2) * Zc - removed_bit);
|
||||
|
||||
for (int j = 0; j < MAX_NUM_DLSCH_SEGMENTS; j++) {
|
||||
for (int j = 0; j < n_segments; j++) {
|
||||
#ifdef LDPC_CUDA
|
||||
cudaFreeHost(test_input[j]);
|
||||
#else
|
||||
free(test_input[j]);
|
||||
#endif
|
||||
free(channel_input[j]);
|
||||
}
|
||||
#ifdef LDPC_CUDA
|
||||
cudaFreeHost(test_input);
|
||||
#endif
|
||||
free(channel_input_optim);
|
||||
|
||||
print_meas(&time, "ldpc_encoder", NULL, NULL);
|
||||
print_meas(&ret.time_optim, "ldpc_encoder_optim", NULL, NULL);
|
||||
print_meas(&tinput, "ldpc_encoder_optim(input)", NULL, NULL);
|
||||
print_meas(&tinput_memcpy, "ldpc_encoder_optim(input memcpy)", NULL, NULL);
|
||||
print_meas(&tprep, "ldpc_encoder_optim(prep)", NULL, NULL);
|
||||
print_meas(&tparity, "ldpc_encoder_optim(parity)", NULL, NULL);
|
||||
print_meas(&toutput, "ldpc_encoder_optim(output)", NULL, NULL);
|
||||
@@ -399,6 +463,9 @@ one_measurement_t test_ldpc(short max_iterations,
|
||||
}
|
||||
|
||||
configmodule_interface_t *uniqCfg = NULL;
|
||||
#ifdef LDPC_CUDA
|
||||
extern int pageable,integrated;
|
||||
#endif
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
short Kprime = 8448;
|
||||
@@ -418,19 +485,18 @@ int main(int argc, char *argv[])
|
||||
|
||||
int n_trials = 1;
|
||||
double SNR_step = 0.1;
|
||||
|
||||
int gen_code = 1;
|
||||
randominit();
|
||||
int test_uncoded = 0;
|
||||
n_iter_stats_t dec_iter[400] = {0};
|
||||
|
||||
short BG = 0, Zc;
|
||||
|
||||
if ((uniqCfg = load_configmodule(argc, argv, CONFIG_ENABLECMDLINEONLY)) == 0) {
|
||||
exit_fun("[LDPCTEST] Error, configuration module init failed\n");
|
||||
}
|
||||
logInit();
|
||||
|
||||
while ((c = getopt(argc, argv, "--:O:q:r:s:S:l:G:n:d:i:t:u:hv:")) != -1) {
|
||||
while ((c = getopt(argc, argv, "--:O:q:r:s:S:l:Gn:d:i:t:u:hv:g:Pn:")) != -1) {
|
||||
/* ignore long options starting with '--', option '-O' and their arguments that are handled by configmodule */
|
||||
/* with this opstring getopt returns 1 for non-option arguments, refer to 'man 3 getopt' */
|
||||
if (c == 1 || c == '-' || c == 'O')
|
||||
@@ -454,12 +520,9 @@ int main(int argc, char *argv[])
|
||||
Kprime = atoi(optarg);
|
||||
break;
|
||||
|
||||
case 'G':
|
||||
ldpc_version = "_cuda";
|
||||
break;
|
||||
|
||||
case 'n':
|
||||
n_trials = atoi(optarg);
|
||||
AssertFatal(n_trials < MAX_TRIALS, "max trials %d, please increase MAX_TRIALS\n", MAX_TRIALS);
|
||||
break;
|
||||
|
||||
case 's':
|
||||
@@ -484,6 +547,11 @@ int main(int argc, char *argv[])
|
||||
case 'v':
|
||||
ldpc_version = strdup(optarg);
|
||||
break;
|
||||
case 'g':
|
||||
gen_code = atoi(optarg);
|
||||
AssertFatal(gen_code <= 4, "gen_code %d is not allowed\n", gen_code);
|
||||
n_trials = 0;
|
||||
break;
|
||||
case 'h':
|
||||
default:
|
||||
printf("CURRENTLY SUPPORTED CODE RATES: \n");
|
||||
@@ -494,7 +562,7 @@ int main(int argc, char *argv[])
|
||||
printf("-r Nominator rate, (1, 2, 22), Default: 1\n");
|
||||
printf("-d Denominator rate, (3, 5, 25), Default: 1\n");
|
||||
printf("-l Length of payload bits in a segment (K' in 38.212-5.2.2), [1, 8448], Default: 8448\n");
|
||||
printf("-G give 1 to run cuda for LDPC, Default: 0\n");
|
||||
printf("-P give 1 to run cuda stream parallel for LDPC, Default: 0\n");
|
||||
printf("-n Number of simulation trials, Default: 1\n");
|
||||
// printf("-M MCS2 for TB 2\n");
|
||||
printf("-s SNR per information bit (EbNo) in dB, Default: -2\n");
|
||||
@@ -511,11 +579,29 @@ int main(int argc, char *argv[])
|
||||
printf("n_trials %d: \n", n_trials);
|
||||
printf("SNR0 %f: \n", SNR0);
|
||||
|
||||
printf("loading %s\n",ldpc_version);
|
||||
load_LDPClib(ldpc_version, &ldpc_toCompare);
|
||||
load_LDPClib("_orig", &ldpc_orig);
|
||||
|
||||
// find minimum value in all sets of lifting size
|
||||
Zc = 0;
|
||||
#ifdef LDPC_CUDA
|
||||
cudaError_t err = cudaHostAlloc((void**)&estimated_output,sizeof(uint8_t)* n_segments * Kprime,cudaHostAllocMapped);
|
||||
if (err != cudaSuccess) {
|
||||
printf("[DEBUG] CUDA Error String: %s\n", cudaGetErrorString(err));
|
||||
}
|
||||
AssertFatal(err==cudaSuccess,"estimated_output n_segments %d Kprime %d\n",n_segments,Kprime);
|
||||
err = cudaHostAlloc((void**)&channel_output_fixed,sizeof(int8_t)* n_segments * 68 * 384,cudaHostAllocMapped);
|
||||
AssertFatal(err==cudaSuccess,"channel_output_fixed n_segments %d\n",n_segments);
|
||||
err = cudaHostGetDevicePointer((void**)&estimated_output_dev,estimated_output,0);
|
||||
AssertFatal(err==cudaSuccess,"estimated_output_dev\n");
|
||||
err = cudaHostGetDevicePointer((void**)&channel_output_fixed_dev,channel_output_fixed,0);
|
||||
AssertFatal(err==cudaSuccess,"channel_output_fixed_dev\n");
|
||||
printf("estimated_output_dev %p, channel_output_fixed_dev %p\n",estimated_output_dev,channel_output_fixed_dev);
|
||||
#else
|
||||
estimated_output = malloc(n_segments * Kprime);
|
||||
channel_output_fixed=malloc(n_segments * 68 * 384);
|
||||
#endif
|
||||
|
||||
char fname[200];
|
||||
sprintf(fname, "ldpctest_BG_%d_Zc_%d_rate_%d-%d_Kprime_%d_maxit_%d.txt", BG, Zc, nom_rate, denom_rate, Kprime, max_iterations);
|
||||
@@ -532,7 +618,7 @@ int main(int argc, char *argv[])
|
||||
SNR_lin = pow(10, SNR / 10.0);
|
||||
else
|
||||
SNR_lin = pow(10, SNR / 10.0) * nom_rate / denom_rate;
|
||||
printf("Linear SNR: %f\n", SNR_lin);
|
||||
printf("Linear SNR: %d %f, %d/%d, Kprime %d\n", max_iterations, SNR_lin, nom_rate,denom_rate,Kprime);
|
||||
one_measurement_t res = test_ldpc(max_iterations,
|
||||
nom_rate,
|
||||
denom_rate,
|
||||
@@ -540,13 +626,31 @@ int main(int argc, char *argv[])
|
||||
qbits,
|
||||
Kprime, // block length bytes
|
||||
n_trials,
|
||||
n_segments);
|
||||
n_segments,
|
||||
gen_code);
|
||||
|
||||
decoded_errors[i] = res.errors;
|
||||
dec_iter[i] = res.dec_iter;
|
||||
dec_iter[i].snr = SNR;
|
||||
dec_iter[i].ber = (float)res.errors_bit / (float)n_trials / (float)Kprime / (double)n_segments;
|
||||
dec_iter[i].bler = (float)decoded_errors[i] / (float)n_trials;
|
||||
printf("Failure Mask = ");
|
||||
for(int i=0; i<n_trials;i++){
|
||||
int flag = 0;
|
||||
for(int j = 0; j < n_segments; j++){
|
||||
if(Failure_Mask[i][j] == 1){
|
||||
if(flag == 0){
|
||||
printf(" %d: ", i);
|
||||
flag = 1;
|
||||
}
|
||||
printf(" %d ", j);
|
||||
Failure_Mask[i][j] = 0;
|
||||
}
|
||||
}
|
||||
if(flag == 1) printf(",");
|
||||
}
|
||||
printf("\n");
|
||||
|
||||
printf("SNR %f, BLER %f (%u/%d)\n", SNR, dec_iter[i].bler, decoded_errors[i], n_trials);
|
||||
printf("SNR %f, BER %f (%u/%d)\n", SNR, dec_iter[i].ber, decoded_errors[i], n_trials);
|
||||
printf("SNR %f, Uncoded BER %f (%u/%d)\n",
|
||||
@@ -560,7 +664,9 @@ int main(int argc, char *argv[])
|
||||
printf("\n");
|
||||
|
||||
double cpu_freq = get_cpu_freq_GHz();
|
||||
printf("CPU Freq %f\n",cpu_freq);
|
||||
time_stats_t *t_optim = &res.time_optim;
|
||||
|
||||
printf("Encoding time mean: %15.3f us\n", (double)t_optim->diff / t_optim->trials / 1000.0 / cpu_freq);
|
||||
printf("Encoding time std: %15.3f us\n",
|
||||
sqrt((double)t_optim->diff_square / t_optim->trials / pow(1000, 2) / pow(cpu_freq, 2)
|
||||
@@ -569,12 +675,12 @@ int main(int argc, char *argv[])
|
||||
printf("\n");
|
||||
|
||||
time_stats_t *t_decoder = &res.time_decoder;
|
||||
printf("Decoding time mean: %15.3f us\n", (double)t_decoder->diff / t_decoder->trials / 1000.0 / cpu_freq);
|
||||
printf("Decoding time mean (per segment)");
|
||||
printf(": %15.3f us\n", (double)t_decoder->diff / t_decoder->trials / 1000.0 / cpu_freq);
|
||||
printf("Decoding time std: %15.3f us\n",
|
||||
sqrt((double)t_decoder->diff_square / t_decoder->trials / pow(1000, 2) / pow(cpu_freq, 2)
|
||||
- pow((double)t_decoder->diff / t_decoder->trials / 1000.0 / cpu_freq, 2)));
|
||||
printf("Decoding time max: %15.3f us\n", (double)t_decoder->max / 1000.0 / cpu_freq);
|
||||
|
||||
fprintf(fd,
|
||||
"%f %f %f %f %f %f %f %f %f %f %f %f %d \n",
|
||||
SNR,
|
||||
|
||||
@@ -2,3 +2,7 @@
|
||||
|
||||
add_subdirectory(nrLDPC_coding_segment)
|
||||
add_subdirectory(nrLDPC_coding_aal)
|
||||
add_boolean_option(ENABLE_LDPC_CUDA OFF "Build support for CUDA" OFF)
|
||||
if (ENABLE_LDPC_CUDA)
|
||||
add_subdirectory(nrLDPC_coding_cuda)
|
||||
endif()
|
||||
|
||||
@@ -458,8 +458,9 @@ 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) {
|
||||
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;
|
||||
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;
|
||||
char *data;
|
||||
struct rte_mbuf *m_head = rte_pktmbuf_alloc(mbuf_pool);
|
||||
AssertFatal(m_head != NULL,
|
||||
@@ -602,20 +603,19 @@ 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) {
|
||||
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;
|
||||
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;
|
||||
ops[j]->ldpc_dec.op_flags = RTE_BBDEV_LDPC_ITERATION_STOP_ENABLE | RTE_BBDEV_LDPC_HQ_COMBINE_OUT_ENABLE;
|
||||
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 (p->d_to_be_cleared) {
|
||||
if (active_dev.is_t2)
|
||||
*nrLDPC_slot_decoding_parameters->TBs[h].processedSegments = 0;
|
||||
*p->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)
|
||||
*nrLDPC_slot_decoding_parameters->TBs[h].processedSegments = 0;
|
||||
*p->processedSegments = 0;
|
||||
|
||||
if (!special_case_tb_mode) {
|
||||
ops[j]->ldpc_dec.code_block_mode = 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.cb_params.e = i < p->first_rE2 ? p->E : p->E2;
|
||||
if (p->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 = 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;
|
||||
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;
|
||||
}
|
||||
// Calculate offset in the HARQ combined buffers
|
||||
// Unique segment offset
|
||||
uint32_t segment_offset = (nrLDPC_slot_decoding_parameters->TBs[h].harq_unique_pid * NR_LDPC_MAX_NUM_CB) + i;
|
||||
uint32_t segment_offset = (p->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,6 +673,7 @@ 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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -729,14 +730,16 @@ 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) {
|
||||
for (int i = 0; i < nrLDPC_slot_decoding_parameters->TBs[h].C; ++i) {
|
||||
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) {
|
||||
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(nrLDPC_slot_decoding_parameters->TBs[h].segments[i].c, data, data_len);
|
||||
memcpy(p->c + data_off, data, data_len);
|
||||
|
||||
uint32_t segment_offset = (nrLDPC_slot_decoding_parameters->TBs[h].harq_unique_pid * NR_LDPC_MAX_NUM_CB) + i;
|
||||
uint32_t segment_offset = (p->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) {
|
||||
@@ -749,6 +752,7 @@ 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;
|
||||
@@ -823,7 +827,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].segments[0].ts_ldpc_decode);
|
||||
start_meas(&nrLDPC_slot_decoding_parameters->TBs[0].ts_ldpc_decode);
|
||||
|
||||
uint16_t enq = 0, deq = 0;
|
||||
while (enq < num_segments) {
|
||||
@@ -840,7 +844,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].segments[0].ts_ldpc_decode);
|
||||
stop_meas(&nrLDPC_slot_decoding_parameters->TBs[0].ts_ldpc_decode);
|
||||
|
||||
if (deq == enq) {
|
||||
ret = retrieve_ldpc_dec_op(ops_deq, nrLDPC_slot_decoding_parameters);
|
||||
@@ -849,24 +853,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) {
|
||||
for (int i = 0; i < nrLDPC_slot_decoding_parameters->TBs[h].C; ++i) {
|
||||
bool *status = &nrLDPC_slot_decoding_parameters->TBs[h].segments[i].decodeSuccess;
|
||||
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];
|
||||
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 (nrLDPC_slot_decoding_parameters->TBs[h].C > 1) {
|
||||
if (p->C > 1) {
|
||||
*status = (ops_enq[j]->status == 0);
|
||||
} else {
|
||||
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);
|
||||
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);
|
||||
*status = check_crc(decoded_bytes, len_with_crc, crc_type);
|
||||
}
|
||||
|
||||
if (*status) {
|
||||
*nrLDPC_slot_decoding_parameters->TBs[h].processedSegments =
|
||||
*nrLDPC_slot_decoding_parameters->TBs[h].processedSegments + 1;
|
||||
*p->processedSegments = *p->processedSegments + 1;
|
||||
}
|
||||
++j;
|
||||
}
|
||||
@@ -1057,7 +1061,7 @@ static int normalize_dpdk_dev(const char *input, char *output, size_t out_len)
|
||||
}
|
||||
|
||||
// OAI CODE
|
||||
int32_t nrLDPC_coding_init()
|
||||
int32_t nrLDPC_coding_init(int max_num_pxsch)
|
||||
{
|
||||
pthread_mutex_init(&encode_mutex, NULL);
|
||||
pthread_mutex_init(&decode_mutex, NULL);
|
||||
@@ -1283,28 +1287,24 @@ 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) {
|
||||
for (int r = 0; r < nrLDPC_slot_decoding_parameters->TBs[h].C; r++) {
|
||||
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;
|
||||
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,
|
||||
nrLDPC_slot_decoding_parameters->TBs[h].segments[r].llr,
|
||||
nrLDPC_slot_decoding_parameters->TBs[h].segments[r].E * sizeof(uint16_t));
|
||||
memcpy(z_ol, p->llr + data_off, 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 < ((nrLDPC_slot_decoding_parameters->TBs[h].segments[r].E + 15) >> 4); i += 2, j++) {
|
||||
for (int i = 0, j = 0; j < ((E + 15) >> 4); i += 2, j++) {
|
||||
pl_ol128[j] = simde_mm_packs_epi16(pv_ol128[i], pv_ol128[i + 1]);
|
||||
}
|
||||
} else {
|
||||
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);
|
||||
llr_scaling(p->llr + data_off, E, &l_ol[offset], llr_size, llr_decimal, p->nb_layers, p->Qm);
|
||||
}
|
||||
offset += LDPC_MAX_CB_SIZE;
|
||||
data_off += E;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
enable_language(CUDA)
|
||||
|
||||
# it would be possible to auto-detect compute capailities: https://stackoverflow.com/a/68223399
|
||||
#include(FindCUDA/select_compute_arch)
|
||||
#CUDA_DETECT_INSTALLED_GPUS(INSTALLED_GPU_CCS_1)
|
||||
|
||||
# Nvidia recommends to build against all targeted archs: https://forums.developer.nvidia.com/t/261162
|
||||
# this is for cmake 3.16 (OAI minimum), starting at cmake 3.18 there is another syntax, see below
|
||||
|
||||
SET(CUDA_VERBOSE_BUILD ON)
|
||||
|
||||
# version using NVLink-C2C in Grace Hopper
|
||||
add_library(ldpc_cuda MODULE
|
||||
# main entry
|
||||
nrLDPC_coding_cuda.c
|
||||
|
||||
nrLDPC_decoder_cuda.c
|
||||
ldpc_encoder_cuda32.c
|
||||
ldpc_input32.c
|
||||
|
||||
nrLDPC_coding_segment_encoder_cuda.c
|
||||
nrLDPC_coding_segment_decoder_cuda.c
|
||||
|
||||
# .cu files
|
||||
nrLDPC_decoder_BG1_cuda.cu
|
||||
ldpc_BG1_Zc384_32bit.cu
|
||||
ldpc_input.cu
|
||||
ldpc_deinterleave.cu
|
||||
ldpc_rate_matching.cu
|
||||
)
|
||||
set_target_properties(ldpc_cuda PROPERTIES CUDA_ARCHITECTURES "80;87;90")
|
||||
# we need to find the right include directory, but ti seems that
|
||||
# enable_language(CUDA) does not make this available(?), so also use the CUDA package
|
||||
find_package(CUDA REQUIRED)
|
||||
target_include_directories(ldpc_cuda PRIVATE ${CUDA_INCLUDE_DIRS})
|
||||
|
||||
target_link_libraries(ldpc_cuda ldpc_gen_HEADERS log_headers)
|
||||
set_target_properties(ldpc_cuda PROPERTIES CUDA_SEPARABLE_COMPILATION ON)
|
||||
set_target_properties(ldpc_cuda PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
|
||||
|
||||
add_dependencies(ldpctest ldpc_cuda)
|
||||
add_dependencies(nr-softmodem ldpc_cuda)
|
||||
add_dependencies(nr-uesoftmodem ldpc_cuda)
|
||||
add_dependencies(nr_ulsim ldpc_cuda)
|
||||
add_dependencies(nr_ulschsim ldpc_cuda)
|
||||
add_dependencies(nr_dlsim ldpc_cuda)
|
||||
add_dependencies(nr_dlschsim ldpc_cuda)
|
||||
|
||||
if(ENABLE_PHYSIM_TESTS)
|
||||
|
||||
# this is a list of physical simulators designed to test the functioning of
|
||||
# ldpc_cuda. Of course, one could also modify
|
||||
# openair1/SIMULATION/tests/CMakeLists.txt to run them with ldpc_cuda
|
||||
|
||||
add_physim_test(ldpctest.ldpc_cuda.simple "ldpctest: simple CUDA load check" ldpctest -v _cuda -l8448 -s10 -n300)
|
||||
add_physim_test(ldpctest.ldpc_cuda.r13 "ldpctest: base graph 1, rate 1/3" ldpctest -v _cuda -r1 -n300 -S64 -s4 -i4)
|
||||
add_physim_test(ldpctest.ldpc_cuda.r23 "ldpctest: base graph 1, rate 2/3" ldpctest -v _cuda -r2 -n300 -S64 -s4 -i4)
|
||||
add_physim_test(ldpctest.ldpc_cuda.r89 "ldpctest: base graph 1, rate 8/9" ldpctest -v _cuda -r22 -d25 -n300 -S64 -s4 -i4)
|
||||
|
||||
add_physim_test(nr_dlsim.ldpc_cuda.9seg_r13 "nr_dlsim: 9 segments, rate 1/3" nr_dlsim -n100 -s20 -e13 -R273 -b273 -x1 -y1 -z1 -P --loader.ldpc.shlibversion _cuda)
|
||||
add_physim_test(nr_dlsim.ldpc_cuda.18seg_r23 "nr_dlsim: 18 segments, rate 2/3" nr_dlsim -n100 -s20 -e22 -R273 -b273 -x1 -y1 -z1 -P --loader.ldpc.shlibversion _cuda)
|
||||
add_physim_test(nr_dlsim.ldpc_cuda.50seg_r89 "nr_dlsim: 50 segments, rate 8/9" nr_dlsim -n100 -s40 -e27 -R273 -b273 -z2 -x2 -y2 -P --loader.ldpc.shlibversion _cuda)
|
||||
add_physim_test(nr_dlsim.ldpc_cuda.2t2r_mcs25_64qam "nr_dlsim: 2T2R/2 layers, MCS 25, 64QAM, 100 MHz 30 kHz SCS)" nr_dlsim -n100 -R273 -b273 -P -e 25 -s30 -x2 -y2 -z2 --loader.ldpc.shlibversion _cuda)
|
||||
add_physim_test(nr_dlsim.ldpc_cuda.1t1r_mcs25_256qam "nr_dlsim: 1T1R/1 layer, MCS 25, 256QAM, 100 MHz 30 kHz SCS)" nr_dlsim -n100 -R273 -b273 -P -e 25 -s30 -q 1 --loader.ldpc.shlibversion _cuda)
|
||||
add_physim_test(nr_dlsim.ldpc_cuda.1t1r_mcs25_256qam_bw "nr_dlsim: 1T1R/1 layer, MCS 25 256QAM, 40 MHz 30 kHz SCS" nr_dlsim -n100 -R106 -b106 -P -e 25 -s30 -q 1 --loader.ldpc.shlibversion _cuda)
|
||||
|
||||
add_physim_test(nr_ulsim.ldpc_cuda.9seg_r13 "nr_ulsim: 9 segments, rate 1/3" nr_ulsim -n100 -s20 -m13 -R273 -r273 -W1 -y1 -z1 -P --loader.ldpc.shlibversion _cuda)
|
||||
add_physim_test(nr_ulsim.ldpc_cuda.18seg_r23 "nr_ulsim: 18 segments, rate 2/3" nr_ulsim -n100 -s20 -m22 -R273 -r273 -W1 -y1 -z1 -P --loader.ldpc.shlibversion _cuda)
|
||||
add_physim_test(nr_ulsim.ldpc_cuda.50seg_r89 "nr_ulsim: 50 segments, rate 8/9" nr_ulsim -n100 -s40 -m27 -R273 -r273 -W2 -I9 -y2 -z2 -P --loader.ldpc.shlibversion _cuda)
|
||||
|
||||
endif()
|
||||
@@ -0,0 +1,216 @@
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <cuda_runtime.h>
|
||||
// generated code for Zc=384, byte encoding
|
||||
__global__ void ldpc_BG1_Zc384_worker(uint32_t *c[4],uint32_t *d[4]) {
|
||||
uint32_t *c32=c[blockIdx.x];
|
||||
uint32_t *d32=d[blockIdx.x]+8448-2*384;
|
||||
|
||||
int i2 = threadIdx.x;
|
||||
int i1 = blockIdx.y;
|
||||
// copy 20 c values to d
|
||||
if (i1<20) d[blockIdx.x][(i1*384) + i2] = c32[4*384+(2*384*i1)+i2];
|
||||
|
||||
if (i2 < 384) {
|
||||
c32+=i2;
|
||||
d32+=i2;
|
||||
switch(i1) {
|
||||
case 0:
|
||||
d32[0]=c32[307]^c32[76]^c32[205]^c32[276]^c32[787]^c32[1018]^c32[855]^c32[1586]^c32[1612]^c32[1864]^c32[2673]^c32[2377]^c32[2304]^c32[3360]^c32[3404]^c32[3347]^c32[4021]^c32[3984]^c32[4096]^c32[4824]^c32[4769]^c32[4807]^c32[5707]^c32[5643]^c32[5529]^c32[6475]^c32[6304]^c32[6200]^c32[7229]^c32[7090]^c32[6975]^c32[7968]^c32[7809]^c32[7812]^c32[8557]^c32[8743]^c32[8753]^c32[9233]^c32[9558]^c32[9447]^c32[10341]^c32[10184]^c32[10325]^c32[10969]^c32[10840]^c32[10964]^c32[11735]^c32[11619]^c32[11573]^c32[12394]^c32[12642]^c32[12592]^c32[13170]^c32[13187]^c32[13356]^c32[14066]^c32[14064]^c32[14095]^c32[14772]^c32[14923]^c32[14797]^c32[15690]^c32[15373]^c32[15399]^c32[16474]^c32[16240]^c32[16485];
|
||||
|
||||
break;
|
||||
case 1:
|
||||
d32[384]=c32[307]^c32[308]^c32[77]^c32[206]^c32[277]^c32[787]^c32[788]^c32[1019]^c32[856]^c32[1586]^c32[1587]^c32[1613]^c32[1865]^c32[2673]^c32[2674]^c32[2378]^c32[2305]^c32[3361]^c32[3405]^c32[3348]^c32[4021]^c32[4022]^c32[3985]^c32[4097]^c32[4824]^c32[4825]^c32[4770]^c32[4808]^c32[5708]^c32[5644]^c32[5530]^c32[6476]^c32[6305]^c32[6201]^c32[7229]^c32[7230]^c32[7091]^c32[6976]^c32[7968]^c32[7969]^c32[7810]^c32[7813]^c32[8557]^c32[8558]^c32[8744]^c32[8754]^c32[9233]^c32[9234]^c32[9559]^c32[9448]^c32[10341]^c32[10342]^c32[10185]^c32[10326]^c32[10970]^c32[10841]^c32[10965]^c32[11735]^c32[11736]^c32[11620]^c32[11574]^c32[12394]^c32[12395]^c32[12643]^c32[12593]^c32[13171]^c32[13188]^c32[13357]^c32[14066]^c32[14067]^c32[14065]^c32[14096]^c32[14772]^c32[14773]^c32[14924]^c32[14798]^c32[15690]^c32[15691]^c32[15374]^c32[15400]^c32[16474]^c32[16475]^c32[16241]^c32[16486];
|
||||
|
||||
break;
|
||||
case 2:
|
||||
d32[768]=c32[308]^c32[77]^c32[205]^c32[206]^c32[276]^c32[277]^c32[788]^c32[1018]^c32[1019]^c32[855]^c32[856]^c32[1587]^c32[1613]^c32[1864]^c32[1865]^c32[2674]^c32[2378]^c32[2304]^c32[2305]^c32[3361]^c32[3404]^c32[3405]^c32[3347]^c32[3348]^c32[4022]^c32[3985]^c32[4096]^c32[4097]^c32[4825]^c32[4769]^c32[4770]^c32[4807]^c32[4808]^c32[5708]^c32[5643]^c32[5644]^c32[5529]^c32[5530]^c32[6476]^c32[6304]^c32[6305]^c32[6200]^c32[6201]^c32[7230]^c32[7091]^c32[6975]^c32[6976]^c32[7969]^c32[7809]^c32[7810]^c32[7812]^c32[7813]^c32[8558]^c32[8744]^c32[8753]^c32[8754]^c32[9234]^c32[9559]^c32[9447]^c32[9448]^c32[10342]^c32[10184]^c32[10185]^c32[10325]^c32[10326]^c32[10970]^c32[10840]^c32[10841]^c32[10964]^c32[10965]^c32[11736]^c32[11620]^c32[11573]^c32[11574]^c32[12395]^c32[12643]^c32[12592]^c32[12593]^c32[13171]^c32[13187]^c32[13188]^c32[13356]^c32[13357]^c32[14067]^c32[14064]^c32[14065]^c32[14095]^c32[14096]^c32[14773]^c32[14924]^c32[14797]^c32[14798]^c32[15691]^c32[15373]^c32[15374]^c32[15399]^c32[15400]^c32[16475]^c32[16241]^c32[16485]^c32[16486];
|
||||
|
||||
break;
|
||||
case 3:
|
||||
d32[1152]=c32[308]^c32[77]^c32[206]^c32[276]^c32[277]^c32[788]^c32[1019]^c32[855]^c32[856]^c32[1587]^c32[1613]^c32[1865]^c32[2674]^c32[2378]^c32[2304]^c32[2305]^c32[3361]^c32[3405]^c32[3347]^c32[3348]^c32[4022]^c32[3985]^c32[4097]^c32[4825]^c32[4770]^c32[4807]^c32[4808]^c32[5708]^c32[5644]^c32[5529]^c32[5530]^c32[6476]^c32[6305]^c32[6200]^c32[6201]^c32[7230]^c32[7091]^c32[6976]^c32[7969]^c32[7810]^c32[7812]^c32[7813]^c32[8558]^c32[8744]^c32[8753]^c32[8754]^c32[9234]^c32[9559]^c32[9447]^c32[9448]^c32[10342]^c32[10185]^c32[10325]^c32[10326]^c32[10970]^c32[10841]^c32[10964]^c32[10965]^c32[11736]^c32[11620]^c32[11574]^c32[12395]^c32[12643]^c32[12592]^c32[12593]^c32[13171]^c32[13188]^c32[13356]^c32[13357]^c32[14067]^c32[14065]^c32[14095]^c32[14096]^c32[14773]^c32[14924]^c32[14798]^c32[15691]^c32[15374]^c32[15399]^c32[15400]^c32[16475]^c32[16241]^c32[16485]^c32[16486];
|
||||
|
||||
break;
|
||||
case 4:
|
||||
d32[1536]=c32[332]^c32[949];
|
||||
|
||||
break;
|
||||
case 5:
|
||||
d32[1920]=c32[80]^c32[233]^c32[362]^c32[49]^c32[195]^c32[944]^c32[791]^c32[1012]^c32[782]^c32[1743]^c32[1769]^c32[1637]^c32[2446]^c32[2534]^c32[2461]^c32[2419]^c32[3133]^c32[3177]^c32[3120]^c32[4178]^c32[4141]^c32[3869]^c32[4981]^c32[4926]^c32[4964]^c32[5480]^c32[5416]^c32[5686]^c32[6248]^c32[6461]^c32[6357]^c32[7002]^c32[7247]^c32[7132]^c32[7741]^c32[7966]^c32[7969]^c32[8714]^c32[8516]^c32[8526]^c32[9390]^c32[9331]^c32[9220]^c32[9382]^c32[10114]^c32[10341]^c32[10098]^c32[11126]^c32[10997]^c32[11121]^c32[11892]^c32[11776]^c32[11730]^c32[12551]^c32[12415]^c32[12365]^c32[12529]^c32[13327]^c32[13344]^c32[13129]^c32[13839]^c32[13837]^c32[13868]^c32[14929]^c32[14696]^c32[14954]^c32[15463]^c32[15530]^c32[15556]^c32[16247]^c32[16397]^c32[16258]^c32[16179];
|
||||
|
||||
break;
|
||||
case 6:
|
||||
d32[2304]=c32[278]^c32[4865]^c32[7681]^c32[8799]^c32[10076]^c32[13309]^c32[13842]^c32[15585];
|
||||
|
||||
break;
|
||||
case 7:
|
||||
d32[2688]=c32[9]^c32[830]^c32[3388]^c32[5709]^c32[6434]^c32[10866];
|
||||
|
||||
break;
|
||||
case 8:
|
||||
d32[3072]=c32[374]^c32[94]^c32[143]^c32[247]^c32[272]^c32[375]^c32[376]^c32[343]^c32[62]^c32[63]^c32[307]^c32[854]^c32[958]^c32[1085]^c32[804]^c32[805]^c32[922]^c32[1025]^c32[1026]^c32[947]^c32[1653]^c32[1757]^c32[1679]^c32[1783]^c32[1547]^c32[1650]^c32[1651]^c32[2356]^c32[2460]^c32[2444]^c32[2548]^c32[2371]^c32[2474]^c32[2475]^c32[2469]^c32[3427]^c32[3147]^c32[3087]^c32[3190]^c32[3191]^c32[3414]^c32[3133]^c32[3134]^c32[4088]^c32[4192]^c32[4051]^c32[4155]^c32[4163]^c32[3882]^c32[3883]^c32[4891]^c32[4611]^c32[4836]^c32[4939]^c32[4940]^c32[4874]^c32[4977]^c32[4978]^c32[5390]^c32[5494]^c32[5710]^c32[5429]^c32[5430]^c32[5596]^c32[5699]^c32[5700]^c32[6158]^c32[6262]^c32[6371]^c32[6474]^c32[6475]^c32[6267]^c32[6370]^c32[6371]^c32[6912]^c32[7016]^c32[7157]^c32[7261]^c32[7042]^c32[7145]^c32[7146]^c32[8035]^c32[7755]^c32[7876]^c32[7979]^c32[7980]^c32[7879]^c32[7982]^c32[7983]^c32[8624]^c32[8728]^c32[8810]^c32[8530]^c32[8820]^c32[8539]^c32[8540]^c32[9300]^c32[9404]^c32[9241]^c32[9345]^c32[9514]^c32[9233]^c32[9234]^c32[9234]^c32[10024]^c32[10128]^c32[10251]^c32[10354]^c32[10355]^c32[10008]^c32[10111]^c32[10112]^c32[11036]^c32[10756]^c32[10907]^c32[11010]^c32[11011]^c32[11031]^c32[11134]^c32[11135]^c32[11802]^c32[11522]^c32[11686]^c32[11790]^c32[11640]^c32[11743]^c32[11744]^c32[12461]^c32[12565]^c32[12325]^c32[12429]^c32[12659]^c32[12378]^c32[12379]^c32[12327]^c32[13237]^c32[13341]^c32[13254]^c32[13357]^c32[13358]^c32[13423]^c32[13142]^c32[13143]^c32[14133]^c32[13853]^c32[14131]^c32[13850]^c32[13851]^c32[14162]^c32[13881]^c32[13882]^c32[14839]^c32[14943]^c32[14606]^c32[14710]^c32[14864]^c32[14967]^c32[14968]^c32[14816]^c32[15373]^c32[15477]^c32[15440]^c32[15543]^c32[15544]^c32[15466]^c32[15569]^c32[15570]^c32[16157]^c32[16261]^c32[16307]^c32[16411]^c32[16168]^c32[16271]^c32[16272]^c32[16496];
|
||||
|
||||
break;
|
||||
case 9:
|
||||
d32[3456]=c32[366]^c32[1000]^c32[8001]^c32[8581]^c32[10041]^c32[13359]^c32[13887]^c32[15442];
|
||||
|
||||
break;
|
||||
case 10:
|
||||
d32[3840]=c32[869]^c32[1875]^c32[3346]^c32[5487]^c32[6527]^c32[11106];
|
||||
|
||||
break;
|
||||
case 11:
|
||||
d32[4224]=c32[257]^c32[38]^c32[39]^c32[26]^c32[192]^c32[155]^c32[321]^c32[226]^c32[8]^c32[48]^c32[1121]^c32[902]^c32[903]^c32[968]^c32[1134]^c32[805]^c32[971]^c32[870]^c32[1536]^c32[1701]^c32[1702]^c32[1562]^c32[1728]^c32[1814]^c32[1596]^c32[2623]^c32[2404]^c32[2405]^c32[2327]^c32[2493]^c32[2638]^c32[2420]^c32[3310]^c32[3092]^c32[3354]^c32[3136]^c32[3297]^c32[3079]^c32[3971]^c32[4136]^c32[4137]^c32[3934]^c32[4100]^c32[4046]^c32[4212]^c32[4774]^c32[4939]^c32[4940]^c32[4719]^c32[4885]^c32[4757]^c32[4923]^c32[5657]^c32[5439]^c32[5593]^c32[5759]^c32[5479]^c32[5645]^c32[6425]^c32[6207]^c32[6254]^c32[6420]^c32[6150]^c32[6316]^c32[7179]^c32[6960]^c32[6961]^c32[7040]^c32[7206]^c32[6925]^c32[7091]^c32[7918]^c32[7699]^c32[7700]^c32[7759]^c32[7925]^c32[7762]^c32[7928]^c32[8507]^c32[8672]^c32[8673]^c32[8693]^c32[8475]^c32[8703]^c32[8485]^c32[9567]^c32[9348]^c32[9349]^c32[9508]^c32[9290]^c32[9397]^c32[9563]^c32[9224]^c32[10291]^c32[10072]^c32[10073]^c32[10134]^c32[10300]^c32[10275]^c32[10057]^c32[10919]^c32[11085]^c32[10790]^c32[10956]^c32[10914]^c32[11080]^c32[11685]^c32[11850]^c32[11851]^c32[11569]^c32[11735]^c32[11523]^c32[11689]^c32[12344]^c32[12509]^c32[12510]^c32[12592]^c32[12374]^c32[12542]^c32[12324]^c32[12335]^c32[13120]^c32[13286]^c32[13137]^c32[13303]^c32[13306]^c32[13088]^c32[14016]^c32[14181]^c32[14182]^c32[14014]^c32[14180]^c32[14045]^c32[13827]^c32[14722]^c32[14887]^c32[14888]^c32[14873]^c32[14655]^c32[14747]^c32[14913]^c32[15640]^c32[15421]^c32[15422]^c32[15707]^c32[15489]^c32[15733]^c32[15515]^c32[16424]^c32[16205]^c32[16206]^c32[16190]^c32[16356]^c32[16435]^c32[16217]^c32[16316];
|
||||
|
||||
break;
|
||||
case 12:
|
||||
d32[4608]=c32[77]^c32[954]^c32[7854]^c32[8680]^c32[10034]^c32[13898];
|
||||
|
||||
break;
|
||||
case 13:
|
||||
d32[4992]=c32[293]^c32[294]^c32[63]^c32[192]^c32[263]^c32[313]^c32[773]^c32[774]^c32[1005]^c32[842]^c32[1572]^c32[1573]^c32[1599]^c32[1851]^c32[2659]^c32[2660]^c32[2364]^c32[2675]^c32[2481]^c32[3347]^c32[3391]^c32[3334]^c32[4007]^c32[4008]^c32[3971]^c32[4083]^c32[4810]^c32[4811]^c32[4756]^c32[4794]^c32[5694]^c32[5630]^c32[5516]^c32[5642]^c32[6462]^c32[6291]^c32[6187]^c32[7215]^c32[7216]^c32[7077]^c32[6962]^c32[7954]^c32[7955]^c32[7796]^c32[7799]^c32[8543]^c32[8544]^c32[8730]^c32[8740]^c32[9219]^c32[9220]^c32[9545]^c32[9434]^c32[10327]^c32[10328]^c32[10171]^c32[10312]^c32[10956]^c32[10827]^c32[10951]^c32[11721]^c32[11722]^c32[11606]^c32[11560]^c32[12380]^c32[12381]^c32[12629]^c32[12579]^c32[13157]^c32[13174]^c32[13343]^c32[14052]^c32[14053]^c32[14051]^c32[14082]^c32[14758]^c32[14759]^c32[14910]^c32[14784]^c32[15676]^c32[15677]^c32[15360]^c32[15386]^c32[15475]^c32[16460]^c32[16461]^c32[16227]^c32[16472];
|
||||
|
||||
break;
|
||||
case 14:
|
||||
d32[5376]=c32[142]^c32[9464]^c32[11657]^c32[12377]^c32[13403]^c32[16140];
|
||||
|
||||
break;
|
||||
case 15:
|
||||
d32[5760]=c32[193]^c32[346]^c32[91]^c32[161]^c32[162]^c32[241]^c32[1057]^c32[904]^c32[1124]^c32[1125]^c32[770]^c32[1856]^c32[1882]^c32[1750]^c32[2559]^c32[2647]^c32[2573]^c32[2574]^c32[3246]^c32[3290]^c32[3232]^c32[3233]^c32[3907]^c32[3870]^c32[3982]^c32[4710]^c32[4655]^c32[4692]^c32[4693]^c32[5593]^c32[5529]^c32[5414]^c32[5415]^c32[6361]^c32[6190]^c32[6469]^c32[6470]^c32[7115]^c32[6976]^c32[7245]^c32[7854]^c32[7695]^c32[7697]^c32[7698]^c32[7890]^c32[8827]^c32[8629]^c32[8638]^c32[8639]^c32[9503]^c32[9444]^c32[9332]^c32[9333]^c32[10227]^c32[10070]^c32[10210]^c32[10211]^c32[10302]^c32[10855]^c32[11110]^c32[10849]^c32[10850]^c32[11621]^c32[11889]^c32[11843]^c32[12664]^c32[12528]^c32[12477]^c32[12478]^c32[13056]^c32[13073]^c32[13241]^c32[13242]^c32[13952]^c32[13950]^c32[13980]^c32[13981]^c32[13879]^c32[14658]^c32[14809]^c32[14683]^c32[15576]^c32[15643]^c32[15668]^c32[15669]^c32[16360]^c32[16510]^c32[16370]^c32[16371];
|
||||
|
||||
break;
|
||||
case 16:
|
||||
d32[6144]=c32[364]^c32[133]^c32[262]^c32[333]^c32[844]^c32[1075]^c32[912]^c32[781]^c32[1643]^c32[1669]^c32[1537]^c32[2346]^c32[2434]^c32[2361]^c32[2642]^c32[3417]^c32[3077]^c32[3404]^c32[4078]^c32[4041]^c32[4153]^c32[4881]^c32[4826]^c32[4864]^c32[5380]^c32[5700]^c32[5586]^c32[6148]^c32[6361]^c32[6257]^c32[7286]^c32[7147]^c32[7032]^c32[8025]^c32[7866]^c32[7869]^c32[8614]^c32[8800]^c32[8810]^c32[8505]^c32[9290]^c32[9231]^c32[9504]^c32[10014]^c32[10241]^c32[9998]^c32[11026]^c32[10897]^c32[11021]^c32[11792]^c32[11676]^c32[11630]^c32[12451]^c32[12315]^c32[12649]^c32[13227]^c32[13244]^c32[13413]^c32[14123]^c32[14121]^c32[14152]^c32[14829]^c32[14596]^c32[14854]^c32[15363]^c32[15430]^c32[15456]^c32[15649]^c32[16147]^c32[16297]^c32[16158];
|
||||
|
||||
break;
|
||||
case 17:
|
||||
d32[6528]=c32[260]^c32[11055]^c32[12369]^c32[13414]^c32[16503];
|
||||
|
||||
break;
|
||||
case 18:
|
||||
d32[6912]=c32[898]^c32[9379]^c32[10264]^c32[13956]^c32[14596];
|
||||
|
||||
break;
|
||||
case 19:
|
||||
d32[7296]=c32[145]^c32[981]^c32[5720]^c32[6386]^c32[7877];
|
||||
|
||||
break;
|
||||
case 20:
|
||||
d32[7680]=c32[366]^c32[135]^c32[264]^c32[335]^c32[187]^c32[846]^c32[1077]^c32[914]^c32[1645]^c32[1671]^c32[1539]^c32[2348]^c32[2436]^c32[2363]^c32[2510]^c32[3419]^c32[3079]^c32[3406]^c32[4080]^c32[4043]^c32[4155]^c32[4883]^c32[4828]^c32[4866]^c32[5382]^c32[5702]^c32[5588]^c32[6150]^c32[6363]^c32[6259]^c32[7288]^c32[7149]^c32[7034]^c32[7176]^c32[8027]^c32[7868]^c32[7871]^c32[8616]^c32[8802]^c32[8812]^c32[8789]^c32[9292]^c32[9233]^c32[9506]^c32[10016]^c32[10243]^c32[10000]^c32[11028]^c32[10899]^c32[11023]^c32[11794]^c32[11678]^c32[11632]^c32[12453]^c32[12317]^c32[12651]^c32[13229]^c32[13246]^c32[13415]^c32[14125]^c32[14123]^c32[14154]^c32[14831]^c32[14598]^c32[14856]^c32[15365]^c32[15432]^c32[15458]^c32[16149]^c32[16299]^c32[16160];
|
||||
|
||||
break;
|
||||
case 21:
|
||||
d32[8064]=c32[973]^c32[3942]^c32[12616]^c32[15573]^c32[16225];
|
||||
|
||||
break;
|
||||
case 22:
|
||||
d32[8448]=c32[30]^c32[9227]^c32[10217]^c32[13078];
|
||||
|
||||
break;
|
||||
case 23:
|
||||
d32[8832]=c32[792]^c32[1625]^c32[7741]^c32[13851];
|
||||
|
||||
break;
|
||||
case 24:
|
||||
d32[9216]=c32[157]^c32[310]^c32[55]^c32[126]^c32[298]^c32[1021]^c32[868]^c32[1089]^c32[1820]^c32[1846]^c32[1714]^c32[2523]^c32[2611]^c32[2538]^c32[2462]^c32[3210]^c32[3254]^c32[3197]^c32[3307]^c32[3871]^c32[4218]^c32[3946]^c32[4674]^c32[4619]^c32[4657]^c32[5557]^c32[5493]^c32[5379]^c32[6325]^c32[6154]^c32[6434]^c32[7079]^c32[6940]^c32[7209]^c32[7818]^c32[8043]^c32[8046]^c32[8791]^c32[8593]^c32[8603]^c32[8787]^c32[9467]^c32[9408]^c32[9297]^c32[10191]^c32[10034]^c32[10175]^c32[10819]^c32[11074]^c32[10814]^c32[11585]^c32[11853]^c32[11807]^c32[12628]^c32[12492]^c32[12442]^c32[13404]^c32[13421]^c32[13206]^c32[13916]^c32[13914]^c32[13945]^c32[14622]^c32[14773]^c32[14647]^c32[15540]^c32[15607]^c32[15633]^c32[16324]^c32[16474]^c32[16335];
|
||||
|
||||
break;
|
||||
case 25:
|
||||
d32[9600]=c32[840]^c32[4625]^c32[5759]^c32[11064];
|
||||
|
||||
break;
|
||||
case 26:
|
||||
d32[9984]=c32[71]^c32[1617]^c32[3148]^c32[11656];
|
||||
|
||||
break;
|
||||
case 27:
|
||||
d32[10368]=c32[962]^c32[4802]^c32[6245];
|
||||
|
||||
break;
|
||||
case 28:
|
||||
d32[10752]=c32[222]^c32[3091]^c32[14836]^c32[16402];
|
||||
|
||||
break;
|
||||
case 29:
|
||||
d32[11136]=c32[2]^c32[155]^c32[284]^c32[354]^c32[355]^c32[866]^c32[1097]^c32[933]^c32[934]^c32[1020]^c32[1665]^c32[1691]^c32[1559]^c32[2368]^c32[2456]^c32[2382]^c32[2383]^c32[3439]^c32[3099]^c32[3425]^c32[3426]^c32[4100]^c32[4063]^c32[4175]^c32[4903]^c32[4848]^c32[4885]^c32[4886]^c32[5402]^c32[5722]^c32[5607]^c32[5608]^c32[6170]^c32[6383]^c32[6278]^c32[6279]^c32[6924]^c32[7169]^c32[7054]^c32[8047]^c32[7888]^c32[7890]^c32[7891]^c32[8636]^c32[8822]^c32[8831]^c32[8448]^c32[9312]^c32[9253]^c32[9525]^c32[9526]^c32[10036]^c32[10263]^c32[10019]^c32[10020]^c32[11048]^c32[10919]^c32[11042]^c32[11043]^c32[10757]^c32[11814]^c32[11698]^c32[11652]^c32[12473]^c32[12337]^c32[12670]^c32[12671]^c32[13249]^c32[13266]^c32[13434]^c32[13435]^c32[14145]^c32[14143]^c32[14173]^c32[14174]^c32[13971]^c32[14851]^c32[14618]^c32[14876]^c32[15385]^c32[15452]^c32[15477]^c32[15478]^c32[16169]^c32[16319]^c32[16179]^c32[16180];
|
||||
|
||||
break;
|
||||
case 30:
|
||||
d32[11520]=c32[14]^c32[167]^c32[295]^c32[296]^c32[366]^c32[367]^c32[159]^c32[878]^c32[1108]^c32[1109]^c32[945]^c32[946]^c32[1677]^c32[1703]^c32[1570]^c32[1571]^c32[2380]^c32[2468]^c32[2394]^c32[2395]^c32[3451]^c32[3110]^c32[3111]^c32[3437]^c32[3438]^c32[4112]^c32[4075]^c32[4186]^c32[4187]^c32[4915]^c32[4859]^c32[4860]^c32[4897]^c32[4898]^c32[5414]^c32[5733]^c32[5734]^c32[5619]^c32[5620]^c32[6182]^c32[6394]^c32[6395]^c32[6290]^c32[6291]^c32[6936]^c32[7181]^c32[7065]^c32[7066]^c32[8059]^c32[7899]^c32[7900]^c32[7902]^c32[7903]^c32[7909]^c32[8648]^c32[8450]^c32[8459]^c32[8460]^c32[9324]^c32[9265]^c32[9537]^c32[9538]^c32[10048]^c32[10274]^c32[10275]^c32[10031]^c32[10032]^c32[10244]^c32[11060]^c32[10930]^c32[10931]^c32[11054]^c32[11055]^c32[11826]^c32[11710]^c32[11663]^c32[11664]^c32[12485]^c32[12349]^c32[12298]^c32[12299]^c32[13261]^c32[13277]^c32[13278]^c32[13062]^c32[13063]^c32[14157]^c32[14154]^c32[14155]^c32[14185]^c32[14186]^c32[14863]^c32[14630]^c32[14887]^c32[14888]^c32[15397]^c32[15463]^c32[15464]^c32[15489]^c32[15490]^c32[16181]^c32[16331]^c32[16191]^c32[16192];
|
||||
|
||||
break;
|
||||
case 31:
|
||||
d32[11904]=c32[181]^c32[180]^c32[334]^c32[333]^c32[79]^c32[78]^c32[150]^c32[148]^c32[149]^c32[1045]^c32[1044]^c32[892]^c32[891]^c32[1113]^c32[1111]^c32[1112]^c32[868]^c32[1844]^c32[1843]^c32[1870]^c32[1869]^c32[1738]^c32[1737]^c32[2547]^c32[2546]^c32[2635]^c32[2634]^c32[2562]^c32[2560]^c32[2561]^c32[3234]^c32[3233]^c32[3278]^c32[3277]^c32[3221]^c32[3219]^c32[3220]^c32[3895]^c32[3894]^c32[3858]^c32[3857]^c32[3970]^c32[3969]^c32[4698]^c32[4697]^c32[4643]^c32[4642]^c32[4681]^c32[4679]^c32[4680]^c32[5581]^c32[5580]^c32[5517]^c32[5516]^c32[5403]^c32[5401]^c32[5402]^c32[5591]^c32[6349]^c32[6348]^c32[6178]^c32[6177]^c32[6458]^c32[6456]^c32[6457]^c32[7103]^c32[7102]^c32[6964]^c32[6963]^c32[7233]^c32[7232]^c32[7842]^c32[7841]^c32[7683]^c32[7682]^c32[7686]^c32[7684]^c32[7685]^c32[8815]^c32[8814]^c32[8617]^c32[8616]^c32[8627]^c32[8625]^c32[8626]^c32[9491]^c32[9490]^c32[9432]^c32[9431]^c32[9321]^c32[9319]^c32[9320]^c32[10215]^c32[10214]^c32[10058]^c32[10057]^c32[10199]^c32[10197]^c32[10198]^c32[10843]^c32[10842]^c32[11098]^c32[11097]^c32[10838]^c32[10836]^c32[10837]^c32[11609]^c32[11608]^c32[11877]^c32[11876]^c32[11831]^c32[11830]^c32[12652]^c32[12651]^c32[12516]^c32[12515]^c32[12466]^c32[12464]^c32[12465]^c32[13428]^c32[13427]^c32[13061]^c32[13060]^c32[13230]^c32[13228]^c32[13229]^c32[13940]^c32[13939]^c32[13938]^c32[13937]^c32[13969]^c32[13967]^c32[13968]^c32[14646]^c32[14645]^c32[14797]^c32[14796]^c32[14671]^c32[14670]^c32[15564]^c32[15563]^c32[15631]^c32[15630]^c32[15657]^c32[15655]^c32[15656]^c32[16348]^c32[16347]^c32[16498]^c32[16497]^c32[16359]^c32[16357]^c32[16358];
|
||||
|
||||
break;
|
||||
case 32:
|
||||
d32[12288]=c32[211]^c32[364]^c32[108]^c32[109]^c32[179]^c32[180]^c32[102]^c32[1075]^c32[921]^c32[922]^c32[1142]^c32[1143]^c32[1874]^c32[1900]^c32[1767]^c32[1768]^c32[2577]^c32[2665]^c32[2591]^c32[2592]^c32[3264]^c32[3307]^c32[3308]^c32[3250]^c32[3251]^c32[3925]^c32[3888]^c32[3999]^c32[4000]^c32[4728]^c32[4672]^c32[4673]^c32[4710]^c32[4711]^c32[5611]^c32[5546]^c32[5547]^c32[5432]^c32[5433]^c32[6379]^c32[6207]^c32[6208]^c32[6487]^c32[6488]^c32[7133]^c32[6994]^c32[7262]^c32[7263]^c32[7872]^c32[7712]^c32[7713]^c32[7715]^c32[7716]^c32[8461]^c32[8647]^c32[8656]^c32[8657]^c32[9521]^c32[9462]^c32[9350]^c32[9351]^c32[9417]^c32[10245]^c32[10087]^c32[10088]^c32[10228]^c32[10229]^c32[10873]^c32[11127]^c32[11128]^c32[10867]^c32[10868]^c32[10927]^c32[11639]^c32[11523]^c32[11860]^c32[11861]^c32[12298]^c32[12546]^c32[12495]^c32[12496]^c32[13074]^c32[13090]^c32[13091]^c32[13259]^c32[13260]^c32[13970]^c32[13967]^c32[13968]^c32[13998]^c32[13999]^c32[14676]^c32[14827]^c32[14700]^c32[14701]^c32[15594]^c32[15660]^c32[15661]^c32[15686]^c32[15687]^c32[16378]^c32[16144]^c32[16388]^c32[16389];
|
||||
|
||||
break;
|
||||
case 33:
|
||||
d32[12672]=c32[1091]^c32[1544]^c32[8809]^c32[16233];
|
||||
|
||||
break;
|
||||
case 34:
|
||||
d32[13056]=c32[230]^c32[5524]^c32[11722]^c32[13368];
|
||||
|
||||
break;
|
||||
case 35:
|
||||
d32[13440]=c32[189]^c32[342]^c32[87]^c32[158]^c32[1053]^c32[900]^c32[1121]^c32[1088]^c32[1852]^c32[1878]^c32[1746]^c32[2555]^c32[2643]^c32[2570]^c32[3242]^c32[3286]^c32[3229]^c32[3903]^c32[3866]^c32[3978]^c32[4706]^c32[4651]^c32[4689]^c32[4943]^c32[5589]^c32[5525]^c32[5411]^c32[6357]^c32[6186]^c32[6466]^c32[7111]^c32[6972]^c32[7241]^c32[7850]^c32[7691]^c32[7694]^c32[8823]^c32[8625]^c32[8635]^c32[9499]^c32[9440]^c32[9329]^c32[9218]^c32[10223]^c32[10066]^c32[10207]^c32[10851]^c32[11106]^c32[10846]^c32[11617]^c32[11885]^c32[11839]^c32[12660]^c32[12524]^c32[12474]^c32[13436]^c32[13069]^c32[13238]^c32[13948]^c32[13946]^c32[13977]^c32[14654]^c32[14805]^c32[14679]^c32[15572]^c32[15639]^c32[15665]^c32[16356]^c32[16506]^c32[16367];
|
||||
|
||||
break;
|
||||
case 36:
|
||||
d32[13824]=c32[210]^c32[11065]^c32[11817]^c32[13845];
|
||||
|
||||
break;
|
||||
case 37:
|
||||
d32[14208]=c32[38]^c32[39]^c32[192]^c32[321]^c32[8]^c32[902]^c32[903]^c32[1134]^c32[971]^c32[1037]^c32[1701]^c32[1702]^c32[1728]^c32[1596]^c32[2404]^c32[2405]^c32[2493]^c32[2420]^c32[3092]^c32[3136]^c32[3079]^c32[4136]^c32[4137]^c32[4100]^c32[4212]^c32[4939]^c32[4940]^c32[4885]^c32[4923]^c32[5439]^c32[5759]^c32[5645]^c32[6207]^c32[6420]^c32[6316]^c32[6960]^c32[6961]^c32[7206]^c32[7091]^c32[7699]^c32[7700]^c32[7925]^c32[7928]^c32[8672]^c32[8673]^c32[8475]^c32[8485]^c32[9348]^c32[9349]^c32[9290]^c32[9563]^c32[10072]^c32[10073]^c32[10300]^c32[10057]^c32[10066]^c32[11085]^c32[10956]^c32[11080]^c32[11850]^c32[11851]^c32[11735]^c32[11689]^c32[12509]^c32[12510]^c32[12374]^c32[12324]^c32[13286]^c32[13303]^c32[13088]^c32[14181]^c32[14182]^c32[14180]^c32[13827]^c32[14887]^c32[14888]^c32[14655]^c32[14913]^c32[15421]^c32[15422]^c32[15489]^c32[15515]^c32[16205]^c32[16206]^c32[16356]^c32[16217];
|
||||
|
||||
break;
|
||||
case 38:
|
||||
d32[14592]=c32[185]^c32[7089]^c32[7969]^c32[9430];
|
||||
|
||||
break;
|
||||
case 39:
|
||||
d32[14976]=c32[1026]^c32[2397]^c32[5722]^c32[14889];
|
||||
|
||||
break;
|
||||
case 40:
|
||||
d32[15360]=c32[175]^c32[6181]^c32[13368];
|
||||
|
||||
break;
|
||||
case 41:
|
||||
d32[15744]=c32[820]^c32[2618]^c32[7051]^c32[14112];
|
||||
|
||||
break;
|
||||
case 42:
|
||||
d32[16128]=c32[142]^c32[295]^c32[39]^c32[40]^c32[110]^c32[111]^c32[113]^c32[1006]^c32[852]^c32[853]^c32[1073]^c32[1074]^c32[1805]^c32[1831]^c32[1698]^c32[1699]^c32[2508]^c32[2596]^c32[2522]^c32[2523]^c32[3195]^c32[3238]^c32[3239]^c32[3181]^c32[3182]^c32[3086]^c32[3856]^c32[4203]^c32[3930]^c32[3931]^c32[4659]^c32[4987]^c32[4988]^c32[4641]^c32[4642]^c32[5542]^c32[5477]^c32[5478]^c32[5747]^c32[5748]^c32[6310]^c32[6522]^c32[6523]^c32[6418]^c32[6419]^c32[7064]^c32[6925]^c32[7193]^c32[7194]^c32[7803]^c32[8027]^c32[8028]^c32[8030]^c32[8031]^c32[8776]^c32[8578]^c32[8587]^c32[8588]^c32[9452]^c32[9393]^c32[9281]^c32[9282]^c32[10176]^c32[10018]^c32[10019]^c32[10159]^c32[10160]^c32[10804]^c32[11058]^c32[11059]^c32[10798]^c32[10799]^c32[11570]^c32[11838]^c32[11791]^c32[11792]^c32[12613]^c32[12477]^c32[12426]^c32[12427]^c32[13389]^c32[13405]^c32[13406]^c32[13190]^c32[13191]^c32[13901]^c32[13898]^c32[13899]^c32[13929]^c32[13930]^c32[14607]^c32[14758]^c32[14631]^c32[14632]^c32[15525]^c32[15591]^c32[15592]^c32[15617]^c32[15618]^c32[16309]^c32[16459]^c32[16319]^c32[16320];
|
||||
|
||||
break;
|
||||
case 43:
|
||||
d32[16512]=c32[92]^c32[245]^c32[374]^c32[60]^c32[61]^c32[956]^c32[803]^c32[1023]^c32[1024]^c32[881]^c32[1755]^c32[1781]^c32[1649]^c32[2458]^c32[2546]^c32[2472]^c32[2473]^c32[3145]^c32[3189]^c32[3131]^c32[3132]^c32[4190]^c32[4153]^c32[3881]^c32[4609]^c32[4938]^c32[4975]^c32[4976]^c32[5492]^c32[5428]^c32[5697]^c32[5698]^c32[6260]^c32[6473]^c32[6368]^c32[6369]^c32[7014]^c32[7259]^c32[7144]^c32[7753]^c32[7978]^c32[7980]^c32[7981]^c32[8726]^c32[8528]^c32[8537]^c32[8538]^c32[9402]^c32[9343]^c32[9231]^c32[9232]^c32[10126]^c32[10353]^c32[10109]^c32[10110]^c32[10754]^c32[11009]^c32[11132]^c32[11133]^c32[11520]^c32[11788]^c32[11742]^c32[12563]^c32[12427]^c32[12376]^c32[12377]^c32[12420]^c32[13339]^c32[13356]^c32[13140]^c32[13141]^c32[13851]^c32[13849]^c32[13879]^c32[13880]^c32[13938]^c32[14941]^c32[14708]^c32[14966]^c32[15475]^c32[15542]^c32[15567]^c32[15568]^c32[16259]^c32[16409]^c32[16269]^c32[16270];
|
||||
|
||||
break;
|
||||
case 44:
|
||||
d32[16896]=c32[197]^c32[350]^c32[95]^c32[166]^c32[80]^c32[1061]^c32[908]^c32[1129]^c32[1860]^c32[1886]^c32[1754]^c32[2563]^c32[2651]^c32[2578]^c32[3250]^c32[3294]^c32[3237]^c32[3911]^c32[3874]^c32[3986]^c32[4714]^c32[4659]^c32[4697]^c32[5597]^c32[5533]^c32[5419]^c32[5454]^c32[6365]^c32[6194]^c32[6474]^c32[7119]^c32[6980]^c32[7249]^c32[7075]^c32[7858]^c32[7699]^c32[7702]^c32[8831]^c32[8633]^c32[8643]^c32[9507]^c32[9448]^c32[9337]^c32[10231]^c32[10074]^c32[10215]^c32[10859]^c32[11114]^c32[10854]^c32[11625]^c32[11893]^c32[11847]^c32[12668]^c32[12532]^c32[12482]^c32[13060]^c32[13077]^c32[13246]^c32[13956]^c32[13954]^c32[13985]^c32[14662]^c32[14813]^c32[14687]^c32[15580]^c32[15647]^c32[15673]^c32[16364]^c32[16130]^c32[16375];
|
||||
|
||||
break;
|
||||
case 45:
|
||||
d32[17280]=c32[903]^c32[4757]^c32[7695];
|
||||
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
extern "C" int ldpc_BG1_Zc384_cuda32(uint32_t *c[4],uint32_t *d[4],int n_inputs,cudaStream_t *stream,int sidx) {
|
||||
|
||||
dim3 numblocks(n_inputs,46);
|
||||
ldpc_BG1_Zc384_worker<<<numblocks,384,0,stream[sidx]>>>(c,d);
|
||||
cudaError_t err=cudaPeekAtLastError();
|
||||
if (err!=cudaSuccess) {
|
||||
printf("cuda error: %s (c %p, d %p)\n",cudaGetErrorString(err),c,d);
|
||||
exit(-1);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
@@ -0,0 +1,131 @@
|
||||
// deinterleave_u16.cu
|
||||
#include <cuda_runtime.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
|
||||
__global__ void deinterleave_i16_2(int16_t* __restrict__ e,
|
||||
const int16_t* __restrict__ f,
|
||||
int E1,
|
||||
int E2,
|
||||
int r_firstE2)
|
||||
{
|
||||
int g = (int)(blockIdx.x * blockDim.x + threadIdx.x);
|
||||
int r = (int)blockIdx.y;
|
||||
int E = (r<r_firstE2) ? E1 : E2;
|
||||
int EQm = E/2;
|
||||
if (g >= EQm) return;
|
||||
|
||||
int r_off = r<r_firstE2 ? r*E1 : ((r_firstE2*E1)+(r-r_firstE2)*E2);
|
||||
const int16_t *in = f +r_off + 2*g;
|
||||
|
||||
int16_t* e0 = e + r_off;
|
||||
int16_t* e1 = e0 + EQm;
|
||||
e0[g] = in[0];
|
||||
e1[g] = in[1];
|
||||
}
|
||||
|
||||
__global__ void deinterleave_i16_4(int16_t* __restrict__ e,
|
||||
const int16_t* __restrict__ f,
|
||||
int E1,
|
||||
int E2,
|
||||
int r_firstE2)
|
||||
{
|
||||
int g = (int)(blockIdx.x * blockDim.x + threadIdx.x);
|
||||
int r = (int)blockIdx.y;
|
||||
int E = (r<r_firstE2) ? E1 : E2;
|
||||
int EQm = E/4;
|
||||
if (g >= EQm) return;
|
||||
|
||||
int r_off = r<r_firstE2 ? r*E1 : ((r_firstE2*E1)+(r-r_firstE2)*E2);
|
||||
const int16_t *in = f + r_off + 4*g;
|
||||
int16_t* e0 = e + r_off;
|
||||
int16_t* e1 = e0 + EQm;
|
||||
int16_t* e2 = e1 + EQm;
|
||||
int16_t* e3 = e2 + EQm;
|
||||
e0[g] = in[0];
|
||||
e1[g] = in[1];
|
||||
e2[g] = in[2];
|
||||
e3[g] = in[3];
|
||||
}
|
||||
|
||||
__global__ void deinterleave_i16_6(int16_t* __restrict__ e,
|
||||
const int16_t* __restrict__ f,
|
||||
int E1,
|
||||
int E2,
|
||||
int r_firstE2)
|
||||
{
|
||||
int g = (int)(blockIdx.x * blockDim.x + threadIdx.x);
|
||||
int r = (int)blockIdx.y;
|
||||
int E = (r<r_firstE2) ? E1 : E2;
|
||||
int EQm = E/6;
|
||||
if (g >= EQm) return;
|
||||
|
||||
int r_off = r<r_firstE2 ? r*E1 : (r_firstE2*E1)+(r-r_firstE2)*E2;
|
||||
const int16_t* in = f + r_off + 6*g;
|
||||
int16_t* e0 = e + r_off;
|
||||
int16_t* e1 = e0 + EQm;
|
||||
int16_t* e2 = e1 + EQm;
|
||||
int16_t* e3 = e2 + EQm;
|
||||
int16_t* e4 = e3 + EQm;
|
||||
int16_t* e5 = e4 + EQm;
|
||||
e0[g] = in[0];
|
||||
e1[g] = in[1];
|
||||
e2[g] = in[2];
|
||||
e3[g] = in[3];
|
||||
e4[g] = in[4];
|
||||
e5[g] = in[5];
|
||||
}
|
||||
|
||||
__global__ void deinterleave_i16_8(int16_t* __restrict__ e,
|
||||
const int16_t* __restrict__ f,
|
||||
const int E1,
|
||||
const int E2,
|
||||
const int r_firstE2)
|
||||
{
|
||||
int g = (int)(blockIdx.x * blockDim.x + threadIdx.x);
|
||||
int r = (int)blockIdx.y;
|
||||
int E = (r<r_firstE2) ? E1 : E2;
|
||||
int EQm = E/8;
|
||||
if (g >= EQm) return;
|
||||
int r_off = r<r_firstE2 ? r*E1 : (r_firstE2*E1)+(r-r_firstE2)*E2;
|
||||
|
||||
const int16_t *in = (f + r_off + 8*g);
|
||||
int16_t* e0 = e + r_off;
|
||||
int16_t* e1 = e0 + EQm;
|
||||
int16_t* e2 = e1 + EQm;
|
||||
int16_t* e3 = e2 + EQm;
|
||||
int16_t* e4 = e3 + EQm;
|
||||
int16_t* e5 = e4 + EQm;
|
||||
int16_t* e6 = e5 + EQm;
|
||||
int16_t* e7 = e6 + EQm;
|
||||
e0[g] = in[0];
|
||||
e1[g] = in[1];
|
||||
e2[g] = in[2];
|
||||
e3[g] = in[3];
|
||||
e4[g] = in[4];
|
||||
e5[g] = in[5];
|
||||
e6[g] = in[6];
|
||||
e7[g] = in[7];
|
||||
}
|
||||
|
||||
// Host launcher
|
||||
extern "C" void launch_deinterleave_i16(int Qm, int E1, int E2, int C, int r_firstE2,int16_t* e, const int16_t* f,cudaStream_t *s,int8_t sidx)
|
||||
{
|
||||
const int threads = 256;
|
||||
dim3 blocks(((E2/Qm) + threads - 1) / threads,C);
|
||||
|
||||
switch (Qm) {
|
||||
case 2: deinterleave_i16_2<<<blocks, threads, 0, s[sidx]>>>(e, f, E1,E2,r_firstE2); break;
|
||||
case 4: deinterleave_i16_4<<<blocks, threads, 0, s[sidx]>>>(e, f, E1,E2,r_firstE2); break;
|
||||
case 6: deinterleave_i16_6<<<blocks, threads, 0, s[sidx]>>>(e, f, E1,E2,r_firstE2); break;
|
||||
case 8: deinterleave_i16_8<<<blocks, threads, 0, s[sidx]>>>(e, f, E1,E2,r_firstE2); break;
|
||||
default: /* unsupported */ break;
|
||||
}
|
||||
cudaError_t err=cudaPeekAtLastError();
|
||||
|
||||
if (err!=cudaSuccess) {
|
||||
printf("cuda error (deinterleave_i16): %s (e %p, f %p, E1 %d, E2 %d, Qm %d, C %d)\n",cudaGetErrorString(err),e,f,E1,E2,Qm,C);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: LicenseRef-CSSL-1.0
|
||||
*/
|
||||
|
||||
/*!\file ldpc_encode_parity_check.c
|
||||
* \brief Parity check function used by ldpc encoders
|
||||
* \author Florian Kaltenberger, Raymond Knopp, Kien le Trung (Eurecom)
|
||||
* \email openair_tech@eurecom.fr
|
||||
* \date 27-03-2018
|
||||
* \version 1.0
|
||||
* \note
|
||||
* \warning
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "assertions.h"
|
||||
#include "common/utils/LOG/log.h"
|
||||
#include <cuda_runtime.h>
|
||||
|
||||
|
||||
|
||||
int ldpc_BG1_Zc384_cuda32(uint32_t **c,uint32_t **d,int n_inputs, cudaStream_t *stream,int sidx);
|
||||
|
||||
|
||||
void encode_parity_check_part_cuda(uint32_t **c, uint32_t **d, short BG,short Zc,short Kb, int ncols, int n_inputs, cudaStream_t *stream,int sidx)
|
||||
{
|
||||
|
||||
if (BG == 1) {
|
||||
switch (Zc) {
|
||||
case 176:
|
||||
case 192:
|
||||
case 208:
|
||||
case 224:
|
||||
case 240:
|
||||
case 256:
|
||||
case 288:
|
||||
case 320:
|
||||
case 352:
|
||||
AssertFatal(1==0,"BG %d Zc %d not supported yet for CUDA\n",BG, Zc);
|
||||
break;
|
||||
case 384:
|
||||
ldpc_BG1_Zc384_cuda32(c, d, n_inputs, stream,sidx);
|
||||
break;
|
||||
default:
|
||||
AssertFatal(false, "BG %d Zc %d is not supported yet\n", BG, Zc);
|
||||
}
|
||||
} else if (BG == 2) {
|
||||
switch (Zc) {
|
||||
case 72:
|
||||
case 80:
|
||||
case 88:
|
||||
case 96:
|
||||
case 104:
|
||||
case 112:
|
||||
case 120:
|
||||
case 128:
|
||||
case 144:
|
||||
case 160:
|
||||
case 176:
|
||||
case 192:
|
||||
case 208:
|
||||
case 224:
|
||||
case 240:
|
||||
case 256:
|
||||
case 288:
|
||||
case 320:
|
||||
case 352:
|
||||
case 384:
|
||||
default:
|
||||
AssertFatal(false , "BG %d Zc %d is not supported yet\n", BG, Zc);
|
||||
}
|
||||
} else
|
||||
AssertFatal(false, "BG %d is not supported\n", BG);
|
||||
}
|
||||
@@ -0,0 +1,194 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: LicenseRef-CSSL-1.0
|
||||
*/
|
||||
|
||||
/*! \file ldpc_encoder_cuda32.c
|
||||
* \brief Defines the optimized LDPC encoder for NVidia GPUs
|
||||
* \email openair_tech@eurecom.fr
|
||||
* \date 11-30-2025
|
||||
* \version 1.0
|
||||
* \note
|
||||
* \warning
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "assertions.h"
|
||||
#include "common/utils/LOG/log.h"
|
||||
#include "time_meas.h"
|
||||
#include "openair1/PHY/CODING/nrLDPC_defs.h"
|
||||
#include "PHY/sse_intrin.h"
|
||||
#include "openair1/PHY/CODING/nrLDPC_extern.h"
|
||||
|
||||
#include <cuda_runtime.h>
|
||||
|
||||
//#define DEBUG_LDPC 1
|
||||
|
||||
#include "ldpc_encode_parity_check_cuda.c"
|
||||
|
||||
uint32_t *c_dev;
|
||||
uint32_t **c_host;
|
||||
uint32_t *c_devh[4];
|
||||
uint32_t *d_dev;
|
||||
uint32_t **d_host;
|
||||
uint32_t *d_devh[4];
|
||||
uint32_t *input_dev;
|
||||
uint32_t **input_host;
|
||||
uint32_t *input_devh[128];
|
||||
int managed = 0, concurrent = 0, uva = 0, pageable = 0, pageable_uses_host = 0, register_host = 0, integrated = 0;
|
||||
|
||||
int cuda_support_set = 0;
|
||||
|
||||
extern cudaStream_t encoderStreams[4];
|
||||
|
||||
int ldpc_input(uint32_t **input,uint32_t *cc[4],int nseg,cudaStream_t *s,int sidx);
|
||||
|
||||
void cuda_support_init() {
|
||||
|
||||
int dev = 0;
|
||||
struct cudaDeviceProp prop;
|
||||
cudaGetDeviceProperties(&prop, dev);
|
||||
|
||||
|
||||
cudaDeviceGetAttribute(&managed, cudaDevAttrManagedMemory, dev);
|
||||
cudaDeviceGetAttribute(&concurrent, cudaDevAttrConcurrentManagedAccess, dev);
|
||||
cudaDeviceGetAttribute(&uva, cudaDevAttrUnifiedAddressing, dev);
|
||||
cudaDeviceGetAttribute(&pageable, cudaDevAttrPageableMemoryAccess, dev);
|
||||
cudaDeviceGetAttribute(&pageable_uses_host, cudaDevAttrPageableMemoryAccessUsesHostPageTables, dev);
|
||||
cudaDeviceGetAttribute(®ister_host, cudaDevAttrHostRegisterSupported,dev);
|
||||
cudaDeviceGetAttribute(&integrated, cudaDevAttrIntegrated,dev);
|
||||
|
||||
LOG_I(NR_PHY,"Device: %s (cc %d.%d)\n", prop.name, prop.major, prop.minor);
|
||||
LOG_I(NR_PHY,"Unified Virtual Addressing (UVA): %s\n", uva ? "YES" : "NO");
|
||||
LOG_I(NR_PHY,"Managed (Unified) Memory: %s\n", managed ? "YES" : "NO");
|
||||
LOG_I(NR_PHY,"Concurrent managed access: %s\n", concurrent ? "YES" : "NO");
|
||||
LOG_I(NR_PHY,"Pageable memory access: %s\n", pageable ? "YES" : "NO");
|
||||
LOG_I(NR_PHY,"Uses host page tables: %s\n", pageable_uses_host ? "YES" : "NO");
|
||||
LOG_I(NR_PHY,"Host Register supported: %s\n", register_host ? "YES" : "NO");
|
||||
LOG_I(NR_PHY,"Integrated (shared) Memory %s\n", integrated ? "YES" : "NO");
|
||||
|
||||
if (!pageable && !integrated) {
|
||||
LOG_I(NR_PHY,"Allocating c,d,cc arrays for GPU \n");
|
||||
cudaError_t err=cudaMalloc((void **)&c_dev,4*sizeof(uint32_t*));
|
||||
AssertFatal(err == cudaSuccess,"CUDA Error (c_dev): %s\n", cudaGetErrorString(err));
|
||||
err=cudaHostAlloc((void **)&c_host,4*sizeof(uint32_t*),cudaHostAllocDefault);
|
||||
AssertFatal(err == cudaSuccess,"CUDA Error (c_host): %s\n", cudaGetErrorString(err));
|
||||
for (int i=0;i<4;i++) {
|
||||
err=cudaMalloc((void**)&c_devh[i],2*22*384*sizeof(uint32_t));
|
||||
AssertFatal(err == cudaSuccess,"CUDA Error (c_devh[%d]): %s\n", i,cudaGetErrorString(err));
|
||||
err=cudaHostAlloc((void**)&c_host[i],2*22*384*sizeof(uint32_t),cudaHostAllocDefault);
|
||||
AssertFatal(err == cudaSuccess,"CUDA Error (chost[%d]): %s\n", i,cudaGetErrorString(err));
|
||||
}
|
||||
err = cudaMemcpy(c_dev,c_devh,4*sizeof(uint32_t*),cudaMemcpyHostToDevice);
|
||||
AssertFatal(err == cudaSuccess,"CUDA Error (memcpy c_devh -> c_dev): %s\n", cudaGetErrorString(err));
|
||||
err=cudaMalloc((void**)&d_dev,4*sizeof(uint32_t*));
|
||||
AssertFatal(err == cudaSuccess,"CUDA Error: %s\n", cudaGetErrorString(err));
|
||||
err=cudaHostAlloc((void **)&d_host,4*sizeof(uint32_t*),cudaHostAllocDefault);
|
||||
AssertFatal(err == cudaSuccess,"CUDA Error (d_host): %s\n", cudaGetErrorString(err));
|
||||
for (int i=0;i<4;i++) {
|
||||
err=cudaMalloc((void**)&d_devh[i],68*384*sizeof(uint32_t));
|
||||
AssertFatal(err == cudaSuccess,"CUDA Error (d_devh[%d]: %s\n", i,cudaGetErrorString(err));
|
||||
err=cudaHostAlloc((void**)&d_host[i],68*384*sizeof(uint32_t),cudaHostAllocDefault);
|
||||
AssertFatal(err == cudaSuccess,"CUDA Error (d_host[%d]): %s\n", i,cudaGetErrorString(err));
|
||||
}
|
||||
err=cudaMemcpy(d_dev,d_devh,4*sizeof(uint32_t*),cudaMemcpyHostToDevice);
|
||||
AssertFatal(err == cudaSuccess,"CUDA Error (memcpy d_devh -> d_dev): %s\n", cudaGetErrorString(err));
|
||||
err=cudaMalloc((void**)&input_dev,128*sizeof(uint8_t*));
|
||||
AssertFatal(err == cudaSuccess,"CUDA Error: %s\n", cudaGetErrorString(err));
|
||||
err=cudaHostAlloc((void **)&input_host,128*sizeof(uint8_t*),cudaHostAllocDefault);
|
||||
AssertFatal(err == cudaSuccess,"CUDA Error (cc_host): %s\n", cudaGetErrorString(err));
|
||||
for (int i=0;i<128;i++) {
|
||||
err=cudaMalloc((void**)&input_devh[i],(8448/8)*sizeof(uint8_t));
|
||||
AssertFatal(err == cudaSuccess,"CUDA Error (input_devh[%d]: %s\n", i,cudaGetErrorString(err));
|
||||
err=cudaHostAlloc((void**)&input_host[i],(8448/8)*sizeof(uint8_t),cudaHostAllocDefault);
|
||||
AssertFatal(err == cudaSuccess,"CUDA Error (input_host[%d]): %s\n", i,cudaGetErrorString(err));
|
||||
}
|
||||
err=cudaMemcpy(input_dev,input_devh,128*sizeof(uint8_t*),cudaMemcpyHostToDevice);
|
||||
AssertFatal(err == cudaSuccess,"CUDA Error (memcpy cc_devh -> d_dev): %s\n", cudaGetErrorString(err));
|
||||
}
|
||||
else {
|
||||
LOG_I(NR_PHY,"Allocating c,d,cc arrays for CPU/GPU shared-memory\n");
|
||||
cudaError_t err=cudaHostAlloc((void **)&c_host,4*sizeof(uint32_t*),cudaHostAllocMapped|cudaHostAllocPortable);
|
||||
AssertFatal(err == cudaSuccess,"CUDA Error (c_host): %s\n", cudaGetErrorString(err));
|
||||
err = cudaHostGetDevicePointer((void**)&c_dev, c_host, 0);
|
||||
AssertFatal(err == cudaSuccess,"CUDA Error (c_dev): %s\n", cudaGetErrorString(err));
|
||||
LOG_I(NR_PHY,"c_host %p, c_dev %p\n",c_host,c_dev);
|
||||
for (int i=0;i<4;i++) {
|
||||
err=cudaHostAlloc((void**)&c_host[i],2*22*384*sizeof(uint32_t),cudaHostAllocMapped);
|
||||
AssertFatal(err == cudaSuccess,"CUDA Error (c_host[%d]): %s\n", i,cudaGetErrorString(err));
|
||||
err = cudaHostGetDevicePointer((void**)&c_devh[i], c_host[i], 0);
|
||||
AssertFatal(err == cudaSuccess,"CUDA Error (c_devh[%d]): %s\n", i,cudaGetErrorString(err));
|
||||
}
|
||||
err=cudaMemcpy(c_dev,c_devh,4*sizeof(uint32_t*),cudaMemcpyHostToDevice);
|
||||
AssertFatal(err == cudaSuccess,"CUDA Error (memcpy c_devh -> c_dev): %s\n", cudaGetErrorString(err));
|
||||
err=cudaHostAlloc((void **)&d_host,4*sizeof(uint32_t*),cudaHostAllocMapped);
|
||||
AssertFatal(err == cudaSuccess,"CUDA Error (d_host): %s\n", cudaGetErrorString(err));
|
||||
err=cudaHostGetDevicePointer((void**)&d_dev, d_host, 0);
|
||||
AssertFatal(err == cudaSuccess,"CUDA Error cudaHostGetDevicePointer(d_dev): %s\n", cudaGetErrorString(err));
|
||||
LOG_I(NR_PHY,"d_host %p, d_dev %p\n",d_host,d_dev);
|
||||
for (int i=0;i<4;i++) {
|
||||
err=cudaHostAlloc((void**)&d_host[i],68*384*sizeof(uint32_t),cudaHostAllocMapped);
|
||||
AssertFatal(err == cudaSuccess,"CUDA Error (d_host[%d]): %s\n", i,cudaGetErrorString(err));
|
||||
err=cudaHostGetDevicePointer((void**)&d_devh[i], d_host[i], 0);
|
||||
AssertFatal(err == cudaSuccess,"CUDA Error (cudaHostGetDevicePointer) d_devh[%d]: %s\n", i,cudaGetErrorString(err));
|
||||
LOG_I(NR_PHY,"d_host[%d] %p, d_devh[%d] %p\n",i,d_host[i],i,d_devh[i]);
|
||||
}
|
||||
err=cudaMemcpy(d_dev,d_devh,4*sizeof(uint32_t*),cudaMemcpyHostToDevice);
|
||||
AssertFatal(err == cudaSuccess,"CUDA Error (memcpy d_devh -> d_dev): %s\n", cudaGetErrorString(err));
|
||||
err=cudaHostAlloc((void **)&input_host,128*sizeof(uint8_t*),cudaHostAllocMapped);
|
||||
AssertFatal(err == cudaSuccess,"CUDA Error (input_host): %s\n", cudaGetErrorString(err));
|
||||
err=cudaHostGetDevicePointer((void**)&input_dev, input_host, 0);
|
||||
AssertFatal(err == cudaSuccess,"CUDA Error cudaHostGetDevicePointer(cc_host): %s\n", cudaGetErrorString(err));
|
||||
LOG_I(NR_PHY,"input_host %p, input_dev %p\n",input_host,input_dev);
|
||||
}
|
||||
|
||||
|
||||
cuda_support_set=1;
|
||||
}
|
||||
|
||||
uint32_t **LDPCencoder32(uint8_t **input, encoder_implemparams_t *impp)
|
||||
{
|
||||
//set_log(PHY, 4);
|
||||
|
||||
int Zc = impp->Zc;
|
||||
int Kb = impp->Kb;
|
||||
short block_length = impp->K;
|
||||
short BG = impp->BG;
|
||||
int ncols=22;
|
||||
|
||||
int encoder_stream=0;
|
||||
|
||||
AssertFatal(BG==1,"BG %d is not supported for CUDA version\n",BG);
|
||||
AssertFatal(Zc==384,"Zc %d is not supported for CUDA version \n", Zc);
|
||||
|
||||
if(impp->tinput != NULL) start_meas(impp->tinput);
|
||||
|
||||
#ifdef DEBUG_LDPC
|
||||
LOG_I(PHY,"ldpc_encoder_cuda32: BG %d, Zc %d, Kb %d, block_length %d, segments %d\n",BG,Zc,Kb,block_length,impp->n_segments);
|
||||
LOG_I(PHY,"ldpc_encoder_cuda32: PDU (seg 0) %x %x %x %x\n",input[0][0],input[0][1],input[0][2],input[0][3]);
|
||||
#endif
|
||||
|
||||
int n_inputs = (impp->n_segments/32)+(((impp->n_segments&31) > 0) ? 1: 0);
|
||||
// uint32_t cc[4][22*Zc]; //padded input, unpacked, max size
|
||||
|
||||
if (!pageable&&!integrated) { // this means we are not on shared memory
|
||||
for (int r=0;r<impp->n_segments;r++) {
|
||||
cudaMemcpyAsync(input_devh[r],input[r],block_length>>3,cudaMemcpyHostToDevice,encoderStreams[encoder_stream]);
|
||||
}
|
||||
}
|
||||
ldpc_input(pageable||integrated? (uint32_t**)input : (uint32_t**)input_dev,(uint32_t**)c_dev,impp->n_segments,encoderStreams,encoder_stream);
|
||||
if(impp->tinput != NULL) stop_meas(impp->tinput);
|
||||
//parity check part
|
||||
if(impp->tparity != NULL) start_meas(impp->tparity);
|
||||
encode_parity_check_part_cuda((uint32_t**)c_dev, (uint32_t**)d_dev, BG, Zc, Kb, ncols,n_inputs,encoderStreams,encoder_stream);
|
||||
if (!pageable&&!integrated) { // this means we are not on shared memory
|
||||
for (int r=0; r<n_inputs;r++) cudaMemcpyAsync(d_host[r],d_devh[r],68*384*sizeof(uint32_t),cudaMemcpyDeviceToHost,encoderStreams[encoder_stream]);
|
||||
}
|
||||
cudaStreamSynchronize(encoderStreams[encoder_stream]);
|
||||
if(impp->tparity != NULL) stop_meas(impp->tparity);
|
||||
|
||||
return d_host;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,92 @@
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <cuda_runtime.h>
|
||||
/*
|
||||
__device__ const uint32_t masks[4] = {0x80,0x8000,0x800000,0x80000000};
|
||||
__global__ void ldpc_input_worker(uint32_t **input,uint32_t *cc[4],int block_length,int nseg) {
|
||||
|
||||
int block_off = blockIdx.x*blockDim.x<<2;
|
||||
int i2 = threadIdx.x<<2;
|
||||
uint32_t *out=cc[blockIdx.y] + block_off + i2;
|
||||
int nseg0 = (blockIdx.y << 5);
|
||||
int nseg1;
|
||||
if ((nseg0 + 32) <= nseg) nseg1 = nseg0+32;
|
||||
else nseg1 = nseg0 + (nseg&31);
|
||||
int bit_offset = i2+block_off;
|
||||
int uint32_offset = bit_offset>>5;
|
||||
uint32_t mask = masks[(bit_offset&31)>>3];
|
||||
uint32_t mask0 = mask>>(bit_offset&7);bit_offset++;
|
||||
uint32_t mask1 = mask>>(bit_offset&7);bit_offset++;
|
||||
uint32_t mask2 = mask>>(bit_offset&7);bit_offset++;
|
||||
uint32_t mask3 = mask>>(bit_offset&7);
|
||||
uint32_t tmp,jmod;
|
||||
uint32_t otmp0,otmp1,otmp2,otmp3;
|
||||
if (bit_offset < block_length) {
|
||||
tmp=input[nseg0][uint32_offset];
|
||||
otmp0 = ((tmp&mask0) > 0);
|
||||
otmp1 = ((tmp&mask1) > 0);
|
||||
otmp2 = ((tmp&mask2) > 0);
|
||||
otmp3 = ((tmp&mask3) > 0);
|
||||
for (int j=nseg0+1;j<nseg1;j++) {
|
||||
tmp=input[j][uint32_offset];
|
||||
jmod = j&31;
|
||||
otmp0 |= (((tmp&mask0) > 0)<<jmod);
|
||||
otmp1 |= (((tmp&mask1) > 0)<<jmod);
|
||||
otmp2 |= (((tmp&mask2) > 0)<<jmod);
|
||||
otmp3 |= (((tmp&mask3) > 0)<<jmod);
|
||||
}
|
||||
out[0]=otmp0;
|
||||
out[1]=otmp1;
|
||||
out[2]=otmp2;
|
||||
out[3]=otmp3;
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
__device__ uint32_t masks[32] = {
|
||||
0x80,0x40,0x20,0x10,0x8,0x4,0x2,0x1,
|
||||
0x8000,0x4000,0x2000,0x1000,0x800,0x400,0x200,0x100,
|
||||
0x800000,0x400000,0x200000,0x100000,0x80000,0x40000,0x20000,0x10000,
|
||||
0x80000000,0x40000000,0x20000000,0x10000000,0x8000000,0x4000000,0x2000000,0x1000000};
|
||||
__global__ void ldpc_input_worker(uint32_t **input,uint32_t *cc[4],int nseg) {
|
||||
|
||||
// int block_off = blockIdx.y*blockDim.x;
|
||||
int i1 = blockIdx.y;
|
||||
int i2 = threadIdx.x;
|
||||
int nseg0 = (blockIdx.x << 5);
|
||||
int nseg1;
|
||||
if ((nseg0 + 32) <= nseg) nseg1 = nseg0+32;
|
||||
else nseg1 = nseg0 + (nseg&31);
|
||||
int bit_offset = i2+(i1*384);
|
||||
int uint32_offset = bit_offset>>5;
|
||||
uint32_t mask0 = masks[bit_offset&31];
|
||||
uint32_t tmp,jmod;
|
||||
uint32_t otmp0;
|
||||
if (bit_offset < 8448) {
|
||||
tmp=input[nseg0][uint32_offset];
|
||||
otmp0 = ((tmp&mask0) > 0);
|
||||
for (int j=nseg0+1;j<nseg1;j++) {
|
||||
tmp=input[j][uint32_offset];
|
||||
jmod = j&31;
|
||||
otmp0 |= (((tmp&mask0) > 0)<<jmod);
|
||||
}
|
||||
|
||||
cc[blockIdx.x][(2*i1*384) + i2] = otmp0;
|
||||
cc[blockIdx.x][(2*i1+1)*384 + i2]=otmp0;
|
||||
}
|
||||
}
|
||||
extern "C" int ldpc_input(uint32_t **input,uint32_t *cc[4],int nseg,cudaStream_t *stream,int sidx) {
|
||||
|
||||
int ns = nseg>>5;
|
||||
if ((nseg&31)>0) ns++;
|
||||
|
||||
dim3 numblocks(ns,22);
|
||||
//printf("input %p\n",input);
|
||||
ldpc_input_worker<<<numblocks,384,0,stream[sidx]>>>(input,cc,nseg);
|
||||
cudaError_t err=cudaPeekAtLastError();
|
||||
if (err!=cudaSuccess) {
|
||||
printf("cuda error: %s (input %p, cc %p, nseg %d, ns %d)\n",cudaGetErrorString(err),input,cc,nseg,ns);
|
||||
exit(-1);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
@@ -0,0 +1,492 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: LicenseRef-CSSL-1.0
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "assertions.h"
|
||||
#include "common/utils/LOG/log.h"
|
||||
#include "openair1/PHY/CODING/nrLDPC_defs.h"
|
||||
#include "PHY/sse_intrin.h"
|
||||
#include "openair1/PHY/CODING/nrLDPC_extern.h"
|
||||
|
||||
|
||||
void ldpc_input32(uint8_t **input, uint32_t **c, int n_inputs, int n_segments) {
|
||||
|
||||
#ifndef __aarch64__
|
||||
simde__m256i andmask = simde_mm256_set_epi32(0x1,0x2,0x4,0x8,0x10,0x20,0x40,0x80); // every 8 bits -> 8 bytes, pattern repeats.
|
||||
simde__m256i zero256 = simde_mm256_setzero_si256();
|
||||
simde__m256i masks[32];
|
||||
register simde__m256i c256;
|
||||
for (int i=0;i<32;i++) {
|
||||
masks[i] = simde_mm256_set1_epi32(1<<i);
|
||||
}
|
||||
|
||||
for (int b=0;b<8448;b+=384) {
|
||||
for (int i=0; i < 384; i += 8) {
|
||||
unsigned int i8 = (2*b + i) >> 3;
|
||||
for (int j0=0;j0<n_inputs;j0++) {
|
||||
c256 = simde_mm256_and_si256(simde_mm256_cmpeq_epi32(simde_mm256_andnot_si256(simde_mm256_set1_epi32(input[j0<<5][i8]),andmask),zero256),masks[0]);
|
||||
int j2 = 32;
|
||||
if (j0==(n_inputs-1)) j2= n_segments-(j0<<5);
|
||||
for (int j=1; j < j2; j++) {
|
||||
c256 = simde_mm256_or_si256(simde_mm256_and_si256(simde_mm256_cmpeq_epi32(simde_mm256_andnot_si256(simde_mm256_set1_epi32(input[(j0<<5)+j][i8]),andmask),zero256),masks[j]),c256);
|
||||
}
|
||||
((simde__m256i *)c[j0])[i8] = c256;
|
||||
((simde__m256i *)c[j0])[i8+48] = c256;
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
int i2=0;
|
||||
uint32_t cc[4][8448];
|
||||
const int32_t ucShifta[32][4] = {
|
||||
{-7,-6,-5,-4}, // 0
|
||||
{-6,-5,-4,-3}, // 1
|
||||
{-5,-4,-3,-2}, // 2
|
||||
{-4,-3,-2,-1}, // 3
|
||||
{-3,-2,-1,0}, // 4
|
||||
{-2,-1,0,1}, // 5
|
||||
{-1,0,1,2}, // 6
|
||||
{0,1,2,3}, // 7
|
||||
{1,2,3,4}, // 8
|
||||
{2,3,4,5}, // 9
|
||||
{3,4,5,6}, // 10
|
||||
{4,5,6,7}, // 11
|
||||
{5,6,7,8}, // 12
|
||||
{6,7,8,9}, // 13
|
||||
{7,8,9,10}, // 14
|
||||
{8,9,10,11}, // 15
|
||||
{9,10,11,12}, // 16
|
||||
{10,11,12,13}, // 17
|
||||
{11,12,13,14}, // 18
|
||||
{12,13,14,15}, // 19
|
||||
{13,14,15,16}, // 20
|
||||
{14,15,16,17}, // 21
|
||||
{15,16,17,18}, // 22
|
||||
{16,17,18,19}, // 23
|
||||
{17,18,19,20}, // 24
|
||||
{18,19,20,21}, // 25
|
||||
{19,20,21,22}, // 26
|
||||
{20,21,22,23}, // 27
|
||||
{21,22,23,24}, // 28
|
||||
{22,23,24,25}, // 29
|
||||
{23,24,25,26}, // 30
|
||||
{24,25,26,27}}; // 31
|
||||
const int32_t ucShiftb[32][4] = {
|
||||
{-3,-2,-1,0}, // 0
|
||||
{-2,-1,0,1}, // 1
|
||||
{-1,0,1,2}, // 2
|
||||
{0,1,2,3}, // 3
|
||||
{1,2,3,4}, // 4
|
||||
{2,3,4,5}, // 5
|
||||
{3,4,5,6}, // 6
|
||||
{4,5,6,7}, // 7
|
||||
{5,6,7,8}, // 8
|
||||
{6,7,8,9}, // 9
|
||||
{7,8,9,10}, // 10
|
||||
{8,9,10,11}, // 11
|
||||
{9,10,11,12}, // 12
|
||||
{10,11,12,13}, // 13
|
||||
{11,12,13,14}, // 14
|
||||
{12,13,14,15}, // 15
|
||||
{13,14,15,16}, // 16
|
||||
{14,15,16,17}, // 17
|
||||
{15,16,17,18}, // 18
|
||||
{16,17,18,19}, // 19
|
||||
{17,18,19,20}, // 20
|
||||
{18,19,20,21}, // 21
|
||||
{19,20,21,22}, // 22
|
||||
{20,21,22,23}, // 23
|
||||
{21,22,23,24}, // 24
|
||||
{22,23,24,25}, // 25
|
||||
{23,24,25,26}, // 26
|
||||
{24,25,26,27}, // 27
|
||||
{25,26,27,28}, // 28
|
||||
{26,27,28,29}, // 29
|
||||
{27,28,29,30}, // 30
|
||||
{28,29,30,31}}; // 31
|
||||
|
||||
const int32_t ucShiftc[32][4] = {
|
||||
{-15,-14,-13,-12}, // 0
|
||||
{-14,-13,-12,-11}, // 1
|
||||
{-13,-12,-11,-10}, // 2
|
||||
{-12,-11,-10,-9}, // 3
|
||||
{-11,-10,-9,-8}, // 4
|
||||
{-10,-9,-8,-7}, // 5
|
||||
{-9,-8,-7,-6}, // 6
|
||||
{-8,-7,-6,-5}, // 7
|
||||
{-7,-6,-5,-4}, // 8
|
||||
{-6,-5,-4,-3}, // 9
|
||||
{-5,-4,-3,-2}, // 10
|
||||
{-4,-3,-2,-1}, // 11
|
||||
{-3,-2,-1,0}, // 12
|
||||
{-2,-1,0,1}, // 13
|
||||
{-1,0,1,2}, // 14
|
||||
{0,1,2,3}, // 15
|
||||
{1,2,3,4}, // 16
|
||||
{2,3,4,5}, // 17
|
||||
{3,4,5,6}, // 18
|
||||
{4,5,6,7}, // 19
|
||||
{5,6,7,8}, // 20
|
||||
{6,7,8,9}, // 21
|
||||
{7,8,9,10}, // 22
|
||||
{8,9,10,11}, // 23
|
||||
{9,10,11,12}, // 24
|
||||
{10,11,12,13}, // 25
|
||||
{11,12,13,14}, // 26
|
||||
{12,13,14,15}, // 27
|
||||
{13,14,15,16}, // 28
|
||||
{14,15,16,17}, // 29
|
||||
{15,16,17,18}, // 30
|
||||
{16,17,18,19}}; // 31
|
||||
const int32_t ucShiftd[32][4] = {
|
||||
{-11,-10,-9,-8}, // 0
|
||||
{-10,-9,-8,-7}, // 1
|
||||
{-9,-8,-7,-6}, // 2
|
||||
{-8,-7,-6,-5}, // 3
|
||||
{-7,-6,-5,-4}, // 4
|
||||
{-6,-5,-4,-3}, // 5
|
||||
{-5,-4,-3,-2}, // 6
|
||||
{-4,-3,-2,-1}, // 7
|
||||
{-3,-2,-1,0}, // 8
|
||||
{-2,-1,0,1}, // 9
|
||||
{-1,0,1,2}, // 10
|
||||
{0,1,2,3}, // 11
|
||||
{1,2,3,4}, // 12
|
||||
{2,3,4,5}, // 13
|
||||
{3,4,5,6}, // 14
|
||||
{4,5,6,7}, // 15
|
||||
{5,6,7,8}, // 16
|
||||
{6,7,8,9}, // 17
|
||||
{7,8,9,10}, // 18
|
||||
{8,9,10,11}, // 19
|
||||
{9,10,11,12}, // 20
|
||||
{10,11,12,13}, // 21
|
||||
{11,12,13,14}, // 22
|
||||
{12,13,14,15}, // 23
|
||||
{13,14,15,16}, // 24
|
||||
{14,15,16,17}, // 25
|
||||
{15,16,17,18}, // 26
|
||||
{16,17,18,19}, // 27
|
||||
{17,18,19,20}, // 28
|
||||
{18,19,20,21}, // 29
|
||||
{19,20,21,22}, // 30
|
||||
{20,21,22,23}};// 31
|
||||
|
||||
const int32_t ucShifte[32][4] = {
|
||||
{-23,-22,-21,-20}, // 0
|
||||
{-22,-21,-20,-19}, // 1
|
||||
{-21,-20,-19,-18}, // 2
|
||||
{-20,-19,-18,-17}, // 3
|
||||
{-19,-18,-17,-16}, // 4
|
||||
{-18,-17,-16,-15}, // 5
|
||||
{-17,-16,-15,-14}, // 6
|
||||
{-16,-15,-14,-13}, // 7
|
||||
{-15,-14,-13,-12}, // 8
|
||||
{-14,-13,-12,-11}, // 9
|
||||
{-13,-12,-11,-10}, // 10
|
||||
{-12,-11,-10,-9}, // 11
|
||||
{-11,-10,-9,-8}, // 12
|
||||
{-10,-9,-8,-7}, // 13
|
||||
{-9,-8,-7,-6}, // 14
|
||||
{-8,-7,-6,-5}, // 15
|
||||
{-7,-6,-5,-4}, // 16
|
||||
{-6,-5,-4,-3}, // 17
|
||||
{-5,-4,-3,-2}, // 18
|
||||
{-4,-3,-2,-1}, // 19
|
||||
{-3,-2,-1,0}, // 20
|
||||
{-2,-1,0,1}, // 21
|
||||
{-1,0,1,2}, // 22
|
||||
{0,1,2,3}, // 23
|
||||
{1,2,3,4}, // 24
|
||||
{2,3,4,5}, // 25
|
||||
{3,4,5,6}, // 26
|
||||
{4,5,6,7}, // 27
|
||||
{5,6,7,8}, // 28
|
||||
{6,7,8,9}, // 29
|
||||
{7,8,9,10}, // 30
|
||||
{8,9,10,11}}; // 31
|
||||
|
||||
const int32_t ucShiftf[32][4] = {
|
||||
{-19,-18,-17,-16}, // 0
|
||||
{-18,-17,-16,-15}, // 1
|
||||
{-17,-16,-15,-14}, // 2
|
||||
{-16,-15,-14,-13}, // 3
|
||||
{-15,-14,-13,-12}, // 4
|
||||
{-14,-13,-12,-11}, // 5
|
||||
{-13,-12,-11,-10}, // 6
|
||||
{-12,-11,-10,-9}, // 7
|
||||
{-11,-10,-9,-8}, // 8
|
||||
{-10,-9,-8,-7}, // 9
|
||||
{-9,-8,-7,-6}, // 10
|
||||
{-8,-7,-6,-5}, // 11
|
||||
{-7,-6,-5,-4}, // 12
|
||||
{-6,-5,-4,-3}, // 13
|
||||
{-5,-4,-3,-2}, // 14
|
||||
{-4,-3,-2,-1}, // 15
|
||||
{-3,-2,-1,0}, // 16
|
||||
{-2,-1,0,1}, // 17
|
||||
{-1,0,1,2}, // 18
|
||||
{0,1,2,3}, // 19
|
||||
{1,2,3,4}, // 20
|
||||
{2,3,4,5}, // 21
|
||||
{3,4,5,6}, // 22
|
||||
{4,5,6,7}, // 23
|
||||
{5,6,7,8}, // 24
|
||||
{6,7,8,9}, // 25
|
||||
{7,8,9,10}, // 26
|
||||
{8,9,10,11}, // 27
|
||||
{9,10,11,12}, // 28
|
||||
{10,11,12,13}, // 29
|
||||
{11,12,13,14}, // 30
|
||||
{12,13,14,15}}; // 31
|
||||
|
||||
const int32_t ucShiftg[32][4] = {
|
||||
{-31,-30,-29,-28},
|
||||
{-30,-29,-28,-27},
|
||||
{-29,-28,-27,-26},
|
||||
{-28,-27,-26,-25},
|
||||
{-27,-26,-25,-24},
|
||||
{-26,-25,-24,-23},
|
||||
{-25,-24,-23,-22},
|
||||
{-24,-23,-22,-21},
|
||||
{-23,-22,-21,-20}, // 0
|
||||
{-22,-21,-20,-19}, // 1
|
||||
{-21,-20,-19,-18}, // 2
|
||||
{-20,-19,-18,-17}, // 3
|
||||
{-19,-18,-17,-16}, // 4
|
||||
{-18,-17,-16,-15}, // 5
|
||||
{-17,-16,-15,-14}, // 6
|
||||
{-16,-15,-14,-13}, // 7
|
||||
{-15,-14,-13,-12}, // 8
|
||||
{-14,-13,-12,-11}, // 9
|
||||
{-13,-12,-11,-10}, // 10
|
||||
{-12,-11,-10,-9}, // 11
|
||||
{-11,-10,-9,-8}, // 12
|
||||
{-10,-9,-8,-7}, // 13
|
||||
{-9,-8,-7,-6}, // 14
|
||||
{-8,-7,-6,-5}, // 15
|
||||
{-7,-6,-5,-4}, // 16
|
||||
{-6,-5,-4,-3}, // 17
|
||||
{-5,-4,-3,-2}, // 18
|
||||
{-4,-3,-2,-1}, // 19
|
||||
{-3,-2,-1,0}, // 20
|
||||
{-2,-1,0,1}, // 21
|
||||
{-1,0,1,2}, // 22
|
||||
{0,1,2,3}}; // 23
|
||||
|
||||
const int32_t ucShifth[32][4] = {
|
||||
{-27,-26,-25,-24}, // 0
|
||||
{-26,-25,-24,-23}, // 1
|
||||
{-25,-24,-23,-22}, // 2
|
||||
{-24,-23,-22,-21}, // 3
|
||||
{-23,-22,-21,-20}, // 4
|
||||
{-22,-21,-20,-19}, // 5
|
||||
{-21,-20,-19,-18}, // 6
|
||||
{-20,-19,-18,-17}, // 7
|
||||
{-19,-18,-17,-16}, // 8
|
||||
{-18,-17,-16,-15}, // 9
|
||||
{-17,-16,-15,-14}, // 10
|
||||
{-16,-15,-14,-13}, // 11
|
||||
{-15,-14,-13,-12}, // 12
|
||||
{-14,-13,-12,-11}, // 13
|
||||
{-13,-12,-11,-10}, // 14
|
||||
{-12,-11,-10,-9}, // 15
|
||||
{-11,-10,-9,-8}, // 16
|
||||
{-10,-9,-8,-7}, // 17
|
||||
{-9,-8,-7,-6}, // 18
|
||||
{-8,-7,-6,-5}, // 19
|
||||
{-7,-6,-5,-4}, // 20
|
||||
{-6,-5,-4,-3}, // 21
|
||||
{-5,-4,-3,-2}, // 22
|
||||
{-4,-3,-2,-1}, // 23
|
||||
{-3,-2,-1,0}, // 24
|
||||
{-2,-1,0,1}, // 25
|
||||
{-1,0,1,2}, // 26
|
||||
{0,1,2,3}, // 27
|
||||
{1,2,3,4}, // 28
|
||||
{2,3,4,5}, // 29
|
||||
{3,4,5,6}, // 30
|
||||
{4,5,6,7}}; // 31
|
||||
const uint32_t __attribute__ ((aligned (16))) masksa[4] = {0x80,0x40,0x20,0x10};
|
||||
const uint32_t __attribute__ ((aligned (16))) masksb[4] = {0x8,0x4,0x2,0x1};
|
||||
const uint32_t __attribute__ ((aligned (16))) masksc[4] = {0x8000,0x4000,0x2000,0x1000};
|
||||
const uint32_t __attribute__ ((aligned (16))) masksd[4] = {0x800,0x400,0x200,0x100};
|
||||
const uint32_t __attribute__ ((aligned (16))) maskse[4] = {0x800000,0x400000,0x200000,0x100000};
|
||||
const uint32_t __attribute__ ((aligned (16))) masksf[4] = {0x80000,0x40000,0x20000,0x10000};
|
||||
const uint32_t __attribute__ ((aligned (16))) masksg[4] = {0x80000000,0x40000000,0x20000000,0x10000000};
|
||||
const uint32_t __attribute__ ((aligned (16))) masksh[4] = {0x8000000,0x4000000,0x2000000,0x1000000};
|
||||
int32x4_t vshifta[32],vshiftb[32],vshiftc[32],vshiftd[32],vshifte[32],vshiftf[32],vshiftg[32],vshifth[32];
|
||||
uint32x4_t vmasksa = vld1q_u32(masksa);
|
||||
uint32x4_t vmasksb = vld1q_u32(masksb);
|
||||
uint32x4_t vmasksc = vld1q_u32(masksc);
|
||||
uint32x4_t vmasksd = vld1q_u32(masksd);
|
||||
uint32x4_t vmaskse = vld1q_u32(maskse);
|
||||
uint32x4_t vmasksf = vld1q_u32(masksf);
|
||||
uint32x4_t vmasksg = vld1q_u32(masksg);
|
||||
uint32x4_t vmasksh = vld1q_u32(masksh);
|
||||
uint32x4_t in;
|
||||
|
||||
for (int n=0;n<32;n++) {
|
||||
vshifta[n] = vld1q_s32(ucShifta[n]);
|
||||
vshiftb[n] = vld1q_s32(ucShiftb[n]);
|
||||
vshiftc[n] = vld1q_s32(ucShiftc[n]);
|
||||
vshiftd[n] = vld1q_s32(ucShiftd[n]);
|
||||
vshifte[n] = vld1q_s32(ucShifte[n]);
|
||||
vshiftf[n] = vld1q_s32(ucShiftf[n]);
|
||||
vshiftg[n] = vld1q_s32(ucShiftg[n]);
|
||||
vshifth[n] = vld1q_s32(ucShifth[n]);
|
||||
}
|
||||
i2=0;
|
||||
int j0=0,j1=0,j2=0,j3=0;
|
||||
if (n_segments <= 32) {
|
||||
j0=n_segments;
|
||||
}
|
||||
else if (n_segments <= 64) {
|
||||
j0=32;
|
||||
j1=n_segments-32;
|
||||
}
|
||||
else if (n_segments <= 96) {
|
||||
j0=32; j1=32;
|
||||
j2=n_segments-64;
|
||||
}
|
||||
else if (n_segments <= 128) {
|
||||
j0=32; j1=32; j2=32;
|
||||
j3=n_segments-96;
|
||||
}
|
||||
uint32x4_t *ccp,cc0,cc1,cc2,cc3,cc4,cc5,cc6,cc7;
|
||||
for (int i=0; i < 264; i++,i2+=8) {
|
||||
in = vdupq_n_u32(((uint32_t*)input[0])[i]);
|
||||
cc0 = vshlq_u32(vandq_u32(in,vmasksa),vshifta[0]);
|
||||
cc1 = vshlq_u32(vandq_u32(in,vmasksb),vshiftb[0]);
|
||||
cc2 = vshlq_u32(vandq_u32(in,vmasksc),vshiftc[0]);
|
||||
cc3 = vshlq_u32(vandq_u32(in,vmasksd),vshiftd[0]);
|
||||
cc4 = vshlq_u32(vandq_u32(in,vmaskse),vshifte[0]);
|
||||
cc5 = vshlq_u32(vandq_u32(in,vmasksf),vshiftf[0]);
|
||||
cc6 = vshlq_u32(vandq_u32(in,vmasksg),vshiftg[0]);
|
||||
cc7 = vshlq_u32(vandq_u32(in,vmasksh),vshifth[0]);
|
||||
for (int j = 1; j < j0; j++) {
|
||||
in = vdupq_n_u32(((uint32_t*)input[j])[i]);
|
||||
cc0 = vorrq_u32(cc0,vshlq_u32(vandq_u32(in,vmasksa),vshifta[j]));
|
||||
cc1 = vorrq_u32(cc1,vshlq_u32(vandq_u32(in,vmasksb),vshiftb[j]));
|
||||
cc2 = vorrq_u32(cc2,vshlq_u32(vandq_u32(in,vmasksc),vshiftc[j]));
|
||||
cc3 = vorrq_u32(cc3,vshlq_u32(vandq_u32(in,vmasksd),vshiftd[j]));
|
||||
cc4 = vorrq_u32(cc4,vshlq_u32(vandq_u32(in,vmaskse),vshifte[j]));
|
||||
cc5 = vorrq_u32(cc5,vshlq_u32(vandq_u32(in,vmasksf),vshiftf[j]));
|
||||
cc6 = vorrq_u32(cc6,vshlq_u32(vandq_u32(in,vmasksg),vshiftg[j]));
|
||||
cc7 = vorrq_u32(cc7,vshlq_u32(vandq_u32(in,vmasksh),vshifth[j]));
|
||||
}
|
||||
ccp=&((uint32x4_t *)cc[0])[i2];
|
||||
ccp[0] = cc0;
|
||||
ccp[1] = cc1;
|
||||
ccp[2] = cc2;
|
||||
ccp[3] = cc3;
|
||||
ccp[4] = cc4;
|
||||
ccp[5] = cc5;
|
||||
ccp[6] = cc6;
|
||||
ccp[7] = cc7;
|
||||
if (j1>0) {
|
||||
in = vdupq_n_u32(((uint32_t*)input[32])[i]);
|
||||
cc0 = vshlq_u32(vandq_u32(in,vmasksa),vshifta[0]);
|
||||
cc1 = vshlq_u32(vandq_u32(in,vmasksb),vshiftb[0]);
|
||||
cc2 = vshlq_u32(vandq_u32(in,vmasksc),vshiftc[0]);
|
||||
cc3 = vshlq_u32(vandq_u32(in,vmasksd),vshiftd[0]);
|
||||
cc4 = vshlq_u32(vandq_u32(in,vmaskse),vshifte[0]);
|
||||
cc5 = vshlq_u32(vandq_u32(in,vmasksf),vshiftf[0]);
|
||||
cc6 = vshlq_u32(vandq_u32(in,vmasksg),vshiftg[0]);
|
||||
cc7 = vshlq_u32(vandq_u32(in,vmasksh),vshifth[0]);
|
||||
for (int j = 1; j < j1; j++) {
|
||||
in = vdupq_n_u32(((uint32_t*)input[32+j])[i]);
|
||||
cc0 = vorrq_u32(cc0,vshlq_u32(vandq_u32(in,vmasksa),vshifta[j]));
|
||||
cc1 = vorrq_u32(cc1,vshlq_u32(vandq_u32(in,vmasksb),vshiftb[j]));
|
||||
cc2 = vorrq_u32(cc2,vshlq_u32(vandq_u32(in,vmasksc),vshiftc[j]));
|
||||
cc3 = vorrq_u32(cc3,vshlq_u32(vandq_u32(in,vmasksd),vshiftd[j]));
|
||||
cc4 = vorrq_u32(cc4,vshlq_u32(vandq_u32(in,vmaskse),vshifte[j]));
|
||||
cc5 = vorrq_u32(cc5,vshlq_u32(vandq_u32(in,vmasksf),vshiftf[j]));
|
||||
cc6 = vorrq_u32(cc6,vshlq_u32(vandq_u32(in,vmasksg),vshiftg[j]));
|
||||
cc7 = vorrq_u32(cc7,vshlq_u32(vandq_u32(in,vmasksh),vshifth[j]));
|
||||
}
|
||||
ccp=&((uint32x4_t *)cc[1])[i2];
|
||||
ccp[0] = cc0;
|
||||
ccp[1] = cc1;
|
||||
ccp[2] = cc2;
|
||||
ccp[3] = cc3;
|
||||
ccp[4] = cc4;
|
||||
ccp[5] = cc5;
|
||||
ccp[6] = cc6;
|
||||
ccp[7] = cc7;
|
||||
}
|
||||
if (j2>0) {
|
||||
in = vdupq_n_u32(((uint32_t*)input[64])[i]);
|
||||
cc0 = vshlq_u32(vandq_u32(in,vmasksa),vshifta[0]);
|
||||
cc1 = vshlq_u32(vandq_u32(in,vmasksb),vshiftb[0]);
|
||||
cc2 = vshlq_u32(vandq_u32(in,vmasksc),vshiftc[0]);
|
||||
cc3 = vshlq_u32(vandq_u32(in,vmasksd),vshiftd[0]);
|
||||
cc4 = vshlq_u32(vandq_u32(in,vmaskse),vshifte[0]);
|
||||
cc5 = vshlq_u32(vandq_u32(in,vmasksf),vshiftf[0]);
|
||||
cc6 = vshlq_u32(vandq_u32(in,vmasksg),vshiftg[0]);
|
||||
cc7 = vshlq_u32(vandq_u32(in,vmasksh),vshifth[0]);
|
||||
for (int j = 1; j < j2; j++) {
|
||||
in = vdupq_n_u32(((uint32_t*)input[64+j])[i]);
|
||||
cc0 = vorrq_u32(cc0,vshlq_u32(vandq_u32(in,vmasksa),vshifta[j]));
|
||||
cc1 = vorrq_u32(cc1,vshlq_u32(vandq_u32(in,vmasksb),vshiftb[j]));
|
||||
cc2 = vorrq_u32(cc2,vshlq_u32(vandq_u32(in,vmasksc),vshiftc[j]));
|
||||
cc3 = vorrq_u32(cc3,vshlq_u32(vandq_u32(in,vmasksd),vshiftd[j]));
|
||||
cc4 = vorrq_u32(cc4,vshlq_u32(vandq_u32(in,vmaskse),vshifte[j]));
|
||||
cc5 = vorrq_u32(cc5,vshlq_u32(vandq_u32(in,vmasksf),vshiftf[j]));
|
||||
cc6 = vorrq_u32(cc6,vshlq_u32(vandq_u32(in,vmasksg),vshiftg[j]));
|
||||
cc7 = vorrq_u32(cc7,vshlq_u32(vandq_u32(in,vmasksh),vshifth[j]));
|
||||
}
|
||||
ccp=&((uint32x4_t *)cc[2])[i2];
|
||||
ccp[0] = cc0;
|
||||
ccp[1] = cc1;
|
||||
ccp[2] = cc2;
|
||||
ccp[3] = cc3;
|
||||
ccp[4] = cc4;
|
||||
ccp[5] = cc5;
|
||||
ccp[6] = cc6;
|
||||
ccp[7] = cc7;
|
||||
}
|
||||
if (j3>0) {
|
||||
in = vdupq_n_u32(((uint32_t*)input[96])[i]);
|
||||
cc0 = vshlq_u32(vandq_u32(in,vmasksa),vshifta[0]);
|
||||
cc1 = vshlq_u32(vandq_u32(in,vmasksb),vshiftb[0]);
|
||||
cc2 = vshlq_u32(vandq_u32(in,vmasksc),vshiftc[0]);
|
||||
cc3 = vshlq_u32(vandq_u32(in,vmasksd),vshiftd[0]);
|
||||
cc4 = vshlq_u32(vandq_u32(in,vmaskse),vshifte[0]);
|
||||
cc5 = vshlq_u32(vandq_u32(in,vmasksf),vshiftf[0]);
|
||||
cc6 = vshlq_u32(vandq_u32(in,vmasksg),vshiftg[0]);
|
||||
cc7 = vshlq_u32(vandq_u32(in,vmasksh),vshifth[0]);
|
||||
for (int j = 1; j < j3; j++) {
|
||||
in = vdupq_n_u32(((uint32_t*)input[96+j])[i]);
|
||||
cc0 = vorrq_u32(cc0,vshlq_u32(vandq_u32(in,vmasksa),vshifta[j]));
|
||||
cc1 = vorrq_u32(cc1,vshlq_u32(vandq_u32(in,vmasksb),vshiftb[j]));
|
||||
cc2 = vorrq_u32(cc2,vshlq_u32(vandq_u32(in,vmasksc),vshiftc[j]));
|
||||
cc3 = vorrq_u32(cc3,vshlq_u32(vandq_u32(in,vmasksd),vshiftd[j]));
|
||||
cc4 = vorrq_u32(cc4,vshlq_u32(vandq_u32(in,vmaskse),vshifte[j]));
|
||||
cc5 = vorrq_u32(cc5,vshlq_u32(vandq_u32(in,vmasksf),vshiftf[j]));
|
||||
cc6 = vorrq_u32(cc6,vshlq_u32(vandq_u32(in,vmasksg),vshiftg[j]));
|
||||
cc7 = vorrq_u32(cc7,vshlq_u32(vandq_u32(in,vmasksh),vshifth[j]));
|
||||
}
|
||||
ccp=&((uint32x4_t *)cc[3])[i2];
|
||||
ccp[0] = cc0;
|
||||
ccp[1] = cc1;
|
||||
ccp[2] = cc2;
|
||||
ccp[3] = cc3;
|
||||
ccp[4] = cc4;
|
||||
ccp[5] = cc5;
|
||||
ccp[6] = cc6;
|
||||
ccp[7] = cc7;
|
||||
}
|
||||
}
|
||||
for (int s=0;s<n_inputs;s++) {
|
||||
for (int i1 = 0; i1 < 22; i1++) {
|
||||
memcpy(&c[s][2 * i1 * 384] , &cc[s][i1 * 384], 384 * sizeof(uint32_t));
|
||||
memcpy(&c[s][(2 * i1 + 1) * 384], &cc[s][i1 * 384], 384 * sizeof(uint32_t));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -0,0 +1,300 @@
|
||||
/*
|
||||
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.openairinterface.org/?page_id=698
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*-------------------------------------------------------------------------------
|
||||
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include "openair1/PHY/CODING/nrLDPC_coding/nrLDPC_coding_segment/nr_rate_matching.h"
|
||||
|
||||
__device__ __forceinline__ int clamp_i16_to_i8(int x)
|
||||
{
|
||||
// x is int (promoted)
|
||||
x = (x < -128) ? -128 : x;
|
||||
x = (x > 127) ? 127 : x;
|
||||
return x;
|
||||
}
|
||||
|
||||
__device__ __forceinline__ uint32_t packs_4x16_to_4x8(uint32_t a, uint32_t b)
|
||||
{
|
||||
int a0 = (int)(int16_t)(a & 0xFFFFu);
|
||||
int a1 = (int)(int16_t)(a >> 16);
|
||||
int b0 = (int)(int16_t)(b & 0xFFFFu);
|
||||
int b1 = (int)(int16_t)(b >> 16);
|
||||
|
||||
uint32_t o0 = (uint8_t)(int8_t)clamp_i16_to_i8(a0);
|
||||
uint32_t o1 = (uint8_t)(int8_t)clamp_i16_to_i8(a1);
|
||||
uint32_t o2 = (uint8_t)(int8_t)clamp_i16_to_i8(b0);
|
||||
uint32_t o3 = (uint8_t)(int8_t)clamp_i16_to_i8(b1);
|
||||
|
||||
return (o0) | (o1 << 8) | (o2 << 16) | (o3 << 24);
|
||||
}
|
||||
|
||||
__device__ __forceinline__ uint16_t packs_2x16_to_2x8(uint32_t a)
|
||||
{
|
||||
int a0 = (int)(int16_t)(a & 0xFFFFu);
|
||||
int a1 = (int)(int16_t)(a >> 16);
|
||||
|
||||
uint16_t o0 = (uint8_t)(int8_t)clamp_i16_to_i8(a0);
|
||||
uint16_t o1 = (uint8_t)(int8_t)clamp_i16_to_i8(a1);
|
||||
|
||||
return (o0) | (o1 << 8) ;
|
||||
}
|
||||
|
||||
__global__ void rm(int Ncb_4,int ind0_4, int E1, int E2, int r_firstE2, int Foffset_4, int F_4, int clear, int seglen_4, int K_4, int Z_4, uint32_t *d, uint32_t *e, uint32_t *llr_buffer) {
|
||||
|
||||
int ind_4 = (int)(blockIdx.x * blockDim.x + threadIdx.x);
|
||||
int r = (int)blockIdx.y;
|
||||
uint32_t *er = e + ((r<r_firstE2) ? r*(E1>>1) : ((r_firstE2*E1)+(r-r_firstE2)*E2)>>1);
|
||||
uint32_t *dr = d + (2*r*seglen_4);
|
||||
uint32_t *llr_bufferr = llr_buffer + (r*seglen_4);
|
||||
#ifdef DEBUG_RM
|
||||
if (blockIdx.x == 0 && threadIdx.x == 0) printf("r %d, seglen %d\n",r,seglen_4);
|
||||
#endif
|
||||
if (ind_4>= Foffset_4 && ind_4 < Foffset_4+F_4) {
|
||||
llr_bufferr[ind_4-Foffset_4+K_4-F_4] = 0x7f7f7f7f;
|
||||
#ifdef DEBUG_RM
|
||||
if (r==0) printf("writing 0x7f7f7f7f to position %d (ind %d, K %d, Foffset %d, F %d)\n",seglen_4*r + ind_4-Foffset_4+K_4-F_4,ind_4,K_4,Foffset_4,F_4);
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
if (ind_4 >= Ncb_4) return;
|
||||
if (clear == 1) { dr[2*ind_4] = 0; dr[(2*ind_4)+1]=0; }
|
||||
|
||||
int E_4;
|
||||
if (r<r_firstE2) E_4=(E1/4); else E_4=(E2/4);
|
||||
|
||||
int ind1=ind0_4,ind2;
|
||||
int k=0;
|
||||
|
||||
#ifdef DEBUG_RM
|
||||
if (r==0 && threadIdx.x == 0) printf("check 1a: ind %d ind1 %d Foffset %d\n",ind,ind1,Foffset);
|
||||
#endif
|
||||
if (ind1 < Foffset_4) {
|
||||
int ind2 = ind1 + min(Foffset_4-ind1,E_4);
|
||||
|
||||
#ifdef DEBUG_RM
|
||||
if (r==0 && threadIdx.x == 0) printf("check 1b: ind %d ind1 %d ind2 %d\n",ind,ind1,ind2);
|
||||
#endif
|
||||
if (ind_4 >= ind1 && ind_4 < ind2) {
|
||||
dr[2*ind_4] = __vaddss2(dr[2*ind_4],er[2*(ind_4-ind1)]);
|
||||
dr[(2*ind_4)+1] = __vaddss2(dr[(2*ind_4)+1],er[2*(ind_4-ind1)+1]);
|
||||
}
|
||||
#ifdef DEBUG_RM
|
||||
if (r<=1 && threadIdx.x == 0 && ind_4 >= ind1 && ind_4 < ind2) printf("write 1. r %d : ind %d, ind1 %d, ind2 %d,k %d/E %d, pos %d, er %d %d\n",r,ind_4,ind1,ind2,ind_4-ind1,E_4,4*(ind_4-ind1),(int16_t)(er[2*(ind_4-ind1)]&0xffff),(int16_t)(er[2*(ind_4-ind1)]>>16));
|
||||
#endif
|
||||
k=ind2-ind1;
|
||||
ind1 = ind2;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_RM
|
||||
if (r==0 && threadIdx.x == 0) printf("check 2a: ind %d ind1 %d Foffset %d Foffset+F %d\n",ind,ind1,Foffset,Foffset+F);
|
||||
#endif
|
||||
if (ind1 >= Foffset_4 && ind1 < Foffset_4 + F_4) ind1 = Foffset_4 + F_4;
|
||||
ind2 = ind1 + min(Ncb_4-ind1,E_4-k);
|
||||
|
||||
#ifdef DEBUG_RM
|
||||
if (r==0 && threadIdx.x == 0) printf("check 2b: ind %d ind1 %d ind2 %d\n",ind_4,ind1,ind2);
|
||||
#endif
|
||||
if (ind_4 >= ind1 && ind_4 < ind2) {
|
||||
dr[2*ind_4] = __vaddss2(dr[2*ind_4],er[2*(k+(ind_4-ind1))]);
|
||||
dr[(2*ind_4)+1] = __vaddss2(dr[(2*ind_4)+1],er[2*(k+(ind_4-ind1))+1]);
|
||||
}
|
||||
#ifdef DEBUG_RM
|
||||
if (r==0 && threadIdx.x == 0 && ind >= ind1 && ind < ind2) printf("write 2. ind %d, ind1 %d, ind2 %d, k %d/E %d\n",ind,ind1,ind2,k+ind-ind1,E);
|
||||
#endif
|
||||
k+=(ind2-ind1);
|
||||
|
||||
#ifdef DEBUG_RM
|
||||
if (r==0 && threadIdx.x == 0) printf("check k %d E %d\n",k,E);
|
||||
#endif
|
||||
while (k < E_4) {
|
||||
ind2 = min(Foffset_4,E_4-k);
|
||||
if (ind_4 < ind2) {
|
||||
dr[2*ind_4] = __vaddss2(dr[2*ind_4],er[2*(k+ind_4)]);
|
||||
dr[(2*ind_4)+1] = __vaddss2(dr[(2*ind_4)+1],er[2*(k+ind_4)+1]);
|
||||
}
|
||||
#ifdef DEBUG_RM
|
||||
if (r==0 && threadIdx.x == 0 && ind < ind2 && ind >= ind1) printf("3. ind %d, ind2 %d, k %d/E %d\n",ind,ind2,k+ind,E);
|
||||
#endif
|
||||
k+=ind2;
|
||||
|
||||
ind1=Foffset_4+F_4;
|
||||
ind2 = ind1 + min(Ncb_4-ind1,E_4-k);
|
||||
if (ind_4 >= ind1 && ind_4 < ind2 && k < E_4) {
|
||||
dr[2*ind_4] = __vaddss2(dr[2*ind_4],er[2*(k+ind_4-ind1)]);
|
||||
dr[(2*ind_4)+1] = __vaddss2(dr[(2*ind_4)+1],er[2*(k+ind_4-ind1)+1]);
|
||||
}
|
||||
#ifdef DEBUG_RM
|
||||
if (r==0 && threadIdx.x == 0 && ind < ind && ind >= ind1) printf("4. ind %d, ind1 %d, ind2 %d, k %d/E %d\n",ind,ind1,ind2,k+ind-ind1,E);
|
||||
#endif
|
||||
k+=(ind2-ind1);
|
||||
}
|
||||
// note the offset here is such that when ind < Foffset = Kprime - 2Z, the output is put in position r*seglen + (2Z ... Kprime) and when ind > Foffset+F, it is in position r*seglen + (Kprime+F = K .. 2Z+(66*Z)=seglen
|
||||
llr_bufferr[2*Z_4 + ind_4] = packs_4x16_to_4x8(dr[(2*ind_4)], dr[(2*ind_4)+1]);
|
||||
#ifdef DEBUG_RM
|
||||
if (r<=1 && threadIdx.x == 0) printf("RM segment %d: writing %x to position %d (ind %d)\n",r,llr_bufferr[2*Z_4 + ind_4],r*seglen_4 + 2*Z_4 + ind_4,ind_4);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
__global__ void rm2(int Ncb_2,int ind0_2, int E1, int E2, int r_firstE2, int Foffset_2, int F_2, int clear, int seglen_2, int K_2, int Z_2, uint32_t *d, uint32_t *e, uint16_t *llr_buffer) {
|
||||
|
||||
int ind_2 = (int)(blockIdx.x * blockDim.x + threadIdx.x);
|
||||
int r = (int)blockIdx.y;
|
||||
uint32_t *er = e + ((r<r_firstE2) ? r*(E1>>1) : ((r_firstE2*E1)+(r-r_firstE2)*E2)>>1);
|
||||
uint32_t *dr = d + (r*seglen_2);
|
||||
uint16_t *llr_bufferr = llr_buffer + (r*seglen_2);
|
||||
|
||||
if (ind_2 >= Ncb_2) return;
|
||||
#ifdef RM_DEBUG
|
||||
if (r==0) printf("Looking for ind %d...%d, Ncb %d\n",ind_2*2,1+ind_2*2,Ncb_2*2);
|
||||
#endif
|
||||
if (ind_2>= Foffset_2 && ind_2 < Foffset_2+F_2) {
|
||||
llr_bufferr[ind_2-Foffset_2+K_2-F_2] = 0x7f7f;
|
||||
#ifdef RM_DEBUG
|
||||
if (r==0) printf("writing 0x7f7f7f7f to position %d (ind %d, K %d, Foffset %d, F %d)\n",(seglen_2*r + ind_2-Foffset_2+K_2-F_2)*2,ind_2*2,K_2*2,Foffset_2*2,F_2*2);
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
if (clear == 1) dr[ind_2] = 0;
|
||||
|
||||
int E_2;
|
||||
if (r<r_firstE2) E_2=E1/2; else E_2=E2/2;
|
||||
|
||||
int ind1=ind0_2,ind2;
|
||||
int k=0;
|
||||
|
||||
// if (r==0 && threadIdx.x == 0 && blockIdx.x == 0) printf("check 1a: ind %d ind1 %d Foffset %d\n",ind,ind1,Foffset);
|
||||
if (ind1 < Foffset_2) {
|
||||
int ind2 = ind1 + min(Foffset_2-ind1,E_2);
|
||||
|
||||
// if (r==0 && threadIdx.x == 0 && blockIdx.x == 0) printf("check RM1B: ind %d ind1 %d ind2 %d k %d/E %d\n",4*ind,4*ind1,4*ind2,4*k,4*E);
|
||||
if (ind_2 >= ind1 && ind_2 < ind2) {
|
||||
dr[ind_2] = __vaddss2(dr[ind_2],er[ind_2-ind1]);
|
||||
}
|
||||
#ifdef RM_DEBUG
|
||||
if (r==0 /*&& threadIdx.x == 0 && blockIdx.x == 0*/ && ind_2 >= ind1 && ind_2 < ind2) printf("RM1A: ind_2 %d, ind1 %d, ind2 %d,k %d/E %d\n",2*ind_2,2*ind1,2*ind2,2*(ind_2-ind1),2*E_2);
|
||||
#endif
|
||||
k=ind2-ind1;
|
||||
ind1 = ind2;
|
||||
}
|
||||
|
||||
// if (r==0 && threadIdx.x == 0 && blockIdx.x == 0) printf("check 2a: ind %d ind1 %d Foffset %d Foffset+F %d\n",ind,ind1,Foffset,Foffset+F);
|
||||
if (ind1 >= Foffset_2 && ind1 < Foffset_2 + F_2) ind1 = Foffset_2 + F_2;
|
||||
ind2 = ind1 + min(Ncb_2-ind1,E_2-k);
|
||||
|
||||
// if (r==0 && threadIdx.x == 0 && blockIdx.x == 0) printf("check RM2B: ind %d ind1 %d ind2 %d k%d/E %d\n",4*ind,4*ind1,4*ind2,4*k,4*E);
|
||||
if (ind_2 >= ind1 && ind_2 < ind2) {
|
||||
dr[ind_2] = __vaddss2(dr[ind_2],er[(k+(ind_2-ind1))]);
|
||||
}
|
||||
#ifdef RM_DEBUG
|
||||
if (r==0 /*&& threadIdx.x == 0 && blockIdx.x == 0*/ && ind_2 >= ind1 && ind_2 < ind2) printf("RM2A: ind %d, ind1 %d, ind2 %d, k %d/E %d\n",2*ind_2,2*ind1,2*ind2,2*(k+(ind-ind1)),2*E_2);
|
||||
#endif
|
||||
k+=(ind2-ind1);
|
||||
|
||||
// if (r==0 && threadIdx.x == 0 && blockIdx.x == 0) printf("check k %d E %d\n",k,E);
|
||||
while (k < E_2) {
|
||||
ind2 = min(Foffset_2,E_2-k);
|
||||
// if (r==0 && threadIdx.x == 0 && blockIdx.x == 0) printf("check RM3B: ind %d ind1 %d ind2 %d k %d/E %d\n",4*ind,0,4*ind2,4*k,4*E);
|
||||
if (ind_2 < ind2) {
|
||||
dr[ind_2] = __vaddss2(dr[ind_2],er[(k+ind_2)]);
|
||||
}
|
||||
#ifdef RM_DEBUG
|
||||
if (r==0 /*&& threadIdx.x == 0 && blockIdx.x == 0*/ && ind_2 < ind2 ) printf("RM3A: ind %d, ind2 %d, k %d/E %d\n",2*ind_2,2*ind2,2*(k+ind_2),2*E_2);
|
||||
#endif
|
||||
k+=ind2;
|
||||
|
||||
ind1=Foffset_2+F_2;
|
||||
ind2 = ind1 + min(Ncb_2-ind1,E_2-k);
|
||||
// if (r==0 && threadIdx.x == 0 && blockIdx.x == 0) printf("check RM4B: ind %d ind1 %d ind2 %d k %d/E %d\n",4*ind,0,4*ind2,4*k,4*E);
|
||||
if (ind_2 >= ind1 && ind_2 < ind2 && k < E_2) {
|
||||
dr[ind_2] = __vaddss2(dr[ind_2],er[(k+ind_2-ind1)]);
|
||||
}
|
||||
#ifdef RM_DEBUG
|
||||
if (r==0 /*&& threadIdx.x == 0 && blockIdx.x == 0*/ && ind_2 < ind2 && ind_2 >= ind1) printf("RM4A: ind %d, ind1 %d, ind2 %d, k %d/E %d\n",2*ind_2,2*ind1,2*ind2_2,2*(k+ind_2-ind1),2*E_2);
|
||||
#endif
|
||||
k+=(ind2-ind1);
|
||||
|
||||
}
|
||||
// note the offset here is such that when ind < Foffset = Kprime - 2Z, the output is put in position r*seglen + (2Z ... Kprime) and when ind > Foffset+F, it is in potiion r*seglent + (Kprime+F = K .. 2Z+(66*Z)=seglen
|
||||
llr_bufferr[2*Z_2 + ind_2] = packs_2x16_to_2x8(dr[ind_2]);
|
||||
// if (r==0 && threadIdx.x == 0 && blockIdx.x == 0) printf("writing %x to position %d (ind %d)\n",llr_bufferr[2*Z + ind_2],r*seglen + 2*Z + ind_2,ind_2);
|
||||
}
|
||||
|
||||
|
||||
static const uint8_t index_k0[2][4] = {{0, 17, 33, 56}, {0, 13, 25, 43}};
|
||||
extern "C" int nr_rate_matching_ldpc_rx_cuda(uint32_t Tbslbrm,
|
||||
uint8_t BG,
|
||||
uint16_t Z,
|
||||
int16_t *d,
|
||||
int16_t *soft_input,
|
||||
int8_t *llr_buffer,
|
||||
uint32_t K,
|
||||
uint8_t C,
|
||||
uint8_t rvidx,
|
||||
uint8_t clear,
|
||||
uint32_t E1,
|
||||
uint32_t E2,
|
||||
uint32_t r_firstE2,
|
||||
uint32_t F,
|
||||
uint32_t Foffset,
|
||||
cudaStream_t *s,
|
||||
int8_t sidx)
|
||||
{
|
||||
if (C == 0 || C>132) {
|
||||
printf("nr_rate_matching: invalid parameter C %d\n", C);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
//Bit selection
|
||||
uint32_t N = (BG == 1) ? (66 * Z) : (50 * Z);
|
||||
uint32_t Ncb;
|
||||
if (Tbslbrm == 0)
|
||||
Ncb = N;
|
||||
else {
|
||||
uint32_t Nref = (3 * Tbslbrm / (2 * C)); //R_LBRM = 2/3
|
||||
Ncb = min(N, Nref);
|
||||
}
|
||||
|
||||
uint32_t ind = (index_k0[BG - 1][rvidx] * Ncb / N) * Z;
|
||||
|
||||
|
||||
int nthreads=Z;
|
||||
#ifdef RM_DEBUG
|
||||
printf("\nrm (%d,%d): Ncb %d, ind %d, rvidx %d, E1 %d, E2 %d, Foffset %d, F %d, K %d, Z %d, clear %d\n",nblocks.x,nthreads,Ncb, ind, rvidx, E1, E2, Foffset, F,K,Z,clear);
|
||||
#endif
|
||||
if ((E1&3) == 0 && (E2&3) == 0) {
|
||||
dim3 nblocks(((Ncb>>2) + nthreads-1)/nthreads,C);
|
||||
rm<<<nblocks, nthreads, 0, s[sidx]>>>(Ncb/4,ind/4,E1,E2,r_firstE2,Foffset/4,F/4,clear,68*384/4,K/4,Z/4,(uint32_t*)d,(uint32_t*)soft_input,(uint32_t*)llr_buffer);
|
||||
}
|
||||
else {
|
||||
dim3 nblocks2(((Ncb>>1) + nthreads-1)/nthreads,C);
|
||||
rm2<<<nblocks2, nthreads, 0, s[sidx]>>>(Ncb/2,ind/2,E1,E2,r_firstE2,Foffset/2,F/2,clear,68*384/2,K/2,Z/2,(uint32_t*)d,(uint32_t*)soft_input,(uint16_t*)llr_buffer);
|
||||
}
|
||||
cudaError_t err=cudaPeekAtLastError();
|
||||
|
||||
if (err!=cudaSuccess) {
|
||||
printf("cuda error (nr_rate_matching_ldpc_rx_cuda): %s Ncb %d, ind %d, rvidx %d, E1 %d, E2 %d, Foffset %d, F %d, K %d, Z %d, clear %d\n",cudaGetErrorString(err),Ncb, ind, rvidx, E1, E2, Foffset, F,K,Z,clear);
|
||||
exit(-1);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,444 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: LicenseRef-CSSL-1.0
|
||||
*/
|
||||
/*! \file nrLDPC_CUDA_BnProcKernel_BG1.h
|
||||
* \brief Defines the kernels for bit node processing
|
||||
* \author Qizhi Pan, Raymond Knopp
|
||||
* \company EURECOM
|
||||
* \email: qizhi.pan@eurecom.fr, raymond.knopp@eurecom.fr
|
||||
* \date 2025-12-30
|
||||
* \version 1.0
|
||||
* \note
|
||||
* \warning
|
||||
*/
|
||||
#include <cuda_runtime.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include "openair1/PHY/CODING/nrLDPC_decoder/nrLDPCdecoder_defs.h"
|
||||
|
||||
__device__ __forceinline__ void unpack_and_sign_extend(uint32_t packed, uint32_t *val_lo, uint32_t *val_hi)
|
||||
{
|
||||
uint32_t magic_sub = 0x00800080;
|
||||
|
||||
uint32_t lo_zext = __byte_perm(packed, 0, 0x5140);
|
||||
*val_lo = __vsub2(lo_zext ^ magic_sub, magic_sub);
|
||||
|
||||
uint32_t hi_zext = __byte_perm(packed, 0, 0x7362);
|
||||
*val_hi = __vsub2(hi_zext ^ magic_sub, magic_sub);
|
||||
}
|
||||
|
||||
__device__ __forceinline__ uint32_t saturate_and_pack(uint32_t val_lo, uint32_t val_hi)
|
||||
{
|
||||
uint32_t lo_clamped = __vmins2(val_lo, 0x007F007F); // min(v, 127)
|
||||
lo_clamped = __vmaxs2(lo_clamped, 0xFF80FF80); // max(v, -128)
|
||||
|
||||
uint32_t hi_clamped = __vmins2(val_hi, 0x007F007F);
|
||||
hi_clamped = __vmaxs2(hi_clamped, 0xFF80FF80);
|
||||
|
||||
return __byte_perm(lo_clamped, hi_clamped, 0x6420);
|
||||
}
|
||||
|
||||
__device__ __forceinline__ void bnProcKernel_BG1_int8_Gn_Node_R13(const int8_t *__restrict__ d_bnProcBuf,
|
||||
int8_t *__restrict__ d_cnProcBuf,
|
||||
const int8_t *__restrict__ d_llrProcBuf,
|
||||
int8_t *__restrict__ d_llrRes,
|
||||
uint32_t lane,
|
||||
uint32_t BnGrpIdx,
|
||||
uint32_t BnIdx,
|
||||
uint32_t GrpNum,
|
||||
uint32_t Bn2MsgStartIdx,
|
||||
uint32_t Zc,
|
||||
uint32_t ZcIdx)
|
||||
{
|
||||
const int32_t *bnProcBufPtr = (const int32_t *)(d_bnProcBuf) + lane;
|
||||
|
||||
uint32_t packed_intrinsic = ((const int32_t *)(d_llrProcBuf))[lane];
|
||||
|
||||
uint32_t MsgSumLo, MsgSumHi;
|
||||
unpack_and_sign_extend(packed_intrinsic, &MsgSumLo, &MsgSumHi);
|
||||
|
||||
uint32_t off = (GrpNum * NR_LDPC_ZMAX) >> 2;
|
||||
const int32_t *currPtr = bnProcBufPtr;
|
||||
|
||||
int i = 0;
|
||||
|
||||
// --- 2-Way Unroll ---
|
||||
|
||||
for (; i < (int)BnGrpIdx - 1; i += 2) {
|
||||
uint32_t val1 = *currPtr;
|
||||
uint32_t val2 = *(currPtr + off);
|
||||
|
||||
uint32_t v1_lo, v1_hi;
|
||||
unpack_and_sign_extend(val1, &v1_lo, &v1_hi);
|
||||
MsgSumLo = __vaddss2(MsgSumLo, v1_lo);
|
||||
MsgSumHi = __vaddss2(MsgSumHi, v1_hi);
|
||||
|
||||
uint32_t v2_lo, v2_hi;
|
||||
unpack_and_sign_extend(val2, &v2_lo, &v2_hi);
|
||||
MsgSumLo = __vaddss2(MsgSumLo, v2_lo);
|
||||
MsgSumHi = __vaddss2(MsgSumHi, v2_hi);
|
||||
|
||||
currPtr += (off << 1);
|
||||
}
|
||||
|
||||
if (i < BnGrpIdx) {
|
||||
uint32_t val = *currPtr;
|
||||
uint32_t v_lo, v_hi;
|
||||
unpack_and_sign_extend(val, &v_lo, &v_hi);
|
||||
MsgSumLo = __vaddss2(MsgSumLo, v_lo);
|
||||
MsgSumHi = __vaddss2(MsgSumHi, v_hi);
|
||||
}
|
||||
|
||||
uint32_t saturated_llr = saturate_and_pack(MsgSumLo, MsgSumHi);
|
||||
|
||||
uint32_t BricksToBeGet;
|
||||
if (BnGrpIdx == 1) {
|
||||
BricksToBeGet = packed_intrinsic;
|
||||
uint32_t MsgIdx = Bn2MsgStartIdx;
|
||||
uint32_t circShift = bn_cn_map_BG1_Z_R13[MsgIdx][ZcIdx];
|
||||
int8_t *p_cnProcBuf = (int8_t *)(d_cnProcBuf + bn_cn_map_BG1_Z_R13[MsgIdx][0]);
|
||||
|
||||
moveBricks_forput_circ(p_cnProcBuf, lane * 4, (uint8_t *)&BricksToBeGet, Zc, circShift);
|
||||
} else {
|
||||
for (int temp_MsgIdx = 0; temp_MsgIdx < BnGrpIdx; temp_MsgIdx++) {
|
||||
uint32_t prevIdxWords = (temp_MsgIdx * GrpNum * NR_LDPC_ZMAX) >> 2;
|
||||
uint32_t prev = bnProcBufPtr[prevIdxWords];
|
||||
BricksToBeGet = __vsubss4(saturated_llr, prev);
|
||||
uint32_t MsgIdx = Bn2MsgStartIdx + temp_MsgIdx;
|
||||
uint32_t circShift = bn_cn_map_BG1_Z_R13[MsgIdx][ZcIdx];
|
||||
int8_t *p_cnProcBuf = (int8_t *)(d_cnProcBuf + bn_cn_map_BG1_Z_R13[MsgIdx][0]);
|
||||
|
||||
moveBricks_forput_circ(p_cnProcBuf, lane * 4, (uint8_t *)&BricksToBeGet, Zc, circShift);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
__device__ __forceinline__ void bnProcKernel_BG1_int8_Gn_Node_R23(const int8_t *__restrict__ d_bnProcBuf,
|
||||
int8_t *__restrict__ d_cnProcBuf,
|
||||
const int8_t *__restrict__ d_llrProcBuf,
|
||||
int8_t *__restrict__ d_llrRes,
|
||||
uint32_t lane,
|
||||
uint32_t BnGrpIdx,
|
||||
uint32_t BnIdx,
|
||||
uint32_t GrpNum,
|
||||
uint32_t Bn2MsgStartIdx,
|
||||
uint32_t Zc,
|
||||
uint32_t ZcIdx)
|
||||
{
|
||||
const int32_t *bnProcBufPtr = (const int32_t *)(d_bnProcBuf) + lane;
|
||||
|
||||
uint32_t packed_intrinsic = ((const int32_t *)(d_llrProcBuf))[lane];
|
||||
|
||||
uint32_t MsgSumLo, MsgSumHi;
|
||||
unpack_and_sign_extend(packed_intrinsic, &MsgSumLo, &MsgSumHi);
|
||||
|
||||
uint32_t off = (GrpNum * NR_LDPC_ZMAX) >> 2;
|
||||
const int32_t *currPtr = bnProcBufPtr;
|
||||
|
||||
int i = 0;
|
||||
|
||||
// --- 2-Way Unroll ---
|
||||
|
||||
for (; i < (int)BnGrpIdx - 1; i += 2) {
|
||||
uint32_t val1 = *currPtr;
|
||||
uint32_t val2 = *(currPtr + off);
|
||||
|
||||
uint32_t v1_lo, v1_hi;
|
||||
unpack_and_sign_extend(val1, &v1_lo, &v1_hi);
|
||||
MsgSumLo = __vaddss2(MsgSumLo, v1_lo);
|
||||
MsgSumHi = __vaddss2(MsgSumHi, v1_hi);
|
||||
|
||||
uint32_t v2_lo, v2_hi;
|
||||
unpack_and_sign_extend(val2, &v2_lo, &v2_hi);
|
||||
MsgSumLo = __vaddss2(MsgSumLo, v2_lo);
|
||||
MsgSumHi = __vaddss2(MsgSumHi, v2_hi);
|
||||
|
||||
currPtr += (off << 1);
|
||||
}
|
||||
|
||||
if (i < BnGrpIdx) {
|
||||
uint32_t val = *currPtr;
|
||||
uint32_t v_lo, v_hi;
|
||||
unpack_and_sign_extend(val, &v_lo, &v_hi);
|
||||
MsgSumLo = __vaddss2(MsgSumLo, v_lo);
|
||||
MsgSumHi = __vaddss2(MsgSumHi, v_hi);
|
||||
}
|
||||
|
||||
uint32_t saturated_llr = saturate_and_pack(MsgSumLo, MsgSumHi);
|
||||
|
||||
uint32_t BricksToBeGet;
|
||||
if (BnGrpIdx == 1) {
|
||||
BricksToBeGet = packed_intrinsic;
|
||||
uint32_t MsgIdx = Bn2MsgStartIdx;
|
||||
uint32_t circShift = bn_cn_map_BG1_Z_R23[MsgIdx][ZcIdx];
|
||||
int8_t *p_cnProcBuf = (int8_t *)(d_cnProcBuf + bn_cn_map_BG1_Z_R23[MsgIdx][0]);
|
||||
|
||||
moveBricks_forput_circ(p_cnProcBuf, lane * 4, (uint8_t *)&BricksToBeGet, Zc, circShift);
|
||||
} else {
|
||||
for (int temp_MsgIdx = 0; temp_MsgIdx < BnGrpIdx; temp_MsgIdx++) {
|
||||
uint32_t prevIdxWords = (temp_MsgIdx * GrpNum * NR_LDPC_ZMAX) >> 2;
|
||||
uint32_t prev = bnProcBufPtr[prevIdxWords];
|
||||
BricksToBeGet = __vsubss4(saturated_llr, prev);
|
||||
uint32_t MsgIdx = Bn2MsgStartIdx + temp_MsgIdx;
|
||||
uint32_t circShift = bn_cn_map_BG1_Z_R23[MsgIdx][ZcIdx];
|
||||
int8_t *p_cnProcBuf = (int8_t *)(d_cnProcBuf + bn_cn_map_BG1_Z_R23[MsgIdx][0]);
|
||||
|
||||
moveBricks_forput_circ(p_cnProcBuf, lane * 4, (uint8_t *)&BricksToBeGet, Zc, circShift);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
__device__ __forceinline__ void bnProcKernel_BG1_int8_Gn_Node_R89(const int8_t *__restrict__ d_bnProcBuf,
|
||||
int8_t *__restrict__ d_cnProcBuf,
|
||||
const int8_t *__restrict__ d_llrProcBuf,
|
||||
int8_t *__restrict__ d_llrRes,
|
||||
uint32_t lane,
|
||||
uint32_t BnGrpIdx,
|
||||
uint32_t BnIdx,
|
||||
uint32_t GrpNum,
|
||||
uint32_t Bn2MsgStartIdx,
|
||||
uint32_t Zc,
|
||||
uint32_t ZcIdx)
|
||||
{
|
||||
const int32_t *bnProcBufPtr = (const int32_t *)(d_bnProcBuf) + lane;
|
||||
|
||||
uint32_t packed_intrinsic = ((const int32_t *)(d_llrProcBuf))[lane];
|
||||
|
||||
uint32_t MsgSumLo, MsgSumHi;
|
||||
unpack_and_sign_extend(packed_intrinsic, &MsgSumLo, &MsgSumHi);
|
||||
|
||||
uint32_t off = (GrpNum * NR_LDPC_ZMAX) >> 2;
|
||||
const int32_t *currPtr = bnProcBufPtr;
|
||||
|
||||
int i = 0;
|
||||
|
||||
// --- 2-Way Unroll ---
|
||||
|
||||
for (; i < (int)BnGrpIdx - 1; i += 2) {
|
||||
uint32_t val1 = *currPtr;
|
||||
uint32_t val2 = *(currPtr + off);
|
||||
|
||||
uint32_t v1_lo, v1_hi;
|
||||
unpack_and_sign_extend(val1, &v1_lo, &v1_hi);
|
||||
MsgSumLo = __vaddss2(MsgSumLo, v1_lo);
|
||||
MsgSumHi = __vaddss2(MsgSumHi, v1_hi);
|
||||
|
||||
uint32_t v2_lo, v2_hi;
|
||||
unpack_and_sign_extend(val2, &v2_lo, &v2_hi);
|
||||
MsgSumLo = __vaddss2(MsgSumLo, v2_lo);
|
||||
MsgSumHi = __vaddss2(MsgSumHi, v2_hi);
|
||||
|
||||
currPtr += (off << 1);
|
||||
}
|
||||
|
||||
if (i < BnGrpIdx) {
|
||||
uint32_t val = *currPtr;
|
||||
uint32_t v_lo, v_hi;
|
||||
unpack_and_sign_extend(val, &v_lo, &v_hi);
|
||||
MsgSumLo = __vaddss2(MsgSumLo, v_lo);
|
||||
MsgSumHi = __vaddss2(MsgSumHi, v_hi);
|
||||
}
|
||||
|
||||
uint32_t saturated_llr = saturate_and_pack(MsgSumLo, MsgSumHi);
|
||||
|
||||
uint32_t BricksToBeGet;
|
||||
if (BnGrpIdx == 1) {
|
||||
BricksToBeGet = packed_intrinsic;
|
||||
uint32_t MsgIdx = Bn2MsgStartIdx;
|
||||
uint32_t circShift = bn_cn_map_BG1_Z_R89[MsgIdx][ZcIdx];
|
||||
int8_t *p_cnProcBuf = (int8_t *)(d_cnProcBuf + bn_cn_map_BG1_Z_R89[MsgIdx][0]);
|
||||
|
||||
moveBricks_forput_circ(p_cnProcBuf, lane * 4, (uint8_t *)&BricksToBeGet, Zc, circShift);
|
||||
} else {
|
||||
for (int temp_MsgIdx = 0; temp_MsgIdx < BnGrpIdx; temp_MsgIdx++) {
|
||||
uint32_t prevIdxWords = (temp_MsgIdx * GrpNum * NR_LDPC_ZMAX) >> 2;
|
||||
uint32_t prev = bnProcBufPtr[prevIdxWords];
|
||||
BricksToBeGet = __vsubss4(saturated_llr, prev);
|
||||
uint32_t MsgIdx = Bn2MsgStartIdx + temp_MsgIdx;
|
||||
uint32_t circShift = bn_cn_map_BG1_Z_R89[MsgIdx][ZcIdx];
|
||||
int8_t *p_cnProcBuf = (int8_t *)(d_cnProcBuf + bn_cn_map_BG1_Z_R89[MsgIdx][0]);
|
||||
|
||||
moveBricks_forput_circ(p_cnProcBuf, lane * 4, (uint8_t *)&BricksToBeGet, Zc, circShift);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
__device__ __forceinline__ void bnProcKernel_BG1_int8_Gn_Node_last(const int8_t *__restrict__ d_bnProcBuf,
|
||||
int8_t *__restrict__ d_cnProcBuf,
|
||||
const int8_t *__restrict__ d_llrProcBuf,
|
||||
int8_t *__restrict__ d_llrRes,
|
||||
uint32_t lane,
|
||||
uint32_t BnGrpIdx,
|
||||
uint32_t BnIdx,
|
||||
uint32_t GrpNum,
|
||||
uint32_t Bn2MsgStartIdx,
|
||||
uint32_t Zc,
|
||||
uint32_t ZcIdx)
|
||||
{
|
||||
const int32_t *bnProcBufPtr = (const int32_t *)(d_bnProcBuf) + lane;
|
||||
|
||||
uint32_t packed_intrinsic = ((const int32_t *)(d_llrProcBuf))[lane];
|
||||
|
||||
uint32_t MsgSumLo, MsgSumHi;
|
||||
unpack_and_sign_extend(packed_intrinsic, &MsgSumLo, &MsgSumHi);
|
||||
|
||||
uint32_t off = (GrpNum * NR_LDPC_ZMAX) >> 2;
|
||||
const int32_t *currPtr = bnProcBufPtr;
|
||||
|
||||
int i = 0;
|
||||
|
||||
// --- 2-Way Unroll ---
|
||||
|
||||
for (; i < (int)BnGrpIdx - 1; i += 2) {
|
||||
uint32_t val1 = *currPtr;
|
||||
uint32_t val2 = *(currPtr + off);
|
||||
|
||||
uint32_t v1_lo, v1_hi;
|
||||
unpack_and_sign_extend(val1, &v1_lo, &v1_hi);
|
||||
MsgSumLo = __vaddss2(MsgSumLo, v1_lo);
|
||||
MsgSumHi = __vaddss2(MsgSumHi, v1_hi);
|
||||
|
||||
uint32_t v2_lo, v2_hi;
|
||||
unpack_and_sign_extend(val2, &v2_lo, &v2_hi);
|
||||
MsgSumLo = __vaddss2(MsgSumLo, v2_lo);
|
||||
MsgSumHi = __vaddss2(MsgSumHi, v2_hi);
|
||||
|
||||
currPtr += (off << 1);
|
||||
}
|
||||
|
||||
if (i < BnGrpIdx) {
|
||||
uint32_t val = *currPtr;
|
||||
uint32_t v_lo, v_hi;
|
||||
unpack_and_sign_extend(val, &v_lo, &v_hi);
|
||||
MsgSumLo = __vaddss2(MsgSumLo, v_lo);
|
||||
MsgSumHi = __vaddss2(MsgSumHi, v_hi);
|
||||
}
|
||||
|
||||
uint32_t saturated_llr = saturate_and_pack(MsgSumLo, MsgSumHi);
|
||||
|
||||
((int32_t *)(d_llrRes))[lane] = saturated_llr;
|
||||
}
|
||||
|
||||
|
||||
__device__ __forceinline__ void bnProcKernel_BG1_int8_Gn_Edge(const int8_t *__restrict__ d_bnProcBuf,
|
||||
int8_t *__restrict__ d_cnProcBuf,
|
||||
const int8_t *__restrict__ d_llrProcBuf,
|
||||
int8_t *__restrict__ d_llrRes,
|
||||
uint32_t lane,
|
||||
uint32_t GrpIdx,
|
||||
uint32_t MsgIdx,
|
||||
uint32_t BnIdx,
|
||||
uint32_t GrpNum,
|
||||
uint32_t circShift,
|
||||
uint32_t Zc)
|
||||
{
|
||||
const int32_t *bnProcBufPtr = (const int32_t *)(d_bnProcBuf) + lane;
|
||||
|
||||
uint32_t packed_intrinsic = ((const int32_t *)(d_llrProcBuf))[lane];
|
||||
|
||||
uint32_t MsgSumLo, MsgSumHi;
|
||||
unpack_and_sign_extend(packed_intrinsic, &MsgSumLo, &MsgSumHi);
|
||||
|
||||
uint32_t off = (GrpNum * NR_LDPC_ZMAX) >> 2;
|
||||
const int32_t *currPtr = bnProcBufPtr;
|
||||
|
||||
int i = 0;
|
||||
|
||||
// --- 2-Way Unroll ---
|
||||
|
||||
for (; i < (int)GrpIdx - 1; i += 2) {
|
||||
uint32_t val1 = *currPtr;
|
||||
uint32_t val2 = *(currPtr + off);
|
||||
|
||||
uint32_t v1_lo, v1_hi;
|
||||
unpack_and_sign_extend(val1, &v1_lo, &v1_hi);
|
||||
MsgSumLo = __vaddss2(MsgSumLo, v1_lo);
|
||||
MsgSumHi = __vaddss2(MsgSumHi, v1_hi);
|
||||
|
||||
uint32_t v2_lo, v2_hi;
|
||||
unpack_and_sign_extend(val2, &v2_lo, &v2_hi);
|
||||
MsgSumLo = __vaddss2(MsgSumLo, v2_lo);
|
||||
MsgSumHi = __vaddss2(MsgSumHi, v2_hi);
|
||||
|
||||
currPtr += (off << 1);
|
||||
}
|
||||
|
||||
if (i < GrpIdx) {
|
||||
uint32_t val = *currPtr;
|
||||
uint32_t v_lo, v_hi;
|
||||
unpack_and_sign_extend(val, &v_lo, &v_hi);
|
||||
MsgSumLo = __vaddss2(MsgSumLo, v_lo);
|
||||
MsgSumHi = __vaddss2(MsgSumHi, v_hi);
|
||||
}
|
||||
|
||||
uint32_t saturated_llr = saturate_and_pack(MsgSumLo, MsgSumHi);
|
||||
|
||||
uint32_t BricksToBeGet;
|
||||
if (GrpIdx == 1) {
|
||||
BricksToBeGet = packed_intrinsic;
|
||||
} else {
|
||||
uint32_t prevIdxWords = (MsgIdx * GrpNum * NR_LDPC_ZMAX) >> 2;
|
||||
uint32_t prev = bnProcBufPtr[prevIdxWords];
|
||||
BricksToBeGet = __vsubss4(saturated_llr, prev);
|
||||
}
|
||||
|
||||
moveBricks_forput_circ(d_cnProcBuf, lane * 4, (uint8_t *)&BricksToBeGet, Zc, circShift);
|
||||
}
|
||||
|
||||
__device__ __forceinline__ void bnProcKernel_BG1_int8_Gn_Edge_last(const int8_t *__restrict__ d_bnProcBuf,
|
||||
int8_t *__restrict__ d_cnProcBuf,
|
||||
const int8_t *__restrict__ d_llrProcBuf,
|
||||
int8_t *__restrict__ d_llrRes,
|
||||
uint32_t lane,
|
||||
uint32_t GrpIdx,
|
||||
uint32_t MsgIdx,
|
||||
uint32_t BnIdx,
|
||||
uint32_t GrpNum,
|
||||
uint32_t circShift,
|
||||
uint32_t Zc)
|
||||
{
|
||||
const int32_t *bnProcBufPtr = (const int32_t *)(d_bnProcBuf) + lane;
|
||||
|
||||
uint32_t packed_intrinsic = ((const int32_t *)(d_llrProcBuf))[lane];
|
||||
|
||||
uint32_t MsgSumLo, MsgSumHi;
|
||||
unpack_and_sign_extend(packed_intrinsic, &MsgSumLo, &MsgSumHi);
|
||||
|
||||
uint32_t off = (GrpNum * NR_LDPC_ZMAX) >> 2;
|
||||
const int32_t *currPtr = bnProcBufPtr;
|
||||
|
||||
int i = 0;
|
||||
|
||||
// --- 2-Way Unroll ---
|
||||
|
||||
for (; i < (int)GrpIdx - 1; i += 2) {
|
||||
uint32_t val1 = *currPtr;
|
||||
uint32_t val2 = *(currPtr + off);
|
||||
|
||||
uint32_t v1_lo, v1_hi;
|
||||
unpack_and_sign_extend(val1, &v1_lo, &v1_hi);
|
||||
MsgSumLo = __vaddss2(MsgSumLo, v1_lo);
|
||||
MsgSumHi = __vaddss2(MsgSumHi, v1_hi);
|
||||
|
||||
uint32_t v2_lo, v2_hi;
|
||||
unpack_and_sign_extend(val2, &v2_lo, &v2_hi);
|
||||
MsgSumLo = __vaddss2(MsgSumLo, v2_lo);
|
||||
MsgSumHi = __vaddss2(MsgSumHi, v2_hi);
|
||||
|
||||
currPtr += (off << 1);
|
||||
}
|
||||
|
||||
if (i < GrpIdx) {
|
||||
uint32_t val = *currPtr;
|
||||
uint32_t v_lo, v_hi;
|
||||
unpack_and_sign_extend(val, &v_lo, &v_hi);
|
||||
MsgSumLo = __vaddss2(MsgSumLo, v_lo);
|
||||
MsgSumHi = __vaddss2(MsgSumHi, v_hi);
|
||||
}
|
||||
|
||||
uint32_t saturated_llr = saturate_and_pack(MsgSumLo, MsgSumHi);
|
||||
|
||||
if (MsgIdx == 0) {
|
||||
((int32_t *)(d_llrRes))[lane] = saturated_llr;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,566 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: LicenseRef-CSSL-1.0
|
||||
*/
|
||||
/*! \file nrLDPC_CUDA_CnProcKernel_BG1.h
|
||||
* \brief Defines the kernels for check node processing
|
||||
* \author Qizhi Pan, Raymond Knopp
|
||||
* \company EURECOM
|
||||
* \email: qizhi.pan@eurecom.fr, raymond.knopp@eurecom.fr
|
||||
* \date 2025-12-30
|
||||
* \version 1.0
|
||||
* \note
|
||||
* \warning
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <cuda_runtime.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include "nrLDPC_CUDA_public.h"
|
||||
#include "nrLDPC_CUDA_lut.h"
|
||||
|
||||
__device__ __forceinline__ void cnProcKernel_BG1_int8_Gn_R13_node(const int8_t *__restrict__ d_cnProcBuf,
|
||||
int8_t *__restrict__ d_bnProcBuf,
|
||||
uint32_t lane,
|
||||
uint32_t CnIdx,
|
||||
uint32_t CnNumInGrp,
|
||||
uint32_t CnGrpIdxNum,
|
||||
uint32_t Cn2MsgStartIdx,
|
||||
uint32_t Zc,
|
||||
uint32_t ZcIdx)
|
||||
{
|
||||
uint32_t min1 = 0x7F7F7F7F;
|
||||
uint32_t min2 = 0x7F7F7F7F;
|
||||
uint32_t total_xor = 0;
|
||||
|
||||
uint32_t cache_raw[19];
|
||||
uint32_t cache_abs[19];
|
||||
|
||||
const int32_t *cnProcBufPtr = (const int32_t *)(d_cnProcBuf) + lane;
|
||||
const int32_t *currPtr = cnProcBufPtr;
|
||||
uint32_t offset = (CnNumInGrp * NR_LDPC_ZMAX) >> 2;
|
||||
#pragma unroll
|
||||
for (int MsgIdx = 0; MsgIdx < CnGrpIdxNum; MsgIdx++) {
|
||||
uint32_t val = *currPtr;
|
||||
|
||||
cache_raw[MsgIdx] = val;
|
||||
uint32_t v_abs = __vabs4(val);
|
||||
cache_abs[MsgIdx] = v_abs;
|
||||
|
||||
total_xor = __vxor4(total_xor, val);
|
||||
|
||||
uint32_t old_min1 = min1;
|
||||
|
||||
min1 = __vminu4(old_min1, v_abs);
|
||||
|
||||
uint32_t candidate = __vmaxu4(old_min1, v_abs);
|
||||
|
||||
min2 = __vminu4(min2, candidate);
|
||||
currPtr += offset;
|
||||
}
|
||||
|
||||
#pragma unroll
|
||||
for (int temp_MsgIdx = 0; temp_MsgIdx < CnGrpIdxNum; temp_MsgIdx++) {
|
||||
uint32_t target_sign = __vxor4(total_xor, cache_raw[temp_MsgIdx]);
|
||||
|
||||
uint32_t my_abs = cache_abs[temp_MsgIdx];
|
||||
|
||||
uint32_t is_min_mask = __vcmpeq4(my_abs, min1);
|
||||
|
||||
uint32_t final_mag = (min2 & is_min_mask) | (min1 & ~is_min_mask);
|
||||
|
||||
// final_mag = scale_int8x4(final_mag, 0.75);
|
||||
|
||||
uint32_t BricksToBeMoved = __vsign4(final_mag, target_sign);
|
||||
|
||||
uint32_t MsgIdx = Cn2MsgStartIdx + temp_MsgIdx;
|
||||
uint32_t circShift = cn_bn_map_BG1_Z_R13[MsgIdx][ZcIdx];
|
||||
int8_t *p_bnProcBuf = (int8_t *)(d_bnProcBuf + cn_bn_map_BG1_Z_R13[MsgIdx][0]);
|
||||
|
||||
moveBricks_invput_circ(p_bnProcBuf, lane * 4, (uint8_t *)&BricksToBeMoved, Zc, circShift);
|
||||
}
|
||||
}
|
||||
__device__ __forceinline__ void cnProcKernel_BG1_int8_Gn_R23_node(const int8_t *__restrict__ d_cnProcBuf,
|
||||
int8_t *__restrict__ d_bnProcBuf,
|
||||
uint32_t lane,
|
||||
uint32_t CnIdx,
|
||||
uint32_t CnNumInGrp,
|
||||
uint32_t CnGrpIdxNum,
|
||||
uint32_t Cn2MsgStartIdx,
|
||||
uint32_t Zc,
|
||||
uint32_t ZcIdx)
|
||||
{
|
||||
|
||||
uint32_t min1 = 0x7F7F7F7F;
|
||||
uint32_t min2 = 0x7F7F7F7F;
|
||||
uint32_t total_xor = 0;
|
||||
|
||||
uint32_t cache_raw[19];
|
||||
uint32_t cache_abs[19];
|
||||
|
||||
const int32_t *cnProcBufPtr = (const int32_t *)(d_cnProcBuf) + lane;
|
||||
const int32_t *currPtr = cnProcBufPtr;
|
||||
uint32_t offset = (CnNumInGrp * NR_LDPC_ZMAX) >> 2;
|
||||
#pragma unroll
|
||||
for (int MsgIdx = 0; MsgIdx < CnGrpIdxNum; MsgIdx++) {
|
||||
uint32_t val = *currPtr;
|
||||
|
||||
cache_raw[MsgIdx] = val;
|
||||
uint32_t v_abs = __vabs4(val);
|
||||
cache_abs[MsgIdx] = v_abs;
|
||||
|
||||
total_xor = __vxor4(total_xor, val);
|
||||
|
||||
uint32_t old_min1 = min1;
|
||||
|
||||
min1 = __vminu4(old_min1, v_abs);
|
||||
|
||||
uint32_t candidate = __vmaxu4(old_min1, v_abs);
|
||||
|
||||
min2 = __vminu4(min2, candidate);
|
||||
currPtr += offset;
|
||||
}
|
||||
|
||||
#pragma unroll
|
||||
for (int temp_MsgIdx = 0; temp_MsgIdx < CnGrpIdxNum; temp_MsgIdx++) {
|
||||
uint32_t target_sign = __vxor4(total_xor, cache_raw[temp_MsgIdx]);
|
||||
|
||||
uint32_t my_abs = cache_abs[temp_MsgIdx];
|
||||
|
||||
uint32_t is_min_mask = __vcmpeq4(my_abs, min1);
|
||||
|
||||
uint32_t final_mag = (min2 & is_min_mask) | (min1 & ~is_min_mask);
|
||||
|
||||
// final_mag = scale_int8x4(final_mag, 0.75);
|
||||
|
||||
uint32_t BricksToBeMoved = __vsign4(final_mag, target_sign);
|
||||
|
||||
uint32_t MsgIdx = Cn2MsgStartIdx + temp_MsgIdx;
|
||||
uint32_t circShift = cn_bn_map_BG1_Z_R23[MsgIdx][ZcIdx];
|
||||
int8_t *p_bnProcBuf = (int8_t *)(d_bnProcBuf + cn_bn_map_BG1_Z_R23[MsgIdx][0]);
|
||||
|
||||
moveBricks_invput_circ(p_bnProcBuf, lane * 4, (uint8_t *)&BricksToBeMoved, Zc, circShift);
|
||||
}
|
||||
}
|
||||
__device__ __forceinline__ void cnProcKernel_BG1_int8_Gn_R89_node(const int8_t *__restrict__ d_cnProcBuf,
|
||||
int8_t *__restrict__ d_bnProcBuf,
|
||||
uint32_t lane,
|
||||
uint32_t CnIdx,
|
||||
uint32_t CnNumInGrp,
|
||||
uint32_t CnGrpIdxNum,
|
||||
uint32_t Cn2MsgStartIdx,
|
||||
uint32_t Zc,
|
||||
uint32_t ZcIdx)
|
||||
{
|
||||
|
||||
uint32_t min1 = 0x7F7F7F7F;
|
||||
uint32_t min2 = 0x7F7F7F7F;
|
||||
uint32_t total_xor = 0;
|
||||
|
||||
uint32_t cache_raw[19];
|
||||
uint32_t cache_abs[19];
|
||||
|
||||
const int32_t *cnProcBufPtr = (const int32_t *)(d_cnProcBuf) + lane;
|
||||
const int32_t *currPtr = cnProcBufPtr;
|
||||
uint32_t offset = (CnNumInGrp * NR_LDPC_ZMAX) >> 2;
|
||||
#pragma unroll
|
||||
for (int MsgIdx = 0; MsgIdx < CnGrpIdxNum; MsgIdx++) {
|
||||
uint32_t val = *currPtr;
|
||||
|
||||
cache_raw[MsgIdx] = val;
|
||||
uint32_t v_abs = __vabs4(val);
|
||||
cache_abs[MsgIdx] = v_abs;
|
||||
|
||||
total_xor = __vxor4(total_xor, val);
|
||||
|
||||
uint32_t old_min1 = min1;
|
||||
|
||||
min1 = __vminu4(old_min1, v_abs);
|
||||
|
||||
uint32_t candidate = __vmaxu4(old_min1, v_abs);
|
||||
|
||||
min2 = __vminu4(min2, candidate);
|
||||
currPtr += offset;
|
||||
}
|
||||
|
||||
#pragma unroll
|
||||
for (int temp_MsgIdx = 0; temp_MsgIdx < CnGrpIdxNum; temp_MsgIdx++) {
|
||||
uint32_t target_sign = __vxor4(total_xor, cache_raw[temp_MsgIdx]);
|
||||
|
||||
uint32_t my_abs = cache_abs[temp_MsgIdx];
|
||||
|
||||
uint32_t is_min_mask = __vcmpeq4(my_abs, min1);
|
||||
|
||||
uint32_t final_mag = (min2 & is_min_mask) | (min1 & ~is_min_mask);
|
||||
|
||||
// final_mag = scale_int8x4(final_mag, 0.75);
|
||||
|
||||
uint32_t BricksToBeMoved = __vsign4(final_mag, target_sign);
|
||||
|
||||
uint32_t MsgIdx = Cn2MsgStartIdx + temp_MsgIdx;
|
||||
uint32_t circShift = cn_bn_map_BG1_Z_R89[MsgIdx][ZcIdx];
|
||||
int8_t *p_bnProcBuf = (int8_t *)(d_bnProcBuf + cn_bn_map_BG1_Z_R89[MsgIdx][0]);
|
||||
|
||||
moveBricks_invput_circ(p_bnProcBuf, lane * 4, (uint8_t *)&BricksToBeMoved, Zc, circShift);
|
||||
}
|
||||
}
|
||||
__device__ __forceinline__ void cnProcKernel_BG1_int8_G3(const int8_t *__restrict__ p_cnProcBuf,
|
||||
int8_t *__restrict__ p_bnProcBuf,
|
||||
uint32_t row,
|
||||
uint32_t lane,
|
||||
uint32_t idxBn,
|
||||
uint32_t circShift,
|
||||
uint32_t Zc)
|
||||
{
|
||||
uint32_t ymm0, sgn, min;
|
||||
const uint32_t ones = 0x01010101;
|
||||
|
||||
ymm0 = *(const uint32_t *)(p_cnProcBuf + lane * 4 + c_lut_idxG3[row][0] * 4);
|
||||
sgn = __vxor4(ones, ymm0);
|
||||
min = __vabs4(ymm0);
|
||||
|
||||
// loop starts here
|
||||
ymm0 = *(const uint32_t *)(p_cnProcBuf + lane * 4 + c_lut_idxG3[row][1] * 4);
|
||||
|
||||
min = __vminu4(min, __vabs4(ymm0));
|
||||
sgn = __vxor4(sgn, ymm0);
|
||||
|
||||
uint32_t BricksToBeMoved = __vsign4(min, sgn);
|
||||
|
||||
moveBricks_invput_circ((int8_t *)&p_bnProcBuf[idxBn], lane * 4, (uint8_t *)&BricksToBeMoved, Zc, circShift);
|
||||
}
|
||||
|
||||
__device__ __forceinline__ void cnProcKernel_BG1_int8_G4(const int8_t *__restrict__ p_cnProcBuf,
|
||||
int8_t *__restrict__ p_bnProcBuf,
|
||||
uint32_t row,
|
||||
uint32_t lane,
|
||||
uint32_t idxBn,
|
||||
uint32_t circShift,
|
||||
uint32_t Zc)
|
||||
{
|
||||
uint32_t ymm0, sgn, min;
|
||||
const uint32_t ones = 0x01010101;
|
||||
|
||||
ymm0 = *(const uint32_t *)(p_cnProcBuf + lane * 4 + c_lut_idxG4[row][0] * 4);
|
||||
|
||||
sgn = __vxor4(ones, ymm0);
|
||||
min = __vabs4(ymm0);
|
||||
//-------------------------loop starts here-------------------------------
|
||||
ymm0 = *(const uint32_t *)(p_cnProcBuf + lane * 4 + c_lut_idxG4[row][1] * 4);
|
||||
min = __vminu4(min, __vabs4(ymm0));
|
||||
sgn = __vxor4(sgn, ymm0);
|
||||
ymm0 = *(const uint32_t *)(p_cnProcBuf + lane * 4 + c_lut_idxG4[row][2] * 4);
|
||||
min = __vminu4(min, __vabs4(ymm0));
|
||||
sgn = __vxor4(sgn, ymm0);
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
uint32_t BricksToBeMoved = __vsign4(min, sgn);
|
||||
|
||||
moveBricks_invput_circ((int8_t *)&p_bnProcBuf[idxBn], lane * 4, (uint8_t *)&BricksToBeMoved, Zc, circShift);
|
||||
}
|
||||
|
||||
__device__ __forceinline__ void cnProcKernel_BG1_int8_G5(const int8_t *__restrict__ p_cnProcBuf,
|
||||
int8_t *__restrict__ p_bnProcBuf,
|
||||
uint32_t row,
|
||||
uint32_t lane,
|
||||
uint32_t idxBn,
|
||||
uint32_t circShift,
|
||||
uint32_t Zc)
|
||||
{
|
||||
uint32_t ymm0, sgn, min;
|
||||
const uint32_t ones = 0x01010101;
|
||||
|
||||
ymm0 = *(const uint32_t *)(p_cnProcBuf + lane * 4 + c_lut_idxG5[row][0] * 4);
|
||||
sgn = __vxor4(ones, ymm0);
|
||||
min = __vabs4(ymm0);
|
||||
|
||||
//-------------------------loop starts here-------------------------------
|
||||
ymm0 = *(const uint32_t *)(p_cnProcBuf + lane * 4 + c_lut_idxG5[row][1] * 4);
|
||||
min = __vminu4(min, __vabs4(ymm0));
|
||||
sgn = __vxor4(sgn, ymm0);
|
||||
ymm0 = *(const uint32_t *)(p_cnProcBuf + lane * 4 + c_lut_idxG5[row][2] * 4);
|
||||
min = __vminu4(min, __vabs4(ymm0));
|
||||
sgn = __vxor4(sgn, ymm0);
|
||||
ymm0 = *(const uint32_t *)(p_cnProcBuf + lane * 4 + c_lut_idxG5[row][3] * 4);
|
||||
min = __vminu4(min, __vabs4(ymm0));
|
||||
sgn = __vxor4(sgn, ymm0);
|
||||
//-------------------------------------------------------------------------
|
||||
uint32_t BricksToBeMoved = __vsign4(min, sgn);
|
||||
|
||||
moveBricks_invput_circ((int8_t *)&p_bnProcBuf[idxBn], lane * 4, (uint8_t *)&BricksToBeMoved, Zc, circShift);
|
||||
}
|
||||
|
||||
__device__ __forceinline__ void cnProcKernel_BG1_int8_G6(const int8_t *__restrict__ p_cnProcBuf,
|
||||
int8_t *__restrict__ p_bnProcBuf,
|
||||
uint32_t row,
|
||||
uint32_t lane,
|
||||
uint32_t idxBn,
|
||||
uint32_t circShift,
|
||||
uint32_t Zc)
|
||||
{
|
||||
uint32_t ymm0, sgn, min;
|
||||
const uint32_t ones = 0x01010101;
|
||||
|
||||
ymm0 = *(const uint32_t *)(p_cnProcBuf + lane * 4 + c_lut_idxG6[row][0] * 4);
|
||||
sgn = __vxor4(ones, ymm0);
|
||||
min = __vabs4(ymm0);
|
||||
|
||||
//-------------------------loop starts here-------------------------------
|
||||
ymm0 = *(const uint32_t *)(p_cnProcBuf + lane * 4 + c_lut_idxG6[row][1] * 4);
|
||||
min = __vminu4(min, __vabs4(ymm0));
|
||||
sgn = __vxor4(sgn, ymm0);
|
||||
ymm0 = *(const uint32_t *)(p_cnProcBuf + lane * 4 + c_lut_idxG6[row][2] * 4);
|
||||
min = __vminu4(min, __vabs4(ymm0));
|
||||
sgn = __vxor4(sgn, ymm0);
|
||||
ymm0 = *(const uint32_t *)(p_cnProcBuf + lane * 4 + c_lut_idxG6[row][3] * 4);
|
||||
min = __vminu4(min, __vabs4(ymm0));
|
||||
sgn = __vxor4(sgn, ymm0);
|
||||
ymm0 = *(const uint32_t *)(p_cnProcBuf + lane * 4 + c_lut_idxG6[row][4] * 4);
|
||||
min = __vminu4(min, __vabs4(ymm0));
|
||||
sgn = __vxor4(sgn, ymm0);
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
uint32_t BricksToBeMoved = __vsign4(min, sgn);
|
||||
|
||||
moveBricks_invput_circ((int8_t *)&p_bnProcBuf[idxBn], lane * 4, (uint8_t *)&BricksToBeMoved, Zc, circShift);
|
||||
}
|
||||
|
||||
__device__ __forceinline__ void cnProcKernel_BG1_int8_G7(const int8_t *__restrict__ p_cnProcBuf,
|
||||
int8_t *__restrict__ p_bnProcBuf,
|
||||
uint32_t row,
|
||||
uint32_t lane,
|
||||
uint32_t idxBn,
|
||||
uint32_t circShift,
|
||||
uint32_t Zc)
|
||||
{
|
||||
uint32_t ymm0, sgn, min;
|
||||
const uint32_t ones = 0x01010101;
|
||||
|
||||
ymm0 = *(const uint32_t *)(p_cnProcBuf + lane * 4 + c_lut_idxG7[row][0] * 4);
|
||||
sgn = __vxor4(ones, ymm0);
|
||||
min = __vabs4(ymm0);
|
||||
|
||||
//-------------------------loop starts here-------------------------------
|
||||
ymm0 = *(const uint32_t *)(p_cnProcBuf + lane * 4 + c_lut_idxG7[row][1] * 4);
|
||||
min = __vminu4(min, __vabs4(ymm0));
|
||||
sgn = __vxor4(sgn, ymm0);
|
||||
ymm0 = *(const uint32_t *)(p_cnProcBuf + lane * 4 + c_lut_idxG7[row][2] * 4);
|
||||
min = __vminu4(min, __vabs4(ymm0));
|
||||
sgn = __vxor4(sgn, ymm0);
|
||||
ymm0 = *(const uint32_t *)(p_cnProcBuf + lane * 4 + c_lut_idxG7[row][3] * 4);
|
||||
min = __vminu4(min, __vabs4(ymm0));
|
||||
sgn = __vxor4(sgn, ymm0);
|
||||
ymm0 = *(const uint32_t *)(p_cnProcBuf + lane * 4 + c_lut_idxG7[row][4] * 4);
|
||||
min = __vminu4(min, __vabs4(ymm0));
|
||||
sgn = __vxor4(sgn, ymm0);
|
||||
ymm0 = *(const uint32_t *)(p_cnProcBuf + lane * 4 + c_lut_idxG7[row][5] * 4);
|
||||
min = __vminu4(min, __vabs4(ymm0));
|
||||
sgn = __vxor4(sgn, ymm0);
|
||||
//-------------------------------------------------------------------------
|
||||
uint32_t BricksToBeMoved = __vsign4(min, sgn);
|
||||
|
||||
moveBricks_invput_circ((int8_t *)&p_bnProcBuf[idxBn], lane * 4, (uint8_t *)&BricksToBeMoved, Zc, circShift);
|
||||
}
|
||||
|
||||
__device__ __forceinline__ void cnProcKernel_BG1_int8_G8(const int8_t *__restrict__ p_cnProcBuf,
|
||||
int8_t *__restrict__ p_bnProcBuf,
|
||||
uint32_t row,
|
||||
uint32_t lane,
|
||||
uint32_t idxBn,
|
||||
uint32_t circShift,
|
||||
uint32_t Zc)
|
||||
{
|
||||
uint32_t ymm0, sgn, min;
|
||||
const uint32_t ones = 0x01010101;
|
||||
|
||||
ymm0 = *(const uint32_t *)(p_cnProcBuf + lane * 4 + c_lut_idxG8[row][0] * 4);
|
||||
sgn = __vxor4(ones, ymm0);
|
||||
min = __vabs4(ymm0);
|
||||
|
||||
//-------------------------loop starts here-------------------------------
|
||||
ymm0 = *(const uint32_t *)(p_cnProcBuf + lane * 4 + c_lut_idxG8[row][1] * 4);
|
||||
min = __vminu4(min, __vabs4(ymm0));
|
||||
sgn = __vxor4(sgn, ymm0);
|
||||
ymm0 = *(const uint32_t *)(p_cnProcBuf + lane * 4 + c_lut_idxG8[row][2] * 4);
|
||||
min = __vminu4(min, __vabs4(ymm0));
|
||||
sgn = __vxor4(sgn, ymm0);
|
||||
ymm0 = *(const uint32_t *)(p_cnProcBuf + lane * 4 + c_lut_idxG8[row][3] * 4);
|
||||
min = __vminu4(min, __vabs4(ymm0));
|
||||
sgn = __vxor4(sgn, ymm0);
|
||||
ymm0 = *(const uint32_t *)(p_cnProcBuf + lane * 4 + c_lut_idxG8[row][4] * 4);
|
||||
min = __vminu4(min, __vabs4(ymm0));
|
||||
sgn = __vxor4(sgn, ymm0);
|
||||
ymm0 = *(const uint32_t *)(p_cnProcBuf + lane * 4 + c_lut_idxG8[row][5] * 4);
|
||||
min = __vminu4(min, __vabs4(ymm0));
|
||||
sgn = __vxor4(sgn, ymm0);
|
||||
ymm0 = *(const uint32_t *)(p_cnProcBuf + lane * 4 + c_lut_idxG8[row][6] * 4);
|
||||
min = __vminu4(min, __vabs4(ymm0));
|
||||
sgn = __vxor4(sgn, ymm0);
|
||||
//-------------------------------------------------------------------------
|
||||
uint32_t BricksToBeMoved = __vsign4(min, sgn);
|
||||
|
||||
moveBricks_invput_circ((int8_t *)&p_bnProcBuf[idxBn], lane * 4, (uint8_t *)&BricksToBeMoved, Zc, circShift);
|
||||
}
|
||||
|
||||
__device__ __forceinline__ void cnProcKernel_BG1_int8_G9(const int8_t *__restrict__ p_cnProcBuf,
|
||||
int8_t *__restrict__ p_bnProcBuf,
|
||||
uint32_t row,
|
||||
uint32_t lane,
|
||||
uint32_t idxBn,
|
||||
uint32_t circShift,
|
||||
uint32_t Zc)
|
||||
{
|
||||
uint32_t ymm0, sgn, min;
|
||||
const uint32_t ones = 0x01010101;
|
||||
|
||||
ymm0 = *(const uint32_t *)(p_cnProcBuf + lane * 4 + c_lut_idxG9[row][0] * 4);
|
||||
sgn = __vxor4(ones, ymm0);
|
||||
min = __vabs4(ymm0);
|
||||
|
||||
//-------------------------loop starts here-------------------------------
|
||||
ymm0 = *(const uint32_t *)(p_cnProcBuf + lane * 4 + c_lut_idxG9[row][1] * 4);
|
||||
min = __vminu4(min, __vabs4(ymm0));
|
||||
sgn = __vxor4(sgn, ymm0);
|
||||
ymm0 = *(const uint32_t *)(p_cnProcBuf + lane * 4 + c_lut_idxG9[row][2] * 4);
|
||||
min = __vminu4(min, __vabs4(ymm0));
|
||||
sgn = __vxor4(sgn, ymm0);
|
||||
ymm0 = *(const uint32_t *)(p_cnProcBuf + lane * 4 + c_lut_idxG9[row][3] * 4);
|
||||
min = __vminu4(min, __vabs4(ymm0));
|
||||
sgn = __vxor4(sgn, ymm0);
|
||||
ymm0 = *(const uint32_t *)(p_cnProcBuf + lane * 4 + c_lut_idxG9[row][4] * 4);
|
||||
min = __vminu4(min, __vabs4(ymm0));
|
||||
sgn = __vxor4(sgn, ymm0);
|
||||
ymm0 = *(const uint32_t *)(p_cnProcBuf + lane * 4 + c_lut_idxG9[row][5] * 4);
|
||||
min = __vminu4(min, __vabs4(ymm0));
|
||||
sgn = __vxor4(sgn, ymm0);
|
||||
ymm0 = *(const uint32_t *)(p_cnProcBuf + lane * 4 + c_lut_idxG9[row][6] * 4);
|
||||
min = __vminu4(min, __vabs4(ymm0));
|
||||
sgn = __vxor4(sgn, ymm0);
|
||||
ymm0 = *(const uint32_t *)(p_cnProcBuf + lane * 4 + c_lut_idxG9[row][7] * 4);
|
||||
min = __vminu4(min, __vabs4(ymm0));
|
||||
sgn = __vxor4(sgn, ymm0);
|
||||
//-------------------------------------------------------------------------
|
||||
uint32_t BricksToBeMoved = __vsign4(min, sgn);
|
||||
|
||||
moveBricks_invput_circ((int8_t *)&p_bnProcBuf[idxBn], lane * 4, (uint8_t *)&BricksToBeMoved, Zc, circShift);
|
||||
}
|
||||
|
||||
__device__ __forceinline__ void cnProcKernel_BG1_int8_G10(const int8_t *__restrict__ p_cnProcBuf,
|
||||
int8_t *__restrict__ p_bnProcBuf,
|
||||
uint32_t row,
|
||||
uint32_t lane,
|
||||
uint32_t idxBn,
|
||||
uint32_t circShift,
|
||||
uint32_t Zc)
|
||||
{
|
||||
uint32_t ymm0, sgn, min;
|
||||
const uint32_t ones = 0x01010101;
|
||||
|
||||
ymm0 = *(const uint32_t *)(p_cnProcBuf + lane * 4 + c_lut_idxG10[row][0] * 4);
|
||||
sgn = __vxor4(ones, ymm0);
|
||||
min = __vabs4(ymm0);
|
||||
|
||||
//-------------------------loop starts here-------------------------------
|
||||
ymm0 = *(const uint32_t *)(p_cnProcBuf + lane * 4 + c_lut_idxG10[row][1] * 4);
|
||||
min = __vminu4(min, __vabs4(ymm0));
|
||||
sgn = __vxor4(sgn, ymm0);
|
||||
ymm0 = *(const uint32_t *)(p_cnProcBuf + lane * 4 + c_lut_idxG10[row][2] * 4);
|
||||
min = __vminu4(min, __vabs4(ymm0));
|
||||
sgn = __vxor4(sgn, ymm0);
|
||||
ymm0 = *(const uint32_t *)(p_cnProcBuf + lane * 4 + c_lut_idxG10[row][3] * 4);
|
||||
min = __vminu4(min, __vabs4(ymm0));
|
||||
sgn = __vxor4(sgn, ymm0);
|
||||
ymm0 = *(const uint32_t *)(p_cnProcBuf + lane * 4 + c_lut_idxG10[row][4] * 4);
|
||||
min = __vminu4(min, __vabs4(ymm0));
|
||||
sgn = __vxor4(sgn, ymm0);
|
||||
ymm0 = *(const uint32_t *)(p_cnProcBuf + lane * 4 + c_lut_idxG10[row][5] * 4);
|
||||
min = __vminu4(min, __vabs4(ymm0));
|
||||
sgn = __vxor4(sgn, ymm0);
|
||||
ymm0 = *(const uint32_t *)(p_cnProcBuf + lane * 4 + c_lut_idxG10[row][6] * 4);
|
||||
min = __vminu4(min, __vabs4(ymm0));
|
||||
sgn = __vxor4(sgn, ymm0);
|
||||
ymm0 = *(const uint32_t *)(p_cnProcBuf + lane * 4 + c_lut_idxG10[row][7] * 4);
|
||||
min = __vminu4(min, __vabs4(ymm0));
|
||||
sgn = __vxor4(sgn, ymm0);
|
||||
ymm0 = *(const uint32_t *)(p_cnProcBuf + lane * 4 + c_lut_idxG10[row][8] * 4);
|
||||
min = __vminu4(min, __vabs4(ymm0));
|
||||
sgn = __vxor4(sgn, ymm0);
|
||||
//-------------------------------------------------------------------------
|
||||
uint32_t BricksToBeMoved = __vsign4(min, sgn);
|
||||
|
||||
moveBricks_invput_circ((int8_t *)&p_bnProcBuf[idxBn], lane * 4, (uint8_t *)&BricksToBeMoved, Zc, circShift);
|
||||
}
|
||||
|
||||
__device__ __forceinline__ void cnProcKernel_BG1_int8_G19(const int8_t *__restrict__ p_cnProcBuf,
|
||||
int8_t *__restrict__ p_bnProcBuf,
|
||||
uint32_t row,
|
||||
uint32_t lane,
|
||||
uint32_t idxBn,
|
||||
uint32_t circShift,
|
||||
uint32_t Zc)
|
||||
{
|
||||
uint32_t ymm0, sgn, min;
|
||||
const uint32_t ones = 0x01010101;
|
||||
|
||||
ymm0 = *(const uint32_t *)(p_cnProcBuf + lane * 4 + c_lut_idxG19[row][0] * 4);
|
||||
|
||||
sgn = __vxor4(ones, ymm0);
|
||||
min = __vabs4(ymm0);
|
||||
|
||||
//-------------------------loop starts here-------------------------------
|
||||
ymm0 = *(const uint32_t *)(p_cnProcBuf + lane * 4 + c_lut_idxG19[row][1] * 4);
|
||||
min = __vminu4(min, __vabs4(ymm0));
|
||||
sgn = __vxor4(sgn, ymm0);
|
||||
ymm0 = *(const uint32_t *)(p_cnProcBuf + lane * 4 + c_lut_idxG19[row][2] * 4);
|
||||
min = __vminu4(min, __vabs4(ymm0));
|
||||
sgn = __vxor4(sgn, ymm0);
|
||||
ymm0 = *(const uint32_t *)(p_cnProcBuf + lane * 4 + c_lut_idxG19[row][3] * 4);
|
||||
min = __vminu4(min, __vabs4(ymm0));
|
||||
sgn = __vxor4(sgn, ymm0);
|
||||
ymm0 = *(const uint32_t *)(p_cnProcBuf + lane * 4 + c_lut_idxG19[row][4] * 4);
|
||||
min = __vminu4(min, __vabs4(ymm0));
|
||||
sgn = __vxor4(sgn, ymm0);
|
||||
ymm0 = *(const uint32_t *)(p_cnProcBuf + lane * 4 + c_lut_idxG19[row][5] * 4);
|
||||
min = __vminu4(min, __vabs4(ymm0));
|
||||
sgn = __vxor4(sgn, ymm0);
|
||||
ymm0 = *(const uint32_t *)(p_cnProcBuf + lane * 4 + c_lut_idxG19[row][6] * 4);
|
||||
min = __vminu4(min, __vabs4(ymm0));
|
||||
sgn = __vxor4(sgn, ymm0);
|
||||
ymm0 = *(const uint32_t *)(p_cnProcBuf + lane * 4 + c_lut_idxG19[row][7] * 4);
|
||||
min = __vminu4(min, __vabs4(ymm0));
|
||||
sgn = __vxor4(sgn, ymm0);
|
||||
ymm0 = *(const uint32_t *)(p_cnProcBuf + lane * 4 + c_lut_idxG19[row][8] * 4);
|
||||
min = __vminu4(min, __vabs4(ymm0));
|
||||
sgn = __vxor4(sgn, ymm0);
|
||||
ymm0 = *(const uint32_t *)(p_cnProcBuf + lane * 4 + c_lut_idxG19[row][9] * 4);
|
||||
min = __vminu4(min, __vabs4(ymm0));
|
||||
sgn = __vxor4(sgn, ymm0);
|
||||
ymm0 = *(const uint32_t *)(p_cnProcBuf + lane * 4 + c_lut_idxG19[row][10] * 4);
|
||||
min = __vminu4(min, __vabs4(ymm0));
|
||||
sgn = __vxor4(sgn, ymm0);
|
||||
ymm0 = *(const uint32_t *)(p_cnProcBuf + lane * 4 + c_lut_idxG19[row][11] * 4);
|
||||
min = __vminu4(min, __vabs4(ymm0));
|
||||
sgn = __vxor4(sgn, ymm0);
|
||||
ymm0 = *(const uint32_t *)(p_cnProcBuf + lane * 4 + c_lut_idxG19[row][12] * 4);
|
||||
min = __vminu4(min, __vabs4(ymm0));
|
||||
sgn = __vxor4(sgn, ymm0);
|
||||
ymm0 = *(const uint32_t *)(p_cnProcBuf + lane * 4 + c_lut_idxG19[row][13] * 4);
|
||||
min = __vminu4(min, __vabs4(ymm0));
|
||||
sgn = __vxor4(sgn, ymm0);
|
||||
ymm0 = *(const uint32_t *)(p_cnProcBuf + lane * 4 + c_lut_idxG19[row][14] * 4);
|
||||
min = __vminu4(min, __vabs4(ymm0));
|
||||
sgn = __vxor4(sgn, ymm0);
|
||||
ymm0 = *(const uint32_t *)(p_cnProcBuf + lane * 4 + c_lut_idxG19[row][15] * 4);
|
||||
min = __vminu4(min, __vabs4(ymm0));
|
||||
sgn = __vxor4(sgn, ymm0);
|
||||
ymm0 = *(const uint32_t *)(p_cnProcBuf + lane * 4 + c_lut_idxG19[row][16] * 4);
|
||||
min = __vminu4(min, __vabs4(ymm0));
|
||||
sgn = __vxor4(sgn, ymm0);
|
||||
ymm0 = *(const uint32_t *)(p_cnProcBuf + lane * 4 + c_lut_idxG19[row][17] * 4);
|
||||
min = __vminu4(min, __vabs4(ymm0));
|
||||
sgn = __vxor4(sgn, ymm0);
|
||||
//-------------------------------------------------------------------------
|
||||
uint32_t BricksToBeMoved = __vsign4(min, sgn);
|
||||
|
||||
moveBricks_invput_circ((int8_t *)&p_bnProcBuf[idxBn], lane * 4, (uint8_t *)&BricksToBeMoved, Zc, circShift);
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,186 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: LicenseRef-CSSL-1.0
|
||||
*/
|
||||
/*! \file nrLDPC_CUDA_mPassKernel.h
|
||||
* \brief Defines the kernels for message passing in CUDA version of LDPC decoder
|
||||
* \author Qizhi Pan, Raymond Knopp
|
||||
* \company EURECOM
|
||||
* \email: qizhi.pan@eurecom.fr, raymond.knopp@eurecom.fr
|
||||
* \date 2025-12-30
|
||||
* \version 1.0
|
||||
* \note
|
||||
* \warning
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <cuda_runtime.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include "nrLDPC_CUDA_public.h"
|
||||
#include "nrLDPC_CUDA_shared_param.h"
|
||||
|
||||
__device__ __forceinline__ void llrPreProc_Kernel_BG1_int8_Gn_stream(const int8_t *p_llr,
|
||||
int8_t *p_llrProcBuf,
|
||||
int8_t *p_cnProcBuf,
|
||||
uint32_t MsgIdx,
|
||||
uint32_t lane,
|
||||
uint32_t colIdx,
|
||||
uint32_t idxBn,
|
||||
uint32_t GrpIdx,
|
||||
uint32_t circShift,
|
||||
uint32_t Zc,
|
||||
uint32_t R)
|
||||
{
|
||||
{
|
||||
uint32_t *p_cnProcBufBit;
|
||||
|
||||
uint8_t bricksLocal[4];
|
||||
uint8_t *BricksToBeMoved = bricksLocal;
|
||||
|
||||
p_cnProcBufBit = (uint32_t *)(p_cnProcBuf + d_lut_numCnInCnGroups_BG1_R13[GrpIdx] * NR_LDPC_ZMAX * MsgIdx + lane * 4);
|
||||
|
||||
moveBricks_invget_circ((int8_t *)&p_llr[idxBn * Zc], lane * 4, BricksToBeMoved, Zc, circShift);
|
||||
|
||||
*p_cnProcBufBit = *(uint32_t *)BricksToBeMoved;
|
||||
}
|
||||
|
||||
if (colIdx >= 68)
|
||||
return;
|
||||
|
||||
const uint8_t numBn2CnG1 =
|
||||
(R == 13) ? d_lut_numBnInBnGroups_BG1_R13[0]
|
||||
: ((R == 89) ? d_lut_numBnInBnGroups_BG1_R89[0] : d_lut_numBnInBnGroups_BG1_R23[0]); // for R13 is 42
|
||||
const uint32_t startColParity = NR_LDPC_START_COL_PARITY_BG1; // 26 for BG1
|
||||
const uint32_t colG1 = startColParity * Zc;
|
||||
|
||||
const uint32_t *lut_llr2llrProcBufAddr =
|
||||
(R == 13) ? d_llr2llrProcBufAddr_BG1_R13 : ((R == 89) ? d_llr2llrProcBufAddr_BG1_R89 : d_llr2llrProcBufAddr_BG1_R23);
|
||||
const uint32_t *lut_llr2llrProcBufBnPos =
|
||||
(R == 13) ? d_llr2llrProcBufBnPos_BG1_R13 : ((R == 89) ? d_llr2llrProcBufBnPos_BG1_R89 : d_llr2llrProcBufBnPos_BG1_R23);
|
||||
|
||||
if (colIdx < startColParity) {
|
||||
const uint32_t idxBn = lut_llr2llrProcBufAddr[colIdx] + lut_llr2llrProcBufBnPos[colIdx] * NR_LDPC_ZMAX;
|
||||
int32_t *dst = (int32_t *)(&p_llrProcBuf[idxBn] + lane * 4);
|
||||
int32_t *src = (int32_t *)(&p_llr[colIdx * Zc] + lane * 4);
|
||||
*dst = *src;
|
||||
} else {
|
||||
colIdx = colIdx - startColParity;
|
||||
if (numBn2CnG1 > 0 && colIdx < numBn2CnG1) {
|
||||
int32_t *dst = (int32_t *)(&p_llrProcBuf[colIdx * NR_LDPC_ZMAX] + lane * 4);
|
||||
int32_t *src = (int32_t *)(&p_llr[colG1 + colIdx * Zc] + lane * 4);
|
||||
*dst = *src;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
__device__ void llr2bit_Kernel_BG1_int8(uint32_t R,
|
||||
uint8_t *__restrict__ out,
|
||||
const int8_t *__restrict__ llrRes,
|
||||
uint32_t numLLR,
|
||||
uint32_t Zc)
|
||||
{
|
||||
uint32_t lane = threadIdx.x;
|
||||
uint32_t outColIdx = (blockIdx.x << 2) + threadIdx.y;
|
||||
|
||||
if (outColIdx >= num_TotalBlocks_llr_llrRes)
|
||||
return;
|
||||
|
||||
// Constants Setup
|
||||
const uint8_t numBn2CnG1 = (R == 13) ? d_lut_numBnInBnGroups_BG1_R13[0]
|
||||
: ((R == 89) ? d_lut_numBnInBnGroups_BG1_R89[0] : d_lut_numBnInBnGroups_BG1_R23[0]);
|
||||
const uint32_t startColParity = NR_LDPC_START_COL_PARITY_BG1;
|
||||
const uint32_t *lut_Addr =
|
||||
(R == 13) ? d_llr2llrProcBufAddr_BG1_R13 : ((R == 89) ? d_llr2llrProcBufAddr_BG1_R89 : d_llr2llrProcBufAddr_BG1_R23);
|
||||
const uint32_t *lut_Pos =
|
||||
(R == 13) ? d_llr2llrProcBufBnPos_BG1_R13 : ((R == 89) ? d_llr2llrProcBufBnPos_BG1_R89 : d_llr2llrProcBufBnPos_BG1_R23);
|
||||
|
||||
int32_t raw_llrs;
|
||||
|
||||
// Load Data: Handle Systematic (Scatter/Gather) vs Parity (Linear) mapping
|
||||
if (outColIdx < startColParity) {
|
||||
uint32_t idxBn = lut_Addr[outColIdx] + lut_Pos[outColIdx] * NR_LDPC_ZMAX;
|
||||
raw_llrs = *(const int32_t *)(&llrRes[idxBn] + lane * 4);
|
||||
} else {
|
||||
uint32_t srcParityIdx = outColIdx - startColParity;
|
||||
if (numBn2CnG1 > 0 && outColIdx < numBn2CnG1) {
|
||||
raw_llrs = *(const int32_t *)(llrRes + srcParityIdx * NR_LDPC_ZMAX + lane * 4);
|
||||
} else {
|
||||
raw_llrs = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Hard Decision: Convert 4 int8 LLRs -> 4 bytes (0 or 1)
|
||||
int8_t *p_val = (int8_t *)&raw_llrs;
|
||||
uint32_t my_word = 0;
|
||||
|
||||
#pragma unroll
|
||||
for (int i = 0; i < 4; i++) {
|
||||
// Hard decision: LLR < 0 implies bit 1
|
||||
uint32_t byte_val = (p_val[i] < 0) ? 1 : 0;
|
||||
my_word |= (byte_val << (i * 8));
|
||||
}
|
||||
|
||||
// Store output linearly
|
||||
*(uint32_t *)(&out[outColIdx * Zc + lane * 4]) = my_word;
|
||||
}
|
||||
|
||||
__device__ void llr2bitPacked_Kernel_BG1_int8(uint32_t R,
|
||||
uint8_t *__restrict__ out,
|
||||
const int8_t *__restrict__ llrRes,
|
||||
uint32_t numLLR,
|
||||
uint32_t Zc)
|
||||
{
|
||||
uint32_t lane = threadIdx.x;
|
||||
uint32_t outColIdx = (blockIdx.x << 2) + threadIdx.y;
|
||||
|
||||
if (outColIdx >= num_TotalBlocks_llr_llrRes)
|
||||
return;
|
||||
|
||||
const uint8_t numBn2CnG1 = (R == 13) ? d_lut_numBnInBnGroups_BG1_R13[0]
|
||||
: ((R == 89) ? d_lut_numBnInBnGroups_BG1_R89[0] : d_lut_numBnInBnGroups_BG1_R23[0]);
|
||||
const uint32_t startColParity = NR_LDPC_START_COL_PARITY_BG1;
|
||||
const uint32_t *lut_Addr =
|
||||
(R == 13) ? d_llr2llrProcBufAddr_BG1_R13 : ((R == 89) ? d_llr2llrProcBufAddr_BG1_R89 : d_llr2llrProcBufAddr_BG1_R23);
|
||||
const uint32_t *lut_Pos =
|
||||
(R == 13) ? d_llr2llrProcBufBnPos_BG1_R13 : ((R == 89) ? d_llr2llrProcBufBnPos_BG1_R89 : d_llr2llrProcBufBnPos_BG1_R23);
|
||||
|
||||
int32_t raw_llrs;
|
||||
|
||||
// Load Data: Handle Systematic vs Parity mapping
|
||||
if (outColIdx < startColParity) {
|
||||
uint32_t idxBn = lut_Addr[outColIdx] + lut_Pos[outColIdx] * NR_LDPC_ZMAX;
|
||||
raw_llrs = *(const int32_t *)(&llrRes[idxBn] + lane * 4);
|
||||
} else {
|
||||
uint32_t srcParityIdx = outColIdx - startColParity;
|
||||
if (numBn2CnG1 > 0 && outColIdx < numBn2CnG1) {
|
||||
raw_llrs = *(const int32_t *)(llrRes + srcParityIdx * NR_LDPC_ZMAX + lane * 4);
|
||||
} else {
|
||||
raw_llrs = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Extract 4 bits from 4 LLRs (Local Packing)
|
||||
// Assuming MSB order within nibble: [3][2][1][0]
|
||||
uint32_t my_4_bits = 0;
|
||||
int8_t *p_val = (int8_t *)&raw_llrs;
|
||||
|
||||
#pragma unroll
|
||||
for (int i = 0; i < 4; i++) {
|
||||
if (p_val[i] < 0) {
|
||||
my_4_bits |= (1 << (3 - i));
|
||||
}
|
||||
}
|
||||
|
||||
// Thread Cooperation: Pair threads to pack 8 bits (1 byte)
|
||||
// Even thread (0,2..) takes low nibble, Odd thread (1,3..) takes high nibble.
|
||||
uint32_t neighbor_bits = __shfl_xor_sync(0xffffffff, my_4_bits, 1);
|
||||
|
||||
if ((lane & 1) == 0) {
|
||||
// Combine: [Odd Thread Bits (High)] | [My Bits (Low)]
|
||||
uint8_t packed_byte = (neighbor_bits & 0xF) | ((my_4_bits & 0xF) << 4);
|
||||
|
||||
// Output addr: lane steps by 4 LLRs, but we output 1 byte per 8 LLRs -> lane >> 1
|
||||
uint32_t outAddr = outColIdx * (Zc >> 3) + (lane >> 1);
|
||||
out[outAddr] = packed_byte;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,120 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: LicenseRef-CSSL-1.0
|
||||
*/
|
||||
/*! \file nrLDPC_CUDA_public.h
|
||||
* \brief Shared functions in CUDA implementation of LDPC decoder
|
||||
* \author Qizhi Pan, Raymond Knopp
|
||||
* \company EURECOM
|
||||
* \email: qizhi.pan@eurecom.fr, raymond.knopp@eurecom.fr
|
||||
* \date 2025-12-30
|
||||
* \version 1.0
|
||||
* \note
|
||||
* \warning
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cuda_runtime.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <cuda_runtime.h>
|
||||
#include <stdint.h>
|
||||
|
||||
|
||||
__device__ __forceinline__ void moveBricks_invput_circ(int8_t *__restrict__ dstBuf,
|
||||
uint32_t dstBuf_Offset,
|
||||
const uint8_t *__restrict__ Four_Bricks,
|
||||
uint32_t Z,
|
||||
uint32_t cshift)
|
||||
{
|
||||
uint32_t tmp = cshift + dstBuf_Offset;
|
||||
uint32_t pos = (tmp >= Z) ? tmp - Z : tmp;
|
||||
|
||||
if (pos <= Z - 4) {
|
||||
uint32_t val = *(const uint32_t*)Four_Bricks;
|
||||
memcpy(dstBuf + pos, &val, 4);
|
||||
}
|
||||
else {
|
||||
uint32_t bytes_at_end = Z - pos; // 1, 2, or 3
|
||||
|
||||
#pragma unroll
|
||||
for(int i=0; i<4; i++) {
|
||||
if (i < bytes_at_end) {
|
||||
dstBuf[pos + i] = Four_Bricks[i];
|
||||
} else {
|
||||
dstBuf[i - bytes_at_end] = Four_Bricks[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
__device__ __forceinline__ void moveBricks_forput_circ(int8_t *__restrict__ dstBuf,
|
||||
uint32_t dstBuf_Offset,
|
||||
const uint8_t *__restrict__ Four_Bricks,
|
||||
uint32_t Z,
|
||||
uint32_t cshift)
|
||||
{
|
||||
uint32_t tmp = dstBuf_Offset + Z - cshift;
|
||||
uint32_t pos = (tmp >= Z) ? tmp - Z : tmp;
|
||||
|
||||
if (pos <= Z - 4) {
|
||||
uint32_t val = *(const uint32_t*)Four_Bricks;
|
||||
memcpy(dstBuf + pos, &val, 4);
|
||||
}
|
||||
else {
|
||||
uint32_t bytes_at_end = Z - pos;
|
||||
|
||||
#pragma unroll
|
||||
for(int i=0; i<4; i++) {
|
||||
if (i < bytes_at_end) {
|
||||
dstBuf[pos + i] = Four_Bricks[i];
|
||||
} else {
|
||||
dstBuf[i - bytes_at_end] = Four_Bricks[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
__device__ __forceinline__ void moveBricks_invget_circ(const int8_t *__restrict__ dstBuf,
|
||||
uint32_t dstBuf_Offset,
|
||||
uint8_t *__restrict__ Four_Bricks,
|
||||
uint32_t Z,
|
||||
uint32_t cshift)
|
||||
{
|
||||
uint32_t tmp = cshift + dstBuf_Offset;
|
||||
uint32_t pos = (tmp >= Z) ? tmp - Z : tmp;
|
||||
|
||||
if (pos <= Z - 4) {
|
||||
uint32_t val;
|
||||
memcpy(&val, dstBuf + pos, 4);
|
||||
*(uint32_t*)Four_Bricks = val;
|
||||
}
|
||||
else {
|
||||
uint32_t bytes_at_end = Z - pos;
|
||||
|
||||
#pragma unroll
|
||||
for(int i=0; i<4; i++) {
|
||||
if (i < bytes_at_end) {
|
||||
Four_Bricks[i] = dstBuf[pos + i];
|
||||
} else {
|
||||
Four_Bricks[i] = dstBuf[i - bytes_at_end];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
__device__ __forceinline__ uint32_t __vxor4(const uint32_t a, uint32_t b)
|
||||
{
|
||||
return a ^ b;
|
||||
}
|
||||
|
||||
__device__ __forceinline__ uint32_t __vsign4(const uint32_t a, uint32_t b)
|
||||
{
|
||||
uint32_t mask = __vcmplts4(b, 0);
|
||||
uint32_t bneg = __vneg4(a);
|
||||
return (mask & bneg) | (~mask & a);
|
||||
//uint32_t is_zero_mask = __vcmpeq4(b, 0);
|
||||
//return result & (~is_zero_mask);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: LicenseRef-CSSL-1.0
|
||||
*/
|
||||
/*! \file nrLDPC_CUDA_shared_param.h
|
||||
* \brief Shared parameters in CUDA implementation of LDPC decoder
|
||||
* \author Qizhi Pan, Raymond Knopp
|
||||
* \company EURECOM
|
||||
* \email: qizhi.pan@eurecom.fr, raymond.knopp@eurecom.fr
|
||||
* \date 2025-12-30
|
||||
* \version 1.0
|
||||
* \note
|
||||
* \warning
|
||||
*/
|
||||
|
||||
#ifndef NRLDPC_CUDA_SHARED_PARAM_H_
|
||||
#define NRLDPC_CUDA_SHARED_PARAM_H_
|
||||
|
||||
#include <cuda_runtime.h>
|
||||
|
||||
#ifndef MAX_NUM_NR_DLSCH_SEGMENTS_PER_LAYER
|
||||
#define MAX_NUM_NR_DLSCH_SEGMENTS_PER_LAYER 36
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define RowLength 96 //Zc = 384/4 = 96
|
||||
|
||||
#define num_TotalBlocks_BG1_R13_Edge 316//based on number of Cn2Bn Msgs
|
||||
#define num_TotalBlocks_BG1_R23_Edge 144
|
||||
#define num_TotalBlocks_BG1_R89_Edge 79
|
||||
#define num_TotalBlocks_llr_llrRes 22 //Only includes systematic bits
|
||||
|
||||
#define num_TotalBlocks_cn_BG1_R13_Node 46 //based on number of CNs
|
||||
#define num_TotalBlocks_bn_BG1_R13_Node 68 //based on number of BNs
|
||||
#define num_TotalBlocks_cn_BG1_R23_Node 13
|
||||
#define num_TotalBlocks_bn_BG1_R23_Node 35
|
||||
#define num_TotalBlocks_cn_BG1_R89_Node 5
|
||||
#define num_TotalBlocks_bn_BG1_R89_Node 27
|
||||
|
||||
#define JETSON_ORIN
|
||||
//#define GH200
|
||||
|
||||
#if defined(GH200)
|
||||
#define NodeEdge_Switch_Cn_R13 32
|
||||
#define NodeEdge_Switch_Bn_R13 10
|
||||
#define NodeEdge_Switch_Cn_R23 32
|
||||
#define NodeEdge_Switch_Bn_R23 12
|
||||
#define NodeEdge_Switch_Cn_R89 48
|
||||
#define NodeEdge_Switch_Bn_R89 24
|
||||
#elif defined(JETSON_ORIN)
|
||||
#define NodeEdge_Switch_Cn_R13 3
|
||||
#define NodeEdge_Switch_Bn_R13 1
|
||||
#define NodeEdge_Switch_Cn_R23 3
|
||||
#define NodeEdge_Switch_Bn_R23 1
|
||||
#define NodeEdge_Switch_Cn_R89 4
|
||||
#define NodeEdge_Switch_Bn_R89 2
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
typedef struct KernelLaunchConfig {
|
||||
dim3 grid;
|
||||
dim3 block;
|
||||
}KernelLaunchConfig;
|
||||
|
||||
|
||||
typedef struct {
|
||||
int idxBn;
|
||||
int idxCn;
|
||||
int preBuf;
|
||||
int circShift;
|
||||
int8_t dd;
|
||||
} DumpEntry;
|
||||
|
||||
typedef struct {
|
||||
int8_t* p_llr_ptr;
|
||||
int8_t* p_out_ptr;
|
||||
} ldpc_cuda_bridge_t;
|
||||
|
||||
#endif /* NRLDPC_CUDA_SHARED_PARAM_H_ */
|
||||
@@ -0,0 +1,164 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: LicenseRef-CSSL-1.0
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <dlfcn.h>
|
||||
|
||||
#include "log.h"
|
||||
#include "openair1/PHY/CODING/nrLDPC_defs.h"
|
||||
#include "openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_types.h"
|
||||
#include "openair1/PHY/CODING/nrLDPC_coding/nrLDPC_coding_interface.h"
|
||||
|
||||
|
||||
/* segment interface */
|
||||
extern int32_t LDPCinit_cuda();
|
||||
int32_t LDPCinit()
|
||||
{
|
||||
return LDPCinit_cuda();
|
||||
}
|
||||
|
||||
// LDPCshutdown_cuda
|
||||
extern int32_t LDPCshutdown_cuda();
|
||||
int32_t LDPCshutdown()
|
||||
{
|
||||
return LDPCshutdown_cuda();
|
||||
}
|
||||
|
||||
|
||||
// LDPCdecoder
|
||||
extern int32_t LDPCdecoder_cuda(t_nrLDPC_dec_params* p_decParams,
|
||||
int8_t* p_llr,
|
||||
uint8_t* p_out,
|
||||
t_nrLDPC_time_stats* p_profiler,
|
||||
decode_abort_t* ab);
|
||||
|
||||
|
||||
// LDPCencoder <= (LDPCencoder32)
|
||||
extern uint32_t **LDPCencoder32(uint8_t **input, encoder_implemparams_t *impp);
|
||||
|
||||
|
||||
/* slot interface */
|
||||
|
||||
// fallback for LDPC sizes not implemented by CUDA LDPC
|
||||
nrLDPC_coding_interface_t ldpc_cpu;
|
||||
void *ldpc_lib_handle; // corresponding dlsym() handle, see also below
|
||||
|
||||
extern int nrLDPC_coding_encoder32(nrLDPC_slot_encoding_parameters_t *nrLDPC_slot_encoding_parameters, nrLDPC_TB_encoding_parameters_t *nrLDPC_TB_encoding_parameters);
|
||||
int nrLDPC_coding_encoder(nrLDPC_slot_encoding_parameters_t *slot_params)
|
||||
{
|
||||
// this should be the same as previous nrLDPC_coding_encoder() in nrLDPC_coding_segment_encoder.c
|
||||
nrLDPC_TB_encoding_parameters_t tbCPU[32] = {0};
|
||||
nrLDPC_slot_encoding_parameters_t cpu = {
|
||||
.frame = slot_params->frame,
|
||||
.slot = slot_params->slot,
|
||||
.threadPool = slot_params->threadPool,
|
||||
// timing?
|
||||
.TBs = tbCPU,
|
||||
};
|
||||
|
||||
for (int dlsch_id = 0; dlsch_id < slot_params->nb_TBs; dlsch_id++) {
|
||||
nrLDPC_TB_encoding_parameters_t *tbp = &slot_params->TBs[dlsch_id];
|
||||
if (tbp->BG == 1 && tbp->C > 8 && tbp->Z == 384) {
|
||||
nrLDPC_coding_encoder32(slot_params, tbp);
|
||||
} else {
|
||||
// this is not handled by CUDA, handle with CPU
|
||||
cpu.TBs[cpu.nb_TBs++] = *tbp;
|
||||
}
|
||||
}
|
||||
if (cpu.nb_TBs > 0) {
|
||||
ldpc_cpu.nrLDPC_coding_encoder(&cpu);
|
||||
slot_params->TBs[0] = cpu.TBs[0];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void nr_process_decode_segment_cuda(nrLDPC_TB_decoding_parameters_t *);
|
||||
int32_t nrLDPC_coding_decoder(nrLDPC_slot_decoding_parameters_t *slot_params)
|
||||
{
|
||||
// this should be the same as previous nrLDPC_coding_decoder() in nrLDPC_coding_segment_decoder.c
|
||||
nrLDPC_TB_decoding_parameters_t tbCPU[32] = {0};
|
||||
nrLDPC_slot_decoding_parameters_t cpu = {
|
||||
.frame = slot_params->frame,
|
||||
.slot = slot_params->slot,
|
||||
.threadPool = slot_params->threadPool,
|
||||
.TBs = tbCPU,
|
||||
};
|
||||
for (int pusch_id = 0; pusch_id < slot_params->nb_TBs; pusch_id++) {
|
||||
nrLDPC_TB_decoding_parameters_t *tbp = &slot_params->TBs[pusch_id];
|
||||
if (tbp->Z >= 128 && tbp->BG == 1) {
|
||||
nr_process_decode_segment_cuda(tbp);
|
||||
} else {
|
||||
// this is not handled by CUDA, handle with CPU
|
||||
cpu.TBs[cpu.nb_TBs++] = *tbp;
|
||||
}
|
||||
}
|
||||
if (cpu.nb_TBs > 0) {
|
||||
ldpc_cpu.nrLDPC_coding_decoder(&cpu);
|
||||
slot_params->TBs[0] = cpu.TBs[0];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define CHECK_DLFCN_ERROR(COND, SYMB) \
|
||||
if (!(COND)) { \
|
||||
LOG_E(NR_PHY, "could not open %s: %s\n", SYMB, dlerror()); \
|
||||
return false; \
|
||||
}
|
||||
static bool open_default_ldpc(nrLDPC_coding_interface_t *ldpc, int max_num_pxsch)
|
||||
{
|
||||
const char *default_ldpc = "libldpc.so";
|
||||
if (ldpc_lib_handle) {
|
||||
LOG_W(NR_PHY, "%s already initialized\n", default_ldpc);
|
||||
return true;
|
||||
}
|
||||
ldpc_lib_handle = dlopen(default_ldpc, RTLD_LAZY|RTLD_NODELETE|RTLD_GLOBAL);
|
||||
CHECK_DLFCN_ERROR(ldpc_lib_handle, default_ldpc);
|
||||
|
||||
ldpc->nrLDPC_coding_init = dlsym(ldpc_lib_handle, "nrLDPC_coding_init");
|
||||
CHECK_DLFCN_ERROR(ldpc->nrLDPC_coding_init, "nrLDPC_coding_init");
|
||||
ldpc->nrLDPC_coding_shutdown = dlsym(ldpc_lib_handle, "nrLDPC_coding_shutdown");
|
||||
CHECK_DLFCN_ERROR(ldpc->nrLDPC_coding_shutdown, "nrLDPC_coding_shutdown");
|
||||
ldpc->nrLDPC_coding_decoder = dlsym(ldpc_lib_handle, "nrLDPC_coding_decoder");
|
||||
CHECK_DLFCN_ERROR(ldpc->nrLDPC_coding_decoder, "nrLDPC_coding_decoder");
|
||||
ldpc->nrLDPC_coding_encoder = dlsym(ldpc_lib_handle, "nrLDPC_coding_encoder");
|
||||
CHECK_DLFCN_ERROR(ldpc->nrLDPC_coding_encoder, "nrLDPC_coding_encoder");
|
||||
|
||||
bool success = ldpc->nrLDPC_coding_init(max_num_pxsch) == 0;
|
||||
if (!success)
|
||||
LOG_E(NR_PHY, "could not initialize %s\n", default_ldpc);
|
||||
return success;
|
||||
}
|
||||
|
||||
static void close_default_ldpc(nrLDPC_coding_interface_t *ldpc)
|
||||
{
|
||||
if (!ldpc_lib_handle) {
|
||||
LOG_W(NR_PHY, "cannot stop LDPC, not loaded\n");
|
||||
return;
|
||||
}
|
||||
|
||||
ldpc->nrLDPC_coding_shutdown();
|
||||
dlclose(ldpc_lib_handle);
|
||||
ldpc_lib_handle = NULL;
|
||||
}
|
||||
|
||||
extern int32_t nrLDPC_coding_init_cuda(int max_num_pxsch);
|
||||
int32_t nrLDPC_coding_init(int max_num_pxsch)
|
||||
{
|
||||
// we can't use load_nrLDPC_coding_interface() because:
|
||||
// 1. it caches the lib under the "ldpc" name, but links to "ldpc_cuda", so
|
||||
// we recursively load this function again => stack overflow
|
||||
// 2. the global --loader.ldpc.shlibversion _cuda would be reapplied => we
|
||||
// cannot actually load ourselves
|
||||
// hence use dlsym() directly.
|
||||
bool success = open_default_ldpc(&ldpc_cpu, max_num_pxsch);
|
||||
AssertFatal(success, "error loading LDPC library\n");
|
||||
return nrLDPC_coding_init_cuda(max_num_pxsch);
|
||||
}
|
||||
|
||||
extern int32_t nrLDPC_coding_shutdown_cuda(void);
|
||||
int32_t nrLDPC_coding_shutdown(void)
|
||||
{
|
||||
close_default_ldpc(&ldpc_cpu);
|
||||
return nrLDPC_coding_shutdown_cuda();
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user