Merge remote-tracking branch 'origin/t2-offload-mr' into integration_2023_w48

This commit is contained in:
Robert Schmidt
2023-12-04 17:16:51 +01:00
29 changed files with 2251 additions and 3445 deletions
+35 -38
View File
@@ -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) add_boolean_option(ENABLE_LDPC_T2 OFF "Build support for LDPC Offload to T2 library" OFF)
if (ENABLE_LDPC_T1) set(ENV{PKG_CONFIG_PATH} "$ENV{PKG_CONFIG_PATH}:/usr/local/lib/x86_64-linux-gnu/pkgconfig")
pkg_check_modules(LIBDPDK_T1 REQUIRED libdpdk=20.05.0) if (ENABLE_LDPC_T2)
find_library(T1 NAMES rte_pmd_hpac_sdfec_pmd REQUIRED) pkg_check_modules(LIBDPDK_T2 REQUIRED libdpdk=20.11.7)
if (NOT T1) find_library(PMD_T2 NAMES rte_baseband_accl_ldpc HINTS "/opt/dpdk-t2/lib/x86_64-linux-gnu/")
message(FATAL_ERROR "Library rte_pmd_hpac_sdfec_pmd for T1 offload not found") if (NOT PMD_T2)
message(FATAL_ERROR "could not find PMD T2")
endif() endif()
add_library(ldpc_t1 MODULE ${OPENAIR1_DIR}/PHY/CODING/nrLDPC_decoder/nrLDPC_decoder_offload.c) message(STATUS "T2 build: use ${PMD_T2}")
set_target_properties(ldpc_t1 PROPERTIES COMPILE_FLAGS "-DALLOW_EXPERIMENTAL_API") add_library(ldpc_t2 MODULE ${OPENAIR1_DIR}/PHY/CODING/nrLDPC_decoder/nrLDPC_decoder_offload.c)
target_compile_options(ldpc_t1 PRIVATE ${LIBDPDK_T1_CFLAGS}) set_target_properties(ldpc_t2 PROPERTIES COMPILE_FLAGS "-DALLOW_EXPERIMENTAL_API")
target_link_libraries(ldpc_t1 ${LIBDPDK_T1_LDFLAGS} ${T1}) target_link_libraries(ldpc_t2 ${LIBDPDK_T2_LDFLAGS} ${PMD_T2})
endif() endif()
########################################################## ##########################################################
@@ -819,19 +820,30 @@ set(PHY_LDPC_ORIG_SRC
${OPENAIR1_DIR}/PHY/CODING/nrLDPC_decoder/nrLDPC_decoder.c ${OPENAIR1_DIR}/PHY/CODING/nrLDPC_decoder/nrLDPC_decoder.c
${OPENAIR1_DIR}/PHY/CODING/nrLDPC_encoder/ldpc_encoder.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 set(PHY_LDPC_OPTIM_SRC
${OPENAIR1_DIR}/PHY/CODING/nrLDPC_decoder/nrLDPC_decoder.c ${OPENAIR1_DIR}/PHY/CODING/nrLDPC_decoder/nrLDPC_decoder.c
${OPENAIR1_DIR}/PHY/CODING/nrLDPC_encoder/ldpc_encoder_optim.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 set(PHY_LDPC_OPTIM8SEG_SRC
${OPENAIR1_DIR}/PHY/CODING/nrLDPC_decoder/nrLDPC_decoder.c ${OPENAIR1_DIR}/PHY/CODING/nrLDPC_decoder/nrLDPC_decoder.c
${OPENAIR1_DIR}/PHY/CODING/nrLDPC_encoder/ldpc_encoder_optim8seg.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 set(PHY_LDPC_OPTIM8SEGMULTI_SRC
${OPENAIR1_DIR}/PHY/CODING/nrLDPC_decoder/nrLDPC_decoder.c ${OPENAIR1_DIR}/PHY/CODING/nrLDPC_decoder/nrLDPC_decoder.c
${OPENAIR1_DIR}/PHY/CODING/nrLDPC_encoder/ldpc_encoder_optim8segmulti.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 set(PHY_LDPC_CUDA_SRC
${OPENAIR1_DIR}/PHY/CODING/nrLDPC_decoder_LYC/nrLDPC_decoder_LYC.cu ${OPENAIR1_DIR}/PHY/CODING/nrLDPC_decoder_LYC/nrLDPC_decoder_LYC.cu
${OPENAIR1_DIR}/PHY/CODING/nrLDPC_encoder/ldpc_encoder_optim8segmulti.c ${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 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 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} ) add_library(ldpc_cl MODULE ${PHY_LDPC_CL_SRC} )
target_link_libraries(ldpc_cl OpenCL) target_link_libraries(ldpc_cl OpenCL)
add_dependencies(ldpc_cl nrLDPC_decoder_kernels_CL) add_dependencies(ldpc_cl nrLDPC_decoder_kernels_CL)
set(PHY_NR_CODINGIF
${OPENAIR1_DIR}/PHY/CODING/nrLDPC_load.c
)
############################################## ##############################################
# Base CUDA setting # Base CUDA setting
@@ -877,13 +881,6 @@ if (ENABLE_LDPC_CUDA)
endif() endif()
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(coding MODULE ${PHY_TURBOSRC} )
add_library(dfts MODULE ${OPENAIR1_DIR}/PHY/TOOLS/oai_dfts.c ${OPENAIR1_DIR}/PHY/TOOLS/oai_dfts_neon.c) 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) add_dependencies(nr-softmodem ldpc_orig ldpc_optim ldpc_optim8seg ldpc)
if (ENABLE_LDPC_T1) if (ENABLE_LDPC_T2)
add_dependencies(nr-softmodem ldpc_t1) add_dependencies(nr-softmodem ldpc_t2)
endif() endif()
# force the generation of ASN.1 so that we don't need to wait during the build # 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 ${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) if (ENABLE_LDPC_CUDA)
add_dependencies(ldpctest ldpc_cuda) add_dependencies(ldpctest ldpc_cuda)
endif() endif()
target_link_libraries(ldpctest PRIVATE 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} m pthread dl shlib_loader ${T_LIB}
) )
@@ -2307,8 +2304,8 @@ add_executable(nr_ulsim
${PHY_INTERFACE_DIR}/queue_t.c ${PHY_INTERFACE_DIR}/queue_t.c
) )
if (ENABLE_LDPC_T1) if (ENABLE_LDPC_T2)
add_dependencies(nr_ulsim ldpc_t1) add_dependencies(nr_ulsim ldpc_t2)
endif() endif()
target_link_libraries(nr_ulsim PRIVATE 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 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 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 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}) if (TARGET ${i})
add_dependencies(${i} generate_T) add_dependencies(${i} generate_T)
endif() endif()
+1 -1
View File
@@ -35,7 +35,7 @@
<mode>TesteNB</mode> <mode>TesteNB</mode>
<class>Build_eNB</class> <class>Build_eNB</class>
<desc>Build gNB (USRP)</desc> <desc>Build gNB (USRP)</desc>
<Build_eNB_args>--gNB -w USRP --ninja -c -P --build-lib "ldpc_cuda ldpc_t1" --cmake-opt -DASN1C_EXEC=/opt/asn1c/bin/asn1c</Build_eNB_args> <Build_eNB_args>--gNB -w USRP --ninja -c -P --build-lib "ldpc_cuda" --cmake-opt -DASN1C_EXEC=/opt/asn1c/bin/asn1c</Build_eNB_args>
<forced_workspace_cleanup>True</forced_workspace_cleanup> <forced_workspace_cleanup>True</forced_workspace_cleanup>
</testCase> </testCase>
-102
View File
@@ -1,102 +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
-->
<testCaseList>
<htmlTabRef>test-t1-offload</htmlTabRef>
<htmlTabName>Test T1 Offload</htmlTabName>
<htmlTabIcon>tasks</htmlTabIcon>
<repeatCount>1</repeatCount>
<TestCaseRequestedList>000111 000112 000121 000122 000131 000132 000211 000212 000221 000222 000231 000232</TestCaseRequestedList>
<TestCaseExclusionList></TestCaseExclusionList>
<testCase id="000111">
<class>Run_LDPCt1Test</class>
<desc>Run nr_ulsim with CPU</desc>
<physim_run_args>-n100 -s30 -m5 -r106 -R106 -C10 -P</physim_run_args>
</testCase>
<testCase id="000112">
<class>Run_LDPCt1Test</class>
<desc>Run nr_ulsim with T1 LDPC offload</desc>
<physim_run_args>-n100 -s30 -m5 -r106 -R106 -o -P</physim_run_args>
</testCase>
<testCase id="000121">
<class>Run_LDPCt1Test</class>
<desc>Run nr_ulsim with CPU</desc>
<physim_run_args>-n100 -s30 -m15 -r106 -R106 -C10 -P</physim_run_args>
</testCase>
<testCase id="000122">
<class>Run_LDPCt1Test</class>
<desc>Run nr_ulsim with T1 LDPC offload</desc>
<physim_run_args>-n100 -s30 -m15 -r106 -R106 -o -P</physim_run_args>
</testCase>
<testCase id="000131">
<class>Run_LDPCt1Test</class>
<desc>Run nr_ulsim with CPU</desc>
<physim_run_args>-n100 -s30 -m25 -r106 -R106 -C10 -P</physim_run_args>
</testCase>
<testCase id="000132">
<class>Run_LDPCt1Test</class>
<desc>Run nr_ulsim with T1 LDPC offload</desc>
<physim_run_args>-n100 -s30 -m25 -r106 -R106 -o -P</physim_run_args>
</testCase>
<testCase id="000211">
<class>Run_LDPCt1Test</class>
<desc>Run nr_ulsim with CPU</desc>
<physim_run_args>-n100 -s30 -m5 -r273 -R273 -C10 -P</physim_run_args>
</testCase>
<testCase id="000212">
<class>Run_LDPCt1Test</class>
<desc>Run nr_ulsim with T1 LDPC offload</desc>
<physim_run_args>-n100 -s30 -m5 -r273 -R273 -o -P</physim_run_args>
</testCase>
<testCase id="000221">
<class>Run_LDPCt1Test</class>
<desc>Run nr_ulsim with CPU</desc>
<physim_run_args>-n100 -s30 -m15 -r273 -R273 -C10 -P</physim_run_args>
</testCase>
<testCase id="000222">
<class>Run_LDPCt1Test</class>
<desc>Run nr_ulsim with T1 LDPC offload</desc>
<physim_run_args>-n100 -s30 -m15 -r273 -R273 -o -P</physim_run_args>
</testCase>
<testCase id="000231">
<class>Run_LDPCt1Test</class>
<desc>Run nr_ulsim with CPU</desc>
<physim_run_args>-n100 -s30 -m25 -r273 -R273 -C10 -P</physim_run_args>
</testCase>
<testCase id="000232">
<class>Run_LDPCt1Test</class>
<desc>Run nr_ulsim with T1 LDPC offload</desc>
<physim_run_args>-n100 -s30 -m25 -r273 -R273 -o -P</physim_run_args>
</testCase>
</testCaseList>
+1 -1
View File
@@ -46,7 +46,7 @@ BUILD_DOXYGEN=0
DISABLE_HARDWARE_DEPENDENCY="False" DISABLE_HARDWARE_DEPENDENCY="False"
CMAKE_BUILD_TYPE="RelWithDebInfo" CMAKE_BUILD_TYPE="RelWithDebInfo"
CMAKE_CMD="$CMAKE" 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="" TARGET_LIST=""
function print_help() { function print_help() {
-1
View File
@@ -183,7 +183,6 @@ Some libraries have further dependencies and might not build on every system:
- `enbscope`, `uescope`, `nrscope`: libforms/X - `enbscope`, `uescope`, `nrscope`: libforms/X
- `nrqtscope`: Qt5 - `nrqtscope`: Qt5
- `ldpc_cuda`: CUDA - `ldpc_cuda`: CUDA
- `ldpc_t1`: DPDK and VVDN T1
- `websrv`: npm and others - `websrv`: npm and others
# Running `cmake` directly # Running `cmake` directly
+149
View File
@@ -0,0 +1,149 @@
<table style="border-collapse: collapse; border: none;">
<tr style="border-collapse: collapse; border: none;">
<td style="border-collapse: collapse; border: none;">
<a href="http://www.openairinterface.org/">
<img src="./images/oai_final_logo.png" alt="" border=3 height=50 width=150>
</img>
</a>
</td>
<td style="border-collapse: collapse; border: none; vertical-align: center;">
<b><font size = "5">OAI T1/T2 LDPC offload</font></b>
</td>
</tr>
</table>
**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.*
+1 -1
View File
@@ -98,7 +98,7 @@
#define CONFIG_HLP_WORKER_CMD "two option for worker 'WORKER_DISABLE' or 'WORKER_ENABLE'\n" #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_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_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_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_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" #define CONFIG_HLP_RX_SUBDEV "set the arguments to select rx_subdev (same syntax as in UHD)\n"
+5 -2
View File
@@ -428,6 +428,9 @@ static void get_channel_model_mode(configmodule_interface_t *cfg)
int NB_UE_INST = 1; int NB_UE_INST = 1;
configmodule_interface_t *uniqCfg = NULL; 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 main( int argc, char **argv ) {
int set_exe_prio = 1; int set_exe_prio = 1;
if (checkIfFedoraDistribution()) if (checkIfFedoraDistribution())
@@ -465,8 +468,8 @@ int main( int argc, char **argv ) {
itti_init(TASK_MAX, tasks_info); itti_init(TASK_MAX, tasks_info);
init_opt() ; init_opt() ;
load_nrLDPClib(NULL); load_LDPClib(NULL, &ldpc_interface);
if (ouput_vcd) { if (ouput_vcd) {
vcd_signal_dumper_init("/tmp/openair_dump_nrUE.vcd"); vcd_signal_dumper_init("/tmp/openair_dump_nrUE.vcd");
} }
+272 -349
View File
@@ -42,6 +42,7 @@
#define NR_LDPC_PROFILER_DETAIL #define NR_LDPC_PROFILER_DETAIL
#define NR_LDPC_ENABLE_PARITY_CHECK #define NR_LDPC_ENABLE_PARITY_CHECK
ldpc_interface_t ldpc_orig, ldpc_toCompare;
// 4-bit quantizer // 4-bit quantizer
int8_t quantize4bit(double D,double x) int8_t quantize4bit(double D,double x)
@@ -77,49 +78,48 @@ int8_t quantize8bit(double D,double x)
} }
typedef struct { typedef struct {
double n_iter_mean[400]; double n_iter_mean;
double n_iter_std[400]; double n_iter_std;
int n_iter_max[400]; int n_iter_max;
double snr[400]; double snr;
double ber[400]; double ber;
double bler[400]; double bler;
} n_iter_stats_t; } 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}; one_measurement_t test_ldpc(short max_iterations,
int nom_rate,
int test_ldpc(short max_iterations, int denom_rate,
int nom_rate, double SNR,
int denom_rate, unsigned char qbits,
double SNR, short block_length,
uint8_t qbits, unsigned int ntrials,
short block_length, int n_segments)
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 ret = {0};
reset_meas(&ret.time_optim);
reset_meas(&ret.time_decoder);
//clock initiate //clock initiate
//time_stats_t time,time_optim,tinput,tprep,tparity,toutput, time_decoder; //time_stats_t time,time_optim,tinput,tprep,tparity,toutput, time_decoder;
time_stats_t time, tinput,tprep,tparity,toutput; time_stats_t time, tinput,tprep,tparity,toutput;
double n_iter_mean = 0; double n_iter_mean = 0;
double n_iter_std = 0; double n_iter_std = 0;
int n_iter_max = 0; int n_iter_max = 0;
unsigned int segment_bler = 0;
double sigma; double sigma;
sigma = 1.0/sqrt(2*SNR); sigma = 1.0/sqrt(2*SNR);
opp_enabled=1; opp_enabled=1;
//short test_input[block_length]; //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};; uint8_t *test_input[MAX_NUM_NR_DLSCH_SEGMENTS_PER_LAYER * NR_MAX_NB_LAYERS];
//short *c; //padded codeword
uint8_t estimated_output[MAX_NUM_DLSCH_SEGMENTS][block_length]; uint8_t estimated_output[MAX_NUM_DLSCH_SEGMENTS][block_length];
memset(estimated_output, 0, sizeof(estimated_output)); memset(estimated_output, 0, sizeof(estimated_output));
uint8_t *channel_input[MAX_NUM_DLSCH_SEGMENTS]; 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 }; double modulated_input[MAX_NUM_DLSCH_SEGMENTS][68 * 384] = { 0 };
int8_t channel_output_fixed[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; short BG=0,nrows=0;//,ncols;
int no_punctured_columns,removed_bit; int i1, Kb = 0;
int i1,Zc,Kb=0;
int R_ind = 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 n_segments=1;
int code_rate_vec[8] = {15, 13, 25, 12, 23, 34, 56, 89}; 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}; //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; int32_t n_iter = 0;
*errors=0;
*errors_bit=0;
*errors_bit_uncoded=0;
*crc_misses=0;
// generate input block // generate input block
for(int j=0;j<MAX_NUM_DLSCH_SEGMENTS;j++) { for(int j=0;j<MAX_NUM_DLSCH_SEGMENTS;j++) {
test_input[j]=(uint8_t *)malloc16(sizeof(uint8_t) * block_length/8); test_input[j] = malloc16(block_length / 8);
memset(test_input[j], 0, sizeof(uint8_t) * block_length / 8); memset(test_input[j], 0, block_length / 8);
channel_input[j] = (uint8_t *)malloc16(sizeof(uint8_t) * 68*384); channel_input[j] = malloc16(68 * 384);
memset(channel_input[j], 0, sizeof(uint8_t) * 68 * 384); memset(channel_input[j], 0, 68 * 384);
channel_input_optim[j] = (uint8_t *)malloc16(sizeof(uint8_t) * 68*384); channel_input_optim[j] = malloc16(68 * 384);
memset(channel_input_optim[j], 0, sizeof(uint8_t) * 68 * 384); memset(channel_input_optim[j], 0, 68 * 384);
} }
reset_meas(&time); reset_meas(&time);
reset_meas(time_optim);
reset_meas(time_decoder);
reset_meas(&tinput); reset_meas(&tinput);
reset_meas(&tprep); reset_meas(&tprep);
reset_meas(&tparity); reset_meas(&tparity);
@@ -178,243 +168,220 @@ int test_ldpc(short max_iterations,
reset_meas(&decoder_profiler.llr2bit); reset_meas(&decoder_profiler.llr2bit);
//reset_meas(&decoder_profiler.total); //reset_meas(&decoder_profiler.total);
for (int j=0;j<MAX_NUM_DLSCH_SEGMENTS;j++) { // Fill a input packet with random values
for (int i=0; i<block_length/8; i++) { for (int j = 0; j < MAX_NUM_DLSCH_SEGMENTS; j++)
test_input[j][i]=(uint8_t) rand(); for (int i = 0; i < block_length / 8; i++)
//test_input[j][i]=j%256; test_input[j][i] = (uint8_t)rand();
//test_input[j][i]=252;
}
}
//determine number of bits in codeword //determine number of bits in codeword
if (block_length>3840) if (block_length > 3840) {
{
BG = 1; BG = 1;
Kb = 22; Kb = 22;
nrows = 46; //parity check bits nrows = 46; // parity check bits
//ncols=22; //info bits // ncols=22; //info bits
} } else {
else if (block_length<=3840)
{
BG = 2; BG = 2;
nrows = 42; //parity check bits nrows = 42; // parity check bits
//ncols=10; // info bits // ncols=10; // info bits
if (block_length > 640)
if (block_length>640)
Kb = 10; Kb = 10;
else if (block_length>560) else if (block_length > 560)
Kb = 9; Kb = 9;
else if (block_length>192) else if (block_length > 192)
Kb = 8; Kb = 8;
else else
Kb = 6; Kb = 6;
} }
if (nom_rate == 1) bool error = false;
if (denom_rate == 5) switch (nom_rate) {
if (BG == 2) case 1:
R_ind = 0; if (denom_rate == 5)
else if (BG == 2)
printf("Not supported"); R_ind = 0;
else if (denom_rate == 3) else
R_ind = 1; error = true;
else if (denom_rate == 2) else if (denom_rate == 3)
//R_ind = 3; R_ind = 1;
printf("Not supported"); else if (denom_rate == 2)
else // R_ind = 3;
printf("Not supported"); 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 (error) {
if (denom_rate == 5) printf("Not supported: nom_rate: %d, denom_rate: %d\n", nom_rate, denom_rate);
//R_ind = 2; exit(1);
printf("Not supported"); }
else if (denom_rate == 3)
R_ind = 4;
else
printf("Not supported");
else if ((nom_rate == 22) && (denom_rate == 30)) // find minimum value in all sets of lifting size
//R_ind = 5; int Zc = 0;
printf("Not supported"); const short lift_size[51] = {2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 18, 20,
else if ((nom_rate == 22) && (denom_rate == 27)) 22, 24, 26, 28, 30, 32, 36, 40, 44, 48, 52, 56, 60, 64, 72, 80, 88,
//R_ind = 6; 96, 104, 112, 120, 128, 144, 160, 176, 192, 208, 224, 240, 256, 288, 320, 352, 384};
printf("Not supported"); for (i1 = 0; i1 < 51; i1++) {
else if ((nom_rate == 22) && (denom_rate == 25)) if (lift_size[i1] >= (double)block_length / Kb) {
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)
{
Zc = lift_size[i1]; Zc = lift_size[i1];
//printf("%d\n",Zc);
break; 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); 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); // 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)); const int removed_bit =
encoder_implemparams_t impp=INIT0_LDPCIMPLEMPARAMS; (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; impp.gen_code = 2;
if (ntrials==0) 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; impp.gen_code=0;
decode_abort_t dec_abort; decode_abort_t dec_abort;
init_abort(&dec_abort); init_abort(&dec_abort);
for (int trial=0; trial < ntrials; trial++) for (int trial = 0; trial < ntrials; trial++) {
{ unsigned int segment_bler = 0;
segment_bler = 0;
//// encoder //// encoder
start_meas(&time); start_meas(&time);
for(int j=0;j<n_segments;j++) { for (int j = 0; j < n_segments; j++) {
encoder_orig(&(test_input[j]), &(channel_input[j]),Zc,Kb,block_length,BG,&impp); ldpc_orig.LDPCencoder(&test_input[j], &channel_input[j], &impp);
} }
stop_meas(&time); stop_meas(&time);
/* start_meas(time_optim); impp.n_segments = n_segments;
ldpc_encoder_optim_8seg(test_input,channel_input_optim,Zc,Kb,block_length,BG,n_segments,&tinput,&tprep,&tparity,&toutput); for (int j = 0; j < (n_segments / 8 + 1); j++) {
for(j=0;j<n_segments;j++) { start_meas(&ret.time_optim);
ldpc_encoder_optim(test_input[j],channel_input_optim[j],Zc,Kb,block_length,BG,&tinput,&tprep,&tparity,&toutput); impp.macro_num = j;
} ldpc_toCompare.LDPCencoder(test_input, channel_input_optim, &impp);
stop_meas(time_optim);*/ stop_meas(&ret.time_optim);
impp.n_segments=n_segments;
for(int j=0;j<(n_segments/8+1);j++) {
start_meas(time_optim);
impp.macro_num=j;
nrLDPC_encoder(test_input,channel_input_optim,Zc,Kb,block_length, BG, &impp);
stop_meas(time_optim);
}
if (ntrials==1)
for (int j=0;j<n_segments;j++)
for (int i = 0; i < block_length+(nrows-no_punctured_columns) * Zc - removed_bit; i++)
if (channel_input[j][i]!=channel_input_optim[j][i]) {
printf("differ in seg %d pos %d (%u,%u)\n", j, i, channel_input[j][i], channel_input_optim[j][i]);
return (-1);
}
//else{
// printf("NOT differ in seg %d pos %d (%d,%d)\n",j,i,channel_input[j][i],channel_input_optim[j][i]);
// }
if (trial== 0) {
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);
} }
if (1) { // Transmitting one segment if (ntrials == 1)
for(int j=0;j<n_segments;j++) { for (int j = 0; j < n_segments; j++)
for (int i = 2*Zc; i < (Kb+nrows-no_punctured_columns) * Zc-removed_bit; i++) { for (int i = 0; i < block_length + (nrows - no_punctured_columns) * Zc - removed_bit; i++)
if (channel_input[j][i] != channel_input_optim[j][i]) {
printf("differ in seg %d pos %d (%u,%u)\n", j, i, channel_input[j][i], channel_input_optim[j][i]);
return ret;
}
for (int j = 0; j < n_segments; j++) {
for (int i = 2 * Zc; i < (Kb + nrows - no_punctured_columns) * Zc - removed_bit; i++) {
#ifdef DEBUG_CODER #ifdef DEBUG_CODER
if ((i&0xf)==0) if ((i & 0xf) == 0)
printf("\ne %d..%d: ",i,i+15); printf("\ne %d..%d: ", i, i + 15);
#endif #endif
if (channel_input_optim[j][i-2*Zc]==0) if (channel_input_optim[j][i - 2 * Zc] == 0)
modulated_input[j][i]=1.0;///sqrt(2); //QPSK modulated_input[j][i] = 1.0; /// sqrt(2); //QPSK
else else
modulated_input[j][i]=-1.0;///sqrt(2); modulated_input[j][i] = -1.0; /// sqrt(2);
///channel_output[i] = modulated_input[i] + gaussdouble(0.0,1.0) * 1/sqrt(2*SNR); channel_output_fixed[j][i] =
//channel_output_fixed[i] = (int8_t) ((channel_output[i]*128)<0?(channel_output[i]*128-0.5):(channel_output[i]*128+0.5)); //fixed point 9-7 (int8_t)quantize(sigma / 4.0 / 4.0, modulated_input[j][i] + sigma * gaussdouble(0.0, 1.0), qbits);
//printf("llr[%d]=%d\n",i,channel_output_fixed[i]);
//channel_output_fixed[i] = (int8_t)quantize(sigma/4.0,(2.0*modulated_input[i]) - 1.0 + sigma*gaussdouble(0.0,1.0),qbits); // Uncoded BER
channel_output_fixed[j][i] = (int8_t)quantize(sigma/4.0/4.0,modulated_input[j][i] + sigma*gaussdouble(0.0,1.0),qbits); uint8_t channel_output_uncoded = channel_output_fixed[j][i] < 0 ? 1 /* QPSK demod */ : 0;
//channel_output_fixed[i] = (int8_t)quantize8bit(sigma/4.0,(2.0*modulated_input[i]) - 1.0 + sigma*gaussdouble(0.0,1.0)); if (channel_output_uncoded != channel_input_optim[j][i - 2 * Zc])
//printf("llr[%d]=%d\n",i,channel_output_fixed[i]); ret.errors_bit_uncoded++;
//printf("channel_output_fixed[%d]: %d\n",i,channel_output_fixed[i]); }
//Uncoded BER
uint8_t channel_output_uncoded = channel_output_fixed[j][i]<0 ? 1 /* QPSK demod */ : 0;
if (channel_output_uncoded != channel_input_optim[j][i-2*Zc])
*errors_bit_uncoded = (*errors_bit_uncoded) + 1;
}
#ifdef DEBUG_CODER #ifdef DEBUG_CODER
printf("\n"); printf("\n");
exit(-1); exit(-1);
#endif #endif
decParams[j].BG=BG; decParams[j].BG = BG;
decParams[j].Z=Zc; decParams[j].Z = Zc;
decParams[j].R=code_rate_vec[R_ind];//13; decParams[j].R = code_rate_vec[R_ind]; // 13;
decParams[j].numMaxIter=max_iterations; decParams[j].numMaxIter = max_iterations;
decParams[j].outMode = nrLDPC_outMode_BIT; decParams[j].outMode = nrLDPC_outMode_BIT;
decParams[j].block_length=block_length; decParams[j].E = block_length;
nrLDPC_initcall(&decParams[j], (int8_t*)channel_output_fixed[j], (int8_t*)estimated_output[j]); ldpc_toCompare.LDPCinit();
}
for(int j=0;j<n_segments;j++) {
start_meas(time_decoder);
set_abort(&dec_abort, false);
n_iter = nrLDPC_decoder(&decParams[j],
(int8_t *)channel_output_fixed[j],
(int8_t *)estimated_output[j],
&decoder_profiler,
&dec_abort);
stop_meas(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++)
{
uint8_t estoutputbit = (estimated_output[j][i/8]&(1<<(i&7)))>>(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;
} }
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; ret.errors_bit_uncoded = ret.errors_bit_uncoded / (double)((Kb + nrows - no_punctured_columns - 2) * Zc - removed_bit);
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;
*errors_bit_uncoded = *errors_bit_uncoded / (double)((Kb+nrows-no_punctured_columns-2) * Zc-removed_bit); for (int j = 0; j < MAX_NUM_DLSCH_SEGMENTS; j++) {
for(int j=0;j<MAX_NUM_DLSCH_SEGMENTS;j++) {
free(test_input[j]); free(test_input[j]);
free(channel_input[j]); free(channel_input[j]);
free(channel_input_optim[j]); free(channel_input_optim[j]);
} }
print_meas(&time,"ldpc_encoder",NULL,NULL); print_meas(&time,"ldpc_encoder",NULL,NULL);
print_meas(time_optim,"ldpc_encoder_optim",NULL,NULL); print_meas(&ret.time_optim, "ldpc_encoder_optim", NULL, NULL);
print_meas(&tinput,"ldpc_encoder_optim(input)",NULL,NULL); print_meas(&tinput,"ldpc_encoder_optim(input)",NULL,NULL);
print_meas(&tprep,"ldpc_encoder_optim(prep)",NULL,NULL); print_meas(&tprep,"ldpc_encoder_optim(prep)",NULL,NULL);
print_meas(&tparity,"ldpc_encoder_optim(parity)",NULL,NULL); print_meas(&tparity,"ldpc_encoder_optim(parity)",NULL,NULL);
print_meas(&toutput,"ldpc_encoder_optim(output)",NULL,NULL); print_meas(&toutput,"ldpc_encoder_optim(output)",NULL,NULL);
printf("\n"); printf("\n");
print_meas(time_decoder,"ldpc_decoder",NULL,NULL); print_meas(&ret.time_decoder, "ldpc_decoder", NULL, NULL);
print_meas(&decoder_profiler.llr2llrProcBuf,"llr2llrProcBuf",NULL,NULL); print_meas(&decoder_profiler.llr2llrProcBuf,"llr2llrProcBuf",NULL,NULL);
print_meas(&decoder_profiler.llr2CnProcBuf,"llr2CnProcBuf",NULL,NULL); print_meas(&decoder_profiler.llr2CnProcBuf,"llr2CnProcBuf",NULL,NULL);
print_meas(&decoder_profiler.cnProc,"cnProc (per iteration)",NULL,NULL); print_meas(&decoder_profiler.cnProc,"cnProc (per iteration)",NULL,NULL);
@@ -427,18 +394,15 @@ int test_ldpc(short max_iterations,
print_meas(&decoder_profiler.llr2bit,"llr2bit",NULL,NULL); print_meas(&decoder_profiler.llr2bit,"llr2bit",NULL,NULL);
printf("\n"); printf("\n");
return *errors; return ret;
} }
configmodule_interface_t *uniqCfg = NULL; configmodule_interface_t *uniqCfg = NULL;
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
unsigned int errors, errors_bit, crc_misses;
double errors_bit_uncoded;
short block_length=8448; // decoder supports length: 1201 -> 1280, 2401 -> 2560 short block_length=8448; // decoder supports length: 1201 -> 1280, 2401 -> 2560
// default to check output inside ldpc, the NR version checks the outer CRC defined by 3GPP // 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 */ /* version of the ldpc decoder library to use (XXX suffix to use when loading libldpc_XXX.so */
short max_iterations=5; short max_iterations=5;
int n_segments=1; int n_segments=1;
@@ -446,25 +410,22 @@ int main(int argc, char *argv[])
int nom_rate=1; int nom_rate=1;
int denom_rate=3; int denom_rate=3;
double SNR0=-2.0,SNR,SNR_lin; double SNR0=-2.0;
uint8_t qbits=8; uint8_t qbits=8;
unsigned int decoded_errors[10000]; // initiate the size of matrix equivalent to size of SNR 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; int n_trials = 1;
double SNR_step = 0.1; double SNR_step = 0.1;
randominit(0); randominit(0);
int test_uncoded= 0; int test_uncoded= 0;
n_iter_stats_t dec_iter[400] = {0};
time_stats_t time_optim[10], time_decoder[10]; short BG = 0, Zc;
n_iter_stats_t dec_iter;
short BG=0,Zc,Kb=0;
while ((c = getopt (argc, argv, "q:r:s:S:l:G:n:d:i:t:u:hv:")) != -1) while ((c = getopt (argc, argv, "q:r:s:S:l:G:n:d:i:t:u:hv:")) != -1)
switch (c) switch (c) {
{
case 'q': case 'q':
qbits = atoi(optarg); qbits = atoi(optarg);
break; break;
@@ -509,29 +470,29 @@ int main(int argc, char *argv[])
test_uncoded = atoi(optarg); test_uncoded = atoi(optarg);
break; break;
case 'v': case 'v':
ldpc_version=strdup(optarg); ldpc_version = strdup(optarg);
break; break;
case 'h': case 'h':
default: default:
printf("CURRENTLY SUPPORTED CODE RATES: \n"); printf("CURRENTLY SUPPORTED CODE RATES: \n");
printf("BG1 (blocklength > 3840): 1/3, 2/3, 22/25 (8/9) \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("BG2 (blocklength <= 3840): 1/5, 1/3, 2/3 \n\n");
printf("-h This message\n"); printf("-h This message\n");
printf("-q Quantization bits, Default: 8\n"); printf("-q Quantization bits, Default: 8\n");
printf("-r Nominator rate, (1, 2, 22), Default: 1\n"); printf("-r Nominator rate, (1, 2, 22), Default: 1\n");
printf("-d Denominator rate, (3, 5, 25), 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("-l Block length (l > 3840 -> BG1, rest BG2 ), Default: 8448\n");
printf("-G give 1 to run cuda for LDPC, Default: 0\n"); printf("-G give 1 to run cuda for LDPC, Default: 0\n");
printf("-n Number of simulation trials, Default: 1\n"); printf("-n Number of simulation trials, Default: 1\n");
//printf("-M MCS2 for TB 2\n"); // printf("-M MCS2 for TB 2\n");
printf("-s SNR per information bit (EbNo) in dB, Default: -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("-S Number of segments (Maximum: 8), Default: 1\n");
printf("-t SNR simulation step, Default: 0.1\n"); printf("-t SNR simulation step, Default: 0.1\n");
printf("-i Max decoder iterations, Default: 5\n"); printf("-i Max decoder iterations, Default: 5\n");
printf("-u Set SNR per coded bit, Default: 0\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"); printf("-v XXX Set ldpc shared library version. libldpc_XXX.so will be used \n");
exit(1); exit(1);
break; break;
} }
//printf("the decoder supports BG2, Kb=10, Z=128 & 256\n"); //printf("the decoder supports BG2, Kb=10, Z=128 & 256\n");
//printf(" range of blocklength: 1201 -> 1280, 2401 -> 2560\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("n_trials %d: \n", n_trials);
printf("SNR0 %f: \n", SNR0); printf("SNR0 %f: \n", SNR0);
load_nrLDPClib(ldpc_version); load_LDPClib(ldpc_version, &ldpc_toCompare);
load_nrLDPClib_ref("_orig", &encoder_orig); load_LDPClib("_orig", &ldpc_orig);
//for (block_length=8;block_length<=MAX_BLOCK_LENGTH;block_length+=8) //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 //find minimum value in all sets of lifting size
Zc=0; 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]; 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); 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"); 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"); 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;SNR<SNR0+20.0;SNR+=SNR_step) { for (double SNR = SNR0; SNR < SNR0 + 20.0; SNR += SNR_step) {
//reset_meas(&time_optim); double SNR_lin;
//reset_meas(&time_decoder);
//n_iter_stats_t dec_iter = {0, 0, 0};
if (test_uncoded == 1) if (test_uncoded == 1)
SNR_lin = pow(10,SNR/10.0); SNR_lin = pow(10, SNR / 10.0);
else else
SNR_lin = pow(10,SNR/10.0)*nom_rate/denom_rate; SNR_lin = pow(10, SNR / 10.0) * nom_rate / denom_rate;
printf("Linear SNR: %f\n", SNR_lin); printf("Linear SNR: %f\n", SNR_lin);
decoded_errors[i]=test_ldpc(max_iterations, one_measurement_t res = test_ldpc(max_iterations,
nom_rate, nom_rate,
denom_rate, denom_rate,
SNR_lin, // noise standard deviation SNR_lin, // noise standard deviation
qbits, qbits,
block_length, // block length bytes block_length, // block length bytes
n_trials, n_trials,
n_segments, n_segments);
&errors, decoded_errors[i] = res.errors;
&errors_bit, dec_iter[i] = res.dec_iter;
&errors_bit_uncoded, dec_iter[i].snr = SNR;
&crc_misses, dec_iter[i].ber = (float)res.errors_bit / (float)n_trials / (float)block_length / (double)n_segments;
time_optim, dec_iter[i].bler = (float)decoded_errors[i] / (float)n_trials;
time_decoder, printf("SNR %f, BLER %f (%u/%d)\n", SNR, dec_iter[i].bler, decoded_errors[i], n_trials);
&dec_iter, printf("SNR %f, BER %f (%u/%d)\n", SNR, dec_iter[i].ber, decoded_errors[i], n_trials);
i); printf("SNR %f, Uncoded BER %f (%u/%d)\n",
SNR,
dec_iter.snr[i] = SNR; res.errors_bit_uncoded / (float)n_trials / (double)n_segments,
dec_iter.ber[i] = (float)errors_bit/(float)n_trials/(float)block_length/(double)n_segments; decoded_errors[i],
dec_iter.bler[i] = (float)decoded_errors[i]/(float)n_trials; n_trials);
printf("SNR %f, BLER %f (%u/%d)\n", SNR, dec_iter.bler[i], decoded_errors[i], n_trials); printf("SNR %f, Mean iterations: %f\n", SNR, dec_iter[i].n_iter_mean);
printf("SNR %f, BER %f (%u/%d)\n", SNR, dec_iter.ber[i], decoded_errors[i], n_trials); printf("SNR %f, Std iterations: %f\n", SNR, dec_iter[i].n_iter_std);
printf("SNR %f, Uncoded BER %f (%u/%d)\n",SNR, errors_bit_uncoded/(float)n_trials/(double)n_segments, decoded_errors[i], n_trials); printf("SNR %f, Max iterations: %d\n", SNR, dec_iter[i].n_iter_max);
printf("SNR %f, Mean iterations: %f\n",SNR, dec_iter.n_iter_mean[i]);
printf("SNR %f, Std iterations: %f\n",SNR, dec_iter.n_iter_std[i]);
printf("SNR %f, Max iterations: %d\n",SNR, dec_iter.n_iter_max[i]);
printf("\n"); printf("\n");
printf("Encoding time mean: %15.3f us\n",(double)time_optim->diff/time_optim->trials/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)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 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)time_optim->max/1000.0/get_cpu_freq_GHz()); printf("Encoding time max: %15.3f us\n",(double)res.time_optim.max/1000.0/get_cpu_freq_GHz());
printf("\n"); 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 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)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 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)time_decoder->max/1000.0/get_cpu_freq_GHz()); 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", fprintf(fd,
SNR, "%f %f %f %f %f %f %f %f %f %f %f %f %d \n",
(double)decoded_errors[i]/(double)n_trials , SNR,
(double)errors_bit/(double)n_trials/(double)block_length/(double)n_segments , (double)decoded_errors[i] / (double)n_trials,
errors_bit_uncoded/(double)n_trials/(double)n_segments , (double)res.errors_bit / (double)n_trials / (double)block_length / (double)n_segments,
(double)time_optim->diff/time_optim->trials/1000.0/get_cpu_freq_GHz(), res.errors_bit_uncoded / (double)n_trials / (double)n_segments,
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)res.time_optim.diff / res.time_optim.trials / 1000.0 / get_cpu_freq_GHz(),
(double)time_optim->max/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)
(double)time_decoder->diff/time_decoder->trials/1000.0/get_cpu_freq_GHz(), - pow((double)res.time_optim.diff / res.time_optim.trials / 1000.0 / get_cpu_freq_GHz(), 2)),
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)res.time_optim.max / 1000.0 / get_cpu_freq_GHz(),
(double)time_decoder->max/1000.0/get_cpu_freq_GHz(), (double)res.time_decoder.diff / res.time_decoder.trials / 1000.0 / get_cpu_freq_GHz(),
dec_iter.n_iter_mean[i], sqrt((double)res.time_decoder.diff_square / res.time_decoder.trials / pow(1000, 2) / pow(get_cpu_freq_GHz(), 2)
dec_iter.n_iter_std[i], - pow((double)res.time_decoder.diff / res.time_decoder.trials / 1000.0 / get_cpu_freq_GHz(), 2)),
dec_iter.n_iter_max[i] (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; i=i+1;
if (decoded_errors[i-1] == 0) break; if (decoded_errors[i - 1] == 0)
break;
} }
fclose(fd); fclose(fd);
LOG_M("ldpctestStats.m","SNR",&dec_iter.snr[0],i,1,7); LOG_M("ldpctestStats.m", "SNR", &dec_iter[0].snr, i, 1, 7);
LOG_MM("ldpctestStats.m","BLER",&dec_iter.bler[0],i,1,7); LOG_MM("ldpctestStats.m", "BLER", &dec_iter[0].bler, i, 1, 7);
LOG_MM("ldpctestStats.m","BER",&dec_iter.ber[0],i,1,7); LOG_MM("ldpctestStats.m", "BER", &dec_iter[0].ber, i, 1, 7);
LOG_MM("ldpctestStats.m","meanIter",&dec_iter.n_iter_mean[0],i,1,7); LOG_MM("ldpctestStats.m", "meanIter", &dec_iter[0].n_iter_mean, i, 1, 7);
loader_reset(); loader_reset();
logTerm(); logTerm();
@@ -133,14 +133,24 @@
#include "bnProc128/nrLDPC_bnProc_BG2_R23_128.h" #include "bnProc128/nrLDPC_bnProc_BG2_R23_128.h"
#endif #endif
//#define NR_LDPC_ENABLE_PARITY_CHECK
//#define NR_LDPC_PROFILER_DETAIL(a) a //#define NR_LDPC_PROFILER_DETAIL(a) a
#define NR_LDPC_PROFILER_DETAIL(a) #define NR_LDPC_PROFILER_DETAIL(a)
#include "openair1/PHY/CODING/nrLDPC_extern.h"
#ifdef NR_LDPC_DEBUG_MODE #ifdef NR_LDPC_DEBUG_MODE
#include "nrLDPC_tools/nrLDPC_debug.h" #include "nrLDPC_tools/nrLDPC_debug.h"
#endif #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, static inline uint32_t nrLDPC_decoder_core(int8_t* p_llr,
int8_t* p_out, int8_t* p_out,
uint32_t numLLR, 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_dec_params* p_decParams,
t_nrLDPC_time_stats* p_profiler, t_nrLDPC_time_stats* p_profiler,
decode_abort_t* ab); 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, int32_t LDPCshutdown()
int8_t* p_out, {
t_nrLDPC_time_stats* p_profiler, return 0;
decode_abort_t* ab) }
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; uint32_t numLLR;
t_nrLDPC_lut lut; t_nrLDPC_lut lut;
@@ -817,31 +839,30 @@ static inline uint32_t nrLDPC_decoder_core(int8_t* p_llr,
#endif #endif
// Parity Check // Parity Check
#ifdef NR_LDPC_ENABLE_PARITY_CHECK if (!p_decParams->check_crc) {
NR_LDPC_PROFILER_DETAIL(start_meas(&p_profiler->cnProcPc)); NR_LDPC_PROFILER_DETAIL(start_meas(&p_profiler->cnProcPc));
if (BG == 1) if (BG == 1)
pcRes = nrLDPC_cnProcPc_BG1(p_lut, cnProcBuf, cnProcBufRes, Z); pcRes = nrLDPC_cnProcPc_BG1(p_lut, cnProcBuf, cnProcBufRes, Z);
else else
pcRes = nrLDPC_cnProcPc_BG2(p_lut, cnProcBuf, cnProcBufRes, Z); pcRes = nrLDPC_cnProcPc_BG2(p_lut, cnProcBuf, cnProcBufRes, Z);
NR_LDPC_PROFILER_DETAIL(stop_meas(&p_profiler->cnProcPc)); NR_LDPC_PROFILER_DETAIL(stop_meas(&p_profiler->cnProcPc));
#else } else {
if (numIter > 2) { if (numIter > 2) {
int8_t llrOut[NR_LDPC_MAX_NUM_LLR] __attribute__((aligned(64))) = {0}; int8_t llrOut[NR_LDPC_MAX_NUM_LLR] __attribute__((aligned(64))) = {0};
int8_t* p_llrOut = outMode == nrLDPC_outMode_LLRINT8 ? p_out : llrOut; int8_t* p_llrOut = outMode == nrLDPC_outMode_LLRINT8 ? p_out : llrOut;
nrLDPC_llrRes2llrOut(p_lut, p_llrOut, llrRes, Z, BG); nrLDPC_llrRes2llrOut(p_lut, p_llrOut, llrRes, Z, BG);
if (outMode == nrLDPC_outMode_BIT) if (outMode == nrLDPC_outMode_BIT)
nrLDPC_llr2bitPacked(p_out, p_llrOut, numLLR); nrLDPC_llr2bitPacked(p_out, p_llrOut, numLLR);
else // if (outMode == nrLDPC_outMode_BITINT8) else // if (outMode == nrLDPC_outMode_BITINT8)
nrLDPC_llr2bit(p_out, p_llrOut, numLLR); nrLDPC_llr2bit(p_out, p_llrOut, numLLR);
if (check_crc((uint8_t*)p_out, p_decParams->block_length, p_decParams->crc_type)) { 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"); LOG_D(PHY, "Segment CRC OK, exiting LDPC decoder\n");
break; 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 llrOut[NR_LDPC_MAX_NUM_LLR] __attribute__((aligned(64))) = {0};
int8_t* p_llrOut = outMode == nrLDPC_outMode_LLRINT8 ? p_out : llrOut; int8_t* p_llrOut = outMode == nrLDPC_outMode_LLRINT8 ? p_out : llrOut;
// Assign results from processing buffer to output // 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); nrLDPC_llr2bit(p_out, p_llrOut, numLLR);
NR_LDPC_PROFILER_DETAIL(stop_meas(&p_profiler->llr2bit)); NR_LDPC_PROFILER_DETAIL(stop_meas(&p_profiler->llr2bit));
} }
#endif
return numIter; return numIter;
} }
@@ -47,8 +47,7 @@ typedef struct{
#include <unistd.h> #include <unistd.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <CL/opencl.h> #include <CL/opencl.h>
#include "PHY/CODING/nrLDPC_decoder/nrLDPC_types.h" #include "openair1/PHY/CODING/nrLDPC_extern.h"
#include "PHY/CODING/nrLDPC_decoder/nrLDPCdecoder_defs.h"
#include "assertions.h" #include "assertions.h"
#include "common/utils/LOG/log.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); 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); 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); 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 *h1;
h_element *h2; h_element *h2;
switch(lift_index){ switch(lift_index){
@@ -328,18 +327,25 @@ int ldpc_autoinit(void) { // called by the library loader
return 0; return 0;
} }
int32_t LDPCshutdown()
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); return 0;
// init_LLR_DMA(p_decParams, p_llr, p_out);
} }
int32_t nrLDPC_decod(t_nrLDPC_dec_params *p_decParams, int32_t LDPCinit()
int8_t *p_llr, {
int8_t *p_out, // init_LLR_DMA(p_decParams, p_llr, p_out);
t_nrLDPC_procBuf *p_procBuf, return 0;
t_nrLDPC_time_stats *time_decoder, }
decode_abort_t *ab)
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; uint16_t Zc = p_decParams->Z;
uint8_t BG = p_decParams->BG; 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; int memorySize_llr = col * Zc * sizeof(char) * MC;
// cudaCheck( cudaMemcpyToSymbol(dev_const_llr, p_llr, memorySize_llr_cuda) ); // cudaCheck( cudaMemcpyToSymbol(dev_const_llr, p_llr, memorySize_llr_cuda) );
// cudaCheck( cudaMemcpyToSymbol(dev_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, set_compact_BG(p_decParams->Z, p_decParams->BG);
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); 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, rt = clEnqueueWriteBuffer(ocl.runtime[0].queue[0], ocl.runtime[0].dev_llr, CL_TRUE, 0,
memorySize_llr, p_llr, 0, NULL, NULL); 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 // Define CUDA kernel dimension
// int blockSizeX = Zc; // int blockSizeX = Zc;
// dim3 dimGridKernel1(row, MC, 1); // dim of the thread blocks // dim3 dimGridKernel1(row, MC, 1); // dim of the thread blocks
File diff suppressed because it is too large Load Diff
@@ -85,24 +85,27 @@ typedef struct nrLDPC_dec_params {
uint8_t BG; /**< Base graph */ uint8_t BG; /**< Base graph */
uint16_t Z; /**< Lifting size */ uint16_t Z; /**< Lifting size */
uint8_t R; /**< Decoding rate: Format 15,13,... for code rates 1/5, 1/3,... */ 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 */ uint8_t numMaxIter; /**< Maximum number of iterations */
int block_length; int E;
e_nrLDPC_outMode outMode; /**< Output format */ e_nrLDPC_outMode outMode; /**< Output format */
int crc_type; int crc_type;
int (*check_crc)(uint8_t* decoded_bytes, uint32_t n, uint8_t crc_type);
uint8_t setCombIn;
} t_nrLDPC_dec_params; } t_nrLDPC_dec_params;
/**
Structure containing LDPC decoder parameters.
*/
typedef struct nrLDPCoffload_params { typedef struct nrLDPCoffload_params {
uint8_t BG; /**< Base graph */ uint8_t BG; /**< Base graph */
uint16_t Z; uint16_t Z;
uint16_t Kr; uint16_t Kr;
uint8_t rv; uint8_t rv;
uint32_t E; uint32_t E;
uint16_t n_cb; uint16_t n_cb;
uint16_t F; /**< Filler bits */ uint16_t F; /**< Filler bits */
uint8_t Qm; /**< Modulation */ uint8_t Qm; /**< Modulation */
uint8_t setCombIn;
} t_nrLDPCoffload_params; } t_nrLDPCoffload_params;
/** /**
@@ -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 * \brief LDPC cuda support BG1 all length
* \author NCTU OpinConnect Terng-Yin Hsu,WEI-YING,LIN * \author NCTU OpinConnect Terng-Yin Hsu,WEI-YING,LIN
* \email tyhsu@cs.nctu.edu.tw * \email tyhsu@cs.nctu.edu.tw
* \date 13-05-2020 * \date 13-05-2020
* \version * \version
* \note * \note
* \warning * \warning
*/ */
@@ -31,17 +31,17 @@
#include "bgs/BG2_I5" #include "bgs/BG2_I5"
#include "bgs/BG2_I6" #include "bgs/BG2_I6"
#include "bgs/BG2_I7" #include "bgs/BG2_I7"
#define MAX_ITERATION 2 #define MAX_ITERATION 2
#define MC 1 #define MC 1
typedef void decode_abort_t;
#define cudaCheck(ans) { cudaAssert((ans), __FILE__, __LINE__); } #define cudaCheck(ans) { cudaAssert((ans), __FILE__, __LINE__); }
inline void cudaAssert(cudaError_t code, const char *file, int line) inline void cudaAssert(cudaError_t code, const char *file, int line)
{ {
if (code != cudaSuccess){ if (code != cudaSuccess) {
fprintf(stderr,"GPUassert: %s %s %d\n", cudaGetErrorString(code), file, line); fprintf(stderr, "GPUassert: %s %s %d\n", cudaGetErrorString(code), file, line);
exit(code); exit(code);
} }
} }
typedef struct{ 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 // __device__ __constant__ h_element dev_h_compact2[68*30]; // used in kernel 2
// row and col element count // row and col element count
__device__ __constant__ char h_ele_row_bg1_count[46] = { __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,
19, 19, 19, 19, 3, 8, 9, 7, 10, 9, 5, 6, 5, 5, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 4, 5, 5, 4, 5, 4, 5, 5, 4};
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] = { __device__ __constant__ char h_ele_col_bg1_count[68] = {
30, 28, 7, 11, 9, 4, 8, 12, 8, 7, 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,
12, 10, 12, 11, 10, 7, 10, 10, 13, 7, 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};
8, 11, 12, 5, 6, 6, 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,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 4, 3, 4, 4, 3, 5, 3, 4, 3, 5, 3, 4, 4, 4, 4, 4, 3, 4, 4, 4, 4};
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, __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, 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() __global__ void warmup()
{ {
// warm up gpu for time measurement // warm up gpu for time measurement
} }
extern "C" extern "C"
void warmup_for_GPU(){ void warmup_for_GPU(){
warmup<<<20, 1024>>>();
warmup<<<20,1024 >>>();
} }
extern "C" extern "C"
void set_compact_BG(int Zc,short BG){ void set_compact_BG(int Zc,short BG){
int row, col;
int row,col; if (BG == 1) {
if(BG == 1){ row = 46;
row = 46; col = 68;
col = 68; } else {
} row = 42;
else{ col = 52;
row = 42; }
col = 52; int compact_row = 30;
} int compact_col = 19;
int compact_row = 30; if (BG == 2) {
int compact_col = 19; compact_row = 10, compact_col = 23;
if(BG==2){compact_row = 10, compact_col = 23;} }
int memorySize_h_compact1 = row * compact_col * sizeof(h_element); int memorySize_h_compact1 = row * compact_col * sizeof(h_element);
int memorySize_h_compact2 = compact_row * col * sizeof(h_element); int memorySize_h_compact2 = compact_row * col * sizeof(h_element);
int lift_index = 0; int lift_index = 0;
short lift_set[][9] = { short lift_set[][9] = {{2, 4, 8, 16, 32, 64, 128, 256},
{2,4,8,16,32,64,128,256}, {3, 6, 12, 24, 48, 96, 192, 384},
{3,6,12,24,48,96,192,384}, {5, 10, 20, 40, 80, 160, 320},
{5,10,20,40,80,160,320}, {7, 14, 28, 56, 112, 224},
{7,14,28,56,112,224}, {9, 18, 36, 72, 144, 288},
{9,18,36,72,144,288}, {11, 22, 44, 88, 176, 352},
{11,22,44,88,176,352}, {13, 26, 52, 104, 208},
{13,26,52,104,208}, {15, 30, 60, 120, 240},
{15,30,60,120,240}, {0}};
{0}
}; for (int i = 0; lift_set[i][0] != 0; i++) {
for (int j = 0; lift_set[i][j] != 0; j++) {
for(int i = 0; lift_set[i][0] != 0; i++){ if (Zc == lift_set[i][j]) {
for(int j = 0; lift_set[i][j] != 0; j++){ lift_index = i;
if(Zc == lift_set[i][j]){ break;
lift_index = i; }
break; }
} }
} printf("\nZc = %d BG = %d\n", Zc, BG);
} switch (lift_index) {
printf("\nZc = %d BG = %d\n",Zc,BG); case 0:
switch(lift_index){ cudaCheck(cudaMemcpyToSymbol(dev_h_compact1, host_h_compact1_I0, memorySize_h_compact1));
case 0: cudaCheck(cudaMemcpyToSymbol(dev_h_compact2, host_h_compact2_I0, memorySize_h_compact2));
cudaCheck( cudaMemcpyToSymbol(dev_h_compact1, host_h_compact1_I0, memorySize_h_compact1) ); break;
cudaCheck( cudaMemcpyToSymbol(dev_h_compact2, host_h_compact2_I0, memorySize_h_compact2) ); case 1:
break; cudaCheck(cudaMemcpyToSymbol(dev_h_compact1, host_h_compact1_I1, memorySize_h_compact1));
case 1: cudaCheck(cudaMemcpyToSymbol(dev_h_compact2, host_h_compact2_I1, memorySize_h_compact2));
cudaCheck( cudaMemcpyToSymbol(dev_h_compact1, host_h_compact1_I1, memorySize_h_compact1) ); break;
cudaCheck( cudaMemcpyToSymbol(dev_h_compact2, host_h_compact2_I1, memorySize_h_compact2) ); case 2:
break; cudaCheck(cudaMemcpyToSymbol(dev_h_compact1, host_h_compact1_I2, memorySize_h_compact1));
case 2: cudaCheck(cudaMemcpyToSymbol(dev_h_compact2, host_h_compact2_I2, memorySize_h_compact2));
cudaCheck( cudaMemcpyToSymbol(dev_h_compact1, host_h_compact1_I2, memorySize_h_compact1) ); break;
cudaCheck( cudaMemcpyToSymbol(dev_h_compact2, host_h_compact2_I2, memorySize_h_compact2) ); case 3:
break; cudaCheck(cudaMemcpyToSymbol(dev_h_compact1, host_h_compact1_I3, memorySize_h_compact1));
case 3: cudaCheck(cudaMemcpyToSymbol(dev_h_compact2, host_h_compact2_I3, memorySize_h_compact2));
cudaCheck( cudaMemcpyToSymbol(dev_h_compact1, host_h_compact1_I3, memorySize_h_compact1) ); break;
cudaCheck( cudaMemcpyToSymbol(dev_h_compact2, host_h_compact2_I3, memorySize_h_compact2) ); case 4:
break; cudaCheck(cudaMemcpyToSymbol(dev_h_compact1, host_h_compact1_I4, memorySize_h_compact1));
case 4: cudaCheck(cudaMemcpyToSymbol(dev_h_compact2, host_h_compact2_I4, memorySize_h_compact2));
cudaCheck( cudaMemcpyToSymbol(dev_h_compact1, host_h_compact1_I4, memorySize_h_compact1) ); break;
cudaCheck( cudaMemcpyToSymbol(dev_h_compact2, host_h_compact2_I4, memorySize_h_compact2) ); case 5:
break; cudaCheck(cudaMemcpyToSymbol(dev_h_compact1, host_h_compact1_I5, memorySize_h_compact1));
case 5: cudaCheck(cudaMemcpyToSymbol(dev_h_compact2, host_h_compact2_I5, memorySize_h_compact2));
cudaCheck( cudaMemcpyToSymbol(dev_h_compact1, host_h_compact1_I5, memorySize_h_compact1) ); break;
cudaCheck( cudaMemcpyToSymbol(dev_h_compact2, host_h_compact2_I5, memorySize_h_compact2) ); case 6:
break; cudaCheck(cudaMemcpyToSymbol(dev_h_compact1, host_h_compact1_I6, memorySize_h_compact1));
case 6: cudaCheck(cudaMemcpyToSymbol(dev_h_compact2, host_h_compact2_I6, memorySize_h_compact2));
cudaCheck( cudaMemcpyToSymbol(dev_h_compact1, host_h_compact1_I6, memorySize_h_compact1) ); break;
cudaCheck( cudaMemcpyToSymbol(dev_h_compact2, host_h_compact2_I6, memorySize_h_compact2) ); case 7:
break; cudaCheck(cudaMemcpyToSymbol(dev_h_compact1, host_h_compact1_I7, memorySize_h_compact1));
case 7: cudaCheck(cudaMemcpyToSymbol(dev_h_compact2, host_h_compact2_I7, memorySize_h_compact2));
cudaCheck( cudaMemcpyToSymbol(dev_h_compact1, host_h_compact1_I7, memorySize_h_compact1) ); break;
cudaCheck( cudaMemcpyToSymbol(dev_h_compact2, host_h_compact2_I7, memorySize_h_compact2) ); }
break;
} // return 0;
// return 0;
} }
// Kernel 1 // Kernel 1
__global__ void ldpc_cnp_kernel_1st_iter(/*char * dev_llr,*/ int BG, int row, int col, int Zc) __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); // if(blockIdx.x == 0 && threadIdx.x == 1) printf("cnp %d\n", threadIdx.x);
int iMCW = blockIdx.y; // codeword id int iMCW = blockIdx.y; // codeword id
int iBlkRow = blockIdx.x; // block row in h_base int iBlkRow = blockIdx.x; // block row in h_base
int iBlkCol; // block col in h_base int iBlkCol; // block col in h_base
int iSubRow = threadIdx.x; // row index in sub_block of h_base int iSubRow = threadIdx.x; // row index in sub_block of h_base
int iCol; // overall col index in h_base int iCol; // overall col index in h_base
int offsetR; int offsetR;
int shift_t; int shift_t;
// For 2-min algorithm. // For 2-min algorithm.
int Q_sign = 0; int Q_sign = 0;
int sq; int sq;
int Q, Q_abs; int Q, Q_abs;
int R_temp; int R_temp;
int sign = 1; int sign = 1;
int rmin1 = INT32_MAX; int rmin1 = INT32_MAX;
int rmin2 = INT32_MAX; int rmin2 = INT32_MAX;
char idx_min = 0; char idx_min = 0;
h_element h_element_t; h_element h_element_t;
int s = (BG==1)? h_ele_row_bg1_count[iBlkRow]:h_ele_row_bg2_count[iBlkRow]; 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 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); // if(blockIdx.x == 0 && threadIdx.x == 1) printf("s: %d, offset %d\n", s, offsetR);
// The 1st recursion // The 1st recursion
for(int i = 0; i < s; i++) // loop through all the ZxZ sub-blocks in a row 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_t = dev_h_compact1[i * row + iBlkRow]; // compact_col == row
iBlkCol = h_element_t.y; iBlkCol = h_element_t.y;
shift_t = h_element_t.value; shift_t = h_element_t.value;
shift_t = (iSubRow + shift_t) % Zc; shift_t = (iSubRow + shift_t) % Zc;
iCol = (iMCW * col*Zc) + iBlkCol * Zc + shift_t; // col*Zc = size of llr iCol = (iMCW * col * Zc) + iBlkCol * Zc + shift_t; // col*Zc = size of llr
Q = dev_llr[iCol]; Q = dev_llr[iCol];
Q_abs = (Q>0)? Q : -Q; Q_abs = (Q > 0) ? Q : -Q;
sq = Q < 0; sq = Q < 0;
// if(blockIdx.x == 0 && threadIdx.x == 1) printf("i %d, icol %d, Q: %d\n", i, iCol, Q); // if(blockIdx.x == 0 && threadIdx.x == 1) printf("i %d, icol %d, Q: %d\n", i, iCol, Q);
// quick version // quick version
sign = sign * (1 - sq * 2); sign = sign * (1 - sq * 2);
Q_sign |= sq << i; Q_sign |= sq << i;
if (Q_abs < rmin1){ if (Q_abs < rmin1) {
rmin2 = rmin1; rmin2 = rmin1;
rmin1 = Q_abs; rmin1 = Q_abs;
idx_min = i; idx_min = i;
} else if (Q_abs < rmin2){ } else if (Q_abs < rmin2) {
rmin2 = Q_abs; 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 // The 2nd recursion
for(int i = 0; i < s; i++){ for (int i = 0; i < s; i++) {
// v0: Best performance so far. 0.75f is the value of alpha. // v0: Best performance so far. 0.75f is the value of alpha.
sq = 1 - 2 * ((Q_sign >> i) & 0x01); sq = 1 - 2 * ((Q_sign >> i) & 0x01);
R_temp = 0.75f * sign * sq * (i != idx_min ? rmin1 : rmin2); R_temp = 0.75f * sign * sq * (i != idx_min ? rmin1 : rmin2);
// write results to global memory // write results to global memory
h_element_t = dev_h_compact1[i*row+iBlkRow]; h_element_t = dev_h_compact1[i * row + iBlkRow];
int addr_temp = offsetR + h_element_t.y * row * Zc; int addr_temp = offsetR + h_element_t.y * row * Zc;
dev_dt[addr_temp] = R_temp; 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("R_temp %d, temp_addr %d\n", R_temp, addr_temp);
} }
} }
// Kernel_1 // Kernel_1
__global__ void ldpc_cnp_kernel(/*char * dev_llr, char * dev_dt,*/ int BG, int row, int col, int Zc) __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"); // if(blockIdx.x == 0 && threadIdx.x == 1) printf("cnp\n");
int iMCW = blockIdx.y; int iMCW = blockIdx.y;
int iBlkRow = blockIdx.x; // block row in h_base int iBlkRow = blockIdx.x; // block row in h_base
int iBlkCol; // block col in h_base int iBlkCol; // block col in h_base
int iSubRow = threadIdx.x; // row index in sub_block of h_base int iSubRow = threadIdx.x; // row index in sub_block of h_base
int iCol; // overall col index in h_base int iCol; // overall col index in h_base
int offsetR; int offsetR;
int shift_t; int shift_t;
// For 2-min algorithm. // For 2-min algorithm.
int Q_sign = 0; int Q_sign = 0;
int sq; int sq;
int Q, Q_abs; int Q, Q_abs;
int R_temp; int R_temp;
int sign = 1; int sign = 1;
int rmin1 = INT32_MAX; int rmin1 = INT32_MAX;
int rmin2 = INT32_MAX; int rmin2 = INT32_MAX;
char idx_min = 0; char idx_min = 0;
h_element h_element_t; h_element h_element_t;
int s = (BG==1)? h_ele_row_bg1_count[iBlkRow]: h_ele_row_bg2_count[iBlkRow]; 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 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); // if(blockIdx.x == 0 && threadIdx.x == 1) printf("s: %d, offset %d\n", s, offsetR);
// The 1st recursion // The 1st recursion
for(int i = 0; i < s; i++) // loop through all the ZxZ sub-blocks in a row 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_t = dev_h_compact1[i * row + iBlkRow];
iBlkCol = h_element_t.y; iBlkCol = h_element_t.y;
shift_t = h_element_t.value; shift_t = h_element_t.value;
shift_t = (iSubRow + shift_t) % Zc; shift_t = (iSubRow + shift_t) % Zc;
iCol = iBlkCol * Zc + shift_t; iCol = iBlkCol * Zc + shift_t;
R_temp = dev_dt[offsetR + iBlkCol * row * Zc];
Q = dev_llr[iMCW * (col*Zc) + iCol] - R_temp; R_temp = dev_dt[offsetR + iBlkCol * row * Zc];
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 (Q_abs < rmin1){ Q = dev_llr[iMCW * (col * Zc) + iCol] - R_temp;
rmin2 = rmin1; Q_abs = (Q > 0) ? Q : -Q;
rmin1 = Q_abs; // if(blockIdx.x == 0 && threadIdx.x == 1) printf("i %d, icol %d, Q: %d\n", i, iCol, Q);
idx_min = i; sq = Q < 0;
} else if (Q_abs < rmin2){ sign = sign * (1 - sq * 2);
rmin2 = Q_abs; Q_sign |= sq << i;
}
}
// if(blockIdx.x == 0 && threadIdx.x == 1)printf("min1 %d, min2 %d, min1_idx %d\n", rmin1, rmin2, idx_min); if (Q_abs < rmin1) {
rmin2 = rmin1;
// The 2nd recursion rmin1 = Q_abs;
for(int i = 0; i < s; i ++){ idx_min = i;
sq = 1 - 2 * ((Q_sign >> i) & 0x01); } else if (Q_abs < rmin2) {
R_temp = 0.75f * sign * sq * (i != idx_min ? rmin1 : rmin2); rmin2 = Q_abs;
}
}
// write results to global memory // if(blockIdx.x == 0 && threadIdx.x == 1)printf("min1 %d, min2 %d, min1_idx %d\n", rmin1, rmin2, idx_min);
h_element_t = dev_h_compact1[i*row+iBlkRow];
int addr_temp = h_element_t.y * row * Zc + offsetR; // The 2nd recursion
dev_dt[addr_temp] = R_temp; for (int i = 0; i < s; i++) {
// if(blockIdx.x == 0 && threadIdx.x == 1)printf("R_temp %d, temp_addr %d\n", R_temp, addr_temp); 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 // Kernel 2: VNP processing
__global__ void __global__ void
ldpc_vnp_kernel_normal(/*char * dev_llr, char * dev_dt, char * dev_const_llr,*/ int BG, int row, int col, int Zc) 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 iMCW = blockIdx.y;
int iBlkCol = blockIdx.x; int iBlkCol = blockIdx.x;
int iBlkRow; int iBlkRow;
int iSubCol = threadIdx.x; int iSubCol = threadIdx.x;
int iRow; int iRow;
int iCol; int iCol;
int shift_t, sf; int shift_t, sf;
int APP; int APP;
h_element h_element_t; h_element h_element_t;
// update all the llr values // update all the llr values
iCol = iBlkCol * Zc + iSubCol; iCol = iBlkCol * Zc + iSubCol;
APP = dev_const_llr[iMCW *col*Zc + iCol]; APP = dev_const_llr[iMCW * col * Zc + iCol];
int offsetDt = iMCW *row*col*Zc + iBlkCol * row * Zc; 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]; 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];
shift_t = h_element_t.value%Zc; for (int i = 0; i < s; i++) {
iBlkRow = h_element_t.x; h_element_t = dev_h_compact2[i * col + iBlkCol];
sf = iSubCol - shift_t; shift_t = h_element_t.value % Zc;
sf = (sf + Zc) % Zc; iBlkRow = h_element_t.x;
iRow = iBlkRow * Zc + sf; sf = iSubCol - shift_t;
APP = APP + dev_dt[offsetDt + iRow]; sf = (sf + Zc) % Zc;
}
if(APP > SCHAR_MAX) APP = SCHAR_MAX; iRow = iBlkRow * Zc + sf;
if(APP < SCHAR_MIN) APP = SCHAR_MIN; APP = APP + dev_dt[offsetDt + iRow];
// write back to device global memory }
dev_llr[iMCW *col*Zc + iCol] = APP; 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) __global__ void pack_decoded_bit(/*char *dev, unsigned char *host,*/ int col, int Zc)
{ {
__shared__ unsigned char tmp[128]; __shared__ unsigned char tmp[128];
int iMCW = blockIdx.y; int iMCW = blockIdx.y;
int tid = iMCW * col*Zc + blockIdx.x*128 + threadIdx.x; int tid = iMCW * col * Zc + blockIdx.x * 128 + threadIdx.x;
int btid = threadIdx.x; int btid = threadIdx.x;
tmp[btid] = 0; tmp[btid] = 0;
if(dev_llr[tid] < 0){ if (dev_llr[tid] < 0) {
tmp[btid] = 1 << (7-(btid&7)); tmp[btid] = 1 << (7 - (btid & 7));
} }
__syncthreads(); __syncthreads();
if(threadIdx.x < 16){ if (threadIdx.x < 16) {
dev_tmp[iMCW * col*Zc + blockIdx.x*16+threadIdx.x] = 0; dev_tmp[iMCW * col * Zc + blockIdx.x * 16 + threadIdx.x] = 0;
for(int i = 0; i < 8; i++){ for (int i = 0; i < 8; i++) {
dev_tmp[iMCW * col*Zc + blockIdx.x*16+threadIdx.x] += tmp[threadIdx.x*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) void read_BG(int BG, int *h, int row, int col)
{ {
int compact_row = 30, compact_col = 19; int compact_row = 30, compact_col = 19;
if(BG==2){compact_row = 10, compact_col = 23;} if (BG == 2) {
compact_row = 10, compact_col = 23;
h_element h_element_temp; }
// init the compact matrix h_element h_element_temp;
for(int i = 0; i < compact_col; i++){
for(int j = 0; j < row; j++){ // init the compact matrix
h_element_temp.x = 0; for (int i = 0; i < compact_col; i++) {
h_element_temp.y = 0; for (int j = 0; j < row; j++) {
h_element_temp.value = -1; h_element_temp.x = 0;
h_compact1[i*row+j] = h_element_temp; // h[i][0-11], the same column 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++){ // scan the h matrix, and gengerate compact mode of h
int k = 0; for (int i = 0; i < row; i++) {
for(int j = 0; j < col; j++){ int k = 0;
if(h[i*col+j] != -1){ for (int j = 0; j < col; j++) {
h_element_temp.x = i; if (h[i * col + j] != -1) {
h_element_temp.y = j; h_element_temp.x = i;
h_element_temp.value = h[i*col+j]; h_element_temp.y = j;
h_compact1[k*row+i] = h_element_temp; h_element_temp.value = h[i * col + j];
k++; h_compact1[k * row + i] = h_element_temp;
} k++;
} }
} }
}
// h_compact2
// init the compact matrix // h_compact2
for(int i = 0; i < compact_row; i++){ // init the compact matrix
for(int j = 0; j < col; j++){ for (int i = 0; i < compact_row; i++) {
h_element_temp.x = 0; for (int j = 0; j < col; j++) {
h_element_temp.y = 0; h_element_temp.x = 0;
h_element_temp.value = -1; h_element_temp.y = 0;
h_compact2[i*col+j] = h_element_temp; 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++){ for(int i = 0; i < compact_row; i++){
int k=0; for(int j = 0; j < col; j++){
for(int i = 0; i < row; i++){ printf("%3d,", h_compact2[i*col+j].value);
if(h[i*col+j] != -1){ }
// although h is transposed, the (x,y) is still (iBlkRow, iBlkCol) printf("\n");
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");
}
*/
} }
extern "C" extern "C"
void init_LLR_DMA(t_nrLDPC_dec_params* p_decParams, int8_t* p_llr, int8_t* p_out){ void init_LLR_DMA(t_nrLDPC_dec_params* p_decParams, int8_t* p_llr, int8_t* p_out){
uint16_t Zc = p_decParams->Z;
uint16_t Zc = p_decParams->Z; uint8_t BG = p_decParams->BG;
uint8_t BG = p_decParams->BG; uint8_t col;
int block_length = p_decParams->block_length; if (BG == 1) {
uint8_t row,col; col = 68;
if(BG == 1){ } else {
row = 46; col = 52;
col = 68; }
} int memorySize_llr_cuda = col * Zc * sizeof(char) * MC;
else{ cudaCheck(cudaMemcpyToSymbol(dev_const_llr, p_llr, memorySize_llr_cuda));
row = 42; cudaCheck(cudaMemcpyToSymbol(dev_llr, p_llr, memorySize_llr_cuda));
col = 52; cudaDeviceSynchronize();
}
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();
} }
using namespace std ; using namespace std ;
/* from here: entry points in decoder shared lib */ /* from here: entry points in decoder shared lib */
extern "C" extern "C"
int ldpc_autoinit(void) { // called by the library loader int ldpc_autoinit(void) { // called by the library loader
/*int devices = 0; /*int devices = 0;
cudaError_t err = cudaGetDeviceCount(&devices); cudaError_t err = cudaGetDeviceCount(&devices);
AssertFatal(devices>0,"\nNo cuda GPU found\n\n"); AssertFatal(devices>0,"\nNo cuda GPU found\n\n");
const int kb = 1024; const int kb = 1024;
const int mb = kb * kb; const int mb = kb * kb;
wcout << "NBody.GPU" << endl << "=========" << endl << endl; 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; wcout << "CUDA Devices: " << endl << endl;
for(int i = 0; i < devices; ++i) for(int i = 0; i < devices; ++i)
{ {
cudaDeviceProp props; cudaDeviceProp props;
cudaGetDeviceProperties(&props, i); cudaGetDeviceProperties(&props, i);
wcout << i << ": " << props.name << ": " << props.major << "." << props.minor << endl; wcout << i << ": " << props.name << ": " << props.major << "." << props.minor << endl;
wcout << " Global memory: " << props.totalGlobalMem / mb << "mb" << endl; wcout << " Global memory: " << props.totalGlobalMem / mb << "mb" << endl;
wcout << " Shared memory: " << props.sharedMemPerBlock / kb << "kb" << endl; wcout << " Shared memory: " << props.sharedMemPerBlock / kb << "kb" << endl;
wcout << " Constant memory: " << props.totalConstMem / kb << "kb" << endl; wcout << " Constant memory: " << props.totalConstMem / kb << "kb" << endl;
wcout << " Block registers: " << props.regsPerBlock << endl << endl; wcout << " Block registers: " << props.regsPerBlock << endl << endl;
wcout << " Warp size: " << props.warpSize << endl; wcout << " Warp size: " << props.warpSize << endl;
wcout << " Threads per block: " << props.maxThreadsPerBlock << endl; wcout << " Threads per block: " << props.maxThreadsPerBlock << endl;
wcout << " Max block dimensions: [ " << props.maxThreadsDim[0] << ", " << props.maxThreadsDim[1] << ", " << props.maxThreadsDim[2] << " ]" << endl; wcout << " Max block dimensions: [ " << props.maxThreadsDim[0] << ", " << props.maxThreadsDim[1] << ", " <<
wcout << " Max grid dimensions: [ " << props.maxGridSize[0] << ", " << props.maxGridSize[1] << ", " << props.maxGridSize[2] << " ]" << endl; props.maxThreadsDim[2] << " ]" << endl; wcout << " Max grid dimensions: [ " << props.maxGridSize[0] << ", " <<
wcout << endl; props.maxGridSize[1] << ", " << props.maxGridSize[2] << " ]" << endl; wcout << endl;
} }
*/ */
warmup_for_GPU(); warmup_for_GPU();
return 0; return 0;
} }
extern "C" extern "C" int32_t LDPCinit()
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)
{ {
uint16_t Zc = p_decParams->Z; return 0;
uint8_t BG = p_decParams->BG; }
uint8_t numMaxIter = p_decParams->numMaxIter;
int block_length = p_decParams->block_length; extern "C" void LDPCshutdown()
e_nrLDPC_outMode outMode = p_decParams->outMode; {
cudaError_t cudaStatus; }
uint8_t row,col;
if(BG == 1){ extern "C" int32_t LDPCdecoder(t_nrLDPC_dec_params *p_decParams,
row = 46; uint8_t harq_pid,
col = 68; uint8_t ulsch_id,
} uint8_t C,
else{ int8_t *p_llr,
row = 42; int8_t *p_out,
col = 52; t_nrLDPC_time_stats *,
} decode_abort_t *ab)
{
// alloc memory set_compact_BG(p_decParams->Z, p_decParams->BG);
unsigned char *hard_decision = (unsigned char*)p_out; init_LLR_DMA(p_decParams, p_llr, p_out);
// gpu uint16_t Zc = p_decParams->Z;
int memorySize_llr_cuda = col * Zc * sizeof(char) * MC; uint8_t BG = p_decParams->BG;
cudaCheck( cudaMemcpyToSymbol(dev_const_llr, p_llr, memorySize_llr_cuda) ); int block_length = p_decParams->E;
cudaCheck( cudaMemcpyToSymbol(dev_llr, p_llr, memorySize_llr_cuda) ); uint8_t row, col;
if (BG == 1) {
// Define CUDA kernel dimension row = 46;
int blockSizeX = Zc; col = 68;
dim3 dimGridKernel1(row, MC, 1); // dim of the thread blocks } else {
dim3 dimBlockKernel1(blockSizeX, 1, 1); row = 42;
col = 52;
dim3 dimGridKernel2(col, MC, 1); }
dim3 dimBlockKernel2(blockSizeX, 1, 1);
cudaDeviceSynchronize(); // alloc memory
unsigned char* hard_decision = (unsigned char*)p_out;
// lauch kernel // gpu
int memorySize_llr_cuda = col * Zc * sizeof(char) * MC;
for(int ii = 0; ii < MAX_ITERATION; ii++){ cudaCheck(cudaMemcpyToSymbol(dev_const_llr, p_llr, memorySize_llr_cuda));
// first kernel cudaCheck(cudaMemcpyToSymbol(dev_llr, p_llr, memorySize_llr_cuda));
if(ii == 0){
ldpc_cnp_kernel_1st_iter // Define CUDA kernel dimension
<<<dimGridKernel1, dimBlockKernel1>>> int blockSizeX = Zc;
(/*dev_llr,*/ BG, row, col, Zc); dim3 dimGridKernel1(row, MC, 1); // dim of the thread blocks
}else{ dim3 dimBlockKernel1(blockSizeX, 1, 1);
ldpc_cnp_kernel
<<<dimGridKernel1, dimBlockKernel1>>> dim3 dimGridKernel2(col, MC, 1);
(/*dev_llr,*/ BG, row, col, Zc); dim3 dimBlockKernel2(blockSizeX, 1, 1);
} cudaDeviceSynchronize();
// second kernel
ldpc_vnp_kernel_normal // lauch kernel
<<<dimGridKernel2, dimBlockKernel2>>>
// (dev_llr, dev_const_llr,BG, row, col, Zc); for (int ii = 0; ii < MAX_ITERATION; ii++) {
(BG, row, col, Zc); // first kernel
} if (ii == 0) {
ldpc_cnp_kernel_1st_iter<<<dimGridKernel1, dimBlockKernel1>>>(/*dev_llr,*/ BG, row, col, Zc);
int pack = (block_length/128)+1; } else {
dim3 pack_block(pack, MC, 1); ldpc_cnp_kernel<<<dimGridKernel1, dimBlockKernel1>>>(/*dev_llr,*/ BG, row, col, Zc);
pack_decoded_bit<<<pack_block,128>>>(/*dev_llr,*/ /*dev_tmp,*/ col, Zc); }
// second kernel
cudaCheck( cudaMemcpyFromSymbol((void*)hard_decision, (const void*)dev_tmp, (block_length/8)*sizeof(unsigned char)) ); ldpc_vnp_kernel_normal<<<dimGridKernel2, dimBlockKernel2>>>
cudaDeviceSynchronize(); // (dev_llr, dev_const_llr,BG, row, col, Zc);
(BG, row, col, Zc);
}
return MAX_ITERATION;
int pack = (block_length / 128) + 1;
dim3 pack_block(pack, MC, 1);
pack_decoded_bit<<<pack_block, 128>>>(/*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;
} }
+19 -10
View File
@@ -47,7 +47,7 @@ typedef struct {
time_stats_t *toutput; time_stats_t *toutput;
int Kr; int Kr;
uint32_t Kb; uint32_t Kb;
uint32_t *Zc; uint32_t Zc;
void *harq; void *harq;
/// Encoder BG /// Encoder BG
uint8_t BG; uint8_t BG;
@@ -57,13 +57,16 @@ typedef struct {
uint32_t K; uint32_t K;
/// Number of "Filler" bits /// Number of "Filler" bits
uint32_t F; uint32_t F;
/// LDPC-code outputs /// Modulation order
uint8_t *d[MAX_NUM_NR_DLSCH_SEGMENTS_PER_LAYER*NR_MAX_NB_LAYERS]; uint8_t Qm;
uint32_t E;
unsigned int G;
// Redundancy version index
uint8_t rv;
} encoder_implemparams_t; } 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 int32_t(LDPC_initfunc_t)(void);
typedef int(*nrLDPC_encoderfunc_t)(unsigned char **,unsigned char **,int,int,short, short, encoder_implemparams_t *); typedef int32_t(LDPC_shutdownfunc_t)(void);
//============================================================================================================================
// decoder interface // decoder interface
/** /**
\brief LDPC decoder API type definition \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 \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(LDPC_decoderfunc_t)(t_nrLDPC_dec_params *p_decParams,
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); uint8_t harq_pid,
typedef int32_t(*nrLDPC_dectopfunc_t)(void); 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 #endif
@@ -38,44 +38,29 @@
#include "defs.h" #include "defs.h"
#include "assertions.h" #include "assertions.h"
#include "openair1/PHY/CODING/nrLDPC_defs.h" #include "openair1/PHY/CODING/nrLDPC_defs.h"
#include "openair1/PHY/CODING/nrLDPC_extern.h"
#include "ldpc_generate_coefficient.c" #include "ldpc_generate_coefficient.c"
int LDPCencoder(unsigned char **inputArray, unsigned char **outputArray, encoder_implemparams_t *impp)
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)
{ {
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 c[22*384]; //padded input, unpacked, max size
uint8_t d[68*384]; //coded output, 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
int i,i1,i2,i3,i4,i5,temp_prime,var; 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 nind=0;
int indlist[1000]; int indlist[1000];
int indlist2[1000]; int indlist2[1000];
//determine number of bits in codeword const short *Gen_shift_values = choose_generator_matrix(BG, Zc);
//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);
if (Gen_shift_values==NULL) { if (Gen_shift_values==NULL) {
printf("ldpc_encoder_orig: could not find generator matrix\n"); printf("ldpc_encoder_orig: could not find generator matrix\n");
return(-1); 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); //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 // load base graph of generator matrix
if (BG==1) const short nrows = BG == 1 ? 46 : 42;
{ const short ncols = BG == 1 ? 22 : 10;
no_shift_values=(short *) no_shift_values_BG1; const short rate = BG == 1 ? 3 : 5;
pointer_shift_values=(short *) pointer_shift_values_BG1; 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;
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);
}
no_punctured_columns=(int)((nrows-2)*Zc+block_length-block_length*rate)/Zc; 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); removed_bit=(nrows-no_punctured_columns-2) * Zc+block_length-(block_length*rate);
//printf("%d\n",no_punctured_columns); //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<block_length; i++) for (i=0; i<block_length; i++)
{ {
//c[i] = test_input[i/8]<<(i%8); // c[i] = input[i/8]<<(i%8);
//c[i]=c[i]>>7&1; // c[i]=c[i]>>7&1;
c[i]=(test_input[i/8]&(128>>(i&7)))>>(7-(i&7)); c[i] = (input[i / 8] & (128 >> (i & 7))) >> (7 - (i & 7));
} }
// parity check part // 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," c2=&csimd[i2];\n");
fprintf(fd2," d2=&dsimd[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(fd,"\n//row: %d\n",i1);
fprintf(fd2,"\n//row: %d\n",i1); fprintf(fd2,"\n//row: %d\n",i1);
fprintf(fd," d2[%d]=",(Zc*i1)>>shift); 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]); fprintf(fd2,"c2[%d]",indlist2[i4]);
for (i4=0;i4<nind-1;i4++) { fprintf(fd,")"); fprintf(fd2,")"); } for (i4=0;i4<nind-1;i4++) { fprintf(fd,")"); fprintf(fd2,")"); }
fprintf(fd,";\n"); fprintf(fd,";\n");
fprintf(fd2,";\n"); fprintf(fd2, ";\n");
} }
fprintf(fd," }\n}\n"); fprintf(fd," }\n}\n");
fprintf(fd2," }\n}\n"); fprintf(fd2," }\n}\n");
@@ -243,40 +219,33 @@ int ldpc_encoder_orig(uint8_t *test_input,uint8_t *channel_input,int Zc,int Kb,s
//rotate matrix here //rotate matrix here
for (i5=0; i5 < Kb; i5++) for (i5=0; i5 < Kb; i5++)
{ {
temp = c[i5*Zc]; const int temp = c[i5 * Zc];
memmove(&c[i5*Zc], &c[i5*Zc+1], (Zc-1)*sizeof(uint8_t)); memmove(&c[i5 * Zc], &c[i5 * Zc + 1], Zc - 1);
c[i5*Zc+Zc-1] = temp; c[i5 * Zc + Zc - 1] = temp;
} }
// calculate each row in base graph // calculate each row in base graph
for (i1=0; i1 < nrows-no_punctured_columns; i1++) for (i1=0; i1 < nrows-no_punctured_columns; i1++)
{ {
channel_temp=0; unsigned char channel_temp = 0;
for (i3=0; i3 < Kb; i3++) for (i3 = 0; i3 < Kb; i3++) {
{ temp_prime = i1 * ncols + i3;
temp_prime=i1 * ncols + i3;
for (i4=0; i4 < no_shift_values[temp_prime]; i4++) for (i4 = 0; i4 < no_shift_values[temp_prime]; i4++) {
{ channel_temp = channel_temp ^ c[i3 * Zc + Gen_shift_values[pointer_shift_values[temp_prime] + i4]];
channel_temp = channel_temp ^ c[ i3*Zc + Gen_shift_values[ pointer_shift_values[temp_prime]+i4 ] ];
} }
} }
d[i2+i1*Zc]=channel_temp; d[i2+i1*Zc]=channel_temp;
//channel_input[t+i1*Zc]=channel_temp; // output[t+i1*Zc]=channel_temp;
} }
} }
} }
// information part and puncture columns // information part and puncture columns
memcpy(&channel_input[0], &c[2*Zc], (block_length-2*Zc)*sizeof(uint8_t)); memcpy(&output[0], &c[2 * Zc], block_length - 2 * Zc);
memcpy(&channel_input[block_length-2*Zc], &d[0], ((nrows-no_punctured_columns) * Zc-removed_bit)*sizeof(uint8_t)); memcpy(&output[block_length - 2 * Zc], &d[0], (nrows - no_punctured_columns) * Zc - removed_bit);
//memcpy(channel_input,c,Kb*Zc*sizeof(uint8_t)); // memcpy(output,c,Kb*Zc*sizeof(unsigned char));
return 0; return block_length - 2 * Zc + (nrows - no_punctured_columns) * Zc - removed_bit;
}
int nrLDPC_encod(uint8_t **test_input,uint8_t **channel_input,int Zc,int Kb,short block_length, short BG, encoder_implemparams_t *impp) {
return ldpc_encoder_orig(test_input[0],channel_input[0],Zc,Kb,block_length,BG,impp->gen_code);
} }
@@ -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 <stdlib.h>
#include <math.h>
#include <stdio.h>
#include <string.h>
#include <types.h>
#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<block_length; i++) {
c[i] = (test_input[i/8]&(128>>(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<simd_size;i1++) {
memcpy(&c_extension[(2*ncols*Zc*i1)], &c_extension[i1], (2*ncols*Zc*sizeof(unsigned char))-i1);
// memset(&c_extension[(2*ncols*Zc*i1)],0,i1);
/*
printf("shift %d: ",i1);
for (int j=0;j<64;j++) printf("%d ",c_extension[(2*ncols*Zc*i1)+j]);
printf("\n");
*/
}
if(tprep != NULL) stop_meas(tprep);
//parity check part
if(tparity != NULL) start_meas(tparity);
encode_parity_check_part_optim(c_extension, d, BG, Zc, Kb);
if(tparity != NULL) stop_meas(tparity);
}
else {
if (encode_parity_check_part_orig(c, d, BG, Zc, Kb, block_length)!=0) {
printf("Problem with encoder\n");
return(-1);
}
}
if(toutput != NULL) start_meas(toutput);
// information part and puncture columns
memcpy(&channel_input[0], &c[2*Zc], (block_length-2*Zc)*sizeof(unsigned char));
memcpy(&channel_input[block_length-2*Zc], &d[0], ((nrows-no_punctured_columns) * Zc-removed_bit)*sizeof(unsigned char));
if(toutput != NULL) stop_meas(toutput);
return 0;
}
int ldpc_encoder_optim_8seg(unsigned char **test_input,unsigned char **channel_input,int Zc,int Kb,short block_length,short BG,int n_segments,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;
char temp;
int simd_size;
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);
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<block_length; i++) {
for (j=0; j<n_segments; j++) {
temp = (test_input[j][i/8]&(128>>(i&7)))>>(7-(i&7));
//printf("c(%d,%d)=%d\n",j,i,temp);
c[i] |= (temp << j);
}
}
#else
for (i=0; i<block_length>>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<n_segments; j++) {
c256 = simde_mm256_or_si256(simde_mm256_and_si256(simde_mm256_cmpeq_epi8(simde_mm256_andnot_si256(simde_mm256_shuffle_epi8(simde_mm256_set1_epi32(((uint32_t*)test_input[j])[i]), shufmask),andmask),zero256),masks[j]),c256);
}
((simde__m256i *)c)[i] = c256;
}
for (i=(block_length>>5)<<5;i<block_length;i++) {
for (j=0; j<n_segments; j++) {
temp = (test_input[j][i/8]&(128>>(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<simd_size;i1++) {
memcpy(&c_extension[(2*ncols*Zc*i1)], &c_extension[i1], (2*ncols*Zc*sizeof(unsigned char))-i1);
// memset(&c_extension[(2*ncols*Zc*i1)],0,i1);
/*
printf("shift %d: ",i1);
for (int j=0;j<64;j++) printf("%d ",c_extension[(2*ncols*Zc*i1)+j]);
printf("\n");
*/
}
if(tprep != NULL) stop_meas(tprep);
//parity check part
if(tparity != NULL) start_meas(tparity);
encode_parity_check_part_optim(c_extension, d, BG, Zc, Kb);
if(tparity != NULL) stop_meas(tparity);
}
else {
if (encode_parity_check_part_orig(c, d, BG, Zc, Kb, block_length)!=0) {
printf("Problem with encoder\n");
return(-1);
}
}
if(toutput != NULL) start_meas(toutput);
// information part and puncture columns
/*
memcpy(&channel_input[0], &c[2*Zc], (block_length-2*Zc)*sizeof(unsigned char));
memcpy(&channel_input[block_length-2*Zc], &d[0], ((nrows-no_punctured_columns) * Zc-removed_bit)*sizeof(unsigned char));
*/
if ((((2*Zc)&31) == 0) && (((block_length-(2*Zc))&31) == 0)) {
//AssertFatal(((2*Zc)&31) == 0,"2*Zc needs to be a multiple of 32 for now\n");
//AssertFatal(((block_length-(2*Zc))&31) == 0,"block_length-(2*Zc) needs to be a multiple of 32 for now\n");
uint32_t l1 = (block_length-(2*Zc))>>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;i<l1;i++)
for (j = 0; j < n_segments; j++)
((simde__m256i *)channel_input[j])[i] = simde_mm256_and_si256(simde_mm256_srai_epi16(c256p[i], j), masks[0]);
// if ((((nrows-no_punctured_columns) * Zc-removed_bit)&31)>0) l2++;
for (i1=0;i1<l2;i1++,i++)
for (j = 0; j < n_segments; j++)
((simde__m256i *)channel_input[j])[i] = simde_mm256_and_si256(simde_mm256_srai_epi16(d256p[i1], j), masks[0]);
}
else {
#ifdef DEBUG_LDPC
LOG_W(PHY,"using non-optimized version\n");
#endif
// do non-SIMD version
for (i=0;i<(block_length-2*Zc);i++)
for (j=0; j<n_segments; j++)
channel_input[j][i] = (c[2*Zc+i]>>j)&1;
for (i=0;i<((nrows-no_punctured_columns) * Zc-removed_bit);i++)
for (j=0; j<n_segments; j++)
channel_input[j][block_length-2*Zc+i] = (d[i]>>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<block_length; i++) {
//for (j=0; j<n_segments; j++) {
for (j=macro_segment; j < macro_segment_end; j++) {
temp = (test_input[j][i/8]&(1<<(i&7)))>>(i&7);
//printf("c(%d,%d)=%d\n",j,i,temp);
c[i] |= (temp << (j-macro_segment));
}
}
#else
for (i=0; i<block_length>>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<n_segments; j++) {
for (j=macro_segment+1; j < macro_segment_end; j++) {
c256 = simde_mm256_or_si256(simde_mm256_and_si256(simde_mm256_cmpeq_epi8(simde_mm256_andnot_si256(simde_mm256_shuffle_epi8(simde_mm256_set1_epi32(((uint32_t*)test_input[j])[i]), shufmask),andmask),zero256),masks[j-macro_segment]),c256);
}
((simde__m256i *)c)[i] = c256;
}
for (i=(block_length>>5)<<5;i<block_length;i++) {
//for (j=0; j<n_segments; j++) {
for (j=macro_segment; j < macro_segment_end; j++) {
temp = (test_input[j][i/8]&(128>>(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<simd_size;i1++) {
memcpy(&c_extension[(2*ncols*Zc*i1)], &c_extension[i1], (2*ncols*Zc*sizeof(unsigned char))-i1);
// memset(&c_extension[(2*ncols*Zc*i1)],0,i1);
/*
printf("shift %d: ",i1);
for (int j=0;j<64;j++) printf("%d ",c_extension[(2*ncols*Zc*i1)+j]);
printf("\n");
*/
}
if(tprep != NULL) stop_meas(tprep);
//parity check part
if(tparity != NULL) start_meas(tparity);
encode_parity_check_part_optim(c_extension, d, BG, Zc, Kb);
if(tparity != NULL) stop_meas(tparity);
}
else {
if (encode_parity_check_part_orig(c, d, BG, Zc, Kb, block_length)!=0) {
printf("Problem with encoder\n");
return(-1);
}
}
if(toutput != NULL) start_meas(toutput);
// information part and puncture columns
/*
memcpy(&channel_input[0], &c[2*Zc], (block_length-2*Zc)*sizeof(unsigned char));
memcpy(&channel_input[block_length-2*Zc], &d[0], ((nrows-no_punctured_columns) * Zc-removed_bit)*sizeof(unsigned char));
*/
if ((((2*Zc)&31) == 0) && (((block_length-(2*Zc))&31) == 0)) {
//AssertFatal(((2*Zc)&31) == 0,"2*Zc needs to be a multiple of 32 for now\n");
//AssertFatal(((block_length-(2*Zc))&31) == 0,"block_length-(2*Zc) needs to be a multiple of 32 for now\n");
uint32_t l1 = (block_length-(2*Zc))>>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;i<l1;i++)
// for (j=0;j<n_segments;j++) ((simde__m256i *)channel_input[j])[i] =
// simde_mm256_and_si256(simde_mm256_srai_epi16(c256p[i],j),masks[0]);
for (j = macro_segment; j < macro_segment_end; j++)
((simde__m256i *)channel_input[j])[i] =
simde_mm256_and_si256(simde_mm256_srai_epi16(c256p[i], j - macro_segment), masks[0]);
// if ((((nrows-no_punctured_columns) * Zc-removed_bit)&31)>0) l2++;
for (i1=0;i1<l2;i1++,i++)
// for (j=0;j<n_segments;j++) ((simde__m256i *)channel_input[j])[i] =
// simde_mm256_and_si256(simde_mm256_srai_epi16(d256p[i1],j),masks[0]);
for (j = macro_segment; j < macro_segment_end; j++)
((simde__m256i *)channel_input[j])[i] =
simde_mm256_and_si256(simde_mm256_srai_epi16(d256p[i1], j - macro_segment), masks[0]);
}
else {
#ifdef DEBUG_LDPC
LOG_W(PHY,"using non-optimized version\n");
#endif
// do non-SIMD version
for (i=0;i<(block_length-2*Zc);i++)
//for (j=0; j<n_segments; j++)
for (j=macro_segment; j < macro_segment_end; j++)
channel_input[j][i] = (c[2*Zc+i]>>(j-macro_segment))&1;
for (i=0;i<((nrows-no_punctured_columns) * Zc-removed_bit);i++)
//for (j=0; j<n_segments; j++)
for (j=macro_segment; j < macro_segment_end; j++)
channel_input[j][block_length-2*Zc+i] = (d[i]>>(j-macro_segment))&1;
}
if(toutput != NULL) stop_meas(toutput);
return 0;
}
@@ -37,15 +37,17 @@
#include "common/utils/LOG/log.h" #include "common/utils/LOG/log.h"
#include "time_meas.h" #include "time_meas.h"
#include "openair1/PHY/CODING/nrLDPC_defs.h" #include "openair1/PHY/CODING/nrLDPC_defs.h"
#include "openair1/PHY/CODING/nrLDPC_extern.h"
#include "ldpc_encode_parity_check.c" #include "ldpc_encode_parity_check.c"
#include "ldpc_generate_coefficient.c" #include "ldpc_generate_coefficient.c"
int LDPCencoder(uint8_t **test_input, uint8_t **channel_input, encoder_implemparams_t *impp)
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 Zc = impp->Zc;
short nrows=0,ncols=0; int Kb = impp->Kb;
int block_length = impp->K;
int BG = impp->BG;
int nrows=0,ncols=0;
int rate=3; int rate=3;
int no_punctured_columns,removed_bit; 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; if ((Zc&31) > 0) simd_size = 16;
else simd_size = 32; else simd_size = 32;
unsigned char c[22*Zc] __attribute__((aligned(32))); //padded input, unpacked, max size uint8_t 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 d[46*Zc] __attribute__((aligned(32))); //coded parity part output, unpacked, max size
// calculate number of punctured bits // calculate number of punctured bits
no_punctured_columns=(int)((nrows-2)*Zc+block_length-block_length*rate)/Zc; 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",no_punctured_columns);
// printf("%d\n",removed_bit); // printf("%d\n",removed_bit);
// unpack input // unpack input
memset(c,0,sizeof(unsigned char) * ncols * Zc); memset(c, 0, sizeof(c));
memset(d,0,sizeof(unsigned char) * nrows * Zc); memset(d, 0, sizeof(d));
if(impp->tinput != NULL) start_meas(impp->tinput); if(impp->tinput != NULL) start_meas(impp->tinput);
for (int i=0; i<block_length; i++) { for (int i=0; i<block_length; i++) {
@@ -37,13 +37,17 @@
#include "common/utils/LOG/log.h" #include "common/utils/LOG/log.h"
#include "time_meas.h" #include "time_meas.h"
#include "openair1/PHY/CODING/nrLDPC_defs.h" #include "openair1/PHY/CODING/nrLDPC_defs.h"
#include "openair1/PHY/CODING/nrLDPC_extern.h"
#include "ldpc_encode_parity_check.c" #include "ldpc_encode_parity_check.c"
#include "ldpc_generate_coefficient.c" #include "ldpc_generate_coefficient.c"
#include "PHY/sse_intrin.h" #include "PHY/sse_intrin.h"
int LDPCencoder(uint8_t **test_input, uint8_t **channel_input, encoder_implemparams_t *impp)
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 Zc = impp->Zc;
int Kb = impp->Kb;
short block_length = impp->K;
short BG = impp->BG;
short nrows=0,ncols=0; short nrows=0,ncols=0;
int i,i1,j,rate=3; int i,i1,j,rate=3;
@@ -38,15 +38,19 @@
#include "time_meas.h" #include "time_meas.h"
#include "openair1/PHY/CODING/nrLDPC_defs.h" #include "openair1/PHY/CODING/nrLDPC_defs.h"
#include "PHY/sse_intrin.h" #include "PHY/sse_intrin.h"
#include "openair1/PHY/CODING/nrLDPC_extern.h"
#include "ldpc_encode_parity_check.c" #include "ldpc_encode_parity_check.c"
#include "ldpc_generate_coefficient.c" #include "ldpc_generate_coefficient.c"
int LDPCencoder(uint8_t **input, uint8_t **output, encoder_implemparams_t *impp)
int nrLDPC_encod(unsigned char **input,unsigned char **output,int Zc,int Kb,short block_length, short BG, encoder_implemparams_t *impp)
{ {
//set_log(PHY, 4); //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 nrows=0,ncols=0;
int rate=3; int rate=3;
+19 -18
View File
@@ -18,28 +18,29 @@
* For more information about the OpenAirInterface (OAI) Software Alliance: * For more information about the OpenAirInterface (OAI) Software Alliance:
* contact@openairinterface.org * contact@openairinterface.org
*/ */
#ifndef _NRLDPC_EXTERN_H__
#define _NRLDPC_EXTERN_H__
#include "openair1/PHY/CODING/nrLDPC_defs.h" #include "openair1/PHY/CODING/nrLDPC_defs.h"
#ifdef LDPC_LOADER /* ldpc coder/decoder API*/
nrLDPC_decoderfunc_t nrLDPC_decoder; typedef struct ldpc_interface_s {
nrLDPC_encoderfunc_t nrLDPC_encoder; LDPC_initfunc_t *LDPCinit;
nrLDPC_initcallfunc_t nrLDPC_initcall; LDPC_shutdownfunc_t *LDPCshutdown;
nrLDPC_decoffloadfunc_t nrLDPC_decoder_offload; LDPC_decoderfunc_t *LDPCdecoder;
nrLDPC_dectopfunc_t top_testsuite; LDPC_encoderfunc_t *LDPCencoder;
#else } 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 */ /* functions to load the LDPC shared lib, implemented in openair1/PHY/CODING/nrLDPC_load.c */
int load_nrLDPClib(char *version); int load_LDPClib(char *version, ldpc_interface_t *);
int load_nrLDPClib_offload(void); int free_LDPClib(ldpc_interface_t *ldpc_interface);
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;
extern nrLDPC_decoderfunc_t nrLDPC_decoder; LDPC_initfunc_t LDPCinit;
extern nrLDPC_encoderfunc_t nrLDPC_encoder; LDPC_shutdownfunc_t LDPCshutdown;
extern nrLDPC_decoffloadfunc_t nrLDPC_decoder_offload; LDPC_decoderfunc_t LDPCdecoder;
LDPC_encoderfunc_t LDPCencoder;
extern nrLDPC_dectopfunc_t top_testsuite;
// inline functions: // inline functions:
#endif #endif
+17 -72
View File
@@ -35,20 +35,16 @@
#include <malloc.h> #include <malloc.h>
#include "assertions.h" #include "assertions.h"
#include "common/utils/LOG/log.h" #include "common/utils/LOG/log.h"
#define LDPC_LOADER
#include "PHY/CODING/nrLDPC_extern.h" #include "PHY/CODING/nrLDPC_extern.h"
#include "common/config/config_userapi.h" #include "common/config/config_userapi.h"
#include "common/utils/load_module_shlib.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];
/* arguments used when called from phy simulators exec's which do not use the config module */ /* 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 */ /* arg is used to initialize the config module so that the loader works as expected */
char *arg[64]={"ldpctest",NULL}; 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 *ptr = (char *)config_get_if();
char libname[64] = "ldpc"; char libname[64] = "ldpc";
@@ -56,76 +52,25 @@ int load_nrLDPClib(char *version) {
uniqCfg = load_configmodule(1, arg, CONFIG_ENABLECMDLINEONLY); uniqCfg = load_configmodule(1, arg, CONFIG_ENABLECMDLINEONLY);
logInit(); logInit();
} }
shlib_fdesc[0].fname = "nrLDPC_decod"; /* function description array, to be used when loading the encoding/decoding shared lib */
shlib_fdesc[1].fname = "nrLDPC_encod"; loader_shlibfunc_t shlib_fdesc[] = {{.fname = "LDPCinit"},
shlib_fdesc[2].fname = "nrLDPC_initcall"; {.fname = "LDPCshutdown"},
{.fname = "LDPCdecoder"},
{.fname = "LDPCencoder"}};
int ret; int ret;
ret = load_module_version_shlib(libname, version, shlib_fdesc, sizeofArray(shlib_fdesc), NULL); ret = load_module_version_shlib(libname, version, shlib_fdesc, sizeofArray(shlib_fdesc), NULL);
AssertFatal((ret >= 0), "Error loading ldpc decoder"); AssertFatal((ret >= 0), "Error loading ldpc decoder");
nrLDPC_decoder = (nrLDPC_decoderfunc_t)shlib_fdesc[0].fptr; itf->LDPCinit = (LDPC_initfunc_t *)shlib_fdesc[0].fptr;
nrLDPC_encoder = (nrLDPC_encoderfunc_t)shlib_fdesc[1].fptr; itf->LDPCshutdown = (LDPC_shutdownfunc_t *)shlib_fdesc[1].fptr;
nrLDPC_initcall = (nrLDPC_initcallfunc_t)shlib_fdesc[2].fptr; itf->LDPCdecoder = (LDPC_decoderfunc_t *)shlib_fdesc[2].fptr;
return 0; itf->LDPCencoder = (LDPC_encoderfunc_t *)shlib_fdesc[3].fptr;
}
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");
AssertFatal(itf->LDPCinit() == 0, "error starting LDPC library %s %s\n", libname, version);
return 0; return 0;
} }
int free_nrLDPClib_offload(void) { int free_LDPClib(ldpc_interface_t *ldpc_interface)
t_nrLDPC_dec_params decParams; {
t_nrLDPC_dec_params* p_decParams = &decParams; return ldpc_interface->LDPCshutdown();
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 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;
}
+5 -3
View File
@@ -501,6 +501,9 @@ int init_codebook_gNB(PHY_VARS_gNB *gNB) {
return 0; 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) int phy_init_nr_gNB(PHY_VARS_gNB *gNB)
{ {
// shortcuts // 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 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) if (gNB->ldpc_offload_flag)
load_nrLDPClib_offload(); load_LDPClib("_t2", &ldpc_interface_offload);
gNB->max_nb_pdsch = MAX_MOBILES_PER_GNB; gNB->max_nb_pdsch = MAX_MOBILES_PER_GNB;
init_codebook_gNB(gNB); init_codebook_gNB(gNB);
+94 -46
View File
@@ -163,7 +163,6 @@ void ldpc8blocks(void *p)
{ {
encoder_implemparams_t *impp=(encoder_implemparams_t *) p; encoder_implemparams_t *impp=(encoder_implemparams_t *) p;
NR_DL_gNB_HARQ_t *harq = (NR_DL_gNB_HARQ_t *)impp->harq; 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; nfapi_nr_dl_tti_pdsch_pdu_rel15_t *rel15 = &harq->pdsch_pdu.pdsch_pdu_rel15;
uint8_t mod_order = rel15->qamModOrder[0]; uint8_t mod_order = rel15->qamModOrder[0];
uint16_t nb_rb = rel15->rbSize; uint16_t nb_rb = rel15->rbSize;
@@ -183,9 +182,10 @@ void ldpc8blocks(void *p)
// nrLDPC_encoder output is in "d" // nrLDPC_encoder output is in "d"
// let's make this interface happy! // let's make this interface happy!
uint8_t tmp[8][68 * 384]__attribute__((aligned(32))); 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++ ) 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]; d[rr] = tmp[i];
nrLDPC_encoder(harq->c,impp->d,*impp->Zc, impp->Kb,Kr,impp->BG,impp); ldpc_interface.LDPCencoder(harq->c, d, impp);
// Compute where to place in output buffer that is concatenation of all segments // Compute where to place in output buffer that is concatenation of all segments
uint32_t r_offset=0; uint32_t r_offset=0;
for (int i=0; i < impp->macro_num*8; i++ ) 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++ ) { for (int rr=impp->macro_num*8; rr < impp->n_segments && rr < (impp->macro_num+1)*8; rr++ ) {
if (impp->F>0) { if (impp->F>0) {
// writing into positions d[r][k-2Zc] as in clause 5.3.2 step 2) in 38.212 // 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 #ifdef DEBUG_DLSCH_CODING
@@ -201,14 +201,18 @@ void ldpc8blocks(void *p)
#endif #endif
uint32_t E = nr_get_E(G, impp->n_segments, mod_order, rel15->nrOfLayers, rr); uint32_t E = nr_get_E(G, impp->n_segments, mod_order, rel15->nrOfLayers, rr);
//#ifdef DEBUG_DLSCH_CODING //#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, rr,
impp->n_segments, impp->n_segments,
G, G,
E, E,
impp->F, impp->F,
Kr-impp->F-2*(*impp->Zc), impp->K - impp->F - 2 * impp->Zc,
mod_order,nb_rb,rel15->nrOfLayers); mod_order,
nb_rb,
rel15->nrOfLayers);
uint32_t Tbslbrm = rel15->maintenance_parms_v3.tbSizeLbrmBytes; uint32_t Tbslbrm = rel15->maintenance_parms_v3.tbSizeLbrmBytes;
@@ -216,27 +220,38 @@ void ldpc8blocks(void *p)
bzero (e, E); bzero (e, E);
nr_rate_matching_ldpc(Tbslbrm, nr_rate_matching_ldpc(Tbslbrm,
impp->BG, impp->BG,
*impp->Zc, impp->Zc,
impp->d[rr], d[rr],
e, e,
impp->n_segments, impp->n_segments,
impp->F, impp->F,
Kr-impp->F-2*(*impp->Zc), impp->K - impp->F - 2 * impp->Zc,
rel15->rvIndex[0], rel15->rvIndex[0],
E); E);
if (Kr-impp->F-2*(*impp->Zc)> E) { 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", LOG_E(PHY,
A,impp->K,G, nb_rb,nb_symb_sch,nb_re_dmrs,length_dmrs,(int)mod_order); "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,
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", impp->K,
rr, G,
impp->n_segments, nb_rb,
G, nb_symb_sch,
E, nb_re_dmrs,
Kr, length_dmrs,
impp->F, (int)mod_order);
Kr-impp->F-2*(*impp->Zc),
mod_order,nb_rb); 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 #ifdef DEBUG_DLSCH_CODING
@@ -279,7 +294,7 @@ int nr_dlsch_encoding(PHY_VARS_gNB *gNB,
impp.output=output; impp.output=output;
unsigned int crc=1; unsigned int crc=1;
nfapi_nr_dl_tti_pdsch_pdu_rel15_t *rel15 = &harq->pdsch_pdu.pdsch_pdu_rel15; 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); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_gNB_DLSCH_ENCODING, VCD_FUNCTION_IN);
uint32_t A = rel15->TBSize[0]<<3; uint32_t A = rel15->TBSize[0]<<3;
unsigned char *a=harq->pdu; unsigned char *a=harq->pdu;
@@ -335,14 +350,13 @@ int nr_dlsch_encoding(PHY_VARS_gNB *gNB,
impp.BG = rel15->maintenance_parms_v3.ldpcBaseGraph; impp.BG = rel15->maintenance_parms_v3.ldpcBaseGraph;
start_meas(dlsch_segmentation_stats); 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); stop_meas(dlsch_segmentation_stats);
if (impp.n_segments>MAX_NUM_NR_DLSCH_SEGMENTS_PER_LAYER*rel15->nrOfLayers) { 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); LOG_E(PHY, "nr_segmentation.c: too many segments %d, B %d\n", impp.n_segments, B);
return(-1); return(-1);
} }
for (int r=0; r<impp.n_segments; r++) { for (int r=0; r<impp.n_segments; r++) {
//d_tmp[r] = &harq->d[r][0]; //d_tmp[r] = &harq->d[r][0];
//channel_input[r] = &harq->d[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.tinput = tinput;
impp.tparity = tparity; impp.tparity = tparity;
impp.toutput = toutput; impp.toutput = toutput;
impp.harq = harq;
impp.harq=harq; if (gNB->ldpc_offload_flag && *rel15->mcsIndex > 2) {
notifiedFIFO_t nf; impp.Qm = rel15->qamModOrder[0];
initNotifiedFIFO(&nf); impp.rv = rel15->rvIndex[0];
int nbJobs=0; int nb_re_dmrs =
for(int j=0; j<(impp.n_segments/8+((impp.n_segments&7)==0 ? 0 : 1)); j++) { (rel15->dmrsConfigType == NFAPI_NR_DMRS_TYPE1) ? (6 * rel15->numDmrsCdmGrpsNoData) : (4 * rel15->numDmrsCdmGrpsNoData);
notifiedFIFO_elt_t *req=newNotifiedFIFO_elt(sizeof(impp), j, &nf, ldpc8blocks); impp.G = nr_get_G(rel15->rbSize,
encoder_implemparams_t* perJobImpp=(encoder_implemparams_t*)NotifiedFifoData(req); rel15->NrOfSymbols,
*perJobImpp=impp; nb_re_dmrs,
perJobImpp->macro_num=j; get_num_dmrs(rel15->dlDmrsSymbPos),
pushTpool(&gNB->threadPool, req); harq->unav_res,
nbJobs++; rel15->qamModOrder[0],
} rel15->nrOfLayers);
while(nbJobs) { uint8_t tmp[68 * 384] __attribute__((aligned(32)));
notifiedFIFO_elt_t *req=pullTpool(&nf, &gNB->threadPool); uint8_t *d = tmp;
if (req == NULL) int r_offset = 0;
break; // Tpool has been stopped for (int r = 0; r < impp.n_segments; r++) {
delNotifiedFIFO_elt(req); impp.E = nr_get_E(impp.G, impp.n_segments, impp.Qm, rel15->nrOfLayers, r);
nbJobs--; 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); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_gNB_DLSCH_ENCODING, VCD_FUNCTION_OUT);
return 0; return 0;
+48 -68
View File
@@ -187,7 +187,7 @@ static void nr_processULSegment(void *arg)
memset(ulsch_harq->c[r], 0, Kr_bytes); memset(ulsch_harq->c[r], 0, Kr_bytes);
p_decoderParms->crc_type = crcType(ulsch_harq->C, A); 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); // start_meas(&phy_vars_gNB->ulsch_ldpc_decoding_stats);
// set first 2*Z_c bits to zeros // set first 2*Z_c bits to zeros
@@ -215,7 +215,8 @@ static void nr_processULSegment(void *arg)
////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////// pl =====> llrProcBuf ////////////////////////////////// ////////////////////////////////// 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) if (rdata->decodeIterations <= p_decoderParms->numMaxIter)
memcpy(ulsch_harq->c[r],llrProcBuf, Kr>>3); 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_gNB_ULSCH_t *ulsch = &phy_vars_gNB->ulsch[ULSCH_id];
NR_UL_gNB_HARQ_t *harq_process = ulsch->harq_process; NR_UL_gNB_HARQ_t *harq_process = ulsch->harq_process;
int8_t llrProcBuf[22 * 384] __attribute__((aligned(32))); int16_t z_ol[68 * 384 + 16] __attribute__((aligned(16)));
int16_t z_ol[68 * 384] __attribute__((aligned(32))); int8_t l_ol[68 * 384 + 16] __attribute__((aligned(16)));
int8_t l_ol[68 * 384] __attribute__((aligned(32)));
uint8_t Qm = pusch_pdu->qam_mod_order; uint8_t Qm = pusch_pdu->qam_mod_order;
uint8_t n_layers = pusch_pdu->nrOfLayers; uint8_t n_layers = pusch_pdu->nrOfLayers;
const int Kr = harq_process->K; const int Kr = harq_process->K;
const int Kr_bytes = Kr >> 3; const int Kr_bytes = Kr >> 3;
uint32_t A = (harq_process->TBS) << 3;
const int kc = decParams->BG == 2 ? 52 : 68; 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 decodeIterations = 2;
int dtx_det = 0;
int r_offset = 0, offset = 0; int r_offset = 0, offset = 0;
for (int r = 0; r < harq_process->C; r++) { for (int r = 0; r < harq_process->C; r++) {
int E = nr_get_E(G, harq_process->C, Qm, n_layers, r); int E = nr_get_E(G, harq_process->C, Qm, n_layers, r);
memset(harq_process->c[r], 0, Kr_bytes); memset(harq_process->c[r], 0, Kr_bytes);
decParams->R = nr_get_R_ldpc_decoder(pusch_pdu->pusch_data.rv_index, decParams->R = nr_get_R_ldpc_decoder(pusch_pdu->pusch_data.rv_index,
E, E,
decParams->BG, decParams->BG,
@@ -254,49 +253,24 @@ int decode_offload(PHY_VARS_gNB *phy_vars_gNB,
&harq_process->llrLen, &harq_process->llrLen,
harq_process->round); harq_process->round);
if ((dtx_det == 0) && (pusch_pdu->pusch_data.rv_index == 0)) { memcpy(z_ol, ulsch_llr + r_offset, E * sizeof(short));
memcpy(z_ol, ulsch_llr + r_offset, E * sizeof(short)); simde__m128i *pv_ol128 = (simde__m128i *)&z_ol;
simde__m128i *pv_ol128 = (simde__m128i *)&z_ol; simde__m128i *pl_ol128 = (simde__m128i *)&l_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++) {
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]);
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;
} }
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) { if (decodeSuccess) {
memcpy(harq_process->b + offset, harq_process->c[r], Kr_bytes - (harq_process->F >> 3) - ((harq_process->C > 1) ? 3 : 0)); 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)); 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 { } else {
LOG_D(PHY, "uplink segment error %d/%d\n", r, harq_process->C); LOG_D(PHY, "uplink segment error %d/%d\n", r, harq_process->C);
LOG_D(PHY, "ULSCH %d in error\n", ULSCH_id); 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));
} }
} }
if (crc_valid) {
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_gNB_ULSCH_DECODING, 0);
if (harq_process->processedSegments == harq_process->C) {
LOG_D(PHY, "ULSCH: Setting ACK for slot %d TBS %d\n", ulsch->slot, harq_process->TBS); LOG_D(PHY, "ULSCH: Setting ACK for slot %d TBS %d\n", ulsch->slot, harq_process->TBS);
ulsch->active = false; ulsch->active = false;
harq_process->round = 0; harq_process->round = 0;
LOG_D(PHY, "ULSCH received ok \n"); LOG_D(PHY, "ULSCH received ok \n");
nr_fill_indication(phy_vars_gNB, ulsch->frame, ulsch->slot, ULSCH_id, harq_pid, 0, 0); nr_fill_indication(phy_vars_gNB, ulsch->frame, ulsch->slot, ULSCH_id, harq_pid, 0, 0);
} else { } else {
LOG_D(PHY, LOG_D(PHY,
"[gNB %d] ULSCH: Setting NAK for SFN/SF %d/%d (pid %d, status %d, round %d, TBS %d)\n", "[gNB %d] ULSCH: Setting NAK for SFN/SF %d/%d (pid %d, status %d, round %d, TBS %d)\n",
phy_vars_gNB->Mod_id, phy_vars_gNB->Mod_id,
ulsch->frame, ulsch->frame,
ulsch->slot, ulsch->slot,
harq_pid, harq_pid,
ulsch->active, ulsch->active,
harq_process->round, harq_process->round,
harq_process->TBS); harq_process->TBS);
ulsch->handled = 1; ulsch->handled = 1;
decodeIterations = ulsch->max_ldpc_iterations + 1; decodeIterations = ulsch->max_ldpc_iterations + 1;
LOG_D(PHY, "ULSCH %d in error\n", ULSCH_id); 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); nr_fill_indication(phy_vars_gNB, ulsch->frame, ulsch->slot, ULSCH_id, harq_pid, 1, 0);
} }
ulsch->last_iteration_cnt = decodeIterations; ulsch->last_iteration_cnt = decodeIterations;
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_gNB_ULSCH_DECODING,0);
return 0; return 0;
} }
@@ -373,7 +353,7 @@ int nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB,
harq_process->processedSegments = 0; harq_process->processedSegments = 0;
harq_process->TBS = pusch_pdu->pusch_data.tb_size; 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; decParams.BG = pusch_pdu->maintenance_parms_v3.ldpcBaseGraph;
const uint32_t A = (harq_process->TBS) << 3; const uint32_t A = (harq_process->TBS) << 3;
NR_gNB_PHY_STATS_t *stats = get_phy_stats(phy_vars_gNB, ulsch->rnti); 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.Z = harq_process->Z;
decParams.numMaxIter = ulsch->max_ldpc_iterations; decParams.numMaxIter = ulsch->max_ldpc_iterations;
decParams.outMode = 0; decParams.outMode = 0;
decParams.setCombIn = !harq_process->harq_to_be_cleared;
if (harq_process->harq_to_be_cleared) { if (harq_process->harq_to_be_cleared) {
for (int r = 0; r < harq_process->C; r++) for (int r = 0; r < harq_process->C; r++)
harq_process->d_to_be_cleared[r] = true; harq_process->d_to_be_cleared[r] = true;
harq_process->harq_to_be_cleared = false; 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); return decode_offload(phy_vars_gNB, ULSCH_id, ulsch_llr, pusch_pdu, &decParams, harq_pid, G);
uint32_t offset = 0, r_offset = 0; uint32_t offset = 0, r_offset = 0;
@@ -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); //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); p_decoderParms->crc_type = crcType(harq_process->C, A);
nrLDPC_initcall(p_decoderParms, (int8_t *)&pl[0], LDPCoutput); rdata->decodeIterations =
rdata->decodeIterations = nrLDPC_decoder(p_decoderParms, (int8_t *)&pl[0], LDPCoutput, &procTime, &harq_process->abort_decode); 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); //VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_DLSCH_LDPC, VCD_FUNCTION_OUT);
if (rdata->decodeIterations <= dlsch->max_ldpc_iterations) 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 ret,offset;
uint32_t r,r_offset=0,Kr=8424,Kr_bytes; uint32_t r,r_offset=0,Kr=8424,Kr_bytes;
t_nrLDPC_dec_params decParams; t_nrLDPC_dec_params decParams;
t_nrLDPC_dec_params *p_decParams = &decParams; decParams.check_crc = check_crc;
if (!harq_process) { if (!harq_process) {
LOG_E(PHY,"dlsch_decoding.c: NULL harq_process pointer\n"); 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", 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); 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); decParams.BG = get_BG(A, dlsch->dlsch_config.targetCodeRate);
unsigned int kc = p_decParams->BG == 2 ? 52 : 68; unsigned int kc = decParams.BG == 2 ? 52 : 68;
if (harq_process->first_rx == 1) { if (harq_process->first_rx == 1) {
// This is a new packet, so compute quantities regarding segmentation // 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->K,
&harq_process->Z, // [hna] Z is Zc &harq_process->Z, // [hna] Z is Zc
&harq_process->F, &harq_process->F,
p_decParams->BG); decParams.BG);
if (harq_process->C>MAX_NUM_NR_DLSCH_SEGMENTS_PER_LAYER*dlsch->Nl) { 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); 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); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_DLSCH_SEGMENTATION, VCD_FUNCTION_OUT);
p_decParams->Z = harq_process->Z; decParams.Z = harq_process->Z;
//printf("dlsch decoding nr segmentation Z %d\n", p_decParams->Z); decParams.numMaxIter = dlsch->max_ldpc_iterations;
//printf("coderate %f kc %d \n", Coderate, kc); decParams.outMode = 0;
p_decParams->numMaxIter = dlsch->max_ldpc_iterations;
p_decParams->outMode= 0;
r_offset = 0; r_offset = 0;
uint16_t a_segments = MAX_NUM_NR_DLSCH_SEGMENTS_PER_LAYER*dlsch->Nl; //number of segments to be allocated 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)) if (LOG_DEBUGFLAG(DEBUG_DLSCH_DECOD))
LOG_I(PHY,"Segmentation: C %d, K %d\n",harq_process->C,harq_process->K); 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; Kr_bytes = Kr>>3;
offset = 0; offset = 0;
notifiedFIFO_t nf; notifiedFIFO_t nf;
+43 -31
View File
@@ -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]; NR_UL_UE_HARQ_t *harq_process = &ue->ul_harq_processes[harq_pid];
uint16_t nb_rb = ulsch->pusch_pdu.rb_size; uint16_t nb_rb = ulsch->pusch_pdu.rb_size;
uint32_t A = tb_size << 3; uint32_t A = tb_size << 3;
uint32_t *pz = &harq_process->Z;
uint8_t mod_order = ulsch->pusch_pdu.qam_mod_order; uint8_t mod_order = ulsch->pusch_pdu.qam_mod_order;
uint16_t Kr=0; uint16_t Kr = 0;
uint32_t r_offset=0; uint32_t r_offset = 0;
uint32_t F=0; uint32_t F = 0;
// target_code_rate is in 0.1 units // target_code_rate is in 0.1 units
float Coderate = (float) ulsch->pusch_pdu.target_code_rate / 10240.0f; float Coderate = (float) ulsch->pusch_pdu.target_code_rate / 10240.0f;
@@ -72,9 +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 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, "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", LOG_D(NR_PHY,
harq_pid,harq_process->ndi,ulsch->pusch_pdu.pusch_data.new_data_indicator); "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 || if (harq_process->first_tx == 1 ||
harq_process->ndi != ulsch->pusch_pdu.pusch_data.new_data_indicator) { // this is a new packet harq_process->ndi != ulsch->pusch_pdu.pusch_data.new_data_indicator) { // this is a new packet
#ifdef DEBUG_ULSCH_CODING #ifdef DEBUG_ULSCH_CODING
@@ -140,7 +141,7 @@ int nr_ulsch_encoding(PHY_VARS_NR_UE *ue,
B, B,
&harq_process->C, &harq_process->C,
&harq_process->K, &harq_process->K,
pz, &harq_process->Z,
&harq_process->F, &harq_process->F,
harq_process->BG); harq_process->BG);
@@ -161,7 +162,7 @@ int nr_ulsch_encoding(PHY_VARS_NR_UE *ue,
///////////////////////// c---->| LDCP coding |---->d ///////////////////////// ///////////////////////// 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); //start_meas(te_stats);
for (int r=0; r<harq_process->C; r++) { for (int r=0; r<harq_process->C; r++) {
@@ -170,7 +171,7 @@ int nr_ulsch_encoding(PHY_VARS_NR_UE *ue,
printf("Encoder: B %d F %d \n", B, harq_process->F); printf("Encoder: B %d F %d \n", B, harq_process->F);
printf("start ldpc encoder segment %d/%d\n",r,harq_process->C); 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]); 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("%d ", harq_process->c[r][cnt]);
} }
printf("\n"); printf("\n");
@@ -183,28 +184,38 @@ int nr_ulsch_encoding(PHY_VARS_NR_UE *ue,
//for (int i=0;i<68*384;i++) //for (int i=0;i<68*384;i++)
// printf("channel_input[%d]=%d\n",i,channel_input[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]); /*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],
for (int cnt =0 ; cnt < 66*(*pz); cnt ++){ harq_process->d[0][4]); for (int cnt =0 ; cnt < 66*harq_process->Z; cnt ++){ printf("%d \n", harq_process->d[0][cnt]);
printf("%d \n", harq_process->d[0][cnt]);
} }
printf("\n");*/ printf("\n");*/
encoder_implemparams_t impp = { encoder_implemparams_t impp = {.n_segments = harq_process->C,
.n_segments=harq_process->C, .macro_num = 0,
.macro_num=0, .K = harq_process->K,
.tinput = NULL, .Kb = Kb,
.tprep = NULL, .Zc = harq_process->Z,
.tparity = NULL, .BG = harq_process->BG,
.toutput = NULL}; .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); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_LDPC_ENCODER_OPTIM, VCD_FUNCTION_IN);
start_meas(&ue->ulsch_ldpc_encoding_stats); start_meas(&ue->ulsch_ldpc_encoding_stats);
for(int j = 0; j < (harq_process->C/8 + 1); j++) { if (ldpc_interface_offload.LDPCencoder)
impp.macro_num = j; for (int j = 0; j < harq_process->C; j++) {
nrLDPC_encoder(harq_process->c,harq_process->d,*pz,Kb,Kr,harq_process->BG,&impp); impp.macro_num = j;
} impp.E = nr_get_E(G, harq_process->C, mod_order, ulsch->pusch_pdu.nrOfLayers, j);
stop_meas(&ue->ulsch_ldpc_encoding_stats); 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); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_LDPC_ENCODER_OPTIM, VCD_FUNCTION_OUT);
//stop_meas(te_stats); //stop_meas(te_stats);
@@ -224,7 +235,7 @@ int nr_ulsch_encoding(PHY_VARS_NR_UE *ue,
for (int r=0; r<harq_process->C; r++) { // looping over C segments for (int r=0; r<harq_process->C; r++) { // looping over C segments
if (harq_process->F>0) { if (harq_process->F>0) {
for (int k=(Kr-F-2*(*pz)); k<Kr-2*(*pz); k++) { for (int k = Kr - F - 2 * harq_process->Z; k < Kr - 2 * harq_process->Z; k++) {
harq_process->d[r][k] = NR_NULL; harq_process->d[r][k] = NR_NULL;
//if (k<(Kr-F+8)) //if (k<(Kr-F+8))
//printf("r %d filler bits [%d] = %d \n", r,k, harq_process->d[r][k]); //printf("r %d filler bits [%d] = %d \n", r,k, harq_process->d[r][k]);
@@ -249,14 +260,15 @@ int nr_ulsch_encoding(PHY_VARS_NR_UE *ue,
start_meas(&ue->ulsch_rate_matching_stats); start_meas(&ue->ulsch_rate_matching_stats);
if (nr_rate_matching_ldpc(ulsch->pusch_pdu.tbslbrm, if (nr_rate_matching_ldpc(ulsch->pusch_pdu.tbslbrm,
harq_process->BG, harq_process->BG,
*pz, harq_process->Z,
harq_process->d[r], harq_process->d[r],
harq_process->e+r_offset, harq_process->e + r_offset,
harq_process->C, harq_process->C,
F, F,
Kr-F-2*(*pz), Kr - F - 2 * harq_process->Z,
ulsch->pusch_pdu.pusch_data.rv_index, ulsch->pusch_pdu.pusch_data.rv_index,
E) == -1) E)
== -1)
return -1; return -1;
stop_meas(&ue->ulsch_rate_matching_stats); stop_meas(&ue->ulsch_rate_matching_stats);
+36 -3
View File
@@ -291,6 +291,7 @@ int main(int argc, char **argv)
uint8_t n_tx=1,n_rx=1; uint8_t n_tx=1,n_rx=1;
uint8_t round; uint8_t round;
uint8_t num_rounds = 4; uint8_t num_rounds = 4;
int ldpc_offload_flag = 0;
char gNBthreads[128]="n"; char gNBthreads[128]="n";
channel_desc_t *gNB2UE; channel_desc_t *gNB2UE;
@@ -353,7 +354,7 @@ int main(int argc, char **argv)
FILE *scg_fd=NULL; 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) { switch (c) {
case 'f': case 'f':
scg_fd = fopen(optarg,"r"); scg_fd = fopen(optarg,"r");
@@ -398,6 +399,10 @@ int main(int argc, char **argv)
n_trials = atoi(optarg); n_trials = atoi(optarg);
break; break;
case 'c':
ldpc_offload_flag = 1;
break;
case 's': case 's':
snr0 = atof(optarg); snr0 = atof(optarg);
printf("Setting SNR0 to %f\n",snr0); printf("Setting SNR0 to %f\n",snr0);
@@ -542,7 +547,31 @@ int main(int argc, char **argv)
default: default:
case 'h': 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 <log level, 0(errors), 1(warning), 2(analysis), 3(info), 4(debug), 5(trace)>\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("-a Start PRB for PDSCH\n");
printf("-b Number of PRB for PDSCH\n"); printf("-b Number of PRB for PDSCH\n");
printf("-d number of dlsch threads, 0: no dlsch parallelization\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 = RC.gNB[0];
gNB->ofdm_offset_divisor = UINT_MAX; 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 = &gNB->frame_parms; //to be initialized I suppose (maybe not necessary for PBCH)
frame_parms->nb_antennas_tx = n_tx; frame_parms->nb_antennas_tx = n_tx;
frame_parms->nb_antennas_rx = n_rx; 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);
free(UE->phy_sim_pdsch_dl_ch_estimates_ext); free(UE->phy_sim_pdsch_dl_ch_estimates_ext);
free(UE->phy_sim_dlsch_b); free(UE->phy_sim_dlsch_b);
if (gNB->ldpc_offload_flag)
free_LDPClib(&ldpc_interface_offload);
if (output_fd) if (output_fd)
fclose(output_fd); fclose(output_fd);
+2 -2
View File
@@ -796,7 +796,7 @@ int main(int argc, char *argv[])
ulsch_input_buffer[0] = 0x31; ulsch_input_buffer[0] = 0x31;
for (i = 1; i < TBS/8; i++) { 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); uint8_t ptrs_time_density = get_L_ptrs(ptrs_mcs1, ptrs_mcs2, ptrs_mcs3, Imcs, mcs_table);
@@ -1612,7 +1612,7 @@ int main(int argc, char *argv[])
free_MIB_NR(mib); free_MIB_NR(mib);
if (gNB->ldpc_offload_flag) if (gNB->ldpc_offload_flag)
free_nrLDPClib_offload(); free_LDPClib(&ldpc_interface_offload);
if (output_fd) if (output_fd)
fclose(output_fd); fclose(output_fd);