Commit a2613d56 authored by Robert Schmidt's avatar Robert Schmidt

Merge remote-tracking branch 'origin/ldpc_decoding_module_interface_rework'...

Merge remote-tracking branch 'origin/ldpc_decoding_module_interface_rework' into integration_2024_w50 (2952)

New LDPC coding library interface for decoding and encoding complete slots in one call to the library

Previous attempts to integrate LDPC decoding relying on offloading show
the limitation of the original code segment coding interface for the
library implementing LDPC coding. In order to perform the offload and
therefore the decoding in an optimal fashion, it is relevant to provide
the implementation with the broader amount of data possible per call,
which is a slot.  A previous MR related to T2 offload managed to offer
an interface for decoding transport blocks by modifying only
nr_ulsch_decoding.c. But this may not be sufficient for performing an
efficient decoding in any situation. Slots could be shared between
multiple transport blocks in case multiple UEs are connected to the RAN,
which makes the transport block size shrink and therefore degrades the
efficiency of the offloading.

This MR offers a broader interface with a gNB decoding entry point in
phy_procedures_nr_gNB.c. The file nr_ulsch_decoding.c now lets the
decoding library implement deinterleaving, rate-unmatching and decoding
for the slot. In gNB encoding and UE decoding and encoding as well,
tasks are partitioned in a similar fashion.

As it allows to feed the implementation with the broadest amount of data
possible, it allows to fit any coding solution in a library. This will
avoid further modification to OAI source code and addition of options to
select an implementation when integrating new decoding solutions. An
implementation of this interface will therefore be offered for every
existing decoding solution in OAI and solutions added in the future will
be provided as independent module code without any modification to the
core of OAI code.  The way to choose the decoding solution and to
configure it was also unified using configmodule. The library can be
chosen through the option --loader.ldpc.shlibversion. The slot coding
solutions shipped with this MR can be configured through configmodule
(e.g., T2 address and isolated cores).

This MR includes three coding implementations:

- A wrapper around segment decoding libraries for test purpose: libldpc.so
- A one shot slot coding and encoding with the T2 board: libldpc_t2.so
- A decoder on FPGA using the XDMA driver: libldpc_xdma.so

Improvements brought by this MR:

- Easy integration of a wider variety of LDPC coding solution at gNB and UE
- Easy selection of the LDPC coding solution (option --ldpc-offload-enable is kept for now but it can be ultimately removed)
- T2:
  * More efficient when many UEs are connected
  * Decoding and encoding in nr-uesoftmodem
parents deba36a5 7bf6f3f2
......@@ -485,26 +485,6 @@ target_link_libraries(params_libconfig PRIVATE config_internals ${libconfig_LIBR
add_library(shlib_loader OBJECT common/utils/load_module_shlib.c)
target_link_libraries(shlib_loader PRIVATE CONFIG_LIB)
##########################################################
# LDPC offload library - AMD T2 Accelerator Card
##########################################################
add_boolean_option(ENABLE_LDPC_T2 OFF "Build support for LDPC Offload to T2 library" OFF)
if (ENABLE_LDPC_T2)
pkg_check_modules(LIBDPDK_T2 REQUIRED libdpdk=20.11.9)
find_library(PMD_T2 NAMES rte_baseband_accl_ldpc HINTS ${LIBDPDK_T2_LIBRARY_DIRS})
if (NOT PMD_T2)
message(FATAL_ERROR "could not find poll-mode driver for AccelerComm T2 LDPC Offload (rte_baseband_accl_ldpc.so)")
endif()
message(STATUS "T2 build: use ${PMD_T2}")
add_library(ldpc_t2 MODULE ${OPENAIR1_DIR}/PHY/CODING/nrLDPC_decoder/nrLDPC_decoder_offload.c)
set_target_properties(ldpc_t2 PROPERTIES COMPILE_FLAGS "-DALLOW_EXPERIMENTAL_API")
target_link_libraries(ldpc_t2 ${LIBDPDK_T2_LDFLAGS} ${PMD_T2})
endif()
##########################################################
include_directories ("${OPENAIR_DIR}/radio/COMMON")
##############################################################
......@@ -770,14 +750,6 @@ include_directories(${NFAPI_USER_DIR})
# Layer 1
#############################
set(PHY_TURBOSRC
${OPENAIR1_DIR}/PHY/CODING/3gpplte_sse.c
${OPENAIR1_DIR}/PHY/CODING/3gpplte.c
${OPENAIR1_DIR}/PHY/CODING/3gpplte_turbo_decoder_sse_8bit.c
${OPENAIR1_DIR}/PHY/CODING/3gpplte_turbo_decoder_sse_16bit.c
${OPENAIR1_DIR}/PHY/CODING/3gpplte_turbo_decoder_avx2_16bit.c
${OPENAIR1_DIR}/PHY/CODING/3gpplte_turbo_decoder.c
)
set(PHY_POLARSRC
${OPENAIR1_DIR}/PHY/CODING/nrPolar_tools/nr_polar_init.c
${OPENAIR1_DIR}/PHY/CODING/nrPolar_tools/nr_bitwise_operations.c
......@@ -800,76 +772,16 @@ set(PHY_TURBOIF
${OPENAIR1_DIR}/PHY/CODING/coding_load.c
)
set(PHY_LDPC_ORIG_SRC
${OPENAIR1_DIR}/PHY/CODING/nrLDPC_decoder/nrLDPC_decoder.c
${OPENAIR1_DIR}/PHY/CODING/nrLDPC_encoder/ldpc_encoder.c
)
add_library(ldpc_orig MODULE ${PHY_LDPC_ORIG_SRC} )
target_link_libraries(ldpc_orig PRIVATE ldpc_gen_HEADERS)
set(PHY_LDPC_OPTIM_SRC
${OPENAIR1_DIR}/PHY/CODING/nrLDPC_decoder/nrLDPC_decoder.c
${OPENAIR1_DIR}/PHY/CODING/nrLDPC_encoder/ldpc_encoder_optim.c
)
add_library(ldpc_optim MODULE ${PHY_LDPC_OPTIM_SRC} )
target_link_libraries(ldpc_optim PRIVATE ldpc_gen_HEADERS)
set(PHY_LDPC_OPTIM8SEG_SRC
${OPENAIR1_DIR}/PHY/CODING/nrLDPC_decoder/nrLDPC_decoder.c
${OPENAIR1_DIR}/PHY/CODING/nrLDPC_encoder/ldpc_encoder_optim8seg.c
)
add_library(ldpc_optim8seg MODULE ${PHY_LDPC_OPTIM8SEG_SRC} )
target_link_libraries(ldpc_optim8seg PRIVATE ldpc_gen_HEADERS)
set(PHY_LDPC_OPTIM8SEGMULTI_SRC
${OPENAIR1_DIR}/PHY/CODING/nrLDPC_decoder/nrLDPC_decoder.c
${OPENAIR1_DIR}/PHY/CODING/nrLDPC_encoder/ldpc_encoder_optim8segmulti.c
)
add_library(ldpc MODULE ${PHY_LDPC_OPTIM8SEGMULTI_SRC} )
target_link_libraries(ldpc PRIVATE ldpc_gen_HEADERS)
set(PHY_LDPC_CUDA_SRC
${OPENAIR1_DIR}/PHY/CODING/nrLDPC_decoder_LYC/nrLDPC_decoder_LYC.cu
${OPENAIR1_DIR}/PHY/CODING/nrLDPC_encoder/ldpc_encoder_optim8segmulti.c
)
set(PHY_LDPC_CL_SRC
${OPENAIR1_DIR}/PHY/CODING/nrLDPC_decoder/nrLDPC_decoder_CL.c
${OPENAIR1_DIR}/PHY/CODING/nrLDPC_encoder/ldpc_encoder_optim8segmulti.c
)
add_custom_target( nrLDPC_decoder_kernels_CL
COMMAND gcc ${OPENAIR1_DIR}/PHY/CODING/nrLDPC_decoder/nrLDPC_decoder_CL.c -dD -DNRLDPC_KERNEL_SOURCE -E -o ${CMAKE_CURRENT_BINARY_DIR}/nrLDPC_decoder_kernels_CL.clc
SOURCES ${OPENAIR1_DIR}/PHY/CODING/nrLDPC_decoder/nrLDPC_decoder_CL.c
)
add_library(ldpc_cl MODULE ${PHY_LDPC_CL_SRC} )
target_link_libraries(ldpc_cl OpenCL)
add_dependencies(ldpc_cl nrLDPC_decoder_kernels_CL)
set(PHY_NR_CODINGIF
${OPENAIR1_DIR}/PHY/CODING/nrLDPC_load.c
)
##############################################
# Base CUDA setting
##############################################
add_boolean_option(ENABLE_LDPC_CUDA OFF "Build support for CUDA" OFF)
if (ENABLE_LDPC_CUDA)
find_package(CUDA REQUIRED)
SET(CUDA_NVCC_FLAG "${CUDA_NVCC_FLAGS};-arch=sm_60;")
SET(CUDA_VERBOSE_BUILD ON)
cuda_add_library(ldpc_cuda MODULE ${PHY_LDPC_CUDA_SRC})
set_target_properties(ldpc_cuda PROPERTIES CUDA_SEPARABLE_COMPILATION ON)
if (NOT CUDA_FOUND)
message(FATAL_ERROR "no CUDA found")
endif()
endif()
add_library(coding MODULE ${PHY_TURBOSRC} )
set(PHY_NRLDPC_CODINGIF
${OPENAIR1_DIR}/PHY/CODING/nrLDPC_coding/nrLDPC_coding_interface_load.c
)
add_library(dfts MODULE ${OPENAIR1_DIR}/PHY/TOOLS/oai_dfts.c ${OPENAIR1_DIR}/PHY/TOOLS/oai_dfts_neon.c)
set(PHY_SRC_COMMON
${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/dci_tools_common.c
${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/lte_mcs.c
......@@ -1057,7 +969,7 @@ set(PHY_SRC_UE
${OPENAIR1_DIR}/PHY/TOOLS/simde_operations.c
${PHY_POLARSRC}
${PHY_SMALLBLOCKSRC}
${PHY_NR_CODINGIF}
${PHY_NRLDPC_CODINGIF}
${OPENAIR1_DIR}/PHY/NR_TRANSPORT/pucch_rx.c
${OPENAIR1_DIR}/PHY/NR_TRANSPORT/srs_rx.c
${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_uci_tools_common.c
......@@ -1112,7 +1024,7 @@ set(PHY_SRC_UE
${OPENAIR1_DIR}/PHY/INIT/nr_init_ue.c
${PHY_POLARSRC}
${PHY_SMALLBLOCKSRC}
${PHY_NR_CODINGIF}
${PHY_NRLDPC_CODINGIF}
)
......@@ -2046,12 +1958,6 @@ if(E2_AGENT)
endif()
add_dependencies(nr-softmodem ldpc_orig ldpc_optim ldpc_optim8seg ldpc)
if (ENABLE_LDPC_T2)
add_dependencies(nr-softmodem ldpc_t2)
endif()
# force the generation of ASN.1 so that we don't need to wait during the build
target_link_libraries(nr-softmodem PRIVATE
asn1_lte_rrc asn1_nr_rrc asn1_s1ap asn1_ngap asn1_m2ap asn1_m3ap asn1_x2ap asn1_f1ap asn1_lpp)
......@@ -2104,12 +2010,6 @@ target_link_libraries(nr-uesoftmodem PRIVATE pthread m CONFIG_LIB rt nr_ue_phy_m
target_link_libraries(nr-uesoftmodem PRIVATE ${T_LIB})
target_link_libraries(nr-uesoftmodem PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs)
add_dependencies( nr-uesoftmodem ldpc_orig ldpc_optim ldpc_optim8seg ldpc )
if (ENABLE_LDPC_CUDA)
add_dependencies(nr-uesoftmodem ldpc_cuda)
add_dependencies(nr-softmodem ldpc_cuda)
endif()
# force the generation of ASN.1 so that we don't need to wait during the build
target_link_libraries(nr-uesoftmodem PRIVATE
asn1_lte_rrc asn1_nr_rrc asn1_s1ap asn1_ngap asn1_m2ap asn1_m3ap asn1_x2ap asn1_f1ap asn1_lpp)
......@@ -2163,11 +2063,6 @@ add_executable(ldpctest
${PHY_NR_CODINGIF}
${OPENAIR1_DIR}/PHY/CODING/TESTBENCH/ldpctest.c
)
add_dependencies(ldpctest ldpc_orig ldpc_optim ldpc_optim8seg ldpc)
if (ENABLE_LDPC_CUDA)
add_dependencies(ldpctest ldpc_cuda)
endif()
target_link_libraries(ldpctest PRIVATE
-Wl,--start-group UTIL SIMU PHY_COMMON PHY_NR_COMMON -Wl,--end-group
m pthread dl shlib_loader ${T_LIB}
......@@ -2264,10 +2159,6 @@ add_executable(nr_ulsim
${PHY_INTERFACE_DIR}/queue_t.c
)
if (ENABLE_LDPC_T2)
add_dependencies(nr_ulsim ldpc_t2)
endif()
target_link_libraries(nr_ulsim PRIVATE
-Wl,--start-group UTIL SIMU PHY_COMMON PHY_NR_COMMON PHY_NR PHY_NR_UE SCHED_NR_LIB SCHED_NR_UE_LIB MAC_UE_NR MAC_NR_COMMON nr_rrc CONFIG_LIB L2_NR HASHTABLE x2ap SECURITY ngap -lz -Wl,--end-group
m pthread ${T_LIB} ITTI dl shlib_loader nr_ue_phy_meas
......@@ -2326,14 +2217,14 @@ if (${T_TRACER})
#all "add_library" definitions
ITTI lte_rrc nr_rrc s1ap x2ap m2ap m3ap f1ap
params_libconfig oai_usrpdevif oai_bladerfdevif oai_lmssdrdevif oai_iqplayer
oai_eth_transpro oai_mobipass coding HASHTABLE UTIL OMG_SUMO
oai_eth_transpro oai_mobipass HASHTABLE UTIL OMG_SUMO
SECURITY SCHED_LIB SCHED_NR_LIB SCHED_RU_LIB SCHED_UE_LIB SCHED_NR_UE_LIB default_sched remote_sched RAL
NFAPI_LIB NFAPI_PNF_LIB NFAPI_VNF_LIB NFAPI_USER_LIB
MISC_NFAPI_LTE_LIB MISC_NFAPI_NR_LIB
PHY_COMMON PHY PHY_UE PHY_NR PHY_NR_COMMON PHY_NR_UE PHY_RU PHY_MEX
L2 L2_LTE L2_NR L2_LTE_NR L2_UE NR_L2_UE L2_UE_LTE_NR MAC_NR_COMMON MAC_UE_NR ngap
CN_UTILS GTPV1U SCTP_CLIENT MME_APP LIB_NAS_UE NB_IoT SIMU OPENAIR0_LIB
ldpc_orig ldpc_optim ldpc_optim8seg ldpc_t2 ldpc_cl ldpc_cuda ldpc dfts config_internals nr_common)
dfts config_internals nr_common)
if (TARGET ${i})
add_dependencies(${i} generate_T)
endif()
......
......@@ -73,9 +73,9 @@ then
do
IS_NFAPI=`echo $FILE | grep -E -c "nfapi/open-nFAPI|nfapi/oai_integration/vendor_ext" || true`
IS_OAI_LICENCE_PRESENT=`grep -E -c "OAI Public License" $FILE || true`
IS_BSD_LICENCE_PRESENT=`grep -E -c "the terms of the BSD Licence|License-Identifier: BSD-2-Clause" $FILE || true`
IS_BSD_LICENCE_PRESENT=`grep -E -c "the terms of the BSD Licence|License-Identifier: BSD-2-Clause|License-Identifier: BSD-3-Clause" $FILE || true`
IS_MIT_LICENCE_PRESENT=`grep -E -c "MIT License" $FILE || true`
IS_EXCEPTION=`echo $FILE | grep -E -c "common/utils/collection/tree.h|common/utils/collection/queue.h|openair2/UTIL/OPT/packet-rohc.h|openair3/NAS/COMMON/milenage.h|openair1/PHY/CODING/crc.h|openair1/PHY/CODING/crcext.h|openair1/PHY/CODING/types.h|openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_decoder_offload.c|openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_offload.h" || true`
IS_EXCEPTION=`echo $FILE | grep -E -c "common/utils/collection/tree.h|common/utils/collection/queue.h|openair2/UTIL/OPT/packet-rohc.h|openair3/NAS/COMMON/milenage.h|openair1/PHY/CODING/crc.h|openair1/PHY/CODING/crcext.h|openair1/PHY/CODING/types.h" || true`
if [ $IS_OAI_LICENCE_PRESENT -eq 0 ] && [ $IS_BSD_LICENCE_PRESENT -eq 0 ] && [ $IS_MIT_LICENCE_PRESENT -eq 0 ]
then
if [ $IS_NFAPI -eq 0 ] && [ $IS_EXCEPTION -eq 0 ]
......@@ -184,9 +184,9 @@ do
then
IS_NFAPI=`echo $FULLFILE | grep -E -c "nfapi/open-nFAPI|nfapi/oai_integration/vendor_ext" || true`
IS_OAI_LICENCE_PRESENT=`grep -E -c "OAI Public License" $FULLFILE || true`
IS_BSD_LICENCE_PRESENT=`grep -E -c "the terms of the BSD Licence|License-Identifier: BSD-2-Clause" $FULLFILE || true`
IS_BSD_LICENCE_PRESENT=`grep -E -c "the terms of the BSD Licence|License-Identifier: BSD-2-Clause|License-Identifier: BSD-3-Clause" $FULLFILE || true`
IS_MIT_LICENCE_PRESENT=`grep -E -c "MIT License" $FULLFILE || true`
IS_EXCEPTION=`echo $FULLFILE | grep -E -c "common/utils/collection/tree.h|common/utils/collection/queue.h|openair2/UTIL/OPT/packet-rohc.h|openair3/NAS/COMMON/milenage.h|openair1/PHY/CODING/crc.h|openair1/PHY/CODING/crcext.h|openair1/PHY/CODING/types.h|openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_decoder_offload.c|openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_offload.h" || true`
IS_EXCEPTION=`echo $FULLFILE | grep -E -c "common/utils/collection/tree.h|common/utils/collection/queue.h|openair2/UTIL/OPT/packet-rohc.h|openair3/NAS/COMMON/milenage.h|openair1/PHY/CODING/crc.h|openair1/PHY/CODING/crcext.h|openair1/PHY/CODING/types.h" || true`
if [ $IS_OAI_LICENCE_PRESENT -eq 0 ] && [ $IS_BSD_LICENCE_PRESENT -eq 0 ] && [ $IS_MIT_LICENCE_PRESENT -eq 0 ]
then
if [ $IS_NFAPI -eq 0 ] && [ $IS_EXCEPTION -eq 0 ]
......
......@@ -45,7 +45,7 @@
<always_exec>true</always_exec>
<physim_test>nr_ulsim</physim_test>
<physim_time_threshold>100</physim_time_threshold>
<physim_run_args>-n100 -s30 -S30.2 -m5 -r106 -R106 -C10 -o -P --ldpc_offload.dpdk_dev d8:00.0</physim_run_args>
<physim_run_args>-n100 -s30 -S30.2 -m5 -r106 -R106 -C10 -P --loader.ldpc.shlibversion _t2 --nrLDPC_coding_t2.dpdk_dev d8:00.0 --nrLDPC_coding_t2.dpdk_core_list 11-12</physim_run_args>
</testCase>
<testCase id="010121">
......@@ -63,7 +63,7 @@
<always_exec>true</always_exec>
<physim_test>nr_ulsim</physim_test>
<physim_time_threshold>150</physim_time_threshold>
<physim_run_args>-n100 -s30 -S30.2 -m15 -r106 -R106 -C10 -o -P --ldpc_offload.dpdk_dev d8:00.0</physim_run_args>
<physim_run_args>-n100 -s30 -S30.2 -m15 -r106 -R106 -C10 -P --loader.ldpc.shlibversion _t2 --nrLDPC_coding_t2.dpdk_dev d8:00.0 --nrLDPC_coding_t2.dpdk_core_list 11-12</physim_run_args>
</testCase>
<testCase id="010131">
......@@ -81,7 +81,7 @@
<always_exec>true</always_exec>
<physim_test>nr_ulsim</physim_test>
<physim_time_threshold>250</physim_time_threshold>
<physim_run_args>-n100 -s30 -S30.2 -m25 -r106 -R106 -C10 -o -P --ldpc_offload.dpdk_dev d8:00.0</physim_run_args>
<physim_run_args>-n100 -s30 -S30.2 -m25 -r106 -R106 -C10 -P --loader.ldpc.shlibversion _t2 --nrLDPC_coding_t2.dpdk_dev d8:00.0 --nrLDPC_coding_t2.dpdk_core_list 11-12</physim_run_args>
</testCase>
<testCase id="010211">
......@@ -99,7 +99,7 @@
<always_exec>true</always_exec>
<physim_test>nr_ulsim</physim_test>
<physim_time_threshold>150</physim_time_threshold>
<physim_run_args>-n100 -s30 -S30.2 -m5 -r273 -R273 -C10 -o -P --ldpc_offload.dpdk_dev d8:00.0</physim_run_args>
<physim_run_args>-n100 -s30 -S30.2 -m5 -r273 -R273 -C10 -P --loader.ldpc.shlibversion _t2 --nrLDPC_coding_t2.dpdk_dev d8:00.0 --nrLDPC_coding_t2.dpdk_core_list 11-12</physim_run_args>
</testCase>
<testCase id="010221">
......@@ -117,7 +117,7 @@
<always_exec>true</always_exec>
<physim_test>nr_ulsim</physim_test>
<physim_time_threshold>350</physim_time_threshold>
<physim_run_args>-n100 -s30 -S30.2 -m15 -r273 -R273 -C10 -o -P --ldpc_offload.dpdk_dev d8:00.0</physim_run_args>
<physim_run_args>-n100 -s30 -S30.2 -m15 -r273 -R273 -C10 -P --loader.ldpc.shlibversion _t2 --nrLDPC_coding_t2.dpdk_dev d8:00.0 --nrLDPC_coding_t2.dpdk_core_list 11-12</physim_run_args>
</testCase>
<testCase id="010231">
......@@ -135,7 +135,7 @@
<always_exec>true</always_exec>
<physim_test>nr_ulsim</physim_test>
<physim_time_threshold>550</physim_time_threshold>
<physim_run_args>-n100 -s30 -S30.2 -m25 -r273 -R273 -C10 -o -P --ldpc_offload.dpdk_dev d8:00.0</physim_run_args>
<physim_run_args>-n100 -s30 -S30.2 -m25 -r273 -R273 -C10 -P --loader.ldpc.shlibversion _t2 --nrLDPC_coding_t2.dpdk_dev d8:00.0 --nrLDPC_coding_t2.dpdk_core_list 11-12</physim_run_args>
</testCase>
<testCase id="010311">
......@@ -153,7 +153,7 @@
<always_exec>true</always_exec>
<physim_test>nr_ulsim</physim_test>
<physim_time_threshold>250</physim_time_threshold>
<physim_run_args>-n100 -s30 -S30.2 -m5 -r273 -R273 -C10 -o -W2 -z2 -y2 -P --ldpc_offload.dpdk_dev d8:00.0</physim_run_args>
<physim_run_args>-n100 -s30 -S30.2 -m5 -r273 -R273 -C10 -W2 -z2 -y2 -P --loader.ldpc.shlibversion _t2 --nrLDPC_coding_t2.dpdk_dev d8:00.0 --nrLDPC_coding_t2.dpdk_core_list 11-12</physim_run_args>
</testCase>
<testCase id="010321">
......@@ -171,7 +171,7 @@
<always_exec>true</always_exec>
<physim_test>nr_ulsim</physim_test>
<physim_time_threshold>650</physim_time_threshold>
<physim_run_args>-n100 -s30 -S30.2 -m15 -r273 -R273 -C10 -o -W2 -z2 -y2 -P --ldpc_offload.dpdk_dev d8:00.0</physim_run_args>
<physim_run_args>-n100 -s30 -S30.2 -m15 -r273 -R273 -C10 -W2 -z2 -y2 -P --loader.ldpc.shlibversion _t2 --nrLDPC_coding_t2.dpdk_dev d8:00.0 --nrLDPC_coding_t2.dpdk_core_list 11-12</physim_run_args>
</testCase>
<testCase id="010331">
......@@ -189,7 +189,7 @@
<always_exec>true</always_exec>
<physim_test>nr_ulsim</physim_test>
<physim_time_threshold>1100</physim_time_threshold>
<physim_run_args>-n100 -s30 -S30.2 -m25 -r273 -R273 -C10 -o -W2 -z2 -y2 -P --ldpc_offload.dpdk_dev d8:00.0</physim_run_args>
<physim_run_args>-n100 -s30 -S30.2 -m25 -r273 -R273 -C10 -W2 -z2 -y2 -P --loader.ldpc.shlibversion _t2 --nrLDPC_coding_t2.dpdk_dev d8:00.0 --nrLDPC_coding_t2.dpdk_core_list 11-12</physim_run_args>
</testCase>
</testCaseList>
......@@ -46,7 +46,7 @@
<always_exec>true</always_exec>
<physim_test>nr_dlsim</physim_test>
<physim_time_threshold>100</physim_time_threshold>
<physim_run_args>-n100 -s30 -S30.2 -e5 -b106 -R106 -c -X4,5,6,7,8,9 -P --ldpc_offload.dpdk_dev d8:00.0</physim_run_args>
<physim_run_args>-n100 -s30 -S30.2 -e5 -b106 -R106 -X4,5,6,7,8,9 -P --loader.ldpc.shlibversion _t2 --nrLDPC_coding_t2.dpdk_dev d8:00.0 --nrLDPC_coding_t2.dpdk_core_list 11-12</physim_run_args>
</testCase>
<testCase id="000121">
......@@ -64,7 +64,7 @@
<always_exec>true</always_exec>
<physim_test>nr_dlsim</physim_test>
<physim_time_threshold>100</physim_time_threshold>
<physim_run_args>-n100 -s30 -S30.2 -e15 -b106 -R106 -c -X4,5,6,7,8,9 -P --ldpc_offload.dpdk_dev d8:00.0</physim_run_args>
<physim_run_args>-n100 -s30 -S30.2 -e15 -b106 -R106 -X4,5,6,7,8,9 -P --loader.ldpc.shlibversion _t2 --nrLDPC_coding_t2.dpdk_dev d8:00.0 --nrLDPC_coding_t2.dpdk_core_list 11-12</physim_run_args>
</testCase>
<testCase id="000131">
......@@ -82,7 +82,7 @@
<always_exec>true</always_exec>
<physim_test>nr_dlsim</physim_test>
<physim_time_threshold>200</physim_time_threshold>
<physim_run_args>-n100 -s30 -S30.2 -e25 -b106 -R106 -c -X4,5,6,7,8,9 -P --ldpc_offload.dpdk_dev d8:00.0</physim_run_args>
<physim_run_args>-n100 -s30 -S30.2 -e25 -b106 -R106 -X4,5,6,7,8,9 -P --loader.ldpc.shlibversion _t2 --nrLDPC_coding_t2.dpdk_dev d8:00.0 --nrLDPC_coding_t2.dpdk_core_list 11-12</physim_run_args>
</testCase>
<testCase id="000211">
......@@ -100,7 +100,7 @@
<always_exec>true</always_exec>
<physim_test>nr_dlsim</physim_test>
<physim_time_threshold>150</physim_time_threshold>
<physim_run_args>-n100 -s30 -S30.2 -e5 -b273 -R273 -c -X4,5,6,7,8,9 -P --ldpc_offload.dpdk_dev d8:00.0</physim_run_args>
<physim_run_args>-n100 -s30 -S30.2 -e5 -b273 -R273 -X4,5,6,7,8,9 -P --loader.ldpc.shlibversion _t2 --nrLDPC_coding_t2.dpdk_dev d8:00.0 --nrLDPC_coding_t2.dpdk_core_list 11-12</physim_run_args>
</testCase>
<testCase id="000221">
......@@ -118,7 +118,7 @@
<always_exec>true</always_exec>
<physim_test>nr_dlsim</physim_test>
<physim_time_threshold>250</physim_time_threshold>
<physim_run_args>-n100 -s30 -S30.2 -e15 -b273 -R273 -c -X4,5,6,7,8,9 -P --ldpc_offload.dpdk_dev d8:00.0</physim_run_args>
<physim_run_args>-n100 -s30 -S30.2 -e15 -b273 -R273 -X4,5,6,7,8,9 -P --loader.ldpc.shlibversion _t2 --nrLDPC_coding_t2.dpdk_dev d8:00.0 --nrLDPC_coding_t2.dpdk_core_list 11-12</physim_run_args>
</testCase>
<testCase id="000231">
......@@ -136,7 +136,7 @@
<always_exec>true</always_exec>
<physim_test>nr_dlsim</physim_test>
<physim_time_threshold>400</physim_time_threshold>
<physim_run_args>-n100 -s30 -S30.2 -e25 -b273 -R273 -c -X4,5,6,7,8,9 -P --ldpc_offload.dpdk_dev d8:00.0</physim_run_args>
<physim_run_args>-n100 -s30 -S30.2 -e25 -b273 -R273 -X4,5,6,7,8,9 -P --loader.ldpc.shlibversion _t2 --nrLDPC_coding_t2.dpdk_dev d8:00.0 --nrLDPC_coding_t2.dpdk_core_list 11-12</physim_run_args>
</testCase>
<testCase id="000311">
......@@ -154,7 +154,7 @@
<always_exec>true</always_exec>
<physim_test>nr_dlsim</physim_test>
<physim_time_threshold>200</physim_time_threshold>
<physim_run_args>-n100 -s30 -S30.2 -e5 -b273 -R273 -c -X4,5,6,7,8,9 -x2 -z2 -y2 -P --ldpc_offload.dpdk_dev d8:00.0</physim_run_args>
<physim_run_args>-n100 -s30 -S30.2 -e5 -b273 -R273 -X4,5,6,7,8,9 -x2 -z2 -y2 -P --loader.ldpc.shlibversion _t2 --nrLDPC_coding_t2.dpdk_dev d8:00.0 --nrLDPC_coding_t2.dpdk_core_list 11-12</physim_run_args>
</testCase>
<testCase id="000321">
......@@ -172,7 +172,7 @@
<always_exec>true</always_exec>
<physim_test>nr_dlsim</physim_test>
<physim_time_threshold>500</physim_time_threshold>
<physim_run_args>-n100 -s30 -S30.2 -e15 -b273 -R273 -c -X4,5,6,7,8,9 -x2 -z2 -y2 -P --ldpc_offload.dpdk_dev d8:00.0</physim_run_args>
<physim_run_args>-n100 -s30 -S30.2 -e15 -b273 -R273 -X4,5,6,7,8,9 -x2 -z2 -y2 -P --loader.ldpc.shlibversion _t2 --nrLDPC_coding_t2.dpdk_dev d8:00.0 --nrLDPC_coding_t2.dpdk_core_list 11-12</physim_run_args>
</testCase>
<testCase id="000331">
......@@ -190,7 +190,7 @@
<always_exec>true</always_exec>
<physim_test>nr_dlsim</physim_test>
<physim_time_threshold>500</physim_time_threshold>
<physim_run_args>-n100 -s30 -S30.2 -e25 -b273 -R273 -c -X4,5,6,7,8,9 -x2 -z2 -y2 -P --ldpc_offload.dpdk_dev d8:00.0</physim_run_args>
<physim_run_args>-n100 -s30 -S30.2 -e25 -b273 -R273 -X4,5,6,7,8,9 -x2 -z2 -y2 -P --loader.ldpc.shlibversion _t2 --nrLDPC_coding_t2.dpdk_dev d8:00.0 --nrLDPC_coding_t2.dpdk_core_list 11-12</physim_run_args>
</testCase>
<testCase id="000411">
......@@ -208,7 +208,7 @@
<always_exec>true</always_exec>
<physim_test>nr_dlsim</physim_test>
<physim_time_threshold>200</physim_time_threshold>
<physim_run_args>-n100 -s30 -S30.2 -e5 -b273 -R273 -c -X4,5,6,7,8,9 -x2 -z4 -y4 -P --ldpc_offload.dpdk_dev d8:00.0</physim_run_args>
<physim_run_args>-n100 -s30 -S30.2 -e5 -b273 -R273 -X4,5,6,7,8,9 -x2 -z4 -y4 -P --loader.ldpc.shlibversion _t2 --nrLDPC_coding_t2.dpdk_dev d8:00.0 --nrLDPC_coding_t2.dpdk_core_list 11-12</physim_run_args>
</testCase>
<testCase id="000421">
......@@ -226,7 +226,7 @@
<always_exec>true</always_exec>
<physim_test>nr_dlsim</physim_test>
<physim_time_threshold>300</physim_time_threshold>
<physim_run_args>-n100 -s30 -S30.2 -e15 -b273 -R273 -c -X4,5,6,7,8,9 -x2 -z4 -y4 -P --ldpc_offload.dpdk_dev d8:00.0</physim_run_args>
<physim_run_args>-n100 -s30 -S30.2 -e15 -b273 -R273 -X4,5,6,7,8,9 -x2 -z4 -y4 -P --loader.ldpc.shlibversion _t2 --nrLDPC_coding_t2.dpdk_dev d8:00.0 --nrLDPC_coding_t2.dpdk_core_list 11-12</physim_run_args>
</testCase>
<testCase id="000431">
......@@ -244,6 +244,6 @@
<always_exec>true</always_exec>
<physim_test>nr_dlsim</physim_test>
<physim_time_threshold>450</physim_time_threshold>
<physim_run_args>-n100 -s30 -S30.2 -e25 -b273 -R273 -c -X4,5,6,7,8,9 -x2 -z4 -y4 -P --ldpc_offload.dpdk_dev d8:00.0</physim_run_args>
<physim_run_args>-n100 -s30 -S30.2 -e25 -b273 -R273 -X4,5,6,7,8,9 -x2 -z4 -y4 -P --loader.ldpc.shlibversion _t2 --nrLDPC_coding_t2.dpdk_dev d8:00.0 --nrLDPC_coding_t2.dpdk_core_list 11-12</physim_run_args>
</testCase>
</testCaseList>
......@@ -46,7 +46,7 @@ BUILD_DOXYGEN=0
DISABLE_HARDWARE_DEPENDENCY="False"
CMAKE_BUILD_TYPE="RelWithDebInfo"
CMAKE_CMD="$CMAKE"
OPTIONAL_LIBRARIES="telnetsrv enbscope uescope nrscope ldpc_cuda ldpc_t2 websrv oai_iqplayer imscope"
OPTIONAL_LIBRARIES="telnetsrv enbscope uescope nrscope ldpc_cuda ldpc_t2 ldpc_xdma websrv oai_iqplayer imscope"
TARGET_LIST=""
BUILD_TOOL_OPT="-j$(nproc)"
......
......@@ -74,11 +74,6 @@ If DPDK library was installed into custom path, you have to point to the right d
```
export PKG_CONFIG_PATH=/opt/dpdk-t2/lib64/pkgconfig/:$PKG_CONFIG_PATH
```
## Setup of T2-related DPDK EAL parameters
To configure T2-related DPDK Environment Abstraction Layer (EAL) parameters, you can set the following parameters via the command line:
- `ldpc_offload.dpdk_dev` - **mandatory** parameter, specifies PCI address of the T2 card. PCI address of the T2 card can be detected by `lspci | grep "Xilinx"` command.
- `ldpc_offload.dpdk_cores_list` - CPU cores assigned to DPDK for T2 processing, by default set to *11-12*. Ensure that the CPU cores specified in *ldpc_offload.dpdk_cores_list* are available and not used by other processes to avoid conflicts.
- `ldpc_offload.dpdk_prefix` - DPDK shared data file prefix, by default set to *b6*
# OAI Build
OTA deployment is precisely described in the following tutorial:
......@@ -106,14 +101,35 @@ Shared object file *libldpc_t2.so* is created during the compilation. This objec
*Required poll mode driver has to be present on the host machine and required DPDK version has to be installed on the host, prior to the build of OAI*
# Setup of T2-related DPDK EAL parameters
To configure T2-related DPDK Environment Abstraction Layer (EAL) parameters, you can set the following parameters via the command line of PHY simulators or softmodem:
- `nrLDPC_coding_t2.dpdk_dev` - **mandatory** parameter, specifies PCI address of the T2 card. PCI address of the T2 card can be detected by `lspci | grep "Xilinx"` command.
- `nrLDPC_coding_t2.dpdk_core_list` - **mandatory** parameter, specifies CPU cores assigned to DPDK for T2 processing. Ensure that the CPU cores specified in *nrLDPC_coding_t2.dpdk_core_list* are available and not used by other processes to avoid conflicts.
- `nrLDPC_coding_t2.dpdk_prefix` - DPDK shared data file prefix, by default set to *b6*.
**Note:** These parameters can also be provided in a configuration file:
```
nrLDPC_coding_t2 : {
dpdk_dev : "41:00.0";
dpdk_core_list : "14-15";
};
loader : {
ldpc : {
shlibversion : "_t2";
};
};
```
# 5G PHY simulators
## nr_ulsim test
Offload of the channel decoding to the T2 card is in nr_ulsim specified by *-o* option. Example command for running nr_ulsim with LDPC decoding offload to the T2 card:
Offload of the channel decoding to the T2 card is in nr_ulsim specified by *--loader.ldpc.shlibversion _t2* option. Example command for running nr_ulsim with LDPC decoding offload to the T2 card:
```
cd ~/openairinterface5g
source oaienv
cd cmake_targets/ran_build/build
sudo ./nr_ulsim -n100 -s20 -m20 -r273 -R273 -o --ldpc_offload.dpdk_dev 01:00.0
sudo ./nr_ulsim -n100 -s20 -m20 -r273 -R273 --loader.ldpc.shlibversion _t2 --nrLDPC_coding_t2.dpdk_dev 01:00.0 --nrLDPC_coding_t2.dpdk_core_list 0-1
```
## nr_dlsim test
Offload of the channel encoding to the AMD Xilinx T2 card is in nr_dlsim specified by *-c* option. Example command for running nr_dlsim with LDPC encoding offload to the T2 card:
......@@ -121,18 +137,18 @@ Offload of the channel encoding to the AMD Xilinx T2 card is in nr_dlsim specifi
cd ~/openairinterface5g
source oaienv
cd cmake_targets/ran_build/build
sudo ./nr_dlsim -n300 -s30 -R 106 -e 27 -c --ldpc_offload.dpdk_dev 01:00.0
sudo ./nr_dlsim -n300 -s30 -R 106 -e 27 --loader.ldpc.shlibversion _t2 --nrLDPC_coding_t2.dpdk_dev 01:00.0 --nrLDPC_coding_t2.dpdk_core_list 0-1
```
# OTA test
Offload of the channel encoding and decoding to the AMD Xilinx T2 card is enabled by *--ldpc-offload-enable* option.
Offload of the channel encoding and decoding to the AMD Xilinx T2 card is enabled by *--loader.ldpc.shlibversion _t2* option.
## Run OAI gNB with USRP B210
```
cd ~/openairinterface5g
source oaienv
cd cmake_targets/ran_build/build
sudo ./nr-softmodem -O ../../../targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.conf --ldpc-offload-enable --ldpc_offload.dpdk_dev 01:00.0
sudo ./nr-softmodem -O ../../../targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.conf --loader.ldpc.shlibversion _t2 --nrLDPC_coding_t2.dpdk_dev 01:00.0 --nrLDPC_coding_t2.dpdk_core_list 0-1
```
# Limitations
......
# LDPC offload with the XDMA driver
[TOC]
This documentation aims to provide a tutorial for using Xilinx PCIe-XDMA based FPGA LDPC decoding within OAI. LDPC decoding is offloaded to FPGA.
## XDMA Driver Build & Install
- Get XDMA driver source
```bash
git clone https://github.com/Xilinx/dma_ip_drivers.git
cd dma_ip_drivers/XDMA/linux-kernel
```
The *xdma_driver* directory contains the following:
```bash
dma_ip_drivers/XDMA/linux-kernel/
├── COPYING
├── include
├── LICENSE
├── readme.txt
├── RELEASE
├── tests
├── tools
└── xdma
```
Before building the driver, ensure that your system recognizes the Xilinx device. You can check this using the `lspci` command:
```bash
$ lspci | grep Xilinx
01:00.0 Serial controller: Xilinx Corporation Device 8038
```
Building and Installing the Driver
```bash
cd ~/dma_ip_drivers/XDMA/linux-kernel/xdma
make clean
make
# install to make the driver loading automatically at system startup
sudo make install
```
Load the Driver
```bash
cd ~/dma_ip_drivers/XDMA/linux-kernel/tests
sudo ./load_driver.sh
```
## OAI Build
```bash
# Get openairinterface5g source code
git clone https://gitlab.eurecom.fr/oai/openairinterface5g.git ~/openairinterface5g
cd ~/openairinterface5g
# Install OAI dependencies
cd ~/openairinterface5g/cmake_targets
./build_oai -I
# Build OAI gNB & UE
cd ~/openairinterface5g
source oaienv
cd cmake_targets
./build_oai --ninja -w SIMU --gNB --nrUE -P --build-lib "ldpc_xdma" -C -c
```
Shared object file *libldpc_xdma.so* is created during the compilation. This object is conditionally compiled. Selection of the library to compile is done using `--build-lib ldpc_xdma`.
## 5G PHY simulators
The simulated test uses the option `--loader.ldpc.shlibversion _xdma` to select the XDMA version for loading into the LDPC interface. Additionally, the option `--nrLDPC_coding_xdma.num_threads_prepare` is used to specify the number of threads for preparing data before the LDPC processing, specifically for the deinterleaving and rate matching parts.
Another way to activate the feature is to add the `xdma.conf` file with the following content:
```
nrLDPC_coding_xdma : {
num_threads_prepare : 2;
};
loader : {
ldpc : {
shlibversion : "_xdma";
};
};
```
and use option `-O xdma.conf`.
### nr_ulsim test
Example command for running nr_ulsim with LDPC decoding offload to the FPGA:
```bash
cd ~/openairinterface5g/cmake_targets/ran_build/build
sudo ./nr_ulsim -n100 -m28 -r273 -R273 -s22 -I10 -C8 -P --loader.ldpc.shlibversion _xdma --nrLDPC_coding_xdma.num_threads_prepare 2
```
or
```
sudo ./nr_ulsim -n100 -m28 -r273 -R273 -s22 -I10 -C8 -P -O xdma.conf
```
## Run
Both gNB and nrUE use the option `--loader.ldpc.shlibversion _xdma` to select the XDMA version for loading into the LDPC interface and `--nrLDPC_coding_xdma.num_threads_prepare` to specify the number of threads for preparing data before the LDPC processing, specifically for the deinterleaving and rate matching parts.
Another way to activate the feature is to add the following content to the `.conf` file you want to use:
```
nrLDPC_coding_xdma : {
num_threads_prepare : 2;
};
loader : {
ldpc : {
shlibversion : "_xdma";
};
};
```
and use option `-O *.conf`.
### gNB
Example command using rfsim:
```bash
cd ~/openairinterface5g/cmake_targets/ran_build/build
sudo ./nr-softmodem --rfsim --log_config.global_log_options level,nocolor,time -O ../../../ci-scripts/conf_files/gnb.sa.band78.106prb.rfsim.conf --loader.ldpc.shlibversion _xdma --nrLDPC_coding_xdma.num_threads_prepare 2
```
or
```bash
sudo ./nr-softmodem --rfsim --log_config.global_log_options level,nocolor,time -O ../../../ci-scripts/conf_files/gnb.sa.band78.106prb.rfsim.conf
```
if you have added the configuration to the `.conf` file.
### UE
Example command using rfsim:
```bash
cd ~/openairinterface5g/cmake_targets/ran_build/build
sudo ./nr-uesoftmodem --rfsim -r 106 --numerology 1 --band 78 -C 3319680000 --ue-nb-ant-tx 1 --ue-nb-ant-rx 1 -O ../../../ci-scripts/conf_files/nrue1.uicc.cluCN.conf --rfsimulator.serveraddr 10.201.1.100 --loader.ldpc.shlibversion _xdma --nrLDPC_coding_xdma.num_threads_prepare 2
```
or
```bash
sudo ./nr-uesoftmodem --rfsim -r 106 --numerology 1 --band 78 -C 3319680000 --ue-nb-ant-tx 1 --ue-nb-ant-rx 1 -O ../../../ci-scripts/conf_files/nrue1.uicc.cluCN.conf --rfsimulator.serveraddr 10.201.1.100
```
if you have added the configuration to the `.conf` file.
......@@ -403,7 +403,6 @@ void init_eNB_afterRU(void) {
for (inst=0; inst<RC.nb_nr_inst; inst++) {
gNB = RC.gNB[inst];
gNB->ldpc_offload_flag = get_softmodem_params()->ldpc_offload_flag;
phy_init_nr_gNB(gNB);
......
......@@ -42,6 +42,7 @@
//#undef FRAME_LENGTH_COMPLEX_SAMPLES //there are two conflicting definitions, so we better make sure we don't use it at all
#include "openair1/PHY/MODULATION/nr_modulation.h"
#include "PHY/CODING/nrLDPC_coding/nrLDPC_coding_interface.h"
#include "PHY/phy_vars_nr_ue.h"
#include "PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h"
#include "PHY/NR_TRANSPORT/nr_dlsch.h"
......@@ -216,7 +217,6 @@ void set_options(int CC_id, PHY_VARS_NR_UE *UE){
UE->rf_map.card = 0;
UE->rf_map.chain = CC_id + 0;
UE->max_ldpc_iterations = nrUE_params.max_ldpc_iterations;
UE->ldpc_offload_enable = nrUE_params.ldpc_offload_flag;
UE->UE_scan_carrier = nrUE_params.UE_scan_carrier;
UE->UE_fo_compensation = nrUE_params.UE_fo_compensation;
UE->if_freq = nrUE_params.if_freq;
......@@ -385,6 +385,7 @@ configmodule_interface_t *uniqCfg = NULL;
// A global var to reduce the changes size
ldpc_interface_t ldpc_interface = {0}, ldpc_interface_offload = {0};
nrLDPC_coding_interface_t nrLDPC_coding_interface = {0};
int main(int argc, char **argv)
{
......@@ -424,10 +425,8 @@ int main(int argc, char **argv)
init_opt();
if (nrUE_params.ldpc_offload_flag)
load_LDPClib("_t2", &ldpc_interface_offload);
load_LDPClib(NULL, &ldpc_interface);
int ret_loader = load_nrLDPC_coding_interface(NULL, &nrLDPC_coding_interface);
AssertFatal(ret_loader == 0, "error loading LDPC library\n");
if (ouput_vcd) {
vcd_signal_dumper_init("/tmp/openair_dump_nrUE.vcd");
......@@ -442,6 +441,8 @@ int main(int argc, char **argv)
for (int CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) {
PHY_vars_UE_g[inst][CC_id] = malloc(sizeof(*PHY_vars_UE_g[inst][CC_id]));
memset(PHY_vars_UE_g[inst][CC_id], 0, sizeof(*PHY_vars_UE_g[inst][CC_id]));
// All instances use the same coding interface
PHY_vars_UE_g[inst][CC_id]->nrLDPC_coding_interface = nrLDPC_coding_interface;
}
}
......
......@@ -39,7 +39,6 @@
{"dlsch-parallel", CONFIG_HLP_DLSCH_PARA, 0, .u8ptr=NULL, .defintval=0, TYPE_UINT8, 0}, \
{"offset-divisor", CONFIG_HLP_OFFSET_DIV, 0, .uptr=&nrUE_params.ofdm_offset_divisor, .defuintval=8, TYPE_UINT32, 0}, \
{"max-ldpc-iterations", CONFIG_HLP_MAX_LDPC_ITERATIONS, 0, .iptr=&nrUE_params.max_ldpc_iterations, .defuintval=8, TYPE_UINT8, 0}, \
{"ldpc-offload-enable", CONFIG_HLP_LDPC_OFFLOAD, PARAMFLAG_BOOL, .iptr=&(nrUE_params.ldpc_offload_flag), .defintval=0, TYPE_INT, 0}, \
{"V" , CONFIG_HLP_VCD, PARAMFLAG_BOOL, .iptr=&nrUE_params.vcdflag, .defintval=0, TYPE_INT, 0}, \
{"uecap_file", CONFIG_HLP_UECAP_FILE, 0, .strptr=&nrUE_params.uecap_file, .defstrval="./uecap_ports1.xml", TYPE_STRING, 0}, \
{"reconfig-file", CONFIG_HLP_RE_CFG_FILE, 0, .strptr=&nrUE_params.reconfig_file, .defstrval="./reconfig.raw", TYPE_STRING, 0}, \
......@@ -85,7 +84,6 @@ typedef struct {
int nb_antennas_tx;
int N_RB_DL;
int ssb_start_subcarrier;
int ldpc_offload_flag;
double time_sync_P;
double time_sync_I;
int autonomous_ta;
......
......@@ -108,7 +108,6 @@ extern "C"
#define CONFIG_HLP_CONTINUOUS_TX "perform continuous transmission, even in TDD mode (to work around USRP issues)\n"
#define CONFIG_HLP_STATS_DISABLE "disable globally the stats generation and persistence"
#define CONFIG_HLP_NOITTI "Do not start itti threads, call queue processing in place, inside the caller thread"
#define CONFIG_HLP_LDPC_OFFLOAD "Enable LDPC offload to AMD Xilinx T2 telco card\n"
#define CONFIG_HLP_SYNC_REF "UE acts a Sync Reference in Sidelink. 0-none 1-GNB 2-GNSS 4-localtiming\n"
#define CONFIG_HLP_TADV \
"Set RF board timing_advance to compensate fix delay inside the RF board between Rx and Tx timestamps (RF board internal " \
......@@ -142,7 +141,6 @@ extern "C"
#define EMULATE_L1 softmodem_params.emulate_l1
#define CONTINUOUS_TX softmodem_params.continuous_tx
#define SYNC_REF softmodem_params.sync_ref
#define LDPC_OFFLOAD_FLAG softmodem_params.ldpc_offload_flag
#define DEFAULT_RFCONFIG_FILE "/usr/local/etc/syriq/ue.band7.tm1.PRB100.NR40.dat";
......@@ -182,7 +180,6 @@ extern int usrp_tx_thread;
{"continuous-tx", CONFIG_HLP_CONTINUOUS_TX, PARAMFLAG_BOOL, .iptr=&CONTINUOUS_TX, .defintval=0, TYPE_INT, 0}, \
{"disable-stats", CONFIG_HLP_STATS_DISABLE, PARAMFLAG_BOOL, .iptr=&stats_disabled, .defintval=0, TYPE_INT, 0}, \
{"no-itti-threads", CONFIG_HLP_NOITTI, PARAMFLAG_BOOL, .iptr=&softmodem_params.no_itti, .defintval=0, TYPE_INT, 0}, \
{"ldpc-offload-enable", CONFIG_HLP_LDPC_OFFLOAD, PARAMFLAG_BOOL, .iptr=&LDPC_OFFLOAD_FLAG, .defstrval=0, TYPE_INT, 0}, \
{"sync-ref", CONFIG_HLP_SYNC_REF, 0, .uptr=&SYNC_REF, .defintval=0, TYPE_UINT, 0}, \
{"A" , CONFIG_HLP_TADV, 0, .iptr=&softmodem_params.command_line_sample_advance,.defintval=0, TYPE_INT, 0}, \
{"E" , CONFIG_HLP_TQFS, PARAMFLAG_BOOL, .iptr=&softmodem_params.threequarter_fs, .defintval=0, TYPE_INT, 0}, \
......@@ -232,7 +229,6 @@ extern int usrp_tx_thread;
{ .s5 = { NULL } }, \
{ .s5 = { NULL } }, \
{ .s5 = { NULL } }, \
{ .s5 = { NULL } }, \
}
// clang-format on
......@@ -321,7 +317,6 @@ typedef struct {
int continuous_tx;
uint32_t sync_ref;
int no_itti;
int ldpc_offload_flag;
int threequarter_fs;
} softmodem_params_t;
......
add_subdirectory(nr_phy_common)
add_subdirectory(TOOLS)
add_subdirectory(NR_TRANSPORT)
add_subdirectory(CODING)
add_library(coding MODULE
3gpplte_sse.c
3gpplte.c
3gpplte_turbo_decoder_sse_8bit.c
3gpplte_turbo_decoder_sse_16bit.c
3gpplte_turbo_decoder_avx2_16bit.c
3gpplte_turbo_decoder.c
)
set_target_properties(coding PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
add_library(ldpc_orig MODULE
nrLDPC_decoder/nrLDPC_decoder.c
nrLDPC_encoder/ldpc_encoder.c
)
set_target_properties(ldpc_orig PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
target_link_libraries(ldpc_orig PRIVATE ldpc_gen_HEADERS)
add_library(ldpc_optim MODULE
nrLDPC_decoder/nrLDPC_decoder.c
nrLDPC_encoder/ldpc_encoder_optim.c
)
set_target_properties(ldpc_optim PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
target_link_libraries(ldpc_optim PRIVATE ldpc_gen_HEADERS)
add_library(ldpc_optim8seg MODULE
nrLDPC_decoder/nrLDPC_decoder.c
nrLDPC_encoder/ldpc_encoder_optim8seg.c
)
set_target_properties(ldpc_optim8seg PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
target_link_libraries(ldpc_optim8seg PRIVATE ldpc_gen_HEADERS)
add_library(ldpc_optim8segmulti MODULE
nrLDPC_decoder/nrLDPC_decoder.c
nrLDPC_encoder/ldpc_encoder_optim8segmulti.c
)
set_target_properties(ldpc_optim8segmulti PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
target_link_libraries(ldpc_optim8segmulti PRIVATE ldpc_gen_HEADERS)
add_custom_target(nrLDPC_decoder_kernels_CL
COMMAND gcc nrLDPC_decoder/nrLDPC_decoder_CL.c -dD -DNRLDPC_KERNEL_SOURCE -E -o ${CMAKE_CURRENT_BINARY_DIR}/nrLDPC_decoder_kernels_CL.clc
SOURCES nrLDPC_decoder/nrLDPC_decoder_CL.c
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
)
add_library(ldpc_cl MODULE
nrLDPC_decoder/nrLDPC_decoder_CL.c
nrLDPC_encoder/ldpc_encoder_optim8segmulti.c
)
set_target_properties(ldpc_cl PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
target_link_libraries(ldpc_cl PRIVATE OpenCL)
add_dependencies(ldpc_cl nrLDPC_decoder_kernels_CL)
##############################################
# Base CUDA setting
##############################################
add_boolean_option(ENABLE_LDPC_CUDA OFF "Build support for CUDA" OFF)
if (ENABLE_LDPC_CUDA)
find_package(CUDA REQUIRED)
if (NOT CUDA_FOUND)
message(FATAL_ERROR "no CUDA found")
endif()
SET(CUDA_NVCC_FLAG "${CUDA_NVCC_FLAGS};-arch=sm_60;")
SET(CUDA_VERBOSE_BUILD ON)
cuda_add_library(ldpc_cuda MODULE
nrLDPC_decoder_LYC/nrLDPC_decoder_LYC.cu
nrLDPC_encoder/ldpc_encoder_optim8segmulti.c
)
set_target_properties(ldpc_cuda PROPERTIES CUDA_SEPARABLE_COMPILATION ON)
set_target_properties(ldpc_cuda PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
endif()
add_dependencies(ldpctest ldpc_orig ldpc_optim ldpc_optim8seg ldpc_optim8segmulti)
if (ENABLE_LDPC_CUDA)
add_dependencies(ldpctest ldpc_cuda)
endif()
add_subdirectory(nrLDPC_coding)
......@@ -403,7 +403,7 @@ int main(int argc, char *argv[])
{
short block_length=8448; // decoder supports length: 1201 -> 1280, 2401 -> 2560
// default to check output inside ldpc, the NR version checks the outer CRC defined by 3GPP
char *ldpc_version = NULL;
char *ldpc_version = "_optim8segmulti";
/* version of the ldpc decoder library to use (XXX suffix to use when loading libldpc_XXX.so */
short max_iterations=5;
int n_segments=1;
......
add_subdirectory(nrLDPC_coding_segment)
add_subdirectory(nrLDPC_coding_xdma)
add_subdirectory(nrLDPC_coding_t2)
/*
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenAirInterface Software Alliance licenses this file to You under
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
* except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.openairinterface.org/?page_id=698
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*-------------------------------------------------------------------------------
* For more information about the OpenAirInterface (OAI) Software Alliance:
* contact@openairinterface.org
*/
/*! \file openair1/PHY/CODING/nrLDPC_coding/nrLDPC_coding_interface.h
* \brief interface for libraries implementing coding/decoding algorithms
*/
#include "PHY/defs_gNB.h"
#ifndef __NRLDPC_CODING_INTERFACE__H__
#define __NRLDPC_CODING_INTERFACE__H__
/**
* \typedef nrLDPC_segment_decoding_parameters_t
* \struct nrLDPC_segment_decoding_parameters_s
* \brief decoding parameter of segments
* \var E input llr segment size
* \var R code rate indication
* \var llr segment input llr array
* \var d Pointers to code blocks before LDPC decoding (38.212 V15.4.0 section 5.3.2)
* \var d_to_be_cleared
* pointer to the flag used to clear d properly
* when true, clear d after rate dematching
* \var c Pointers to code blocks after LDPC decoding (38.212 V15.4.0 section 5.2.2)
* \var decodeSuccess
* flag indicating that the decoding of the segment was successful
* IT MUST BE FILLED BY THE IMPLEMENTATION
* \var ts_deinterleave deinterleaving time stats
* \var ts_rate_unmatch rate unmatching time stats
* \var ts_ldpc_decode decoding time stats
*/
typedef struct nrLDPC_segment_decoding_parameters_s{
int E;
uint8_t R;
short *llr;
int16_t *d;
bool *d_to_be_cleared;
uint8_t *c;
bool decodeSuccess;
time_stats_t ts_deinterleave;
time_stats_t ts_rate_unmatch;
time_stats_t ts_ldpc_decode;
} nrLDPC_segment_decoding_parameters_t;
/**
* \typedef nrLDPC_TB_decoding_parameters_t
* \struct nrLDPC_TB_decoding_parameters_s
* \brief decoding parameter of transport blocks
* \var harq_unique_pid unique id of the HARQ process
* WARNING This id should be unique in the whole instance
* among the active HARQ processes for the duration of the process
* \var processedSegments
* pointer to the number of succesfully decoded segments
* it initially holds the total number of segments decoded after the previous HARQ round
* it finally holds the total number of segments decoded after the current HARQ round
* \var nb_rb number of resource blocks
* \var Qm modulation order
* \var mcs MCS
* \var nb_layers number of layers
* \var BG LDPC base graph id
* \var rv_index redundancy version of the current HARQ round
* \var max_ldpc_iterations maximum number of LDPC iterations
* \var abort_decode pointer to decode abort flag
* \var G Available radio resource bits
* \var tbslbrm Transport block size LBRM
* \var A Transport block size (This is A from 38.212 V15.4.0 section 5.1)
* \var K Code block size at decoder output
* \var Z lifting size
* \var F filler bits size
* \var C number of segments
* \var segments array of segments parameters
*/
typedef struct nrLDPC_TB_decoding_parameters_s{
uint32_t harq_unique_pid;
uint32_t *processedSegments;
uint16_t nb_rb;
uint8_t Qm;
uint8_t mcs;
uint8_t nb_layers;
uint8_t BG;
uint8_t rv_index;
uint8_t max_ldpc_iterations;
decode_abort_t *abort_decode;
uint32_t G;
uint32_t tbslbrm;
uint32_t A;
uint32_t K;
uint32_t Z;
uint32_t F;
uint32_t C;
nrLDPC_segment_decoding_parameters_t *segments;
} nrLDPC_TB_decoding_parameters_t;
/**
* \typedef nrLDPC_slot_decoding_parameters_t
* \struct nrLDPC_slot_decoding_parameters_s
* \brief decoding parameter of slot
* \var frame frame index
* \var slot slot index
* \var nb_TBs number of transport blocks
* \var threadPool pointer to the thread pool
* The thread pool can be used by the implementation
* in order to launch jobs internally
* DEQUEUING THE JOBS IS DONE WITHIN THE IMPLEMENTATION
* \var TBs array of TBs decoding parameters
*/
typedef struct nrLDPC_slot_decoding_parameters_s{
int frame;
int slot;
int nb_TBs;
tpool_t *threadPool;
nrLDPC_TB_decoding_parameters_t *TBs;
} nrLDPC_slot_decoding_parameters_t;
/**
* \typedef nrLDPC_segment_encoding_parameters_t
* \struct nrLDPC_segment_encoding_parameters_s
* \brief encoding parameter of segments
* \var E input llr segment size
* \var output input llr segment array
* \var c Pointers to code blocks before LDPC encoding (38.212 V15.4.0 section 5.2.2)
* flag indicating that the decoding of the segment was successful
* IT MUST BE FILLED BY THE IMPLEMENTATION
* \var ts_interleave interleaving time stats
* \var ts_rate_match rate matching time stats
* \var ts_ldpc_encode encoding time stats
*/
typedef struct nrLDPC_segment_encoding_parameters_s{
int E;
unsigned char *output;
uint8_t *c;
time_stats_t ts_interleave;
time_stats_t ts_rate_match;
time_stats_t ts_ldpc_encode;
} nrLDPC_segment_encoding_parameters_t;
/**
* \typedef nrLDPC_TB_encoding_parameters_t
* \struct nrLDPC_TB_encoding_parameters_s
* \brief encoding parameter of transport blocks
* \var harq_unique_pid unique id of the HARQ process
* WARNING This id should be unique in the whole instance
* among the active HARQ processes for the duration of the process
* \var nb_rb number of resource blocks
* \var Qm modulation order
* \var mcs MCS
* \var nb_layers number of layers
* \var BG LDPC base graph id
* \var rv_index
* \var G Available radio resource bits
* \var tbslbrm Transport block size LBRM
* \var A Transport block size (This is A from 38.212 V15.4.0 section 5.1)
* \var Kb Code block size divided by lifting size
* \var K Code block size at input of encoder
* \var Z lifting size
* \var F filler bits size
* \var C number of segments
* \var segments array of segments parameters
*/
typedef struct nrLDPC_TB_encoding_parameters_s{
uint32_t harq_unique_pid;
uint16_t nb_rb;
uint8_t Qm;
uint8_t mcs;
uint8_t nb_layers;
uint8_t BG;
uint8_t rv_index;
uint32_t G;
uint32_t tbslbrm;
uint32_t A;
uint32_t Kb;
uint32_t K;
uint32_t Z;
uint32_t F;
uint32_t C;
nrLDPC_segment_encoding_parameters_t *segments;
} nrLDPC_TB_encoding_parameters_t;
/**
* \typedef nrLDPC_slot_encoding_parameters_t
* \struct nrLDPC_slot_encoding_parameters_s
* \brief encoding parameter of slot
* \var frame frame index
* \var slot slot index
* \var nb_TBs number of transport blocks
* \var threadPool pointer to the thread pool
* The thread pool can be used by the implementation
* in order to launch jobs internally
* DEQUEUING THE JOBS IS DONE WITHIN THE IMPLEMENTATION
* \var tinput pointer to the input timer struct
* \var tprep pointer to the preparation timer struct
* \var tparity pointer to the parity timer struct
* \var toutput pointer to the output timer struct
* \var TBs array of TBs decoding parameters
*/
typedef struct nrLDPC_slot_encoding_parameters_s{
int frame;
int slot;
int nb_TBs;
tpool_t *threadPool;
time_stats_t *tinput;
time_stats_t *tprep;
time_stats_t *tparity;
time_stats_t *toutput;
nrLDPC_TB_encoding_parameters_t *TBs;
} nrLDPC_slot_encoding_parameters_t;
typedef int32_t(nrLDPC_coding_init_t)(void);
typedef int32_t(nrLDPC_coding_shutdown_t)(void);
/**
* \brief slot decoding function interface
* \param nrLDPC_slot_decoding_parameters pointer to the structure holding the parameters necessary for decoding
*/
typedef int32_t(nrLDPC_coding_decoder_t)(nrLDPC_slot_decoding_parameters_t *nrLDPC_slot_decoding_parameters);
/**
* \brief slot encoding function interface
* \param nrLDPC_slot_encoding_parameters pointer to the structure holding the parameters necessary for encoding
*/
typedef int32_t(nrLDPC_coding_encoder_t)(nrLDPC_slot_encoding_parameters_t *nrLDPC_slot_encoding_parameters);
typedef struct nrLDPC_coding_interface_s {
nrLDPC_coding_init_t *nrLDPC_coding_init;
nrLDPC_coding_shutdown_t *nrLDPC_coding_shutdown;
nrLDPC_coding_decoder_t *nrLDPC_coding_decoder;
nrLDPC_coding_encoder_t *nrLDPC_coding_encoder;
} nrLDPC_coding_interface_t;
int load_nrLDPC_coding_interface(char *version, nrLDPC_coding_interface_t *interface);
int free_nrLDPC_coding_interface(nrLDPC_coding_interface_t *interface);
#endif
/*
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenAirInterface Software Alliance licenses this file to You under
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
* except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.openairinterface.org/?page_id=698
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*-------------------------------------------------------------------------------
* For more information about the OpenAirInterface (OAI) Software Alliance:
* contact@openairinterface.org
*/
/*! \file openair1/PHY/CODING/nrLDPC_coding/nrLDPC_coding_interface_load.c
* \brief load library implementing coding/decoding algorithms
*/
#define _GNU_SOURCE
#include <sys/types.h>
#include <stdlib.h>
#include <malloc.h>
#include "assertions.h"
#include "common/utils/LOG/log.h"
#include "PHY/CODING/nrLDPC_coding/nrLDPC_coding_interface.h"
#include "PHY/CODING/nrLDPC_extern.h"
#include "common/config/config_userapi.h"
#include "common/utils/load_module_shlib.h"
/* arguments used when called from phy simulators exec's which do not use the config module */
/* arg is used to initialize the config module so that the loader works as expected */
char *arguments_phy_simulators[64]={"ldpctest",NULL};
int load_nrLDPC_coding_interface(char *version, nrLDPC_coding_interface_t *itf)
{
char *ptr = (char *)config_get_if();
char libname[64] = "ldpc";
if (ptr == NULL) { // phy simulators, config module possibly not loaded
uniqCfg = load_configmodule(1, arguments_phy_simulators, CONFIG_ENABLECMDLINEONLY);
logInit();
}
/* function description array, to be used when loading the encoding/decoding shared lib */
loader_shlibfunc_t shlib_fdesc[] = {{.fname = "nrLDPC_coding_init"},
{.fname = "nrLDPC_coding_shutdown"},
{.fname = "nrLDPC_coding_decoder"},
{.fname = "nrLDPC_coding_encoder"}};
int ret;
ret = load_module_version_shlib(libname, version, shlib_fdesc, sizeofArray(shlib_fdesc), NULL);
if(ret < 0){
LOG_D(PHY, "NR ULSCH decoding module unavailable");
return ret;
}
itf->nrLDPC_coding_init = (nrLDPC_coding_init_t *)shlib_fdesc[0].fptr;
itf->nrLDPC_coding_shutdown = (nrLDPC_coding_shutdown_t *)shlib_fdesc[1].fptr;
itf->nrLDPC_coding_decoder = (nrLDPC_coding_decoder_t *)shlib_fdesc[2].fptr;
itf->nrLDPC_coding_encoder = (nrLDPC_coding_encoder_t *)shlib_fdesc[3].fptr;
AssertFatal(itf->nrLDPC_coding_init() == 0, "error starting LDPC library %s %s\n", libname, version);
return 0;
}
int free_nrLDPC_coding_interface(nrLDPC_coding_interface_t *interface)
{
return interface->nrLDPC_coding_shutdown();
}
add_library(ldpc MODULE
nrLDPC_coding_segment_decoder.c
nrLDPC_coding_segment_encoder.c
${PHY_NR_CODINGIF}
)
set_target_properties(ldpc PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
add_dependencies(nr-softmodem ldpc)
add_dependencies(nr-uesoftmodem ldpc)
add_dependencies(nr_ulsim ldpc)
add_dependencies(nr_ulschsim ldpc)
add_dependencies(nr_dlsim ldpc)
add_dependencies(nr_dlschsim ldpc)
add_dependencies(ldpc ldpc_orig ldpc_optim ldpc_optim8seg ldpc_optim8segmulti)
if (ENABLE_LDPC_CUDA)
add_dependencies(ldpc ldpc_cuda)
endif()
/*
* 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.0 (the "License"); you may not use this file
* except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.openairinterface.org/?page_id=698
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*-------------------------------------------------------------------------------
* For more information about the OpenAirInterface (OAI) Software Alliance:
* contact@openairinterface.org
*/
/*! \file PHY/CODING/nrLDPC_coding/nrLDPC_coding_segment/nrLDPC_coding_segment_encoder.c
* \brief Top-level routines for implementing LDPC encoding of transport channels
*/
#include "PHY/defs_gNB.h"
#include "PHY/CODING/coding_extern.h"
#include "PHY/CODING/coding_defs.h"
#include "PHY/CODING/lte_interleaver_inline.h"
#include "PHY/CODING/nrLDPC_coding/nrLDPC_coding_interface.h"
#include "PHY/CODING/nrLDPC_extern.h"
#include "PHY/NR_TRANSPORT/nr_transport_proto.h"
#include "PHY/NR_TRANSPORT/nr_transport_common_proto.h"
#include "PHY/NR_TRANSPORT/nr_dlsch.h"
#include "SCHED_NR/sched_nr.h"
#include "common/utils/LOG/vcd_signal_dumper.h"
#include "common/utils/LOG/log.h"
#include "common/utils/nr/nr_common.h"
#include <openair2/UTIL/OPT/opt.h>
#include <syscall.h>
//#define DEBUG_LDPC_ENCODING
//#define DEBUG_LDPC_ENCODING_FREE 1
extern ldpc_interface_t ldpc_interface_segment;
typedef struct ldpc8blocks_args_s {
nrLDPC_TB_encoding_parameters_t *nrLDPC_TB_encoding_parameters;
encoder_implemparams_t impp;
} ldpc8blocks_args_t;
static void ldpc8blocks_coding_segment(void *p)
{
ldpc8blocks_args_t *args = (ldpc8blocks_args_t *)p;
nrLDPC_TB_encoding_parameters_t *nrLDPC_TB_encoding_parameters = args->nrLDPC_TB_encoding_parameters;
encoder_implemparams_t *impp = &args->impp;
uint8_t mod_order = nrLDPC_TB_encoding_parameters->Qm;
uint16_t nb_rb = nrLDPC_TB_encoding_parameters->nb_rb;
uint32_t A = nrLDPC_TB_encoding_parameters->A;
unsigned int G = nrLDPC_TB_encoding_parameters->G;
LOG_D(PHY,"dlsch coding A %d Kr %d G %d (nb_rb %d, mod_order %d)\n",
A,impp->K,G, nb_rb,(int)mod_order);
// nrLDPC_encoder output is in "d"
// let's make this interface happy!
uint8_t tmp[8][68 * 384]__attribute__((aligned(32)));
uint8_t *d[impp->n_segments];
for (int rr=impp->macro_num*8, i=0; rr < impp->n_segments && rr < (impp->macro_num+1)*8; rr++,i++ )
d[rr] = tmp[i];
uint8_t *c[nrLDPC_TB_encoding_parameters->C];
for (int r = 0; r < nrLDPC_TB_encoding_parameters->C; r++)
c[r]=nrLDPC_TB_encoding_parameters->segments[r].c;
start_meas(&nrLDPC_TB_encoding_parameters->segments[impp->macro_num*8].ts_ldpc_encode);
ldpc_interface_segment.LDPCencoder(c, d, impp);
stop_meas(&nrLDPC_TB_encoding_parameters->segments[impp->macro_num*8].ts_ldpc_encode);
// Compute where to place in output buffer that is concatenation of all segments
uint32_t r_offset=0;
for (int i=0; i < impp->macro_num*8; i++ )
r_offset+=nrLDPC_TB_encoding_parameters->segments[i].E;
for (int rr=impp->macro_num*8; rr < impp->n_segments && rr < (impp->macro_num+1)*8; rr++ ) {
if (impp->F>0) {
// writing into positions d[r][k-2Zc] as in clause 5.3.2 step 2) in 38.212
memset(&d[rr][impp->K - impp->F - 2 * impp->Zc], NR_NULL, impp->F);
}
#ifdef DEBUG_LDPC_ENCODING
LOG_D(PHY,"rvidx in encoding = %d\n", rel15->rvIndex[0]);
#endif
uint32_t E = nrLDPC_TB_encoding_parameters->segments[rr].E;
LOG_D(NR_PHY,
"Rate Matching, Code segment %d/%d (coded bits (G) %u, E %d, Filler bits %d, Filler offset %d mod_order %d, nb_rb "
"%d,nrOfLayer %d)...\n",
rr,
impp->n_segments,
G,
E,
impp->F,
impp->K - impp->F - 2 * impp->Zc,
mod_order,
nb_rb,
nrLDPC_TB_encoding_parameters->nb_layers);
uint32_t Tbslbrm = nrLDPC_TB_encoding_parameters->tbslbrm;
uint8_t e[E];
bzero (e, E);
start_meas(&nrLDPC_TB_encoding_parameters->segments[rr].ts_rate_match);
nr_rate_matching_ldpc(Tbslbrm,
impp->BG,
impp->Zc,
d[rr],
e,
impp->n_segments,
impp->F,
impp->K - impp->F - 2 * impp->Zc,
nrLDPC_TB_encoding_parameters->rv_index,
E);
stop_meas(&nrLDPC_TB_encoding_parameters->segments[rr].ts_rate_match);
if (impp->K - impp->F - 2 * impp->Zc > E) {
LOG_E(PHY,
"dlsch coding A %d Kr %d G %d (nb_rb %d, mod_order %d)\n",
A,
impp->K,
G,
nb_rb,
(int)mod_order);
LOG_E(NR_PHY,
"Rate Matching, Code segment %d/%d (coded bits (G) %u, E %d, Kr %d, Filler bits %d, Filler offset %d mod_order %d, "
"nb_rb %d)...\n",
rr,
impp->n_segments,
G,
E,
impp->K,
impp->F,
impp->K - impp->F - 2 * impp->Zc,
mod_order,
nb_rb);
}
#ifdef DEBUG_LDPC_ENCODING
for (int i =0; i<16; i++)
printf("output ratematching e[%d]= %d r_offset %u\n", i,e[i], r_offset);
#endif
start_meas(&nrLDPC_TB_encoding_parameters->segments[rr].ts_interleave);
nr_interleaving_ldpc(E,
mod_order,
e,
impp->output+r_offset);
stop_meas(&nrLDPC_TB_encoding_parameters->segments[rr].ts_interleave);
#ifdef DEBUG_LDPC_ENCODING
for (int i =0; i<16; i++)
printf("output interleaving f[%d]= %d r_offset %u\n", i,impp->output[i+r_offset], r_offset);
if (r==impp->n_segments-1)
write_output("enc_output.m","enc",impp->output,G,1,4);
#endif
r_offset += E;
}
// Task running in // completed
completed_task_ans(impp->ans);
}
static int nrLDPC_prepare_TB_encoding(nrLDPC_slot_encoding_parameters_t *nrLDPC_slot_encoding_parameters, int dlsch_id, thread_info_tm_t *t_info)
{
nrLDPC_TB_encoding_parameters_t *nrLDPC_TB_encoding_parameters = &nrLDPC_slot_encoding_parameters->TBs[dlsch_id];
encoder_implemparams_t impp = {0};
impp.n_segments = nrLDPC_TB_encoding_parameters->C;
impp.tinput = nrLDPC_slot_encoding_parameters->tinput;
impp.tprep = nrLDPC_slot_encoding_parameters->tprep;
impp.tparity = nrLDPC_slot_encoding_parameters->tparity;
impp.toutput = nrLDPC_slot_encoding_parameters->toutput;
impp.Kb = nrLDPC_TB_encoding_parameters->Kb;
impp.Zc = nrLDPC_TB_encoding_parameters->Z;
NR_DL_gNB_HARQ_t harq;
impp.harq = &harq;
impp.BG = nrLDPC_TB_encoding_parameters->BG;
impp.output = nrLDPC_TB_encoding_parameters->segments->output;
impp.K = nrLDPC_TB_encoding_parameters->K;
impp.F = nrLDPC_TB_encoding_parameters->F;
size_t const n_seg = (impp.n_segments / 8 + ((impp.n_segments & 7) == 0 ? 0 : 1));
for (int j = 0; j < n_seg; j++) {
ldpc8blocks_args_t *perJobImpp = &((ldpc8blocks_args_t *)t_info->buf)[t_info->len];
DevAssert(t_info->len < t_info->cap);
impp.ans = &t_info->ans[t_info->len];
t_info->len += 1;
impp.macro_num = j;
perJobImpp->impp = impp;
perJobImpp->nrLDPC_TB_encoding_parameters = nrLDPC_TB_encoding_parameters;
task_t t = {.func = ldpc8blocks_coding_segment, .args = perJobImpp};
pushTpool(nrLDPC_slot_encoding_parameters->threadPool, t);
}
return n_seg;
}
int nrLDPC_coding_encoder(nrLDPC_slot_encoding_parameters_t *nrLDPC_slot_encoding_parameters)
{
int nbTasks = 0;
for (int dlsch_id = 0; dlsch_id < nrLDPC_slot_encoding_parameters->nb_TBs; dlsch_id++) {
nrLDPC_TB_encoding_parameters_t *nrLDPC_TB_encoding_parameters = &nrLDPC_slot_encoding_parameters->TBs[dlsch_id];
size_t n_seg = (nrLDPC_TB_encoding_parameters->C / 8 + ((nrLDPC_TB_encoding_parameters->C & 7) == 0 ? 0 : 1));
nbTasks += n_seg;
}
ldpc8blocks_args_t arr[nbTasks];
task_ans_t ans[nbTasks];
memset(ans, 0, nbTasks * sizeof(task_ans_t));
thread_info_tm_t t_info = {.buf = (uint8_t *)arr, .len = 0, .cap = nbTasks, .ans = ans};
int nbEncode = 0;
for (int dlsch_id = 0; dlsch_id < nrLDPC_slot_encoding_parameters->nb_TBs; dlsch_id++) {
nbEncode += nrLDPC_prepare_TB_encoding(nrLDPC_slot_encoding_parameters, dlsch_id, &t_info);
}
DevAssert(nbEncode == t_info.len);
// Execute thread poool tasks
join_task_ans(ans, nbEncode);
return 0;
}
##########################################################
# LDPC offload library - AMD T2 Accelerator Card
##########################################################
add_boolean_option(ENABLE_LDPC_T2 OFF "Build support for LDPC Offload to T2 library" OFF)
if (ENABLE_LDPC_T2)
pkg_check_modules(LIBDPDK_T2 REQUIRED libdpdk=20.11.9)
find_library(PMD_T2 NAMES rte_baseband_accl_ldpc HINTS ${LIBDPDK_T2_LIBRARY_DIRS})
if (NOT PMD_T2)
message(FATAL_ERROR "could not find poll-mode driver for AccelerComm T2 LDPC Offload (rte_baseband_accl_ldpc.so)")
endif()
message(STATUS "T2 build: use ${PMD_T2}")
add_library(ldpc_t2 MODULE nrLDPC_coding_t2.c)
set_target_properties(ldpc_t2 PROPERTIES COMPILE_FLAGS "-DALLOW_EXPERIMENTAL_API")
set_target_properties(ldpc_t2 PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
target_link_libraries(ldpc_t2 PRIVATE ldpc_gen_HEADERS ${LIBDPDK_T2_LDFLAGS} ${PMD_T2})
add_dependencies(nr-softmodem ldpc_t2)
add_dependencies(nr-uesoftmodem ldpc_t2)
add_dependencies(nr_ulsim ldpc_t2)
add_dependencies(nr_ulschsim ldpc_t2)
add_dependencies(nr_dlsim ldpc_t2)
add_dependencies(nr_dlschsim ldpc_t2)
endif()
##########################################################
# LDPC offload library - XDMA
##########################################################
add_boolean_option(ENABLE_LDPC_XDMA OFF "Build support for LDPC Offload to XDMA library" OFF)
if (ENABLE_LDPC_XDMA)
add_library(ldpc_xdma MODULE
nrLDPC_coding_xdma_offload.c
nrLDPC_coding_xdma.c
../nrLDPC_coding_segment/nrLDPC_coding_segment_encoder.c
../../nrLDPC_load.c
)
set_target_properties(ldpc_xdma PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
add_dependencies(nr-softmodem ldpc_xdma)
add_dependencies(nr-uesoftmodem ldpc_xdma)
add_dependencies(nr_ulsim ldpc_xdma)
add_dependencies(nr_ulschsim ldpc_xdma)
add_dependencies(nr_dlsim ldpc_xdma)
add_dependencies(nr_dlschsim ldpc_xdma)
add_dependencies(ldpc_xdma ldpc_orig ldpc_optim ldpc_optim8seg ldpc_optim8segmulti)
if (ENABLE_LDPC_CUDA)
add_dependencies(ldpc_xdma ldpc_cuda)
endif()
endif()
/*
* 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.0 (the "License"); you may not use this
* file except in compliance with the License. You may obtain a copy of the
* License at
*
* http://www.openairinterface.org/?page_id=698
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* -------------------------------------------------------------------------------
* For more information about the OpenAirInterface (OAI) Software Alliance:
* contact@openairinterface.org
*/
/*! \file PHY/CODING/nrLDPC_coding/nrLDPC_coding_xdma/nrLDPC_coding_xdma_offload.h
* \briefFPGA accelerator integrated into OAI (for one and multi code block)
* \author Sendren Xu, SY Yeh(fdragon), Hongming, Terng-Yin Hsu
* \date 2022-05-31
* \version 5.0
* \email: summery19961210@gmail.com
*/
#ifndef __NRLDPC_CODING_XDMA_OFFLOAD__H_
#define __NRLDPC_CODING_XDMA_OFFLOAD__H_
#include <stdint.h>
#define DEVICE_NAME_DEFAULT_USER "/dev/xdma0_user"
#define DEVICE_NAME_DEFAULT_ENC_READ "/dev/xdma0_c2h_1"
#define DEVICE_NAME_DEFAULT_ENC_WRITE "/dev/xdma0_h2c_1"
#define DEVICE_NAME_DEFAULT_DEC_READ "/dev/xdma0_c2h_0"
#define DEVICE_NAME_DEFAULT_DEC_WRITE "/dev/xdma0_h2c_0"
/**
\brief LDPC input parameter
\param Zc shifting size
\param Rows
\param baseGraph base graph
\param CB_num number of code block
\param numChannelLlrs input soft bits length, Zc x 66 - length of filler bits
\param numFillerBits filler bits length
*/
typedef struct {
char *user_device, *enc_write_device, *enc_read_device, *dec_write_device, *dec_read_device;
unsigned char max_schedule;
unsigned char SetIdx;
int Zc;
unsigned char numCB;
unsigned char BG;
unsigned char max_iter;
int nRows;
int numChannelLls;
int numFillerBits;
} DecIFConf;
int nrLDPC_decoder_FPGA_PYM(uint8_t *buf_in, uint8_t *buf_out, DecIFConf dec_conf);
#endif // __NRLDPC_CODING_XDMA_OFFLOAD__H_
/*
* Copyright (c) 2016-present, Xilinx, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license
* the terms of the BSD Licence are reported below:
*
* BSD License
*
* For Xilinx DMA IP software
*
* Copyright (c) 2016-present, Xilinx, Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name Xilinx nor the names of its contributors may be used to
* endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef MODULES_TXCTRL_INC_XDMA_DIAG_H_
#define MODULES_TXCTRL_INC_XDMA_DIAG_H_
#ifdef __cplusplus
extern "C" {
#endif
typedef struct {
unsigned char max_schedule; // max_schedule = 0;
unsigned char mb; // mb = 32;
unsigned char CB_num; // id = CB_num;
unsigned char BGSel; // bg = 1;
unsigned char z_set; // z_set = 0;
unsigned char z_j; // z_j = 6;
unsigned char max_iter; // max_iter = 8;
unsigned char SetIdx; // sc_idx = 12;
} DecIPConf;
typedef struct {
int SetIdx;
int NumCBSegm;
int PayloadLen;
int Z;
int z_set;
int z_j;
int Kbmax;
int BGSel;
unsigned mb;
unsigned char CB_num;
unsigned char kb_1;
} EncIPConf;
typedef struct {
char *user_device, *enc_write_device, *enc_read_device, *dec_write_device, *dec_read_device;
} devices_t;
/* ltoh: little to host */
/* htol: little to host */
#if __BYTE_ORDER == __LITTLE_ENDIAN
#define ltohl(x) (x)
#define ltohs(x) (x)
#define htoll(x) (x)
#define htols(x) (x)
#elif __BYTE_ORDER == __BIG_ENDIAN
#define ltohl(x) __bswap_32(x)
#define ltohs(x) __bswap_16(x)
#define htoll(x) __bswap_32(x)
#define htols(x) __bswap_16(x)
#endif
#define MAP_SIZE (32 * 1024UL)
#define MAP_MASK (MAP_SIZE - 1)
#define SIZE_DEFAULT (32)
#define COUNT_DEFAULT (1)
#define OFFSET_DEC_IN 0x0000
#define OFFSET_DEC_OUT 0x0004
#define OFFSET_ENC_IN 0x0008
#define OFFSET_ENC_OUT 0x000c
#define OFFSET_RESET 0x0020
#define PCIE_OFF 0x0030
#define CB_PROCESS_NUMBER 24 // add by JW
#define CB_PROCESS_NUMBER_Dec 24
// dma_from_device.c
int test_dma_enc_read(char *EncOut, EncIPConf Confparam);
int test_dma_enc_write(char *data, EncIPConf Confparam);
int test_dma_dec_read(char *DecOut, DecIPConf Confparam);
int test_dma_dec_write(char *data, DecIPConf Confparam);
void test_dma_init(devices_t devices);
void test_dma_shutdown();
void dma_reset(devices_t devices);
#ifdef __cplusplus
}
#endif
#endif
......@@ -78,15 +78,6 @@ typedef enum nrLDPC_outMode {
nrLDPC_outMode_LLRINT8 /**< Single LLR value per int8_t output */
} e_nrLDPC_outMode;
/**
Structure containing LDPC parameters per CB
*/
typedef struct nrLDPC_params_per_cb {
uint32_t E_cb;
uint8_t status_cb;
uint8_t* p_status_cb;
} nrLDPC_params_per_cb_t;
/**
Structure containing LDPC decoder parameters.
*/
......@@ -94,35 +85,14 @@ typedef struct nrLDPC_dec_params {
uint8_t BG; /**< Base graph */
uint16_t Z; /**< Lifting size */
uint8_t R; /**< Decoding rate: Format 15,13,... for code rates 1/5, 1/3,... */
uint16_t F; /**< Filler bits */
uint8_t Qm; /**< Modulation */
uint8_t rv;
uint8_t numMaxIter; /**< Maximum number of iterations */
int E;
e_nrLDPC_outMode outMode; /**< Output format */
int crc_type;
int (*check_crc)(uint8_t* decoded_bytes, uint32_t n, uint8_t crc_type);
uint8_t setCombIn;
nrLDPC_params_per_cb_t perCB[NR_LDPC_MAX_NUM_CB];
} t_nrLDPC_dec_params;
/**
Structure containing LDPC offload parameters.
*/
typedef struct nrLDPCoffload_params {
uint8_t BG; /**< Base graph */
uint16_t Z;
uint16_t Kr;
uint8_t rv;
uint16_t n_cb;
uint16_t F; /**< Filler bits */
uint8_t Qm; /**< Modulation */
uint8_t C;
uint8_t numMaxIter;
uint8_t setCombIn;
nrLDPC_params_per_cb_t perCB[NR_LDPC_MAX_NUM_CB];
} t_nrLDPCoffload_params;
/**
Structure containing LDPC decoder processing time statistics.
*/
......
......@@ -57,13 +57,6 @@ typedef struct {
uint32_t K;
/// Number of "Filler" bits
uint32_t F;
/// Modulation order
uint8_t Qm;
uint32_t Tbslbrm;
unsigned int G;
nrLDPC_params_per_cb_t perCB[NR_LDPC_MAX_NUM_CB];
// Redundancy version index
uint8_t rv;
task_ans_t *ans;
} encoder_implemparams_t;
......
......@@ -26,6 +26,7 @@
#include "PHY/defs_gNB.h"
#include "PHY/NR_REFSIG/nr_refsig.h"
#include "PHY/INIT/nr_phy_init.h"
#include "PHY/CODING/nrLDPC_coding/nrLDPC_coding_interface.h"
#include "PHY/CODING/nrPolar_tools/nr_polar_pbch_defs.h"
#include "PHY/NR_TRANSPORT/nr_transport_proto.h"
#include "PHY/NR_TRANSPORT/nr_transport_common_proto.h"
......@@ -40,6 +41,7 @@
#include "PHY/NR_REFSIG/nr_refsig.h"
#include "SCHED_NR/fapi_nr_l1.h"
#include "PHY/NR_REFSIG/ul_ref_seq_nr.h"
#include <string.h>
int l1_north_init_gNB()
{
......@@ -96,9 +98,6 @@ void reset_active_stats(PHY_VARS_gNB *gNB, int frame)
}
}
// A global var to reduce the changes size
ldpc_interface_t ldpc_interface = {0}, ldpc_interface_offload = {0};
void phy_init_nr_gNB(PHY_VARS_gNB *gNB)
{
// shortcuts
......@@ -134,15 +133,11 @@ void phy_init_nr_gNB(PHY_VARS_gNB *gNB)
nr_init_fde(); // Init array for frequency equalization of transform precoding of PUSCH
load_LDPClib(NULL, &ldpc_interface);
int ret_loader = load_nrLDPC_coding_interface(NULL, &gNB->nrLDPC_coding_interface);
AssertFatal(ret_loader == 0, "error loading LDPC library\n");
pthread_mutex_init(&gNB->UL_INFO.crc_rx_mutex, NULL);
if (gNB->ldpc_offload_flag)
load_LDPClib("_t2", &ldpc_interface_offload);
else
load_LDPClib(NULL, &ldpc_interface);
gNB->max_nb_pdsch = MAX_MOBILES_PER_GNB;
init_delay_table(fp->ofdm_symbol_size, MAX_DELAY_COMP, NR_MAX_OFDM_SYMBOL_SIZE, fp->delay_table);
......
......@@ -358,6 +358,7 @@ void free_nr_ue_dl_harq(NR_DL_UE_HARQ_t harq_list[2][NR_MAX_DLSCH_HARQ_PROCESSES
free_and_zero(harq_list[j][i].c[r]);
free_and_zero(harq_list[j][i].d[r]);
}
free_and_zero(harq_list[j][i].b);
free_and_zero(harq_list[j][i].c);
free_and_zero(harq_list[j][i].d);
}
......@@ -408,6 +409,7 @@ void nr_init_dl_harq_processes(NR_DL_UE_HARQ_t harq_list[2][NR_MAX_DLSCH_HARQ_PR
memset(harq_list[j] + i, 0, sizeof(NR_DL_UE_HARQ_t));
init_downlink_harq_status(harq_list[j] + i);
harq_list[j][i].b = malloc16_clear(a_segments * 1056);
harq_list[j][i].c = malloc16(a_segments*sizeof(uint8_t *));
harq_list[j][i].d = malloc16(a_segments*sizeof(int16_t *));
const int sz=5*8448*sizeof(int16_t);
......
......@@ -65,6 +65,67 @@ void nr_generate_pdsch(processingData_L1tx_t *msgTx, int frame, int slot)
time_stats_t *dlsch_interleaving_stats=&gNB->dlsch_interleaving_stats;
time_stats_t *dlsch_segmentation_stats=&gNB->dlsch_segmentation_stats;
size_t size_output = 0;
for (int dlsch_id=0; dlsch_id<msgTx->num_pdsch_slot; dlsch_id++) {
NR_gNB_DLSCH_t *dlsch = msgTx->dlsch[dlsch_id];
NR_DL_gNB_HARQ_t *harq = &dlsch->harq_process;
nfapi_nr_dl_tti_pdsch_pdu_rel15_t *rel15 = &harq->pdsch_pdu.pdsch_pdu_rel15;
LOG_D(PHY,"pdsch: BWPStart %d, BWPSize %d, rbStart %d, rbsize %d\n",
rel15->BWPStart,rel15->BWPSize,rel15->rbStart,rel15->rbSize);
const int Qm = rel15->qamModOrder[0];
/* PTRS */
uint16_t dlPtrsSymPos = 0;
int n_ptrs = 0;
uint32_t ptrsSymbPerSlot = 0;
if(rel15->pduBitmap & 0x1) {
set_ptrs_symb_idx(&dlPtrsSymPos,
rel15->NrOfSymbols,
rel15->StartSymbolIndex,
1 << rel15->PTRSTimeDensity,
rel15->dlDmrsSymbPos);
n_ptrs = (rel15->rbSize + rel15->PTRSFreqDensity - 1) / rel15->PTRSFreqDensity;
ptrsSymbPerSlot = get_ptrs_symbols_in_slot(dlPtrsSymPos, rel15->StartSymbolIndex, rel15->NrOfSymbols);
}
harq->unav_res = ptrsSymbPerSlot * n_ptrs;
/// CRC, coding, interleaving and rate matching
AssertFatal(harq->pdu!=NULL,"harq->pdu is null\n");
/* output and its parts for each dlsch should be aligned on 64 bytes
* => size_output is a sum of parts sizes rounded up to a multiple of 64
*/
size_t size_output_tb = rel15->rbSize * NR_SYMBOLS_PER_SLOT * NR_NB_SC_PER_RB * Qm * rel15->nrOfLayers;
size_output += (size_output_tb + 63 - ((size_output_tb + 63) % 64));
}
unsigned char output[size_output] __attribute__((aligned(64)));
bzero(output, size_output);
size_t offset_output = 0;
start_meas(dlsch_encoding_stats);
if (nr_dlsch_encoding(gNB,
msgTx,
frame,
slot,
frame_parms,
output,
tinput,
tprep,
tparity,
toutput,
dlsch_rate_matching_stats,
dlsch_interleaving_stats,
dlsch_segmentation_stats) == -1) {
return;
}
stop_meas(dlsch_encoding_stats);
for (int dlsch_id=0; dlsch_id<msgTx->num_pdsch_slot; dlsch_id++) {
NR_gNB_DLSCH_t *dlsch = msgTx->dlsch[dlsch_id];
......@@ -100,45 +161,24 @@ void nr_generate_pdsch(processingData_L1tx_t *msgTx, int frame, int slot)
}
harq->unav_res = ptrsSymbPerSlot * n_ptrs;
/// CRC, coding, interleaving and rate matching
AssertFatal(harq->pdu!=NULL,"harq->pdu is null\n");
unsigned char output[rel15->rbSize * NR_SYMBOLS_PER_SLOT * NR_NB_SC_PER_RB * Qm * rel15->nrOfLayers] __attribute__((aligned(64)));
bzero(output,rel15->rbSize * NR_SYMBOLS_PER_SLOT * NR_NB_SC_PER_RB * Qm * rel15->nrOfLayers);
start_meas(dlsch_encoding_stats);
if (nr_dlsch_encoding(gNB,
frame,
slot,
harq,
frame_parms,
output,
tinput,
tprep,
tparity,
toutput,
dlsch_rate_matching_stats,
dlsch_interleaving_stats,
dlsch_segmentation_stats) == -1)
return;
stop_meas(dlsch_encoding_stats);
#ifdef DEBUG_DLSCH
printf("PDSCH encoding:\nPayload:\n");
for (int i=0; i<harq->B>>7; i++) {
for (int j=0; j<16; j++)
printf("0x%02x\t", harq->pdu[(i<<4)+j]);
for (int i = 0; i < (harq->B>>3); i += 16) {
for (int j=0; j < 16; j++)
printf("0x%02x\t", harq->pdu[i + j]);
printf("\n");
}
printf("\nEncoded payload:\n");
for (int i=0; i<encoded_length>>3; i++) {
for (int j=0; j<8; j++)
printf("%d", output[(i<<3)+j]);
for (int i = 0; i < encoded_length; i += 8) {
for (int j = 0; j < 8; j++)
printf("%d", output[offset_output + i + j]);
printf("\t");
}
printf("\n");
#endif
if (IS_SOFTMODEM_DLSIM)
memcpy(harq->f, output, encoded_length);
memcpy(harq->f, &output[offset_output], encoded_length);
c16_t mod_symbs[rel15->NrOfCodewords][encoded_length];
for (int codeWord = 0; codeWord < rel15->NrOfCodewords; codeWord++) {
......@@ -147,7 +187,7 @@ void nr_generate_pdsch(processingData_L1tx_t *msgTx, int frame, int slot)
uint32_t scrambled_output[(encoded_length>>5)+4]; // modulator acces by 4 bytes in some cases
memset(scrambled_output, 0, sizeof(scrambled_output));
if ( encoded_length > rel15->rbSize * NR_SYMBOLS_PER_SLOT * NR_NB_SC_PER_RB * Qm * rel15->nrOfLayers) abort();
nr_pdsch_codeword_scrambling(output, encoded_length, codeWord, rel15->dataScramblingId, rel15->rnti, scrambled_output);
nr_pdsch_codeword_scrambling(&output[offset_output], encoded_length, codeWord, rel15->dataScramblingId, rel15->rnti, scrambled_output);
#ifdef DEBUG_DLSCH
printf("PDSCH scrambling:\n");
......@@ -176,6 +216,12 @@ void nr_generate_pdsch(processingData_L1tx_t *msgTx, int frame, int slot)
}
/// Resource mapping
/* output and its parts for each dlsch should be aligned on 64 bytes
* => offset_output should remain a multiple of 64 with enough offset to fit each dlsch
*/
uint32_t size_output_tb = rel15->rbSize * NR_SYMBOLS_PER_SLOT * NR_NB_SC_PER_RB * Qm * rel15->nrOfLayers;
offset_output += (size_output_tb + 63) & ~63;
// Non interleaved VRB to PRB mapping
uint16_t start_sc = frame_parms->first_carrier_offset + (rel15->rbStart+rel15->BWPStart)*NR_NB_SC_PER_RB;
if (start_sc >= frame_parms->ofdm_symbol_size)
......
......@@ -44,18 +44,18 @@ void nr_generate_pdsch(processingData_L1tx_t *msgTx,
int slot);
int nr_dlsch_encoding(PHY_VARS_gNB *gNB,
int frame,
uint8_t slot,
NR_DL_gNB_HARQ_t *harq,
NR_DL_FRAME_PARMS* frame_parms,
unsigned char * output,
time_stats_t *tinput,
time_stats_t *tprep,
time_stats_t *tparity,
time_stats_t *toutput,
time_stats_t *dlsch_rate_matching_stats,
time_stats_t *dlsch_interleaving_stats,
time_stats_t *dlsch_segmentation_stats);
processingData_L1tx_t *msgTx,
int frame,
uint8_t slot,
NR_DL_FRAME_PARMS *frame_parms,
unsigned char *output,
time_stats_t *tinput,
time_stats_t *tprep,
time_stats_t *tparity,
time_stats_t *toutput,
time_stats_t *dlsch_rate_matching_stats,
time_stats_t *dlsch_interleaving_stats,
time_stats_t *dlsch_segmentation_stats);
void nr_emulate_dlsch_payload(uint8_t* payload, uint16_t size);
......
This diff is collapsed.
......@@ -42,28 +42,23 @@ void free_gNB_ulsch(NR_gNB_ULSCH_t *ulsch, uint16_t N_RB_UL);
NR_gNB_ULSCH_t new_gNB_ulsch(uint8_t max_ldpc_iterations, uint16_t N_RB_UL);
/*! \brief Perform PUSCH decoding. TS 38.212 V15.4.0 subclause 6.2
/*! \brief Perform PUSCH decoding for the whole current received TTI. TS 38.212 V15.4.0 subclause 6.2
@param phy_vars_gNB, Pointer to PHY data structure for gNB
@param UE_id, ID of UE transmitting this PUSCH
@param ulsch_llr, Pointer to received llr in ulsch
@param frame_parms, Pointer to frame descriptor structure
@param nb_symb_sch, number of symbols used in the uplink shared channel
@param nb_re_dmrs, number of DMRS resource elements in one RB
@param frame, current received frame
@param nr_tti_rx, current received TTI
@param harq_pid, harq process id
@param is_crnti
@param G
@param ULSCH_ids, array of ULSCH ids
@param nb_pusch, number of uplink shared channels
*/
int nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB,
uint8_t UE_id,
short *ulsch_llr,
NR_DL_FRAME_PARMS *frame_parms,
nfapi_nr_pusch_pdu_t *pusch_pdu,
uint32_t frame,
uint8_t nr_tti_rx,
uint8_t harq_pid,
uint32_t G,
thread_info_tm_t *t_info);
uint32_t *G,
uint8_t *ULSCH_ids,
int nb_pusch);
/*! \brief Perform PUSCH unscrambling. TS 38.211 V15.4.0 subclause 6.3.1.1
@param llr, Pointer to llr bits
......
......@@ -65,50 +65,51 @@ void nr_conjch0_mult_ch1(int *ch0,
unsigned short nb_rb,
unsigned char output_shift0);
/** \brief This is the top-level entry point for DLSCH decoding in UE. It should be replicated on several
threads (on multi-core machines) corresponding to different HARQ processes. The routine first
computes the segmentation information, followed by rate dematching and sub-block deinterleaving the of the
received LLRs computed by dlsch_demodulation for each transport block segment. It then calls the
turbo-decoding algorithm for each segment and stops after either after unsuccesful decoding of at least
one segment or correct decoding of all segments. Only the segment CRCs are check for the moment, the
overall CRC is ignored. Finally transport block reassembly is performed.
@param phy_vars_ue Pointer to ue variables
@param proc
@param eNB_id
@param dlsch_llr Pointer to LLR values computed by dlsch_demodulation
@param frame_parms Pointer to frame descriptor
@param dlsch Pointer to DLSCH descriptor
@param harq_process
@param frame Frame number
@param nb_symb_sch
@param nr_slot_rx Slot number
@param harq_pid
@param b_size
@param b
/** \brief This is the alternative top-level entry point for DLSCH decoding in UE.
It handles all the HARQ processes in only one call. The routine first
computes the segmentation information and then call LDPC decoder on the
received LLRs computed by dlsch_demodulation.
It stops after either unsuccesful decoding of at least
one segment or correct decoding of all segments. Only the segment CRCs are checked for the moment, the
overall CRC is ignored. Finally transport block reassembly is performed.
@param[in] phy_vars_ue Pointer to ue variables
@param[in] proc
@param[in] dlsch_llr Pointers to LLR values computed by dlsch_demodulation
@param[in] b
@param[in] G array of Gs
@param[in] nb_dlsch number of active downlink shared channels
@param[in] DLSCH_ids array of active downlink shared channels
@returns 0 on success, 1 on unsuccessful decoding
*/
uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue,
const UE_nr_rxtx_proc_t *proc,
int eNB_id,
short *dlsch_llr,
NR_DL_FRAME_PARMS *frame_parms,
NR_UE_DLSCH_t *dlsch,
NR_DL_UE_HARQ_t *harq_process,
uint32_t frame,
uint16_t nb_symb_sch,
uint8_t nr_slot_rx,
uint8_t harq_pid,
int b_size,
uint8_t b[b_size],
int G);
short **dlsch_llr,
uint8_t **b,
int *G,
int nb_dlsch,
uint8_t *DLSCH_ids);
/** \brief This is the alternative top-level entry point for ULSCH encoding in UE.
It handles all the HARQ processes in only one call. The routine first
computes the segmentation information, followed by LDPC encoding algorithm of the
Transport Block.
@param[in] phy_vars_ue pointer to ue variables
@param[in] ulsch Pointer to ULSCH descriptor
@param[in] frame frame index
@param[in] slot slot index
@param[in] G array of Gs
@param[in] nb_ulsch number of uplink shared channels
@param[in] ULSCH_ids array of uplink shared channel ids
@returns 0 on success, -1 on unsuccessful decoding
*/
int nr_ulsch_encoding(PHY_VARS_NR_UE *ue,
NR_UE_ULSCH_t *ulsch,
NR_DL_FRAME_PARMS* frame_parms,
uint8_t harq_pid,
uint32_t tb_size,
unsigned int G);
NR_UE_ULSCH_t *ulsch,
const uint32_t frame,
const uint8_t slot,
unsigned int *G,
int nb_ulsch,
uint8_t *ULSCH_ids);
/*! \brief Perform PUSCH scrambling. TS 38.211 V15.4.0 subclause 6.3.1.1
@param[in] in Pointer to input bits
......@@ -125,18 +126,23 @@ void nr_pusch_codeword_scrambling(uint8_t *in,
bool uci_on_pusch,
uint32_t* out);
/** \brief Perform the following functionalities:
/** \brief Alternative entry point to UE uplink shared channels procedures.
It handles all the HARQ processes in only one call.
Performs the following functionalities:
- encoding
- scrambling
- modulation
- transform precoding
@param[in] UE pointer to ue variables
@param[in] frame frame index
@param[in] slot slot index
@param[in] phy_data PHY layer informations
@param[in] c16_t
*/
void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE,
const unsigned char harq_pid,
const uint32_t frame,
const uint8_t slot,
const int gNB_id,
nr_phy_data_tx_t *phy_data,
c16_t **txdataF);
......
......@@ -104,6 +104,8 @@ typedef struct {
uint8_t first_rx;
/// DLSCH status flag indicating
SCH_status_t status;
/// Pointer to the payload (38.212 V15.4.0 section 5.1)
uint8_t *b;
/// Pointers to transport block segments
uint8_t **c;
/// soft bits for each received segment ("d"-sequence)(for definition see 36-212 V8.6 2009-03, p.15)
......@@ -126,6 +128,8 @@ typedef struct {
/// Last index of LLR buffer that contains information.
/// Used for computing LDPC decoder R
int llrLen;
/// Number of segments processed so far
uint32_t processedSegments;
decode_abort_t abort_decode;
} NR_DL_UE_HARQ_t;
......
This diff is collapsed.
......@@ -40,6 +40,7 @@
#include "PHY/NR_TRANSPORT/nr_transport_common_proto.h"
#include "PHY/impl_defs_top.h"
#include "PHY/defs_common.h"
#include "PHY/CODING/nrLDPC_coding/nrLDPC_coding_interface.h"
#include "PHY/CODING/nrLDPC_extern.h"
#include "PHY/CODING/nrLDPC_decoder/nrLDPC_types.h"
#include "executables/rt_profiling.h"
......@@ -494,9 +495,10 @@ typedef struct PHY_VARS_gNB_s {
/// OFDM symbol offset divisor for UL
uint32_t ofdm_offset_divisor;
int ldpc_offload_flag;
/// NR LDPC coding related
nrLDPC_coding_interface_t nrLDPC_coding_interface;
int max_ldpc_iterations;
/// indicate the channel estimation technique in time domain
int chest_time;
/// indicate the channel estimation technique in freq domain
......
......@@ -98,6 +98,7 @@
#include "impl_defs_nr.h"
#include "time_meas.h"
#include "PHY/CODING/coding_defs.h"
#include "PHY/CODING/nrLDPC_coding/nrLDPC_coding_interface.h"
#include "PHY/TOOLS/tools_defs.h"
#include "common/platform_types.h"
#include "NR_UE_TRANSPORT/nr_transport_ue.h"
......@@ -494,9 +495,10 @@ typedef struct PHY_VARS_NR_UE_s {
/// N0 (used for abstraction)
double N0;
/// NR LDPC coding related
nrLDPC_coding_interface_t nrLDPC_coding_interface;
uint8_t max_ldpc_iterations;
int ldpc_offload_enable;
/// SRS variables
nr_srs_info_t *nr_srs_info;
......
This diff is collapsed.
This diff is collapsed.
......@@ -35,6 +35,7 @@
#include "PHY/defs_nr_common.h"
#include "PHY/defs_nr_UE.h"
#include "PHY/types.h"
#include "PHY/CODING/nrLDPC_coding/nrLDPC_coding_interface.h"
#include "PHY/INIT/nr_phy_init.h"
#include "PHY/MODULATION/modulation_eNB.h"
#include "PHY/MODULATION/modulation_UE.h"
......@@ -380,7 +381,7 @@ int main(int argc, char **argv)
RC.gNB[0] = calloc(1, sizeof(PHY_VARS_gNB));
gNB = RC.gNB[0];
initNamedTpool(gNBthreads, &gNB->threadPool, true, "gNB-tpool");
initFloatingCoresTpool(dlsch_threads, &nrUE_params.Tpool, false, "UE-tpool");
initFloatingCoresTpool(dlsch_threads, &nrUE_params.Tpool, false, "UE-tpool");
//gNB_config = &gNB->gNB_config;
frame_parms = &gNB->frame_parms; //to be initialized I suppose (maybe not necessary for PBCH)
frame_parms->nb_antennas_tx = n_tx;
......@@ -430,6 +431,8 @@ int main(int argc, char **argv)
//nr_init_frame_parms_ue(&UE->frame_parms);
//init_nr_ue_transport(UE, 0);
UE->nrLDPC_coding_interface = gNB->nrLDPC_coding_interface;
NR_UE_DLSCH_t dlsch_ue[NR_MAX_NB_LAYERS > 4? 2:1] = {0};
int num_codeword = NR_MAX_NB_LAYERS > 4? 2:1;
nr_ue_dlsch_init(dlsch_ue, num_codeword, 5);
......@@ -513,7 +516,8 @@ int main(int argc, char **argv)
unsigned char output[rel15->rbSize * NR_SYMBOLS_PER_SLOT * NR_NB_SC_PER_RB * 8 * NR_MAX_NB_LAYERS] __attribute__((aligned(32)));
bzero(output,rel15->rbSize * NR_SYMBOLS_PER_SLOT * NR_NB_SC_PER_RB * 8 * NR_MAX_NB_LAYERS);
if (input_fd == NULL) {
nr_dlsch_encoding(gNB, frame, slot, &dlsch->harq_process, frame_parms,output,NULL,NULL,NULL,NULL,NULL,NULL,NULL);
msgDataTx.num_pdsch_slot = 1;
nr_dlsch_encoding(gNB, &msgDataTx, frame, slot, frame_parms, output, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
}
for (SNR = snr0; SNR < snr1; SNR += snr_step) {
......@@ -569,20 +573,18 @@ int main(int argc, char **argv)
}
uint32_t dlsch_bytes = a_segments*1056; // allocated bytes per segment
__attribute__ ((aligned(32))) uint8_t b[dlsch_bytes];
uint8_t DLSCH_ids[1] = {0};
short *p_channel_output_fixed = channel_output_fixed;
uint8_t *p_b = b;
int available_bits_array[1] = { available_bits };
ret = nr_dlsch_decoding(UE,
&proc,
0,
channel_output_fixed,
&UE->frame_parms,
dlsch0_ue,
harq_process,
frame,
nb_symb_sch,
slot,
harq_pid,
dlsch_bytes,
b,
available_bits);
&p_channel_output_fixed,
&p_b,
available_bits_array,
1,
DLSCH_ids);
vcd_signal_dumper_dump_function_by_name(VCD_SIGNAL_DUMPER_FUNCTIONS_DLSCH_DECODING0, VCD_FUNCTION_OUT);
......@@ -661,7 +663,10 @@ int main(int argc, char **argv)
free(gNB->gNB_config.tdd_table.max_tdd_periodicity_list[i].max_num_of_symbol_per_slot_list);
free(gNB->gNB_config.tdd_table.max_tdd_periodicity_list);
free_nrLDPC_coding_interface(&gNB->nrLDPC_coding_interface);
abortTpool(&gNB->threadPool);
phy_free_nr_gNB(gNB);
free(RC.gNB[0]);
free(RC.gNB);
......
......@@ -47,7 +47,7 @@
#include "NR_ServingCellConfig.h"
#include "NR_SetupRelease.h"
#include "NR_UE_PHY_INTERFACE/NR_IF_Module.h"
#include "PHY/CODING/nrLDPC_extern.h"
#include "PHY/CODING/nrLDPC_coding/nrLDPC_coding_interface.h"
#include "PHY/INIT/nr_phy_init.h"
#include "PHY/MODULATION/modulation_common.h"
#include "PHY/NR_REFSIG/ptrs_nr.h"
......@@ -297,7 +297,6 @@ int main(int argc, char **argv)
uint8_t n_tx=1,n_rx=1;
uint8_t round;
uint8_t num_rounds = 4;
int ldpc_offload_flag = 0;
char gNBthreads[128]="n";
channel_desc_t *gNB2UE;
......@@ -360,7 +359,7 @@ int main(int argc, char **argv)
FILE *scg_fd=NULL;
while ((c = getopt(argc, argv, "--:O:f:hA:p:f:g:i:n:s:S:t:v:x:y:z:o:M:N:F:GR:d:PI:L:a:b:e:m:w:T:U:q:X:Y:Z:c")) != -1) {
while ((c = getopt(argc, argv, "--:O:f:hA:p:f:g:i:n:s:S:t:v:x:y:z:o:M:N:F:GR:d:PI:L:a:b:e:m:w:T:U:q:X:Y:Z:")) != -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' */
......@@ -412,10 +411,6 @@ int main(int argc, char **argv)
n_trials = atoi(optarg);
break;
case 'c':
ldpc_offload_flag = 1;
break;
case 's':
snr0 = atof(optarg);
printf("Setting SNR0 to %f\n",snr0);
......@@ -580,7 +575,6 @@ int main(int argc, char **argv)
//printf("-j Relative strength of second intefering gNB (in dB) - cell_id mod 3 = 2\n");
printf("-R N_RB_DL\n");
printf("-O oversampling factor (1,2,4,8,16)\n");
printf("-c ldpc offload flag\n");
printf("-A Interpolation_filname Run with Abstraction to generate Scatter plot using interpolation polynomial in file\n");
//printf("-C Generate Calibration information for Abstraction (effective SNR adjustment to remove Pe bias w.r.t. AWGN)\n");
printf("-f raw file containing RRC configuration (generated by gNB)\n");
......@@ -640,7 +634,6 @@ int main(int argc, char **argv)
gNB = RC.gNB[0];
gNB->ofdm_offset_divisor = UINT_MAX;
gNB->ldpc_offload_flag = ldpc_offload_flag;
gNB->phase_comp = true; // we need to perform phase compensation, otherwise everything will fail
frame_parms = &gNB->frame_parms; //to be initialized I suppose (maybe not necessary for PBCH)
frame_parms->nb_antennas_tx = n_tx;
......@@ -849,6 +842,7 @@ int main(int argc, char **argv)
memcpy(&UE->frame_parms,frame_parms,sizeof(NR_DL_FRAME_PARMS));
UE->frame_parms.nb_antennas_rx = n_rx;
UE->frame_parms.nb_antenna_ports_gNB = n_tx;
UE->nrLDPC_coding_interface = gNB->nrLDPC_coding_interface;
UE->max_ldpc_iterations = max_ldpc_iterations;
init_nr_ue_phy_cpu_stats(&UE->phy_cpu_stats);
......@@ -1337,8 +1331,7 @@ int main(int argc, char **argv)
free(UE->phy_sim_pdsch_dl_ch_estimates_ext);
free(UE->phy_sim_dlsch_b);
if (gNB->ldpc_offload_flag)
free_LDPClib(&ldpc_interface_offload);
free_nrLDPC_coding_interface(&gNB->nrLDPC_coding_interface);
if (output_fd)
fclose(output_fd);
......
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment