diff --git a/.clang-format b/.clang-format index aa8f087091..a7248821a9 100644 --- a/.clang-format +++ b/.clang-format @@ -61,6 +61,7 @@ ForEachMacros: - Q_FOREACH - BOOST_FOREACH - RB_FOREACH + - UE_iterator IncludeBlocks: Preserve IncludeCategories: - Regex: '^' diff --git a/CMakeLists.txt b/CMakeLists.txt index cc4b8d87f9..4aefd12b54 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -494,20 +494,21 @@ target_link_libraries(shlib_loader PRIVATE CONFIG_LIB) ########################################################## -# LDPC offload library +# LDPC offload library - AMD T2 Accelerator Card ########################################################## -add_boolean_option(ENABLE_LDPC_T1 OFF "Build support for LDPC Offload to T1 library" OFF) -if (ENABLE_LDPC_T1) - pkg_check_modules(LIBDPDK_T1 REQUIRED libdpdk=20.05.0) - find_library(T1 NAMES rte_pmd_hpac_sdfec_pmd REQUIRED) - if (NOT T1) - message(FATAL_ERROR "Library rte_pmd_hpac_sdfec_pmd for T1 offload not found") +add_boolean_option(ENABLE_LDPC_T2 OFF "Build support for LDPC Offload to T2 library" OFF) +set(ENV{PKG_CONFIG_PATH} "$ENV{PKG_CONFIG_PATH}:/usr/local/lib/x86_64-linux-gnu/pkgconfig") +if (ENABLE_LDPC_T2) + pkg_check_modules(LIBDPDK_T2 REQUIRED libdpdk=20.11.7) + find_library(PMD_T2 NAMES rte_baseband_accl_ldpc HINTS "/opt/dpdk-t2/lib/x86_64-linux-gnu/") + if (NOT PMD_T2) + message(FATAL_ERROR "could not find PMD T2") endif() - add_library(ldpc_t1 MODULE ${OPENAIR1_DIR}/PHY/CODING/nrLDPC_decoder/nrLDPC_decoder_offload.c) - set_target_properties(ldpc_t1 PROPERTIES COMPILE_FLAGS "-DALLOW_EXPERIMENTAL_API") - target_compile_options(ldpc_t1 PRIVATE ${LIBDPDK_T1_CFLAGS}) - target_link_libraries(ldpc_t1 ${LIBDPDK_T1_LDFLAGS} ${T1}) + 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() ########################################################## @@ -819,19 +820,30 @@ 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 @@ -845,21 +857,13 @@ 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 ) - -set(PHY_NR_CODINGIF - ${OPENAIR1_DIR}/PHY/CODING/nrLDPC_load.c; -) - -add_library(ldpc_orig MODULE ${PHY_LDPC_ORIG_SRC} ) -target_link_libraries(ldpc_orig PRIVATE ldpc_gen_HEADERS) -add_library(ldpc_optim MODULE ${PHY_LDPC_OPTIM_SRC} ) -target_link_libraries(ldpc_optim PRIVATE ldpc_gen_HEADERS) -add_library(ldpc_optim8seg MODULE ${PHY_LDPC_OPTIM8SEG_SRC} ) -target_link_libraries(ldpc_optim8seg PRIVATE ldpc_gen_HEADERS) 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 @@ -877,13 +881,6 @@ if (ENABLE_LDPC_CUDA) endif() endif() -add_library(ldpc MODULE ${PHY_LDPC_OPTIM8SEGMULTI_SRC} ) -target_link_libraries(ldpc PRIVATE ldpc_gen_HEADERS) - -add_library(ldpc_parityCheck MODULE ${PHY_LDPC_OPTIM8SEGMULTI_SRC} ) -target_compile_definitions(ldpc_parityCheck PUBLIC NR_LDPC_ENABLE_PARITY_CHECK) -target_link_libraries(ldpc_parityCheck PRIVATE ldpc_gen_HEADERS) - add_library(coding MODULE ${PHY_TURBOSRC} ) add_library(dfts MODULE ${OPENAIR1_DIR}/PHY/TOOLS/oai_dfts.c ${OPENAIR1_DIR}/PHY/TOOLS/oai_dfts_neon.c) @@ -2090,8 +2087,8 @@ endif() add_dependencies(nr-softmodem ldpc_orig ldpc_optim ldpc_optim8seg ldpc) -if (ENABLE_LDPC_T1) - add_dependencies(nr-softmodem ldpc_t1) +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 @@ -2212,12 +2209,12 @@ add_executable(ldpctest ${OPENAIR1_DIR}/PHY/CODING/TESTBENCH/ldpctest.c ) -add_dependencies( ldpctest ldpc_orig ldpc_optim ldpc_optim8seg ldpc ldpc_parityCheck) +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_NR PHY_COMMON PHY_NR_COMMON -Wl,--end-group + -Wl,--start-group UTIL SIMU PHY_COMMON PHY_NR_COMMON -Wl,--end-group m pthread dl shlib_loader ${T_LIB} ) @@ -2307,8 +2304,8 @@ add_executable(nr_ulsim ${PHY_INTERFACE_DIR}/queue_t.c ) -if (ENABLE_LDPC_T1) - add_dependencies(nr_ulsim ldpc_t1) +if (ENABLE_LDPC_T2) + add_dependencies(nr_ulsim ldpc_t2) endif() target_link_libraries(nr_ulsim PRIVATE @@ -2376,7 +2373,7 @@ if (${T_TRACER}) 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 SIMU_ETH OPENAIR0_LIB - ldpc_orig ldpc_optim ldpc_optim8seg ldpc dfts config_internals) + ldpc_orig ldpc_optim ldpc_optim8seg ldpc_t2 ldpc_cl ldpc_cuda ldpc dfts config_internals) if (TARGET ${i}) add_dependencies(${i} generate_T) endif() diff --git a/ci-scripts/cls_containerize.py b/ci-scripts/cls_containerize.py index 7957bdf066..79bc4fa46e 100644 --- a/ci-scripts/cls_containerize.py +++ b/ci-scripts/cls_containerize.py @@ -58,7 +58,7 @@ import cls_oaicitest # Helper functions used here and in other classes # (e.g., cls_cluster.py) #----------------------------------------------------------- -IMAGES = ['oai-enb', 'oai-lte-ru', 'oai-lte-ue', 'oai-gnb', 'oai-nr-cuup', 'oai-gnb-aw2s', 'oai-nr-ue'] +IMAGES = ['oai-enb', 'oai-lte-ru', 'oai-lte-ue', 'oai-gnb', 'oai-nr-cuup', 'oai-gnb-aw2s', 'oai-nr-ue', 'oai-gnb-asan', 'oai-nr-ue-asan', 'oai-nr-cuup-asan'] def CreateWorkspace(sshSession, sourcePath, ranRepository, ranCommitID, ranTargetBranch, ranAllowMerge): if ranCommitID == '': @@ -364,25 +364,30 @@ class Containerize(): self.cliBuildOptions = '--no-cache --disable-compression' # we always build the ran-build image with all targets - imageNames = [('ran-build', 'build')] + # Creating a tupple with the imageName, the DockerFile prefix pattern, targetName and sanitized option + imageNames = [('ran-build', 'build', 'ran-build', '')] result = re.search('eNB', self.imageKind) - # Creating a tupple with the imageName and the DockerFile prefix pattern on obelix if result is not None: - imageNames.append(('oai-enb', 'eNB')) + imageNames.append(('oai-enb', 'eNB', 'oai-enb', '')) result = re.search('gNB', self.imageKind) if result is not None: - imageNames.append(('oai-gnb', 'gNB')) + imageNames.append(('oai-gnb', 'gNB', 'oai-gnb', '')) result = re.search('all', self.imageKind) if result is not None: - imageNames.append(('oai-enb', 'eNB')) - imageNames.append(('oai-gnb', 'gNB')) - imageNames.append(('oai-nr-cuup', 'nr-cuup')) - imageNames.append(('oai-lte-ue', 'lteUE')) - imageNames.append(('oai-nr-ue', 'nrUE')) + imageNames.append(('oai-enb', 'eNB', 'oai-enb', '')) + imageNames.append(('oai-gnb', 'gNB', 'oai-gnb', '')) + imageNames.append(('oai-nr-cuup', 'nr-cuup', 'oai-nr-cuup', '')) + imageNames.append(('oai-lte-ue', 'lteUE', 'oai-lte-ue', '')) + imageNames.append(('oai-nr-ue', 'nrUE', 'oai-nr-ue', '')) if self.host == 'Red Hat': - imageNames.append(('oai-physim', 'phySim')) + imageNames.append(('oai-physim', 'phySim', 'oai-physim', '')) if self.host == 'Ubuntu': - imageNames.append(('oai-lte-ru', 'lteRU')) + imageNames.append(('oai-lte-ru', 'lteRU', 'oai-lte-ru', '')) + # Building again the 5G images with Address Sanitizer + imageNames.append(('ran-build', 'build', 'ran-build-asan', '--build-arg "BUILD_OPTION=--sanitize"')) + imageNames.append(('oai-gnb', 'gNB', 'oai-gnb-asan', '--build-arg "BUILD_OPTION=--sanitize"')) + imageNames.append(('oai-nr-ue', 'nrUE', 'oai-nr-ue-asan', '--build-arg "BUILD_OPTION=--sanitize"')) + imageNames.append(('oai-nr-cuup', 'nr-cuup', 'oai-nr-cuup-asan', '--build-arg "BUILD_OPTION=--sanitize"')) result = re.search('build_cross_arm64', self.imageKind) if result is not None: self.dockerfileprefix = '.ubuntu20.cross-arm64' @@ -421,8 +426,8 @@ class Containerize(): cmd.run(f"{self.cli} image prune --force") if forceBaseImageBuild: cmd.run(f"{self.cli} image rm {baseImage}:{baseTag}") - for image,pattern in imageNames: - cmd.run(f"{self.cli} image rm {image}:{imageTag}") + for image,pattern,name,option in imageNames: + cmd.run(f"{self.cli} image rm {name}:{imageTag}") # Build the base image only on Push Events (not on Merge Requests) # On when the base image docker file is being modified. @@ -460,46 +465,50 @@ class Containerize(): # Build the target image(s) status = True attemptedImages = ['ran-base'] - for image,pattern in imageNames: - attemptedImages += [image] + for image,pattern,name,option in imageNames: + attemptedImages += [name] # the archived Dockerfiles have "ran-base:latest" as base image # we need to update them with proper tag + cmd.run(f'git checkout -- docker/Dockerfile.{pattern}{self.dockerfileprefix}') cmd.run(f'sed -i -e "s#{baseImage}:latest#{baseImage}:{baseTag}#" docker/Dockerfile.{pattern}{self.dockerfileprefix}') - if image != 'ran-build': + # target images should use the proper ran-build image + if image != 'ran-build' and "-asan" in name: + cmd.run(f'sed -i -e "s#ran-build:latest#ran-build-asan:{imageTag}#" docker/Dockerfile.{pattern}{self.dockerfileprefix}') + elif image != 'ran-build': cmd.run(f'sed -i -e "s#ran-build:latest#ran-build:{imageTag}#" docker/Dockerfile.{pattern}{self.dockerfileprefix}') - ret = cmd.run(f'{self.cli} build {self.cliBuildOptions} --target {image} --tag {image}:{imageTag} --file docker/Dockerfile.{pattern}{self.dockerfileprefix} . > cmake_targets/log/{image}.log 2>&1', timeout=1200) + ret = cmd.run(f'{self.cli} build {self.cliBuildOptions} --target {image} --tag {name}:{imageTag} --file docker/Dockerfile.{pattern}{self.dockerfileprefix} {option} . > cmake_targets/log/{name}.log 2>&1', timeout=1200) if image == 'ran-build' and ret.returncode == 0: - cmd.run(f"docker run --name test-log -d {image}:{imageTag} /bin/true") - cmd.run(f"docker cp test-log:/oai-ran/cmake_targets/log/ cmake_targets/log/{image}/") + cmd.run(f"docker run --name test-log -d {name}:{imageTag} /bin/true") + cmd.run(f"docker cp test-log:/oai-ran/cmake_targets/log/ cmake_targets/log/{name}/") cmd.run(f"docker rm -f test-log") else: - cmd.run(f"mkdir -p cmake_targets/log/{image}") + cmd.run(f"mkdir -p cmake_targets/log/{name}") # check the status of the build - ret = cmd.run(f"{self.cli} image inspect --format=\'Size = {{{{.Size}}}} bytes\' {image}:{imageTag}") + ret = cmd.run(f"{self.cli} image inspect --format=\'Size = {{{{.Size}}}} bytes\' {name}:{imageTag}") if ret.returncode != 0: - logging.error('\u001B[1m Could not build properly ' + image + '\u001B[0m') + logging.error('\u001B[1m Could not build properly ' + name + '\u001B[0m') status = False # Here we should check if the last container corresponds to a failed command and destroy it cmd.run(f"{self.cli} ps --quiet --filter \"status=exited\" -n1 | xargs --no-run-if-empty {self.cli} rm -f") - allImagesSize[image] = 'N/A -- Build Failed' + allImagesSize[name] = 'N/A -- Build Failed' break else: result = re.search('Size *= *(?P[0-9\-]+) *bytes', cmd.getBefore()) if result is not None: size = float(result.group("size")) / 1000000 # convert to MB imageSizeStr = f'{size:.1f}' - logging.debug(f'\u001B[1m {image} size is {imageSizeStr} Mbytes\u001B[0m') - allImagesSize[image] = f'{imageSizeStr} Mbytes' + logging.debug(f'\u001B[1m {name} size is {imageSizeStr} Mbytes\u001B[0m') + allImagesSize[name] = f'{imageSizeStr} Mbytes' else: - logging.debug(f'{image} size is unknown') - allImagesSize[image] = 'unknown' + logging.debug(f'{name} size is unknown') + allImagesSize[name] = 'unknown' # Now pruning dangling images in between target builds cmd.run(f"{self.cli} image prune --force") # Remove all intermediate build images and clean up if self.ranAllowMerge and forceBaseImageBuild: cmd.run(f"{self.cli} image rm {baseImage}:{baseTag}") - cmd.run(f"{self.cli} image rm ran-build:{imageTag}") + cmd.run(f"{self.cli} image rm ran-build:{imageTag} ran-build-asan:{imageTag}") cmd.run(f"{self.cli} volume prune --force") # create a zip with all logs @@ -698,10 +707,11 @@ class Containerize(): orgTag = 'develop' if self.ranAllowMerge: orgTag = 'ci-temp' - imageNames = ['oai-enb', 'oai-gnb', 'oai-lte-ue', 'oai-nr-ue', 'oai-lte-ru', 'oai-nr-cuup'] - for image in imageNames: + for image in IMAGES: tagToUse = ImageTagToUse(image, self.ranCommitID, self.ranBranch, self.ranAllowMerge) mySSH.command(f'docker image tag {image}:{orgTag} {imagePrefix}/{tagToUse}', '\$', 5) + if re.search('Error response from daemon: No such image:', mySSH.getBefore()) is not None: + continue mySSH.command(f'docker push {imagePrefix}/{tagToUse}', '\$', 120) if re.search(': digest:', mySSH.getBefore()) is None: logging.debug(mySSH.getBefore()) @@ -1061,6 +1071,16 @@ class Containerize(): imageNames = ['oai-enb', 'oai-gnb', 'oai-lte-ue', 'oai-nr-ue', 'oai-lte-ru', 'oai-nr-cuup'] for image in imageNames: tagToUse = ImageTagToUse(image, self.ranCommitID, self.ranBranch, self.ranAllowMerge) + # In the scenario, for 5G images, we have the choice of either pulling normal images + # or -asan images. We need to detect which kind we did pull. + if image == 'oai-gnb' or image == 'oai-nr-ue' or image == 'oai-nr-cuup': + ret = myCmd.run(f'docker image inspect oai-ci/{tagToUse}', reportNonZero=False, silent=self.displayedNewTags) + if ret.returncode != 0: + tagToUse = tagToUse.replace('oai-gnb', 'oai-gnb-asan') + tagToUse = tagToUse.replace('oai-nr-ue', 'oai-nr-ue-asan') + tagToUse = tagToUse.replace('oai-nr-cuup', 'oai-nr-cuup-asan') + if not self.displayedNewTags: + logging.debug(f'\u001B[1m Using sanitized version of {image} with {tagToUse}\u001B[0m') cmd = f'sed -i -e "s@oaisoftwarealliance/{image}:develop@oai-ci/{tagToUse}@" docker-compose-ci.yml' myCmd.run(cmd, silent=self.displayedNewTags) self.displayedNewTags = True @@ -1199,12 +1219,7 @@ class Containerize(): logPath = '../cmake_targets/log/' + ymlPath[1] myCmd = cls_cmd.LocalCmd(d = self.yamlPath[0]) cmd = 'cp docker-compose.y*ml docker-compose-ci.yml' - myCmd.run(cmd, silent=self.displayedNewTags) - for image in IMAGES: - tagToUse = ImageTagToUse(image, self.ranCommitID, self.ranBranch, self.ranAllowMerge) - cmd = f'sed -i -e "s@oaisoftwarealliance/{image}:develop@oai-ci/{tagToUse}@" docker-compose-ci.yml' - myCmd.run(cmd, silent=self.displayedNewTags) - self.displayedNewTags = True + myCmd.run(cmd) # check which containers are running for log recovery later cmd = 'docker-compose -f docker-compose-ci.yml ps --all' diff --git a/ci-scripts/conf_files/gnb-cuup.sa.f1.conf b/ci-scripts/conf_files/gnb-cuup.sa.f1.conf index 357518bcf2..d6c54f0b9a 100644 --- a/ci-scripts/conf_files/gnb-cuup.sa.f1.conf +++ b/ci-scripts/conf_files/gnb-cuup.sa.f1.conf @@ -8,6 +8,7 @@ gNBs = { ////////// Identification parameters: gNB_ID = 0xe00; + gNB_CU_UP_ID = 0xe00; # cell_type = "CELL_MACRO_GNB"; diff --git a/ci-scripts/conf_files/gnb-cuup.sa.f1.quectel.conf b/ci-scripts/conf_files/gnb-cuup.sa.f1.quectel.conf index 4e65547db9..7a2fc7db21 100644 --- a/ci-scripts/conf_files/gnb-cuup.sa.f1.quectel.conf +++ b/ci-scripts/conf_files/gnb-cuup.sa.f1.quectel.conf @@ -8,6 +8,7 @@ gNBs = { ////////// Identification parameters: gNB_ID = 0xe00; + gNB_CU_UP_ID = 0xe00; # cell_type = "CELL_MACRO_GNB"; diff --git a/ci-scripts/conf_files/gnb-du.band78.106prb.rfsim.conf b/ci-scripts/conf_files/gnb-du.band78.106prb.rfsim.conf index 94474b86bf..919c1d219f 100644 --- a/ci-scripts/conf_files/gnb-du.band78.106prb.rfsim.conf +++ b/ci-scripts/conf_files/gnb-du.band78.106prb.rfsim.conf @@ -7,6 +7,7 @@ gNBs = { ////////// Identification parameters: gNB_ID = 0xe00; + gNB_DU_ID = 0xe00; # cell_type = "CELL_MACRO_GNB"; diff --git a/ci-scripts/conf_files/gnb-du.sa.band78.106prb.rfsim.conf b/ci-scripts/conf_files/gnb-du.sa.band78.106prb.rfsim.conf index 105530c0ba..75d2beed6d 100644 --- a/ci-scripts/conf_files/gnb-du.sa.band78.106prb.rfsim.conf +++ b/ci-scripts/conf_files/gnb-du.sa.band78.106prb.rfsim.conf @@ -7,6 +7,7 @@ gNBs = { ////////// Identification parameters: gNB_ID = 0xe00; + gNB_DU_ID = 0xe00; # cell_type = "CELL_MACRO_GNB"; diff --git a/ci-scripts/conf_files/gnb-du.sa.band78.106prb.usrpb200.conf b/ci-scripts/conf_files/gnb-du.sa.band78.106prb.usrpb200.conf index f7891902db..f773b2dd33 100644 --- a/ci-scripts/conf_files/gnb-du.sa.band78.106prb.usrpb200.conf +++ b/ci-scripts/conf_files/gnb-du.sa.band78.106prb.usrpb200.conf @@ -7,6 +7,7 @@ gNBs = { ////////// Identification parameters: gNB_ID = 0xe00; + gNB_DU_ID = 0xe00; # cell_type = "CELL_MACRO_GNB"; diff --git a/ci-scripts/xml_files/container_5g_e1_rfsim.xml b/ci-scripts/xml_files/container_5g_e1_rfsim.xml index e37ba4cf96..b89b8a2bd2 100644 --- a/ci-scripts/xml_files/container_5g_e1_rfsim.xml +++ b/ci-scripts/xml_files/container_5g_e1_rfsim.xml @@ -43,7 +43,7 @@ Pull_Local_Registry Pull Images from Local Registry 0 - oai-gnb oai-nr-cuup oai-nr-ue + oai-gnb-asan oai-nr-cuup-asan oai-nr-ue-asan diff --git a/ci-scripts/xml_files/container_5g_f1_rfsim.xml b/ci-scripts/xml_files/container_5g_f1_rfsim.xml index 0f4e0e5487..6f8f71095c 100644 --- a/ci-scripts/xml_files/container_5g_f1_rfsim.xml +++ b/ci-scripts/xml_files/container_5g_f1_rfsim.xml @@ -42,7 +42,7 @@ Pull_Local_Registry Pull Images from Local Registry 0 - oai-gnb oai-nr-ue + oai-gnb-asan oai-nr-ue-asan diff --git a/ci-scripts/xml_files/container_5g_fdd_rfsim.xml b/ci-scripts/xml_files/container_5g_fdd_rfsim.xml index e2d1e3c287..34f5ceec6e 100644 --- a/ci-scripts/xml_files/container_5g_fdd_rfsim.xml +++ b/ci-scripts/xml_files/container_5g_fdd_rfsim.xml @@ -44,7 +44,7 @@ Pull_Local_Registry Pull Images from Local Registry 0 - oai-gnb oai-nr-ue + oai-gnb-asan oai-nr-ue-asan diff --git a/ci-scripts/xml_files/container_5g_l2sim_tdd.xml b/ci-scripts/xml_files/container_5g_l2sim_tdd.xml index 53a941a518..50ad28e5ca 100644 --- a/ci-scripts/xml_files/container_5g_l2sim_tdd.xml +++ b/ci-scripts/xml_files/container_5g_l2sim_tdd.xml @@ -45,7 +45,7 @@ Pull_Local_Registry Pull Images from Local Registry 0 - oai-gnb oai-nr-ue + oai-gnb-asan oai-nr-ue-asan diff --git a/ci-scripts/xml_files/container_5g_rfsim.xml b/ci-scripts/xml_files/container_5g_rfsim.xml index 7c755ab184..1c67266f0c 100644 --- a/ci-scripts/xml_files/container_5g_rfsim.xml +++ b/ci-scripts/xml_files/container_5g_rfsim.xml @@ -58,7 +58,7 @@ Pull_Local_Registry Pull Images from Local Registry 0 - oai-gnb oai-nr-ue + oai-gnb-asan oai-nr-ue-asan diff --git a/ci-scripts/xml_files/container_5g_rfsim_24prb.xml b/ci-scripts/xml_files/container_5g_rfsim_24prb.xml index f124176209..538122c751 100644 --- a/ci-scripts/xml_files/container_5g_rfsim_24prb.xml +++ b/ci-scripts/xml_files/container_5g_rfsim_24prb.xml @@ -44,7 +44,7 @@ Pull_Local_Registry Pull Images from Local Registry 0 - oai-gnb oai-nr-ue + oai-gnb-asan oai-nr-ue-asan diff --git a/ci-scripts/xml_files/container_5g_rfsim_2x2.xml b/ci-scripts/xml_files/container_5g_rfsim_2x2.xml index b178fe0df7..f6f84eaa50 100644 --- a/ci-scripts/xml_files/container_5g_rfsim_2x2.xml +++ b/ci-scripts/xml_files/container_5g_rfsim_2x2.xml @@ -44,7 +44,7 @@ Pull_Local_Registry Pull Images from Local Registry 0 - oai-gnb oai-nr-ue + oai-gnb-asan oai-nr-ue-asan diff --git a/ci-scripts/xml_files/container_5g_rfsim_fdd_phytest.xml b/ci-scripts/xml_files/container_5g_rfsim_fdd_phytest.xml index 37525357fa..7eba071e16 100644 --- a/ci-scripts/xml_files/container_5g_rfsim_fdd_phytest.xml +++ b/ci-scripts/xml_files/container_5g_rfsim_fdd_phytest.xml @@ -43,7 +43,7 @@ Pull_Local_Registry Pull Images from Local Registry 0 - oai-gnb oai-nr-ue + oai-gnb-asan oai-nr-ue-asan diff --git a/ci-scripts/xml_files/container_5g_rfsim_fr2_32prb.xml b/ci-scripts/xml_files/container_5g_rfsim_fr2_32prb.xml index 17c2c9f8b7..25ffb4b7b2 100644 --- a/ci-scripts/xml_files/container_5g_rfsim_fr2_32prb.xml +++ b/ci-scripts/xml_files/container_5g_rfsim_fr2_32prb.xml @@ -41,7 +41,7 @@ Pull_Local_Registry Pull Images from Local Registry 0 - oai-gnb oai-nr-ue + oai-gnb-asan oai-nr-ue-asan diff --git a/ci-scripts/xml_files/container_5g_rfsim_tdd_dora.xml b/ci-scripts/xml_files/container_5g_rfsim_tdd_dora.xml index c520a82046..9f0c3bc93a 100644 --- a/ci-scripts/xml_files/container_5g_rfsim_tdd_dora.xml +++ b/ci-scripts/xml_files/container_5g_rfsim_tdd_dora.xml @@ -41,7 +41,7 @@ Pull_Local_Registry Pull Images from Local Registry 0 - oai-gnb oai-nr-ue + oai-gnb-asan oai-nr-ue-asan diff --git a/ci-scripts/xml_files/container_5g_rfsim_u0_25prb.xml b/ci-scripts/xml_files/container_5g_rfsim_u0_25prb.xml index e9e9374cf1..7d8cd6a723 100644 --- a/ci-scripts/xml_files/container_5g_rfsim_u0_25prb.xml +++ b/ci-scripts/xml_files/container_5g_rfsim_u0_25prb.xml @@ -44,7 +44,7 @@ Pull_Local_Registry Pull Images from Local Registry 0 - oai-gnb oai-nr-ue + oai-gnb-asan oai-nr-ue-asan diff --git a/ci-scripts/xml_files/gnb_usrp_build.xml b/ci-scripts/xml_files/gnb_usrp_build.xml index b250d6baa4..37cee01994 100644 --- a/ci-scripts/xml_files/gnb_usrp_build.xml +++ b/ci-scripts/xml_files/gnb_usrp_build.xml @@ -35,7 +35,7 @@ TesteNB Build_eNB Build gNB (USRP) - --gNB -w USRP --ninja -c -P --build-lib "ldpc_cuda ldpc_t1" --cmake-opt -DASN1C_EXEC=/opt/asn1c/bin/asn1c + --gNB -w USRP --ninja -c -P --build-lib "ldpc_cuda" --cmake-opt -DASN1C_EXEC=/opt/asn1c/bin/asn1c True diff --git a/ci-scripts/xml_files/t1_offload_test.xml b/ci-scripts/xml_files/t1_offload_test.xml deleted file mode 100644 index cfbba04c74..0000000000 --- a/ci-scripts/xml_files/t1_offload_test.xml +++ /dev/null @@ -1,102 +0,0 @@ - - - - test-t1-offload - Test T1 Offload - tasks - 1 - 000111 000112 000121 000122 000131 000132 000211 000212 000221 000222 000231 000232 - - - - Run_LDPCt1Test - Run nr_ulsim with CPU - -n100 -s30 -m5 -r106 -R106 -C10 -P - - - - Run_LDPCt1Test - Run nr_ulsim with T1 LDPC offload - -n100 -s30 -m5 -r106 -R106 -o -P - - - - Run_LDPCt1Test - Run nr_ulsim with CPU - -n100 -s30 -m15 -r106 -R106 -C10 -P - - - - Run_LDPCt1Test - Run nr_ulsim with T1 LDPC offload - -n100 -s30 -m15 -r106 -R106 -o -P - - - - Run_LDPCt1Test - Run nr_ulsim with CPU - -n100 -s30 -m25 -r106 -R106 -C10 -P - - - - Run_LDPCt1Test - Run nr_ulsim with T1 LDPC offload - -n100 -s30 -m25 -r106 -R106 -o -P - - - - Run_LDPCt1Test - Run nr_ulsim with CPU - -n100 -s30 -m5 -r273 -R273 -C10 -P - - - - Run_LDPCt1Test - Run nr_ulsim with T1 LDPC offload - -n100 -s30 -m5 -r273 -R273 -o -P - - - - Run_LDPCt1Test - Run nr_ulsim with CPU - -n100 -s30 -m15 -r273 -R273 -C10 -P - - - - Run_LDPCt1Test - Run nr_ulsim with T1 LDPC offload - -n100 -s30 -m15 -r273 -R273 -o -P - - - - Run_LDPCt1Test - Run nr_ulsim with CPU - -n100 -s30 -m25 -r273 -R273 -C10 -P - - - - Run_LDPCt1Test - Run nr_ulsim with T1 LDPC offload - -n100 -s30 -m25 -r273 -R273 -o -P - - - diff --git a/ci-scripts/yaml_files/5g_f1_rfsimulator/docker-compose.yaml b/ci-scripts/yaml_files/5g_f1_rfsimulator/docker-compose.yaml index e2c6d7ed0d..93d9011f83 100644 --- a/ci-scripts/yaml_files/5g_f1_rfsimulator/docker-compose.yaml +++ b/ci-scripts/yaml_files/5g_f1_rfsimulator/docker-compose.yaml @@ -168,6 +168,7 @@ services: container_name: rfsim5g-oai-cu environment: USE_ADDITIONAL_OPTIONS: --sa --rfsim --log_config.global_log_options level,nocolor,time + ASAN_OPTIONS: detect_leaks=0 depends_on: - oai-ext-dn networks: @@ -186,6 +187,7 @@ services: container_name: rfsim5g-oai-du environment: USE_ADDITIONAL_OPTIONS: --sa --rfsim --log_config.global_log_options level,nocolor,time + ASAN_OPTIONS: detect_leaks=0 depends_on: - oai-cu networks: @@ -203,7 +205,8 @@ services: privileged: true container_name: rfsim5g-oai-du2 environment: - USE_ADDITIONAL_OPTIONS: --sa --rfsim --gNBs.[0].gNB_ID 0xe01 --gNBs.[0].nr_cellid 87654321 --gNBs.[0].servingCellConfigCommon.[0].physCellId 1 --MACRLCs.[0].local_n_address 192.168.71.143 --log_config.global_log_options level,nocolor,time + USE_ADDITIONAL_OPTIONS: --sa --rfsim --gNBs.[0].gNB_DU_ID 0xe01 --gNBs.[0].nr_cellid 87654321 --gNBs.[0].servingCellConfigCommon.[0].physCellId 1 --MACRLCs.[0].local_n_address 192.168.71.143 --log_config.global_log_options level,nocolor,time + ASAN_OPTIONS: detect_leaks=0 depends_on: - oai-cu networks: @@ -221,7 +224,8 @@ services: privileged: true container_name: rfsim5g-oai-du3 environment: - USE_ADDITIONAL_OPTIONS: --sa --rfsim --gNBs.[0].gNB_ID 0xe02 --gNBs.[0].nr_cellid 11111111 --gNBs.[0].servingCellConfigCommon.[0].physCellId 2 --MACRLCs.[0].local_n_address 192.168.71.144 --log_config.global_log_options level,nocolor,time + USE_ADDITIONAL_OPTIONS: --sa --rfsim --gNBs.[0].gNB_DU_ID 0xe02 --gNBs.[0].nr_cellid 11111111 --gNBs.[0].servingCellConfigCommon.[0].physCellId 2 --MACRLCs.[0].local_n_address 192.168.71.144 --log_config.global_log_options level,nocolor,time + ASAN_OPTIONS: detect_leaks=0 depends_on: - oai-cu networks: @@ -240,6 +244,7 @@ services: container_name: rfsim5g-oai-nr-ue environment: USE_ADDITIONAL_OPTIONS: --sa --rfsim -r 106 --numerology 1 --uicc0.imsi 208990100001100 -C 3619200000 --rfsimulator.serveraddr 192.168.71.142 --log_config.global_log_options level,nocolor,time + ASAN_OPTIONS: detect_leaks=0 depends_on: - oai-du networks: @@ -258,6 +263,7 @@ services: container_name: rfsim5g-oai-nr-ue2 environment: USE_ADDITIONAL_OPTIONS: --sa --rfsim -r 106 --numerology 1 --uicc0.imsi 208990100001101 -C 3619200000 --rfsimulator.serveraddr 192.168.71.143 --log_config.global_log_options level,nocolor,time + ASAN_OPTIONS: detect_leaks=0 depends_on: - oai-du2 networks: @@ -276,6 +282,7 @@ services: container_name: rfsim5g-oai-nr-ue3 environment: USE_ADDITIONAL_OPTIONS: --sa --rfsim -r 106 --numerology 1 --uicc0.imsi 208990100001102 -C 3619200000 --rfsimulator.serveraddr 192.168.71.144 --log_config.global_log_options level,nocolor,time + ASAN_OPTIONS: detect_leaks=0 depends_on: - oai-du3 networks: diff --git a/ci-scripts/yaml_files/5g_fdd_rfsimulator/docker-compose.yaml b/ci-scripts/yaml_files/5g_fdd_rfsimulator/docker-compose.yaml index 8cf83e8943..7912c48408 100644 --- a/ci-scripts/yaml_files/5g_fdd_rfsimulator/docker-compose.yaml +++ b/ci-scripts/yaml_files/5g_fdd_rfsimulator/docker-compose.yaml @@ -168,6 +168,7 @@ services: container_name: rfsim5g-oai-gnb environment: USE_ADDITIONAL_OPTIONS: --sa -E --rfsim --log_config.global_log_options level,nocolor,time + ASAN_OPTIONS: detect_leaks=0 depends_on: - oai-ext-dn networks: @@ -186,6 +187,7 @@ services: container_name: rfsim5g-oai-nr-ue environment: USE_ADDITIONAL_OPTIONS: -E --sa --rfsim -r 106 --numerology 1 --uicc0.imsi 208990100001100 --band 66 -C 2169090000 --CO -400000000 --ssb 378 --rfsimulator.serveraddr 192.168.71.140 --log_config.global_log_options level,nocolor,time + ASAN_OPTIONS: detect_leaks=0 depends_on: - oai-gnb networks: diff --git a/ci-scripts/yaml_files/5g_l2sim_tdd/docker-compose.yaml b/ci-scripts/yaml_files/5g_l2sim_tdd/docker-compose.yaml index 86c678c811..38b82988f9 100644 --- a/ci-scripts/yaml_files/5g_l2sim_tdd/docker-compose.yaml +++ b/ci-scripts/yaml_files/5g_l2sim_tdd/docker-compose.yaml @@ -170,6 +170,7 @@ services: environment: TZ: Europe/Paris USE_ADDITIONAL_OPTIONS: --sa --nfapi VNF --emulate-l1 --log_config.global_log_options level,time,thread_id,nocolor + ASAN_OPTIONS: detect_leaks=0 depends_on: - oai-spgwu - oai-amf @@ -206,6 +207,7 @@ services: TZ: Europe/Paris OPENAIR_DIR: /opt/oai-nr-ue USE_ADDITIONAL_OPTIONS: --nfapi STANDALONE_PNF --node-number 2 --sa --emulate-l1 --log_config.global_log_options level,time,thread_id,nocolor + ASAN_OPTIONS: detect_leaks=0 volumes: - ../../conf_files/nrue.band78.106prb.l2sim.conf:/opt/oai-nr-ue/etc/nr-ue.conf - ../../../openair1/SIMULATION/LTE_PHY/BLER_SIMULATIONS/AWGN/AWGN_results:/opt/oai-nr-ue/openair1/SIMULATION/LTE_PHY/BLER_SIMULATIONS/AWGN/AWGN_results diff --git a/ci-scripts/yaml_files/5g_rfsimulator/docker-compose.yaml b/ci-scripts/yaml_files/5g_rfsimulator/docker-compose.yaml index bbdfe7d1f4..d238d63ea1 100644 --- a/ci-scripts/yaml_files/5g_rfsimulator/docker-compose.yaml +++ b/ci-scripts/yaml_files/5g_rfsimulator/docker-compose.yaml @@ -168,6 +168,7 @@ services: container_name: rfsim5g-oai-gnb environment: USE_ADDITIONAL_OPTIONS: --sa -E --rfsim --log_config.global_log_options level,nocolor,time + ASAN_OPTIONS: detect_leaks=0 depends_on: - oai-ext-dn networks: @@ -186,6 +187,7 @@ services: container_name: rfsim5g-oai-nr-ue environment: USE_ADDITIONAL_OPTIONS: -E --sa --rfsim -r 106 --numerology 1 --uicc0.imsi 208990100001100 -C 3619200000 --rfsimulator.serveraddr 192.168.71.140 --log_config.global_log_options level,nocolor,time + ASAN_OPTIONS: detect_leaks=0 depends_on: - oai-gnb networks: @@ -204,6 +206,7 @@ services: container_name: rfsim5g-oai-nr-ue2 environment: USE_ADDITIONAL_OPTIONS: -E --sa --rfsim -r 106 --numerology 1 --uicc0.imsi 208990100001101 -C 3619200000 --rfsimulator.serveraddr 192.168.71.140 --log_config.global_log_options level,nocolor,time + ASAN_OPTIONS: detect_leaks=0 depends_on: - oai-gnb networks: @@ -222,6 +225,7 @@ services: container_name: rfsim5g-oai-nr-ue3 environment: USE_ADDITIONAL_OPTIONS: -E --sa --rfsim -r 106 --numerology 1 --uicc0.imsi 208990100001102 -C 3619200000 --rfsimulator.serveraddr 192.168.71.140 --log_config.global_log_options level,nocolor,time + ASAN_OPTIONS: detect_leaks=0 depends_on: - oai-gnb networks: @@ -240,6 +244,7 @@ services: container_name: rfsim5g-oai-nr-ue4 environment: USE_ADDITIONAL_OPTIONS: -E --sa --rfsim -r 106 --numerology 1 --uicc0.imsi 208990100001103 -C 3619200000 --rfsimulator.serveraddr 192.168.71.140 --log_config.global_log_options level,nocolor,time + ASAN_OPTIONS: detect_leaks=0 depends_on: - oai-gnb networks: @@ -258,6 +263,7 @@ services: container_name: rfsim5g-oai-nr-ue5 environment: USE_ADDITIONAL_OPTIONS: -E --sa --rfsim -r 106 --numerology 1 --uicc0.imsi 208990100001104 -C 3619200000 --rfsimulator.serveraddr 192.168.71.140 --log_config.global_log_options level,nocolor,time + ASAN_OPTIONS: detect_leaks=0 depends_on: - oai-gnb networks: @@ -276,6 +282,7 @@ services: container_name: rfsim5g-oai-nr-ue6 environment: USE_ADDITIONAL_OPTIONS: -E --sa --rfsim -r 106 --numerology 1 --uicc0.imsi 208990100001105 -C 3619200000 --rfsimulator.serveraddr 192.168.71.140 --log_config.global_log_options level,nocolor,time + ASAN_OPTIONS: detect_leaks=0 depends_on: - oai-gnb networks: @@ -294,6 +301,7 @@ services: container_name: rfsim5g-oai-nr-ue7 environment: USE_ADDITIONAL_OPTIONS: -E --sa --rfsim -r 106 --numerology 1 --uicc0.imsi 208990100001106 -C 3619200000 --rfsimulator.serveraddr 192.168.71.140 --log_config.global_log_options level,nocolor,time + ASAN_OPTIONS: detect_leaks=0 depends_on: - oai-gnb networks: @@ -312,6 +320,7 @@ services: container_name: rfsim5g-oai-nr-ue8 environment: USE_ADDITIONAL_OPTIONS: -E --sa --rfsim -r 106 --numerology 1 --uicc0.imsi 208990100001107 -C 3619200000 --rfsimulator.serveraddr 192.168.71.140 --log_config.global_log_options level,nocolor,time + ASAN_OPTIONS: detect_leaks=0 depends_on: - oai-gnb networks: @@ -330,6 +339,7 @@ services: container_name: rfsim5g-oai-nr-ue9 environment: USE_ADDITIONAL_OPTIONS: -E --sa --rfsim -r 106 --numerology 1 --uicc0.imsi 208990100001108 -C 3619200000 --rfsimulator.serveraddr 192.168.71.140 --log_config.global_log_options level,nocolor,time + ASAN_OPTIONS: detect_leaks=0 depends_on: - oai-gnb networks: @@ -348,6 +358,7 @@ services: container_name: rfsim5g-oai-nr-ue10 environment: USE_ADDITIONAL_OPTIONS: -E --sa --rfsim -r 106 --numerology 1 --uicc0.imsi 208990100001109 -C 3619200000 --rfsimulator.serveraddr 192.168.71.140 --log_config.global_log_options level,nocolor,time + ASAN_OPTIONS: detect_leaks=0 depends_on: - oai-gnb networks: diff --git a/ci-scripts/yaml_files/5g_rfsimulator_24prb/docker-compose.yaml b/ci-scripts/yaml_files/5g_rfsimulator_24prb/docker-compose.yaml index 15df28bb7e..eaadeb1b1b 100644 --- a/ci-scripts/yaml_files/5g_rfsimulator_24prb/docker-compose.yaml +++ b/ci-scripts/yaml_files/5g_rfsimulator_24prb/docker-compose.yaml @@ -168,6 +168,7 @@ services: container_name: rfsim5g-oai-gnb environment: USE_ADDITIONAL_OPTIONS: --sa --rfsim --log_config.global_log_options level,nocolor,time + ASAN_OPTIONS: detect_leaks=0 depends_on: - oai-ext-dn networks: @@ -186,6 +187,7 @@ services: container_name: rfsim5g-oai-nr-ue environment: USE_ADDITIONAL_OPTIONS: --sa --rfsim -r 24 --ssb 24 --numerology 1 -C 3604800000 --uicc0.imsi 208990100001100 --rfsimulator.serveraddr 192.168.71.140 --log_config.global_log_options level,nocolor,time + ASAN_OPTIONS: detect_leaks=0 depends_on: - oai-gnb networks: diff --git a/ci-scripts/yaml_files/5g_rfsimulator_2x2/docker-compose.yaml b/ci-scripts/yaml_files/5g_rfsimulator_2x2/docker-compose.yaml index cd5c28b9ff..8ebf8602eb 100644 --- a/ci-scripts/yaml_files/5g_rfsimulator_2x2/docker-compose.yaml +++ b/ci-scripts/yaml_files/5g_rfsimulator_2x2/docker-compose.yaml @@ -168,6 +168,7 @@ services: container_name: rfsim5g-oai-gnb environment: USE_ADDITIONAL_OPTIONS: --sa --rfsim --log_config.global_log_options level,nocolor,time + ASAN_OPTIONS: detect_leaks=0 depends_on: - oai-ext-dn networks: @@ -187,6 +188,7 @@ services: container_name: rfsim5g-oai-nr-ue environment: USE_ADDITIONAL_OPTIONS: --sa --rfsim -r 106 --numerology 1 --band 78 -C 3319680000 --ue-nb-ant-tx 2 --uicc0.imsi 208990100001100 --ue-nb-ant-rx 2 --uecap_file /opt/oai-nr-ue/etc/uecap.xml --rfsimulator.serveraddr 192.168.71.140 --log_config.global_log_options level,nocolor,time + ASAN_OPTIONS: detect_leaks=0 depends_on: - oai-gnb networks: diff --git a/ci-scripts/yaml_files/5g_rfsimulator_e1/docker-compose.yaml b/ci-scripts/yaml_files/5g_rfsimulator_e1/docker-compose.yaml index 71f00f96c2..7b4a0fcc96 100644 --- a/ci-scripts/yaml_files/5g_rfsimulator_e1/docker-compose.yaml +++ b/ci-scripts/yaml_files/5g_rfsimulator_e1/docker-compose.yaml @@ -170,6 +170,7 @@ services: container_name: rfsim5g-oai-cucp environment: USE_ADDITIONAL_OPTIONS: --sa --rfsim --log_config.global_log_options level,nocolor,time + ASAN_OPTIONS: detect_leaks=0 depends_on: - oai-ext-dn networks: @@ -190,8 +191,8 @@ services: privileged: true container_name: rfsim5g-oai-cuup environment: - USE_ADDITIONAL_OPTIONS: --sa --rfsim - #--log_config.global_log_options level,nocolor,time + USE_ADDITIONAL_OPTIONS: --sa --rfsim --log_config.global_log_options level,nocolor,time + ASAN_OPTIONS: detect_leaks=0 depends_on: - oai-cucp networks: @@ -213,6 +214,7 @@ services: container_name: rfsim5g-oai-du environment: USE_ADDITIONAL_OPTIONS: --sa --rfsim --log_config.global_log_options level,nocolor,time + ASAN_OPTIONS: detect_leaks=0 networks: ran_net: ipv4_address: 192.168.72.142 @@ -230,6 +232,7 @@ services: container_name: rfsim5g-oai-nr-ue environment: USE_ADDITIONAL_OPTIONS: --sa --rfsim -r 106 --numerology 1 -C 3619200000 --rfsimulator.serveraddr 192.168.72.142 --log_config.global_log_options level,nocolor,time + ASAN_OPTIONS: detect_leaks=0 depends_on: - oai-du networks: diff --git a/ci-scripts/yaml_files/5g_rfsimulator_fdd_phytest/docker-compose.yaml b/ci-scripts/yaml_files/5g_rfsimulator_fdd_phytest/docker-compose.yaml index 5ead5b485e..e3d21c6d13 100644 --- a/ci-scripts/yaml_files/5g_rfsimulator_fdd_phytest/docker-compose.yaml +++ b/ci-scripts/yaml_files/5g_rfsimulator_fdd_phytest/docker-compose.yaml @@ -6,6 +6,7 @@ services: container_name: rfsim5g-oai-gnb environment: USE_ADDITIONAL_OPTIONS: --phy-test --rfsim --rfsimulator.wait_timeout 20 --noS1 --log_config.global_log_options level,nocolor,time + ASAN_OPTIONS: detect_leaks=0 networks: public_net: ipv4_address: 192.168.71.140 @@ -24,6 +25,7 @@ services: container_name: rfsim5g-oai-nr-ue environment: USE_ADDITIONAL_OPTIONS: --phy-test --rfsim --noS1 --reconfig-file etc/rrc/reconfig.raw --rbconfig-file etc/rrc/rbconfig.raw --rfsimulator.serveraddr 192.168.71.140 --log_config.global_log_options level,nocolor,time + ASAN_OPTIONS: detect_leaks=0 volumes: - ../../conf_files/nrue.uicc.conf:/opt/oai-nr-ue/etc/nr-ue.conf - rrc.config:/opt/oai-nr-ue/etc/rrc/ diff --git a/ci-scripts/yaml_files/5g_rfsimulator_fr2_32prb/docker-compose.yaml b/ci-scripts/yaml_files/5g_rfsimulator_fr2_32prb/docker-compose.yaml index 10d57983b8..145122d97e 100644 --- a/ci-scripts/yaml_files/5g_rfsimulator_fr2_32prb/docker-compose.yaml +++ b/ci-scripts/yaml_files/5g_rfsimulator_fr2_32prb/docker-compose.yaml @@ -6,6 +6,7 @@ services: container_name: rfsim5g-oai-gnb environment: USE_ADDITIONAL_OPTIONS: --do-ra --rfsim --rfsimulator.wait_timeout 20 --noS1 --log_config.global_log_options level,nocolor,time + ASAN_OPTIONS: detect_leaks=0 networks: public_net: ipv4_address: 192.168.71.140 @@ -24,6 +25,7 @@ services: container_name: rfsim5g-oai-nr-ue environment: USE_ADDITIONAL_OPTIONS: --do-ra --rfsim --noS1 --reconfig-file etc/rrc/reconfig.raw --rbconfig-file etc/rrc/rbconfig.raw --rfsimulator.serveraddr 192.168.71.140 --log_config.global_log_options level,nocolor,time + ASAN_OPTIONS: detect_leaks=0 volumes: - ../../conf_files/nrue.uicc.conf:/opt/oai-nr-ue/etc/nr-ue.conf - rrc.config:/opt/oai-nr-ue/etc/rrc/ diff --git a/ci-scripts/yaml_files/5g_rfsimulator_tdd_dora/docker-compose.yaml b/ci-scripts/yaml_files/5g_rfsimulator_tdd_dora/docker-compose.yaml index dc1998dffa..eb2b59f5f4 100644 --- a/ci-scripts/yaml_files/5g_rfsimulator_tdd_dora/docker-compose.yaml +++ b/ci-scripts/yaml_files/5g_rfsimulator_tdd_dora/docker-compose.yaml @@ -6,6 +6,7 @@ services: container_name: rfsim5g-oai-gnb environment: USE_ADDITIONAL_OPTIONS: --do-ra --rfsim --rfsimulator.wait_timeout 20 --noS1 --log_config.global_log_options level,nocolor,time + ASAN_OPTIONS: detect_leaks=0 networks: public_net: ipv4_address: 192.168.71.140 @@ -24,6 +25,7 @@ services: container_name: rfsim5g-oai-nr-ue environment: USE_ADDITIONAL_OPTIONS: --do-ra --rfsim --noS1 --reconfig-file etc/rrc/reconfig.raw --rbconfig-file etc/rrc/rbconfig.raw --rfsimulator.serveraddr 192.168.71.140 --log_config.global_log_options level,nocolor,time + ASAN_OPTIONS: detect_leaks=0 volumes: - ../../conf_files/nrue.uicc.conf:/opt/oai-nr-ue/etc/nr-ue.conf - rrc.config:/opt/oai-nr-ue/etc/rrc/ diff --git a/ci-scripts/yaml_files/5g_rfsimulator_u0_25prb/docker-compose.yaml b/ci-scripts/yaml_files/5g_rfsimulator_u0_25prb/docker-compose.yaml index 6055138e65..42fb6648e8 100644 --- a/ci-scripts/yaml_files/5g_rfsimulator_u0_25prb/docker-compose.yaml +++ b/ci-scripts/yaml_files/5g_rfsimulator_u0_25prb/docker-compose.yaml @@ -168,6 +168,7 @@ services: container_name: rfsim5g-oai-gnb environment: USE_ADDITIONAL_OPTIONS: --sa --rfsim --log_config.global_log_options level,nocolor,time + ASAN_OPTIONS: detect_leaks=0 depends_on: - oai-ext-dn networks: @@ -187,6 +188,7 @@ services: container_name: rfsim5g-oai-nr-ue environment: USE_ADDITIONAL_OPTIONS: --sa --rfsim -r 25 --numerology 0 --uicc0.imsi 208990100001100 --band 66 -C 2152260000 --CO -400000000 --ssb 76 --rfsimulator.serveraddr 192.168.71.140 --log_config.global_log_options level,nocolor,time + ASAN_OPTIONS: detect_leaks=0 depends_on: - oai-gnb networks: diff --git a/cmake_targets/build_oai b/cmake_targets/build_oai index 819017fedb..31d54ab9ea 100755 --- a/cmake_targets/build_oai +++ b/cmake_targets/build_oai @@ -46,7 +46,7 @@ BUILD_DOXYGEN=0 DISABLE_HARDWARE_DEPENDENCY="False" CMAKE_BUILD_TYPE="RelWithDebInfo" CMAKE_CMD="$CMAKE" -OPTIONAL_LIBRARIES="telnetsrv enbscope uescope nrscope nrqtscope ldpc_cuda ldpc_t1 websrv oai_iqplayer" +OPTIONAL_LIBRARIES="telnetsrv enbscope uescope nrscope nrqtscope ldpc_cuda ldpc_t2 websrv oai_iqplayer" TARGET_LIST="" function print_help() { diff --git a/doc/BUILD.md b/doc/BUILD.md index 3499249475..6fd6d76e3a 100644 --- a/doc/BUILD.md +++ b/doc/BUILD.md @@ -183,7 +183,6 @@ Some libraries have further dependencies and might not build on every system: - `enbscope`, `uescope`, `nrscope`: libforms/X - `nrqtscope`: Qt5 - `ldpc_cuda`: CUDA -- `ldpc_t1`: DPDK and VVDN T1 - `websrv`: npm and others # Running `cmake` directly diff --git a/doc/F1-design.md b/doc/F1-design.md index 2666856a42..916c1a2edf 100644 --- a/doc/F1-design.md +++ b/doc/F1-design.md @@ -116,6 +116,14 @@ sudo cmake_targets/ran_build/build/nr-softmodem --sa -O ci-scripts/conf_files/gn These files are tested in the CI, and are configured for use in docker, see [this `docker-compose` file](../ci-scripts/yaml_files/5g_f1_rfsimulator/docker-compose.yaml). +The rules to decide if a config triggers a start of a DU, CU, or monolithic +gNB, are, in order: +1. If the `MACRLCs` section lists `f1` as northbound transport preference + (`tr_n_preference`), it is a DU. +2. If the `gNBs` section lists `f1` as a southound transport preference + (`tr_s_preference`), it is a CU. +3. It is a (monolithic) gNB. + ## Configuration of F1 IP/port information For a local deployment, you should update the following fields. diff --git a/doc/LDPC_T2_OFFLOAD_SETUP.md b/doc/LDPC_T2_OFFLOAD_SETUP.md new file mode 100644 index 0000000000..551ddcc1df --- /dev/null +++ b/doc/LDPC_T2_OFFLOAD_SETUP.md @@ -0,0 +1,149 @@ + + + + + +
+ + + + + + OAI T1/T2 LDPC offload +
+ +**Table of Contents** + +[[_TOC_]] + +This documentation aims to provide a tutorial for AMD Xilinx T2 Telco card integration into OAI and its usage. + +# Requirements + + - bitstream image and PMD driver for the T2 card provided by AccelerComm + - DPDK 20.11.7 with patch from Accelercomm (also tested with DPDK 20.11.3) + - tested on RHEL7.9, RHEL9.2, Ubuntu 20.04, Ubuntu 22.04 + +# DPDK setup +## DPDK installation +``` +# Get DPDK source code +git clone https://github.com/DPDK/dpdk-stable.git ~/dpdk-stable +cd ~/dpdk-stable +git checkout v20.11.7 +git apply ~/ACL_BBDEV_DPDK20.11.3_xxx.patch +``` +Replace `~/ACL_BBDEV_DPDK20.11.3_xxx.patch` by patch file provided by +Accelercomm. +``` +cd ~/dpdk-stable +meson setup build +# meson setup --prefix=/opt/dpdk-t2 build for installation with non-default installation prefix +cd build +ninja +sudo ninja install +sudo ldconfig +``` +## DPDK configuration + - load required kernel module +``` +sudo modprobe igb_uio +sudo insmod ~/dpdk-stable/kernel/linux/igb_uio/igb_uio.ko +``` + - check presence of the card and its PCI addres on the host machine +``` +lspci | grep "Xilinx" +``` + - bind the card with igb_uio driver +``` +sudo python3 ~/dpdk-stable/usertools/dpdk-devbind.py -b igb_uio 41:00.0 +``` +Replace PCI address of the card *41:00.0* by address detected by *lspci | grep "Xilinx"* command + - hugepages setup (10 x 1GB hugepages) +``` +sudo python3 ~/dpdk-stable/usertools/dpdk-hugepages.py -p 1G --setup 10G` +``` + +*Note: device binding and hugepages setup has to be done after every reboot of +the host machine* + +# Modifications in the OAI code +## PMD path specification +Path to the PMD for operating the card is specified in `CMakeLists.txt` file in +*LDPC OFFLOAD library* section. Modify following line based on the location of +the PMD on your system. By deafult, path to the PMD is set to `/opt/dpdk-t2/lib/x86_64-linux-gnu/`. +``` +find_library(PMD_T2 NAMES rte_baseband_accl_ldpc HINTS "/opt/dpdk-t2/lib/x86_64-linux-gnu/") +``` + +## T2 card DPDK initialization +Following lines in `openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_decoder_offload.c` file has to be +modified based on your system requirements. By default, PCI address of the T2 card is set to 41:00.0 and cores 14 and 15 are assigned to the DPDK. +``` + char *dpdk_dev = "41:00.0"; //PCI address of the card + char *argv_re[] = {"bbdev", "-a", dpdk_dev, "-l", "14-15", "--file-prefix=b6", "--"}; +``` +For the DPDK EAL initialization, device is specified by `-a` option and list +of cores to run the DPDK application on is selected by `-l` option. PCI adress of +the T2 card can be detected by `lspci | grep "Xilinx"` command. + +# OAI Build +OTA deployment is precisely described in the following tutorial: +- [NR_SA_Tutorial_COTS_UE](https://gitlab.eurecom.fr/oai/openairinterface5g/-/blob/develop/doc/NR_SA_Tutorial_COTS_UE.md) +Instead of section *3.2 Build OAI gNB* from the tutorial, run following commands: + +``` +# Get openairinterface5g source code +git clone https://gitlab.eurecom.fr/oai/openairinterface5g.git ~/openairinterface5g +cd ~/openairinterface5g +git checkout develop + +# Install OAI dependencies +cd ~/openairinterface5g/cmake_targets +./build_oai -I + +# Build OAI gNB +cd ~/openairinterface5g +source oaienv +cd cmake_targets +./build_oai -w USRP --ninja --gNB -P -C --build-lib "ldpc_t2" +``` +Shared object file *libldpc_t2.so* is created during the compilation. This object is conditionally compiled. Selection of the library to compile is done using *--build-lib ldpc_t2*. + +*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* + +# 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: +``` +cd ~/openairinterface5g +source oaienv +cd cmake_targets/ran_build/build +sudo ./nr_ulsim -n100 -s20 -m20 -r273 -R273 -o +``` +## 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: +``` +cd ~/openairinterface5g +source oaienv +cd cmake_targets/ran_build/build +sudo ./nr_dlsim -n300 -s30 -R 106 -e 27 -c +``` + +# OTA test +Offload of the channel encoding and decoding to the AMD Xilinx T2 card is enabled by *--ldpc-offload-enable 1* option. + +## Run OAI gNB with USRP B210 +``` +cd ~/openairinterface5g +source oaienv +cd cmake_targets/ran_build/build +sudo ./nr-softmodem --sa -O ../../../targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.conf --ldpc-offload-enable 1 +``` + +# Limitations +## AMD Xilinx T2 card + - offload of the LDPC encoding implemented for MCS > 2, OAI CPU encoder is used for MCS =< 2 + - functionality of the LDPC encoding and decoding offload verified in OTA SISO setup with USRP N310 and Quectel RM500Q, blocking of the card reported for MIMO setup (2 layers) + +*Note: AMD Xilinx T1 Telco card is not supported anymore.* diff --git a/doc/NR_SA_Tutorial_OAI_nrUE.md b/doc/NR_SA_Tutorial_OAI_nrUE.md index a77df3266b..a956dd84f5 100644 --- a/doc/NR_SA_Tutorial_OAI_nrUE.md +++ b/doc/NR_SA_Tutorial_OAI_nrUE.md @@ -207,3 +207,8 @@ sudo ethtool -G enp1s0f0 tx 4096 rx 4096 ## 6.3 Uplink issues related with noise on the DC carriers - There is noise on the DC carriers on N300 and especially the X300 in UL. To avoid their use or shift them away from the center to use more UL spectrum, use the `--tune-offset ` command line switch, where `` is ideally half the bandwidth, or possibly less. + +## 6.4 Timing-related Problems +- Sometimes, the nrUE would keep repeating RA procedure because of Msg3 failure at the gNB. If it happens, add the `-A` option at the nrUE and/or gNB side, e.g., `-A 45`. This modifies the timing advance (in samples). Adjust +/-5 if the issue persists. +- This can be necessary since certain USRPs have larger signal delays than others; it is therefore specific to the used USRP model. +- The x310 and B210 are found to work with the default configuration; N310 and x410 can benefit from setting this timing advance. diff --git a/docker/Dockerfile.build.ubuntu20 b/docker/Dockerfile.build.ubuntu20 index 807b7d258a..ea1a0d0c42 100644 --- a/docker/Dockerfile.build.ubuntu20 +++ b/docker/Dockerfile.build.ubuntu20 @@ -26,6 +26,7 @@ #--------------------------------------------------------------------- FROM ran-base:latest as ran-build +ARG BUILD_OPTION RUN rm -Rf /oai-ran WORKDIR /oai-ran @@ -35,4 +36,12 @@ COPY . . RUN /bin/sh oaienv && \ cd cmake_targets && \ mkdir -p log && \ - ./build_oai --eNB --gNB --RU --UE --nrUE --ninja --build-lib "telnetsrv enbscope uescope nrscope nrqtscope" -w USRP -t Ethernet --noavx512 -c --cmake-opt -DCMAKE_C_FLAGS=-Werror --cmake-opt -DCMAKE_CXX_FLAGS=-Werror + ./build_oai -c --ninja \ + --eNB --gNB --RU --UE --nrUE \ + --build-lib "telnetsrv enbscope uescope nrscope nrqtscope" \ + -w USRP -t Ethernet \ + --build-e2 --cmake-opt -DXAPP_MULTILANGUAGE=OFF \ + --noavx512 \ + --cmake-opt -DCMAKE_C_FLAGS=-Werror --cmake-opt -DCMAKE_CXX_FLAGS=-Werror $BUILD_OPTION && \ + # Mainly to see if the sanitize option was perfectly executed + ldd ran_build/build/nr-softmodem diff --git a/docker/Dockerfile.eNB.ubuntu20 b/docker/Dockerfile.eNB.ubuntu20 index 15418474a9..2f10bda9ef 100644 --- a/docker/Dockerfile.eNB.ubuntu20 +++ b/docker/Dockerfile.eNB.ubuntu20 @@ -32,6 +32,7 @@ FROM ran-build:latest AS enb-build #start from scratch for target executable FROM ubuntu:focal as oai-enb +ARG BUILD_OPTION ENV DEBIAN_FRONTEND=noninteractive ENV TZ=Europe/Paris @@ -57,6 +58,11 @@ RUN apt-get update && \ python3-six \ python3-requests \ libusb-1.0-0 && \ +# if the --sanitize option was used to build, additional packages are required + /bin/bash -c 'if [[ "$BUILD_OPTION" = "--sanitize" ]]; then DEBIAN_FRONTEND=noninteractive apt-get install --yes \ + libasan5 \ + libubsan1 \ + liblapacke; fi' && \ rm -rf /var/lib/apt/lists/* WORKDIR /opt/oai-enb/bin @@ -93,8 +99,8 @@ COPY --from=enb-base \ RUN /bin/bash -c "ln -s /usr/local/lib/liboai_usrpdevif.so /usr/local/lib/liboai_device.so" && \ /bin/bash -c "ln -s /usr/local/lib/liboai_eth_transpro.so /usr/local/lib/liboai_transpro.so" && \ - ldconfig - + ldconfig && \ + ldd /opt/oai-enb/bin/lte-softmodem WORKDIR /opt/oai-enb diff --git a/docker/Dockerfile.gNB.ubuntu20 b/docker/Dockerfile.gNB.ubuntu20 index f9ee719839..6cc0af8965 100644 --- a/docker/Dockerfile.gNB.ubuntu20 +++ b/docker/Dockerfile.gNB.ubuntu20 @@ -32,6 +32,7 @@ FROM ran-build:latest AS gnb-build #start from scratch for target executable FROM ubuntu:focal as oai-gnb +ARG BUILD_OPTION ENV DEBIAN_FRONTEND=noninteractive ENV TZ=Europe @@ -56,6 +57,11 @@ RUN apt-get update && \ python3-six \ python3-requests \ libusb-1.0-0 && \ +# if the --sanitize option was used to build, additional packages are required + /bin/bash -c 'if [[ "$BUILD_OPTION" = "--sanitize" ]]; then DEBIAN_FRONTEND=noninteractive apt-get install --yes \ + libasan5 \ + libubsan1 \ + liblapacke; fi' && \ rm -rf /var/lib/apt/lists/* WORKDIR /opt/oai-gnb/bin @@ -91,7 +97,8 @@ COPY --from=gnb-base \ /usr/lib/x86_64-linux-gnu/ RUN /bin/bash -c "ln -s /usr/local/lib/liboai_usrpdevif.so /usr/local/lib/liboai_device.so" && \ - ldconfig + ldconfig && \ + ldd /opt/oai-gnb/bin/nr-softmodem WORKDIR /opt/oai-gnb #EXPOSE 2152/udp # S1U, GTP/UDP diff --git a/docker/Dockerfile.lteUE.ubuntu20 b/docker/Dockerfile.lteUE.ubuntu20 index dc7376e644..89dbd505d5 100644 --- a/docker/Dockerfile.lteUE.ubuntu20 +++ b/docker/Dockerfile.lteUE.ubuntu20 @@ -32,6 +32,7 @@ FROM ran-build:latest AS lte-ue-build #start from scratch for target executable FROM ubuntu:focal as oai-lte-ue +ARG BUILD_OPTION ENV DEBIAN_FRONTEND=noninteractive ENV TZ=Europe/Paris @@ -56,6 +57,11 @@ RUN apt-get update && \ iputils-ping \ iproute2 \ iperf && \ +# if the --sanitize option was used to build, additional packages are required + /bin/bash -c 'if [[ "$BUILD_OPTION" = "--sanitize" ]]; then DEBIAN_FRONTEND=noninteractive apt-get install --yes \ + libasan5 \ + libubsan1 \ + liblapacke; fi' && \ rm -rf /var/lib/apt/lists/* WORKDIR /opt/oai-lte-ue/bin @@ -94,7 +100,8 @@ COPY --from=lte-ue-base \ /usr/lib/x86_64-linux-gnu/ RUN /bin/bash -c "ln -s /usr/local/lib/liboai_usrpdevif.so /usr/local/lib/liboai_device.so" && \ - ldconfig + ldconfig && \ + ldd /opt/oai-lte-ue/bin/lte-uesoftmodem WORKDIR /opt/oai-lte-ue CMD ["/opt/oai-lte-ue/bin/lte-uesoftmodem"] diff --git a/docker/Dockerfile.nr-cuup.ubuntu20 b/docker/Dockerfile.nr-cuup.ubuntu20 index 222a4dd361..9cd795ac1f 100644 --- a/docker/Dockerfile.nr-cuup.ubuntu20 +++ b/docker/Dockerfile.nr-cuup.ubuntu20 @@ -31,6 +31,7 @@ FROM ran-build:latest AS gnb-build FROM ubuntu:focal as oai-nr-cuup +ARG BUILD_OPTION ENV DEBIAN_FRONTEND=noninteractive ENV TZ=Europe @@ -40,6 +41,11 @@ RUN apt-get update && \ libsctp1 \ libconfig9 \ openssl && \ +# if the --sanitize option was used to build, additional packages are required + /bin/bash -c 'if [[ "$BUILD_OPTION" = "--sanitize" ]]; then DEBIAN_FRONTEND=noninteractive apt-get install --yes \ + libasan5 \ + libubsan1 \ + liblapacke; fi' && \ rm -rf /var/lib/apt/lists/* WORKDIR /opt/oai-gnb/bin diff --git a/docker/Dockerfile.nrUE.ubuntu20 b/docker/Dockerfile.nrUE.ubuntu20 index a4b63d3cef..30d32b2f31 100644 --- a/docker/Dockerfile.nrUE.ubuntu20 +++ b/docker/Dockerfile.nrUE.ubuntu20 @@ -32,6 +32,7 @@ FROM ran-build:latest AS nr-ue-build #start from scratch for target executable FROM ubuntu:focal as oai-nr-ue +ARG BUILD_OPTION ENV DEBIAN_FRONTEND=noninteractive ENV TZ=Europe/Paris @@ -56,6 +57,10 @@ RUN apt-get update && \ iputils-ping \ iproute2 \ iperf && \ +# if the --sanitize option was used to build, additional packages are required + /bin/bash -c 'if [[ "$BUILD_OPTION" = "--sanitize" ]]; then DEBIAN_FRONTEND=noninteractive apt-get install --yes \ + libasan5 \ + libubsan1; fi' && \ rm -rf /var/lib/apt/lists/* WORKDIR /opt/oai-nr-ue/bin @@ -95,7 +100,8 @@ COPY --from=nr-ue-base \ /usr/lib/x86_64-linux-gnu/ RUN /bin/bash -c "ln -s /usr/local/lib/liboai_usrpdevif.so /usr/local/lib/liboai_device.so" && \ - ldconfig + ldconfig && \ + ldd /opt/oai-nr-ue/bin/nr-uesoftmodem WORKDIR /opt/oai-nr-ue CMD ["/opt/oai-nr-ue/bin/nr-uesoftmodem", "-O", "/opt/oai-nr-ue/etc/nr-ue.conf"] diff --git a/docker/README.md b/docker/README.md index ebfaefb3d2..578cd47274 100644 --- a/docker/README.md +++ b/docker/README.md @@ -46,16 +46,15 @@ For all platforms, the strategy for building docker/podman images is the same: - Some tools (such as `ping`, `ifconfig`) Note that on every push to develop (i.e., typically after integrating merge -requests), we build all images and push them to [Docker -Hub](https://hub.docker.com/u/oaisoftwarealliance). To pull them, do +requests), we build all images and push them to [Docker Hub](https://hub.docker.com/u/oaisoftwarealliance). To pull them, do + ``` docker pull oaisoftwarealliance/oai-gnb:develop docker pull oaisoftwarealliance/oai-nr-ue:develop docker pull oaisoftwarealliance/oai-enb:develop docker pull oaisoftwarealliance/oai-lte-ue:develop ``` -Have a look at [this -README](../ci-scripts/yaml_files/5g_rfsimulator/README.md) to get some +Have a look at [this README](../ci-scripts/yaml_files/5g_rfsimulator/README.md) to get some information on how to use the images. # 2. File organization # @@ -114,6 +113,34 @@ ran-base latest 5c9c02a5b4a8 1 minute ago Note that the steps are identical for `rocky-linux`. +### 3.2.1. Additional build otions + +This is only available for the Ubuntu-20 version. + +You can, for example, create a `sanitizer` version of the ran-build image. + +```bash +docker build --target ran-build --tag ran-build:latest --file docker/Dockerfile.build.ubuntu20 --build-arg "BUILD_OPTION=--sanitize" . +``` + +Currently the `--sanitize` option for `build_oai` enables: + +* [Address Sanitizer](https://github.com/google/sanitizers/wiki/AddressSanitizer) +* [Undefined Behavior Sanitizer](https://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html) + +After building: + +```bash +docker image ls +REPOSITORY TAG IMAGE ID CREATED SIZE +ran-build latest f2633a7f5102 1 minute ago 8.78GB +... +``` + +Note that the image is much bigger. + +You can also use this docker build arguments to pass any available option(s) on the `build-oai` script. + ## 3.3. Building any target image ## For example, the eNB: @@ -141,6 +168,14 @@ docker image prune --force Note that the steps are identical for `rocky-linux`. +If you have used the sanitizer option, then you should also pass it when building the target image: + +```bash +docker build --target oai-gnb --tag oai-gnb:latest --file docker/Dockerfile.gNB.ubuntu20 --build-arg "BUILD_OPTION=--sanitize" . +``` + +Normally the target image will be around 200 Mbytes bigger. + # 4. Building using `podman` under Red Hat Entreprise Linux 8.2 # Analogous to the above steps: diff --git a/executables/nr-cuup.c b/executables/nr-cuup.c index 1e6c22a337..5fb66bc73a 100644 --- a/executables/nr-cuup.c +++ b/executables/nr-cuup.c @@ -130,7 +130,8 @@ int main(int argc, char **argv) AssertFatal(rc >= 0, "Create task for CUUP E1 failed\n"); nr_pdcp_layer_init(true); cu_init_f1_ue_data(); // for CU-UP/CP mapping: we use the same - MessageDef *msg = RCconfig_NR_CU_E1(true); + E1_t e1type = UPtype; + MessageDef *msg = RCconfig_NR_CU_E1(&e1type); AssertFatal(msg != NULL, "Send init to task for E1AP UP failed\n"); itti_send_msg_to_task(TASK_CUUP_E1, 0, msg); diff --git a/executables/nr-softmodem-common.h b/executables/nr-softmodem-common.h index 2550001956..da743e4342 100644 --- a/executables/nr-softmodem-common.h +++ b/executables/nr-softmodem-common.h @@ -98,7 +98,7 @@ #define CONFIG_HLP_WORKER_CMD "two option for worker 'WORKER_DISABLE' or 'WORKER_ENABLE'\n" #define CONFIG_HLP_USRP_THREAD "having extra thead for usrp tx\n" #define CONFIG_HLP_DISABLNBIOT "disable nb-iot, even if defined in config\n" -#define CONFIG_HLP_LDPC_OFFLOAD "enable LDPC offload\n" +#define CONFIG_HLP_LDPC_OFFLOAD "enable LDPC offload to AMD Xilinx T2 card\n" #define CONFIG_HLP_USRP_ARGS "set the arguments to identify USRP (same syntax as in UHD)\n" #define CONFIG_HLP_TX_SUBDEV "set the arguments to select tx_subdev (same syntax as in UHD)\n" #define CONFIG_HLP_RX_SUBDEV "set the arguments to select rx_subdev (same syntax as in UHD)\n" diff --git a/executables/nr-softmodem.c b/executables/nr-softmodem.c index edead47430..aa8dd6025e 100644 --- a/executables/nr-softmodem.c +++ b/executables/nr-softmodem.c @@ -402,9 +402,9 @@ static int create_gNB_tasks(ngran_node_t node_type, configmodule_interface_t *cf // If CU if (node_type == ngran_gNB_CU || node_type == ngran_gNB) { - MessageDef *msg = RCconfig_NR_CU_E1(false); + MessageDef *msg = RCconfig_NR_CU_E1(NULL); instance_t inst = 0; - createE1inst(UPtype, inst, &E1AP_REGISTER_REQ(msg).net_config, NULL); + createE1inst(UPtype, inst, E1AP_REGISTER_REQ(msg).gnb_id, &E1AP_REGISTER_REQ(msg).net_config, NULL); cuup_init_n3(inst); RC.nrrrc[gnb_id_start]->e1_inst = inst; // stupid instance !!!*/ @@ -571,6 +571,53 @@ void init_pdcp(void) { } } +#ifdef E2_AGENT +#include "openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h" // need to get info from MAC +static void initialize_agent(ngran_node_t node_type, e2_agent_args_t oai_args) +{ + AssertFatal(oai_args.sm_dir != NULL , "Please, specify the directory where the SMs are located in the config file, i.e., add in config file the next line: e2_agent = {near_ric_ip_addr = \"127.0.0.1\"; sm_dir = \"/usr/local/lib/flexric/\");} "); + AssertFatal(oai_args.ip != NULL , "Please, specify the IP address of the nearRT-RIC in the config file, i.e., e2_agent = {near_ric_ip_addr = \"127.0.0.1\"; sm_dir = \"/usr/local/lib/flexric/\""); + + printf("After RCconfig_NR_E2agent %s %s \n",oai_args.sm_dir, oai_args.ip ); + + fr_args_t args = { .ip = oai_args.ip }; // init_fr_args(0, NULL); + memcpy(args.libs_dir, oai_args.sm_dir, 128); + + sleep(1); + const gNB_RRC_INST* rrc = RC.nrrrc[0]; + assert(rrc != NULL && "rrc cannot be NULL"); + + const int mcc = rrc->configuration.mcc[0]; + const int mnc = rrc->configuration.mnc[0]; + const int mnc_digit_len = rrc->configuration.mnc_digit_length[0]; + // const ngran_node_t node_type = rrc->node_type; + int nb_id = 0; + int cu_du_id = 0; + if (node_type == ngran_gNB) { + nb_id = rrc->node_id; + } else if (node_type == ngran_gNB_DU) { + const gNB_MAC_INST* mac = RC.nrmac[0]; + AssertFatal(mac != NULL, "MAC not initialized\n"); + cu_du_id = mac->f1_config.gnb_id; + nb_id = mac->f1_config.setup_req->gNB_DU_id; + } else if (node_type == ngran_gNB_CU) { + // agent buggy: the CU has no second ID, it is the CU-UP ID + // however, that is not a problem her for us, so put the same ID twice + nb_id = rrc->node_id; + cu_du_id = rrc->node_id; + } else { + LOG_E(NR_RRC, "not supported ran type detect\n"); + } + + printf("[E2 NODE]: mcc = %d mnc = %d mnc_digit = %d nb_id = %d \n", mcc, mnc, mnc_digit_len, nb_id); + + printf("[E2 NODE]: Args %s %s \n", args.ip, args.libs_dir); + + sm_io_ag_ran_t io = init_ran_func_ag(); + init_agent_api(mcc, mnc, mnc_digit_len, nb_id, cu_du_id, node_type, io, &args); +} +#endif + configmodule_interface_t *uniqCfg = NULL; int main( int argc, char **argv ) { int ru_id, CC_id = 0; @@ -689,54 +736,18 @@ int main( int argc, char **argv ) { config_sync_var=0; - - #ifdef E2_AGENT ////////////////////////////////// ////////////////////////////////// //// Init the E2 Agent - sm_io_ag_ran_t io = init_ran_func_ag(); - // OAI Wrapper e2_agent_args_t oai_args = RCconfig_NR_E2agent(); - AssertFatal(oai_args.sm_dir != NULL , "Please, specify the directory where the SMs are located in the config file, i.e., add in config file the next line: e2_agent = {near_ric_ip_addr = \"127.0.0.1\"; sm_dir = \"/usr/local/lib/flexric/\");} "); - AssertFatal(oai_args.ip != NULL , "Please, specify the IP address of the nearRT-RIC in the config file, i.e., e2_agent = {near_ric_ip_addr = \"127.0.0.1\"; sm_dir = \"/usr/local/lib/flexric/\""); - - printf("After RCconfig_NR_E2agent %s %s \n",oai_args.sm_dir, oai_args.ip ); - - fr_args_t args = { .ip = oai_args.ip }; // init_fr_args(0, NULL); - memcpy(args.libs_dir, oai_args.sm_dir, 128); - - sleep(1); - const gNB_RRC_INST* rrc = RC.nrrrc[0]; - assert(rrc != NULL && "rrc cannot be NULL"); - - const int mcc = rrc->configuration.mcc[0]; - const int mnc = rrc->configuration.mnc[0]; - const int mnc_digit_len = rrc->configuration.mnc_digit_length[0]; - // const ngran_node_t node_type = rrc->node_type; - int nb_id = 0; - int cu_du_id = 0; - if (node_type == ngran_gNB) { - nb_id = rrc->configuration.cell_identity; - } else if (node_type == ngran_gNB_DU) { - cu_du_id = rrc->node_id + 1; // Hack to avoid been 0 - nb_id = rrc->configuration.cell_identity; - } else if (node_type == ngran_gNB_CU) { - cu_du_id = rrc->node_id + 1; - nb_id = rrc->configuration.cell_identity; - } else { - LOG_E(NR_RRC, "not supported ran type detect\n"); + if (oai_args.enabled) { + initialize_agent(node_type, oai_args); } - - printf("[E2 NODE]: mcc = %d mnc = %d mnc_digit = %d nb_id = %d \n", mcc, mnc, mnc_digit_len, nb_id); - - printf("[E2 NODE]: Args %s %s \n", args.ip, args.libs_dir); - init_agent_api(mcc, mnc, mnc_digit_len, nb_id, cu_du_id, node_type, io, &args); -// } #endif // E2_AGENT diff --git a/executables/nr-uesoftmodem.c b/executables/nr-uesoftmodem.c index 12362105bd..3a5532af43 100644 --- a/executables/nr-uesoftmodem.c +++ b/executables/nr-uesoftmodem.c @@ -428,6 +428,9 @@ static void get_channel_model_mode(configmodule_interface_t *cfg) int NB_UE_INST = 1; configmodule_interface_t *uniqCfg = NULL; +// A global var to reduce the changes size +ldpc_interface_t ldpc_interface = {0}, ldpc_interface_offload = {0}; + int main( int argc, char **argv ) { int set_exe_prio = 1; if (checkIfFedoraDistribution()) @@ -465,8 +468,8 @@ int main( int argc, char **argv ) { itti_init(TASK_MAX, tasks_info); init_opt() ; - load_nrLDPClib(NULL); - + load_LDPClib(NULL, &ldpc_interface); + if (ouput_vcd) { vcd_signal_dumper_init("/tmp/openair_dump_nrUE.vcd"); } diff --git a/openair1/PHY/CODING/TESTBENCH/ldpctest.c b/openair1/PHY/CODING/TESTBENCH/ldpctest.c index f8a49e2199..7a3d299139 100644 --- a/openair1/PHY/CODING/TESTBENCH/ldpctest.c +++ b/openair1/PHY/CODING/TESTBENCH/ldpctest.c @@ -42,6 +42,7 @@ #define NR_LDPC_PROFILER_DETAIL #define NR_LDPC_ENABLE_PARITY_CHECK +ldpc_interface_t ldpc_orig, ldpc_toCompare; // 4-bit quantizer int8_t quantize4bit(double D,double x) @@ -77,49 +78,48 @@ int8_t quantize8bit(double D,double x) } typedef struct { - double n_iter_mean[400]; - double n_iter_std[400]; - int n_iter_max[400]; - double snr[400]; - double ber[400]; - double bler[400]; + double n_iter_mean; + double n_iter_std; + int n_iter_max; + double snr; + double ber; + double bler; } n_iter_stats_t; -nrLDPC_encoderfunc_t encoder_orig; +typedef struct { + unsigned int errors; + unsigned int errors_bit; + double errors_bit_uncoded; + unsigned int crc_misses; + time_stats_t time_optim; + time_stats_t time_decoder; + n_iter_stats_t dec_iter; +} one_measurement_t; -short lift_size[51]= {2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,20,22,24,26,28,30,32,36,40,44,48,52,56,60,64,72,80,88,96,104,112,120,128,144,160,176,192,208,224,240,256,288,320,352,384}; - -int test_ldpc(short max_iterations, - int nom_rate, - int denom_rate, - double SNR, - uint8_t qbits, - short block_length, - unsigned int ntrials, - int n_segments, - unsigned int *errors, - unsigned int *errors_bit, - double *errors_bit_uncoded, - unsigned int *crc_misses, - time_stats_t *time_optim, - time_stats_t *time_decoder, - n_iter_stats_t *dec_iter, - int nsnr) +one_measurement_t test_ldpc(short max_iterations, + int nom_rate, + int denom_rate, + double SNR, + unsigned char qbits, + short block_length, + unsigned int ntrials, + int n_segments) { + one_measurement_t ret = {0}; + reset_meas(&ret.time_optim); + reset_meas(&ret.time_decoder); //clock initiate //time_stats_t time,time_optim,tinput,tprep,tparity,toutput, time_decoder; time_stats_t time, tinput,tprep,tparity,toutput; double n_iter_mean = 0; double n_iter_std = 0; int n_iter_max = 0; - unsigned int segment_bler = 0; double sigma; sigma = 1.0/sqrt(2*SNR); opp_enabled=1; //short test_input[block_length]; - uint8_t *test_input[MAX_NUM_NR_DLSCH_SEGMENTS_PER_LAYER*NR_MAX_NB_LAYERS]={NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL};; - //short *c; //padded codeword + uint8_t *test_input[MAX_NUM_NR_DLSCH_SEGMENTS_PER_LAYER * NR_MAX_NB_LAYERS]; uint8_t estimated_output[MAX_NUM_DLSCH_SEGMENTS][block_length]; memset(estimated_output, 0, sizeof(estimated_output)); uint8_t *channel_input[MAX_NUM_DLSCH_SEGMENTS]; @@ -128,11 +128,8 @@ int test_ldpc(short max_iterations, double modulated_input[MAX_NUM_DLSCH_SEGMENTS][68 * 384] = { 0 }; int8_t channel_output_fixed[MAX_NUM_DLSCH_SEGMENTS][68 * 384] = { 0 }; short BG=0,nrows=0;//,ncols; - int no_punctured_columns,removed_bit; - int i1,Zc,Kb=0; + int i1, Kb = 0; int R_ind = 0; - //Table of possible lifting sizes - //short lift_size[51]= {2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,20,22,24,26,28,30,32,36,40,44,48,52,56,60,64,72,80,88,96,104,112,120,128,144,160,176,192,208,224,240,256,288,320,352,384}; //int n_segments=1; int code_rate_vec[8] = {15, 13, 25, 12, 23, 34, 56, 89}; //double code_rate_actual_vec[8] = {0.2, 0.33333, 0.4, 0.5, 0.66667, 0.73333, 0.81481, 0.88}; @@ -143,24 +140,17 @@ int test_ldpc(short max_iterations, int32_t n_iter = 0; - *errors=0; - *errors_bit=0; - *errors_bit_uncoded=0; - *crc_misses=0; - // generate input block for(int j=0;j3840) - { + if (block_length > 3840) { BG = 1; Kb = 22; - nrows = 46; //parity check bits - //ncols=22; //info bits - } - else if (block_length<=3840) - { + nrows = 46; // parity check bits + // ncols=22; //info bits + } else { BG = 2; - nrows = 42; //parity check bits - //ncols=10; // info bits - - if (block_length>640) + nrows = 42; // parity check bits + // ncols=10; // info bits + if (block_length > 640) Kb = 10; - else if (block_length>560) + else if (block_length > 560) Kb = 9; - else if (block_length>192) + else if (block_length > 192) Kb = 8; else Kb = 6; } - if (nom_rate == 1) - if (denom_rate == 5) - if (BG == 2) - R_ind = 0; - else - printf("Not supported"); - else if (denom_rate == 3) - R_ind = 1; - else if (denom_rate == 2) - //R_ind = 3; - printf("Not supported"); - else - printf("Not supported"); + bool error = false; + switch (nom_rate) { + case 1: + if (denom_rate == 5) + if (BG == 2) + R_ind = 0; + else + error = true; + else if (denom_rate == 3) + R_ind = 1; + else if (denom_rate == 2) + // R_ind = 3; + error = true; + else + error = true; + break; + case 2: + if (denom_rate == 5) + // R_ind = 2; + error = true; + else if (denom_rate == 3) + R_ind = 4; + else + error = true; + break; + case 22: + if (denom_rate == 25 && BG == 1) + R_ind = 7; + else + error = true; + break; + default: + error = true; + } - else if (nom_rate == 2) - if (denom_rate == 5) - //R_ind = 2; - printf("Not supported"); - else if (denom_rate == 3) - R_ind = 4; - else - printf("Not supported"); + if (error) { + printf("Not supported: nom_rate: %d, denom_rate: %d\n", nom_rate, denom_rate); + exit(1); + } - else if ((nom_rate == 22) && (denom_rate == 30)) - //R_ind = 5; - printf("Not supported"); - else if ((nom_rate == 22) && (denom_rate == 27)) - //R_ind = 6; - printf("Not supported"); - else if ((nom_rate == 22) && (denom_rate == 25)) - if (BG == 1) - R_ind = 7; - else - printf("Not supported"); - else - printf("Not supported"); - - //find minimum value in all sets of lifting size - Zc=0; - - for (i1=0; i1 < 51; i1++) - { - if (lift_size[i1] >= (double) block_length/Kb) - { + // find minimum value in all sets of lifting size + int Zc = 0; + const short lift_size[51] = {2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 18, 20, + 22, 24, 26, 28, 30, 32, 36, 40, 44, 48, 52, 56, 60, 64, 72, 80, 88, + 96, 104, 112, 120, 128, 144, 160, 176, 192, 208, 224, 240, 256, 288, 320, 352, 384}; + for (i1 = 0; i1 < 51; i1++) { + if (lift_size[i1] >= (double)block_length / Kb) { Zc = lift_size[i1]; - //printf("%d\n",Zc); break; } } printf("ldpc_test: codeword_length %d, n_segments %d, block_length %d, BG %d, Zc %d, Kb %d\n",n_segments *block_length, n_segments, block_length, BG, Zc, Kb); - no_punctured_columns=(int)((nrows-2)*Zc+block_length-block_length*(1/((float)nom_rate/(float)denom_rate)))/Zc; + const int no_punctured_columns = + (int)((nrows - 2) * Zc + block_length - block_length * (1 / ((float)nom_rate / (float)denom_rate))) / Zc; // printf("puncture:%d\n",no_punctured_columns); - removed_bit=(nrows-no_punctured_columns-2) * Zc+block_length-(int)(block_length/((float)nom_rate/(float)denom_rate)); - encoder_implemparams_t impp=INIT0_LDPCIMPLEMPARAMS; + const int removed_bit = + (nrows - no_punctured_columns - 2) * Zc + block_length - (int)(block_length / ((float)nom_rate / (float)denom_rate)); + printf("nrows: %d\n", nrows); + printf("no_punctured_columns: %d\n", no_punctured_columns); + printf("removed_bit: %d\n", removed_bit); + printf("To: %d\n", (Kb + nrows - no_punctured_columns) * Zc - removed_bit); + printf("number of undecoded bits: %d\n", (Kb + nrows - no_punctured_columns - 2) * Zc - removed_bit); + + encoder_implemparams_t impp = {.Zc = Zc, .Kb = Kb, .E = block_length, .BG = BG, .Kr = block_length, .K = block_length}; impp.gen_code = 2; + if (ntrials==0) - encoder_orig(test_input,channel_input, Zc, BG, block_length, BG, &impp); + ldpc_orig.LDPCencoder(test_input, channel_input, &impp); impp.gen_code=0; decode_abort_t dec_abort; init_abort(&dec_abort); - for (int trial=0; trial < ntrials; trial++) - { - segment_bler = 0; + for (int trial = 0; trial < ntrials; trial++) { + unsigned int segment_bler = 0; //// encoder start_meas(&time); - for(int j=0;j>(i&7); - uint8_t inputbit = (test_input[j][i/8]&(1<<(i&7)))>>(i&7); // Further correct for multiple segments - if (estoutputbit != inputbit) - *errors_bit = (*errors_bit) + 1; - } - - n_iter_mean += n_iter; - n_iter_std += pow(n_iter-1,2); - - if ( n_iter > n_iter_max ) - n_iter_max = n_iter; - - } // end segments - - if (segment_bler != 0) - *errors = (*errors) + 1; - + decParams[j].E = block_length; + ldpc_toCompare.LDPCinit(); } + for (int j = 0; j < n_segments; j++) { + start_meas(&ret.time_decoder); + set_abort(&dec_abort, false); + + n_iter = ldpc_toCompare.LDPCdecoder(&decParams[j], + 0, + 0, + 0, + (int8_t *)channel_output_fixed[j], + (int8_t *)estimated_output[j], + &decoder_profiler, + &dec_abort); + stop_meas(&ret.time_decoder); + // count errors + if (memcmp(estimated_output[j], test_input[j], block_length / 8) != 0) { + segment_bler++; + } + for (int i = 0; i < block_length; i++) { + unsigned char estoutputbit = (estimated_output[j][i / 8] & (1 << (i & 7))) >> (i & 7); + unsigned char inputbit = (test_input[j][i / 8] & (1 << (i & 7))) >> (i & 7); // Further correct for multiple segments + if (estoutputbit != inputbit) + ret.errors_bit++; + } + + n_iter_mean += n_iter; + n_iter_std += pow(n_iter - 1, 2); + + if (n_iter > n_iter_max) + n_iter_max = n_iter; + + } // end segments + + if (segment_bler != 0) + ret.errors++; } + ret.dec_iter.n_iter_mean = n_iter_mean / (double)ntrials / (double)n_segments - 1; + ret.dec_iter.n_iter_std = + sqrt(n_iter_std / (double)ntrials / (double)n_segments - pow(n_iter_mean / (double)ntrials / (double)n_segments - 1, 2)); + ret.dec_iter.n_iter_max = n_iter_max - 1; - dec_iter->n_iter_mean[nsnr] = n_iter_mean/(double)ntrials/(double)n_segments - 1; - dec_iter->n_iter_std[nsnr] = sqrt(n_iter_std/(double)ntrials/(double)n_segments - pow(n_iter_mean/(double)ntrials/(double)n_segments - 1,2)); - dec_iter->n_iter_max[nsnr] = n_iter_max -1; + ret.errors_bit_uncoded = ret.errors_bit_uncoded / (double)((Kb + nrows - no_punctured_columns - 2) * Zc - removed_bit); - *errors_bit_uncoded = *errors_bit_uncoded / (double)((Kb+nrows-no_punctured_columns-2) * Zc-removed_bit); - - for(int j=0;j 1280, 2401 -> 2560 // default to check output inside ldpc, the NR version checks the outer CRC defined by 3GPP - char *ldpc_version = "_parityCheck"; + char *ldpc_version = ""; /* 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; @@ -446,25 +410,22 @@ int main(int argc, char *argv[]) int nom_rate=1; int denom_rate=3; - double SNR0=-2.0,SNR,SNR_lin; + double SNR0=-2.0; uint8_t qbits=8; unsigned int decoded_errors[10000]; // initiate the size of matrix equivalent to size of SNR - int c,i=0, i1 = 0; + int c, i = 0; int n_trials = 1; double SNR_step = 0.1; randominit(0); int test_uncoded= 0; + n_iter_stats_t dec_iter[400] = {0}; - time_stats_t time_optim[10], time_decoder[10]; - n_iter_stats_t dec_iter; - - short BG=0,Zc,Kb=0; + short BG = 0, Zc; while ((c = getopt (argc, argv, "q:r:s:S:l:G:n:d:i:t:u:hv:")) != -1) - switch (c) - { + switch (c) { case 'q': qbits = atoi(optarg); break; @@ -509,29 +470,29 @@ int main(int argc, char *argv[]) test_uncoded = atoi(optarg); break; case 'v': - ldpc_version=strdup(optarg); + ldpc_version = strdup(optarg); break; case 'h': default: - printf("CURRENTLY SUPPORTED CODE RATES: \n"); - printf("BG1 (blocklength > 3840): 1/3, 2/3, 22/25 (8/9) \n"); - printf("BG2 (blocklength <= 3840): 1/5, 1/3, 2/3 \n\n"); - printf("-h This message\n"); - printf("-q Quantization bits, Default: 8\n"); - printf("-r Nominator rate, (1, 2, 22), Default: 1\n"); - printf("-d Denominator rate, (3, 5, 25), Default: 1\n"); - printf("-l Block length (l > 3840 -> BG1, rest BG2 ), Default: 8448\n"); - printf("-G give 1 to run cuda for LDPC, Default: 0\n"); - printf("-n Number of simulation trials, Default: 1\n"); - //printf("-M MCS2 for TB 2\n"); - printf("-s SNR per information bit (EbNo) in dB, Default: -2\n"); - printf("-S Number of segments (Maximum: 8), Default: 1\n"); - printf("-t SNR simulation step, Default: 0.1\n"); - printf("-i Max decoder iterations, Default: 5\n"); - printf("-u Set SNR per coded bit, Default: 0\n"); - printf("-v XXX Set ldpc shared library version. libldpc_XXX.so will be used \n"); - exit(1); - break; + printf("CURRENTLY SUPPORTED CODE RATES: \n"); + printf("BG1 (blocklength > 3840): 1/3, 2/3, 22/25 (8/9) \n"); + printf("BG2 (blocklength <= 3840): 1/5, 1/3, 2/3 \n\n"); + printf("-h This message\n"); + printf("-q Quantization bits, Default: 8\n"); + printf("-r Nominator rate, (1, 2, 22), Default: 1\n"); + printf("-d Denominator rate, (3, 5, 25), Default: 1\n"); + printf("-l Block length (l > 3840 -> BG1, rest BG2 ), Default: 8448\n"); + printf("-G give 1 to run cuda for LDPC, Default: 0\n"); + printf("-n Number of simulation trials, Default: 1\n"); + // printf("-M MCS2 for TB 2\n"); + printf("-s SNR per information bit (EbNo) in dB, Default: -2\n"); + printf("-S Number of segments (Maximum: 8), Default: 1\n"); + printf("-t SNR simulation step, Default: 0.1\n"); + printf("-i Max decoder iterations, Default: 5\n"); + printf("-u Set SNR per coded bit, Default: 0\n"); + printf("-v XXX Set ldpc shared library version. libldpc_XXX.so will be used \n"); + exit(1); + break; } //printf("the decoder supports BG2, Kb=10, Z=128 & 256\n"); //printf(" range of blocklength: 1201 -> 1280, 2401 -> 2560\n"); @@ -539,48 +500,13 @@ int main(int argc, char *argv[]) printf("n_trials %d: \n", n_trials); printf("SNR0 %f: \n", SNR0); - load_nrLDPClib(ldpc_version); - load_nrLDPClib_ref("_orig", &encoder_orig); + load_LDPClib(ldpc_version, &ldpc_toCompare); + load_LDPClib("_orig", &ldpc_orig); //for (block_length=8;block_length<=MAX_BLOCK_LENGTH;block_length+=8) - - //determine number of bits in codeword - if (block_length>3840) - { - BG = 1; - Kb = 22; - //nrows=46; //parity check bits - //ncols=22; //info bits - } - else if (block_length<=3840) - { - BG = 2; - //nrows=42; //parity check bits - //ncols=10; // info bits - - if (block_length>640) - Kb = 10; - else if (block_length>560) - Kb = 9; - else if (block_length>192) - Kb = 8; - else - Kb = 6; - } - //find minimum value in all sets of lifting size Zc=0; - for (i1=0; i1 < 51; i1++) - { - if (lift_size[i1] >= (double) block_length/Kb) - { - Zc = lift_size[i1]; - //printf("%d\n",Zc); - break; - } - } - char fname[200]; sprintf(fname,"ldpctest_BG_%d_Zc_%d_rate_%d-%d_block_length_%d_maxit_%d.txt",BG,Zc,nom_rate,denom_rate,block_length, max_iterations); FILE *fd=fopen(fname,"w"); @@ -588,75 +514,72 @@ int main(int argc, char *argv[]) fprintf(fd,"SNR BLER BER UNCODED_BER ENCODER_MEAN ENCODER_STD ENCODER_MAX DECODER_TIME_MEAN DECODER_TIME_STD DECODER_TIME_MAX DECODER_ITER_MEAN DECODER_ITER_STD DECODER_ITER_MAX\n"); - for (SNR=SNR0;SNRdiff/time_optim->trials/1000.0/get_cpu_freq_GHz()); - printf("Encoding time std: %15.3f us\n",sqrt((double)time_optim->diff_square/time_optim->trials/pow(1000,2)/pow(get_cpu_freq_GHz(),2)-pow((double)time_optim->diff/time_optim->trials/1000.0/get_cpu_freq_GHz(),2))); - printf("Encoding time max: %15.3f us\n",(double)time_optim->max/1000.0/get_cpu_freq_GHz()); + printf("Encoding time mean: %15.3f us\n",(double)res.time_optim.diff/res.time_optim.trials/1000.0/get_cpu_freq_GHz()); + printf("Encoding time std: %15.3f us\n",sqrt((double)res.time_optim.diff_square/res.time_optim.trials/pow(1000,2)/pow(get_cpu_freq_GHz(),2)-pow((double)res.time_optim.diff/res.time_optim.trials/1000.0/get_cpu_freq_GHz(),2))); + printf("Encoding time max: %15.3f us\n",(double)res.time_optim.max/1000.0/get_cpu_freq_GHz()); printf("\n"); - printf("Decoding time mean: %15.3f us\n",(double)time_decoder->diff/time_decoder->trials/1000.0/get_cpu_freq_GHz()); - printf("Decoding time std: %15.3f us\n",sqrt((double)time_decoder->diff_square/time_decoder->trials/pow(1000,2)/pow(get_cpu_freq_GHz(),2)-pow((double)time_decoder->diff/time_decoder->trials/1000.0/get_cpu_freq_GHz(),2))); - printf("Decoding time max: %15.3f us\n",(double)time_decoder->max/1000.0/get_cpu_freq_GHz()); + printf("Decoding time mean: %15.3f us\n",(double)res.time_decoder.diff/res.time_decoder.trials/1000.0/get_cpu_freq_GHz()); + printf("Decoding time std: %15.3f us\n",sqrt((double)res.time_decoder.diff_square/res.time_decoder.trials/pow(1000,2)/pow(get_cpu_freq_GHz(),2)-pow((double)res.time_decoder.diff/res.time_decoder.trials/1000.0/get_cpu_freq_GHz(),2))); + printf("Decoding time max: %15.3f us\n",(double)res.time_decoder.max/1000.0/get_cpu_freq_GHz()); - fprintf(fd,"%f %f %f %f %f %f %f %f %f %f %f %f %d \n", - SNR, - (double)decoded_errors[i]/(double)n_trials , - (double)errors_bit/(double)n_trials/(double)block_length/(double)n_segments , - errors_bit_uncoded/(double)n_trials/(double)n_segments , - (double)time_optim->diff/time_optim->trials/1000.0/get_cpu_freq_GHz(), - sqrt((double)time_optim->diff_square/time_optim->trials/pow(1000,2)/pow(get_cpu_freq_GHz(),2)-pow((double)time_optim->diff/time_optim->trials/1000.0/get_cpu_freq_GHz(),2)), - (double)time_optim->max/1000.0/get_cpu_freq_GHz(), - (double)time_decoder->diff/time_decoder->trials/1000.0/get_cpu_freq_GHz(), - sqrt((double)time_decoder->diff_square/time_decoder->trials/pow(1000,2)/pow(get_cpu_freq_GHz(),2)-pow((double)time_decoder->diff/time_decoder->trials/1000.0/get_cpu_freq_GHz(),2)), - (double)time_decoder->max/1000.0/get_cpu_freq_GHz(), - dec_iter.n_iter_mean[i], - dec_iter.n_iter_std[i], - dec_iter.n_iter_max[i] - ); + fprintf(fd, + "%f %f %f %f %f %f %f %f %f %f %f %f %d \n", + SNR, + (double)decoded_errors[i] / (double)n_trials, + (double)res.errors_bit / (double)n_trials / (double)block_length / (double)n_segments, + res.errors_bit_uncoded / (double)n_trials / (double)n_segments, + (double)res.time_optim.diff / res.time_optim.trials / 1000.0 / get_cpu_freq_GHz(), + sqrt((double)res.time_optim.diff_square / res.time_optim.trials / pow(1000, 2) / pow(get_cpu_freq_GHz(), 2) + - pow((double)res.time_optim.diff / res.time_optim.trials / 1000.0 / get_cpu_freq_GHz(), 2)), + (double)res.time_optim.max / 1000.0 / get_cpu_freq_GHz(), + (double)res.time_decoder.diff / res.time_decoder.trials / 1000.0 / get_cpu_freq_GHz(), + sqrt((double)res.time_decoder.diff_square / res.time_decoder.trials / pow(1000, 2) / pow(get_cpu_freq_GHz(), 2) + - pow((double)res.time_decoder.diff / res.time_decoder.trials / 1000.0 / get_cpu_freq_GHz(), 2)), + (double)res.time_decoder.max / 1000.0 / get_cpu_freq_GHz(), + dec_iter[i].n_iter_mean, + dec_iter[i].n_iter_std, + dec_iter[i].n_iter_max); i=i+1; - if (decoded_errors[i-1] == 0) break; - + if (decoded_errors[i - 1] == 0) + break; } fclose(fd); - LOG_M("ldpctestStats.m","SNR",&dec_iter.snr[0],i,1,7); - LOG_MM("ldpctestStats.m","BLER",&dec_iter.bler[0],i,1,7); - LOG_MM("ldpctestStats.m","BER",&dec_iter.ber[0],i,1,7); - LOG_MM("ldpctestStats.m","meanIter",&dec_iter.n_iter_mean[0],i,1,7); + LOG_M("ldpctestStats.m", "SNR", &dec_iter[0].snr, i, 1, 7); + LOG_MM("ldpctestStats.m", "BLER", &dec_iter[0].bler, i, 1, 7); + LOG_MM("ldpctestStats.m", "BER", &dec_iter[0].ber, i, 1, 7); + LOG_MM("ldpctestStats.m", "meanIter", &dec_iter[0].n_iter_mean, i, 1, 7); loader_reset(); logTerm(); diff --git a/openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_decoder.c b/openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_decoder.c index 5f56879eba..4ac8f4799e 100644 --- a/openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_decoder.c +++ b/openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_decoder.c @@ -133,14 +133,24 @@ #include "bnProc128/nrLDPC_bnProc_BG2_R23_128.h" #endif -//#define NR_LDPC_ENABLE_PARITY_CHECK //#define NR_LDPC_PROFILER_DETAIL(a) a #define NR_LDPC_PROFILER_DETAIL(a) +#include "openair1/PHY/CODING/nrLDPC_extern.h" + #ifdef NR_LDPC_DEBUG_MODE #include "nrLDPC_tools/nrLDPC_debug.h" #endif +// decoder interface +/** + \brief LDPC decoder API type definition + \param p_decParams LDPC decoder parameters + \param p_llr Input LLRs + \param p_llrOut Output vector + \param p_profiler LDPC profiler statistics +*/ + static inline uint32_t nrLDPC_decoder_core(int8_t* p_llr, int8_t* p_out, uint32_t numLLR, @@ -148,13 +158,25 @@ static inline uint32_t nrLDPC_decoder_core(int8_t* p_llr, t_nrLDPC_dec_params* p_decParams, t_nrLDPC_time_stats* p_profiler, decode_abort_t* ab); -void nrLDPC_initcall(t_nrLDPC_dec_params* p_decParams, int8_t* p_llr, int8_t* p_out) { + +int32_t LDPCinit() +{ + return 0; } -int32_t nrLDPC_decod(t_nrLDPC_dec_params* p_decParams, - int8_t* p_llr, - int8_t* p_out, - t_nrLDPC_time_stats* p_profiler, - decode_abort_t* ab) + +int32_t LDPCshutdown() +{ + return 0; +} + +int32_t LDPCdecoder(t_nrLDPC_dec_params* p_decParams, + uint8_t harq_pid, + uint8_t ulsch_id, + uint8_t C, + int8_t* p_llr, + int8_t* p_out, + t_nrLDPC_time_stats* p_profiler, + decode_abort_t* ab) { uint32_t numLLR; t_nrLDPC_lut lut; @@ -817,31 +839,30 @@ static inline uint32_t nrLDPC_decoder_core(int8_t* p_llr, #endif // Parity Check -#ifdef NR_LDPC_ENABLE_PARITY_CHECK - NR_LDPC_PROFILER_DETAIL(start_meas(&p_profiler->cnProcPc)); - if (BG == 1) - pcRes = nrLDPC_cnProcPc_BG1(p_lut, cnProcBuf, cnProcBufRes, Z); - else - pcRes = nrLDPC_cnProcPc_BG2(p_lut, cnProcBuf, cnProcBufRes, Z); - NR_LDPC_PROFILER_DETAIL(stop_meas(&p_profiler->cnProcPc)); -#else - if (numIter > 2) { - int8_t llrOut[NR_LDPC_MAX_NUM_LLR] __attribute__((aligned(64))) = {0}; - int8_t* p_llrOut = outMode == nrLDPC_outMode_LLRINT8 ? p_out : llrOut; - nrLDPC_llrRes2llrOut(p_lut, p_llrOut, llrRes, Z, BG); - if (outMode == nrLDPC_outMode_BIT) - nrLDPC_llr2bitPacked(p_out, p_llrOut, numLLR); - else // if (outMode == nrLDPC_outMode_BITINT8) - nrLDPC_llr2bit(p_out, p_llrOut, numLLR); - if (check_crc((uint8_t*)p_out, p_decParams->block_length, p_decParams->crc_type)) { - LOG_D(PHY, "Segment CRC OK, exiting LDPC decoder\n"); - break; + if (!p_decParams->check_crc) { + NR_LDPC_PROFILER_DETAIL(start_meas(&p_profiler->cnProcPc)); + if (BG == 1) + pcRes = nrLDPC_cnProcPc_BG1(p_lut, cnProcBuf, cnProcBufRes, Z); + else + pcRes = nrLDPC_cnProcPc_BG2(p_lut, cnProcBuf, cnProcBufRes, Z); + NR_LDPC_PROFILER_DETAIL(stop_meas(&p_profiler->cnProcPc)); + } else { + if (numIter > 2) { + int8_t llrOut[NR_LDPC_MAX_NUM_LLR] __attribute__((aligned(64))) = {0}; + int8_t* p_llrOut = outMode == nrLDPC_outMode_LLRINT8 ? p_out : llrOut; + nrLDPC_llrRes2llrOut(p_lut, p_llrOut, llrRes, Z, BG); + if (outMode == nrLDPC_outMode_BIT) + nrLDPC_llr2bitPacked(p_out, p_llrOut, numLLR); + else // if (outMode == nrLDPC_outMode_BITINT8) + nrLDPC_llr2bit(p_out, p_llrOut, numLLR); + if (p_decParams->check_crc((uint8_t*)p_out, p_decParams->E, p_decParams->crc_type)) { + LOG_D(PHY, "Segment CRC OK, exiting LDPC decoder\n"); + break; + } } } -#endif } -#ifdef NR_LDPC_ENABLE_PARITY_CHECK - { + if (!p_decParams->check_crc) { int8_t llrOut[NR_LDPC_MAX_NUM_LLR] __attribute__((aligned(64))) = {0}; int8_t* p_llrOut = outMode == nrLDPC_outMode_LLRINT8 ? p_out : llrOut; // Assign results from processing buffer to output @@ -856,7 +877,6 @@ static inline uint32_t nrLDPC_decoder_core(int8_t* p_llr, nrLDPC_llr2bit(p_out, p_llrOut, numLLR); NR_LDPC_PROFILER_DETAIL(stop_meas(&p_profiler->llr2bit)); } -#endif return numIter; } diff --git a/openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_decoder_CL.c b/openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_decoder_CL.c index 74b3dbb41b..bd3d6b882c 100644 --- a/openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_decoder_CL.c +++ b/openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_decoder_CL.c @@ -47,8 +47,7 @@ typedef struct{ #include #include #include -#include "PHY/CODING/nrLDPC_decoder/nrLDPC_types.h" -#include "PHY/CODING/nrLDPC_decoder/nrLDPCdecoder_defs.h" +#include "openair1/PHY/CODING/nrLDPC_extern.h" #include "assertions.h" #include "common/utils/LOG/log.h" @@ -135,9 +134,9 @@ void set_compact_BG(int Zc,short BG){ } printf("\nZc = %d BG = %d\n",Zc,BG); ocl.runtime[0].dev_h_compact1 = clCreateBuffer(ocl.runtime[0].context, CL_MEM_READ_ONLY|CL_MEM_HOST_WRITE_ONLY, memorySize_h_compact1, NULL, (cl_int *)&rt); - AssertFatal(rt == CL_SUCCESS, "Error %d creating buffer dev_h_compact1 for platform %i \n" , (int)rt, 0); + AssertFatal(rt == CL_SUCCESS, "Error %d creating buffer dev_h_compact1 for platform %i \n" , (int)rt, 0); ocl.runtime[0].dev_h_compact2 = clCreateBuffer(ocl.runtime[0].context, CL_MEM_READ_ONLY|CL_MEM_HOST_WRITE_ONLY, memorySize_h_compact2, NULL, (cl_int *)&rt); - AssertFatal(rt == CL_SUCCESS, "Error %d creating buffer dev_h_compact2 for platform %i \n" , (int)rt, 0); + AssertFatal(rt == CL_SUCCESS, "Error %d creating buffer dev_h_compact2 for platform %i \n" , (int)rt, 0); h_element *h1; h_element *h2; switch(lift_index){ @@ -328,18 +327,25 @@ int ldpc_autoinit(void) { // called by the library loader return 0; } - -void nrLDPC_initcall(t_nrLDPC_dec_params* p_decParams, int8_t* p_llr, int8_t* p_out) { - set_compact_BG(p_decParams->Z,p_decParams->BG); -// init_LLR_DMA(p_decParams, p_llr, p_out); +int32_t LDPCshutdown() +{ + return 0; } -int32_t nrLDPC_decod(t_nrLDPC_dec_params *p_decParams, - int8_t *p_llr, - int8_t *p_out, - t_nrLDPC_procBuf *p_procBuf, - t_nrLDPC_time_stats *time_decoder, - decode_abort_t *ab) +int32_t LDPCinit() +{ + // init_LLR_DMA(p_decParams, p_llr, p_out); + return 0; +} + +int32_t LDPCdecoder(t_nrLDPC_dec_params *p_decParams, + uint8_t harq_pid, + uint8_t ulsch_id, + uint8_t C, + int8_t *p_llr, + int8_t *p_out, + t_nrLDPC_time_stats *time_decoder, + decode_abort_t *ab) { uint16_t Zc = p_decParams->Z; uint8_t BG = p_decParams->BG; @@ -362,12 +368,14 @@ int32_t nrLDPC_decod(t_nrLDPC_dec_params *p_decParams, int memorySize_llr = col * Zc * sizeof(char) * MC; // cudaCheck( cudaMemcpyToSymbol(dev_const_llr, p_llr, memorySize_llr_cuda) ); // cudaCheck( cudaMemcpyToSymbol(dev_llr, p_llr, memorySize_llr_cuda) ); - int rt = clEnqueueWriteBuffer(ocl.runtime[0].queue[0], ocl.runtime[0].dev_const_llr, CL_TRUE, 0, - memorySize_llr, p_llr, 0, NULL, NULL); - AssertFatal(rt == CL_SUCCESS, "Error %d moving p_llr data to read only memory in pltf %i dev %i\n" , (int)rt, 0,0); + set_compact_BG(p_decParams->Z, p_decParams->BG); + + int rt = + clEnqueueWriteBuffer(ocl.runtime[0].queue[0], ocl.runtime[0].dev_const_llr, CL_TRUE, 0, memorySize_llr, p_llr, 0, NULL, NULL); + AssertFatal(rt == CL_SUCCESS, "Error %d moving p_llr data to read only memory in pltf %i dev %i\n" , (int)rt, 0,0); rt = clEnqueueWriteBuffer(ocl.runtime[0].queue[0], ocl.runtime[0].dev_llr, CL_TRUE, 0, memorySize_llr, p_llr, 0, NULL, NULL); - AssertFatal(rt == CL_SUCCESS, "Error %d moving p_llr data to read-write memory in pltf %i dev %i\n" , (int)rt, 0,0); + AssertFatal(rt == CL_SUCCESS, "Error %d moving p_llr data to read-write memory in pltf %i dev %i\n" , (int)rt, 0,0); // Define CUDA kernel dimension // int blockSizeX = Zc; // dim3 dimGridKernel1(row, MC, 1); // dim of the thread blocks diff --git a/openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_decoder_offload.c b/openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_decoder_offload.c index f9137e522c..a77fdfc2f7 100644 --- a/openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_decoder_offload.c +++ b/openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_decoder_offload.c @@ -4,7 +4,7 @@ /*!\file nrLDPC_decoder_offload.c * \brief Defines the LDPC decoder - * \author openairinterface + * \author openairinterface * \date 12-06-2021 * \version 1.0 * \note: based on testbbdev test_bbdev_perf.c functions. Harq buffer offset added. @@ -27,6 +27,8 @@ #include "nrLDPC_tools/nrLDPC_debug.h" #endif +#include "openair1/PHY/CODING/nrLDPC_extern.h" + #include #include #include @@ -38,6 +40,7 @@ #include #include #include +#include #include "nrLDPC_offload.h" #include @@ -50,36 +53,10 @@ #include #include +// this socket is the NUMA socket, so the hardware CPU id (numa is complex) #define GET_SOCKET(socket_id) (((socket_id) == SOCKET_ID_ANY) ? 0 : (socket_id)) -#define MAX_QUEUES RTE_MAX_LCORE -#define TEST_REPETITIONS 1 - -#ifdef RTE_LIBRTE_PMD_BBDEV_FPGA_LTE_FEC -#include -#define FPGA_LTE_PF_DRIVER_NAME ("intel_fpga_lte_fec_pf") -#define FPGA_LTE_VF_DRIVER_NAME ("intel_fpga_lte_fec_vf") -#define VF_UL_4G_QUEUE_VALUE 4 -#define VF_DL_4G_QUEUE_VALUE 4 -#define UL_4G_BANDWIDTH 3 -#define DL_4G_BANDWIDTH 3 -#define UL_4G_LOAD_BALANCE 128 -#define DL_4G_LOAD_BALANCE 128 -#define FLR_4G_TIMEOUT 610 -#endif - -#ifdef RTE_LIBRTE_PMD_BBDEV_FPGA_5GNR_FEC -#include -#define FPGA_5GNR_PF_DRIVER_NAME ("intel_fpga_5gnr_fec_pf") -#define FPGA_5GNR_VF_DRIVER_NAME ("intel_fpga_5gnr_fec_vf") -#define VF_UL_5G_QUEUE_VALUE 4 -#define VF_DL_5G_QUEUE_VALUE 4 -#define UL_5G_BANDWIDTH 3 -#define DL_5G_BANDWIDTH 3 -#define UL_5G_LOAD_BALANCE 128 -#define DL_5G_LOAD_BALANCE 128 -#define FLR_5G_TIMEOUT 610 -#endif +#define MAX_QUEUES 16 #define OPS_CACHE_SIZE 256U #define OPS_POOL_SIZE_MIN 511U /* 0.5K per queue */ @@ -87,1119 +64,738 @@ #define SYNC_WAIT 0 #define SYNC_START 1 #define INVALID_OPAQUE -1 - +#define TIME_OUT_POLL 1e8 #define INVALID_QUEUE_ID -1 /* Increment for next code block in external HARQ memory */ #define HARQ_INCR 32768 /* Headroom for filler LLRs insertion in HARQ buffer */ #define FILLER_HEADROOM 1024 -/* Switch between PMD and Interrupt for throughput TC */ -static bool intr_enabled; +pthread_mutex_t encode_mutex; +pthread_mutex_t decode_mutex; + +const char *typeStr[] = { + "RTE_BBDEV_OP_NONE", /**< Dummy operation that does nothing */ + "RTE_BBDEV_OP_TURBO_DEC", /**< Turbo decode */ + "RTE_BBDEV_OP_TURBO_ENC", /**< Turbo encode */ + "RTE_BBDEV_OP_LDPC_DEC", /**< LDPC decode */ + "RTE_BBDEV_OP_LDPC_ENC", /**< LDPC encode */ + "RTE_BBDEV_OP_TYPE_COUNT", /**< Count of different op types */ +}; /* Represents tested active devices */ struct active_device { - const char *driver_name; - uint8_t dev_id; - uint16_t supported_ops; - uint16_t queue_ids[MAX_QUEUES]; - uint16_t nb_queues; - struct rte_mempool *ops_mempool; - struct rte_mempool *in_mbuf_pool; - struct rte_mempool *hard_out_mbuf_pool; - struct rte_mempool *soft_out_mbuf_pool; - struct rte_mempool *harq_in_mbuf_pool; - struct rte_mempool *harq_out_mbuf_pool; + const char *driver_name; + uint8_t dev_id; + int dec_queue; + int enc_queue; + uint16_t queue_ids[MAX_QUEUES]; + uint16_t nb_queues; + struct rte_mempool *bbdev_dec_op_pool; + struct rte_mempool *bbdev_enc_op_pool; + struct rte_mempool *in_mbuf_pool; + struct rte_mempool *hard_out_mbuf_pool; + struct rte_mempool *soft_out_mbuf_pool; + struct rte_mempool *harq_in_mbuf_pool; + struct rte_mempool *harq_out_mbuf_pool; } active_devs[RTE_BBDEV_MAX_DEVS]; - -static uint8_t nb_active_devs; +static int nb_active_devs; /* Data buffers used by BBDEV ops */ struct test_buffers { - struct rte_bbdev_op_data *inputs; - struct rte_bbdev_op_data *hard_outputs; - struct rte_bbdev_op_data *soft_outputs; - struct rte_bbdev_op_data *harq_inputs; - struct rte_bbdev_op_data *harq_outputs; + struct rte_bbdev_op_data *inputs; + struct rte_bbdev_op_data *hard_outputs; + struct rte_bbdev_op_data *soft_outputs; + struct rte_bbdev_op_data *harq_inputs; + struct rte_bbdev_op_data *harq_outputs; }; /* Operation parameters specific for given test case */ struct test_op_params { - struct rte_mempool *mp; - struct rte_bbdev_dec_op *ref_dec_op; - struct rte_bbdev_enc_op *ref_enc_op; - uint16_t burst_sz; - uint16_t num_to_process; - uint16_t num_lcores; - int vector_mask; - rte_atomic16_t sync; - struct test_buffers q_bufs[RTE_MAX_NUMA_NODES][MAX_QUEUES]; + struct rte_mempool *mp_dec; + struct rte_mempool *mp_enc; + struct rte_bbdev_dec_op *ref_dec_op; + struct rte_bbdev_enc_op *ref_enc_op; + uint16_t burst_sz; + uint16_t num_to_process; + uint16_t num_lcores; + int vector_mask; + rte_atomic16_t sync; + struct test_buffers q_bufs[RTE_MAX_NUMA_NODES][MAX_QUEUES]; }; /* Contains per lcore params */ struct thread_params { - uint8_t dev_id; - uint16_t queue_id; - uint32_t lcore_id; - uint64_t start_time; - double ops_per_sec; - double mbps; - uint8_t iter_count; - double iter_average; - double bler; - struct nrLDPCoffload_params *p_offloadParams; - int8_t* p_out; - uint8_t r; - uint8_t harq_pid; - uint8_t ulsch_id; - rte_atomic16_t nb_dequeued; - rte_atomic16_t processing_status; - rte_atomic16_t burst_sz; - struct test_op_params *op_params; - struct rte_bbdev_dec_op *dec_ops[MAX_BURST]; - struct rte_bbdev_enc_op *enc_ops[MAX_BURST]; + uint8_t dev_id; + uint16_t queue_id; + uint32_t lcore_id; + uint64_t start_time; + double ops_per_sec; + double mbps; + uint8_t iter_count; + double iter_average; + double bler; + struct nrLDPCoffload_params *p_offloadParams; + uint8_t *p_out; + uint8_t r; + uint8_t harq_pid; + uint8_t ulsch_id; + rte_atomic16_t nb_dequeued; + rte_atomic16_t processing_status; + rte_atomic16_t burst_sz; + struct test_op_params *op_params; + struct rte_bbdev_dec_op *dec_ops[MAX_BURST]; + struct rte_bbdev_enc_op *enc_ops[MAX_BURST]; }; -#ifdef RTE_BBDEV_OFFLOAD_COST -/* Stores time statistics */ -struct test_time_stats { - /* Stores software enqueue total working time */ - uint64_t enq_sw_total_time; - /* Stores minimum value of software enqueue working time */ - uint64_t enq_sw_min_time; - /* Stores maximum value of software enqueue working time */ - uint64_t enq_sw_max_time; - /* Stores turbo enqueue total working time */ - uint64_t enq_acc_total_time; - /* Stores minimum value of accelerator enqueue working time */ - uint64_t enq_acc_min_time; - /* Stores maximum value of accelerator enqueue working time */ - uint64_t enq_acc_max_time; - /* Stores dequeue total working time */ - uint64_t deq_total_time; - /* Stores minimum value of dequeue working time */ - uint64_t deq_min_time; - /* Stores maximum value of dequeue working time */ - uint64_t deq_max_time; -}; -#endif - -typedef int (test_case_function)(struct active_device *ad, - struct test_op_params *op_params); - +// DPDK BBDEV copy static inline void mbuf_reset(struct rte_mbuf *m) { - m->pkt_len = 0; + m->pkt_len = 0; - do { - m->data_len = 0; - m = m->next; - } while (m != NULL); + do { + m->data_len = 0; + m = m->next; + } while (m != NULL); } /* Read flag value 0/1 from bitmap */ +// DPDK BBDEV copy static inline bool check_bit(uint32_t bitmap, uint32_t bitmask) { - return bitmap & bitmask; -} - -static inline void -set_avail_op(struct active_device *ad, enum rte_bbdev_op_type op_type) -{ - ad->supported_ops |= (1 << op_type); -} - -static inline bool -is_avail_op(struct active_device *ad, enum rte_bbdev_op_type op_type) -{ - return ad->supported_ops & (1 << op_type); -} - -static inline bool -flags_match(uint32_t flags_req, uint32_t flags_present) -{ - return (flags_req & flags_present) == flags_req; -} - - -static int -check_dev_cap(const struct rte_bbdev_info *dev_info) -{ - unsigned int i; - const struct rte_bbdev_op_cap *op_cap = dev_info->drv.capabilities; - - for (i = 0; op_cap->type != RTE_BBDEV_OP_NONE; ++i, ++op_cap) { - if (op_cap->type != RTE_BBDEV_OP_LDPC_DEC) - continue; - - if (op_cap->type == RTE_BBDEV_OP_LDPC_DEC) { - const struct rte_bbdev_op_cap_ldpc_dec *cap = - &op_cap->cap.ldpc_dec; - - if (!flags_match(RTE_BBDEV_LDPC_ITERATION_STOP_ENABLE, - cap->capability_flags)){ - printf("Flag Mismatch\n"); - return TEST_FAILED; - } - return TEST_SUCCESS; - } - } - - return TEST_FAILED; + return bitmap & bitmask; } /* calculates optimal mempool size not smaller than the val */ +// DPDK BBDEV copy static unsigned int optimal_mempool_size(unsigned int val) { - return rte_align32pow2(val + 1) - 1; + return rte_align32pow2(val + 1) - 1; } -/* allocates mbuf mempool for inputs and outputs */ -static struct rte_mempool * -create_mbuf_pool(uint32_t length, uint8_t dev_id, - int socket_id, unsigned int mbuf_pool_size, - const char *op_type_str) +// DPDK BBDEV modified - sizes passed to the function, use of data_len and nb_segments, remove code related to Soft outputs, HARQ +// inputs, HARQ outputs +static int create_mempools(struct active_device *ad, int socket_id, uint16_t num_ops, int out_buff_sz, int in_max_sz) { - uint32_t max_seg_sz = 0; - char pool_name[RTE_MEMPOOL_NAMESIZE]; + unsigned int ops_pool_size, mbuf_pool_size, data_room_size = 0; + uint8_t nb_segments = 1; + ops_pool_size = optimal_mempool_size(RTE_MAX( + /* Ops used plus 1 reference op */ + RTE_MAX((unsigned int)(ad->nb_queues * num_ops + 1), + /* Minimal cache size plus 1 reference op */ + (unsigned int)(1.5 * rte_lcore_count() * OPS_CACHE_SIZE + 1)), + OPS_POOL_SIZE_MIN)); - /* find max input segment size */ - //for (i = 0; i < entries->nb_segments; ++i) - if (length > max_seg_sz) - max_seg_sz = length; + /* Decoder ops mempool */ + ad->bbdev_dec_op_pool = rte_bbdev_op_pool_create("bbdev_op_pool_dec", RTE_BBDEV_OP_LDPC_DEC, + /* Encoder ops mempool */ ops_pool_size, OPS_CACHE_SIZE, socket_id); + ad->bbdev_enc_op_pool = rte_bbdev_op_pool_create("bbdev_op_pool_enc", RTE_BBDEV_OP_LDPC_ENC, + ops_pool_size, OPS_CACHE_SIZE, socket_id); - snprintf(pool_name, sizeof(pool_name), "%s_pool_%u", op_type_str, - dev_id); - return rte_pktmbuf_pool_create(pool_name, mbuf_pool_size, 0, 0, - RTE_MAX(max_seg_sz + RTE_PKTMBUF_HEADROOM - + FILLER_HEADROOM, - (unsigned int)RTE_MBUF_DEFAULT_BUF_SIZE), socket_id); + if ((ad->bbdev_dec_op_pool == NULL) || (ad->bbdev_enc_op_pool == NULL)) + TEST_ASSERT_NOT_NULL(NULL, "ERROR Failed to create %u items ops pool for dev %u on socket %d.", + ops_pool_size, ad->dev_id, socket_id); + + /* Inputs */ + mbuf_pool_size = optimal_mempool_size(ops_pool_size * nb_segments); + data_room_size = RTE_MAX(in_max_sz + RTE_PKTMBUF_HEADROOM + FILLER_HEADROOM, (unsigned int)RTE_MBUF_DEFAULT_BUF_SIZE); + ad->in_mbuf_pool = rte_pktmbuf_pool_create("in_mbuf_pool", mbuf_pool_size, 0, 0, data_room_size, socket_id); + TEST_ASSERT_NOT_NULL(ad->in_mbuf_pool, + "ERROR Failed to create %u items input pktmbuf pool for dev %u on socket %d.", + mbuf_pool_size, ad->dev_id, socket_id); + + /* Hard outputs */ + data_room_size = RTE_MAX(out_buff_sz + RTE_PKTMBUF_HEADROOM + FILLER_HEADROOM, (unsigned int)RTE_MBUF_DEFAULT_BUF_SIZE); + ad->hard_out_mbuf_pool = rte_pktmbuf_pool_create("hard_out_mbuf_pool", mbuf_pool_size, 0, 0, data_room_size, socket_id); + TEST_ASSERT_NOT_NULL(ad->hard_out_mbuf_pool, + "ERROR Failed to create %u items hard output pktmbuf pool for dev %u on socket %d.", + mbuf_pool_size, ad->dev_id, socket_id); + return 0; } -static int -create_mempools(struct active_device *ad, int socket_id, - enum rte_bbdev_op_type org_op_type, uint16_t num_ops, t_nrLDPCoffload_params *p_offloadParams) +const char *ldpcenc_flag_bitmask[] = { + /** Set for bit-level interleaver bypass on output stream. */ + "RTE_BBDEV_LDPC_INTERLEAVER_BYPASS", + /** If rate matching is to be performed */ + "RTE_BBDEV_LDPC_RATE_MATCH", + /** Set for transport block CRC-24A attach */ + "RTE_BBDEV_LDPC_CRC_24A_ATTACH", + /** Set for code block CRC-24B attach */ + "RTE_BBDEV_LDPC_CRC_24B_ATTACH", + /** Set for code block CRC-16 attach */ + "RTE_BBDEV_LDPC_CRC_16_ATTACH", + /** Set if a device supports encoder dequeue interrupts. */ + "RTE_BBDEV_LDPC_ENC_INTERRUPTS", + /** Set if a device supports scatter-gather functionality. */ + "RTE_BBDEV_LDPC_ENC_SCATTER_GATHER", + /** Set if a device supports concatenation of non byte aligned output */ + "RTE_BBDEV_LDPC_ENC_CONCATENATION", +}; + +const char *ldpcdec_flag_bitmask[] = { + /** Set for transport block CRC-24A checking */ + "RTE_BBDEV_LDPC_CRC_TYPE_24A_CHECK", + /** Set for code block CRC-24B checking */ + "RTE_BBDEV_LDPC_CRC_TYPE_24B_CHECK", + /** Set to drop the last CRC bits decoding output */ + "RTE_BBDEV_LDPC_CRC_TYPE_24B_DROP" + /** Set for bit-level de-interleaver bypass on Rx stream. */ + "RTE_BBDEV_LDPC_DEINTERLEAVER_BYPASS", + /** Set for HARQ combined input stream enable. */ + "RTE_BBDEV_LDPC_HQ_COMBINE_IN_ENABLE", + /** Set for HARQ combined output stream enable. */ + "RTE_BBDEV_LDPC_HQ_COMBINE_OUT_ENABLE", + /** Set for LDPC decoder bypass. + * RTE_BBDEV_LDPC_HQ_COMBINE_OUT_ENABLE must be set. + */ + "RTE_BBDEV_LDPC_DECODE_BYPASS", + /** Set for soft-output stream enable */ + "RTE_BBDEV_LDPC_SOFT_OUT_ENABLE", + /** Set for Rate-Matching bypass on soft-out stream. */ + "RTE_BBDEV_LDPC_SOFT_OUT_RM_BYPASS", + /** Set for bit-level de-interleaver bypass on soft-output stream. */ + "RTE_BBDEV_LDPC_SOFT_OUT_DEINTERLEAVER_BYPASS", + /** Set for iteration stopping on successful decode condition + * i.e. a successful syndrome check. + */ + "RTE_BBDEV_LDPC_ITERATION_STOP_ENABLE", + /** Set if a device supports decoder dequeue interrupts. */ + "RTE_BBDEV_LDPC_DEC_INTERRUPTS", + /** Set if a device supports scatter-gather functionality. */ + "RTE_BBDEV_LDPC_DEC_SCATTER_GATHER", + /** Set if a device supports input/output HARQ compression. */ + "RTE_BBDEV_LDPC_HARQ_6BIT_COMPRESSION", + /** Set if a device supports input LLR compression. */ + "RTE_BBDEV_LDPC_LLR_COMPRESSION", + /** Set if a device supports HARQ input from + * device's internal memory. + */ + "RTE_BBDEV_LDPC_INTERNAL_HARQ_MEMORY_IN_ENABLE", + /** Set if a device supports HARQ output to + * device's internal memory. + */ + "RTE_BBDEV_LDPC_INTERNAL_HARQ_MEMORY_OUT_ENABLE", + /** Set if a device supports loop-back access to + * HARQ internal memory. Intended for troubleshooting. + */ + "RTE_BBDEV_LDPC_INTERNAL_HARQ_MEMORY_LOOPBACK", + /** Set if a device includes LLR filler bits in the circular buffer + * for HARQ memory. If not set, it is assumed the filler bits are not + * in HARQ memory and handled directly by the LDPC decoder. + */ + "RTE_BBDEV_LDPC_INTERNAL_HARQ_MEMORY_FILLERS", +}; + +// DPDK BBDEV modified - in DPDK this function is named add_bbdev_dev, removed code for RTE_BASEBAND_ACC100, IMO we can also remove +// RTE_LIBRTE_PMD_BBDEV_FPGA_LTE_FEC and RTE_LIBRTE_PMD_BBDEV_FPGA_5GNR_FEC - to be checked +static int add_dev(uint8_t dev_id, struct rte_bbdev_info *info) { - struct rte_mempool *mp; - unsigned int ops_pool_size, mbuf_pool_size = 0; - char pool_name[RTE_MEMPOOL_NAMESIZE]; - const char *op_type_str; - enum rte_bbdev_op_type op_type = org_op_type; - uint8_t nb_segments = 1; - uint32_t data_len; - - /* allocate ops mempool */ - ops_pool_size = optimal_mempool_size(RTE_MAX( - /* Ops used plus 1 reference op */ - RTE_MAX((unsigned int)(ad->nb_queues * num_ops + 1), - /* Minimal cache size plus 1 reference op */ - (unsigned int)(1.5 * rte_lcore_count() * - OPS_CACHE_SIZE + 1)), - OPS_POOL_SIZE_MIN)); + int ret; + struct active_device *ad = &active_devs[nb_active_devs]; + unsigned int nb_queues; + nb_queues = RTE_MIN(rte_lcore_count(), info->drv.max_num_queues); + nb_queues = RTE_MIN(nb_queues, (unsigned int)MAX_QUEUES); - if (org_op_type == RTE_BBDEV_OP_NONE) - op_type = RTE_BBDEV_OP_TURBO_ENC; + /* Display for debug the capabilities of the card */ + for (int i = 0; info->drv.capabilities[i].type != RTE_BBDEV_OP_NONE; i++) { + printf("device: %d, capability[%d]=%s\n", dev_id, i, typeStr[info->drv.capabilities[i].type]); + if (info->drv.capabilities[i].type == RTE_BBDEV_OP_LDPC_ENC) { + const struct rte_bbdev_op_cap_ldpc_enc cap = info->drv.capabilities[i].cap.ldpc_enc; + printf(" buffers: src = %d, dst = %d\n capabilites: ", cap.num_buffers_src, cap.num_buffers_dst); + for (int j = 0; j < sizeof(cap.capability_flags) * 8; j++) + if (cap.capability_flags & (1ULL << j)) + printf("%s ", ldpcenc_flag_bitmask[j]); + printf("\n"); + } + if (info->drv.capabilities[i].type == RTE_BBDEV_OP_LDPC_DEC) { + const struct rte_bbdev_op_cap_ldpc_dec cap = info->drv.capabilities[i].cap.ldpc_dec; + printf(" buffers: src = %d, hard out = %d, soft_out %d, llr size %d, llr decimals %d \n capabilities: ", + cap.num_buffers_src, + cap.num_buffers_hard_out, + cap.num_buffers_soft_out, + cap.llr_size, + cap.llr_decimals); + for (int j = 0; j < sizeof(cap.capability_flags) * 8; j++) + if (cap.capability_flags & (1ULL << j)) + printf("%s ", ldpcdec_flag_bitmask[j]); + printf("\n"); + } + } - op_type_str = rte_bbdev_op_type_str(op_type); - TEST_ASSERT_NOT_NULL(op_type_str, "Invalid op type: %u", op_type); + /* setup device */ + ret = rte_bbdev_setup_queues(dev_id, nb_queues, info->socket_id); + if (ret < 0) { + printf("rte_bbdev_setup_queues(%u, %u, %d) ret %i\n", dev_id, nb_queues, info->socket_id, ret); + return TEST_FAILED; + } - snprintf(pool_name, sizeof(pool_name), "%s_pool_%u", op_type_str, - ad->dev_id); - mp = rte_bbdev_op_pool_create(pool_name, op_type, - ops_pool_size, OPS_CACHE_SIZE, socket_id); - TEST_ASSERT_NOT_NULL(mp, - "ERROR Failed to create %u items ops pool for dev %u on socket %d.", - ops_pool_size, - ad->dev_id, - socket_id); - ad->ops_mempool = mp; + /* setup device queues */ + struct rte_bbdev_queue_conf qconf = { + .socket = info->socket_id, + .queue_size = info->drv.default_queue_conf.queue_size, + }; - /* Do not create inputs and outputs mbufs for BaseBand Null Device */ - if (org_op_type == RTE_BBDEV_OP_NONE) - return TEST_SUCCESS; - data_len = (p_offloadParams->BG==1)?(22*p_offloadParams->Z):(10*p_offloadParams->Z); - /* Inputs */ - if (nb_segments > 0) { - mbuf_pool_size = optimal_mempool_size(ops_pool_size * - nb_segments); - mp = create_mbuf_pool(p_offloadParams->E, ad->dev_id, socket_id, - mbuf_pool_size, "in"); - TEST_ASSERT_NOT_NULL(mp, - "ERROR Failed to create %u items input pktmbuf pool for dev %u on socket %d.", - mbuf_pool_size, - ad->dev_id, - socket_id); - ad->in_mbuf_pool = mp; - } - /* Hard outputs */ - if (nb_segments > 0) { - mbuf_pool_size = optimal_mempool_size(ops_pool_size * - nb_segments); - mp = create_mbuf_pool(data_len, ad->dev_id, socket_id, - mbuf_pool_size, - "hard_out"); - TEST_ASSERT_NOT_NULL(mp, - "ERROR Failed to create %u items hard output pktmbuf pool for dev %u on socket %d.", - mbuf_pool_size, - ad->dev_id, - socket_id); - ad->hard_out_mbuf_pool = mp; - } + // Search a queue linked to HW capability ldpc decoding + qconf.op_type = RTE_BBDEV_OP_LDPC_ENC; + int queue_id; + for (queue_id = 0; queue_id < nb_queues; ++queue_id) { + ret = rte_bbdev_queue_configure(dev_id, queue_id, &qconf); + if (ret == 0) { + printf("Found LDCP encoding queue (id=%u) at prio%u on dev%u\n", queue_id, qconf.priority, dev_id); + qconf.priority++; + //ret = rte_bbdev_queue_configure(ad->dev_id, queue_id, &qconf); + ad->enc_queue = queue_id; + ad->queue_ids[queue_id] = queue_id; + break; + } + } + TEST_ASSERT(queue_id != nb_queues, "ERROR Failed to configure encoding queues on dev %u", dev_id); - return TEST_SUCCESS; + // Search a queue linked to HW capability ldpc encoding + qconf.op_type = RTE_BBDEV_OP_LDPC_DEC; + for (queue_id++; queue_id < nb_queues; ++queue_id) { + ret = rte_bbdev_queue_configure(dev_id, queue_id, &qconf); + if (ret == 0) { + printf("Found LDCP decoding queue (id=%u) at prio%u on dev%u\n", queue_id, qconf.priority, dev_id); + qconf.priority++; + //ret = rte_bbdev_queue_configure(ad->dev_id, queue_id, &qconf); + ad->dec_queue = queue_id; + ad->queue_ids[queue_id] = queue_id; + break; + } + } + TEST_ASSERT(queue_id != nb_queues, "ERROR Failed to configure encoding queues on dev %u", dev_id); + ad->nb_queues = 2; + return TEST_SUCCESS; } -static int -add_dev(uint8_t dev_id, struct rte_bbdev_info *info) +// DPDK BBDEV modified - nb_segments used, we are not using struct op_data_entries *ref_entries, but struct rte_mbuf *m_head, +// rte_pktmbuf_reset(m_head) added? if ((op_type == DATA_INPUT) || (op_type == DATA_HARQ_INPUT)) -> no code in else? +static int init_op_data_objs(struct rte_bbdev_op_data *bufs, + uint8_t *input, + uint32_t data_len, + struct rte_mbuf *m_head, + struct rte_mempool *mbuf_pool, + const uint16_t n, + enum op_data_type op_type, + uint16_t min_alignment) { - int ret; - unsigned int queue_id; - struct rte_bbdev_queue_conf qconf; - struct active_device *ad = &active_devs[nb_active_devs]; - unsigned int nb_queues; - enum rte_bbdev_op_type op_type = RTE_BBDEV_OP_LDPC_DEC; + int ret; + unsigned int i, j; + bool large_input = false; + uint8_t nb_segments = 1; + for (i = 0; i < n; ++i) { + char *data; + if (data_len > RTE_BBDEV_LDPC_E_MAX_MBUF) { + /* + * Special case when DPDK mbuf cannot handle + * the required input size + */ + printf("Warning: Larger input size than DPDK mbuf %u\n", data_len); + large_input = true; + } + bufs[i].data = m_head; + bufs[i].offset = 0; + bufs[i].length = 0; -/* Configure fpga lte fec with PF & VF values - * if '-i' flag is set and using fpga device - */ -#ifdef RTE_LIBRTE_PMD_BBDEV_FPGA_LTE_FEC - if ((get_init_device() == true) && - (!strcmp(info->drv.driver_name, FPGA_LTE_PF_DRIVER_NAME))) { - struct fpga_lte_fec_conf conf; - unsigned int i; + if ((op_type == DATA_INPUT) || (op_type == DATA_HARQ_INPUT)) { + if ((op_type == DATA_INPUT) && large_input) { + /* Allocate a fake overused mbuf */ + data = rte_malloc(NULL, data_len, 0); + TEST_ASSERT_NOT_NULL(data, "rte malloc failed with %u bytes", data_len); + memcpy(data, input, data_len); + m_head->buf_addr = data; + m_head->buf_iova = rte_malloc_virt2iova(data); + m_head->data_off = 0; + m_head->data_len = data_len; + } else { + // rte_pktmbuf_reset added + rte_pktmbuf_reset(m_head); + data = rte_pktmbuf_append(m_head, data_len); - printf("Configure FPGA LTE FEC Driver %s with default values\n", - info->drv.driver_name); + TEST_ASSERT_NOT_NULL(data, "Couldn't append %u bytes to mbuf from %d data type mbuf pool", data_len, op_type); - /* clear default configuration before initialization */ - memset(&conf, 0, sizeof(struct fpga_lte_fec_conf)); + TEST_ASSERT(data == RTE_PTR_ALIGN(data, min_alignment), + "Data addr in mbuf (%p) is not aligned to device min alignment (%u)", + data, + min_alignment); + rte_memcpy(data, input, data_len); + } - /* Set PF mode : - * true if PF is used for data plane - * false for VFs - */ - conf.pf_mode_en = true; + bufs[i].length += data_len; - for (i = 0; i < FPGA_LTE_FEC_NUM_VFS; ++i) { - /* Number of UL queues per VF (fpga supports 8 VFs) */ - conf.vf_ul_queues_number[i] = VF_UL_4G_QUEUE_VALUE; - /* Number of DL queues per VF (fpga supports 8 VFs) */ - conf.vf_dl_queues_number[i] = VF_DL_4G_QUEUE_VALUE; - } + for (j = 1; j < nb_segments; ++j) { + struct rte_mbuf *m_tail = rte_pktmbuf_alloc(mbuf_pool); + TEST_ASSERT_NOT_NULL(m_tail, + "Not enough mbufs in %d data type mbuf pool (needed %d, available %u)", + op_type, + n * nb_segments, + mbuf_pool->size); - /* UL bandwidth. Needed for schedule algorithm */ - conf.ul_bandwidth = UL_4G_BANDWIDTH; - /* DL bandwidth */ - conf.dl_bandwidth = DL_4G_BANDWIDTH; + data = rte_pktmbuf_append(m_tail, data_len); + TEST_ASSERT_NOT_NULL(data, "Couldn't append %u bytes to mbuf from %d data type mbuf pool", data_len, op_type); - /* UL & DL load Balance Factor to 64 */ - conf.ul_load_balance = UL_4G_LOAD_BALANCE; - conf.dl_load_balance = DL_4G_LOAD_BALANCE; + TEST_ASSERT(data == RTE_PTR_ALIGN(data, min_alignment), + "Data addr in mbuf (%p) is not aligned to device min alignment (%u)", + data, + min_alignment); + rte_memcpy(data, input, data_len); + bufs[i].length += data_len; - /**< FLR timeout value */ - conf.flr_time_out = FLR_4G_TIMEOUT; + ret = rte_pktmbuf_chain(m_head, m_tail); + TEST_ASSERT_SUCCESS(ret, "Couldn't chain mbufs from %d data type mbuf pool", op_type); + } + } else { + /* allocate chained-mbuf for output buffer */ + /*for (j = 1; j < nb_segments; ++j) { + struct rte_mbuf *m_tail = + rte_pktmbuf_alloc(mbuf_pool); + TEST_ASSERT_NOT_NULL(m_tail, + "Not enough mbufs in %d data type mbuf pool (needed %u, available %u)", + op_type, + n * nb_segments, + mbuf_pool->size); - /* setup FPGA PF with configuration information */ - ret = fpga_lte_fec_configure(info->dev_name, &conf); - TEST_ASSERT_SUCCESS(ret, - "Failed to configure 4G FPGA PF for bbdev %s", - info->dev_name); - } -#endif -#ifdef RTE_LIBRTE_PMD_BBDEV_FPGA_5GNR_FEC - if ((get_init_device() == true) && - (!strcmp(info->drv.driver_name, FPGA_5GNR_PF_DRIVER_NAME))) { - struct fpga_5gnr_fec_conf conf; - unsigned int i; + ret = rte_pktmbuf_chain(m_head, m_tail); + TEST_ASSERT_SUCCESS(ret, + "Couldn't chain mbufs from %d data type mbuf pool", + op_type); + }*/ + } + } - printf("Configure FPGA 5GNR FEC Driver %s with default values\n", - info->drv.driver_name); - - /* clear default configuration before initialization */ - memset(&conf, 0, sizeof(struct fpga_5gnr_fec_conf)); - - /* Set PF mode : - * true if PF is used for data plane - * false for VFs - */ - conf.pf_mode_en = true; - - for (i = 0; i < FPGA_5GNR_FEC_NUM_VFS; ++i) { - /* Number of UL queues per VF (fpga supports 8 VFs) */ - conf.vf_ul_queues_number[i] = VF_UL_5G_QUEUE_VALUE; - /* Number of DL queues per VF (fpga supports 8 VFs) */ - conf.vf_dl_queues_number[i] = VF_DL_5G_QUEUE_VALUE; - } - - /* UL bandwidth. Needed for schedule algorithm */ - conf.ul_bandwidth = UL_5G_BANDWIDTH; - /* DL bandwidth */ - conf.dl_bandwidth = DL_5G_BANDWIDTH; - - /* UL & DL load Balance Factor to 64 */ - conf.ul_load_balance = UL_5G_LOAD_BALANCE; - conf.dl_load_balance = DL_5G_LOAD_BALANCE; - - /**< FLR timeout value */ - conf.flr_time_out = FLR_5G_TIMEOUT; - - /* setup FPGA PF with configuration information */ - ret = fpga_5gnr_fec_configure(info->dev_name, &conf); - TEST_ASSERT_SUCCESS(ret, - "Failed to configure 5G FPGA PF for bbdev %s", - info->dev_name); - } -#endif - nb_queues = RTE_MIN(rte_lcore_count(), info->drv.max_num_queues); - nb_queues = RTE_MIN(nb_queues, (unsigned int) MAX_QUEUES); - - /* setup device */ - ret = rte_bbdev_setup_queues(dev_id, nb_queues, info->socket_id); - if (ret < 0) { - printf("rte_bbdev_setup_queues(%u, %u, %d) ret %i\n", - dev_id, nb_queues, info->socket_id, ret); - return TEST_FAILED; - } - - /* configure interrupts if needed */ - if (intr_enabled) { - ret = rte_bbdev_intr_enable(dev_id); - if (ret < 0) { - printf("rte_bbdev_intr_enable(%u) ret %i\n", dev_id, - ret); - return TEST_FAILED; - } - } - - /* setup device queues */ - qconf.socket = info->socket_id; - qconf.queue_size = info->drv.default_queue_conf.queue_size; - qconf.priority = 0; - qconf.deferred_start = 0; - qconf.op_type = op_type; - - for (queue_id = 0; queue_id < nb_queues; ++queue_id) { - ret = rte_bbdev_queue_configure(dev_id, queue_id, &qconf); - if (ret != 0) { - printf( - "Allocated all queues (id=%u) at prio%u on dev%u\n", - queue_id, qconf.priority, dev_id); - qconf.priority++; - ret = rte_bbdev_queue_configure(ad->dev_id, queue_id, - &qconf); - } - if (ret != 0) { - printf("All queues on dev %u allocated: %u\n", - dev_id, queue_id); - break; - } - ad->queue_ids[queue_id] = queue_id; - } - TEST_ASSERT(queue_id != 0, - "ERROR Failed to configure any queues on dev %u", - dev_id); - ad->nb_queues = queue_id; - - set_avail_op(ad, op_type); - - return TEST_SUCCESS; + return 0; } -static int -add_active_device(uint8_t dev_id, struct rte_bbdev_info *info) +// DPDK BBEV copy +static int allocate_buffers_on_socket(struct rte_bbdev_op_data **buffers, const int len, const int socket) { - int ret; + int i; - active_devs[nb_active_devs].driver_name = info->drv.driver_name; - active_devs[nb_active_devs].dev_id = dev_id; + *buffers = rte_zmalloc_socket(NULL, len, 0, socket); + if (*buffers == NULL) { + printf("WARNING: Failed to allocate op_data on socket %d\n", socket); + /* try to allocate memory on other detected sockets */ + for (i = 0; i < socket; i++) { + *buffers = rte_zmalloc_socket(NULL, len, 0, i); + if (*buffers != NULL) + break; + } + } - ret = add_dev(dev_id, info); - if (ret == TEST_SUCCESS) - ++nb_active_devs; - return ret; + return (*buffers == NULL) ? TEST_FAILED : TEST_SUCCESS; } -static uint8_t -populate_active_devices(void) -{ - int ret; - uint8_t dev_id; - uint8_t nb_devs_added = 0; - struct rte_bbdev_info info; - - RTE_BBDEV_FOREACH(dev_id) { - rte_bbdev_info_get(dev_id, &info); - - if (check_dev_cap(&info)) { - printf( - "Device %d (%s) does not support specified capabilities\n", - dev_id, info.dev_name); - continue; - } - ret = add_active_device(dev_id, &info); - if (ret != 0) { - printf("Adding active bbdev %s skipped\n", - info.dev_name); - continue; - } - nb_devs_added++; - } - - return nb_devs_added; -} - -static int -device_setup(void) -{ - if (populate_active_devices() == 0) { - printf("No suitable devices found!\n"); - return TEST_SKIPPED; - } - return TEST_SUCCESS; -} - - -static void -testsuite_teardown(void) -{ - uint8_t dev_id; - /* Unconfigure devices */ - RTE_BBDEV_FOREACH(dev_id) - rte_bbdev_close(dev_id); - - /* Clear active devices structs. */ - memset(active_devs, 0, sizeof(active_devs)); - nb_active_devs = 0; - - /* Disable interrupts */ - intr_enabled = false; -} - -static int -ut_setup(void) -{ - uint8_t i, dev_id; - - for (i = 0; i < nb_active_devs; i++) { - dev_id = active_devs[i].dev_id; - /* reset bbdev stats */ - TEST_ASSERT_SUCCESS(rte_bbdev_stats_reset(dev_id), - "Failed to reset stats of bbdev %u", dev_id); - /* start the device */ - TEST_ASSERT_SUCCESS(rte_bbdev_start(dev_id), - "Failed to start bbdev %u", dev_id); - } - - return TEST_SUCCESS; -} - -static void -ut_teardown(void) -{ - uint8_t i, dev_id; - struct rte_bbdev_stats stats; - - for (i = 0; i < nb_active_devs; i++) { - dev_id = active_devs[i].dev_id; - /* read stats and print */ - rte_bbdev_stats_get(dev_id, &stats); - /* Stop the device */ - rte_bbdev_stop(dev_id); - } -} - -static int -init_op_data_objs(struct rte_bbdev_op_data *bufs, - int8_t* p_llr, uint32_t data_len, - struct rte_mbuf *m_head, - struct rte_mempool *mbuf_pool, const uint16_t n, - enum op_data_type op_type, uint16_t min_alignment) -{ - int ret; - unsigned int i, j; - bool large_input = false; - uint8_t nb_segments = 1; - //uint64_t start_time=rte_rdtsc_precise(); - //uint64_t start_time1; //=rte_rdtsc_precise(); - //uint64_t total_time=0, total_time1=0; - - for (i = 0; i < n; ++i) { - char *data; - - if (data_len > RTE_BBDEV_LDPC_E_MAX_MBUF) { - /* - * Special case when DPDK mbuf cannot handle - * the required input size - */ - printf("Warning: Larger input size than DPDK mbuf %u\n", - data_len); - large_input = true; - } - bufs[i].data = m_head; - bufs[i].offset = 0; - bufs[i].length = 0; - - if ((op_type == DATA_INPUT) || (op_type == DATA_HARQ_INPUT)) { - if ((op_type == DATA_INPUT) && large_input) { - /* Allocate a fake overused mbuf */ - data = rte_malloc(NULL, data_len, 0); - memcpy(data, p_llr, data_len); - m_head->buf_addr = data; - m_head->buf_iova = rte_malloc_virt2iova(data); - m_head->data_off = 0; - m_head->data_len = data_len; - } else { - - rte_pktmbuf_reset(m_head); - data = rte_pktmbuf_append(m_head, data_len); - - /*total_time = rte_rdtsc_precise() - start_time; - - if (total_time > 10*3000) - LOG_E(PHY," init op first: %u\n",(uint) (total_time/3000)); - - start_time1 = rte_rdtsc_precise(); - - */ - TEST_ASSERT_NOT_NULL(data, - "Couldn't append %u bytes to mbuf from %d data type mbuf pool", - data_len, op_type); - - TEST_ASSERT(data == RTE_PTR_ALIGN( - data, min_alignment), - "Data addr in mbuf (%p) is not aligned to device min alignment (%u)", - data, min_alignment); - rte_memcpy(data, p_llr, data_len); - /*total_time1 = rte_rdtsc_precise() - start_time; - if (total_time1 > 10*3000) - LOG_E(PHY,"init op second: %u\n",(uint) (total_time1/3000));*/ - } - - bufs[i].length += data_len; - - for (j = 1; j < nb_segments; ++j) { - struct rte_mbuf *m_tail = - rte_pktmbuf_alloc(mbuf_pool); - TEST_ASSERT_NOT_NULL(m_tail, - "Not enough mbufs in %d data type mbuf pool (needed %d, available %u)", - op_type, - n * nb_segments, - mbuf_pool->size); - //seg += 1; - - data = rte_pktmbuf_append(m_tail, data_len); - TEST_ASSERT_NOT_NULL(data, - "Couldn't append %u bytes to mbuf from %d data type mbuf pool", - data_len, op_type); - - TEST_ASSERT(data == RTE_PTR_ALIGN(data, - min_alignment), - "Data addr in mbuf (%p) is not aligned to device min alignment (%u)", - data, min_alignment); - rte_memcpy(data, p_llr, data_len); - bufs[i].length += data_len; - - ret = rte_pktmbuf_chain(m_head, m_tail); - TEST_ASSERT_SUCCESS(ret, - "Couldn't chain mbufs from %d data type mbuf pool", - op_type); - } - } else { - - /* allocate chained-mbuf for output buffer */ - /*for (j = 1; j < nb_segments; ++j) { - struct rte_mbuf *m_tail = - rte_pktmbuf_alloc(mbuf_pool); - TEST_ASSERT_NOT_NULL(m_tail, - "Not enough mbufs in %d data type mbuf pool (needed %u, available %u)", - op_type, - n * nb_segments, - mbuf_pool->size); - - ret = rte_pktmbuf_chain(m_head, m_tail); - TEST_ASSERT_SUCCESS(ret, - "Couldn't chain mbufs from %d data type mbuf pool", - op_type); - }*/ - } - } - - return 0; -} - -static int -allocate_buffers_on_socket(struct rte_bbdev_op_data **buffers, const int len, - const int socket) -{ - int i; - - *buffers = rte_zmalloc_socket(NULL, len, 0, socket); - if (*buffers == NULL) { - printf("WARNING: Failed to allocate op_data on socket %d\n", - socket); - /* try to allocate memory on other detected sockets */ - for (i = 0; i < socket; i++) { - *buffers = rte_zmalloc_socket(NULL, len, 0, i); - if (*buffers != NULL) - break; - } - } - - return (*buffers == NULL) ? TEST_FAILED : TEST_SUCCESS; -} - - - +// DPDK BBDEV copy static void free_buffers(struct active_device *ad, struct test_op_params *op_params) { - unsigned int i, j; + rte_mempool_free(ad->bbdev_dec_op_pool); + rte_mempool_free(ad->bbdev_enc_op_pool); + rte_mempool_free(ad->in_mbuf_pool); + rte_mempool_free(ad->hard_out_mbuf_pool); + rte_mempool_free(ad->soft_out_mbuf_pool); + rte_mempool_free(ad->harq_in_mbuf_pool); + rte_mempool_free(ad->harq_out_mbuf_pool); - rte_mempool_free(ad->ops_mempool); - rte_mempool_free(ad->in_mbuf_pool); - rte_mempool_free(ad->hard_out_mbuf_pool); - rte_mempool_free(ad->soft_out_mbuf_pool); - rte_mempool_free(ad->harq_in_mbuf_pool); - rte_mempool_free(ad->harq_out_mbuf_pool); - - for (i = 0; i < rte_lcore_count(); ++i) { - for (j = 0; j < RTE_MAX_NUMA_NODES; ++j) { - rte_free(op_params->q_bufs[j][i].inputs); - rte_free(op_params->q_bufs[j][i].hard_outputs); - rte_free(op_params->q_bufs[j][i].soft_outputs); - rte_free(op_params->q_bufs[j][i].harq_inputs); - rte_free(op_params->q_bufs[j][i].harq_outputs); - } - } -} - - - -static inline double -maxstar(double A, double B) -{ - if (fabs(A - B) > 5) - return RTE_MAX(A, B); - else - return RTE_MAX(A, B) + log1p(exp(-fabs(A - B))); + for (int i = 0; i < rte_lcore_count(); ++i) { + for (int j = 0; j < RTE_MAX_NUMA_NODES; ++j) { + rte_free(op_params->q_bufs[j][i].inputs); + rte_free(op_params->q_bufs[j][i].hard_outputs); + rte_free(op_params->q_bufs[j][i].soft_outputs); + rte_free(op_params->q_bufs[j][i].harq_inputs); + rte_free(op_params->q_bufs[j][i].harq_outputs); + } + } } +// OAI / DPDK BBDEV modified - in DPDK named copy_reference_dec_op, here we are passing t_nrLDPCoffload_params *p_offloadParams to +// the function, check what is value of n, commented code for code block mode static void set_ldpc_dec_op(struct rte_bbdev_dec_op **ops, unsigned int n, unsigned int start_idx, - struct rte_bbdev_op_data *inputs, - struct rte_bbdev_op_data *hard_outputs, - struct rte_bbdev_op_data *soft_outputs, - struct rte_bbdev_op_data *harq_inputs, - struct rte_bbdev_op_data *harq_outputs, + struct test_buffers *bufs, struct rte_bbdev_dec_op *ref_op, uint8_t r, uint8_t harq_pid, uint8_t ulsch_id, t_nrLDPCoffload_params *p_offloadParams) { - unsigned int i; - //struct rte_bbdev_op_ldpc_dec *ldpc_dec = &ref_op->ldpc_dec; - for (i = 0; i < n; ++i) { - /* if (ldpc_dec->code_block_mode == 0) { - ops[i]->ldpc_dec.tb_params.ea = - ldpc_dec->tb_params.ea; - ops[i]->ldpc_dec.tb_params.eb = - ldpc_dec->tb_params.eb; - ops[i]->ldpc_dec.tb_params.c = - ldpc_dec->tb_params.c; - ops[i]->ldpc_dec.tb_params.cab = - ldpc_dec->tb_params.cab; - ops[i]->ldpc_dec.tb_params.r = - ldpc_dec->tb_params.r; - printf("code block ea %d eb %d c %d cab %d r %d\n",ldpc_dec->tb_params.ea,ldpc_dec->tb_params.eb,ldpc_dec->tb_params.c, ldpc_dec->tb_params.cab, ldpc_dec->tb_params.r); - } else { */ - ops[i]->ldpc_dec.cb_params.e = p_offloadParams->E; - //} - - ops[i]->ldpc_dec.basegraph = p_offloadParams->BG; - ops[i]->ldpc_dec.z_c = p_offloadParams->Z; - ops[i]->ldpc_dec.q_m = p_offloadParams->Qm; - ops[i]->ldpc_dec.n_filler = p_offloadParams->F; - ops[i]->ldpc_dec.n_cb = p_offloadParams->n_cb; - ops[i]->ldpc_dec.iter_max = 20; - ops[i]->ldpc_dec.rv_index = p_offloadParams->rv; - ops[i]->ldpc_dec.op_flags = RTE_BBDEV_LDPC_ITERATION_STOP_ENABLE|RTE_BBDEV_LDPC_INTERNAL_HARQ_MEMORY_IN_ENABLE|RTE_BBDEV_LDPC_INTERNAL_HARQ_MEMORY_OUT_ENABLE; //|RTE_BBDEV_LDPC_CRC_TYPE_24B_DROP; - ops[i]->ldpc_dec.code_block_mode = 1; //ldpc_dec->code_block_mode; - //printf("set ldpc ulsch_id %d\n",ulsch_id); - ops[i]->ldpc_dec.harq_combined_input.offset = ulsch_id*(32*1024*1024)+harq_pid*(2*1024*1024)+r*(1024*32); - ops[i]->ldpc_dec.harq_combined_output.offset = ulsch_id*(32*1024*1024)+harq_pid*(2*1024*1024)+r*(1024*32); - - - if (hard_outputs != NULL) - ops[i]->ldpc_dec.hard_output = - hard_outputs[start_idx + i]; - if (inputs != NULL) - ops[i]->ldpc_dec.input = - inputs[start_idx + i]; - if (soft_outputs != NULL) - ops[i]->ldpc_dec.soft_output = - soft_outputs[start_idx + i]; - if (harq_inputs != NULL) - ops[i]->ldpc_dec.harq_combined_input = - harq_inputs[start_idx + i]; - if (harq_outputs != NULL) - ops[i]->ldpc_dec.harq_combined_output = - harq_outputs[start_idx + i]; - - } + unsigned int i; + for (i = 0; i < n; ++i) { + ops[i]->ldpc_dec.cb_params.e = p_offloadParams->E; + ops[i]->ldpc_dec.basegraph = p_offloadParams->BG; + ops[i]->ldpc_dec.z_c = p_offloadParams->Z; + ops[i]->ldpc_dec.q_m = p_offloadParams->Qm; + ops[i]->ldpc_dec.n_filler = p_offloadParams->F; + ops[i]->ldpc_dec.n_cb = p_offloadParams->n_cb; + ops[i]->ldpc_dec.iter_max = 20; + ops[i]->ldpc_dec.rv_index = p_offloadParams->rv; + ops[i]->ldpc_dec.op_flags = RTE_BBDEV_LDPC_ITERATION_STOP_ENABLE | + RTE_BBDEV_LDPC_INTERNAL_HARQ_MEMORY_IN_ENABLE | + RTE_BBDEV_LDPC_INTERNAL_HARQ_MEMORY_OUT_ENABLE | + RTE_BBDEV_LDPC_HQ_COMBINE_OUT_ENABLE; + if (p_offloadParams->setCombIn) { + ops[i]->ldpc_dec.op_flags |= RTE_BBDEV_LDPC_HQ_COMBINE_IN_ENABLE; + } + LOG_D(PHY,"ULSCH %02d HARQPID %02d R %02d COMBIN %d RV %d NCB %05d \n", ulsch_id, harq_pid, r, p_offloadParams->setCombIn, p_offloadParams->rv, p_offloadParams->n_cb); + ops[i]->ldpc_dec.code_block_mode = 1; // ldpc_dec->code_block_mode; + ops[i]->ldpc_dec.harq_combined_input.offset = ulsch_id * (32 * 1024 * 1024) + harq_pid * (2 * 1024 * 1024) + r * (1024 * 32); + ops[i]->ldpc_dec.harq_combined_output.offset = ulsch_id * (32 * 1024 * 1024) + harq_pid * (2 * 1024 * 1024) + r * (1024 * 32); + if (bufs->hard_outputs != NULL) + ops[i]->ldpc_dec.hard_output = bufs->hard_outputs[start_idx + i]; + if (bufs->inputs != NULL) + ops[i]->ldpc_dec.input = bufs->inputs[start_idx + i]; + if (bufs->soft_outputs != NULL) + ops[i]->ldpc_dec.soft_output = bufs->soft_outputs[start_idx + i]; + if (bufs->harq_inputs != NULL) + ops[i]->ldpc_dec.harq_combined_input = bufs->harq_inputs[start_idx + i]; + if (bufs->harq_outputs != NULL) + ops[i]->ldpc_dec.harq_combined_output = bufs->harq_outputs[start_idx + i]; + } } - - -/*static int -check_dec_status_and_ordering(struct rte_bbdev_dec_op *op, - unsigned int order_idx, const int expected_status) +static void set_ldpc_enc_op(struct rte_bbdev_enc_op **ops, + unsigned int n, + unsigned int start_idx, + struct rte_bbdev_op_data *inputs, + struct rte_bbdev_op_data *outputs, + struct rte_bbdev_enc_op *ref_op, + t_nrLDPCoffload_params *p_offloadParams) { - int status = op->status; - if (get_iter_max() >= 10) { - if (!(expected_status & (1 << RTE_BBDEV_SYNDROME_ERROR)) && - (status & (1 << RTE_BBDEV_SYNDROME_ERROR))) { - printf("WARNING: Ignore Syndrome Check mismatch\n"); - status -= (1 << RTE_BBDEV_SYNDROME_ERROR); - } - if ((expected_status & (1 << RTE_BBDEV_SYNDROME_ERROR)) && - !(status & (1 << RTE_BBDEV_SYNDROME_ERROR))) { - printf("WARNING: Ignore Syndrome Check mismatch\n"); - status += (1 << RTE_BBDEV_SYNDROME_ERROR); - } - } - - TEST_ASSERT(status == expected_status, - "op_status (%d) != expected_status (%d)", - op->status, expected_status); - - TEST_ASSERT((void *)(uintptr_t)order_idx == op->opaque_data, - "Ordering error, expected %p, got %p", - (void *)(uintptr_t)order_idx, op->opaque_data); - - return TEST_SUCCESS; + // struct rte_bbdev_op_ldpc_enc *ldpc_enc = &ref_op->ldpc_enc; + for (int i = 0; i < n; ++i) { + ops[i]->ldpc_enc.cb_params.e = 3 * p_offloadParams->E; // Fix mee: what is the correct size for "e" ??? + ops[i]->ldpc_enc.basegraph = p_offloadParams->BG; + ops[i]->ldpc_enc.z_c = p_offloadParams->Z; + ops[i]->ldpc_enc.q_m = p_offloadParams->Qm; + ops[i]->ldpc_enc.n_filler = p_offloadParams->F; + ops[i]->ldpc_enc.n_cb = p_offloadParams->n_cb; + ops[i]->ldpc_enc.rv_index = p_offloadParams->rv; + ops[i]->ldpc_enc.op_flags = RTE_BBDEV_LDPC_INTERLEAVER_BYPASS; // RTE_BBDEV_LDPC_RATE_MATCH; + ops[i]->ldpc_enc.code_block_mode = 1; + ops[i]->ldpc_enc.output = outputs[start_idx + i]; + ops[i]->ldpc_enc.input = inputs[start_idx + i]; + } } -static int -check_enc_status_and_ordering(struct rte_bbdev_enc_op *op, - unsigned int order_idx, const int expected_status) +// DPDK BBDEV modified - in DPDK called validate_dec_op, int8_t* p_out added, remove code related to op_data_entries, turbo_dec +// replaced by ldpc_dec, removed coderelated to soft_output, memcpy(p_out, data+m->data_off, data_len) +static int retrieve_ldpc_dec_op(struct rte_bbdev_dec_op **ops, + const uint16_t n, + struct rte_bbdev_dec_op *ref_op, + const int vector_mask, + uint8_t *p_out) { - TEST_ASSERT(op->status == expected_status, - "op_status (%d) != expected_status (%d)", - op->status, expected_status); - - if (op->opaque_data != (void *)(uintptr_t)INVALID_OPAQUE) - TEST_ASSERT((void *)(uintptr_t)order_idx == op->opaque_data, - "Ordering error, expected %p, got %p", - (void *)(uintptr_t)order_idx, op->opaque_data); - - return TEST_SUCCESS; + struct rte_bbdev_op_data *hard_output; + struct rte_mbuf *m; + unsigned int i; + char *data; + for (i = 0; i < n; ++i) { + hard_output = &ops[i]->ldpc_dec.hard_output; + m = hard_output->data; + uint16_t data_len = rte_pktmbuf_data_len(m) - hard_output->offset; + data = m->buf_addr; + memcpy(p_out, data + m->data_off, data_len); + } + return 0; } -*/ -static int -retrieve_ldpc_dec_op(struct rte_bbdev_dec_op **ops, const uint16_t n, - struct rte_bbdev_dec_op *ref_op, const int vector_mask, - int8_t* p_out) +static int retrieve_ldpc_enc_op(struct rte_bbdev_enc_op **ops, const uint16_t n, struct rte_bbdev_enc_op *ref_op, uint8_t *p_out) { - unsigned int i; - //int ret; - struct rte_bbdev_op_ldpc_dec *ops_td; - struct rte_bbdev_op_data *hard_output; - //struct rte_bbdev_op_ldpc_dec *ref_td = &ref_op->ldpc_dec; - struct rte_mbuf *m; - char *data; - - for (i = 0; i < n; ++i) { - ops_td = &ops[i]->ldpc_dec; - hard_output = &ops_td->hard_output; - m = hard_output->data; - /* ret = check_dec_status_and_ordering(ops[i], i, ref_op->status); - TEST_ASSERT_SUCCESS(ret, - "Checking status and ordering for decoder failed"); - if (vector_mask & TEST_BBDEV_VF_EXPECTED_ITER_COUNT) - TEST_ASSERT(ops_td->iter_count <= ref_td->iter_count, - "Returned iter_count (%d) > expected iter_count (%d)", - ops_td->iter_count, ref_td->iter_count); - */ - uint16_t offset = hard_output->offset; - uint16_t data_len = rte_pktmbuf_data_len(m) - offset; - - data = m->buf_addr; - memcpy(p_out, data+m->data_off, data_len); - - } - - return TEST_SUCCESS; + struct rte_bbdev_op_data *output; + struct rte_mbuf *m; + unsigned int i; + char *data; + for (i = 0; i < n; ++i) { + output = &ops[i]->ldpc_enc.output; + m = output->data; + uint16_t data_len = min((384 * 68) / 8, rte_pktmbuf_data_len(m)); // fix me + data = m->buf_addr; + for (int byte = 0; byte < data_len; byte++) + for (int bit = 0; bit < 8; bit++) + p_out[byte * 8 + bit] = (data[m->data_off + byte] >> (7 - bit)) & 1; + } + return 0; } - -/*static int -validate_ldpc_enc_op(struct rte_bbdev_enc_op **ops, const uint16_t n, - struct rte_bbdev_enc_op *ref_op) +// DPDK BBDEV copy +static int init_test_op_params(struct test_op_params *op_params, + enum rte_bbdev_op_type op_type, + struct rte_mempool *ops_mp, + uint16_t burst_sz, + uint16_t num_to_process, + uint16_t num_lcores) { - unsigned int i; - int ret; - struct op_data_entries *hard_data_orig = - &test_vector.entries[DATA_HARD_OUTPUT]; + int ret = 0; + if (op_type == RTE_BBDEV_OP_LDPC_DEC) { + ret = rte_bbdev_dec_op_alloc_bulk(ops_mp, &op_params->ref_dec_op, 1); + op_params->mp_dec = ops_mp; + } else { + ret = rte_bbdev_enc_op_alloc_bulk(ops_mp, &op_params->ref_enc_op, 1); + op_params->mp_enc = ops_mp; + } - for (i = 0; i < n; ++i) { - ret = check_enc_status_and_ordering(ops[i], i, ref_op->status); - TEST_ASSERT_SUCCESS(ret, - "Checking status and ordering for encoder failed"); - TEST_ASSERT_SUCCESS(validate_op_chain( - &ops[i]->ldpc_enc.output, - hard_data_orig), - "Output buffers (CB=%u) are not equal", - i); - } + TEST_ASSERT_SUCCESS(ret, "rte_bbdev_op_alloc_bulk() failed"); - return TEST_SUCCESS; -} -*/ - -static void -create_reference_ldpc_dec_op(struct rte_bbdev_dec_op *op, t_nrLDPCoffload_params *p_offloadParams) -{ -// unsigned int i; - - //for (i = 0; i < entry->nb_segments; ++i) - op->ldpc_dec.input.length = p_offloadParams->E; - op->ldpc_dec.basegraph = p_offloadParams->BG; - op->ldpc_dec.z_c = p_offloadParams->Z; - op->ldpc_dec.n_filler = p_offloadParams->F; - op->ldpc_dec.code_block_mode = 1; - op->ldpc_dec.op_flags = RTE_BBDEV_LDPC_ITERATION_STOP_ENABLE|RTE_BBDEV_LDPC_INTERNAL_HARQ_MEMORY_IN_ENABLE|RTE_BBDEV_LDPC_INTERNAL_HARQ_MEMORY_OUT_ENABLE|RTE_BBDEV_LDPC_CRC_TYPE_24B_DROP; -} - - - -/* -static uint32_t -calc_ldpc_dec_TB_size(struct rte_bbdev_dec_op *op) -{ - uint8_t i; - uint32_t c, r, tb_size = 0; - uint16_t sys_cols = (op->ldpc_dec.basegraph == 1) ? 22 : 10; - - if (op->ldpc_dec.code_block_mode) { - tb_size = sys_cols * op->ldpc_dec.z_c - op->ldpc_dec.n_filler; - //printf("calc tb sys cols %d tb_size %d\n",sys_cols,tb_size); - - } else { - c = op->ldpc_dec.tb_params.c; - r = op->ldpc_dec.tb_params.r; - for (i = 0; i < c-r; i++) - tb_size += sys_cols * op->ldpc_dec.z_c - - op->ldpc_dec.n_filler; - printf("calc tb c %d r %d sys cols %d tb_size %d\n",c,r,sys_cols,tb_size); - } - return tb_size; -} -*/ - -static int -init_test_op_params(struct test_op_params *op_params, - enum rte_bbdev_op_type op_type, const int expected_status, - const int vector_mask, struct rte_mempool *ops_mp, - uint16_t burst_sz, uint16_t num_to_process, uint16_t num_lcores) -{ - int ret = 0; - if (op_type == RTE_BBDEV_OP_TURBO_DEC || - op_type == RTE_BBDEV_OP_LDPC_DEC) - ret = rte_bbdev_dec_op_alloc_bulk(ops_mp, - &op_params->ref_dec_op, 1); - else - ret = rte_bbdev_enc_op_alloc_bulk(ops_mp, - &op_params->ref_enc_op, 1); - - TEST_ASSERT_SUCCESS(ret, "rte_bbdev_op_alloc_bulk() failed"); - - op_params->mp = ops_mp; - op_params->burst_sz = burst_sz; - op_params->num_to_process = num_to_process; - op_params->num_lcores = num_lcores; - op_params->vector_mask = vector_mask; - if (op_type == RTE_BBDEV_OP_TURBO_DEC || - op_type == RTE_BBDEV_OP_LDPC_DEC) - op_params->ref_dec_op->status = expected_status; - else if (op_type == RTE_BBDEV_OP_TURBO_ENC - || op_type == RTE_BBDEV_OP_LDPC_ENC) - op_params->ref_enc_op->status = expected_status; - return 0; + op_params->burst_sz = burst_sz; + op_params->num_to_process = num_to_process; + op_params->num_lcores = num_lcores; + return 0; } +// DPDK BBDEV modified - in DPDK called throughput_pmd_lcore_ldpc_dec, code related to extDdr removed static int pmd_lcore_ldpc_dec(void *arg) { - struct thread_params *tp = arg; - uint16_t enq, deq; - //uint64_t total_time = 0, start_time; - const uint16_t queue_id = tp->queue_id; - const uint16_t burst_sz = tp->op_params->burst_sz; - const uint16_t num_ops = tp->op_params->num_to_process; - struct rte_bbdev_dec_op *ops_enq[num_ops]; - struct rte_bbdev_dec_op *ops_deq[num_ops]; - struct rte_bbdev_dec_op *ref_op = tp->op_params->ref_dec_op; - uint8_t r= tp->r; - uint8_t harq_pid = tp->harq_pid; - uint8_t ulsch_id = tp->ulsch_id; - struct test_buffers *bufs = NULL; - int i, j, ret; - struct rte_bbdev_info info; - uint16_t num_to_enq; - int8_t *p_out = tp->p_out; - t_nrLDPCoffload_params *p_offloadParams = tp->p_offloadParams; - - //struct rte_bbdev_op_data *hard_output; - - //bool extDdr = check_bit(ldpc_cap_flags, - // RTE_BBDEV_LDPC_INTERNAL_HARQ_MEMORY_OUT_ENABLE); - //start_time = rte_rdtsc_precise(); - bool loopback = check_bit(ref_op->ldpc_dec.op_flags, - RTE_BBDEV_LDPC_INTERNAL_HARQ_MEMORY_LOOPBACK); - bool hc_out = check_bit(ref_op->ldpc_dec.op_flags, - RTE_BBDEV_LDPC_HQ_COMBINE_OUT_ENABLE); - - TEST_ASSERT_SUCCESS((burst_sz > MAX_BURST), - "BURST_SIZE should be <= %u", MAX_BURST); + struct thread_params *tp = arg; + uint16_t enq, deq; + const uint16_t queue_id = tp->queue_id; + const uint16_t burst_sz = tp->op_params->burst_sz; + const uint16_t num_ops = tp->op_params->num_to_process; + struct rte_bbdev_dec_op *ops_enq[num_ops]; + struct rte_bbdev_dec_op *ops_deq[num_ops]; + struct rte_bbdev_dec_op *ref_op = tp->op_params->ref_dec_op; + uint8_t r = tp->r; + uint8_t harq_pid = tp->harq_pid; + uint8_t ulsch_id = tp->ulsch_id; + struct test_buffers *bufs = NULL; + int i, j, ret; + struct rte_bbdev_info info; + uint16_t num_to_enq; + uint8_t *p_out = tp->p_out; + t_nrLDPCoffload_params *p_offloadParams = tp->p_offloadParams; - rte_bbdev_info_get(tp->dev_id, &info); + TEST_ASSERT_SUCCESS((burst_sz > MAX_BURST), "BURST_SIZE should be <= %u", MAX_BURST); + rte_bbdev_info_get(tp->dev_id, &info); - TEST_ASSERT_SUCCESS((num_ops > info.drv.queue_size_lim), - "NUM_OPS cannot exceed %u for this device", - info.drv.queue_size_lim); + bufs = &tp->op_params->q_bufs[GET_SOCKET(info.socket_id)][queue_id]; + while (rte_atomic16_read(&tp->op_params->sync) == SYNC_WAIT) + rte_pause(); + ret = rte_mempool_get_bulk(tp->op_params->mp_dec, (void **)ops_enq, num_ops); + // looks like a bbdev internal error for the free operation, workaround here + ops_enq[0]->mempool = tp->op_params->mp_dec; + // ret = rte_bbdev_dec_op_alloc_bulk(tp->op_params->mp, ops_enq, num_ops); + TEST_ASSERT_SUCCESS(ret, "Allocation failed for %d ops", num_ops); - bufs = &tp->op_params->q_bufs[GET_SOCKET(info.socket_id)][queue_id]; - - while (rte_atomic16_read(&tp->op_params->sync) == SYNC_WAIT) - rte_pause(); + set_ldpc_dec_op(ops_enq, + num_ops, + 0, + bufs, + ref_op, + r, + harq_pid, + ulsch_id, + p_offloadParams); - ret = rte_bbdev_dec_op_alloc_bulk(tp->op_params->mp, ops_enq, num_ops); - TEST_ASSERT_SUCCESS(ret, "Allocation failed for %d ops", num_ops); + /* Set counter to validate the ordering */ + for (j = 0; j < num_ops; ++j) + ops_enq[j]->opaque_data = (void *)(uintptr_t)j; - /* For throughput tests we need to disable early termination */ - if (check_bit(ref_op->ldpc_dec.op_flags, - RTE_BBDEV_LDPC_ITERATION_STOP_ENABLE)) - ref_op->ldpc_dec.op_flags -= - RTE_BBDEV_LDPC_ITERATION_STOP_ENABLE; - ref_op->ldpc_dec.iter_max = get_iter_max(); - ref_op->ldpc_dec.iter_count = ref_op->ldpc_dec.iter_max; + for (enq = 0, deq = 0; enq < num_ops;) { + num_to_enq = burst_sz; + if (unlikely(num_ops - enq < num_to_enq)) + num_to_enq = num_ops - enq; - set_ldpc_dec_op(ops_enq, num_ops, 0, bufs->inputs, - bufs->hard_outputs, bufs->soft_outputs, - bufs->harq_inputs, bufs->harq_outputs, ref_op, r, harq_pid, ulsch_id, p_offloadParams); + enq += rte_bbdev_enqueue_ldpc_dec_ops(tp->dev_id, queue_id, &ops_enq[enq], num_to_enq); + deq += rte_bbdev_dequeue_ldpc_dec_ops(tp->dev_id, queue_id, &ops_deq[deq], enq - deq); + } - /* Set counter to validate the ordering */ - for (j = 0; j < num_ops; ++j) - ops_enq[j]->opaque_data = (void *)(uintptr_t)j; + /* dequeue the remaining */ + int time_out = 0; + while (deq < enq) { + deq += rte_bbdev_dequeue_ldpc_dec_ops(tp->dev_id, queue_id, &ops_deq[deq], enq - deq); + time_out++; + DevAssert(time_out <= TIME_OUT_POLL); + } - for (i = 0; i < TEST_REPETITIONS; ++i) { - for (j = 0; j < num_ops; ++j) { - if (!loopback) - mbuf_reset( - ops_enq[j]->ldpc_dec.hard_output.data); - if (hc_out || loopback) - mbuf_reset( - ops_enq[j]->ldpc_dec.harq_combined_output.data); - } - // start_time = rte_rdtsc_precise(); + // This if statement is not in DPDK + if (deq == enq) { + tp->iter_count = 0; + /* get the max of iter_count for all dequeued ops */ + for (i = 0; i < num_ops; ++i) { + tp->iter_count = RTE_MAX(ops_enq[i]->ldpc_dec.iter_count, tp->iter_count); + } + ret = retrieve_ldpc_dec_op(ops_deq, num_ops, ref_op, tp->op_params->vector_mask, p_out); + TEST_ASSERT_SUCCESS(ret, "Validation failed!"); + } - for (enq = 0, deq = 0; enq < num_ops;) { - num_to_enq = burst_sz; + if (num_ops > 0) + rte_mempool_put_bulk(ops_enq[0]->mempool, (void **)ops_enq, num_ops); - if (unlikely(num_ops - enq < num_to_enq)) - num_to_enq = num_ops - enq; - - enq += rte_bbdev_enqueue_ldpc_dec_ops(tp->dev_id, - queue_id, &ops_enq[enq], num_to_enq); - - deq += rte_bbdev_dequeue_ldpc_dec_ops(tp->dev_id, - queue_id, &ops_deq[deq], enq - deq); - - //printf("enq %d, deq %d\n",enq,deq); - - } - - /* dequeue the remaining */ - //int trials=0; - while (deq < enq) { - deq += rte_bbdev_dequeue_ldpc_dec_ops(tp->dev_id, - queue_id, &ops_deq[deq], enq - deq); - /*usleep(10); - trials++; - if (trials>=100) { - printf("aborting decoding after 100 dequeue tries\n"); - break; - }*/ - } - - //total_time += rte_rdtsc_precise() - start_time; - } - //total_time = rte_rdtsc_precise() - start_time; - if (deq==enq) { - tp->iter_count = 0; - /* get the max of iter_count for all dequeued ops */ - for (i = 0; i < num_ops; ++i) { - tp->iter_count = RTE_MAX(ops_enq[i]->ldpc_dec.iter_count, - tp->iter_count); - } - - ret = retrieve_ldpc_dec_op(ops_deq, num_ops, ref_op, - tp->op_params->vector_mask, p_out); - TEST_ASSERT_SUCCESS(ret, "Validation failed!"); - } - else { - ret = TEST_FAILED; - } - - rte_bbdev_dec_op_free_bulk(ops_enq, num_ops); - - /*total_time = rte_rdtsc_precise() - start_time; - - if (total_time > 100*3000) - LOG_E(PHY," pmd lcore: %u\n",(uint) (total_time/3000)); - - double tb_len_bits = calc_ldpc_dec_TB_size(ref_op); - - tp->ops_per_sec = ((double)total_time / (double)rte_get_tsc_hz()); - //tp->ops_per_sec = ((double)num_ops * TEST_REPETITIONS) / - // ((double)total_time / (double)rte_get_tsc_hz()); - tp->mbps = (((double)(num_ops * TEST_REPETITIONS * tb_len_bits)) / - 1000000.0) / ((double)total_time / - (double)rte_get_tsc_hz()); - */ - return ret; + // Return the worst decoding number of iterations for all segments + return tp->iter_count; } - -/* Aggregate the performance results over the number of cores used */ -static void -print_dec_throughput(struct thread_params *t_params, unsigned int used_cores) +// DPDK BBDEV copy - in DPDK called throughput_pmd_lcore_ldpc_enc +static int pmd_lcore_ldpc_enc(void *arg) { - unsigned int core_idx = 0; - double total_mops = 0, total_mbps = 0; - uint8_t iter_count = 0; + struct thread_params *tp = arg; + uint16_t enq, deq; + const uint16_t queue_id = tp->queue_id; + const uint16_t burst_sz = tp->op_params->burst_sz; + const uint16_t num_ops = tp->op_params->num_to_process; + struct rte_bbdev_enc_op *ops_enq[num_ops]; + struct rte_bbdev_enc_op *ops_deq[num_ops]; + struct rte_bbdev_enc_op *ref_op = tp->op_params->ref_enc_op; + int j, ret; + uint16_t num_to_enq; + uint8_t *p_out = tp->p_out; + t_nrLDPCoffload_params *p_offloadParams = tp->p_offloadParams; - for (core_idx = 0; core_idx < used_cores; core_idx++) { - printf( - "Throughput for core (%u): %.8lg Ops/s, %.8lg Mbps @ max %u iterations\n", - t_params[core_idx].lcore_id, - t_params[core_idx].ops_per_sec, - t_params[core_idx].mbps, - t_params[core_idx].iter_count); - total_mops += t_params[core_idx].ops_per_sec; - total_mbps += t_params[core_idx].mbps; - iter_count = RTE_MAX(iter_count, - t_params[core_idx].iter_count); - } - printf( - "\nTotal throughput for %u cores: %.8lg MOPS, %.8lg Mbps @ max %u iterations\n", - used_cores, total_mops, total_mbps, iter_count); + TEST_ASSERT_SUCCESS((burst_sz > MAX_BURST), "BURST_SIZE should be <= %u", MAX_BURST); + + struct rte_bbdev_info info; + rte_bbdev_info_get(tp->dev_id, &info); + + TEST_ASSERT_SUCCESS((num_ops > info.drv.queue_size_lim), "NUM_OPS cannot exceed %u for this device", info.drv.queue_size_lim); + + struct test_buffers *bufs = &tp->op_params->q_bufs[GET_SOCKET(info.socket_id)][queue_id]; + + while (rte_atomic16_read(&tp->op_params->sync) == SYNC_WAIT) + rte_pause(); + + ret = rte_mempool_get_bulk(tp->op_params->mp_enc, (void **)ops_enq, num_ops); + // ret = rte_bbdev_enc_op_alloc_bulk(tp->op_params->mp, ops_enq, num_ops); + TEST_ASSERT_SUCCESS(ret, "Allocation failed for %d ops", num_ops); + ops_enq[0]->mempool = tp->op_params->mp_enc; + + set_ldpc_enc_op(ops_enq, num_ops, 0, bufs->inputs, bufs->hard_outputs, ref_op, p_offloadParams); + + /* Set counter to validate the ordering */ + for (j = 0; j < num_ops; ++j) + ops_enq[j]->opaque_data = (void *)(uintptr_t)j; + + for (j = 0; j < num_ops; ++j) + mbuf_reset(ops_enq[j]->ldpc_enc.output.data); + + for (enq = 0, deq = 0; enq < num_ops;) { + num_to_enq = burst_sz; + if (unlikely(num_ops - enq < num_to_enq)) + num_to_enq = num_ops - enq; + + enq += rte_bbdev_enqueue_ldpc_enc_ops(tp->dev_id, queue_id, &ops_enq[enq], num_to_enq); + deq += rte_bbdev_dequeue_ldpc_enc_ops(tp->dev_id, queue_id, &ops_deq[deq], enq - deq); + } + /* dequeue the remaining */ + int time_out = 0; + while (deq < enq) { + deq += rte_bbdev_dequeue_ldpc_enc_ops(tp->dev_id, queue_id, &ops_deq[deq], enq - deq); + time_out++; + DevAssert(time_out <= TIME_OUT_POLL); + } + + ret = retrieve_ldpc_enc_op(ops_deq, num_ops, ref_op, p_out); + TEST_ASSERT_SUCCESS(ret, "Validation failed!"); + // rte_bbdev_enc_op_free_bulk(ops_enq, num_ops); + + if (num_ops > 0) + rte_mempool_put_bulk(ops_enq[0]->mempool, (void **)ops_enq, num_ops); + + return ret; } @@ -1207,450 +803,338 @@ print_dec_throughput(struct thread_params *t_params, unsigned int used_cores) * Test function that determines how long an enqueue + dequeue of a burst * takes on available lcores. */ -int -start_pmd_dec(struct active_device *ad, - struct test_op_params *op_params, - struct thread_params *t_params, - t_nrLDPCoffload_params *p_offloadParams, - uint8_t r, - uint8_t harq_pid, - uint8_t ulsch_id, - int8_t* p_out) +// OAI / DPDK BBDEV modified - in DPDK called throughput_test, here we pass more parameters to the function (t_nrLDPCoffload_params +// *p_offloadParams, uint8_t r, ...), many commented lines Removed code which specified which function to use based on the op_type, +// now we are using only pmd_lcore_ldpc_dec for RTE_BBDEV_OP_LDPC_DEC op type. Encoder is RTE_BBDEV_OP_LDPC_ENC op type, +// pmd_lcore_ldpc_enc to be implemented. +int start_pmd_dec(struct active_device *ad, + struct test_op_params *op_params, + t_nrLDPCoffload_params *p_offloadParams, + uint8_t r, + uint8_t harq_pid, + uint8_t ulsch_id, + uint8_t *p_out) { - int ret; - unsigned int lcore_id, used_cores = 0; - struct thread_params *tp; - //struct rte_bbdev_info info; - uint16_t num_lcores; - //uint64_t start_time, start_time1 ; //= rte_rdtsc_precise(); - //uint64_t total_time=0, total_time1=0; - //rte_bbdev_info_get(ad->dev_id, &info); - //start_time = rte_rdtsc_precise(); - /*printf("+ ------------------------------------------------------- +\n"); - printf("== start pmd dec\ndev: %s, nb_queues: %u, burst size: %u, num ops: %u, num_lcores: %u, itr mode: %s, GHz: %lg\n", - info.dev_name, ad->nb_queues, op_params->burst_sz, - op_params->num_to_process, op_params->num_lcores, - intr_enabled ? "Interrupt mode" : "PMD mode", - (double)rte_get_tsc_hz() / 1000000000.0); - */ - /* Set number of lcores */ - num_lcores = (ad->nb_queues < (op_params->num_lcores)) - ? ad->nb_queues - : op_params->num_lcores; + int ret; + unsigned int lcore_id, used_cores = 0; + // struct rte_bbdev_info info; + uint16_t num_lcores; + // rte_bbdev_info_get(ad->dev_id, &info); + /* Set number of lcores */ + num_lcores = (ad->nb_queues < (op_params->num_lcores)) ? ad->nb_queues : op_params->num_lcores; + /* Allocate memory for thread parameters structure */ + struct thread_params *t_params = rte_zmalloc(NULL, num_lcores * sizeof(struct thread_params), RTE_CACHE_LINE_SIZE); + TEST_ASSERT_NOT_NULL(t_params, + "Failed to alloc %zuB for t_params", + RTE_ALIGN(sizeof(struct thread_params) * num_lcores, RTE_CACHE_LINE_SIZE)); + rte_atomic16_set(&op_params->sync, SYNC_WAIT); - /* Allocate memory for thread parameters structure */ - /*t_params = rte_zmalloc(NULL, num_lcores * sizeof(struct thread_params), - RTE_CACHE_LINE_SIZE); - TEST_ASSERT_NOT_NULL(t_params, "Failed to alloc %zuB for t_params", - RTE_ALIGN(sizeof(struct thread_params) * num_lcores, - RTE_CACHE_LINE_SIZE)); - */ - //total_time = rte_rdtsc_precise() - start_time; - rte_atomic16_set(&op_params->sync, SYNC_WAIT); + /* Master core is set at first entry */ + t_params[0].dev_id = ad->dev_id; + t_params[0].lcore_id = 15; + t_params[0].op_params = op_params; + t_params[0].queue_id = ad->dec_queue; + used_cores++; + t_params[0].iter_count = 0; + t_params[0].p_out = p_out; + t_params[0].p_offloadParams = p_offloadParams; + t_params[0].r = r; + t_params[0].harq_pid = harq_pid; + t_params[0].ulsch_id = ulsch_id; - /* Master core is set at first entry */ - t_params[0].dev_id = ad->dev_id; - t_params[0].lcore_id = rte_lcore_id(); - t_params[0].op_params = op_params; - t_params[0].queue_id = ad->queue_ids[used_cores++]; - t_params[0].iter_count = 0; - t_params[0].p_out = p_out; - t_params[0].p_offloadParams = p_offloadParams; - t_params[0].r = r; - t_params[0].harq_pid = harq_pid; - t_params[0].ulsch_id = ulsch_id; + // For now, we never enter here, we don't use the DPDK thread pool + RTE_LCORE_FOREACH_WORKER(lcore_id) { + if (used_cores >= num_lcores) + break; + t_params[used_cores].dev_id = ad->dev_id; + t_params[used_cores].lcore_id = lcore_id; + t_params[used_cores].op_params = op_params; + t_params[used_cores].queue_id = ad->queue_ids[used_cores]; + t_params[used_cores].iter_count = 0; + t_params[used_cores].p_out = p_out; + t_params[used_cores].p_offloadParams = p_offloadParams; + t_params[used_cores].r = r; + t_params[used_cores].harq_pid = harq_pid; + t_params[used_cores].ulsch_id = ulsch_id; + rte_eal_remote_launch(pmd_lcore_ldpc_dec, &t_params[used_cores++], lcore_id); + } - RTE_LCORE_FOREACH_SLAVE(lcore_id) { - if (used_cores >= num_lcores) - break; - t_params[used_cores].dev_id = ad->dev_id; - t_params[used_cores].lcore_id = lcore_id; - t_params[used_cores].op_params = op_params; - t_params[used_cores].queue_id = ad->queue_ids[used_cores]; - t_params[used_cores].iter_count = 0; - t_params[used_cores].p_out = p_out; - t_params[used_cores].p_offloadParams = p_offloadParams; - t_params[used_cores].r = r; - t_params[used_cores].harq_pid = harq_pid; - t_params[used_cores].ulsch_id = ulsch_id; + rte_atomic16_set(&op_params->sync, SYNC_START); - rte_eal_remote_launch(pmd_lcore_ldpc_dec, - &t_params[used_cores++], lcore_id); - } - - rte_atomic16_set(&op_params->sync, SYNC_START); - - //total_time = rte_rdtsc_precise() - start_time; + ret = pmd_lcore_ldpc_dec(&t_params[0]); - //if (total_time > 100*3000) - //LOG_E(PHY," start pmd 1st: %u\n",(uint) (total_time/3000)); + /* Master core is always used */ + // for (used_cores = 1; used_cores < num_lcores; used_cores++) + // ret |= rte_eal_wait_lcore(t_params[used_cores].lcore_id); - ret = pmd_lcore_ldpc_dec(&t_params[0]); - //start_time1 = rte_rdtsc_precise(); + /* Return if test failed */ + if (ret < 0) { + rte_free(t_params); + return ret; + } - /* Master core is always used */ - //for (used_cores = 1; used_cores < num_lcores; used_cores++) - // ret |= rte_eal_wait_lcore(t_params[used_cores].lcore_id); - - /* Return if test failed */ - if (ret) { - rte_free(t_params); - return ret; - } - - /* Print throughput if interrupts are disabled and test passed */ - if (!intr_enabled) { - ///print_dec_throughput(t_params, num_lcores); - //rte_free(t_params); - // total_time1 = rte_rdtsc_precise() - start_time1; - - // if (total_time1 > 10*3000) - // LOG_E(PHY," start pmd 2nd: %u\n",(uint) (total_time1/3000)); - // rte_free(t_params); - return ret; - } - /* In interrupt TC we need to wait for the interrupt callback to deqeue - * all pending operations. Skip waiting for queues which reported an - * error using processing_status variable. - * Wait for master lcore operations. - */ - tp = &t_params[0]; - while ((rte_atomic16_read(&tp->nb_dequeued) < - op_params->num_to_process) && - (rte_atomic16_read(&tp->processing_status) != - TEST_FAILED)) - rte_pause(); - - tp->ops_per_sec /= TEST_REPETITIONS; - tp->mbps /= TEST_REPETITIONS; - ret |= (int)rte_atomic16_read(&tp->processing_status); - - for (used_cores = 1; used_cores < num_lcores; used_cores++) { - tp = &t_params[used_cores]; - - while ((rte_atomic16_read(&tp->nb_dequeued) < - op_params->num_to_process) && - (rte_atomic16_read(&tp->processing_status) != - TEST_FAILED)) - rte_pause(); - - tp->ops_per_sec /= TEST_REPETITIONS; - tp->mbps /= TEST_REPETITIONS; - ret |= (int)rte_atomic16_read(&tp->processing_status); - } - - /* Print throughput if test passed */ - if (!ret) { - print_dec_throughput(t_params, num_lcores); - } - - rte_free(t_params); - - return ret; + rte_free(t_params); + return ret; } - -/* Declare structure for command line test parameters and options */ -static struct test_params { - struct test_command *test_to_run[8]; - unsigned int num_tests; - unsigned int num_ops; - unsigned int burst_sz; - unsigned int num_lcores; - double snr; - unsigned int iter_max; - char test_vector_filename[PATH_MAX]; - bool init_device; -} test_params; - -unsigned int -get_num_ops(void) +int32_t start_pmd_enc(struct active_device *ad, + struct test_op_params *op_params, + t_nrLDPCoffload_params *p_offloadParams, + uint8_t *p_out) { - return test_params.num_ops; + int ret; + unsigned int lcore_id, used_cores = 0; + + uint16_t num_lcores; + num_lcores = (ad->nb_queues < (op_params->num_lcores)) ? ad->nb_queues : op_params->num_lcores; + /* Allocate memory for thread parameters structure */ + struct thread_params *t_params = rte_zmalloc(NULL, num_lcores * sizeof(struct thread_params), RTE_CACHE_LINE_SIZE); + TEST_ASSERT_NOT_NULL(t_params, + "Failed to alloc %zuB for t_params", + RTE_ALIGN(sizeof(struct thread_params) * num_lcores, RTE_CACHE_LINE_SIZE)); + rte_atomic16_set(&op_params->sync, SYNC_WAIT); + + /* Master core is set at first entry */ + t_params[0].dev_id = ad->dev_id; + t_params[0].lcore_id = 14; + t_params[0].op_params = op_params; + // t_params[0].queue_id = ad->queue_ids[used_cores++]; + used_cores++; + t_params[0].queue_id = ad->enc_queue; + t_params[0].iter_count = 0; + t_params[0].p_out = p_out; + t_params[0].p_offloadParams = p_offloadParams; + + // For now, we never enter here, we don't use the DPDK thread pool + RTE_LCORE_FOREACH_WORKER(lcore_id) { + if (used_cores >= num_lcores) + break; + t_params[used_cores].dev_id = ad->dev_id; + t_params[used_cores].lcore_id = lcore_id; + t_params[used_cores].op_params = op_params; + t_params[used_cores].queue_id = ad->queue_ids[1]; + t_params[used_cores].iter_count = 0; + rte_eal_remote_launch(pmd_lcore_ldpc_enc, &t_params[used_cores++], lcore_id); + } + + rte_atomic16_set(&op_params->sync, SYNC_START); + ret = pmd_lcore_ldpc_enc(&t_params[0]); + if (ret) { + rte_free(t_params); + return ret; + } + + rte_free(t_params); + return ret; } -unsigned int -get_burst_sz(void) -{ - return test_params.burst_sz; -} - -unsigned int -get_num_lcores(void) -{ - return test_params.num_lcores; -} - -double -get_snr(void) -{ - return test_params.snr; -} - -unsigned int -get_iter_max(void) -{ - return test_params.iter_max; -} - -bool -get_init_device(void) -{ - return test_params.init_device; -} - -struct test_op_params op_params_e; -struct test_op_params *op_params = &op_params_e; +struct test_op_params *op_params = NULL; struct rte_mbuf *m_head[DATA_NUM_TYPES]; -struct thread_params *t_params; - - -int32_t nrLDPC_decod_offload(t_nrLDPC_dec_params* p_decParams, uint8_t harq_pid, uint8_t ulsch_id, uint8_t C, uint8_t rv, uint16_t F, - uint32_t E, uint8_t Qm, int8_t* p_llr, int8_t* p_out, uint8_t mode) +// OAI CODE +int32_t LDPCinit() { - t_nrLDPCoffload_params offloadParams; - t_nrLDPCoffload_params* p_offloadParams = &offloadParams; - uint64_t start=rte_rdtsc_precise(); - /*uint64_t start_time;//=rte_rdtsc_precise(); - uint64_t start_time1; //=rte_rdtsc_precise(); - uint64_t total_time=0, total_time1=0;*/ - uint32_t numIter = 0; - int ret; - /*uint64_t start_time_init; - uint64_t total_time_init=0;*/ + pthread_mutex_init(&encode_mutex, NULL); + pthread_mutex_init(&decode_mutex, NULL); + int ret; + int dev_id = 0; + struct rte_bbdev_info info; + struct active_device *ad = active_devs; + char *dpdk_dev = "41:00.0"; //PCI address of the card + char *argv_re[] = {"bbdev", "-a", dpdk_dev, "-l", "14-15", "--file-prefix=b6", "--"}; + // EAL initialization, if already initialized (init in xran lib) try to probe DPDK device + ret = rte_eal_init(5, argv_re); + if (ret < 0) { + printf("EAL initialization failed, probing DPDK device %s\n", dpdk_dev); + if (rte_dev_probe(dpdk_dev) != 0) { + LOG_E(PHY, "T2 card %s not found\n", dpdk_dev); + return (-1); + } + } + // Use only device 0 - first detected device + rte_bbdev_info_get(0, &info); + // Set number of queues based on number of initialized cores (-l option) and driver + // capabilities + TEST_ASSERT_SUCCESS(add_dev(dev_id, &info), "Failed to setup bbdev"); + TEST_ASSERT_SUCCESS(rte_bbdev_stats_reset(dev_id), "Failed to reset stats of bbdev %u", dev_id); + TEST_ASSERT_SUCCESS(rte_bbdev_start(dev_id), "Failed to start bbdev %u", dev_id); - /* - int argc_re=2; - char *argv_re[2]; - argv_re[0] = "/home/eurecom/hongzhi/dpdk-20.05orig/build/app/testbbdev"; - argv_re[1] = "--"; - */ - - int argc_re=7; - char *argv_re[7]; - argv_re[0] = "/home/eurecom/hongzhi/dpdk-20.05orig/build/app/testbbdev"; - argv_re[1] = "-l"; - argv_re[2] = "31"; - argv_re[3] = "-w"; - argv_re[4] = "b0:00.0"; - argv_re[5] = "--file-prefix=b6"; - argv_re[6] = "--"; - - test_params.num_ops=1; - test_params.burst_sz=1; - test_params.num_lcores=1; - test_params.num_tests = 1; - struct active_device *ad; - ad = &active_devs[0]; + //the previous calls have populated this global variable (beurk) + // One more global to remove, not thread safe global op_params + op_params = rte_zmalloc(NULL, sizeof(struct test_op_params), RTE_CACHE_LINE_SIZE); + TEST_ASSERT_NOT_NULL(op_params, "Failed to alloc %zuB for op_params", + RTE_ALIGN(sizeof(struct test_op_params), RTE_CACHE_LINE_SIZE)); - int socket_id=0; - int i,f_ret; - struct rte_bbdev_info info; - enum rte_bbdev_op_type op_type = RTE_BBDEV_OP_LDPC_DEC; - - switch (mode) { - case 0: - ret = rte_eal_init(argc_re, argv_re); - if (ret<0) { - printf("Could not init EAL, ret %d\n",ret); - return(-1); - } - ret = device_setup(); - if (ret != TEST_SUCCESS) { - printf("Couldn't setup device"); - return(-1); - } - ret=ut_setup(); - if (ret != TEST_SUCCESS) { - printf("Couldn't setup ut"); - return(-1); - } + int socket_id = GET_SOCKET(info.socket_id); + int out_max_sz = 8448; // max code block size (for BG1), 22 * 384 + int in_max_sz = 25344; // max number of encoded bits (for BG1), 66 * 384 + int num_ops = 1; + int f_ret = create_mempools(ad, socket_id, num_ops, out_max_sz, in_max_sz); + if (f_ret != TEST_SUCCESS) { + printf("Couldn't create mempools"); + return -1; + } + // get_num_lcores() hardcoded to 1: we use one core for decode, and another for encode + // this code from bbdev test example is not considering encode and decode test + // get_num_ops() replaced by 1: LDPC decode and ldpc encode (7th param) + f_ret = init_test_op_params(op_params, RTE_BBDEV_OP_LDPC_DEC, ad->bbdev_dec_op_pool, 1, 1, 1); + f_ret |= init_test_op_params(op_params, RTE_BBDEV_OP_LDPC_ENC, ad->bbdev_enc_op_pool, 1, 1, 1); + if (f_ret != TEST_SUCCESS) { + printf("Couldn't init test op params"); + return -1; + } - p_offloadParams->E = E; - p_offloadParams->n_cb = (p_decParams->BG==1)?(66*p_decParams->Z):(50*p_decParams->Z); - p_offloadParams->BG = p_decParams->BG; - p_offloadParams->Z = p_decParams->Z; - p_offloadParams->rv = rv; - p_offloadParams->F = F; - p_offloadParams->Qm = Qm; + // fill_queue_buffers -> allocate_buffers_on_socket + for (int i = 0; i < ad->nb_queues; ++i) { + const uint16_t n = op_params->num_to_process; + struct rte_mempool *in_mp = ad->in_mbuf_pool; + struct rte_mempool *hard_out_mp = ad->hard_out_mbuf_pool; + struct rte_mempool *soft_out_mp = ad->soft_out_mbuf_pool; + struct rte_mempool *harq_in_mp = ad->harq_in_mbuf_pool; + struct rte_mempool *harq_out_mp = ad->harq_out_mbuf_pool; + struct rte_mempool *mbuf_pools[DATA_NUM_TYPES] = {in_mp, soft_out_mp, hard_out_mp, harq_in_mp, harq_out_mp}; + uint8_t queue_id = ad->queue_ids[i]; + struct rte_bbdev_op_data **queue_ops[DATA_NUM_TYPES] = {&op_params->q_bufs[socket_id][queue_id].inputs, + &op_params->q_bufs[socket_id][queue_id].soft_outputs, + &op_params->q_bufs[socket_id][queue_id].hard_outputs, + &op_params->q_bufs[socket_id][queue_id].harq_inputs, + &op_params->q_bufs[socket_id][queue_id].harq_outputs}; - op_params = rte_zmalloc(NULL, - sizeof(struct test_op_params), RTE_CACHE_LINE_SIZE); - TEST_ASSERT_NOT_NULL(op_params, "Failed to alloc %zuB for op_params", - RTE_ALIGN(sizeof(struct test_op_params), - RTE_CACHE_LINE_SIZE)); - - rte_bbdev_info_get(ad->dev_id, &info); - socket_id = GET_SOCKET(info.socket_id); - f_ret = create_mempools(ad, socket_id, op_type, - get_num_ops(),p_offloadParams); - if (f_ret != TEST_SUCCESS) { - printf("Couldn't create mempools"); - } - f_ret = init_test_op_params(op_params, op_type, - 0, - 0, - ad->ops_mempool, - 1, - get_num_ops(), - get_num_lcores()); - if (f_ret != TEST_SUCCESS) { - printf("Couldn't init test op params"); - } - - //const struct rte_bbdev_op_cap *capabilities = NULL; - rte_bbdev_info_get(ad->dev_id, &info); - socket_id = GET_SOCKET(info.socket_id); - //enum rte_bbdev_op_type op_type = RTE_BBDEV_OP_LDPC_DEC; - /*const struct rte_bbdev_op_cap *cap = info.drv.capabilities; + for (enum op_data_type type = DATA_INPUT; type < 3; type += 2) { + int ret = allocate_buffers_on_socket(queue_ops[type], n * sizeof(struct rte_bbdev_op_data), socket_id); + TEST_ASSERT_SUCCESS(ret, "Couldn't allocate memory for rte_bbdev_op_data structs"); + m_head[type] = rte_pktmbuf_alloc(mbuf_pools[type]); + TEST_ASSERT_NOT_NULL(m_head[type], + "Not enough mbufs in %d data type mbuf pool (needed %d, available %u)", + type, + 1, + mbuf_pools[type]->size); + } + } - for (i = 0; i < RTE_BBDEV_OP_TYPE_COUNT; i++) { - if (cap->type == op_type) { - capabilities = cap; - break; - } - cap++; - }*/ - ad->nb_queues = 1; - enum op_data_type type; - - for (i = 0; i < ad->nb_queues; ++i) { - - const uint16_t n = op_params->num_to_process; - - struct rte_mempool *in_mp = ad->in_mbuf_pool; - struct rte_mempool *hard_out_mp = ad->hard_out_mbuf_pool; - struct rte_mempool *soft_out_mp = ad->soft_out_mbuf_pool; - struct rte_mempool *harq_in_mp = ad->harq_in_mbuf_pool; - struct rte_mempool *harq_out_mp = ad->harq_out_mbuf_pool; - - struct rte_mempool *mbuf_pools[DATA_NUM_TYPES] = { - in_mp, - soft_out_mp, - hard_out_mp, - harq_in_mp, - harq_out_mp, - }; - - uint8_t queue_id =ad->queue_ids[i]; - struct rte_bbdev_op_data **queue_ops[DATA_NUM_TYPES] = { - &op_params->q_bufs[socket_id][queue_id].inputs, - &op_params->q_bufs[socket_id][queue_id].soft_outputs, - &op_params->q_bufs[socket_id][queue_id].hard_outputs, - &op_params->q_bufs[socket_id][queue_id].harq_inputs, - &op_params->q_bufs[socket_id][queue_id].harq_outputs, - }; - - for (type = DATA_INPUT; type < 3; type+=2) { - - ret = allocate_buffers_on_socket(queue_ops[type], - n * sizeof(struct rte_bbdev_op_data), - socket_id); - TEST_ASSERT_SUCCESS(ret, - "Couldn't allocate memory for rte_bbdev_op_data structs"); - - m_head[type] = rte_pktmbuf_alloc(mbuf_pools[type]); - - TEST_ASSERT_NOT_NULL(m_head[type], - "Not enough mbufs in %d data type mbuf pool (needed %d, available %u)", - op_type, 1, - mbuf_pools[type]->size); - - } - - /* Allocate memory for thread parameters structure */ - t_params = rte_zmalloc(NULL, sizeof(struct thread_params), - RTE_CACHE_LINE_SIZE); - TEST_ASSERT_NOT_NULL(t_params, "Failed to alloc %zuB for t_params", - RTE_ALIGN(sizeof(struct thread_params), - RTE_CACHE_LINE_SIZE)); - } - - break; - case 1: - //printf("offload param E %d BG %d F %d Z %d Qm %d rv %d\n", E,p_decParams->BG, F,p_decParams->Z, Qm,rv); - //uint64_t start_time_init; - //uint64_t total_time_init=0; - - //start_time_init = rte_rdtsc_precise(); - p_offloadParams->E = E; - p_offloadParams->n_cb = (p_decParams->BG==1)?(66*p_decParams->Z):(50*p_decParams->Z); - p_offloadParams->BG = p_decParams->BG; - p_offloadParams->Z = p_decParams->Z; - p_offloadParams->rv = rv; - p_offloadParams->F = F; - p_offloadParams->Qm = Qm; - - rte_bbdev_info_get(ad->dev_id, &info); - socket_id = GET_SOCKET(info.socket_id); - - create_reference_ldpc_dec_op(op_params->ref_dec_op, p_offloadParams); - - struct rte_mempool *in_mp = ad->in_mbuf_pool; - struct rte_mempool *hard_out_mp = ad->hard_out_mbuf_pool; - struct rte_mempool *soft_out_mp = ad->soft_out_mbuf_pool; - struct rte_mempool *harq_in_mp = ad->harq_in_mbuf_pool; - struct rte_mempool *harq_out_mp = ad->harq_out_mbuf_pool; - - struct rte_mempool *mbuf_pools[DATA_NUM_TYPES] = { - in_mp, - soft_out_mp, - hard_out_mp, - harq_in_mp, - harq_out_mp, - }; - - uint8_t queue_id =ad->queue_ids[0]; - struct rte_bbdev_op_data **queue_ops[DATA_NUM_TYPES] = { - &op_params->q_bufs[socket_id][queue_id].inputs, - &op_params->q_bufs[socket_id][queue_id].soft_outputs, - &op_params->q_bufs[socket_id][queue_id].hard_outputs, - &op_params->q_bufs[socket_id][queue_id].harq_inputs, - &op_params->q_bufs[socket_id][queue_id].harq_outputs, - }; - //start_time1 = rte_rdtsc_precise(); - for (type = DATA_INPUT; type < 3; type+=2) { - - ret = init_op_data_objs(*queue_ops[type], p_llr, p_offloadParams->E, - m_head[type], mbuf_pools[type], 1, type, info.drv.min_alignment); - TEST_ASSERT_SUCCESS(ret, - "Couldn't init rte_bbdev_op_data structs"); - - } - /*total_time_init = rte_rdtsc_precise() - start_time_init; - - if (total_time_init > 100*3000) - LOG_E(PHY," ldpc decoder mode 1 first: %u\n",(uint) (total_time_init/3000)); - - start_time1 = rte_rdtsc_precise();*/ - ret = start_pmd_dec(ad, op_params, t_params, p_offloadParams, C, harq_pid, ulsch_id, p_out); - if (ret<0) { - printf("Couldn't start pmd dec"); - return(-1); - } - /*total_time1 = rte_rdtsc_precise() - start_time1; - if (total_time1 > 100*3000) - LOG_E(PHY," ldpc decoder mode 1 second: %u\n",(uint) (total_time1/3000));*/ - break; - case 2: - - free_buffers(ad, op_params); - rte_free(op_params); - rte_free(t_params); - ut_teardown(); - testsuite_teardown(); - break; - default: - printf("Unknown mode: %d\n", mode); - return(-1); - } - /*uint64_t end=rte_rdtsc_precise(); - - if (end - start > 200*3000) - LOG_E(PHY," ldpc decode: %u\n",(uint) ((end - start)/3000)); - */ - return numIter; + return 0; } +int32_t LDPCshutdown() +{ + struct active_device *ad = active_devs; + int dev_id = 0; + struct rte_bbdev_stats stats; + free_buffers(ad, op_params); + rte_free(op_params); + // Stop and close bbdev + rte_bbdev_stats_get(dev_id, &stats); + rte_bbdev_stop(dev_id); + rte_bbdev_close(dev_id); + memset(active_devs, 0, sizeof(active_devs)); + nb_active_devs = 0; + return 0; +} + +int32_t LDPCdecoder(struct nrLDPC_dec_params *p_decParams, + uint8_t harq_pid, + uint8_t ulsch_id, + uint8_t C, + int8_t *p_llr, + int8_t *p_out, + t_nrLDPC_time_stats *p_profiler, + decode_abort_t *ab) +{ + pthread_mutex_lock(&decode_mutex); + // hardcoded we use first device + + struct active_device *ad = active_devs; + t_nrLDPCoffload_params offloadParams = {.E = p_decParams->E, + .n_cb = (p_decParams->BG == 1) ? (66 * p_decParams->Z) : (50 * p_decParams->Z), + .BG = p_decParams->BG, + .Z = p_decParams->Z, + .rv = p_decParams->rv, + .F = p_decParams->F, + .Qm = p_decParams->Qm, + .setCombIn = p_decParams->setCombIn}; + struct rte_bbdev_info info; + rte_bbdev_info_get(ad->dev_id, &info); + int socket_id = GET_SOCKET(info.socket_id); + // fill_queue_buffers -> init_op_data_objs + struct rte_mempool *in_mp = ad->in_mbuf_pool; + struct rte_mempool *hard_out_mp = ad->hard_out_mbuf_pool; + struct rte_mempool *soft_out_mp = ad->soft_out_mbuf_pool; + struct rte_mempool *harq_in_mp = ad->harq_in_mbuf_pool; + struct rte_mempool *harq_out_mp = ad->harq_out_mbuf_pool; + struct rte_mempool *mbuf_pools[DATA_NUM_TYPES] = {in_mp, soft_out_mp, hard_out_mp, harq_in_mp, harq_out_mp}; + uint8_t queue_id = ad->dec_queue; + struct rte_bbdev_op_data **queue_ops[DATA_NUM_TYPES] = {&op_params->q_bufs[socket_id][queue_id].inputs, + &op_params->q_bufs[socket_id][queue_id].soft_outputs, + &op_params->q_bufs[socket_id][queue_id].hard_outputs, + &op_params->q_bufs[socket_id][queue_id].harq_inputs, + &op_params->q_bufs[socket_id][queue_id].harq_outputs}; + // this should be modified + // enum rte_bbdev_op_type op_type = RTE_BBDEV_OP_LDPC_DEC; + for (enum op_data_type type = DATA_INPUT; type < 3; type += 2) { + int ret = init_op_data_objs(*queue_ops[type], + (uint8_t *)p_llr, + p_decParams->E, + m_head[type], + mbuf_pools[type], + 1, + type, + info.drv.min_alignment); + TEST_ASSERT_SUCCESS(ret, "Couldn't init rte_bbdev_op_data structs"); + } + int ret = start_pmd_dec(ad, op_params, &offloadParams, C, harq_pid, ulsch_id, (uint8_t *)p_out); + if (ret < 0) { + printf("Couldn't start pmd dec\n"); + pthread_mutex_unlock(&decode_mutex); + return (20); // Fix me: we should propoagate max_iterations properly in the call (impp struct) + } + pthread_mutex_unlock(&decode_mutex); + return ret; +} + +int32_t LDPCencoder(unsigned char **input, unsigned char **output, encoder_implemparams_t *impp) +{ + pthread_mutex_lock(&encode_mutex); + // hardcoded to use the first found board + struct active_device *ad = active_devs; + int Zc = impp->Zc; + int BG = impp->BG; + t_nrLDPCoffload_params offloadParams = {.E = impp->E, + .n_cb = (BG == 1) ? (66 * Zc) : (50 * Zc), + .BG = BG, + .Z = Zc, + .rv = 0, //impp->rv, + .F = 0, //impp->F, + .Qm = impp->Qm, + .Kr = impp->Kr}; + struct rte_bbdev_info info; + rte_bbdev_info_get(ad->dev_id, &info); + int socket_id = GET_SOCKET(info.socket_id); + // fill_queue_buffers -> init_op_data_objs + struct rte_mempool *in_mp = ad->in_mbuf_pool; + struct rte_mempool *hard_out_mp = ad->hard_out_mbuf_pool; + struct rte_mempool *soft_out_mp = ad->soft_out_mbuf_pool; + struct rte_mempool *harq_in_mp = ad->harq_in_mbuf_pool; + struct rte_mempool *harq_out_mp = ad->harq_out_mbuf_pool; + struct rte_mempool *mbuf_pools[DATA_NUM_TYPES] = {in_mp, soft_out_mp, hard_out_mp, harq_in_mp, harq_out_mp}; + uint8_t queue_id = ad->enc_queue; + struct rte_bbdev_op_data **queue_ops[DATA_NUM_TYPES] = {&op_params->q_bufs[socket_id][queue_id].inputs, + &op_params->q_bufs[socket_id][queue_id].soft_outputs, + &op_params->q_bufs[socket_id][queue_id].hard_outputs, + &op_params->q_bufs[socket_id][queue_id].harq_inputs, + &op_params->q_bufs[socket_id][queue_id].harq_outputs}; + for (enum op_data_type type = DATA_INPUT; type < 3; type += 2) { + int ret = init_op_data_objs(*queue_ops[type], + *input, + (offloadParams.Kr + 7) / 8, + m_head[type], + mbuf_pools[type], + 1, + type, + info.drv.min_alignment); + TEST_ASSERT_SUCCESS(ret, "Couldn't init rte_bbdev_op_data structs"); + } + int ret=start_pmd_enc(ad, op_params, &offloadParams, *output); + pthread_mutex_unlock(&encode_mutex); + return ret; +} diff --git a/openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_types.h b/openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_types.h index 04ec5822d8..63a96645c3 100644 --- a/openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_types.h +++ b/openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_types.h @@ -85,24 +85,27 @@ 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 block_length; + 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; } t_nrLDPC_dec_params; -/** - Structure containing LDPC decoder parameters. - */ typedef struct nrLDPCoffload_params { uint8_t BG; /**< Base graph */ - uint16_t Z; - uint16_t Kr; + uint16_t Z; + uint16_t Kr; uint8_t rv; uint32_t E; uint16_t n_cb; uint16_t F; /**< Filler bits */ uint8_t Qm; /**< Modulation */ + uint8_t setCombIn; } t_nrLDPCoffload_params; /** diff --git a/openair1/PHY/CODING/nrLDPC_decoder_LYC/nrLDPC_decoder_LYC.cu b/openair1/PHY/CODING/nrLDPC_decoder_LYC/nrLDPC_decoder_LYC.cu index 4c678699b5..ee08e9287c 100644 --- a/openair1/PHY/CODING/nrLDPC_decoder_LYC/nrLDPC_decoder_LYC.cu +++ b/openair1/PHY/CODING/nrLDPC_decoder_LYC/nrLDPC_decoder_LYC.cu @@ -1,9 +1,9 @@ - /*! \file PHY/CODING/nrLDPC_decoder_LYC/nrLDPC_decoder_LYC.cu +/*! \file PHY/CODING/nrLDPC_decoder_LYC/nrLDPC_decoder_LYC.cu * \brief LDPC cuda support BG1 all length * \author NCTU OpinConnect Terng-Yin Hsu,WEI-YING,LIN * \email tyhsu@cs.nctu.edu.tw * \date 13-05-2020 - * \version + * \version * \note * \warning */ @@ -31,17 +31,17 @@ #include "bgs/BG2_I5" #include "bgs/BG2_I6" #include "bgs/BG2_I7" - #define MAX_ITERATION 2 #define MC 1 +typedef void decode_abort_t; #define cudaCheck(ans) { cudaAssert((ans), __FILE__, __LINE__); } inline void cudaAssert(cudaError_t code, const char *file, int line) { - if (code != cudaSuccess){ - fprintf(stderr,"GPUassert: %s %s %d\n", cudaGetErrorString(code), file, line); - exit(code); - } + if (code != cudaSuccess) { + fprintf(stderr, "GPUassert: %s %s %d\n", cudaGetErrorString(code), file, line); + exit(code); + } } typedef struct{ @@ -66,534 +66,505 @@ __device__ h_element dev_h_compact2[68*30]; // used in kernel 2 // __device__ __constant__ h_element dev_h_compact2[68*30]; // used in kernel 2 // row and col element count -__device__ __constant__ char h_ele_row_bg1_count[46] = { - 19, 19, 19, 19, 3, 8, 9, 7, 10, 9, - 7, 8, 7, 6, 7, 7, 6, 6, 6, 6, - 6, 6, 5, 5, 6, 5, 5, 4, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 4, 5, 5, - 4, 5, 4, 5, 5, 4}; +__device__ __constant__ char h_ele_row_bg1_count[46] = {19, 19, 19, 19, 3, 8, 9, 7, 10, 9, 7, 8, 7, 6, 7, 7, 6, 6, 6, 6, 6, 6, 5, + 5, 6, 5, 5, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 4, 5, 5, 4, 5, 4, 5, 5, 4}; __device__ __constant__ char h_ele_col_bg1_count[68] = { - 30, 28, 7, 11, 9, 4, 8, 12, 8, 7, - 12, 10, 12, 11, 10, 7, 10, 10, 13, 7, - 8, 11, 12, 5, 6, 6, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1}; -__device__ __constant__ char h_ele_row_bg2_count[42] = { - 8, 10, 8, 10, 4, 6, 6, 6, 4, 5, - 5, 5, 4, 5, 5, 4, 5, 5, 4, 4, - 4, 4, 3, 4, 4, 3, 5, 3, 4, 3, - 5, 3, 4, 4, 4, 4, 4, 3, 4, 4, - 4, 4}; -__device__ __constant__ char h_ele_col_bg2_count[52] = { - 22, 23, 10, 5, 5, 14, 7, 13, 6, 8, - 9, 16, 9, 12, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1}; - + 30, 28, 7, 11, 9, 4, 8, 12, 8, 7, 12, 10, 12, 11, 10, 7, 10, 10, 13, 7, 8, 11, 12, 5, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}; +__device__ __constant__ char h_ele_row_bg2_count[42] = {8, 10, 8, 10, 4, 6, 6, 6, 4, 5, 5, 5, 4, 5, 5, 4, 5, 5, 4, 4, 4, + 4, 3, 4, 4, 3, 5, 3, 4, 3, 5, 3, 4, 4, 4, 4, 4, 3, 4, 4, 4, 4}; +__device__ __constant__ char h_ele_col_bg2_count[52] = {22, 23, 10, 5, 5, 14, 7, 13, 6, 8, 9, 16, 9, 12, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}; __global__ void warmup() { - // warm up gpu for time measurement + // warm up gpu for time measurement } extern "C" void warmup_for_GPU(){ - - warmup<<<20,1024 >>>(); - + warmup<<<20, 1024>>>(); } extern "C" void set_compact_BG(int Zc,short BG){ - - int row,col; - if(BG == 1){ - row = 46; - col = 68; - } - else{ - row = 42; - col = 52; - } - int compact_row = 30; - int compact_col = 19; - if(BG==2){compact_row = 10, compact_col = 23;} - int memorySize_h_compact1 = row * compact_col * sizeof(h_element); - int memorySize_h_compact2 = compact_row * col * sizeof(h_element); - int lift_index = 0; - short lift_set[][9] = { - {2,4,8,16,32,64,128,256}, - {3,6,12,24,48,96,192,384}, - {5,10,20,40,80,160,320}, - {7,14,28,56,112,224}, - {9,18,36,72,144,288}, - {11,22,44,88,176,352}, - {13,26,52,104,208}, - {15,30,60,120,240}, - {0} - }; - - for(int i = 0; lift_set[i][0] != 0; i++){ - for(int j = 0; lift_set[i][j] != 0; j++){ - if(Zc == lift_set[i][j]){ - lift_index = i; - break; - } - } - } - printf("\nZc = %d BG = %d\n",Zc,BG); - switch(lift_index){ - case 0: - cudaCheck( cudaMemcpyToSymbol(dev_h_compact1, host_h_compact1_I0, memorySize_h_compact1) ); - cudaCheck( cudaMemcpyToSymbol(dev_h_compact2, host_h_compact2_I0, memorySize_h_compact2) ); - break; - case 1: - cudaCheck( cudaMemcpyToSymbol(dev_h_compact1, host_h_compact1_I1, memorySize_h_compact1) ); - cudaCheck( cudaMemcpyToSymbol(dev_h_compact2, host_h_compact2_I1, memorySize_h_compact2) ); - break; - case 2: - cudaCheck( cudaMemcpyToSymbol(dev_h_compact1, host_h_compact1_I2, memorySize_h_compact1) ); - cudaCheck( cudaMemcpyToSymbol(dev_h_compact2, host_h_compact2_I2, memorySize_h_compact2) ); - break; - case 3: - cudaCheck( cudaMemcpyToSymbol(dev_h_compact1, host_h_compact1_I3, memorySize_h_compact1) ); - cudaCheck( cudaMemcpyToSymbol(dev_h_compact2, host_h_compact2_I3, memorySize_h_compact2) ); - break; - case 4: - cudaCheck( cudaMemcpyToSymbol(dev_h_compact1, host_h_compact1_I4, memorySize_h_compact1) ); - cudaCheck( cudaMemcpyToSymbol(dev_h_compact2, host_h_compact2_I4, memorySize_h_compact2) ); - break; - case 5: - cudaCheck( cudaMemcpyToSymbol(dev_h_compact1, host_h_compact1_I5, memorySize_h_compact1) ); - cudaCheck( cudaMemcpyToSymbol(dev_h_compact2, host_h_compact2_I5, memorySize_h_compact2) ); - break; - case 6: - cudaCheck( cudaMemcpyToSymbol(dev_h_compact1, host_h_compact1_I6, memorySize_h_compact1) ); - cudaCheck( cudaMemcpyToSymbol(dev_h_compact2, host_h_compact2_I6, memorySize_h_compact2) ); - break; - case 7: - cudaCheck( cudaMemcpyToSymbol(dev_h_compact1, host_h_compact1_I7, memorySize_h_compact1) ); - cudaCheck( cudaMemcpyToSymbol(dev_h_compact2, host_h_compact2_I7, memorySize_h_compact2) ); - break; - } - - // return 0; + int row, col; + if (BG == 1) { + row = 46; + col = 68; + } else { + row = 42; + col = 52; + } + int compact_row = 30; + int compact_col = 19; + if (BG == 2) { + compact_row = 10, compact_col = 23; + } + int memorySize_h_compact1 = row * compact_col * sizeof(h_element); + int memorySize_h_compact2 = compact_row * col * sizeof(h_element); + int lift_index = 0; + short lift_set[][9] = {{2, 4, 8, 16, 32, 64, 128, 256}, + {3, 6, 12, 24, 48, 96, 192, 384}, + {5, 10, 20, 40, 80, 160, 320}, + {7, 14, 28, 56, 112, 224}, + {9, 18, 36, 72, 144, 288}, + {11, 22, 44, 88, 176, 352}, + {13, 26, 52, 104, 208}, + {15, 30, 60, 120, 240}, + {0}}; + + for (int i = 0; lift_set[i][0] != 0; i++) { + for (int j = 0; lift_set[i][j] != 0; j++) { + if (Zc == lift_set[i][j]) { + lift_index = i; + break; + } + } + } + printf("\nZc = %d BG = %d\n", Zc, BG); + switch (lift_index) { + case 0: + cudaCheck(cudaMemcpyToSymbol(dev_h_compact1, host_h_compact1_I0, memorySize_h_compact1)); + cudaCheck(cudaMemcpyToSymbol(dev_h_compact2, host_h_compact2_I0, memorySize_h_compact2)); + break; + case 1: + cudaCheck(cudaMemcpyToSymbol(dev_h_compact1, host_h_compact1_I1, memorySize_h_compact1)); + cudaCheck(cudaMemcpyToSymbol(dev_h_compact2, host_h_compact2_I1, memorySize_h_compact2)); + break; + case 2: + cudaCheck(cudaMemcpyToSymbol(dev_h_compact1, host_h_compact1_I2, memorySize_h_compact1)); + cudaCheck(cudaMemcpyToSymbol(dev_h_compact2, host_h_compact2_I2, memorySize_h_compact2)); + break; + case 3: + cudaCheck(cudaMemcpyToSymbol(dev_h_compact1, host_h_compact1_I3, memorySize_h_compact1)); + cudaCheck(cudaMemcpyToSymbol(dev_h_compact2, host_h_compact2_I3, memorySize_h_compact2)); + break; + case 4: + cudaCheck(cudaMemcpyToSymbol(dev_h_compact1, host_h_compact1_I4, memorySize_h_compact1)); + cudaCheck(cudaMemcpyToSymbol(dev_h_compact2, host_h_compact2_I4, memorySize_h_compact2)); + break; + case 5: + cudaCheck(cudaMemcpyToSymbol(dev_h_compact1, host_h_compact1_I5, memorySize_h_compact1)); + cudaCheck(cudaMemcpyToSymbol(dev_h_compact2, host_h_compact2_I5, memorySize_h_compact2)); + break; + case 6: + cudaCheck(cudaMemcpyToSymbol(dev_h_compact1, host_h_compact1_I6, memorySize_h_compact1)); + cudaCheck(cudaMemcpyToSymbol(dev_h_compact2, host_h_compact2_I6, memorySize_h_compact2)); + break; + case 7: + cudaCheck(cudaMemcpyToSymbol(dev_h_compact1, host_h_compact1_I7, memorySize_h_compact1)); + cudaCheck(cudaMemcpyToSymbol(dev_h_compact2, host_h_compact2_I7, memorySize_h_compact2)); + break; + } + + // return 0; } // Kernel 1 __global__ void ldpc_cnp_kernel_1st_iter(/*char * dev_llr,*/ int BG, int row, int col, int Zc) { -// if(blockIdx.x == 0 && threadIdx.x == 1) printf("cnp %d\n", threadIdx.x); - int iMCW = blockIdx.y; // codeword id - int iBlkRow = blockIdx.x; // block row in h_base - int iBlkCol; // block col in h_base - int iSubRow = threadIdx.x; // row index in sub_block of h_base - int iCol; // overall col index in h_base - int offsetR; - int shift_t; + // if(blockIdx.x == 0 && threadIdx.x == 1) printf("cnp %d\n", threadIdx.x); + int iMCW = blockIdx.y; // codeword id + int iBlkRow = blockIdx.x; // block row in h_base + int iBlkCol; // block col in h_base + int iSubRow = threadIdx.x; // row index in sub_block of h_base + int iCol; // overall col index in h_base + int offsetR; + int shift_t; -// For 2-min algorithm. - int Q_sign = 0; - int sq; - int Q, Q_abs; - int R_temp; + // For 2-min algorithm. + int Q_sign = 0; + int sq; + int Q, Q_abs; + int R_temp; - int sign = 1; - int rmin1 = INT32_MAX; - int rmin2 = INT32_MAX; - char idx_min = 0; + int sign = 1; + int rmin1 = INT32_MAX; + int rmin2 = INT32_MAX; + char idx_min = 0; - h_element h_element_t; - int s = (BG==1)? h_ele_row_bg1_count[iBlkRow]:h_ele_row_bg2_count[iBlkRow]; - offsetR = (iMCW * row*col*Zc) + iBlkRow * Zc + iSubRow; // row*col*Zc = size of dev_dt -// if(blockIdx.x == 0 && threadIdx.x == 1) printf("s: %d, offset %d\n", s, offsetR); -// The 1st recursion - for(int i = 0; i < s; i++) // loop through all the ZxZ sub-blocks in a row - { - h_element_t = dev_h_compact1[i*row+iBlkRow]; // compact_col == row + h_element h_element_t; + int s = (BG == 1) ? h_ele_row_bg1_count[iBlkRow] : h_ele_row_bg2_count[iBlkRow]; + offsetR = (iMCW * row * col * Zc) + iBlkRow * Zc + iSubRow; // row*col*Zc = size of dev_dt + // if(blockIdx.x == 0 && threadIdx.x == 1) printf("s: %d, offset %d\n", s, offsetR); + // The 1st recursion + for (int i = 0; i < s; i++) // loop through all the ZxZ sub-blocks in a row + { + h_element_t = dev_h_compact1[i * row + iBlkRow]; // compact_col == row - iBlkCol = h_element_t.y; - shift_t = h_element_t.value; + iBlkCol = h_element_t.y; + shift_t = h_element_t.value; - shift_t = (iSubRow + shift_t) % Zc; - iCol = (iMCW * col*Zc) + iBlkCol * Zc + shift_t; // col*Zc = size of llr - Q = dev_llr[iCol]; - Q_abs = (Q>0)? Q : -Q; - sq = Q < 0; -// if(blockIdx.x == 0 && threadIdx.x == 1) printf("i %d, icol %d, Q: %d\n", i, iCol, Q); - // quick version - sign = sign * (1 - sq * 2); - Q_sign |= sq << i; + shift_t = (iSubRow + shift_t) % Zc; + iCol = (iMCW * col * Zc) + iBlkCol * Zc + shift_t; // col*Zc = size of llr + Q = dev_llr[iCol]; + Q_abs = (Q > 0) ? Q : -Q; + sq = Q < 0; + // if(blockIdx.x == 0 && threadIdx.x == 1) printf("i %d, icol %d, Q: %d\n", i, iCol, Q); + // quick version + sign = sign * (1 - sq * 2); + Q_sign |= sq << i; - if (Q_abs < rmin1){ - rmin2 = rmin1; - rmin1 = Q_abs; - idx_min = i; - } else if (Q_abs < rmin2){ - rmin2 = Q_abs; - } - } + if (Q_abs < rmin1) { + rmin2 = rmin1; + rmin1 = Q_abs; + idx_min = i; + } else if (Q_abs < rmin2) { + rmin2 = Q_abs; + } + } -// if(blockIdx.x == 0 && threadIdx.x == 1)printf("min1 %d, min2 %d, min1_idx %d\n", rmin1, rmin2, idx_min); + // if(blockIdx.x == 0 && threadIdx.x == 1)printf("min1 %d, min2 %d, min1_idx %d\n", rmin1, rmin2, idx_min); -// The 2nd recursion - for(int i = 0; i < s; i++){ - // v0: Best performance so far. 0.75f is the value of alpha. - sq = 1 - 2 * ((Q_sign >> i) & 0x01); - R_temp = 0.75f * sign * sq * (i != idx_min ? rmin1 : rmin2); - // write results to global memory - h_element_t = dev_h_compact1[i*row+iBlkRow]; - int addr_temp = offsetR + h_element_t.y * row * Zc; - dev_dt[addr_temp] = R_temp; -// if(blockIdx.x == 0 && threadIdx.x == 1)printf("R_temp %d, temp_addr %d\n", R_temp, addr_temp); - } + // The 2nd recursion + for (int i = 0; i < s; i++) { + // v0: Best performance so far. 0.75f is the value of alpha. + sq = 1 - 2 * ((Q_sign >> i) & 0x01); + R_temp = 0.75f * sign * sq * (i != idx_min ? rmin1 : rmin2); + // write results to global memory + h_element_t = dev_h_compact1[i * row + iBlkRow]; + int addr_temp = offsetR + h_element_t.y * row * Zc; + dev_dt[addr_temp] = R_temp; + // if(blockIdx.x == 0 && threadIdx.x == 1)printf("R_temp %d, temp_addr %d\n", R_temp, addr_temp); + } } // Kernel_1 __global__ void ldpc_cnp_kernel(/*char * dev_llr, char * dev_dt,*/ int BG, int row, int col, int Zc) { -// if(blockIdx.x == 0 && threadIdx.x == 1) printf("cnp\n"); - int iMCW = blockIdx.y; - int iBlkRow = blockIdx.x; // block row in h_base - int iBlkCol; // block col in h_base - int iSubRow = threadIdx.x; // row index in sub_block of h_base - int iCol; // overall col index in h_base - int offsetR; - int shift_t; + // if(blockIdx.x == 0 && threadIdx.x == 1) printf("cnp\n"); + int iMCW = blockIdx.y; + int iBlkRow = blockIdx.x; // block row in h_base + int iBlkCol; // block col in h_base + int iSubRow = threadIdx.x; // row index in sub_block of h_base + int iCol; // overall col index in h_base + int offsetR; + int shift_t; -// For 2-min algorithm. - int Q_sign = 0; - int sq; - int Q, Q_abs; - int R_temp; + // For 2-min algorithm. + int Q_sign = 0; + int sq; + int Q, Q_abs; + int R_temp; - int sign = 1; - int rmin1 = INT32_MAX; - int rmin2 = INT32_MAX; - char idx_min = 0; + int sign = 1; + int rmin1 = INT32_MAX; + int rmin2 = INT32_MAX; + char idx_min = 0; - h_element h_element_t; - int s = (BG==1)? h_ele_row_bg1_count[iBlkRow]: h_ele_row_bg2_count[iBlkRow]; - offsetR = (iMCW *row*col*Zc) + iBlkRow * Zc + iSubRow; // row * col * Zc = size of dev_dt -// if(blockIdx.x == 0 && threadIdx.x == 1) printf("s: %d, offset %d\n", s, offsetR); -// The 1st recursion - for(int i = 0; i < s; i++) // loop through all the ZxZ sub-blocks in a row - { - h_element_t = dev_h_compact1[i*row+iBlkRow]; + h_element h_element_t; + int s = (BG == 1) ? h_ele_row_bg1_count[iBlkRow] : h_ele_row_bg2_count[iBlkRow]; + offsetR = (iMCW * row * col * Zc) + iBlkRow * Zc + iSubRow; // row * col * Zc = size of dev_dt + // if(blockIdx.x == 0 && threadIdx.x == 1) printf("s: %d, offset %d\n", s, offsetR); + // The 1st recursion + for (int i = 0; i < s; i++) // loop through all the ZxZ sub-blocks in a row + { + h_element_t = dev_h_compact1[i * row + iBlkRow]; - iBlkCol = h_element_t.y; - shift_t = h_element_t.value; - shift_t = (iSubRow + shift_t) % Zc; - iCol = iBlkCol * Zc + shift_t; - - R_temp = dev_dt[offsetR + iBlkCol * row * Zc]; + iBlkCol = h_element_t.y; + shift_t = h_element_t.value; + shift_t = (iSubRow + shift_t) % Zc; + iCol = iBlkCol * Zc + shift_t; - Q = dev_llr[iMCW * (col*Zc) + iCol] - R_temp; - Q_abs = (Q>0)? Q : -Q; -// if(blockIdx.x == 0 && threadIdx.x == 1) printf("i %d, icol %d, Q: %d\n", i, iCol, Q); - sq = Q < 0; - sign = sign * (1 - sq * 2); - Q_sign |= sq << i; + R_temp = dev_dt[offsetR + iBlkCol * row * Zc]; - if (Q_abs < rmin1){ - rmin2 = rmin1; - rmin1 = Q_abs; - idx_min = i; - } else if (Q_abs < rmin2){ - rmin2 = Q_abs; - } - - } + Q = dev_llr[iMCW * (col * Zc) + iCol] - R_temp; + Q_abs = (Q > 0) ? Q : -Q; + // if(blockIdx.x == 0 && threadIdx.x == 1) printf("i %d, icol %d, Q: %d\n", i, iCol, Q); + sq = Q < 0; + sign = sign * (1 - sq * 2); + Q_sign |= sq << i; -// if(blockIdx.x == 0 && threadIdx.x == 1)printf("min1 %d, min2 %d, min1_idx %d\n", rmin1, rmin2, idx_min); - -// The 2nd recursion - for(int i = 0; i < s; i ++){ - sq = 1 - 2 * ((Q_sign >> i) & 0x01); - R_temp = 0.75f * sign * sq * (i != idx_min ? rmin1 : rmin2); - + if (Q_abs < rmin1) { + rmin2 = rmin1; + rmin1 = Q_abs; + idx_min = i; + } else if (Q_abs < rmin2) { + rmin2 = Q_abs; + } + } - // write results to global memory - h_element_t = dev_h_compact1[i*row+iBlkRow]; - int addr_temp = h_element_t.y * row * Zc + offsetR; - dev_dt[addr_temp] = R_temp; -// if(blockIdx.x == 0 && threadIdx.x == 1)printf("R_temp %d, temp_addr %d\n", R_temp, addr_temp); - } + // if(blockIdx.x == 0 && threadIdx.x == 1)printf("min1 %d, min2 %d, min1_idx %d\n", rmin1, rmin2, idx_min); + + // The 2nd recursion + for (int i = 0; i < s; i++) { + sq = 1 - 2 * ((Q_sign >> i) & 0x01); + R_temp = 0.75f * sign * sq * (i != idx_min ? rmin1 : rmin2); + + // write results to global memory + h_element_t = dev_h_compact1[i * row + iBlkRow]; + int addr_temp = h_element_t.y * row * Zc + offsetR; + dev_dt[addr_temp] = R_temp; + // if(blockIdx.x == 0 && threadIdx.x == 1)printf("R_temp %d, temp_addr %d\n", R_temp, addr_temp); + } } // Kernel 2: VNP processing __global__ void ldpc_vnp_kernel_normal(/*char * dev_llr, char * dev_dt, char * dev_const_llr,*/ int BG, int row, int col, int Zc) -{ - int iMCW = blockIdx.y; - int iBlkCol = blockIdx.x; - int iBlkRow; - int iSubCol = threadIdx.x; - int iRow; - int iCol; +{ + int iMCW = blockIdx.y; + int iBlkCol = blockIdx.x; + int iBlkRow; + int iSubCol = threadIdx.x; + int iRow; + int iCol; - int shift_t, sf; - int APP; + int shift_t, sf; + int APP; - h_element h_element_t; + h_element h_element_t; - // update all the llr values - iCol = iBlkCol * Zc + iSubCol; - APP = dev_const_llr[iMCW *col*Zc + iCol]; - int offsetDt = iMCW *row*col*Zc + iBlkCol * row * Zc; - int s = (BG==1)? h_ele_col_bg1_count[iBlkCol]:h_ele_col_bg2_count[iBlkCol]; - - for(int i = 0; i < s; i++) - { - h_element_t = dev_h_compact2[i*col+iBlkCol]; + // update all the llr values + iCol = iBlkCol * Zc + iSubCol; + APP = dev_const_llr[iMCW * col * Zc + iCol]; + int offsetDt = iMCW * row * col * Zc + iBlkCol * row * Zc; + int s = (BG == 1) ? h_ele_col_bg1_count[iBlkCol] : h_ele_col_bg2_count[iBlkCol]; - shift_t = h_element_t.value%Zc; - iBlkRow = h_element_t.x; + for (int i = 0; i < s; i++) { + h_element_t = dev_h_compact2[i * col + iBlkCol]; - sf = iSubCol - shift_t; - sf = (sf + Zc) % Zc; + shift_t = h_element_t.value % Zc; + iBlkRow = h_element_t.x; - iRow = iBlkRow * Zc + sf; - APP = APP + dev_dt[offsetDt + iRow]; - } - if(APP > SCHAR_MAX) APP = SCHAR_MAX; - if(APP < SCHAR_MIN) APP = SCHAR_MIN; - // write back to device global memory - dev_llr[iMCW *col*Zc + iCol] = APP; + sf = iSubCol - shift_t; + sf = (sf + Zc) % Zc; + + iRow = iBlkRow * Zc + sf; + APP = APP + dev_dt[offsetDt + iRow]; + } + if (APP > SCHAR_MAX) + APP = SCHAR_MAX; + if (APP < SCHAR_MIN) + APP = SCHAR_MIN; + // write back to device global memory + dev_llr[iMCW * col * Zc + iCol] = APP; } __global__ void pack_decoded_bit(/*char *dev, unsigned char *host,*/ int col, int Zc) { - __shared__ unsigned char tmp[128]; - int iMCW = blockIdx.y; - int tid = iMCW * col*Zc + blockIdx.x*128 + threadIdx.x; - int btid = threadIdx.x; - tmp[btid] = 0; - - if(dev_llr[tid] < 0){ - tmp[btid] = 1 << (7-(btid&7)); - } - __syncthreads(); - - if(threadIdx.x < 16){ - dev_tmp[iMCW * col*Zc + blockIdx.x*16+threadIdx.x] = 0; - for(int i = 0; i < 8; i++){ - dev_tmp[iMCW * col*Zc + blockIdx.x*16+threadIdx.x] += tmp[threadIdx.x*8+i]; - } - } + __shared__ unsigned char tmp[128]; + int iMCW = blockIdx.y; + int tid = iMCW * col * Zc + blockIdx.x * 128 + threadIdx.x; + int btid = threadIdx.x; + tmp[btid] = 0; + + if (dev_llr[tid] < 0) { + tmp[btid] = 1 << (7 - (btid & 7)); + } + __syncthreads(); + + if (threadIdx.x < 16) { + dev_tmp[iMCW * col * Zc + blockIdx.x * 16 + threadIdx.x] = 0; + for (int i = 0; i < 8; i++) { + dev_tmp[iMCW * col * Zc + blockIdx.x * 16 + threadIdx.x] += tmp[threadIdx.x * 8 + i]; + } + } } void read_BG(int BG, int *h, int row, int col) { - int compact_row = 30, compact_col = 19; - if(BG==2){compact_row = 10, compact_col = 23;} - - h_element h_element_temp; + int compact_row = 30, compact_col = 19; + if (BG == 2) { + compact_row = 10, compact_col = 23; + } - // init the compact matrix - for(int i = 0; i < compact_col; i++){ - for(int j = 0; j < row; j++){ - h_element_temp.x = 0; - h_element_temp.y = 0; - h_element_temp.value = -1; - h_compact1[i*row+j] = h_element_temp; // h[i][0-11], the same column - } + h_element h_element_temp; + + // init the compact matrix + for (int i = 0; i < compact_col; i++) { + for (int j = 0; j < row; j++) { + h_element_temp.x = 0; + h_element_temp.y = 0; + h_element_temp.value = -1; + h_compact1[i * row + j] = h_element_temp; // h[i][0-11], the same column } - // scan the h matrix, and gengerate compact mode of h - for(int i = 0; i < row; i++){ - int k = 0; - for(int j = 0; j < col; j++){ - if(h[i*col+j] != -1){ - h_element_temp.x = i; - h_element_temp.y = j; - h_element_temp.value = h[i*col+j]; - h_compact1[k*row+i] = h_element_temp; - k++; - } - } + } + // scan the h matrix, and gengerate compact mode of h + for (int i = 0; i < row; i++) { + int k = 0; + for (int j = 0; j < col; j++) { + if (h[i * col + j] != -1) { + h_element_temp.x = i; + h_element_temp.y = j; + h_element_temp.value = h[i * col + j]; + h_compact1[k * row + i] = h_element_temp; + k++; + } } - - // h_compact2 - // init the compact matrix - for(int i = 0; i < compact_row; i++){ - for(int j = 0; j < col; j++){ - h_element_temp.x = 0; - h_element_temp.y = 0; - h_element_temp.value = -1; - h_compact2[i*col+j] = h_element_temp; - } + } + + // h_compact2 + // init the compact matrix + for (int i = 0; i < compact_row; i++) { + for (int j = 0; j < col; j++) { + h_element_temp.x = 0; + h_element_temp.y = 0; + h_element_temp.value = -1; + h_compact2[i * col + j] = h_element_temp; + } + } + + for (int j = 0; j < col; j++) { + int k = 0; + for (int i = 0; i < row; i++) { + if (h[i * col + j] != -1) { + // although h is transposed, the (x,y) is still (iBlkRow, iBlkCol) + h_element_temp.x = i; + h_element_temp.y = j; + h_element_temp.value = h[i * col + j]; + h_compact2[k * col + j] = h_element_temp; + k++; + } + } + } + + /* + for(int i = 0; i < compact_col; i++){ + for(int j = 0; j < row; j++){ + printf("%3d, ", h_compact1[i*row+j].value); + } + printf("\n"); } - for(int j = 0; j < col; j++){ - int k=0; - for(int i = 0; i < row; i++){ - if(h[i*col+j] != -1){ - // although h is transposed, the (x,y) is still (iBlkRow, iBlkCol) - h_element_temp.x = i; - h_element_temp.y = j; - h_element_temp.value = h[i*col+j]; - h_compact2[k*col+j] = h_element_temp; - k++; - } - } - } - - /* - for(int i = 0; i < compact_col; i++){ - for(int j = 0; j < row; j++){ - printf("%3d, ", h_compact1[i*row+j].value); - } - printf("\n"); - } - - for(int i = 0; i < compact_row; i++){ - for(int j = 0; j < col; j++){ - printf("%3d,", h_compact2[i*col+j].value); - } - printf("\n"); - } - */ + for(int i = 0; i < compact_row; i++){ + for(int j = 0; j < col; j++){ + printf("%3d,", h_compact2[i*col+j].value); + } + printf("\n"); + } + */ } extern "C" void init_LLR_DMA(t_nrLDPC_dec_params* p_decParams, int8_t* p_llr, int8_t* p_out){ - - uint16_t Zc = p_decParams->Z; - uint8_t BG = p_decParams->BG; - int block_length = p_decParams->block_length; - uint8_t row,col; - if(BG == 1){ - row = 46; - col = 68; - } - else{ - row = 42; - col = 52; - } - unsigned char *hard_decision = (unsigned char*)p_out; - int memorySize_llr_cuda = col * Zc * sizeof(char) * MC; - cudaCheck( cudaMemcpyToSymbol(dev_const_llr, p_llr, memorySize_llr_cuda) ); - cudaCheck( cudaMemcpyToSymbol(dev_llr, p_llr, memorySize_llr_cuda) ); - cudaDeviceSynchronize(); - + uint16_t Zc = p_decParams->Z; + uint8_t BG = p_decParams->BG; + uint8_t col; + if (BG == 1) { + col = 68; + } else { + col = 52; + } + int memorySize_llr_cuda = col * Zc * sizeof(char) * MC; + cudaCheck(cudaMemcpyToSymbol(dev_const_llr, p_llr, memorySize_llr_cuda)); + cudaCheck(cudaMemcpyToSymbol(dev_llr, p_llr, memorySize_llr_cuda)); + cudaDeviceSynchronize(); } using namespace std ; /* from here: entry points in decoder shared lib */ extern "C" -int ldpc_autoinit(void) { // called by the library loader -/*int devices = 0; +int ldpc_autoinit(void) { // called by the library loader + /*int devices = 0; - cudaError_t err = cudaGetDeviceCount(&devices); - AssertFatal(devices>0,"\nNo cuda GPU found\n\n"); + cudaError_t err = cudaGetDeviceCount(&devices); + AssertFatal(devices>0,"\nNo cuda GPU found\n\n"); const int kb = 1024; const int mb = kb * kb; wcout << "NBody.GPU" << endl << "=========" << endl << endl; - wcout << "CUDA version: v" << CUDART_VERSION << endl; - + wcout << "CUDA version: v" << CUDART_VERSION << endl; + wcout << "CUDA Devices: " << endl << endl; for(int i = 0; i < devices; ++i) { - cudaDeviceProp props; - cudaGetDeviceProperties(&props, i); - wcout << i << ": " << props.name << ": " << props.major << "." << props.minor << endl; - wcout << " Global memory: " << props.totalGlobalMem / mb << "mb" << endl; - wcout << " Shared memory: " << props.sharedMemPerBlock / kb << "kb" << endl; - wcout << " Constant memory: " << props.totalConstMem / kb << "kb" << endl; - wcout << " Block registers: " << props.regsPerBlock << endl << endl; + cudaDeviceProp props; + cudaGetDeviceProperties(&props, i); + wcout << i << ": " << props.name << ": " << props.major << "." << props.minor << endl; + wcout << " Global memory: " << props.totalGlobalMem / mb << "mb" << endl; + wcout << " Shared memory: " << props.sharedMemPerBlock / kb << "kb" << endl; + wcout << " Constant memory: " << props.totalConstMem / kb << "kb" << endl; + wcout << " Block registers: " << props.regsPerBlock << endl << endl; - wcout << " Warp size: " << props.warpSize << endl; - wcout << " Threads per block: " << props.maxThreadsPerBlock << endl; - wcout << " Max block dimensions: [ " << props.maxThreadsDim[0] << ", " << props.maxThreadsDim[1] << ", " << props.maxThreadsDim[2] << " ]" << endl; - wcout << " Max grid dimensions: [ " << props.maxGridSize[0] << ", " << props.maxGridSize[1] << ", " << props.maxGridSize[2] << " ]" << endl; - wcout << endl; + wcout << " Warp size: " << props.warpSize << endl; + wcout << " Threads per block: " << props.maxThreadsPerBlock << endl; + wcout << " Max block dimensions: [ " << props.maxThreadsDim[0] << ", " << props.maxThreadsDim[1] << ", " << + props.maxThreadsDim[2] << " ]" << endl; wcout << " Max grid dimensions: [ " << props.maxGridSize[0] << ", " << + props.maxGridSize[1] << ", " << props.maxGridSize[2] << " ]" << endl; wcout << endl; } -*/ + */ warmup_for_GPU(); return 0; } -extern "C" -void nrLDPC_initcall(t_nrLDPC_dec_params* p_decParams, int8_t* p_llr, int8_t* p_out) { - set_compact_BG(p_decParams->Z,p_decParams->BG); - init_LLR_DMA(p_decParams, p_llr, p_out); -} - - -extern "C" -int32_t nrLDPC_decod(t_nrLDPC_dec_params* p_decParams, int8_t* p_llr, int8_t* p_out,t_nrLDPC_procBuf* p_procBuf, t_nrLDPC_time_stats *time_decoder) +extern "C" int32_t LDPCinit() { - uint16_t Zc = p_decParams->Z; - uint8_t BG = p_decParams->BG; - uint8_t numMaxIter = p_decParams->numMaxIter; - int block_length = p_decParams->block_length; - e_nrLDPC_outMode outMode = p_decParams->outMode; - cudaError_t cudaStatus; - uint8_t row,col; - if(BG == 1){ - row = 46; - col = 68; - } - else{ - row = 42; - col = 52; - } - -// alloc memory - unsigned char *hard_decision = (unsigned char*)p_out; -// gpu - int memorySize_llr_cuda = col * Zc * sizeof(char) * MC; - cudaCheck( cudaMemcpyToSymbol(dev_const_llr, p_llr, memorySize_llr_cuda) ); - cudaCheck( cudaMemcpyToSymbol(dev_llr, p_llr, memorySize_llr_cuda) ); - -// Define CUDA kernel dimension - int blockSizeX = Zc; - dim3 dimGridKernel1(row, MC, 1); // dim of the thread blocks - dim3 dimBlockKernel1(blockSizeX, 1, 1); - - dim3 dimGridKernel2(col, MC, 1); - dim3 dimBlockKernel2(blockSizeX, 1, 1); - cudaDeviceSynchronize(); - -// lauch kernel - - for(int ii = 0; ii < MAX_ITERATION; ii++){ - // first kernel - if(ii == 0){ - ldpc_cnp_kernel_1st_iter - <<>> - (/*dev_llr,*/ BG, row, col, Zc); - }else{ - ldpc_cnp_kernel - <<>> - (/*dev_llr,*/ BG, row, col, Zc); - } - // second kernel - ldpc_vnp_kernel_normal - <<>> - // (dev_llr, dev_const_llr,BG, row, col, Zc); - (BG, row, col, Zc); - } - - int pack = (block_length/128)+1; - dim3 pack_block(pack, MC, 1); - pack_decoded_bit<<>>(/*dev_llr,*/ /*dev_tmp,*/ col, Zc); - - cudaCheck( cudaMemcpyFromSymbol((void*)hard_decision, (const void*)dev_tmp, (block_length/8)*sizeof(unsigned char)) ); - cudaDeviceSynchronize(); - - - return MAX_ITERATION; - + return 0; +} + +extern "C" void LDPCshutdown() +{ +} + +extern "C" int32_t LDPCdecoder(t_nrLDPC_dec_params *p_decParams, + uint8_t harq_pid, + uint8_t ulsch_id, + uint8_t C, + int8_t *p_llr, + int8_t *p_out, + t_nrLDPC_time_stats *, + decode_abort_t *ab) +{ + set_compact_BG(p_decParams->Z, p_decParams->BG); + init_LLR_DMA(p_decParams, p_llr, p_out); + uint16_t Zc = p_decParams->Z; + uint8_t BG = p_decParams->BG; + int block_length = p_decParams->E; + uint8_t row, col; + if (BG == 1) { + row = 46; + col = 68; + } else { + row = 42; + col = 52; + } + + // alloc memory + unsigned char* hard_decision = (unsigned char*)p_out; + // gpu + int memorySize_llr_cuda = col * Zc * sizeof(char) * MC; + cudaCheck(cudaMemcpyToSymbol(dev_const_llr, p_llr, memorySize_llr_cuda)); + cudaCheck(cudaMemcpyToSymbol(dev_llr, p_llr, memorySize_llr_cuda)); + + // Define CUDA kernel dimension + int blockSizeX = Zc; + dim3 dimGridKernel1(row, MC, 1); // dim of the thread blocks + dim3 dimBlockKernel1(blockSizeX, 1, 1); + + dim3 dimGridKernel2(col, MC, 1); + dim3 dimBlockKernel2(blockSizeX, 1, 1); + cudaDeviceSynchronize(); + + // lauch kernel + + for (int ii = 0; ii < MAX_ITERATION; ii++) { + // first kernel + if (ii == 0) { + ldpc_cnp_kernel_1st_iter<<>>(/*dev_llr,*/ BG, row, col, Zc); + } else { + ldpc_cnp_kernel<<>>(/*dev_llr,*/ BG, row, col, Zc); + } + // second kernel + ldpc_vnp_kernel_normal<<>> + // (dev_llr, dev_const_llr,BG, row, col, Zc); + (BG, row, col, Zc); + } + + int pack = (block_length / 128) + 1; + dim3 pack_block(pack, MC, 1); + pack_decoded_bit<<>>(/*dev_llr,*/ /*dev_tmp,*/ col, Zc); + + cudaCheck(cudaMemcpyFromSymbol((void*)hard_decision, (const void*)dev_tmp, (block_length / 8) * sizeof(unsigned char))); + cudaDeviceSynchronize(); + + return MAX_ITERATION; } diff --git a/openair1/PHY/CODING/nrLDPC_defs.h b/openair1/PHY/CODING/nrLDPC_defs.h index 57d84bf8cb..c9e5454087 100644 --- a/openair1/PHY/CODING/nrLDPC_defs.h +++ b/openair1/PHY/CODING/nrLDPC_defs.h @@ -47,7 +47,7 @@ typedef struct { time_stats_t *toutput; int Kr; uint32_t Kb; - uint32_t *Zc; + uint32_t Zc; void *harq; /// Encoder BG uint8_t BG; @@ -57,13 +57,16 @@ typedef struct { uint32_t K; /// Number of "Filler" bits uint32_t F; - /// LDPC-code outputs - uint8_t *d[MAX_NUM_NR_DLSCH_SEGMENTS_PER_LAYER*NR_MAX_NB_LAYERS]; + /// Modulation order + uint8_t Qm; + uint32_t E; + unsigned int G; + // Redundancy version index + uint8_t rv; } encoder_implemparams_t; -#define INIT0_LDPCIMPLEMPARAMS {0,0,0,NULL,NULL,NULL,NULL} -typedef void(*nrLDPC_initcallfunc_t)(t_nrLDPC_dec_params *p_decParams, int8_t *p_llr, int8_t *p_out); -typedef int(*nrLDPC_encoderfunc_t)(unsigned char **,unsigned char **,int,int,short, short, encoder_implemparams_t *); -//============================================================================================================================ + +typedef int32_t(LDPC_initfunc_t)(void); +typedef int32_t(LDPC_shutdownfunc_t)(void); // decoder interface /** \brief LDPC decoder API type definition @@ -73,8 +76,14 @@ typedef int(*nrLDPC_encoderfunc_t)(unsigned char **,unsigned char **,int,int,sho \param p_profiler LDPC profiler statistics */ -typedef int32_t (*nrLDPC_decoderfunc_t)(t_nrLDPC_dec_params *, int8_t *, int8_t *, t_nrLDPC_time_stats *, decode_abort_t *ab); -typedef int32_t(*nrLDPC_decoffloadfunc_t)(t_nrLDPC_dec_params* , uint8_t, uint8_t, uint8_t , uint8_t, uint16_t, uint32_t, uint8_t, int8_t*, int8_t* ,uint8_t); -typedef int32_t(*nrLDPC_dectopfunc_t)(void); +typedef int32_t(LDPC_decoderfunc_t)(t_nrLDPC_dec_params *p_decParams, + uint8_t harq_pid, + uint8_t ulsch_id, + uint8_t C, + int8_t *p_llr, + int8_t *p_out, + t_nrLDPC_time_stats *, + decode_abort_t *ab); +typedef int32_t(LDPC_encoderfunc_t)(uint8_t **, uint8_t **, encoder_implemparams_t *); #endif diff --git a/openair1/PHY/CODING/nrLDPC_encoder/ldpc_encoder.c b/openair1/PHY/CODING/nrLDPC_encoder/ldpc_encoder.c index 1e1b3c156f..f6d065a75b 100644 --- a/openair1/PHY/CODING/nrLDPC_encoder/ldpc_encoder.c +++ b/openair1/PHY/CODING/nrLDPC_encoder/ldpc_encoder.c @@ -38,44 +38,29 @@ #include "defs.h" #include "assertions.h" #include "openair1/PHY/CODING/nrLDPC_defs.h" +#include "openair1/PHY/CODING/nrLDPC_extern.h" #include "ldpc_generate_coefficient.c" - -int ldpc_encoder_orig(uint8_t *test_input,uint8_t *channel_input,int Zc,int Kb,short block_length, short BG,uint8_t gen_code) +int LDPCencoder(unsigned char **inputArray, unsigned char **outputArray, encoder_implemparams_t *impp) { + const unsigned char *input = inputArray[0]; + // channel input is the output of this function! + unsigned char *output = outputArray[0]; + const int Zc = impp->Zc; + const int Kb = impp->Kb; + const short block_length = impp->K; + const short BG = impp->BG; + const uint8_t gen_code = impp->gen_code; uint8_t c[22*384]; //padded input, unpacked, max size - uint8_t d[68*384]; //coded output, unpacked, max size - uint8_t channel_temp,temp; - short *Gen_shift_values, *no_shift_values, *pointer_shift_values; - - short nrows = 46;//parity check bits - short ncols = 22;//info bits - + uint8_t d[68 * 384]; // coded output, unpacked, max size int i,i1,i2,i3,i4,i5,temp_prime,var; - int no_punctured_columns,removed_bit,rate=3; + int no_punctured_columns, removed_bit; int nind=0; int indlist[1000]; int indlist2[1000]; - //determine number of bits in codeword - //if (block_length>3840) - if (BG==1) - { - nrows=46; //parity check bits - ncols=22; //info bits - rate=3; - } - //else if (block_length<=3840) - else if (BG==2) - { - //BG=2; - nrows=42; //parity check bits - ncols=10; // info bits - rate=5; - } - - Gen_shift_values=choose_generator_matrix(BG,Zc); + const short *Gen_shift_values = choose_generator_matrix(BG, Zc); if (Gen_shift_values==NULL) { printf("ldpc_encoder_orig: could not find generator matrix\n"); return(-1); @@ -83,21 +68,14 @@ int ldpc_encoder_orig(uint8_t *test_input,uint8_t *channel_input,int Zc,int Kb,s //printf("ldpc_encoder_orig: BG %d, Zc %d, Kb %d\n",BG, Zc, Kb); + AssertFatal(BG <= 2, "BG %d is not supported yet\n", BG); // load base graph of generator matrix - if (BG==1) - { - no_shift_values=(short *) no_shift_values_BG1; - pointer_shift_values=(short *) pointer_shift_values_BG1; - } - else if (BG==2) - { - no_shift_values=(short *) no_shift_values_BG2; - pointer_shift_values=(short *) pointer_shift_values_BG2; - } - else { - AssertFatal(0,"BG %d is not supported yet\n",BG); - } - + const short nrows = BG == 1 ? 46 : 42; + const short ncols = BG == 1 ? 22 : 10; + const short rate = BG == 1 ? 3 : 5; + const short *no_shift_values = BG == 1 ? no_shift_values_BG1 : no_shift_values_BG2; + const short *pointer_shift_values = BG == 1 ? pointer_shift_values_BG1 : pointer_shift_values_BG2; + no_punctured_columns=(int)((nrows-2)*Zc+block_length-block_length*rate)/Zc; removed_bit=(nrows-no_punctured_columns-2) * Zc+block_length-(block_length*rate); //printf("%d\n",no_punctured_columns); @@ -108,9 +86,9 @@ int ldpc_encoder_orig(uint8_t *test_input,uint8_t *channel_input,int Zc,int Kb,s for (i=0; i>7&1; - c[i]=(test_input[i/8]&(128>>(i&7)))>>(7-(i&7)); + // c[i] = input[i/8]<<(i%8); + // c[i]=c[i]>>7&1; + c[i] = (input[i / 8] & (128 >> (i & 7))) >> (7 - (i & 7)); } // parity check part @@ -188,10 +166,9 @@ int ldpc_encoder_orig(uint8_t *test_input,uint8_t *channel_input,int Zc,int Kb,s fprintf(fd2," c2=&csimd[i2];\n"); fprintf(fd2," d2=&dsimd[i2];\n"); - for (i1=0; i1 < nrows; i1++) + for (i1 = 0; i1 < nrows; i1++) { - channel_temp=0; fprintf(fd,"\n//row: %d\n",i1); fprintf(fd2,"\n//row: %d\n",i1); fprintf(fd," d2[%d]=",(Zc*i1)>>shift); @@ -225,8 +202,7 @@ int ldpc_encoder_orig(uint8_t *test_input,uint8_t *channel_input,int Zc,int Kb,s fprintf(fd2,"c2[%d]",indlist2[i4]); for (i4=0;i4gen_code); + memcpy(&output[0], &c[2 * Zc], block_length - 2 * Zc); + memcpy(&output[block_length - 2 * Zc], &d[0], (nrows - no_punctured_columns) * Zc - removed_bit); + // memcpy(output,c,Kb*Zc*sizeof(unsigned char)); + return block_length - 2 * Zc + (nrows - no_punctured_columns) * Zc - removed_bit; } diff --git a/openair1/PHY/CODING/nrLDPC_encoder/ldpc_encoder2.c b/openair1/PHY/CODING/nrLDPC_encoder/ldpc_encoder2.c deleted file mode 100644 index 1cdb75f459..0000000000 --- a/openair1/PHY/CODING/nrLDPC_encoder/ldpc_encoder2.c +++ /dev/null @@ -1,656 +0,0 @@ -/* - * 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 ldpc_encoder2.c - * \brief Defines the optimized LDPC encoder - * \author Florian Kaltenberger, Raymond Knopp, Kien le Trung (Eurecom) - * \email openair_tech@eurecom.fr - * \date 27-03-2018 - * \version 1.0 - * \note - * \warning - */ - -#include -#include -#include -#include -#include -#include "assertions.h" -#include "common/utils/LOG/log.h" -#include "time_meas.h" -#include "defs.h" -#include "PHY/sse_intrin.h" - -#include "ldpc384_byte.c" -#include "ldpc352_byte.c" -#include "ldpc320_byte.c" -#include "ldpc288_byte.c" -#include "ldpc256_byte.c" -#include "ldpc240_byte.c" -#include "ldpc224_byte.c" -#include "ldpc208_byte.c" -#include "ldpc192_byte.c" -#include "ldpc176_byte.c" -#include "ldpc384_byte_128.c" -#include "ldpc352_byte_128.c" -#include "ldpc320_byte_128.c" -#include "ldpc288_byte_128.c" -#include "ldpc256_byte_128.c" -#include "ldpc224_byte_128.c" -#include "ldpc192_byte_128.c" -#include "ldpc_BG2_Zc384_byte.c" -#include "ldpc_BG2_Zc352_byte.c" -#include "ldpc_BG2_Zc320_byte.c" -#include "ldpc_BG2_Zc288_byte.c" -#include "ldpc_BG2_Zc256_byte.c" -#include "ldpc_BG2_Zc240_byte.c" -#include "ldpc_BG2_Zc224_byte.c" -#include "ldpc_BG2_Zc208_byte.c" -#include "ldpc_BG2_Zc192_byte.c" -#include "ldpc_BG2_Zc176_byte.c" -#include "ldpc_BG2_Zc160_byte.c" -#include "ldpc_BG2_Zc144_byte.c" -#include "ldpc_BG2_Zc128_byte.c" -#include "ldpc_BG2_Zc120_byte.c" -#include "ldpc_BG2_Zc112_byte.c" -#include "ldpc_BG2_Zc104_byte.c" -#include "ldpc_BG2_Zc96_byte.c" -#include "ldpc_BG2_Zc88_byte.c" -#include "ldpc_BG2_Zc80_byte.c" -#include "ldpc_BG2_Zc72_byte.c" - - - -void encode_parity_check_part_optim(uint8_t *c,uint8_t *d, short BG,short Zc,short Kb) -{ - - if (BG==1) - { - switch (Zc) - { - case 2: break; - case 3: break; - case 4: break; - case 5: break; - case 6: break; - case 7: break; - case 8: break; - case 9: break; - case 10: break; - case 11: break; - case 12: break; - case 13: break; - case 14: break; - case 15: break; - case 16: break; - case 18: break; - case 20: break; - case 22: break; - case 24: break; - case 26: break; - case 28: break; - case 30: break; - case 32: break; - case 36: break; - case 40: break; - case 44: break; - case 48: break; - case 52: break; - case 56: break; - case 60: break; - case 64: break; - case 72: break; - case 80: break; - case 88: break; - case 96: break; - case 104: break; - case 112: break; - case 120: break; - case 128: break; - case 144: break; - case 160: break; - case 176: ldpc176_byte(c,d); break; - case 192: ldpc192_byte(c,d); break; - case 208: ldpc208_byte(c,d); break; - case 224: ldpc224_byte(c,d); break; - case 240: ldpc240_byte(c,d); break; - case 256: ldpc256_byte(c,d); break; - case 288: ldpc288_byte(c,d); break; - case 320: ldpc320_byte(c,d); break; - case 352: ldpc352_byte(c,d); break; - case 384: ldpc384_byte(c,d); break; - default: AssertFatal(0,"BG %d Zc %d is not supported yet\n",BG,Zc); break; - } - } - else if (BG==2) { - switch (Zc) - { - case 2: break; - case 3: break; - case 4: break; - case 5: break; - case 6: break; - case 7: break; - case 8: break; - case 9: break; - case 10: break; - case 11: break; - case 12: break; - case 13: break; - case 14: break; - case 15: break; - case 16: break; - case 18: break; - case 20: break; - case 22: break; - case 24: break; - case 26: break; - case 28: break; - case 30: break; - case 32: break; - case 36: break; - case 40: break; - case 44: break; - case 48: break; - case 52: break; - case 56: break; - case 60: break; - case 64: break; - case 72: ldpc_BG2_Zc72_byte(c,d); break; - case 80: ldpc_BG2_Zc80_byte(c,d); break; - case 88: ldpc_BG2_Zc88_byte(c,d); break; - case 96: ldpc_BG2_Zc96_byte(c,d); break; - case 104: ldpc_BG2_Zc104_byte(c,d); break; - case 112: ldpc_BG2_Zc112_byte(c,d); break; - case 120: ldpc_BG2_Zc120_byte(c,d); break; - case 128: ldpc_BG2_Zc128_byte(c,d); break; - case 144: ldpc_BG2_Zc144_byte(c,d); break; - case 160: ldpc_BG2_Zc160_byte(c,d); break; - case 176: ldpc_BG2_Zc176_byte(c,d); break; - case 192: ldpc_BG2_Zc192_byte(c,d); break; - case 208: ldpc_BG2_Zc208_byte(c,d); break; - case 224: ldpc_BG2_Zc224_byte(c,d); break; - case 240: ldpc_BG2_Zc240_byte(c,d); break; - case 256: ldpc_BG2_Zc256_byte(c,d); break; - case 288: ldpc_BG2_Zc288_byte(c,d); break; - case 320: ldpc_BG2_Zc320_byte(c,d); break; - case 352: ldpc_BG2_Zc352_byte(c,d); break; - case 384: ldpc_BG2_Zc384_byte(c,d); break; - default: AssertFatal(0,"BG %d Zc %d is not supported yet\n",BG,Zc); break; - } - } - else { - AssertFatal(0,"BG %d is not supported yet\n",BG); - } - -} - - -int ldpc_encoder_optim(unsigned char *test_input,unsigned char *channel_input,int Zc,int Kb,short block_length,short BG,time_stats_t *tinput,time_stats_t *tprep,time_stats_t *tparity,time_stats_t *toutput) -{ - - short nrows=0,ncols=0; - int i,i1,rate=3; - int no_punctured_columns,removed_bit; - - int simd_size; - - //determine number of bits in codeword - //if (block_length>3840) - if (BG==1) - { - //BG=1; - nrows=46; //parity check bits - ncols=22; //info bits - rate=3; - } - //else if (block_length<=3840) - else if (BG==2) - { - //BG=2; - nrows=42; //parity check bits - ncols=10; // info bits - rate=5; - - } - - -#ifdef DEBUG_LDPC - LOG_D(PHY,"ldpc_encoder_optim_8seg: BG %d, Zc %d, Kb %d, block_length %d\n",BG,Zc,Kb,block_length); - LOG_D(PHY,"ldpc_encoder_optim_8seg: PDU %x %x %x %x\n",test_input[0],test_input[1],test_input[2],test_input[3]); -#endif - - if ((Zc&31) > 0) simd_size = 16; - else simd_size = 32; - - unsigned char c[22*Zc] __attribute__((aligned(32))); //padded input, unpacked, max size - unsigned char d[46*Zc] __attribute__((aligned(32))); //coded parity part output, unpacked, max size - - unsigned char c_extension[2*22*Zc*simd_size] __attribute__((aligned(32))); //double size matrix of c - - // calculate number of punctured bits - no_punctured_columns=(int)((nrows-2)*Zc+block_length-block_length*rate)/Zc; - removed_bit=(nrows-no_punctured_columns-2) * Zc+block_length-(int)(block_length*rate); - // printf("%d\n",no_punctured_columns); - // printf("%d\n",removed_bit); - // unpack input - memset(c,0,sizeof(unsigned char) * ncols * Zc); - memset(d,0,sizeof(unsigned char) * nrows * Zc); - - if(tinput != NULL) start_meas(tinput); - for (i=0; i>(i&7)))>>(7-(i&7)); - //printf("c(%d,%d)=%d\n",j,i,temp); - } - - if(tinput != NULL) stop_meas(tinput); - - if ((BG==1 && Zc>176) || (BG==2 && Zc>64)) { - // extend matrix - if(tprep != NULL) start_meas(tprep); - for (i1=0; i1 < ncols; i1++) - { - memcpy(&c_extension[2*i1*Zc], &c[i1*Zc], Zc*sizeof(unsigned char)); - memcpy(&c_extension[(2*i1+1)*Zc], &c[i1*Zc], Zc*sizeof(unsigned char)); - } - for (i1=1;i1 8 bytes, pattern repeats. - simde__m256i zero256 = simde_mm256_setzero_si256(); - simde__m256i masks[8]; - register simde__m256i c256; - masks[0] = simde_mm256_set1_epi8(0x1); - masks[1] = simde_mm256_set1_epi8(0x2); - masks[2] = simde_mm256_set1_epi8(0x4); - masks[3] = simde_mm256_set1_epi8(0x8); - masks[4] = simde_mm256_set1_epi8(0x10); - masks[5] = simde_mm256_set1_epi8(0x20); - masks[6] = simde_mm256_set1_epi8(0x40); - masks[7] = simde_mm256_set1_epi8(0x80); - - AssertFatal(n_segments>0&&n_segments<=8,"0 < n_segments %d <= 8\n",n_segments); - - //determine number of bits in codeword - //if (block_length>3840) - if (BG==1) - { - nrows=46; //parity check bits - ncols=22; //info bits - rate=3; - } - //else if (block_length<=3840) - else if (BG==2) - { - //BG=2; - nrows=42; //parity check bits - ncols=10; // info bits - rate=5; - - } - -#ifdef DEBUG_LDPC - LOG_D(PHY,"ldpc_encoder_optim_8seg: BG %d, Zc %d, Kb %d, block_length %d, segments %d\n",BG,Zc,Kb,block_length,n_segments); - LOG_D(PHY,"ldpc_encoder_optim_8seg: PDU (seg 0) %x %x %x %x\n",test_input[0][0],test_input[0][1],test_input[0][2],test_input[0][3]); -#endif - - AssertFatal(Zc>0,"no valid Zc found for block length %d\n",block_length); - - if ((Zc&31) > 0) simd_size = 16; - else simd_size = 32; - - unsigned char c[22*Zc] __attribute__((aligned(32))); //padded input, unpacked, max size - unsigned char d[46*Zc] __attribute__((aligned(32))); //coded parity part output, unpacked, max size - - unsigned char c_extension[2*22*Zc*simd_size] __attribute__((aligned(32))); //double size matrix of c - - // calculate number of punctured bits - no_punctured_columns=(int)((nrows-2)*Zc+block_length-block_length*rate)/Zc; - removed_bit=(nrows-no_punctured_columns-2) * Zc+block_length-(int)(block_length*rate); - // printf("%d\n",no_punctured_columns); - // printf("%d\n",removed_bit); - // unpack input - memset(c,0,sizeof(unsigned char) * ncols * Zc); - memset(d,0,sizeof(unsigned char) * nrows * Zc); - - if(tinput != NULL) start_meas(tinput); -#if 0 - for (i=0; i>(i&7)))>>(7-(i&7)); - //printf("c(%d,%d)=%d\n",j,i,temp); - c[i] |= (temp << j); - } - } -#else - for (i=0; i>5; i++) { - c256 = simde_mm256_and_si256(simde_mm256_cmpeq_epi8(simde_mm256_andnot_si256(simde_mm256_shuffle_epi8(simde_mm256_set1_epi32(((uint32_t*)test_input[0])[i]), shufmask),andmask),zero256),masks[0]); - for (j=1; j>5)<<5;i>(i&7)))>>(7-(i&7)); - //printf("c(%d,%d)=%d\n",j,i,temp); - c[i] |= (temp << j); - } - } -#endif - - if(tinput != NULL) stop_meas(tinput); - - if ((BG==1 && Zc>176) || (BG==2 && Zc>64)) { - // extend matrix - if(tprep != NULL) start_meas(tprep); - for (i1=0; i1 < ncols; i1++) - { - memcpy(&c_extension[2*i1*Zc], &c[i1*Zc], Zc*sizeof(unsigned char)); - memcpy(&c_extension[(2*i1+1)*Zc], &c[i1*Zc], Zc*sizeof(unsigned char)); - } - for (i1=1;i1>5; - uint32_t l2 = ((nrows-no_punctured_columns) * Zc-removed_bit)>>5; - simde__m256i *c256p = (simde__m256i *)&c[2 * Zc]; - simde__m256i *d256p = (simde__m256i *)&d[0]; - // if (((block_length-(2*Zc))&31)>0) l1++; - - for (i=0;i0) l2++; - - for (i1=0;i1>j)&1; - for (i=0;i<((nrows-no_punctured_columns) * Zc-removed_bit);i++) - for (j=0; j>j)&1; - } - - if(toutput != NULL) stop_meas(toutput); - return 0; -} - -int ldpc_encoder_optim_8seg_multi(unsigned char **test_input,unsigned char **channel_input,int Zc,int Kb,short block_length, short BG, int n_segments,unsigned int macro_num, time_stats_t *tinput,time_stats_t *tprep,time_stats_t *tparity,time_stats_t *toutput) -{ - - short nrows=0,ncols=0; - int i,i1,j,rate=3; - int no_punctured_columns,removed_bit; - //Table of possible lifting sizes - char temp; - int simd_size; - unsigned int macro_segment, macro_segment_end; - - - macro_segment = 8*macro_num; - macro_segment_end = (n_segments > 8*(macro_num+1)) ? 8*(macro_num+1) : n_segments; - //macro_segment_end = macro_segment + (n_segments > 8 ? 8 : n_segments); - //printf("macro_segment: %d\n", macro_segment); - //printf("macro_segment_end: %d\n", macro_segment_end ); - - simde__m256i shufmask = simde_mm256_set_epi64x(0x0303030303030303, 0x0202020202020202, 0x0101010101010101, 0x0000000000000000); - simde__m256i andmask = simde_mm256_set1_epi64x(0x0102040810204080); // every 8 bits -> 8 bytes, pattern repeats. - simde__m256i zero256 = simde_mm256_setzero_si256(); - simde__m256i masks[8]; - register simde__m256i c256; - masks[0] = simde_mm256_set1_epi8(0x1); - masks[1] = simde_mm256_set1_epi8(0x2); - masks[2] = simde_mm256_set1_epi8(0x4); - masks[3] = simde_mm256_set1_epi8(0x8); - masks[4] = simde_mm256_set1_epi8(0x10); - masks[5] = simde_mm256_set1_epi8(0x20); - masks[6] = simde_mm256_set1_epi8(0x40); - masks[7] = simde_mm256_set1_epi8(0x80); - - //determine number of bits in codeword - if (BG==1) - { - nrows=46; //parity check bits - ncols=22; //info bits - rate=3; - } - else if (BG==2) - { - nrows=42; //parity check bits - ncols=10; // info bits - rate=5; - } - -#ifdef DEBUG_LDPC - LOG_D(PHY,"ldpc_encoder_optim_8seg: BG %d, Zc %d, Kb %d, block_length %d, segments %d\n",BG,Zc,Kb,block_length,n_segments); - LOG_D(PHY,"ldpc_encoder_optim_8seg: PDU (seg 0) %x %x %x %x\n",test_input[0][0],test_input[0][1],test_input[0][2],test_input[0][3]); -#endif - - AssertFatal(Zc>0,"no valid Zc found for block length %d\n",block_length); - - if ((Zc&31) > 0) simd_size = 16; - else simd_size = 32; - - unsigned char c[22*Zc] __attribute__((aligned(32))); //padded input, unpacked, max size - unsigned char d[46*Zc] __attribute__((aligned(32))); //coded parity part output, unpacked, max size - - unsigned char c_extension[2*22*Zc*simd_size] __attribute__((aligned(32))); //double size matrix of c - - // calculate number of punctured bits - no_punctured_columns=(int)((nrows-2)*Zc+block_length-block_length*rate)/Zc; - removed_bit=(nrows-no_punctured_columns-2) * Zc+block_length-(int)(block_length*rate); - //printf("%d\n",no_punctured_columns); - //printf("%d\n",removed_bit); - // unpack input - memset(c,0,sizeof(unsigned char) * ncols * Zc); - memset(d,0,sizeof(unsigned char) * nrows * Zc); - - if(tinput != NULL) start_meas(tinput); -#if 0 - for (i=0; i>(i&7); - //printf("c(%d,%d)=%d\n",j,i,temp); - c[i] |= (temp << (j-macro_segment)); - } - } -#else - for (i=0; i>5; i++) { - c256 = simde_mm256_and_si256(simde_mm256_cmpeq_epi8(simde_mm256_andnot_si256(simde_mm256_shuffle_epi8(simde_mm256_set1_epi32(((uint32_t*)test_input[macro_segment])[i]), shufmask),andmask),zero256),masks[0]); - //for (j=1; j>5)<<5;i>(i&7)))>>(7-(i&7)); - //printf("c(%d,%d)=%d\n",j,i,temp); - c[i] |= (temp << (j-macro_segment)); - } - } -#endif - - if(tinput != NULL) stop_meas(tinput); - - if ((BG==1 && Zc>176) || (BG==2 && Zc>64)) { - // extend matrix - if(tprep != NULL) start_meas(tprep); - for (i1=0; i1 < ncols; i1++) - { - memcpy(&c_extension[2*i1*Zc], &c[i1*Zc], Zc*sizeof(unsigned char)); - memcpy(&c_extension[(2*i1+1)*Zc], &c[i1*Zc], Zc*sizeof(unsigned char)); - } - for (i1=1;i1>5; - uint32_t l2 = ((nrows-no_punctured_columns) * Zc-removed_bit)>>5; - simde__m256i *c256p = (simde__m256i *)&c[2 * Zc]; - simde__m256i *d256p = (simde__m256i *)&d[0]; - // if (((block_length-(2*Zc))&31)>0) l1++; - - for (i=0;i0) l2++; - - for (i1=0;i1>(j-macro_segment))&1; - for (i=0;i<((nrows-no_punctured_columns) * Zc-removed_bit);i++) - //for (j=0; j>(j-macro_segment))&1; - } - - if(toutput != NULL) stop_meas(toutput); - return 0; -} - diff --git a/openair1/PHY/CODING/nrLDPC_encoder/ldpc_encoder_optim.c b/openair1/PHY/CODING/nrLDPC_encoder/ldpc_encoder_optim.c index bf1e6f3400..bf663e0204 100644 --- a/openair1/PHY/CODING/nrLDPC_encoder/ldpc_encoder_optim.c +++ b/openair1/PHY/CODING/nrLDPC_encoder/ldpc_encoder_optim.c @@ -37,15 +37,17 @@ #include "common/utils/LOG/log.h" #include "time_meas.h" #include "openair1/PHY/CODING/nrLDPC_defs.h" +#include "openair1/PHY/CODING/nrLDPC_extern.h" #include "ldpc_encode_parity_check.c" #include "ldpc_generate_coefficient.c" - - -int nrLDPC_encod(unsigned char **test_input,unsigned char **channel_input,int Zc,int Kb,short block_length, short BG, encoder_implemparams_t *impp) +int LDPCencoder(uint8_t **test_input, uint8_t **channel_input, encoder_implemparams_t *impp) { - - short nrows=0,ncols=0; + int Zc = impp->Zc; + int Kb = impp->Kb; + int block_length = impp->K; + int BG = impp->BG; + int nrows=0,ncols=0; int rate=3; int no_punctured_columns,removed_bit; @@ -79,17 +81,17 @@ int nrLDPC_encod(unsigned char **test_input,unsigned char **channel_input,int Zc if ((Zc&31) > 0) simd_size = 16; else simd_size = 32; - unsigned char c[22*Zc] __attribute__((aligned(32))); //padded input, unpacked, max size - unsigned char d[46*Zc] __attribute__((aligned(32))); //coded parity part output, unpacked, max size + uint8_t c[22*Zc] __attribute__((aligned(32))); //padded input, unpacked, max size + uint8_t d[46*Zc] __attribute__((aligned(32))); //coded parity part output, unpacked, max size // calculate number of punctured bits no_punctured_columns=(int)((nrows-2)*Zc+block_length-block_length*rate)/Zc; - removed_bit=(nrows-no_punctured_columns-2) * Zc+block_length-(int)(block_length*rate); + removed_bit = (nrows - no_punctured_columns - 2) * Zc + block_length - block_length * rate; // printf("%d\n",no_punctured_columns); // printf("%d\n",removed_bit); // unpack input - memset(c,0,sizeof(unsigned char) * ncols * Zc); - memset(d,0,sizeof(unsigned char) * nrows * Zc); + memset(c, 0, sizeof(c)); + memset(d, 0, sizeof(d)); if(impp->tinput != NULL) start_meas(impp->tinput); for (int i=0; iZc; + int Kb = impp->Kb; + short block_length = impp->K; + short BG = impp->BG; short nrows=0,ncols=0; int i,i1,j,rate=3; diff --git a/openair1/PHY/CODING/nrLDPC_encoder/ldpc_encoder_optim8segmulti.c b/openair1/PHY/CODING/nrLDPC_encoder/ldpc_encoder_optim8segmulti.c index 7bbe9dfa78..6b48fee6fa 100644 --- a/openair1/PHY/CODING/nrLDPC_encoder/ldpc_encoder_optim8segmulti.c +++ b/openair1/PHY/CODING/nrLDPC_encoder/ldpc_encoder_optim8segmulti.c @@ -38,15 +38,19 @@ #include "time_meas.h" #include "openair1/PHY/CODING/nrLDPC_defs.h" #include "PHY/sse_intrin.h" +#include "openair1/PHY/CODING/nrLDPC_extern.h" #include "ldpc_encode_parity_check.c" #include "ldpc_generate_coefficient.c" - -int nrLDPC_encod(unsigned char **input,unsigned char **output,int Zc,int Kb,short block_length, short BG, encoder_implemparams_t *impp) +int LDPCencoder(uint8_t **input, uint8_t **output, encoder_implemparams_t *impp) { //set_log(PHY, 4); - + + int Zc = impp->Zc; + int Kb = impp->Kb; + short block_length = impp->K; + short BG = impp->BG; int nrows=0,ncols=0; int rate=3; diff --git a/openair1/PHY/CODING/nrLDPC_extern.h b/openair1/PHY/CODING/nrLDPC_extern.h index 5c24b5c3b5..dbfdae21b2 100644 --- a/openair1/PHY/CODING/nrLDPC_extern.h +++ b/openair1/PHY/CODING/nrLDPC_extern.h @@ -18,28 +18,29 @@ * For more information about the OpenAirInterface (OAI) Software Alliance: * contact@openairinterface.org */ +#ifndef _NRLDPC_EXTERN_H__ +#define _NRLDPC_EXTERN_H__ #include "openair1/PHY/CODING/nrLDPC_defs.h" -#ifdef LDPC_LOADER -nrLDPC_decoderfunc_t nrLDPC_decoder; -nrLDPC_encoderfunc_t nrLDPC_encoder; -nrLDPC_initcallfunc_t nrLDPC_initcall; -nrLDPC_decoffloadfunc_t nrLDPC_decoder_offload; -nrLDPC_dectopfunc_t top_testsuite; -#else +/* ldpc coder/decoder API*/ +typedef struct ldpc_interface_s { + LDPC_initfunc_t *LDPCinit; + LDPC_shutdownfunc_t *LDPCshutdown; + LDPC_decoderfunc_t *LDPCdecoder; + LDPC_encoderfunc_t *LDPCencoder; +} ldpc_interface_t; + +// Global var to limit the rework of the dirty legacy code +extern ldpc_interface_t ldpc_interface, ldpc_interface_offload; + /* functions to load the LDPC shared lib, implemented in openair1/PHY/CODING/nrLDPC_load.c */ -int load_nrLDPClib(char *version); -int load_nrLDPClib_offload(void); -int free_nrLDPClib_offload(void); -int load_nrLDPClib_ref(char *libversion, nrLDPC_encoderfunc_t *nrLDPC_encoder_ptr); // for ldpctest -/* ldpc coder/decoder functions, as loaded by load_nrLDPClib(). */ -extern nrLDPC_initcallfunc_t nrLDPC_initcall; +int load_LDPClib(char *version, ldpc_interface_t *); +int free_LDPClib(ldpc_interface_t *ldpc_interface); -extern nrLDPC_decoderfunc_t nrLDPC_decoder; -extern nrLDPC_encoderfunc_t nrLDPC_encoder; -extern nrLDPC_decoffloadfunc_t nrLDPC_decoder_offload; - -extern nrLDPC_dectopfunc_t top_testsuite; +LDPC_initfunc_t LDPCinit; +LDPC_shutdownfunc_t LDPCshutdown; +LDPC_decoderfunc_t LDPCdecoder; +LDPC_encoderfunc_t LDPCencoder; // inline functions: #endif diff --git a/openair1/PHY/CODING/nrLDPC_load.c b/openair1/PHY/CODING/nrLDPC_load.c index 5681605e97..b80887c327 100644 --- a/openair1/PHY/CODING/nrLDPC_load.c +++ b/openair1/PHY/CODING/nrLDPC_load.c @@ -35,20 +35,16 @@ #include #include "assertions.h" #include "common/utils/LOG/log.h" -#define LDPC_LOADER #include "PHY/CODING/nrLDPC_extern.h" -#include "common/config/config_userapi.h" -#include "common/utils/load_module_shlib.h" - - -/* function description array, to be used when loading the encoding/decoding shared lib */ -static loader_shlibfunc_t shlib_fdesc[3]; +#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 *arg[64]={"ldpctest",NULL}; -int load_nrLDPClib(char *version) { +int load_LDPClib(char *version, ldpc_interface_t *itf) +{ char *ptr = (char *)config_get_if(); char libname[64] = "ldpc"; @@ -56,76 +52,25 @@ int load_nrLDPClib(char *version) { uniqCfg = load_configmodule(1, arg, CONFIG_ENABLECMDLINEONLY); logInit(); } - shlib_fdesc[0].fname = "nrLDPC_decod"; - shlib_fdesc[1].fname = "nrLDPC_encod"; - shlib_fdesc[2].fname = "nrLDPC_initcall"; + /* function description array, to be used when loading the encoding/decoding shared lib */ + loader_shlibfunc_t shlib_fdesc[] = {{.fname = "LDPCinit"}, + {.fname = "LDPCshutdown"}, + {.fname = "LDPCdecoder"}, + {.fname = "LDPCencoder"}}; int ret; ret = load_module_version_shlib(libname, version, shlib_fdesc, sizeofArray(shlib_fdesc), NULL); AssertFatal((ret >= 0), "Error loading ldpc decoder"); - nrLDPC_decoder = (nrLDPC_decoderfunc_t)shlib_fdesc[0].fptr; - nrLDPC_encoder = (nrLDPC_encoderfunc_t)shlib_fdesc[1].fptr; - nrLDPC_initcall = (nrLDPC_initcallfunc_t)shlib_fdesc[2].fptr; - return 0; -} - -int load_nrLDPClib_offload(void) { - loader_shlibfunc_t shlib_decoffload_fdesc; - - shlib_decoffload_fdesc.fname = "nrLDPC_decod_offload"; - int ret=load_module_shlib("ldpc_t1",&shlib_decoffload_fdesc,1,NULL); - AssertFatal( (ret >= 0),"Error loading ldpc decoder offload"); - nrLDPC_decoder_offload = (nrLDPC_decoffloadfunc_t)shlib_decoffload_fdesc.fptr; - - t_nrLDPC_dec_params decParams; - t_nrLDPC_dec_params* p_decParams = &decParams; - int8_t l[68*384]; - int8_t llrProcBuf[22*384]; - - p_decParams->Z = 384; - p_decParams->BG = 1; - - AssertFatal(nrLDPC_decoder_offload(p_decParams,0, 0, - 1, - 0, - 0, - 25344, - 8, - l, - llrProcBuf, 0)>=0, - "error loading LDPC decoder offload library\n"); + itf->LDPCinit = (LDPC_initfunc_t *)shlib_fdesc[0].fptr; + itf->LDPCshutdown = (LDPC_shutdownfunc_t *)shlib_fdesc[1].fptr; + itf->LDPCdecoder = (LDPC_decoderfunc_t *)shlib_fdesc[2].fptr; + itf->LDPCencoder = (LDPC_encoderfunc_t *)shlib_fdesc[3].fptr; + AssertFatal(itf->LDPCinit() == 0, "error starting LDPC library %s %s\n", libname, version); return 0; } -int free_nrLDPClib_offload(void) { -t_nrLDPC_dec_params decParams; - t_nrLDPC_dec_params* p_decParams = &decParams; - int8_t l[68*384]; - int8_t llrProcBuf[22*384]; - - p_decParams->Z = 384; - p_decParams->BG = 1; - - nrLDPC_decoder_offload(p_decParams,0,0, - 1, - 0, - 0, - 25344, - 8, - l, - llrProcBuf, 2); -return 0; +int free_LDPClib(ldpc_interface_t *ldpc_interface) +{ + return ldpc_interface->LDPCshutdown(); } - -int load_nrLDPClib_ref(char *libversion, nrLDPC_encoderfunc_t * nrLDPC_encoder_ptr) { - loader_shlibfunc_t shlib_encoder_fdesc; - - shlib_encoder_fdesc.fname = "nrLDPC_encod"; - int ret=load_module_version_shlib("ldpc",libversion,&shlib_encoder_fdesc,1,NULL); - AssertFatal( (ret >= 0),"Error loading ldpc encoder %s\n",(libversion==NULL)?"":libversion); - *nrLDPC_encoder_ptr = (nrLDPC_encoderfunc_t)shlib_encoder_fdesc.fptr; -return 0; -} - - diff --git a/openair1/PHY/INIT/nr_init.c b/openair1/PHY/INIT/nr_init.c index bdec751f79..c10a0071a7 100644 --- a/openair1/PHY/INIT/nr_init.c +++ b/openair1/PHY/INIT/nr_init.c @@ -501,6 +501,9 @@ int init_codebook_gNB(PHY_VARS_gNB *gNB) { return 0; } +// A global var to reduce the changes size +ldpc_interface_t ldpc_interface = {0}, ldpc_interface_offload = {0}; + int phy_init_nr_gNB(PHY_VARS_gNB *gNB) { // shortcuts @@ -528,11 +531,10 @@ int phy_init_nr_gNB(PHY_VARS_gNB *gNB) nr_init_fde(); // Init array for frequency equalization of transform precoding of PUSCH - load_nrLDPClib(NULL); + load_LDPClib(NULL, &ldpc_interface); if (gNB->ldpc_offload_flag) - load_nrLDPClib_offload(); - + load_LDPClib("_t2", &ldpc_interface_offload); gNB->max_nb_pdsch = MAX_MOBILES_PER_GNB; init_codebook_gNB(gNB); diff --git a/openair1/PHY/INIT/nr_init_ue.c b/openair1/PHY/INIT/nr_init_ue.c index dafee33838..641c8a1f67 100644 --- a/openair1/PHY/INIT/nr_init_ue.c +++ b/openair1/PHY/INIT/nr_init_ue.c @@ -615,7 +615,6 @@ void nr_init_ul_harq_processes(NR_UL_UE_HARQ_t harq_list[NR_MAX_ULSCH_HARQ_PROCE DevAssert(harq_list[i].f); bzero(harq_list[i].f,14*num_rb*12*16); - harq_list[i].first_tx = 1; harq_list[i].round = 0; } } @@ -642,7 +641,6 @@ void clean_UE_harq(PHY_VARS_NR_UE *UE) ul_harq_process->tx_status = NEW_TRANSMISSION_HARQ; ul_harq_process->status = SCH_IDLE; ul_harq_process->round = 0; - ul_harq_process->first_tx = 1; } } diff --git a/openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c b/openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c index 4521c08673..0b240ac488 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c +++ b/openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c @@ -163,7 +163,6 @@ void ldpc8blocks(void *p) { encoder_implemparams_t *impp=(encoder_implemparams_t *) p; NR_DL_gNB_HARQ_t *harq = (NR_DL_gNB_HARQ_t *)impp->harq; - uint16_t Kr = impp->K; nfapi_nr_dl_tti_pdsch_pdu_rel15_t *rel15 = &harq->pdsch_pdu.pdsch_pdu_rel15; uint8_t mod_order = rel15->qamModOrder[0]; uint16_t nb_rb = rel15->rbSize; @@ -183,9 +182,10 @@ void ldpc8blocks(void *p) // 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++ ) - impp->d[rr]=tmp[i]; - nrLDPC_encoder(harq->c,impp->d,*impp->Zc, impp->Kb,Kr,impp->BG,impp); + d[rr] = tmp[i]; + ldpc_interface.LDPCencoder(harq->c, d, impp); // 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++ ) @@ -193,7 +193,7 @@ void ldpc8blocks(void *p) 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(&impp->d[rr][Kr-impp->F-2*(*impp->Zc)], NR_NULL, impp->F); + memset(&d[rr][impp->K - impp->F - 2 * impp->Zc], NR_NULL, impp->F); } #ifdef DEBUG_DLSCH_CODING @@ -201,14 +201,18 @@ void ldpc8blocks(void *p) #endif uint32_t E = nr_get_E(G, impp->n_segments, mod_order, rel15->nrOfLayers, rr); //#ifdef DEBUG_DLSCH_CODING - 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", + 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, - Kr-impp->F-2*(*impp->Zc), - mod_order,nb_rb,rel15->nrOfLayers); + impp->K - impp->F - 2 * impp->Zc, + mod_order, + nb_rb, + rel15->nrOfLayers); uint32_t Tbslbrm = rel15->maintenance_parms_v3.tbSizeLbrmBytes; @@ -216,27 +220,38 @@ void ldpc8blocks(void *p) bzero (e, E); nr_rate_matching_ldpc(Tbslbrm, impp->BG, - *impp->Zc, - impp->d[rr], + impp->Zc, + d[rr], e, impp->n_segments, impp->F, - Kr-impp->F-2*(*impp->Zc), + impp->K - impp->F - 2 * impp->Zc, rel15->rvIndex[0], E); - if (Kr-impp->F-2*(*impp->Zc)> E) { - LOG_E(PHY,"dlsch coding A %d Kr %d G %d (nb_rb %d, nb_symb_sch %d, nb_re_dmrs %d, length_dmrs %d, mod_order %d)\n", - A,impp->K,G, nb_rb,nb_symb_sch,nb_re_dmrs,length_dmrs,(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, - Kr, - impp->F, - Kr-impp->F-2*(*impp->Zc), - mod_order,nb_rb); + if (impp->K - impp->F - 2 * impp->Zc > E) { + LOG_E(PHY, + "dlsch coding A %d Kr %d G %d (nb_rb %d, nb_symb_sch %d, nb_re_dmrs %d, length_dmrs %d, mod_order %d)\n", + A, + impp->K, + G, + nb_rb, + nb_symb_sch, + nb_re_dmrs, + length_dmrs, + (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_DLSCH_CODING @@ -279,7 +294,7 @@ int nr_dlsch_encoding(PHY_VARS_gNB *gNB, impp.output=output; unsigned int crc=1; nfapi_nr_dl_tti_pdsch_pdu_rel15_t *rel15 = &harq->pdsch_pdu.pdsch_pdu_rel15; - impp.Zc = &harq->Z; + impp.Zc = harq->Z; VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_gNB_DLSCH_ENCODING, VCD_FUNCTION_IN); uint32_t A = rel15->TBSize[0]<<3; unsigned char *a=harq->pdu; @@ -335,14 +350,13 @@ int nr_dlsch_encoding(PHY_VARS_gNB *gNB, impp.BG = rel15->maintenance_parms_v3.ldpcBaseGraph; start_meas(dlsch_segmentation_stats); - impp.Kb = nr_segmentation(harq->b, harq->c, B, &impp.n_segments, &impp.K, impp.Zc, &impp.F, impp.BG); + impp.Kb = nr_segmentation(harq->b, harq->c, B, &impp.n_segments, &impp.K, &impp.Zc, &impp.F, impp.BG); stop_meas(dlsch_segmentation_stats); if (impp.n_segments>MAX_NUM_NR_DLSCH_SEGMENTS_PER_LAYER*rel15->nrOfLayers) { LOG_E(PHY, "nr_segmentation.c: too many segments %d, B %d\n", impp.n_segments, B); return(-1); } - for (int r=0; rd[r][0]; //channel_input[r] = &harq->d[r][0]; @@ -365,26 +379,60 @@ int nr_dlsch_encoding(PHY_VARS_gNB *gNB, impp.tinput = tinput; impp.tparity = tparity; impp.toutput = toutput; - - impp.harq=harq; - notifiedFIFO_t nf; - initNotifiedFIFO(&nf); - int nbJobs=0; - for(int j=0; j<(impp.n_segments/8+((impp.n_segments&7)==0 ? 0 : 1)); j++) { - notifiedFIFO_elt_t *req=newNotifiedFIFO_elt(sizeof(impp), j, &nf, ldpc8blocks); - encoder_implemparams_t* perJobImpp=(encoder_implemparams_t*)NotifiedFifoData(req); - *perJobImpp=impp; - perJobImpp->macro_num=j; - pushTpool(&gNB->threadPool, req); - nbJobs++; - } - while(nbJobs) { - notifiedFIFO_elt_t *req=pullTpool(&nf, &gNB->threadPool); - if (req == NULL) - break; // Tpool has been stopped - delNotifiedFIFO_elt(req); - nbJobs--; - + impp.harq = harq; + if (gNB->ldpc_offload_flag && *rel15->mcsIndex > 2) { + impp.Qm = rel15->qamModOrder[0]; + impp.rv = rel15->rvIndex[0]; + int nb_re_dmrs = + (rel15->dmrsConfigType == NFAPI_NR_DMRS_TYPE1) ? (6 * rel15->numDmrsCdmGrpsNoData) : (4 * rel15->numDmrsCdmGrpsNoData); + impp.G = nr_get_G(rel15->rbSize, + rel15->NrOfSymbols, + nb_re_dmrs, + get_num_dmrs(rel15->dlDmrsSymbPos), + harq->unav_res, + rel15->qamModOrder[0], + rel15->nrOfLayers); + uint8_t tmp[68 * 384] __attribute__((aligned(32))); + uint8_t *d = tmp; + int r_offset = 0; + for (int r = 0; r < impp.n_segments; r++) { + impp.E = nr_get_E(impp.G, impp.n_segments, impp.Qm, rel15->nrOfLayers, r); + impp.Kr = impp.K; + ldpc_interface_offload.LDPCencoder(&harq->c[r], &d, &impp); + uint8_t e[impp.E]; + bzero(e, impp.E); + nr_rate_matching_ldpc(rel15->maintenance_parms_v3.tbSizeLbrmBytes, + impp.BG, + impp.Zc, + tmp, + e, + impp.n_segments, + impp.F, + impp.K - impp.F - 2 * impp.Zc, + impp.rv, + impp.E); + nr_interleaving_ldpc(impp.E, impp.Qm, e, impp.output + r_offset); + r_offset += impp.E; + } + } else { + notifiedFIFO_t nf; + initNotifiedFIFO(&nf); + int nbJobs = 0; + for (int j = 0; j < (impp.n_segments / 8 + ((impp.n_segments & 7) == 0 ? 0 : 1)); j++) { + notifiedFIFO_elt_t *req = newNotifiedFIFO_elt(sizeof(impp), j, &nf, ldpc8blocks); + encoder_implemparams_t *perJobImpp = (encoder_implemparams_t *)NotifiedFifoData(req); + *perJobImpp = impp; + perJobImpp->macro_num = j; + pushTpool(&gNB->threadPool, req); + nbJobs++; + } + while (nbJobs) { + notifiedFIFO_elt_t *req = pullTpool(&nf, &gNB->threadPool); + if (req == NULL) + break; // Tpool has been stopped + delNotifiedFIFO_elt(req); + nbJobs--; + } } VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_gNB_DLSCH_ENCODING, VCD_FUNCTION_OUT); return 0; diff --git a/openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c b/openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c index 1d4e5bf71c..a3041838b9 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c +++ b/openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c @@ -187,7 +187,7 @@ static void nr_processULSegment(void *arg) memset(ulsch_harq->c[r], 0, Kr_bytes); p_decoderParms->crc_type = crcType(ulsch_harq->C, A); - p_decoderParms->block_length = lenWithCrc(ulsch_harq->C, A); + p_decoderParms->E = lenWithCrc(ulsch_harq->C, A); // start_meas(&phy_vars_gNB->ulsch_ldpc_decoding_stats); // set first 2*Z_c bits to zeros @@ -215,7 +215,8 @@ static void nr_processULSegment(void *arg) ////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////// pl =====> llrProcBuf ////////////////////////////////// - rdata->decodeIterations = nrLDPC_decoder(p_decoderParms, l, llrProcBuf, p_procTime, &ulsch_harq->abort_decode); + rdata->decodeIterations = + ldpc_interface.LDPCdecoder(p_decoderParms, 0, 0, 0, l, llrProcBuf, p_procTime, &ulsch_harq->abort_decode); if (rdata->decodeIterations <= p_decoderParms->numMaxIter) memcpy(ulsch_harq->c[r],llrProcBuf, Kr>>3); @@ -231,22 +232,20 @@ int decode_offload(PHY_VARS_gNB *phy_vars_gNB, { NR_gNB_ULSCH_t *ulsch = &phy_vars_gNB->ulsch[ULSCH_id]; NR_UL_gNB_HARQ_t *harq_process = ulsch->harq_process; - int8_t llrProcBuf[22 * 384] __attribute__((aligned(32))); - int16_t z_ol[68 * 384] __attribute__((aligned(32))); - int8_t l_ol[68 * 384] __attribute__((aligned(32))); + int16_t z_ol[68 * 384 + 16] __attribute__((aligned(16))); + int8_t l_ol[68 * 384 + 16] __attribute__((aligned(16))); uint8_t Qm = pusch_pdu->qam_mod_order; uint8_t n_layers = pusch_pdu->nrOfLayers; const int Kr = harq_process->K; const int Kr_bytes = Kr >> 3; + uint32_t A = (harq_process->TBS) << 3; const int kc = decParams->BG == 2 ? 52 : 68; - const uint32_t A = (harq_process->TBS) << 3; + ulsch->max_ldpc_iterations = 20; int decodeIterations = 2; - int dtx_det = 0; int r_offset = 0, offset = 0; for (int r = 0; r < harq_process->C; r++) { int E = nr_get_E(G, harq_process->C, Qm, n_layers, r); memset(harq_process->c[r], 0, Kr_bytes); - decParams->R = nr_get_R_ldpc_decoder(pusch_pdu->pusch_data.rv_index, E, decParams->BG, @@ -254,49 +253,24 @@ int decode_offload(PHY_VARS_gNB *phy_vars_gNB, &harq_process->llrLen, harq_process->round); - if ((dtx_det == 0) && (pusch_pdu->pusch_data.rv_index == 0)) { - memcpy(z_ol, ulsch_llr + r_offset, E * sizeof(short)); - simde__m128i *pv_ol128 = (simde__m128i *)&z_ol; - simde__m128i *pl_ol128 = (simde__m128i *)&l_ol; - for (int i = 0, j = 0; j < ((kc * harq_process->Z) >> 4) + 1; i += 2, j++) { - pl_ol128[j] = simde_mm_packs_epi16(pv_ol128[i], pv_ol128[i + 1]); - } - - int ret = nrLDPC_decoder_offload(decParams, - harq_pid, - ULSCH_id, - r, - pusch_pdu->pusch_data.rv_index, - harq_process->F, - E, - Qm, - (int8_t *)&pl_ol128[0], - llrProcBuf, - 1); - if (ret < 0) { - LOG_E(PHY, "ulsch_decoding.c: Problem in LDPC decoder offload\n"); - - decodeIterations = ulsch->max_ldpc_iterations + 1; - return -1; - } - for (int m = 0; m < Kr >> 3; m++) { - harq_process->c[r][m] = (uint8_t)llrProcBuf[m]; - } - - if (check_crc((uint8_t *)llrProcBuf, lenWithCrc(harq_process->C, A), crcType(harq_process->C, A))) { - PRINT_CRC_CHECK(LOG_I(PHY, "Segment %d CRC OK\n", r)); - decodeIterations = 2; - } else { - PRINT_CRC_CHECK(LOG_I(PHY, "segment %d CRC NOK\n", r)); - decodeIterations = ulsch->max_ldpc_iterations + 1; - } - - r_offset += E; - } else { - dtx_det = 0; - decodeIterations = ulsch->max_ldpc_iterations + 1; + memcpy(z_ol, ulsch_llr + r_offset, E * sizeof(short)); + simde__m128i *pv_ol128 = (simde__m128i *)&z_ol; + simde__m128i *pl_ol128 = (simde__m128i *)&l_ol; + for (int i = 0, j = 0; j < ((kc * harq_process->Z) >> 4) + 1; i += 2, j++) { + pl_ol128[j] = simde_mm_packs_epi16(pv_ol128[i], pv_ol128[i + 1]); } - bool decodeSuccess = (decodeIterations <= ulsch->max_ldpc_iterations); + decParams->E = E; + decParams->rv = pusch_pdu->pusch_data.rv_index; + decParams->F = harq_process->F; + decParams->Qm = Qm; + decodeIterations = + ldpc_interface_offload + .LDPCdecoder(decParams, harq_pid, ULSCH_id, r, (int8_t *)&pl_ol128[0], (int8_t *)harq_process->c[r], NULL, NULL); + if (decodeIterations < 0) { + LOG_E(PHY, "ulsch_decoding.c: Problem in LDPC decoder offload\n"); + return -1; + } + bool decodeSuccess = check_crc((uint8_t *)harq_process->c[r], lenWithCrc(harq_process->C, A), crcType(harq_process->C, A)); if (decodeSuccess) { memcpy(harq_process->b + offset, harq_process->c[r], Kr_bytes - (harq_process->F >> 3) - ((harq_process->C > 1) ? 3 : 0)); offset += (Kr_bytes - (harq_process->F >> 3) - ((harq_process->C > 1) ? 3 : 0)); @@ -304,36 +278,42 @@ int decode_offload(PHY_VARS_gNB *phy_vars_gNB, } else { LOG_D(PHY, "uplink segment error %d/%d\n", r, harq_process->C); LOG_D(PHY, "ULSCH %d in error\n", ULSCH_id); - break; // don't even attempt to decode other segments + } + r_offset += E; + } + bool crc_valid = false; + if (harq_process->processedSegments == harq_process->C) { + // When the number of code blocks is 1 (C = 1) and ulsch_harq->processedSegments = 1, we can assume a good TB because of the + // CRC check made by the LDPC for early termination, so, no need to perform CRC check twice for a single code block + crc_valid = true; + if (harq_process->C > 1) { + crc_valid = check_crc(harq_process->b, lenWithCrc(1, A), crcType(1, A)); } } - - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_gNB_ULSCH_DECODING, 0); - - if (harq_process->processedSegments == harq_process->C) { + if (crc_valid) { LOG_D(PHY, "ULSCH: Setting ACK for slot %d TBS %d\n", ulsch->slot, harq_process->TBS); ulsch->active = false; harq_process->round = 0; - LOG_D(PHY, "ULSCH received ok \n"); nr_fill_indication(phy_vars_gNB, ulsch->frame, ulsch->slot, ULSCH_id, harq_pid, 0, 0); - } else { LOG_D(PHY, - "[gNB %d] ULSCH: Setting NAK for SFN/SF %d/%d (pid %d, status %d, round %d, TBS %d)\n", - phy_vars_gNB->Mod_id, - ulsch->frame, - ulsch->slot, - harq_pid, - ulsch->active, - harq_process->round, - harq_process->TBS); + "[gNB %d] ULSCH: Setting NAK for SFN/SF %d/%d (pid %d, status %d, round %d, TBS %d)\n", + phy_vars_gNB->Mod_id, + ulsch->frame, + ulsch->slot, + harq_pid, + ulsch->active, + harq_process->round, + harq_process->TBS); ulsch->handled = 1; decodeIterations = ulsch->max_ldpc_iterations + 1; LOG_D(PHY, "ULSCH %d in error\n", ULSCH_id); nr_fill_indication(phy_vars_gNB, ulsch->frame, ulsch->slot, ULSCH_id, harq_pid, 1, 0); } + ulsch->last_iteration_cnt = decodeIterations; + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_gNB_ULSCH_DECODING,0); return 0; } @@ -373,7 +353,7 @@ int nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB, harq_process->processedSegments = 0; harq_process->TBS = pusch_pdu->pusch_data.tb_size; - t_nrLDPC_dec_params decParams = {0}; + t_nrLDPC_dec_params decParams = {.check_crc = check_crc}; decParams.BG = pusch_pdu->maintenance_parms_v3.ldpcBaseGraph; const uint32_t A = (harq_process->TBS) << 3; NR_gNB_PHY_STATS_t *stats = get_phy_stats(phy_vars_gNB, ulsch->rnti); @@ -440,14 +420,14 @@ int nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB, decParams.Z = harq_process->Z; decParams.numMaxIter = ulsch->max_ldpc_iterations; decParams.outMode = 0; - + decParams.setCombIn = !harq_process->harq_to_be_cleared; if (harq_process->harq_to_be_cleared) { for (int r = 0; r < harq_process->C; r++) harq_process->d_to_be_cleared[r] = true; harq_process->harq_to_be_cleared = false; } - if (phy_vars_gNB->ldpc_offload_flag && mcs > 9) + if (phy_vars_gNB->ldpc_offload_flag) return decode_offload(phy_vars_gNB, ULSCH_id, ulsch_llr, pusch_pdu, &decParams, harq_pid, G); uint32_t offset = 0, r_offset = 0; diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c index 19f133ff9a..a0a90e8d42 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c @@ -252,10 +252,10 @@ static void nr_processDLSegment(void *arg) } //VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_DLSCH_LDPC, VCD_FUNCTION_IN); - p_decoderParms->block_length = lenWithCrc(harq_process->C, A); + p_decoderParms->E = lenWithCrc(harq_process->C, A); p_decoderParms->crc_type = crcType(harq_process->C, A); - nrLDPC_initcall(p_decoderParms, (int8_t *)&pl[0], LDPCoutput); - rdata->decodeIterations = nrLDPC_decoder(p_decoderParms, (int8_t *)&pl[0], LDPCoutput, &procTime, &harq_process->abort_decode); + rdata->decodeIterations = + ldpc_interface.LDPCdecoder(p_decoderParms, 0, 0, 0, l, LDPCoutput, &procTime, &harq_process->abort_decode); //VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_DLSCH_LDPC, VCD_FUNCTION_OUT); if (rdata->decodeIterations <= dlsch->max_ldpc_iterations) @@ -281,7 +281,7 @@ uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue, uint32_t ret,offset; uint32_t r,r_offset=0,Kr=8424,Kr_bytes; t_nrLDPC_dec_params decParams; - t_nrLDPC_dec_params *p_decParams = &decParams; + decParams.check_crc = check_crc; if (!harq_process) { LOG_E(PHY,"dlsch_decoding.c: NULL harq_process pointer\n"); @@ -348,8 +348,8 @@ uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue, LOG_D(PHY,"%d.%d DLSCH Decoding, harq_pid %d TBS %d (%d) G %d nb_re_dmrs %d length dmrs %d mcs %d Nl %d nb_symb_sch %d nb_rb %d Qm %d Coderate %f\n", frame,nr_slot_rx,harq_pid,A,A/8,G, nb_re_dmrs, dmrs_length, dlsch->dlsch_config.mcs, dlsch->Nl, nb_symb_sch, nb_rb, dlsch->dlsch_config.qamModOrder, Coderate); - p_decParams->BG = get_BG(A, dlsch->dlsch_config.targetCodeRate); - unsigned int kc = p_decParams->BG == 2 ? 52 : 68; + decParams.BG = get_BG(A, dlsch->dlsch_config.targetCodeRate); + unsigned int kc = decParams.BG == 2 ? 52 : 68; if (harq_process->first_rx == 1) { // This is a new packet, so compute quantities regarding segmentation @@ -360,7 +360,7 @@ uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue, &harq_process->K, &harq_process->Z, // [hna] Z is Zc &harq_process->F, - p_decParams->BG); + decParams.BG); if (harq_process->C>MAX_NUM_NR_DLSCH_SEGMENTS_PER_LAYER*dlsch->Nl) { LOG_E(PHY, "nr_segmentation.c: too many segments %d, A %d\n", harq_process->C, A); @@ -375,11 +375,9 @@ uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue, } VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_DLSCH_SEGMENTATION, VCD_FUNCTION_OUT); - p_decParams->Z = harq_process->Z; - //printf("dlsch decoding nr segmentation Z %d\n", p_decParams->Z); - //printf("coderate %f kc %d \n", Coderate, kc); - p_decParams->numMaxIter = dlsch->max_ldpc_iterations; - p_decParams->outMode= 0; + decParams.Z = harq_process->Z; + decParams.numMaxIter = dlsch->max_ldpc_iterations; + decParams.outMode = 0; r_offset = 0; uint16_t a_segments = MAX_NUM_NR_DLSCH_SEGMENTS_PER_LAYER*dlsch->Nl; //number of segments to be allocated @@ -396,7 +394,7 @@ uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue, if (LOG_DEBUGFLAG(DEBUG_DLSCH_DECOD)) LOG_I(PHY,"Segmentation: C %d, K %d\n",harq_process->C,harq_process->K); - Kr = harq_process->K; // [hna] overwrites this line "Kr = p_decParams->Z*kb" + Kr = harq_process->K; Kr_bytes = Kr>>3; offset = 0; notifiedFIFO_t nf; diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_transport_ue.h b/openair1/PHY/NR_UE_TRANSPORT/nr_transport_ue.h index c60fdb6a6d..b03764696f 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_transport_ue.h +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_transport_ue.h @@ -45,8 +45,6 @@ typedef enum { } harq_result_t; typedef struct { - /// Indicator of first transmission - uint8_t first_tx; /// HARQ tx status harq_result_t tx_status; /// Status Flag indicating for this ULSCH (idle,active,disabled) @@ -57,8 +55,6 @@ typedef struct { uint8_t O_ACK; /// Index of current HARQ round for this ULSCH uint8_t round; - /// Last Ndi for this harq process - uint8_t ndi; /// pointer to pdu from MAC interface (TS 36.212 V15.4.0, Sec 5.1 p. 8) unsigned char *a; /// Pointer to the payload + CRC diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_coding.c b/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_coding.c index 1c4d7c0fec..95aa63d3bd 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_coding.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_coding.c @@ -57,11 +57,10 @@ int nr_ulsch_encoding(PHY_VARS_NR_UE *ue, NR_UL_UE_HARQ_t *harq_process = &ue->ul_harq_processes[harq_pid]; uint16_t nb_rb = ulsch->pusch_pdu.rb_size; uint32_t A = tb_size << 3; - uint32_t *pz = &harq_process->Z; uint8_t mod_order = ulsch->pusch_pdu.qam_mod_order; - uint16_t Kr=0; - uint32_t r_offset=0; - uint32_t F=0; + uint16_t Kr = 0; + uint32_t r_offset = 0; + uint32_t F = 0; // target_code_rate is in 0.1 units float Coderate = (float) ulsch->pusch_pdu.target_code_rate / 10240.0f; @@ -72,15 +71,11 @@ int nr_ulsch_encoding(PHY_VARS_NR_UE *ue, LOG_D(NR_PHY, "ulsch coding nb_rb %d, Nl = %d\n", nb_rb, ulsch->pusch_pdu.nrOfLayers); LOG_D(NR_PHY, "ulsch coding A %d G %d mod_order %d Coderate %f\n", A, G, mod_order, Coderate); - LOG_D(NR_PHY, "harq_pid %d harq_process->ndi %d, pusch_data.new_data_indicator %d\n", - harq_pid,harq_process->ndi,ulsch->pusch_pdu.pusch_data.new_data_indicator); - - if (harq_process->first_tx == 1 || - harq_process->ndi != ulsch->pusch_pdu.pusch_data.new_data_indicator) { // this is a new packet + LOG_D(NR_PHY, "harq_pid %d, pusch_data.new_data_indicator %d\n", harq_pid, ulsch->pusch_pdu.pusch_data.new_data_indicator); + if (ulsch->pusch_pdu.pusch_data.new_data_indicator) { // this is a new packet #ifdef DEBUG_ULSCH_CODING printf("encoding thinks this is a new packet \n"); #endif - harq_process->first_tx = 0; ///////////////////////// a---->| add CRC |---->b ///////////////////////// /////////// /* @@ -140,7 +135,7 @@ int nr_ulsch_encoding(PHY_VARS_NR_UE *ue, B, &harq_process->C, &harq_process->K, - pz, + &harq_process->Z, &harq_process->F, harq_process->BG); @@ -161,7 +156,7 @@ int nr_ulsch_encoding(PHY_VARS_NR_UE *ue, ///////////////////////// c---->| LDCP coding |---->d ///////////////////////// /////////// - //printf("segment Z %d k %d Kr %d BG %d\n", *pz,harq_process->K,Kr,BG); + // printf("segment Z %d k %d Kr %d BG %d\n", harq_process->Z,harq_process->K,Kr,BG); //start_meas(te_stats); for (int r=0; rC; r++) { @@ -170,7 +165,7 @@ int nr_ulsch_encoding(PHY_VARS_NR_UE *ue, printf("Encoder: B %d F %d \n", B, harq_process->F); printf("start ldpc encoder segment %d/%d\n",r,harq_process->C); printf("input %d %d %d %d %d \n", harq_process->c[r][0], harq_process->c[r][1], harq_process->c[r][2],harq_process->c[r][3], harq_process->c[r][4]); - for (int cnt =0 ; cnt < 22*(*pz)/8; cnt ++){ + for (int cnt = 0; cnt < 22 * harq_process->Z / 8; cnt++) { printf("%d ", harq_process->c[r][cnt]); } printf("\n"); @@ -183,28 +178,38 @@ int nr_ulsch_encoding(PHY_VARS_NR_UE *ue, //for (int i=0;i<68*384;i++) // printf("channel_input[%d]=%d\n",i,channel_input[i]); - /*printf("output %d %d %d %d %d \n", harq_process->d[0][0], harq_process->d[0][1], harq_process->d[r][2],harq_process->d[0][3], harq_process->d[0][4]); - for (int cnt =0 ; cnt < 66*(*pz); cnt ++){ - printf("%d \n", harq_process->d[0][cnt]); + /*printf("output %d %d %d %d %d \n", harq_process->d[0][0], harq_process->d[0][1], harq_process->d[r][2],harq_process->d[0][3], + harq_process->d[0][4]); for (int cnt =0 ; cnt < 66*harq_process->Z; cnt ++){ printf("%d \n", harq_process->d[0][cnt]); } printf("\n");*/ - encoder_implemparams_t impp = { - .n_segments=harq_process->C, - .macro_num=0, - .tinput = NULL, - .tprep = NULL, - .tparity = NULL, - .toutput = NULL}; + encoder_implemparams_t impp = {.n_segments = harq_process->C, + .macro_num = 0, + .K = harq_process->K, + .Kb = Kb, + .Zc = harq_process->Z, + .BG = harq_process->BG, + .tinput = NULL, + .tprep = NULL, + .tparity = NULL, + .toutput = NULL}; VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_LDPC_ENCODER_OPTIM, VCD_FUNCTION_IN); start_meas(&ue->ulsch_ldpc_encoding_stats); - for(int j = 0; j < (harq_process->C/8 + 1); j++) { - impp.macro_num = j; - nrLDPC_encoder(harq_process->c,harq_process->d,*pz,Kb,Kr,harq_process->BG,&impp); - } - stop_meas(&ue->ulsch_ldpc_encoding_stats); - + if (ldpc_interface_offload.LDPCencoder) + for (int j = 0; j < harq_process->C; j++) { + impp.macro_num = j; + impp.E = nr_get_E(G, harq_process->C, mod_order, ulsch->pusch_pdu.nrOfLayers, j); + impp.Kr = Kr; + ldpc_interface_offload.LDPCencoder(&harq_process->c[j], &harq_process->d[j], &impp); + } + else + for (int j = 0; j < (harq_process->C / 8 + 1); j++) { + impp.macro_num = j; + impp.E = nr_get_E(G, harq_process->C, mod_order, ulsch->pusch_pdu.nrOfLayers, j); + impp.Kr = Kr; + ldpc_interface.LDPCencoder(harq_process->c, harq_process->d, &impp); + } VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_LDPC_ENCODER_OPTIM, VCD_FUNCTION_OUT); //stop_meas(te_stats); @@ -216,15 +221,13 @@ int nr_ulsch_encoding(PHY_VARS_NR_UE *ue, /////////// /////////////////////////////////////////////////////////////////////////////// - LOG_D(PHY,"setting ndi to %d from pusch_data\n", ulsch->pusch_pdu.pusch_data.new_data_indicator); - harq_process->ndi = ulsch->pusch_pdu.pusch_data.new_data_indicator; } F = harq_process->F; Kr = harq_process->K; for (int r=0; rC; r++) { // looping over C segments if (harq_process->F>0) { - for (int k=(Kr-F-2*(*pz)); kZ; k < Kr - 2 * harq_process->Z; k++) { harq_process->d[r][k] = NR_NULL; //if (k<(Kr-F+8)) //printf("r %d filler bits [%d] = %d \n", r,k, harq_process->d[r][k]); @@ -249,14 +252,15 @@ int nr_ulsch_encoding(PHY_VARS_NR_UE *ue, start_meas(&ue->ulsch_rate_matching_stats); if (nr_rate_matching_ldpc(ulsch->pusch_pdu.tbslbrm, harq_process->BG, - *pz, + harq_process->Z, harq_process->d[r], - harq_process->e+r_offset, + harq_process->e + r_offset, harq_process->C, F, - Kr-F-2*(*pz), + Kr - F - 2 * harq_process->Z, ulsch->pusch_pdu.pusch_data.rv_index, - E) == -1) + E) + == -1) return -1; stop_meas(&ue->ulsch_rate_matching_stats); diff --git a/openair1/PHY/defs_gNB.h b/openair1/PHY/defs_gNB.h index 5c3a5490af..1e62e51c2a 100644 --- a/openair1/PHY/defs_gNB.h +++ b/openair1/PHY/defs_gNB.h @@ -538,7 +538,10 @@ typedef struct { #define MAX_NUM_NR_RX_PRACH_PREAMBLES 4 #define MAX_UL_PDUS_PER_SLOT 8 #define MAX_NUM_NR_SRS_PDUS 8 -#define MAX_NUM_NR_UCI_PDUS 8 +// the current RRC resource allocation is that each UE gets its +// "own" PUCCH resource (for F0) in a dedicated PRB in each slot +// therefore, we can have up to "number of UE" UCI PDUs +#define MAX_NUM_NR_UCI_PDUS MAX_MOBILES_PER_GNB /// Top-level PHY Data Structure for gNB typedef struct PHY_VARS_gNB_s { diff --git a/openair1/SCHED_NR_UE/harq_nr.c b/openair1/SCHED_NR_UE/harq_nr.c index 2cffd3f484..caf6898f88 100644 --- a/openair1/SCHED_NR_UE/harq_nr.c +++ b/openair1/SCHED_NR_UE/harq_nr.c @@ -98,75 +98,6 @@ #define DL_DCI (1) #define UL_DCI (0) -/******************************************************************* -* -* NAME : uplink_harq_process -* -* PARAMETERS : ue context -* slot_tx slot for transmission -* gNB_id identifier -* ndi from DCI -* rnti_type from DCI -* -* RETURN : true it a new transmission -* false it is a retransmission -* -* DESCRIPTION : manage uplink grant information for transmissions/retransmissions -* TS 38.321 5.4.1 UL Grant reception -* TS 38.321 5.4.2.1 HARQ Entity -* -*********************************************************************/ - -harq_result_t uplink_harq_process(NR_UE_ULSCH_t *ulsch, int harq_pid, NR_UL_UE_HARQ_t harq_processes[NR_MAX_ULSCH_HARQ_PROCESSES], int ndi, uint8_t rnti_type) -{ - harq_result_t result_harq = RETRANSMISSION_HARQ; - - if (rnti_type == _CS_RNTI_) { - LOG_E(PHY, "Fatal error in HARQ entity due to not supported CS_RNTI at line %d in function %s of file %s \n", __LINE__ , __func__, __FILE__); - return(NEW_TRANSMISSION_HARQ); - } - else if ((rnti_type != _C_RNTI_) && (rnti_type != _TC_RNTI_)) { - /* harq mechanism is not relevant for other rnti */ - return(NEW_TRANSMISSION_HARQ); - } - else if (harq_pid > ulsch->number_harq_processes_for_pusch) { - LOG_E(PHY, "Fatal error in HARQ entity due to unknown process identity %d at line %d in function %s of file %s \n", harq_pid, __LINE__ , __func__, __FILE__); - assert(0); - } - - /* 38.321 5.4.2.1 2> if the uplink grant was received on PDCCH for the C-RNTI and the HARQ buffer of the identified process is empty */ - if ((harq_processes[harq_pid].first_tx == 1) && (rnti_type == _C_RNTI_)) { /* no transmission yet on this process so consider its harq buffer as empty */ - harq_processes[harq_pid].first_tx = 0; - harq_processes[harq_pid].ndi = ndi; /* store first value of ndi */ - harq_processes[harq_pid].round = 0; - - result_harq = NEW_TRANSMISSION_HARQ; - - LOG_D(PHY, "[HARQ-UL-PUSCH harqId : %d] first new transmission \n", harq_pid); - } - /* 38.321 5.4.2.1 2> if the received grant was not addressed to a Temporary C-RNTI on PDCCH, and the NDI provided in the associated HARQ */ - /* information has been toggled compared to the value in the previous transmission of this TB of this HARQ process */ - else if ((harq_processes[harq_pid].ndi != ndi) && (rnti_type != _TC_RNTI_)) { /* is ndi toogled so this is a new grant ? */ - harq_processes[harq_pid].ndi = ndi; /* store first value of ndi */ - harq_processes[harq_pid].round = 0; - - result_harq = NEW_TRANSMISSION_HARQ; - - LOG_D(PHY, "[HARQ-UL-PUSCH harqId : %d] new transmission due to toogle of ndi \n", harq_pid); - } - /* 38.321 5.4.2.1 2> else (i.e. retransmission): */ - else { - harq_processes[harq_pid].ndi = ndi; /* ndi has not toggled si this is a retransmission */ - harq_processes[harq_pid].round++; /* increment number of retransmission */ - - result_harq = RETRANSMISSION_HARQ; - - LOG_D(PHY, "[HARQ-UL-PUSCH harqId : %d] retransmission \n", harq_pid); - } - - return (result_harq); -} - /******************************************************************* * * NAME : init_downlink_harq_status diff --git a/openair1/SCHED_NR_UE/harq_nr.h b/openair1/SCHED_NR_UE/harq_nr.h index 1e7faf23e0..4c39772948 100644 --- a/openair1/SCHED_NR_UE/harq_nr.h +++ b/openair1/SCHED_NR_UE/harq_nr.h @@ -55,13 +55,6 @@ /*************** FUNCTIONS ****************************************/ -/** \brief This function update uplink harq context and return transmission type (new transmission or retransmission) - @param ulsch uplink harq context - @param harq process identifier harq_pid - @returns retransmission or new transmission */ - -harq_result_t uplink_harq_process(NR_UE_ULSCH_t *ulsch, int harq_pid, NR_UL_UE_HARQ_t harq_processes[NR_MAX_ULSCH_HARQ_PROCESSES], int ndi, uint8_t rnti_type); - /** \brief This function initialises downlink HARQ status @param pointer to downlink harq status @returns none */ diff --git a/openair1/SIMULATION/NR_PHY/dlsim.c b/openair1/SIMULATION/NR_PHY/dlsim.c index 540fef1b38..20aabed512 100644 --- a/openair1/SIMULATION/NR_PHY/dlsim.c +++ b/openair1/SIMULATION/NR_PHY/dlsim.c @@ -291,6 +291,7 @@ 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; @@ -353,7 +354,7 @@ int main(int argc, char **argv) FILE *scg_fd=NULL; - while ((c = getopt(argc, argv, "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) { + while ((c = getopt(argc, argv, "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) { switch (c) { case 'f': scg_fd = fopen(optarg,"r"); @@ -398,6 +399,10 @@ 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); @@ -542,7 +547,31 @@ int main(int argc, char **argv) default: case 'h': - printf("%s -h(elp)\n", argv[0]); + printf("%s -h(elp) -p(extended_prefix) -N cell_id -f output_filename -F input_filename -g channel_model -n n_frames -s snr0 -S snr1 -x transmission_mode -y TXant -z RXant -i Intefrence0 -j Interference1 -A interpolation_file -C(alibration offset dB) -N CellId\n", + argv[0]); + printf("-h This message\n"); + printf("-L \n"); + //printf("-p Use extended prefix mode\n"); + //printf("-d Use TDD\n"); + printf("-n Number of frames to simulate\n"); + printf("-s Starting SNR, runs from SNR0 to SNR0 + 5 dB. If n_frames is 1 then just SNR is simulated\n"); + printf("-S Ending SNR, runs from SNR0 to SNR1\n"); + //printf("-t Delay spread for multipath channel\n"); + printf("-g Channel model: [A] TDLA30, [B] TDLB100, [C] TDLC300, e.g. -g A\n"); + printf("-o Introduce delay in terms of number of samples\n"); + printf("-y Number of TX antennas used in gNB\n"); + printf("-z Number of RX antennas used in UE\n"); + printf("-x Num of layer for PDSCH\n"); + printf("-p Precoding matrix index\n"); + printf("-i Change channel estimation technique. Arguments list: Frequency domain {0:Linear interpolation, 1:PRB based averaging}, Time domain {0:Estimates of last DMRS symbol, 1:Average of DMRS symbols}\n"); + //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"); + printf("-F Input filename (.txt format) for RX conformance testing\n"); printf("-a Start PRB for PDSCH\n"); printf("-b Number of PRB for PDSCH\n"); printf("-d number of dlsch threads, 0: no dlsch parallelization\n"); @@ -597,6 +626,7 @@ int main(int argc, char **argv) gNB = RC.gNB[0]; gNB->ofdm_offset_divisor = UINT_MAX; + gNB->ldpc_offload_flag = ldpc_offload_flag; frame_parms = &gNB->frame_parms; //to be initialized I suppose (maybe not necessary for PBCH) frame_parms->nb_antennas_tx = n_tx; frame_parms->nb_antennas_rx = n_rx; @@ -1301,7 +1331,10 @@ int main(int argc, char **argv) free(UE->phy_sim_pdsch_dl_ch_estimates); 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); + if (output_fd) fclose(output_fd); diff --git a/openair1/SIMULATION/NR_PHY/ulsim.c b/openair1/SIMULATION/NR_PHY/ulsim.c index 25e6d84430..d3ecbdccdb 100644 --- a/openair1/SIMULATION/NR_PHY/ulsim.c +++ b/openair1/SIMULATION/NR_PHY/ulsim.c @@ -796,7 +796,7 @@ int main(int argc, char *argv[]) ulsch_input_buffer[0] = 0x31; for (i = 1; i < TBS/8; i++) { - ulsch_input_buffer[i] = (unsigned char) uniformrandom(); + ulsch_input_buffer[i] = (uint8_t)rand(); } uint8_t ptrs_time_density = get_L_ptrs(ptrs_mcs1, ptrs_mcs2, ptrs_mcs3, Imcs, mcs_table); @@ -1117,7 +1117,7 @@ int main(int argc, char *argv[]) pusch_config_pdu->target_code_rate = code_rate; pusch_config_pdu->tbslbrm = tbslbrm; pusch_config_pdu->pusch_data.tb_size = TBS / 8; - pusch_config_pdu->pusch_data.new_data_indicator = trial & 0x1; + pusch_config_pdu->pusch_data.new_data_indicator = round == 0 ? true : false; pusch_config_pdu->pusch_data.rv_index = rv_index; pusch_config_pdu->pusch_data.harq_process_id = harq_pid; pusch_config_pdu->pusch_ptrs.ptrs_time_density = ptrs_time_density; @@ -1612,7 +1612,7 @@ int main(int argc, char *argv[]) free_MIB_NR(mib); if (gNB->ldpc_offload_flag) - free_nrLDPClib_offload(); + free_LDPClib(&ldpc_interface_offload); if (output_fd) fclose(output_fd); diff --git a/openair1/SIMULATION/NR_UE_PHY/unit_tests/src/harq_test.c b/openair1/SIMULATION/NR_UE_PHY/unit_tests/src/harq_test.c index 96d7382f2b..dc182b2106 100644 --- a/openair1/SIMULATION/NR_UE_PHY/unit_tests/src/harq_test.c +++ b/openair1/SIMULATION/NR_UE_PHY/unit_tests/src/harq_test.c @@ -25,7 +25,7 @@ * * MODULE : UE test bench for hard (hybrid repeat request acknowledgment) * -* DESCRIPTION : it allows unitary tests for uplink and downlink harq +* DESCRIPTION : it allows unitary tests for downlink harq * ************************************************************************/ @@ -39,65 +39,6 @@ //#include "PHY/vars.h" //#include "LAYER2/MAC/vars.h" -/******************************************************************* -* -* NAME : test_harq_uplink -* -* PARAMETERS : none -* -* RETURN : none -* -* DESCRIPTION : test of HARQ uplink feature -* -*********************************************************************/ - -int test_harq_uplink(PHY_VARS_NR_UE *phy_vars_ue) -{ - int gNB_id = 0; - int thread_number = 0; - int code_word_idx = 0; - int harq_pid = 0; - int ndi = 1; - uint8_t rnti_type = _C_RNTI_; - int number_steps = 5; - - printf("\nHARQ Uplink \n"); - - config_uplink_harq_process(phy_vars_ue , gNB_id, thread_number, code_word_idx, NR_DEFAULT_DLSCH_HARQ_PROCESSES); - - NR_UE_ULSCH_t *ulsch_harq = phy_vars_ue->ulsch[gNB_id]; - - /* reach maximum number of retransmissions */ - printf("First sequence ndi does not toggle \n"); - for (int i = 0 ; i < number_steps; i++) { - uplink_harq_process(ulsch_harq, harq_pid, ndi, rnti_type); - } - - harq_pid++; /* next harq */ - - /* new grant so new transmission each try */ - printf("Second sequence ndi toggle each transmission \n"); - for (int i = 0 ; i < number_steps; i++) { - uplink_harq_process(ulsch_harq, harq_pid, ndi, rnti_type); - ndi ^= 1; /* toogle ndi each try */ - } - - harq_pid++; /* next harq */ - - /* new grant so new transmission each try */ - printf("Third sequence ndi toggle each two transmissions \n"); - for (int i = 0 ; i < number_steps; i++) { - uplink_harq_process(ulsch_harq, harq_pid, ndi, rnti_type); - if (i & 0x1) { - ndi ^= 1; /* toogle ndi each try */ - } - } - - release_uplink_harq_process(phy_vars_ue , gNB_id, thread_number, code_word_idx); - - return 0; -} - /******************************************************************* * * NAME : test_harq_downlink @@ -175,11 +116,7 @@ int test_harq(PHY_VARS_NR_UE *phy_vars_ue) { int result = -1; - result = test_harq_uplink(phy_vars_ue); - - if (result == 0) { - result = test_harq_downlink(phy_vars_ue); - } + result = test_harq_downlink(phy_vars_ue); return (result); } @@ -188,7 +125,7 @@ int test_harq(PHY_VARS_NR_UE *phy_vars_ue) * * NAME : main * -* DESCRIPTION : test of uplink and downlink harq entities +* DESCRIPTION : test of downlink harq entities * *********************************************************************/ diff --git a/openair2/COMMON/e1ap_messages_types.h b/openair2/COMMON/e1ap_messages_types.h index c50efd337f..dba73dd8b9 100644 --- a/openair2/COMMON/e1ap_messages_types.h +++ b/openair2/COMMON/e1ap_messages_types.h @@ -87,6 +87,7 @@ typedef struct e1ap_setup_req_s { typedef struct e1ap_register_req_t { e1ap_setup_req_t setup_req; e1ap_net_config_t net_config; + uint32_t gnb_id; // unused in CU-UP, but might be necessary for some functionality, e.g., E2 agent } e1ap_register_req_t; typedef struct e1ap_setup_resp_s { diff --git a/openair2/E1AP/e1ap.c b/openair2/E1AP/e1ap.c index 077c67ca98..2aeb873c71 100644 --- a/openair2/E1AP/e1ap.c +++ b/openair2/E1AP/e1ap.c @@ -1801,7 +1801,7 @@ void cucp_task_send_sctp_init_req(instance_t instance, char *my_addr) { void e1_task_handle_sctp_association_ind(E1_t type, instance_t instance, sctp_new_association_ind_t *sctp_new_ind) { if (!getCxtE1(instance)) - createE1inst(type, instance, NULL, NULL); + createE1inst(type, instance, 0, NULL, NULL); e1ap_upcp_inst_t *inst = getCxtE1(instance); inst->sockState = SCTP_STATE_ESTABLISHED; if (type == UPtype) @@ -1897,7 +1897,7 @@ void *E1AP_CUUP_task(void *arg) { switch (msgType) { case E1AP_REGISTER_REQ: { e1ap_register_req_t *reg_req = &E1AP_REGISTER_REQ(msg); - createE1inst(UPtype, myInstance, ®_req->net_config, ®_req->setup_req); + createE1inst(UPtype, myInstance, reg_req->gnb_id, ®_req->net_config, ®_req->setup_req); e1_task_send_sctp_association_req(TASK_CUUP_E1, myInstance, ®_req->net_config); } break; diff --git a/openair2/E1AP/e1ap_common.c b/openair2/E1AP/e1ap_common.c index cf8982339d..984c3de887 100644 --- a/openair2/E1AP/e1ap_common.c +++ b/openair2/E1AP/e1ap_common.c @@ -37,12 +37,13 @@ e1ap_upcp_inst_t *getCxtE1(instance_t instance) return e1ap_inst[instance]; } -void createE1inst(E1_t type, instance_t instance, e1ap_net_config_t *nc, e1ap_setup_req_t *req) +void createE1inst(E1_t type, instance_t instance, uint64_t gnb_id, e1ap_net_config_t *nc, e1ap_setup_req_t *req) { AssertFatal(e1ap_inst[instance] == NULL, "Double call to E1 instance %d\n", (int)instance); e1ap_inst[instance] = calloc(1, sizeof(e1ap_upcp_inst_t)); e1ap_inst[instance]->type = type; e1ap_inst[instance]->instance = instance; + e1ap_inst[instance]->gnb_id = gnb_id; e1ap_inst[instance]->cuup.assoc_id = -1; if (nc) memcpy(&e1ap_inst[instance]->net_config, nc, sizeof(*nc)); diff --git a/openair2/E1AP/e1ap_common.h b/openair2/E1AP/e1ap_common.h index e0aea6990f..4acc606bec 100644 --- a/openair2/E1AP/e1ap_common.h +++ b/openair2/E1AP/e1ap_common.h @@ -29,6 +29,7 @@ typedef struct e1ap_upcp_inst_s { instance_t instance; + uint32_t gnb_id; // associated gNB's ID, unused in E1 but necessary for e.g. E2 agent E1_t type; enum sctp_state_e sockState; struct { @@ -52,7 +53,7 @@ e1ap_upcp_inst_t *getCxtE1(instance_t instance); long E1AP_get_next_transaction_identifier(); void E1AP_free_transaction_identifier(long id); -void createE1inst(E1_t type, instance_t instance, e1ap_net_config_t *nc, e1ap_setup_req_t *req); +void createE1inst(E1_t type, instance_t instance, uint64_t gnb_id, e1ap_net_config_t *nc, e1ap_setup_req_t *req); int e1ap_encode_send(E1_t type, sctp_assoc_t assoc_id, struct E1AP_E1AP_PDU *pdu, uint16_t stream, const char *func); diff --git a/openair2/E1AP/e1ap_setup.c b/openair2/E1AP/e1ap_setup.c index f80a3962a6..70f90b9a56 100644 --- a/openair2/E1AP/e1ap_setup.c +++ b/openair2/E1AP/e1ap_setup.c @@ -68,7 +68,7 @@ static void get_NGU_S1U_addr(char **addr, uint16_t *port) return; } -MessageDef *RCconfig_NR_CU_E1(bool separate_CUUP_process) +MessageDef *RCconfig_NR_CU_E1(const E1_t *entity) { MessageDef *msgConfig = itti_alloc_new_message(TASK_GNB_APP, 0, E1AP_REGISTER_REQ); if (!msgConfig) @@ -82,14 +82,12 @@ MessageDef *RCconfig_NR_CU_E1(bool separate_CUUP_process) sprintf(aprefix, "%s.[%i]", GNB_CONFIG_STRING_GNB_LIST, 0); int num_gnbs = GNBSParams[GNB_ACTIVE_GNBS_IDX].numelt; AssertFatal(num_gnbs == 1, "Support only one gNB per process\n"); + config_getlist(config_get_if(), &GNBParamList, GNBParams, sizeofArray(GNBParams), NULL); + paramdef_t *gnbParms = GNBParamList.paramarray[0]; + e1ap_setup_req_t *e1Setup = &E1AP_REGISTER_REQ(msgConfig).setup_req; if (num_gnbs > 0) { - config_getlist(config_get_if(), &GNBParamList, GNBParams, sizeofArray(GNBParams), NULL); - paramdef_t *gnbParms = GNBParamList.paramarray[0]; - AssertFatal(gnbParms[GNB_GNB_ID_IDX].uptr != NULL, "gNB id %d is not defined in configuration file\n", 0); - e1ap_setup_req_t *e1Setup = &E1AP_REGISTER_REQ(msgConfig).setup_req; msgConfig->ittiMsgHeader.destinationInstance = 0; - e1Setup->gNB_cu_up_id = *(gnbParms[GNB_GNB_ID_IDX].uptr); if (*gnbParms[GNB_GNB_NAME_IDX].strptr) e1Setup->gNB_cu_up_name = *(gnbParms[GNB_GNB_NAME_IDX].strptr); @@ -132,7 +130,11 @@ MessageDef *RCconfig_NR_CU_E1(bool separate_CUUP_process) get_NGU_S1U_addr(&e1ap_nc->localAddressN3, &e1ap_nc->localPortN3); e1ap_nc->remotePortN3 = e1ap_nc->localPortN3 ; - if (separate_CUUP_process) { + AssertFatal(config_isparamset(gnbParms, GNB_GNB_ID_IDX), "%s is not defined in configuration file\n", GNB_CONFIG_STRING_GNB_ID); + uint32_t gnb_id = *gnbParms[GNB_GNB_ID_IDX].uptr; + E1AP_REGISTER_REQ(msgConfig).gnb_id = gnb_id; + + if (entity != NULL) { paramlist_def_t GNBE1ParamList = {GNB_CONFIG_STRING_E1_PARAMETERS, NULL, 0}; paramdef_t GNBE1Params[] = GNBE1PARAMS_DESC; config_getlist(config_get_if(), &GNBE1ParamList, GNBE1Params, sizeofArray(GNBE1Params), aprefix); @@ -141,6 +143,24 @@ MessageDef *RCconfig_NR_CU_E1(bool separate_CUUP_process) e1ap_nc->CUCP_e1_ip_address.ipv4 = 1; strcpy(e1ap_nc->CUUP_e1_ip_address.ipv4_address, *(e1Parms[GNB_CONFIG_E1_IPV4_ADDRESS_CUUP].strptr)); e1ap_nc->CUUP_e1_ip_address.ipv4 = 1; + if (*entity == CPtype) { + // CP needs gNB_ID (although not used, but other parts check it as + // well), and gNB-CU-UP ID should NOT be present as it comes through E1! + AssertFatal(!config_isparamset(gnbParms, GNB_GNB_CU_UP_ID_IDX), "%s must not be defined in configuration file\n", GNB_CONFIG_STRING_GNB_CU_UP_ID); + } else { // UPtype + AssertFatal(config_isparamset(gnbParms, GNB_GNB_CU_UP_ID_IDX), "%s is not be defined in configuration file\n", GNB_CONFIG_STRING_GNB_CU_UP_ID); + e1Setup->gNB_cu_up_id = *gnbParms[GNB_GNB_CU_UP_ID_IDX].u64ptr; + } + } else { + // integrated CU-CP/UP. We don't care about the gNB-CU-UP ID that much, + // but if it's there, check it's the same as gNB ID + uint64_t *gnb_cu_up_id = gnbParms[GNB_GNB_CU_UP_ID_IDX].u64ptr; + AssertFatal(!config_isparamset(gnbParms, GNB_GNB_CU_UP_ID_IDX) || *gnb_cu_up_id == gnb_id, + "%s is different of %s: they need to match or remove %s from config\n", + GNB_CONFIG_STRING_GNB_CU_UP_ID, + GNB_CONFIG_STRING_GNB_ID, + GNB_CONFIG_STRING_GNB_CU_UP_ID); + e1Setup->gNB_cu_up_id = gnb_id; } } return msgConfig; diff --git a/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_gtp.c b/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_gtp.c index 0a14dfe915..ac02a85c05 100644 --- a/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_gtp.c +++ b/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_gtp.c @@ -1,3 +1,24 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + #include "ran_func_gtp.h" #include diff --git a/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_gtp.h b/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_gtp.h index 0f12aa703a..b69fb7e462 100644 --- a/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_gtp.h +++ b/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_gtp.h @@ -1,3 +1,24 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + #ifndef RAN_FUNC_SM_GTP_READ_WRITE_AGENT_H #define RAN_FUNC_SM_GTP_READ_WRITE_AGENT_H diff --git a/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_mac.c b/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_mac.c index 0f690f64c8..099c1bad1c 100644 --- a/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_mac.c +++ b/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_mac.c @@ -1,3 +1,24 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + #include "ran_func_mac.h" #include "openair2/E2AP/flexric/test/rnd/fill_rnd_data_mac.h" #include diff --git a/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_mac.h b/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_mac.h index f81c9bc4ef..c32d84433d 100644 --- a/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_mac.h +++ b/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_mac.h @@ -1,3 +1,24 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + #ifndef SM_MAC_READ_WRITE_AGENT_H #define SM_MAC_READ_WRITE_AGENT_H diff --git a/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_pdcp.c b/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_pdcp.c index aa3cb39431..a340c6f499 100644 --- a/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_pdcp.c +++ b/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_pdcp.c @@ -1,3 +1,24 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + #include "ran_func_pdcp.h" #include diff --git a/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_pdcp.h b/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_pdcp.h index 01d70e8250..951cd7373d 100644 --- a/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_pdcp.h +++ b/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_pdcp.h @@ -1,3 +1,24 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + #ifndef RAN_FUNC_SM_PDCP_READ_WRITE_AGENT_H #define RAN_FUNC_SM_PDCP_READ_WRITE_AGENT_H diff --git a/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_rlc.c b/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_rlc.c index cb884b03ab..bc9bac5916 100644 --- a/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_rlc.c +++ b/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_rlc.c @@ -1,3 +1,24 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + #include #include #include diff --git a/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_rlc.h b/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_rlc.h index d49e56e9d3..b2f518e7f6 100644 --- a/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_rlc.h +++ b/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_rlc.h @@ -1,3 +1,24 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + #ifndef RAN_FUNC_SM_RLC_READ_WRITE_AGENT_H #define RAN_FUNC_SM_RLC_READ_WRITE_AGENT_H diff --git a/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_slice.c b/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_slice.c index 764cddf28f..b0f81136b0 100644 --- a/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_slice.c +++ b/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_slice.c @@ -1,3 +1,24 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + #include "ran_func_slice.h" #include "../../flexric/test/rnd/fill_rnd_data_slice.h" #include diff --git a/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_slice.h b/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_slice.h index 6cbe466bbc..d01f7f2cf2 100644 --- a/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_slice.h +++ b/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_slice.h @@ -1,3 +1,24 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + #ifndef RAN_FUNC_SM_SLICE_READ_WRITE_AGENT_H #define RAN_FUNC_SM_SLICE_READ_WRITE_AGENT_H diff --git a/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_tc.c b/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_tc.c index ca3997da7b..6d420fa183 100644 --- a/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_tc.c +++ b/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_tc.c @@ -1,3 +1,24 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + #include "ran_func_tc.h" #include "../../flexric/test/rnd/fill_rnd_data_tc.h" #include diff --git a/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_tc.h b/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_tc.h index ab5cc4ba6e..19d655301b 100644 --- a/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_tc.h +++ b/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_tc.h @@ -1,3 +1,24 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + #ifndef RAN_FUNC_SM_TC_READ_WRITE_AGENT_H #define RAN_FUNC_SM_TC_READ_WRITE_AGENT_H diff --git a/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_kpm.c b/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_kpm.c index dc173cc52f..562cc715d8 100644 --- a/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_kpm.c +++ b/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_kpm.c @@ -1,3 +1,24 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + #include "ran_func_kpm.h" #include "openair2/E2AP/flexric/test/rnd/fill_rnd_data_kpm.h" #include "openair2/E2AP/flexric/src/util/time_now_us.h" @@ -14,93 +35,77 @@ typedef struct { - NR_UE_info_t *ue_list; - size_t num_ues; + NR_UE_info_t* ue_list[MAX_MOBILES_PER_GNB]; + size_t num_ues; } matched_ues_mac_t; - -static -matched_ues_mac_t filter_ues_by_s_nssai_in_du_or_monolithic(test_cond_e const condition, int64_t const value) +static bool nssai_matches(nssai_t a_nssai, uint8_t b_sst, const uint32_t *b_sd) { - matched_ues_mac_t matched_ues = {.num_ues = 0, .ue_list = calloc(MAX_MOBILES_PER_GNB, sizeof(NR_UE_info_t)) }; - assert(matched_ues.ue_list != NULL && "Memory exhausted"); + AssertFatal(b_sd == NULL || *b_sd <= 0xffffff, "illegal SD %d\n", *b_sd); + if (b_sd == NULL) { + return a_nssai.sst == b_sst && a_nssai.sd == 0xffffff; + } else { + return a_nssai.sst == b_sst && a_nssai.sd == *b_sd; + } +} - /* IMPORTANT: in the case of gNB-DU, it is not possible to filter UEs by S-NSSAI as the ngap context is stored in gNB-CU - instead, we take all connected UEs*/ +static size_t filter_ues_by_s_nssai_in_du_or_monolithic(test_cond_e const condition, + uint8_t sst, + const uint32_t *sd, + matched_ues_mac_t* matches) +{ + DevAssert(matches != NULL); + AssertFatal(condition == EQUAL_TEST_COND, "Condition %d not yet implemented", condition); // Take MAC info - UE_iterator(RC.nrmac[0]->UE_info.list, ue) - { - if (ue) - { - ngap_gNB_ue_context_t *ngap_ue_context_list = NULL; - - // Filter connected UEs by S-NSSAI test condition to get list of matched UEs - // note: not possible to filter - switch (condition) - { - case EQUAL_TEST_COND: - { - if (NODE_IS_MONOLITHIC(RC.nrrrc[0]->node_type)) - { - rrc_gNB_ue_context_t *rrc_ue_context_list = rrc_gNB_get_ue_context_by_rnti_any_du(RC.nrrrc[0], ue->rnti); - ngap_ue_context_list = ngap_get_ue_context(rrc_ue_context_list->ue_context.rrc_ue_id); - assert(ngap_ue_context_list->gNB_instance[0].s_nssai[0][0].sST == value && "Please, check the condition for S-NSSAI. At the moment, OAI supports eMBB"); - } - matched_ues.ue_list[matched_ues.num_ues] = *ue; - matched_ues.num_ues++; - break; - } - - - default: - assert(false && "Condition not yet implemented"); + size_t i = 0; + UE_iterator (RC.nrmac[0]->UE_info.list, ue) { + NR_UE_sched_ctrl_t *sched_ctrl = &ue->UE_sched_ctrl; + // UE matches if any of its DRBs matches + for (int l = 0; l < sched_ctrl->dl_lc_num; ++l) { + long lcid = sched_ctrl->dl_lc_ids[l]; + if (nssai_matches(sched_ctrl->dl_lc_nssai[lcid], sst, sd)) { + matches->ue_list[i++] = ue; + break; } - - } + } + AssertFatal(i < MAX_MOBILES_PER_GNB, "cannot have more UEs than global UE number maximum\n"); } - assert(matched_ues.num_ues >= 1 && "The number of filtered UEs must be at least equal to 1"); - - return matched_ues; + matches->num_ues = i; + assert(matches->num_ues >= 1 && "The number of filtered UEs must be at least equal to 1"); + return i; } typedef struct { - f1_ue_data_t * rrc_ue_id_list; // list of matched UEs on RRC level containing only rrc_ue_id (gNB CU UE ID) + uint32_t rrc_ue_id_list[MAX_MOBILES_PER_GNB]; // list of matched UEs on RRC level containing only rrc_ue_id (gNB CU UE ID) size_t num_ues; } matched_ues_rrc_t; -static -matched_ues_rrc_t filter_ues_by_s_nssai_in_cu(test_cond_e const condition, int64_t const value) +static size_t filter_ues_by_s_nssai_in_cu(test_cond_e const condition, uint8_t sst, const uint32_t *sd, matched_ues_rrc_t* matches) { - matched_ues_rrc_t matched_ues = {.num_ues = 0, .rrc_ue_id_list = calloc(MAX_MOBILES_PER_GNB, sizeof(f1_ue_data_t)) }; - assert(matched_ues.rrc_ue_id_list != NULL && "Memory exhausted"); - + DevAssert(matches != NULL); + AssertFatal(condition == EQUAL_TEST_COND, "Condition %d not yet implemented\n", condition); struct rrc_gNB_ue_context_s *ue_context_p1 = NULL; + size_t i = 0; RB_FOREACH(ue_context_p1, rrc_nr_ue_tree_s, &RC.nrrrc[0]->rrc_ue_head) { - - ngap_gNB_ue_context_t *ngap_ue_context_list = ngap_get_ue_context(ue_context_p1->ue_context.rrc_ue_id); - - // Filter connected UEs by S-NSSAI test condition to get list of matched UEs - switch (condition) - { - case EQUAL_TEST_COND: - assert(ngap_ue_context_list->gNB_instance[0].s_nssai[0][0].sST == value && "Please, check the condition for S-NSSAI. At the moment, OAI supports eMBB"); - matched_ues.rrc_ue_id_list[matched_ues.num_ues].secondary_ue = ue_context_p1->ue_context.rrc_ue_id; - matched_ues.num_ues++; - break; - - default: - assert(false && "Condition not yet implemented"); + gNB_RRC_UE_t *ue = &ue_context_p1->ue_context; + for (int p = 0; p < ue->nb_of_pdusessions; ++p) { + pdusession_t *pdu = &ue->pduSession[0].param; + if (nssai_matches(pdu->nssai, sst, sd)) { + matches->rrc_ue_id_list[i++] = ue_context_p1->ue_context.rrc_ue_id; + break; + } } + AssertFatal(i < MAX_MOBILES_PER_GNB, "cannot have more UEs than global UE number maximum\n"); } - - assert(matched_ues.num_ues >= 1 && "The number of filtered UEs must be at least equal to 1"); - - return matched_ues; + + matches->num_ues = i; + assert(matches->num_ues >= 1 && "The number of filtered UEs must be at least equal to 1"); + return i; } static @@ -398,8 +403,8 @@ kpm_ind_msg_format_1_t fill_kpm_ind_msg_frm_1_in_du(const NR_UE_info_t* UE, cons return msg_frm_1; } -static -kpm_ind_msg_format_3_t fill_kpm_ind_msg_frm_3_in_du(const matched_ues_mac_t matched_ues, const kpm_act_def_format_1_t * act_def_fr_1) +static kpm_ind_msg_format_3_t fill_kpm_ind_msg_frm_3_in_du(const matched_ues_mac_t* matched_ues, + const kpm_act_def_format_1_t* act_def_fr_1) { assert(act_def_fr_1 != NULL); @@ -407,20 +412,20 @@ kpm_ind_msg_format_3_t fill_kpm_ind_msg_frm_3_in_du(const matched_ues_mac_t matc kpm_ind_msg_format_3_t msg_frm_3 = {0}; // Fill UE Measurement Reports - - msg_frm_3.ue_meas_report_lst_len = matched_ues.num_ues; + + msg_frm_3.ue_meas_report_lst_len = matched_ues->num_ues; msg_frm_3.meas_report_per_ue = calloc(msg_frm_3.ue_meas_report_lst_len, sizeof(meas_report_per_ue_t)); assert(msg_frm_3.meas_report_per_ue != NULL && "Memory exhausted"); for (size_t i = 0; iue_list[i]->rnti); // get gNB CU UE ID as rrc_ue_id msg_frm_3.meas_report_per_ue[i].ue_meas_report_lst.type = GNB_DU_UE_ID_E2SM; msg_frm_3.meas_report_per_ue[i].ue_meas_report_lst.gnb_du = fill_gnb_du_data(&rrc_ue_id); // Fill UE related info - msg_frm_3.meas_report_per_ue[i].ind_msg_format_1 = fill_kpm_ind_msg_frm_1_in_du(&matched_ues.ue_list[i], i, act_def_fr_1); + msg_frm_3.meas_report_per_ue[i].ind_msg_format_1 = fill_kpm_ind_msg_frm_1_in_du(matched_ues->ue_list[i], i, act_def_fr_1); } @@ -481,8 +486,8 @@ kpm_ind_msg_format_1_t fill_kpm_ind_msg_frm_1_in_cu(const uint32_t rrc_ue_id, co return msg_frm_1; } -static -kpm_ind_msg_format_3_t fill_kpm_ind_msg_frm_3_in_cu(const matched_ues_rrc_t matched_ues, const kpm_act_def_format_1_t * act_def_fr_1) +static kpm_ind_msg_format_3_t fill_kpm_ind_msg_frm_3_in_cu(const matched_ues_rrc_t* matched_ues, + const kpm_act_def_format_1_t* act_def_fr_1) { assert(act_def_fr_1 != NULL); @@ -490,20 +495,21 @@ kpm_ind_msg_format_3_t fill_kpm_ind_msg_frm_3_in_cu(const matched_ues_rrc_t matc kpm_ind_msg_format_3_t msg_frm_3 = {0}; // Fill UE Measurement Reports - - msg_frm_3.ue_meas_report_lst_len = matched_ues.num_ues; + + msg_frm_3.ue_meas_report_lst_len = matched_ues->num_ues; msg_frm_3.meas_report_per_ue = calloc(msg_frm_3.ue_meas_report_lst_len, sizeof(meas_report_per_ue_t)); assert(msg_frm_3.meas_report_per_ue != NULL && "Memory exhausted"); for (size_t i = 0; irrc_ue_id_list[i]); msg_frm_3.meas_report_per_ue[i].ue_meas_report_lst.type = GNB_UE_ID_E2SM; msg_frm_3.meas_report_per_ue[i].ue_meas_report_lst.gnb = fill_gnb_data(rrc_ue_context_list); // Fill UE related info - msg_frm_3.meas_report_per_ue[i].ind_msg_format_1 = fill_kpm_ind_msg_frm_1_in_cu(matched_ues.rrc_ue_id_list[i].secondary_ue, i, act_def_fr_1); + msg_frm_3.meas_report_per_ue[i].ind_msg_format_1 = + fill_kpm_ind_msg_frm_1_in_cu(matched_ues->rrc_ue_id_list[i], i, act_def_fr_1); } return msg_frm_3; @@ -571,8 +577,8 @@ kpm_ind_msg_format_1_t fill_kpm_ind_msg_frm_1_in_monolithic(const NR_UE_info_t* return msg_frm_1; } -static -kpm_ind_msg_format_3_t fill_kpm_ind_msg_frm_3_in_monolithic(const matched_ues_mac_t matched_ues, const kpm_act_def_format_1_t * act_def_fr_1) +static kpm_ind_msg_format_3_t fill_kpm_ind_msg_frm_3_in_monolithic(const matched_ues_mac_t* matched_ues, + const kpm_act_def_format_1_t* act_def_fr_1) { assert(act_def_fr_1 != NULL); @@ -580,8 +586,8 @@ kpm_ind_msg_format_3_t fill_kpm_ind_msg_frm_3_in_monolithic(const matched_ues_ma kpm_ind_msg_format_3_t msg_frm_3 = {0}; // Fill UE Measurement Reports - - msg_frm_3.ue_meas_report_lst_len = matched_ues.num_ues; + + msg_frm_3.ue_meas_report_lst_len = matched_ues->num_ues; msg_frm_3.meas_report_per_ue = calloc(msg_frm_3.ue_meas_report_lst_len, sizeof(meas_report_per_ue_t)); assert(msg_frm_3.meas_report_per_ue != NULL && "Memory exhausted"); @@ -589,12 +595,13 @@ kpm_ind_msg_format_3_t fill_kpm_ind_msg_frm_3_in_monolithic(const matched_ues_ma for (size_t i = 0; iue_list[i]->rnti); msg_frm_3.meas_report_per_ue[i].ue_meas_report_lst.type = GNB_UE_ID_E2SM; msg_frm_3.meas_report_per_ue[i].ue_meas_report_lst.gnb = fill_gnb_data(rrc_ue_context_list); // Fill UE related info - msg_frm_3.meas_report_per_ue[i].ind_msg_format_1 = fill_kpm_ind_msg_frm_1_in_monolithic(&matched_ues.ue_list[i], i, rrc_ue_context_list->ue_context.rrc_ue_id, act_def_fr_1); + msg_frm_3.meas_report_per_ue[i].ind_msg_format_1 = + fill_kpm_ind_msg_frm_1_in_monolithic(matched_ues->ue_list[i], i, rrc_ue_context_list->ue_context.rrc_ue_id, act_def_fr_1); } return msg_frm_3; @@ -674,6 +681,39 @@ kpm_ind_hdr_t kpm_ind_hdr(void) return hdr; } +static void capture_sst_sd(test_info_lst_t* test, uint8_t *sst, uint32_t **sd) +{ + DevAssert(test != NULL && test->test_cond_value != NULL); + DevAssert(sst != NULL); + DevAssert(sd != NULL); + + // we made a mistake in the past: NSSAI is supposed to be an OCTET_STRING, + // but earlier version of the RAN function and the xApp used integer, so + // handle this gracefully by accepting integer as well + switch (*test->test_cond_value) { + case INTEGER_TEST_COND_VALUE: + AssertFatal(*test->int_value <= 0xff, "illegal SST %ld\n", *test->int_value); + *sst = *test->int_value; + *sd = NULL; + break; + case OCTET_STRING_TEST_COND_VALUE: + if (test->octet_string_value->len == 1) { + *sst = test->octet_string_value->buf[0]; + *sd = NULL; + } else { + DevAssert(test->octet_string_value->len == 4); + uint8_t *buf = test->octet_string_value->buf; + *sst = buf[0]; + *sd = malloc(**sd); + **sd = buf[1] << 16 | buf[2] << 8 | buf[3]; + } + break; + default: + AssertFatal(false, "test condition value %d impossible\n", *test->test_cond_value); + break; + } +} + void read_kpm_sm(void* data) { assert(data != NULL); @@ -749,20 +789,26 @@ void read_kpm_sm(void* data) assert(frm_4->matching_cond_lst[i].test_info_lst.int_value != NULL && "Even though is optional.."); test_cond_e const test_cond = *frm_4->matching_cond_lst[i].test_info_lst.test_cond; - int64_t const value = *frm_4->matching_cond_lst[i].test_info_lst.int_value; + uint8_t sst = 0; + uint32_t *sd = NULL; + capture_sst_sd(&frm_4->matching_cond_lst[i].test_info_lst, &sst, &sd); // Check E2 Node NG-RAN Type if (NODE_IS_DU(RC.nrrrc[0]->node_type)) { - matched_ues_mac_t matched_ues = filter_ues_by_s_nssai_in_du_or_monolithic(test_cond, value); - kpm->ind.msg.frm_3 = fill_kpm_ind_msg_frm_3_in_du(matched_ues, &frm_4->action_def_format_1); + matched_ues_mac_t matched_ues = {0}; + matched_ues.num_ues = filter_ues_by_s_nssai_in_du_or_monolithic(test_cond, sst, sd, &matched_ues); + kpm->ind.msg.frm_3 = fill_kpm_ind_msg_frm_3_in_du(&matched_ues, &frm_4->action_def_format_1); } else if (NODE_IS_CU(RC.nrrrc[0]->node_type)) { - matched_ues_rrc_t matched_ues = filter_ues_by_s_nssai_in_cu(test_cond, value); - kpm->ind.msg.frm_3 = fill_kpm_ind_msg_frm_3_in_cu(matched_ues, &frm_4->action_def_format_1); + matched_ues_rrc_t matched_ues = {0}; + matched_ues.num_ues = filter_ues_by_s_nssai_in_cu(test_cond, sst, sd, &matched_ues); + kpm->ind.msg.frm_3 = fill_kpm_ind_msg_frm_3_in_cu(&matched_ues, &frm_4->action_def_format_1); } else if (NODE_IS_MONOLITHIC(RC.nrrrc[0]->node_type)) { - matched_ues_mac_t matched_ues = filter_ues_by_s_nssai_in_du_or_monolithic(test_cond, value); - kpm->ind.msg.frm_3 = fill_kpm_ind_msg_frm_3_in_monolithic(matched_ues, &frm_4->action_def_format_1); + matched_ues_mac_t matched_ues = {0}; + matched_ues.num_ues = filter_ues_by_s_nssai_in_du_or_monolithic(test_cond, sst, sd, &matched_ues); + kpm->ind.msg.frm_3 = fill_kpm_ind_msg_frm_3_in_monolithic(&matched_ues, &frm_4->action_def_format_1); } else { assert(false && "NG-RAN Type not implemented"); } + free(sd); // if NULL, nothing happens break; } diff --git a/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_kpm.h b/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_kpm.h index a8505a1671..9ef9207819 100644 --- a/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_kpm.h +++ b/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_kpm.h @@ -1,3 +1,24 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + #ifndef RAN_FUNC_SM_KPM_READ_WRITE_AGENT_H #define RAN_FUNC_SM_KPM_READ_WRITE_AGENT_H diff --git a/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_rc.c b/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_rc.c index d482cfffb6..e05bb3fd7b 100644 --- a/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_rc.c +++ b/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_rc.c @@ -1,3 +1,24 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + #include "ran_func_rc.h" #include "../../flexric/test/rnd/fill_rnd_data_rc.h" #include "../../flexric/src/sm/rc_sm/ie/ir/lst_ran_param.h" diff --git a/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_rc.h b/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_rc.h index fa8638650f..c7f252971c 100644 --- a/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_rc.h +++ b/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_rc.h @@ -1,3 +1,24 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + #ifndef RAN_FUNC_SM_RAN_CTRL_READ_WRITE_AGENT_H #define RAN_FUNC_SM_RAN_CTRL_READ_WRITE_AGENT_H diff --git a/openair2/E2AP/RAN_FUNCTION/init_ran_func.c b/openair2/E2AP/RAN_FUNCTION/init_ran_func.c index e7883e1337..abf503c62c 100644 --- a/openair2/E2AP/RAN_FUNCTION/init_ran_func.c +++ b/openair2/E2AP/RAN_FUNCTION/init_ran_func.c @@ -1,3 +1,24 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + #include "init_ran_func.h" #include "read_setup_ran.h" #include "../flexric/src/agent/e2_agent_api.h" diff --git a/openair2/E2AP/README.md b/openair2/E2AP/README.md index 9042e5ed79..c496605f2f 100644 --- a/openair2/E2AP/README.md +++ b/openair2/E2AP/README.md @@ -89,7 +89,7 @@ git submodule update ```bash git clone https://gitlab.eurecom.fr/mosaic5g/flexric flexric cd flexric/ -git checkout 035fd2e8f9a9d2c16df8d44c9e8c13ccddf9ff19 +git checkout 93961d2480b2c7a5721e03435cb34cf9446d1ad1 ``` ### 2.2.2 Build FlexRIC diff --git a/openair2/E2AP/e2_agent_arg.h b/openair2/E2AP/e2_agent_arg.h index b719c32d97..30f1ce4750 100644 --- a/openair2/E2AP/e2_agent_arg.h +++ b/openair2/E2AP/e2_agent_arg.h @@ -28,6 +28,7 @@ typedef struct{ const char *ip; const char *sm_dir; + const bool enabled; } e2_agent_args_t; #endif diff --git a/openair2/E2AP/flexric b/openair2/E2AP/flexric index 035fd2e8f9..93961d2480 160000 --- a/openair2/E2AP/flexric +++ b/openair2/E2AP/flexric @@ -1 +1 @@ -Subproject commit 035fd2e8f9a9d2c16df8d44c9e8c13ccddf9ff19 +Subproject commit 93961d2480b2c7a5721e03435cb34cf9446d1ad1 diff --git a/openair2/ENB_APP/enb_config.c b/openair2/ENB_APP/enb_config.c index 250b84a710..a360369c94 100644 --- a/openair2/ENB_APP/enb_config.c +++ b/openair2/ENB_APP/enb_config.c @@ -2942,9 +2942,19 @@ e2_agent_args_t RCconfig_E2agent(void) LOG_W(GNB_APP, "configuration file does not contain a \"%s\" section, applying default parameters\n", CONFIG_STRING_E2AGENT); return (e2_agent_args_t) {0}; } + + bool enabled = config_isparamset(e2agent_params, E2AGENT_CONFIG_SMDIR_IDX) + && config_isparamset(e2agent_params, E2AGENT_CONFIG_IP_IDX); + if (!enabled) { + LOG_W(GNB_APP, "E2 agent is DISABLED (for activation, define .%s.{%s,%s} parameters)\n", CONFIG_STRING_E2AGENT, E2AGENT_CONFIG_IP, E2AGENT_CONFIG_SMDIR); + return (e2_agent_args_t) { + .enabled = false, + }; + } + return (e2_agent_args_t) { + .enabled = true, .ip = *e2agent_params[E2AGENT_CONFIG_IP_IDX].strptr, - .port = *e2agent_params[E2AGENT_CONFIG_PORT_IDX].u16ptr, .sm_dir = *e2agent_params[E2AGENT_CONFIG_SMDIR_IDX].strptr, }; } diff --git a/openair2/ENB_APP/enb_paramdef.h b/openair2/ENB_APP/enb_paramdef.h index 6417d3cb75..626705317b 100644 --- a/openair2/ENB_APP/enb_paramdef.h +++ b/openair2/ENB_APP/enb_paramdef.h @@ -1330,9 +1330,8 @@ typedef struct srb1_params_s { //#define E2AGENT_CONFIG_PORT "port" #define E2AGENT_CONFIG_SMDIR "sm_dir" -static const char* const e2agent_config_ip_default = NULL; -static const char* const e2agent_config_smdir_default = NULL; -//static const uint16_t e2agent_config_port_default = 36421; +static const char* const e2agent_config_ip_default = "127.0.0.1"; +static const char* const e2agent_config_smdir_default = "."; #define E2AGENT_PARAMS_DESC { \ {E2AGENT_CONFIG_IP, "RIC IP address", 0, strptr:NULL, defstrval:(char*)e2agent_config_ip_default, TYPE_STRING, 0}, \ diff --git a/openair2/GNB_APP/gnb_app.c b/openair2/GNB_APP/gnb_app.c index 74a8a997bd..e2c0b48bd4 100644 --- a/openair2/GNB_APP/gnb_app.c +++ b/openair2/GNB_APP/gnb_app.c @@ -146,7 +146,8 @@ void *gNB_app_task(void *args_p) if (node_type == ngran_gNB_CUCP) { if (itti_create_task(TASK_CUCP_E1, E1AP_CUCP_task, NULL) < 0) AssertFatal(false, "Create task for E1AP CP failed\n"); - MessageDef *msg = RCconfig_NR_CU_E1(true); + E1_t e1type = CPtype; + MessageDef *msg = RCconfig_NR_CU_E1(&e1type); AssertFatal(msg != NULL, "Send inti to task for E1AP CP failed\n"); // this sends the E1AP_REGISTER_REQ to CU-CP so it sets up the socket // it does NOT use the E1AP part diff --git a/openair2/GNB_APP/gnb_config.c b/openair2/GNB_APP/gnb_config.c index 4355a12303..de0373e37a 100644 --- a/openair2/GNB_APP/gnb_config.c +++ b/openair2/GNB_APP/gnb_config.c @@ -93,7 +93,6 @@ #include "nfapi/oai_integration/vendor_ext.h" extern uint16_t sf_ahead; -int macrlc_has_f1 = 0; // synchronization raster per band tables (Rel.15) // (38.101-1 Table 5.4.3.3-1 and 38.101-2 Table 5.4.3.3-1) @@ -1034,7 +1033,9 @@ static NR_ServingCellConfig_t *get_scd_config(configmodule_interface_t *cfg) } static int read_du_cell_info(configmodule_interface_t *cfg, - uint64_t *id, + bool separate_du, + uint32_t *gnb_id, + uint64_t *gnb_du_id, char **name, f1ap_served_cell_info_t *info, int max_cell_info) @@ -1051,7 +1052,11 @@ static int read_du_cell_info(configmodule_interface_t *cfg, // Output a list of all eNBs. config_getlist(cfg, &GNBParamList, GNBParams, sizeof(GNBParams) / sizeof(paramdef_t), NULL); - AssertFatal(GNBParamList.paramarray[0][GNB_GNB_ID_IDX].uptr != NULL, "gNB id %u is not defined in configuration file\n", 0); + + // read the gNB-ID. The DU itself only needs the gNB-DU ID, but some (e.g., + // E2 agent) need the gNB-ID as well if it is running in a separate process + AssertFatal(config_isparamset(GNBParamList.paramarray[0], GNB_GNB_ID_IDX), "%s is not defined in configuration file\n", GNB_CONFIG_STRING_GNB_ID); + *gnb_id = *GNBParamList.paramarray[0][GNB_GNB_ID_IDX].uptr; AssertFatal(strcmp(GNBSParams[GNB_ACTIVE_GNBS_IDX].strlistptr[0], *GNBParamList.paramarray[0][GNB_GNB_NAME_IDX].strptr) == 0, "no active gNB found/mismatch of gNBs: %s vs %s\n", @@ -1068,7 +1073,17 @@ static int read_du_cell_info(configmodule_interface_t *cfg, paramlist_def_t PLMNParamList = {GNB_CONFIG_STRING_PLMN_LIST, NULL, 0}; config_getlist(cfg, &PLMNParamList, PLMNParams, sizeof(PLMNParams) / sizeof(paramdef_t), aprefix); - *id = *(GNBParamList.paramarray[0][GNB_GNB_ID_IDX].uptr); + // if fronthaul is F1, require gNB_DU_ID, else use gNB_ID + if (separate_du) { + AssertFatal(config_isparamset(GNBParamList.paramarray[0], GNB_GNB_DU_ID_IDX), "%s is not defined in configuration file\n", GNB_CONFIG_STRING_GNB_DU_ID); + *gnb_du_id = *GNBParamList.paramarray[0][GNB_GNB_DU_ID_IDX].u64ptr; + } else { + AssertFatal(!config_isparamset(GNBParamList.paramarray[0], GNB_GNB_DU_ID_IDX), + "%s should not be defined in configuration file for monolithic gNB\n", + GNB_CONFIG_STRING_GNB_DU_ID); + *gnb_du_id = *gnb_id; // the gNB-DU ID is equal to the gNB ID, since the config has no gNB-DU ID + } + *name = strdup(*(GNBParamList.paramarray[0][GNB_GNB_NAME_IDX].strptr)); info->tac = malloc(sizeof(*info->tac)); AssertFatal(info->tac != NULL, "out of memory\n"); @@ -1252,7 +1267,8 @@ void RCconfig_nr_macrlc(configmodule_interface_t *cfg) if (strcmp(*(MacRLC_ParamList.paramarray[j][MACRLC_TRANSPORT_N_PREFERENCE_IDX].strptr), "local_RRC") == 0) { // check number of instances is same as RRC/PDCP - } else if (strcmp(*(MacRLC_ParamList.paramarray[j][MACRLC_TRANSPORT_N_PREFERENCE_IDX].strptr), "f1") == 0) { + } else if (strcmp(*(MacRLC_ParamList.paramarray[j][MACRLC_TRANSPORT_N_PREFERENCE_IDX].strptr), "f1") == 0 + || strcmp(*(MacRLC_ParamList.paramarray[j][MACRLC_TRANSPORT_N_PREFERENCE_IDX].strptr), "cudu") == 0) { printf("Configuring F1 interfaces for MACRLC\n"); RC.nrmac[j]->eth_params_n.local_if_name = strdup(*(MacRLC_ParamList.paramarray[j][MACRLC_LOCAL_N_IF_NAME_IDX].strptr)); RC.nrmac[j]->eth_params_n.my_addr = strdup(*(MacRLC_ParamList.paramarray[j][MACRLC_LOCAL_N_ADDRESS_IDX].strptr)); @@ -1261,18 +1277,6 @@ void RCconfig_nr_macrlc(configmodule_interface_t *cfg) RC.nrmac[j]->eth_params_n.remote_portc = *(MacRLC_ParamList.paramarray[j][MACRLC_REMOTE_N_PORTC_IDX].iptr); RC.nrmac[j]->eth_params_n.my_portd = *(MacRLC_ParamList.paramarray[j][MACRLC_LOCAL_N_PORTD_IDX].iptr); RC.nrmac[j]->eth_params_n.remote_portd = *(MacRLC_ParamList.paramarray[j][MACRLC_REMOTE_N_PORTD_IDX].iptr); - ; - RC.nrmac[j]->eth_params_n.transp_preference = ETH_UDP_MODE; - macrlc_has_f1 = 1; - } else if (strcmp(*(MacRLC_ParamList.paramarray[j][MACRLC_TRANSPORT_N_PREFERENCE_IDX].strptr), "cudu") == 0) { - RC.nrmac[j]->eth_params_n.local_if_name = strdup(*(MacRLC_ParamList.paramarray[j][MACRLC_LOCAL_N_IF_NAME_IDX].strptr)); - RC.nrmac[j]->eth_params_n.my_addr = strdup(*(MacRLC_ParamList.paramarray[j][MACRLC_LOCAL_N_ADDRESS_IDX].strptr)); - RC.nrmac[j]->eth_params_n.remote_addr = strdup(*(MacRLC_ParamList.paramarray[j][MACRLC_REMOTE_N_ADDRESS_IDX].strptr)); - RC.nrmac[j]->eth_params_n.my_portc = *(MacRLC_ParamList.paramarray[j][MACRLC_LOCAL_N_PORTC_IDX].iptr); - RC.nrmac[j]->eth_params_n.remote_portc = *(MacRLC_ParamList.paramarray[j][MACRLC_REMOTE_N_PORTC_IDX].iptr); - RC.nrmac[j]->eth_params_n.my_portd = *(MacRLC_ParamList.paramarray[j][MACRLC_LOCAL_N_PORTD_IDX].iptr); - RC.nrmac[j]->eth_params_n.remote_portd = *(MacRLC_ParamList.paramarray[j][MACRLC_REMOTE_N_PORTD_IDX].iptr); - ; RC.nrmac[j]->eth_params_n.transp_preference = ETH_UDP_MODE; } else { // other midhaul AssertFatal(1 == 0, "MACRLC %d: %s unknown northbound midhaul\n", j, *(MacRLC_ParamList.paramarray[j][MACRLC_TRANSPORT_N_PREFERENCE_IDX].strptr)); @@ -1314,10 +1318,11 @@ void RCconfig_nr_macrlc(configmodule_interface_t *cfg) memcpy(RC.nrmac[j]->ulprbbl, prbbl, 275 * sizeof(prbbl[0])); } // for (j=0;jsa) nr_mac_configure_sib1(RC.nrmac[0], &info.plmn, info.nr_cellid, *info.tac); @@ -1326,9 +1331,10 @@ void RCconfig_nr_macrlc(configmodule_interface_t *cfg) // and store it at MAC for sending later NR_BCCH_BCH_Message_t *mib = RC.nrmac[0]->common_channels[0].mib; const NR_BCCH_DL_SCH_Message_t *sib1 = RC.nrmac[0]->common_channels[0].sib1; - f1ap_setup_req_t *req = RC_read_F1Setup(id, name, &info, scc, mib, sib1); + f1ap_setup_req_t *req = RC_read_F1Setup(gnb_du_id, name, &info, scc, mib, sib1); AssertFatal(req != NULL, "could not read F1 Setup information\n"); RC.nrmac[0]->f1_config.setup_req = req; + RC.nrmac[0]->f1_config.gnb_id = gnb_id; free(name); /* read_du_cell_info() allocated memory */ @@ -1550,12 +1556,12 @@ void RCconfig_NRRRC(gNB_RRC_INST *rrc) printf("NRRRC %u: Southbound Transport %s\n",i,*(GNBParamList.paramarray[i][GNB_TRANSPORT_S_PREFERENCE_IDX].strptr)); rrc->node_type = get_node_type(); + rrc->node_id = gnb_id; if (NODE_IS_CU(rrc->node_type)) { paramdef_t SCTPParams[] = GNBSCTPPARAMS_DESC; char aprefix[MAX_OPTNAME_SIZE*2 + 8]; sprintf(aprefix,"%s.[%u].%s",GNB_CONFIG_STRING_GNB_LIST,i,GNB_CONFIG_STRING_SCTP_CONFIG); config_get(config_get_if(), SCTPParams, sizeofArray(SCTPParams), aprefix); - rrc->node_id = gnb_id; LOG_I(GNB_APP,"F1AP: gNB_CU_id[%d] %d\n",k,rrc->node_id); rrc->node_name = strdup(*(GNBParamList.paramarray[0][GNB_GNB_NAME_IDX].strptr)); LOG_I(GNB_APP,"F1AP: gNB_CU_name[%d] %s\n",k,rrc->node_name); @@ -2242,7 +2248,7 @@ ngran_node_t get_node_type(void) RC.nb_nr_macrlc_inst = MacRLC_ParamList.numelt; for (int j = 0; j < RC.nb_nr_macrlc_inst; j++) { if (strcmp(*(MacRLC_ParamList.paramarray[j][MACRLC_TRANSPORT_N_PREFERENCE_IDX].strptr), "f1") == 0) { - macrlc_has_f1 = 1; + return ngran_gNB_DU; // MACRLCs present in config: it must be a DU } } } @@ -2256,10 +2262,9 @@ ngran_node_t get_node_type(void) return ngran_gNB_CUUP; else return ngran_gNB_CU; - } else if (macrlc_has_f1 == 0) + } else { return ngran_gNB; - else - return ngran_gNB_DU; + } } #ifdef E2_AGENT @@ -2272,7 +2277,14 @@ e2_agent_args_t RCconfig_NR_E2agent(void) LOG_W(GNB_APP, "configuration file does not contain a \"%s\" section, applying default parameters from FlexRIC\n", CONFIG_STRING_E2AGENT); return (e2_agent_args_t) { 0 }; } - e2_agent_args_t dst = {0}; + + bool enabled = config_isparamset(e2agent_params, E2AGENT_CONFIG_SMDIR_IDX) + && config_isparamset(e2agent_params, E2AGENT_CONFIG_IP_IDX); + e2_agent_args_t dst = {.enabled = enabled}; + if (!enabled) { + LOG_W(GNB_APP, "E2 agent is DISABLED (for activation, define .%s.{%s,%s} parameters)\n", CONFIG_STRING_E2AGENT, E2AGENT_CONFIG_IP, E2AGENT_CONFIG_SMDIR); + return dst; + } if (e2agent_params[E2AGENT_CONFIG_SMDIR_IDX].strptr != NULL) dst.sm_dir = *e2agent_params[E2AGENT_CONFIG_SMDIR_IDX].strptr; diff --git a/openair2/GNB_APP/gnb_config.h b/openair2/GNB_APP/gnb_config.h index 1238296045..d02b5eb4f5 100644 --- a/openair2/GNB_APP/gnb_config.h +++ b/openair2/GNB_APP/gnb_config.h @@ -107,7 +107,7 @@ int RCconfig_NR_NG(MessageDef *msg_p, uint32_t i); int RCconfig_NR_X2(MessageDef *msg_p, uint32_t i); void wait_f1_setup_response(void); int gNB_app_handle_f1ap_gnb_cu_configuration_update(f1ap_gnb_cu_configuration_update_t *gnb_cu_cfg_update); -MessageDef *RCconfig_NR_CU_E1(bool separate_CUUP_process); +MessageDef *RCconfig_NR_CU_E1(const E1_t *entity); ngran_node_t get_node_type(void); #ifdef E2_AGENT diff --git a/openair2/GNB_APP/gnb_paramdef.h b/openair2/GNB_APP/gnb_paramdef.h index dac12ce70e..e07a89d305 100644 --- a/openair2/GNB_APP/gnb_paramdef.h +++ b/openair2/GNB_APP/gnb_paramdef.h @@ -127,15 +127,21 @@ typedef enum { #define GNB_CONFIG_STRING_UMONDEFAULTDRB "um_on_default_drb" #define GNB_CONFIG_STRING_FORCE256QAMOFF "force_256qam_off" #define GNB_CONFIG_STRING_ENABLE_SDAP "enable_sdap" +#define GNB_CONFIG_STRING_DRBS "drbs" +#define GNB_CONFIG_STRING_GNB_DU_ID "gNB_DU_ID" +#define GNB_CONFIG_STRING_GNB_CU_UP_ID "gNB_CU_UP_ID" + #define GNB_CONFIG_HLP_STRING_ENABLE_SDAP "enable the SDAP layer\n" #define GNB_CONFIG_HLP_FORCE256QAMOFF "suppress activation of 256 QAM despite UE support" -#define GNB_CONFIG_STRING_DRBS "drbs" #define GNB_CONFIG_HLP_STRING_DRBS "Number of total DRBs to establish, including the mandatory for PDU SEssion (default=1)\n" +#define GNB_CONFIG_HLP_GNB_DU_ID "defines the gNB-DU ID (only applicable for DU)" +#define GNB_CONFIG_HLP_GNB_CU_UP_ID "defines the gNB-CU-UP ID (only applicable for CU-UP)" /*-----------------------------------------------------------------------------------------------------------------------------------------*/ /* cell configuration parameters */ /* optname helpstr paramflags XXXptr defXXXval type numelt */ /*-----------------------------------------------------------------------------------------------------------------------------------------*/ +// clang-format off #define GNBPARAMS_DESC {\ {GNB_CONFIG_STRING_GNB_ID, NULL, 0, .uptr=NULL, .defintval=0, TYPE_UINT, 0}, \ {GNB_CONFIG_STRING_CELL_TYPE, NULL, 0, .strptr=NULL, .defstrval="CELL_MACRO_GNB", TYPE_STRING, 0}, \ @@ -165,7 +171,11 @@ typedef enum { {GNB_CONFIG_STRING_FORCE256QAMOFF, GNB_CONFIG_HLP_FORCE256QAMOFF, PARAMFLAG_BOOL, .iptr=NULL, .defintval=0, TYPE_INT, 0}, \ {GNB_CONFIG_STRING_ENABLE_SDAP, GNB_CONFIG_HLP_STRING_ENABLE_SDAP, PARAMFLAG_BOOL,.iptr=NULL, .defintval=0, TYPE_INT, 0}, \ {GNB_CONFIG_STRING_DRBS, GNB_CONFIG_HLP_STRING_DRBS, 0, .iptr=NULL, .defintval=1, TYPE_INT, 0}, \ +{GNB_CONFIG_STRING_GNB_DU_ID, GNB_CONFIG_HLP_GNB_DU_ID, 0, .u64ptr=NULL, .defint64val=1, TYPE_UINT64, 0}, \ +{GNB_CONFIG_STRING_GNB_CU_UP_ID, GNB_CONFIG_HLP_GNB_CU_UP_ID, 0, .u64ptr=NULL, .defint64val=1, TYPE_UINT64, 0}, \ } +// clang-format on + #define GNB_GNB_ID_IDX 0 #define GNB_CELL_TYPE_IDX 1 @@ -195,6 +205,8 @@ typedef enum { #define GNB_FORCE256QAMOFF_IDX 25 #define GNB_ENABLE_SDAP_IDX 26 #define GNB_DRBS 27 +#define GNB_GNB_DU_ID_IDX 28 +#define GNB_GNB_CU_UP_ID_IDX 29 #define TRACKING_AREA_CODE_OKRANGE {0x0001,0xFFFD} #define GNBPARAMS_CHECK { \ diff --git a/openair2/LAYER2/NR_MAC_UE/mac_defs.h b/openair2/LAYER2/NR_MAC_UE/mac_defs.h index 18560f3e92..c7bbee0780 100644 --- a/openair2/LAYER2/NR_MAC_UE/mac_defs.h +++ b/openair2/LAYER2/NR_MAC_UE/mac_defs.h @@ -505,9 +505,7 @@ typedef struct { fapi_nr_csirs_measurements_t csirs_measurements; /// Last NDI of UL HARQ processes - uint8_t UL_ndi[NR_MAX_HARQ_PROCESSES]; - /// first ULTX of UL HARQ processes - int first_ul_tx[NR_MAX_HARQ_PROCESSES]; + int UL_ndi[NR_MAX_HARQ_PROCESSES]; //// FAPI-like interface message fapi_nr_ul_config_request_t *ul_config_request; fapi_nr_dl_config_request_t *dl_config_request; diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c index 73228af0d1..ebcb0e601b 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c @@ -597,7 +597,7 @@ void nr_Msg3_transmitted(module_id_t mod_id, uint8_t CC_id, frame_t frameP, slot // start contention resolution timer (cnt in slots) int RA_contention_resolution_timer_subframes = (nr_rach_ConfigCommon->ra_ContentionResolutionTimer + 1)<<3; - ra->RA_contention_resolution_target_frame = frameP + (RA_contention_resolution_timer_subframes/10); + ra->RA_contention_resolution_target_frame = (frameP + (RA_contention_resolution_timer_subframes/10)) % MAX_FRAME_NUMBER; ra->RA_contention_resolution_target_slot = (slotP + (RA_contention_resolution_timer_subframes * subframes_per_slot)) % nr_slots_per_frame[mu]; LOG_D(MAC,"In %s: [UE %d] CB-RA: contention resolution timer set in frame.slot %d.%d and expiring in %d.%d\n", diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c index e4bf6a0d26..2bb1691eae 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c @@ -197,7 +197,7 @@ void nr_ue_mac_default_configs(NR_UE_MAC_INST_t *mac) mac->scheduling_info.lc_sched_info[i].LCID_status = LCID_EMPTY; mac->scheduling_info.lc_sched_info[i].LCID_buffer_remain = 0; for (int k = 0; k < NR_MAX_HARQ_PROCESSES; k++) - mac->first_ul_tx[k] = 1; + mac->UL_ndi[k] = -1; // initialize to invalid value } memset(&mac->ssb_measurements, 0, sizeof(mac->ssb_measurements)); diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c index 83ad5e88b1..f688d6c2a4 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c @@ -627,7 +627,8 @@ int nr_config_pusch_pdu(NR_UE_MAC_INST_t *mac, } /* NDI */ - pusch_config_pdu->pusch_data.new_data_indicator = dci->ndi; + pusch_config_pdu->pusch_data.new_data_indicator = dci->ndi != mac->UL_ndi[dci->harq_pid] ? 1 : 0; + mac->UL_ndi[dci->harq_pid] = dci->ndi; /* RV */ pusch_config_pdu->pusch_data.rv_index = dci->rv; /* HARQ_PROCESS_NUMBER */ @@ -1032,9 +1033,8 @@ void nr_ue_ul_scheduler(nr_uplink_indication_t *ul_info) if (ulcfg_pdu->pdu_type == FAPI_NR_UL_CONFIG_TYPE_PUSCH) { int mac_pdu_exist = 0; uint16_t TBS_bytes = ulcfg_pdu->pusch_config_pdu.pusch_data.tb_size; - LOG_D(NR_MAC,"harq_id %d, NDI %d NDI_DCI %d, TBS_bytes %d (ra_state %d)\n", + LOG_D(NR_MAC,"harq_id %d, new_data_indicator %d, TBS_bytes %d (ra_state %d)\n", ulcfg_pdu->pusch_config_pdu.pusch_data.harq_process_id, - mac->UL_ndi[ulcfg_pdu->pusch_config_pdu.pusch_data.harq_process_id], ulcfg_pdu->pusch_config_pdu.pusch_data.new_data_indicator, TBS_bytes,ra->ra_state); if (ra->ra_state == WAIT_RAR && !ra->cfra) { @@ -1043,14 +1043,10 @@ void nr_ue_ul_scheduler(nr_uplink_indication_t *ul_info) for (int k = 0; k < TBS_bytes; k++) { LOG_D(NR_MAC,"(%i): 0x%x\n", k, ulsch_input_buffer[k]); } - LOG_D(NR_MAC,"Flipping NDI for harq_id %d (Msg3)\n", ulcfg_pdu->pusch_config_pdu.pusch_data.new_data_indicator); - mac->UL_ndi[ulcfg_pdu->pusch_config_pdu.pusch_data.harq_process_id] = ulcfg_pdu->pusch_config_pdu.pusch_data.new_data_indicator; - mac->first_ul_tx[ulcfg_pdu->pusch_config_pdu.pusch_data.harq_process_id] = 0; mac_pdu_exist = 1; } else { - if ((mac->UL_ndi[ulcfg_pdu->pusch_config_pdu.pusch_data.harq_process_id] != ulcfg_pdu->pusch_config_pdu.pusch_data.new_data_indicator || - mac->first_ul_tx[ulcfg_pdu->pusch_config_pdu.pusch_data.harq_process_id] == 1) && + if (ulcfg_pdu->pusch_config_pdu.pusch_data.new_data_indicator && (mac->state == UE_CONNECTED || (ra->ra_state == WAIT_RAR && ra->cfra))){ @@ -1059,10 +1055,6 @@ void nr_ue_ul_scheduler(nr_uplink_indication_t *ul_info) mac_pdu_exist = 1; } - LOG_D(NR_MAC,"Flipping NDI for harq_id %d\n",ulcfg_pdu->pusch_config_pdu.pusch_data.new_data_indicator); - mac->UL_ndi[ulcfg_pdu->pusch_config_pdu.pusch_data.harq_process_id] = ulcfg_pdu->pusch_config_pdu.pusch_data.new_data_indicator; - mac->first_ul_tx[ulcfg_pdu->pusch_config_pdu.pusch_data.harq_process_id] = 0; - } // Config UL TX PDU diff --git a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h index b205abafd0..26a24c203e 100644 --- a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h +++ b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h @@ -730,6 +730,7 @@ typedef bool (*nr_pp_impl_ul)(module_id_t mod_id, typedef struct f1_config_t { f1ap_setup_req_t *setup_req; f1ap_setup_resp_t *setup_resp; + uint32_t gnb_id; // associated gNB's ID, not used in DU itself } f1_config_t; /*! \brief top level eNB MAC structure */ diff --git a/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c b/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c index 49df9469ab..383ae37d35 100644 --- a/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c +++ b/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c @@ -647,7 +647,7 @@ void nr_rlc_reestablish_entity(int rnti, int lc_id) nr_rlc_manager_unlock(nr_rlc_ue_manager); } -void nr_rlc_reconfigure_entity(int rnti, int lc_id, struct NR_RLC_Config *rlc_Config, struct NR_LogicalChannelConfig *lc_Config) +void nr_rlc_reconfigure_entity(int rnti, int lc_id, NR_RLC_Config_t *rlc_Config) { nr_rlc_manager_lock(nr_rlc_ue_manager); nr_rlc_ue_t *ue = nr_rlc_manager_get_ue(nr_rlc_ue_manager, rnti); @@ -656,12 +656,6 @@ void nr_rlc_reconfigure_entity(int rnti, int lc_id, struct NR_RLC_Config *rlc_Co LOG_E(RLC, "RLC instance for the given UE was not found \n"); nr_rlc_entity_t *rb = get_rlc_entity_from_lcid(ue, lc_id); - if (lc_Config) { - if (lc_Config->ul_SpecificParameters && lc_Config->ul_SpecificParameters->logicalChannelGroup) - AssertFatal(*lc_Config->ul_SpecificParameters->logicalChannelGroup < 2, - "LCG %ld not supported as per limitation when creating RBs\n", - *lc_Config->ul_SpecificParameters->logicalChannelGroup); - } if (rlc_Config) { AssertFatal(rb->stats.mode != NR_RLC_TM, "Cannot reconfigure TM mode\n"); if (rb->stats.mode == NR_RLC_AM) { @@ -718,9 +712,6 @@ void nr_rlc_reconfigure_entity(int rnti, int lc_id, struct NR_RLC_Config *rlc_Co void nr_rlc_add_srb(int rnti, int srb_id, const NR_RLC_BearerConfig_t *rlc_BearerConfig) { struct NR_RLC_Config *r = rlc_BearerConfig->rlc_Config; - struct NR_LogicalChannelConfig *l = rlc_BearerConfig->mac_LogicalChannelConfig; - int logical_channel_group; - int t_status_prohibit; int t_poll_retransmit; int poll_pdu; @@ -733,17 +724,6 @@ void nr_rlc_add_srb(int rnti, int srb_id, const NR_RLC_BearerConfig_t *rlc_Beare AssertFatal(srb_id > 0 && srb_id < 4, "Invalid srb id %d\n", srb_id); - if (l && l->ul_SpecificParameters && l->ul_SpecificParameters->logicalChannelGroup) - logical_channel_group = *l->ul_SpecificParameters->logicalChannelGroup; - else - logical_channel_group = 0; // default value as in 9.2.1 of 38.331 - - /* TODO: accept other values? */ - if (logical_channel_group != 0) { - LOG_E(RLC, "%s:%d:%s: fatal error\n", __FILE__, __LINE__, __FUNCTION__); - exit(1); - } - if (r && r->present == NR_RLC_Config_PR_am) { struct NR_RLC_Config__am *am; am = r->choice.am; @@ -800,8 +780,6 @@ void nr_rlc_add_srb(int rnti, int srb_id, const NR_RLC_BearerConfig_t *rlc_Beare static void add_drb_am(int rnti, int drb_id, const NR_RLC_BearerConfig_t *rlc_BearerConfig) { struct NR_RLC_Config *r = rlc_BearerConfig->rlc_Config; - struct NR_LogicalChannelConfig *l = rlc_BearerConfig->mac_LogicalChannelConfig; - int logical_channel_group; int t_status_prohibit; int t_poll_retransmit; @@ -814,14 +792,6 @@ static void add_drb_am(int rnti, int drb_id, const NR_RLC_BearerConfig_t *rlc_Be AssertFatal(drb_id > 0 && drb_id <= MAX_DRBS_PER_UE, "Invalid DRB ID %d\n", drb_id); - logical_channel_group = *l->ul_SpecificParameters->logicalChannelGroup; - - /* TODO: accept other values? */ - if (logical_channel_group != 1) { - LOG_E(RLC, "%s:%d:%s: fatal error\n", __FILE__, __LINE__, __FUNCTION__); - //exit(1); - } - switch (r->present) { case NR_RLC_Config_PR_am: { struct NR_RLC_Config__am *am; @@ -875,8 +845,6 @@ static void add_drb_am(int rnti, int drb_id, const NR_RLC_BearerConfig_t *rlc_Be static void add_drb_um(int rnti, int drb_id, const NR_RLC_BearerConfig_t *rlc_BearerConfig) { struct NR_RLC_Config *r = rlc_BearerConfig->rlc_Config; - struct NR_LogicalChannelConfig *l = rlc_BearerConfig->mac_LogicalChannelConfig; - int logical_channel_group; int sn_field_length; int t_reassembly; @@ -884,14 +852,6 @@ static void add_drb_um(int rnti, int drb_id, const NR_RLC_BearerConfig_t *rlc_Be AssertFatal(drb_id > 0 && drb_id <= MAX_DRBS_PER_UE, "Invalid DRB ID %d\n", drb_id); - logical_channel_group = *l->ul_SpecificParameters->logicalChannelGroup; - - /* TODO: accept other values? */ - if (logical_channel_group != 1) { - LOG_E(RLC, "%s:%d:%s: fatal error\n", __FILE__, __LINE__, __FUNCTION__); - exit(1); - } - switch (r->present) { case NR_RLC_Config_PR_um_Bi_Directional: { struct NR_RLC_Config__um_Bi_Directional *um; diff --git a/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.h b/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.h index d8a0d66f00..4f4578ec80 100644 --- a/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.h +++ b/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.h @@ -53,7 +53,7 @@ void nr_rlc_test_trigger_reestablishment(int rnti); void nr_rlc_release_entity(int rnti, logical_chan_id_t channel_id); -void nr_rlc_reconfigure_entity(int rnti, int lc_id, struct NR_RLC_Config *rlc_Config, struct NR_LogicalChannelConfig *lc_Config); +void nr_rlc_reconfigure_entity(int rnti, int lc_id, NR_RLC_Config_t *rlc_Config); int nr_rlc_get_available_tx_space( const rnti_t rntiP, diff --git a/openair2/RRC/NR/nr_rrc_config.c b/openair2/RRC/NR/nr_rrc_config.c index 5c3f44bd7e..c7de394f79 100644 --- a/openair2/RRC/NR/nr_rrc_config.c +++ b/openair2/RRC/NR/nr_rrc_config.c @@ -252,11 +252,19 @@ static uint64_t get_ssb_bitmap(const NR_ServingCellConfigCommon_t *scc) return bitmap; } -static void set_csirs_periodicity(NR_NZP_CSI_RS_Resource_t *nzpcsi0, int id, int nb_slots_per_period, int nb_dl_slots_period) +static int set_ideal_period(const int n_slots_period, const int n_ul_slots_period) +{ + return MAX_MOBILES_PER_GNB * 2 * n_slots_period / n_ul_slots_period; // 2 reports per UE +} + +static void set_csirs_periodicity(NR_NZP_CSI_RS_Resource_t *nzpcsi0, + int id, + int ideal_period, + int nb_slots_per_period, + int nb_dl_slots_period) { nzpcsi0->periodicityAndOffset = calloc(1,sizeof(*nzpcsi0->periodicityAndOffset)); // TODO ideal period to be set according to estimation by the gNB on how fast the channel changes - const int ideal_period = 320; const int offset = nb_slots_per_period * id; if (ideal_period < 5) { @@ -327,8 +335,10 @@ static void config_csirs(const NR_ServingCellConfigCommon_t *servingcellconfigco &servingcellconfigcommon->tdd_UL_DL_ConfigurationCommon->pattern1 : NULL; const int n_slots_frame = slotsperframe[*servingcellconfigcommon->ssbSubcarrierSpacing]; - int nb_slots_per_period = tdd ? n_slots_frame/get_nb_periods_per_frame(tdd->dl_UL_TransmissionPeriodicity): n_slots_frame; - int nb_dl_slots_period = tdd ? tdd->nrofDownlinkSlots : n_slots_frame; + const int nb_slots_per_period = tdd ? n_slots_frame/get_nb_periods_per_frame(tdd->dl_UL_TransmissionPeriodicity): n_slots_frame; + const int nb_dl_slots_period = tdd ? tdd->nrofDownlinkSlots : n_slots_frame; + const int n_ul_slots_period = tdd ? (tdd->nrofUplinkSlots + (tdd->nrofUplinkSymbols > 0)) : n_slots_frame; + const int ideal_period = set_ideal_period(nb_slots_per_period, n_ul_slots_period); // same periodicity as CSI measurement report if(!csi_MeasConfig->nzp_CSI_RS_ResourceToAddModList) csi_MeasConfig->nzp_CSI_RS_ResourceToAddModList = calloc(1,sizeof(*csi_MeasConfig->nzp_CSI_RS_ResourceToAddModList)); @@ -378,7 +388,7 @@ static void config_csirs(const NR_ServingCellConfigCommon_t *servingcellconfigco nzpcsi0->powerControlOffsetSS = calloc(1,sizeof(*nzpcsi0->powerControlOffsetSS)); *nzpcsi0->powerControlOffsetSS = NR_NZP_CSI_RS_Resource__powerControlOffsetSS_db0; nzpcsi0->scramblingID = *servingcellconfigcommon->physCellId; - set_csirs_periodicity(nzpcsi0, id, nb_slots_per_period, nb_dl_slots_period); + set_csirs_periodicity(nzpcsi0, id, ideal_period, nb_slots_per_period, nb_dl_slots_period); nzpcsi0->qcl_InfoPeriodicCSI_RS = calloc(1,sizeof(*nzpcsi0->qcl_InfoPeriodicCSI_RS)); *nzpcsi0->qcl_InfoPeriodicCSI_RS = 0; asn1cSeqAdd(&csi_MeasConfig->nzp_CSI_RS_ResourceToAddModList->list,nzpcsi0); @@ -1458,7 +1468,7 @@ static void set_csi_meas_periodicity(const NR_ServingCellConfigCommon_t *scc, NR const int n_slots_frame = slotsperframe[*scc->ssbSubcarrierSpacing]; const int n_ul_slots_period = tdd ? (tdd->nrofUplinkSlots + (tdd->nrofUplinkSymbols > 0)) : n_slots_frame; const int n_slots_period = tdd ? n_slots_frame / get_nb_periods_per_frame(tdd->dl_UL_TransmissionPeriodicity) : n_slots_frame; - const int ideal_period = MAX_MOBILES_PER_GNB * 2 * n_slots_period / n_ul_slots_period; // 2 reports per UE + const int ideal_period = set_ideal_period(n_slots_period, n_ul_slots_period); const int first_ul_slot_period = tdd ? get_first_ul_slot(tdd->nrofDownlinkSlots, tdd->nrofDownlinkSymbols, tdd->nrofUplinkSymbols) : 0; const int idx = (uid << 1) + is_rsrp; const int offset = first_ul_slot_period + idx % n_ul_slots_period + (idx / n_ul_slots_period) * n_slots_period; diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c index dea1494f17..1d331b6340 100644 --- a/openair2/RRC/NR/rrc_gNB.c +++ b/openair2/RRC/NR/rrc_gNB.c @@ -254,11 +254,19 @@ static int get_ssb_arfcn(const f1ap_served_cell_info_t *cell_info, const NR_MIB_ uint32_t dl_arfcn = get_dl_arfcn(cell_info); int scs = get_ssb_scs(cell_info); int band = get_dl_band(cell_info); - uint64_t scaling = band < 100 ? 1 : 3; + // FR1 includes frequency bands from 410 MHz (ARFCN 82000) to 7125 MHz (ARFCN 875000) + // FR2 includes frequency bands from 24.25 GHz (ARFCN 2016667) to 71.0 GHz (ARFCN 2795832) + uint64_t scaling = 0; + if (dl_arfcn >= 82000 && dl_arfcn < 875000) + scaling = 1; + else if (dl_arfcn >= 2016667 && dl_arfcn < 2795832) + scaling = 4; + else + AssertFatal(false, "Invalid absoluteFrequencyPointA: %d\n", dl_arfcn); + uint64_t freqpointa = from_nrarfcn(band, scs, dl_arfcn); - // offsetToPointA and kSSB are both on 15kHz SCS (see 38.211 sections 7.4.3.1 - // and 4.4.4.2) + // offsetToPointA and kSSB are both on 15kHz SCS for FR1 and 60kHz SCS for FR2 (see 38.211 sections 7.4.3.1 and 4.4.4.2) // SSB uses the SCS of the cell and is 20 RBs wide, so use 10 uint64_t freqssb = freqpointa + scaling * 15000 * (offsetToPointA * 12 + kssb) + 10ll * 12 * (1 << scs) * 15000; int bw_index = get_supported_band_index(scs, band, get_dl_bw(cell_info)); diff --git a/openair2/RRC/NR_UE/rrc_UE.c b/openair2/RRC/NR_UE/rrc_UE.c index d77cfd6a47..0617f79a83 100644 --- a/openair2/RRC/NR_UE/rrc_UE.c +++ b/openair2/RRC/NR_UE/rrc_UE.c @@ -689,8 +689,8 @@ static int8_t nr_rrc_ue_decode_NR_BCCH_DL_SCH_Message(instance_t instance, switch (bcch_message->message.choice.c1->present) { case NR_BCCH_DL_SCH_MessageType__c1_PR_systemInformationBlockType1: LOG_D(NR_RRC, "[UE %ld] Decoding SIB1\n", instance); - if(SI_info->sib1) - ASN_STRUCT_FREE(asn_DEF_NR_SIB1, SI_info->sib1); + ASN_STRUCT_FREE(asn_DEF_NR_SIB1, SI_info->sib1); + SI_info->sib1 = NULL; NR_SIB1_t *sib1 = bcch_message->message.choice.c1->choice.systemInformationBlockType1; if(!SI_info->sib1) SI_info->sib1 = calloc(1, sizeof(*SI_info->sib1)); @@ -745,7 +745,7 @@ static void nr_rrc_manage_rlc_bearers(const instance_t instance, if (rrc->active_RLC_entity[lcid]) { if (rlc_bearer->reestablishRLC) nr_rlc_reestablish_entity(rnti, lcid); - nr_rlc_reconfigure_entity(rnti, lcid, rlc_bearer->rlc_Config, rlc_bearer->mac_LogicalChannelConfig); + nr_rlc_reconfigure_entity(rnti, lcid, rlc_bearer->rlc_Config); } else { rrc->active_RLC_entity[lcid] = true; AssertFatal(rlc_bearer->servedRadioBearer, "servedRadioBearer mandatory in case of setup\n"); diff --git a/openair3/UTILS/conversions.h b/openair3/UTILS/conversions.h index bf24c9f4ee..ad84ecf0e0 100644 --- a/openair3/UTILS/conversions.h +++ b/openair3/UTILS/conversions.h @@ -110,10 +110,10 @@ do { \ /* Convert an array of char containing vALUE to x */ #define BUFFER_TO_INT32(buf, x) \ do { \ - x = ((buf)[0] << 24) | \ - ((buf)[1] << 16) | \ - ((buf)[2] << 8) | \ - ((buf)[3]); \ + x = (((uint32_t)(buf)[0]) << 24) | \ + (((uint32_t)(buf)[1]) << 16) | \ + (((uint32_t)(buf)[2]) << 8) | \ + (((uint32_t)(buf)[3])); \ } while(0) /* Convert an array of char containing vALUE to x */ @@ -427,10 +427,10 @@ do { \ do { \ DevCheck((bITsTRING)->size == 4, (bITsTRING)->size, 4, 0); \ DevCheck((bITsTRING)->bits_unused == 0, (bITsTRING)->bits_unused, 0, 0); \ - mACRO = ((bITsTRING)->buf[3] << 24) + \ - ((bITsTRING)->buf[2] << 16) + \ - ((bITsTRING)->buf[1] << 8) + \ - ((bITsTRING)->buf[0]); \ + mACRO = (((uint32_t) (bITsTRING)->buf[3]) << 24) + \ + (((uint32_t) (bITsTRING)->buf[2]) << 16) + \ + (((uint32_t) (bITsTRING)->buf[1]) << 8) + \ + (((uint32_t) (bITsTRING)->buf[0])); \ } while (0) diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/du_gnb.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/du_gnb.conf index 67fa7726dc..f3c95f1bc7 100644 --- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/du_gnb.conf +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/du_gnb.conf @@ -7,6 +7,7 @@ gNBs = { ////////// Identification parameters: gNB_ID = 0xe00; + gNB_DU_ID = 0xe00; # cell_type = "CELL_MACRO_GNB";