mirror of
https://gitlab.eurecom.fr/oai/openairinterface5g.git
synced 2026-07-13 12:40:28 +00:00
Compare commits
50 Commits
fix_ue_nul
...
ldpc_decod
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f709560814 | ||
|
|
ec99b5179d | ||
|
|
d30c7c30bb | ||
|
|
0a5b46c4c8 | ||
|
|
580ea58119 | ||
|
|
0d4bceabad | ||
|
|
eea9f4874e | ||
|
|
c86bc8ce5c | ||
|
|
c115f01155 | ||
|
|
58ccdb2993 | ||
|
|
3fd8e59814 | ||
|
|
007f001b81 | ||
|
|
4e3da82743 | ||
|
|
f31cde65e3 | ||
|
|
f054fa20f3 | ||
|
|
b332265971 | ||
|
|
211ebf4ac4 | ||
|
|
153498a471 | ||
|
|
5e3f72ccc7 | ||
|
|
b61ea4bea3 | ||
|
|
6f996be21a | ||
|
|
d7187155f8 | ||
|
|
3375775a32 | ||
|
|
1d860c0f00 | ||
|
|
662f6634bf | ||
|
|
45a9bb8bd9 | ||
|
|
16967ddb2e | ||
|
|
cc3d03f738 | ||
|
|
d509dba9f0 | ||
|
|
db034d4f48 | ||
|
|
fd4597b8de | ||
|
|
20b10593db | ||
|
|
6a59f7e7f7 | ||
|
|
8b3993c75b | ||
|
|
9e0e7a8e14 | ||
|
|
bf54022242 | ||
|
|
139bc7d8ea | ||
|
|
76918b076a | ||
|
|
f9a19017a6 | ||
|
|
4e133fff30 | ||
|
|
495f5f563c | ||
|
|
4bfabcb1d5 | ||
|
|
d0f55118a7 | ||
|
|
e8e88f5459 | ||
|
|
19afd37b93 | ||
|
|
ce879f1f92 | ||
|
|
03e5bdd8ae | ||
|
|
e9def5ce04 | ||
|
|
052d0001e3 | ||
|
|
9ea6af0fc2 |
@@ -498,10 +498,30 @@ if (ENABLE_LDPC_T2)
|
||||
add_library(ldpc_t2 MODULE ${OPENAIR1_DIR}/PHY/CODING/nrLDPC_decoder/nrLDPC_decoder_offload.c)
|
||||
set_target_properties(ldpc_t2 PROPERTIES COMPILE_FLAGS "-DALLOW_EXPERIMENTAL_API")
|
||||
target_link_libraries(ldpc_t2 ${LIBDPDK_T2_LDFLAGS} ${PMD_T2})
|
||||
set(PHY_LDPC_SLOT_T2_SRC
|
||||
${OPENAIR1_DIR}/PHY/CODING/nrLDPC_decoder/nrLDPC_coding_t2.c
|
||||
${OPENAIR1_DIR}/PHY/CODING/nrLDPC_decoder/nrLDPC_decoder.c
|
||||
${OPENAIR1_DIR}/PHY/CODING/nrLDPC_encoder/ldpc_encoder_optim8segmulti.c
|
||||
)
|
||||
add_library(ldpc_slot_t2 MODULE ${PHY_LDPC_SLOT_T2_SRC})
|
||||
set_target_properties(ldpc_slot_t2 PROPERTIES COMPILE_FLAGS "-DALLOW_EXPERIMENTAL_API")
|
||||
target_link_libraries(ldpc_slot_t2 PRIVATE ldpc_gen_HEADERS ${LIBDPDK_T2_LDFLAGS} ${PMD_T2})
|
||||
endif()
|
||||
|
||||
##########################################################
|
||||
|
||||
# LDPC offload library - XDMA
|
||||
##########################################################
|
||||
add_boolean_option(ENABLE_LDPC_XDMA OFF "Build support for LDPC Offload to XDMA library" OFF)
|
||||
if (ENABLE_LDPC_XDMA)
|
||||
set(PHY_NRLDPC_CODING_XDMA_SRC
|
||||
${OPENAIR1_DIR}/PHY/CODING/nrLDPC_decoder/nrLDPC_decoder_offload_xdma.c
|
||||
${OPENAIR1_DIR}/PHY/CODING/nrLDPC_coding_interface_xdma.c
|
||||
${OPENAIR1_DIR}/PHY/CODING/nrLDPC_coding_interface_demo_encoder.c
|
||||
)
|
||||
add_library(ldpc_xdma MODULE ${PHY_NRLDPC_CODING_XDMA_SRC})
|
||||
endif()
|
||||
|
||||
include_directories ("${OPENAIR_DIR}/radio/COMMON")
|
||||
|
||||
##############################################################
|
||||
@@ -848,10 +868,19 @@ add_library(ldpc_cl MODULE ${PHY_LDPC_CL_SRC} )
|
||||
target_link_libraries(ldpc_cl OpenCL)
|
||||
add_dependencies(ldpc_cl nrLDPC_decoder_kernels_CL)
|
||||
|
||||
set(PHY_NRLDPC_CODING_DEMO_SRC
|
||||
${OPENAIR1_DIR}/PHY/CODING/nrLDPC_coding_interface_demo_decoder.c
|
||||
${OPENAIR1_DIR}/PHY/CODING/nrLDPC_coding_interface_demo_encoder.c
|
||||
)
|
||||
|
||||
set(PHY_NR_CODINGIF
|
||||
${OPENAIR1_DIR}/PHY/CODING/nrLDPC_load.c
|
||||
)
|
||||
|
||||
set(PHY_NRLDPC_CODINGIF
|
||||
${OPENAIR1_DIR}/PHY/CODING/nrLDPC_coding_interface_load.c
|
||||
)
|
||||
|
||||
##############################################
|
||||
# Base CUDA setting
|
||||
##############################################
|
||||
@@ -872,6 +901,7 @@ 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(ldpc_slot_demo MODULE ${PHY_NRLDPC_CODING_DEMO_SRC})
|
||||
|
||||
set(PHY_SRC_COMMON
|
||||
${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/dci_tools_common.c
|
||||
@@ -1031,7 +1061,9 @@ set(PHY_SRC_UE
|
||||
${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_dlsch.c
|
||||
${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_dlsch_tools.c
|
||||
${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_dlsch_coding.c
|
||||
${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_dlsch_coding_slot.c
|
||||
${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_ulsch_decoding.c
|
||||
${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_ulsch_decoding_slot.c
|
||||
${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_ulsch.c
|
||||
${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_tbs_tools.c
|
||||
${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_sch_dmrs.c
|
||||
@@ -1061,6 +1093,7 @@ set(PHY_SRC_UE
|
||||
${PHY_POLARSRC}
|
||||
${PHY_SMALLBLOCKSRC}
|
||||
${PHY_NR_CODINGIF}
|
||||
${PHY_NRLDPC_CODINGIF}
|
||||
${OPENAIR1_DIR}/PHY/NR_TRANSPORT/pucch_rx.c
|
||||
${OPENAIR1_DIR}/PHY/NR_TRANSPORT/srs_rx.c
|
||||
${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_uci_tools_common.c
|
||||
@@ -1080,7 +1113,9 @@ set(PHY_SRC_UE
|
||||
${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/nr_psbch_tx.c
|
||||
${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c
|
||||
${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/nr_ulsch_coding.c
|
||||
${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/nr_ulsch_coding_slot.c
|
||||
${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c
|
||||
${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding_slot.c
|
||||
${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/nr_dlsch_llr_computation.c
|
||||
${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_tbs_tools.c
|
||||
${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_prach_common.c
|
||||
@@ -1119,6 +1154,7 @@ set(PHY_SRC_UE
|
||||
${PHY_POLARSRC}
|
||||
${PHY_SMALLBLOCKSRC}
|
||||
${PHY_NR_CODINGIF}
|
||||
${PHY_NRLDPC_CODINGIF}
|
||||
)
|
||||
|
||||
|
||||
@@ -2049,10 +2085,14 @@ if(E2_AGENT)
|
||||
endif()
|
||||
|
||||
|
||||
add_dependencies(nr-softmodem ldpc_orig ldpc_optim ldpc_optim8seg ldpc)
|
||||
add_dependencies(nr-softmodem ldpc_orig ldpc_optim ldpc_optim8seg ldpc ldpc_slot_demo)
|
||||
|
||||
if (ENABLE_LDPC_T2)
|
||||
add_dependencies(nr-softmodem ldpc_t2)
|
||||
add_dependencies(nr-softmodem ldpc_t2 ldpc_slot_t2)
|
||||
endif()
|
||||
|
||||
if (ENABLE_LDPC_XDMA)
|
||||
add_dependencies(nr-softmodem ldpc_xdma)
|
||||
endif()
|
||||
|
||||
# force the generation of ASN.1 so that we don't need to wait during the build
|
||||
@@ -2106,7 +2146,7 @@ target_link_libraries(nr-uesoftmodem PRIVATE pthread m CONFIG_LIB rt nr_ue_phy_m
|
||||
target_link_libraries(nr-uesoftmodem PRIVATE ${T_LIB})
|
||||
target_link_libraries(nr-uesoftmodem PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs)
|
||||
|
||||
add_dependencies( nr-uesoftmodem ldpc_orig ldpc_optim ldpc_optim8seg ldpc )
|
||||
add_dependencies( nr-uesoftmodem ldpc_orig ldpc_optim ldpc_optim8seg ldpc ldpc_slot_demo)
|
||||
if (ENABLE_LDPC_CUDA)
|
||||
add_dependencies(nr-uesoftmodem ldpc_cuda)
|
||||
add_dependencies(nr-softmodem ldpc_cuda)
|
||||
@@ -2267,8 +2307,12 @@ add_executable(nr_ulsim
|
||||
)
|
||||
|
||||
if (ENABLE_LDPC_T2)
|
||||
add_dependencies(nr_ulsim ldpc_t2)
|
||||
add_dependencies(nr_ulsim ldpc_t2 ldpc_slot_t2)
|
||||
endif()
|
||||
if (ENABLE_LDPC_XDMA)
|
||||
add_dependencies(nr_ulsim ldpc_xdma)
|
||||
endif()
|
||||
add_dependencies(nr_ulsim ldpc_slot_demo)
|
||||
|
||||
target_link_libraries(nr_ulsim PRIVATE
|
||||
-Wl,--start-group UTIL SIMU PHY_COMMON PHY_NR_COMMON PHY_NR PHY_NR_UE SCHED_NR_LIB SCHED_NR_UE_LIB MAC_UE_NR MAC_NR_COMMON nr_rrc CONFIG_LIB L2_NR HASHTABLE x2ap SECURITY ngap -lz -Wl,--end-group
|
||||
@@ -2335,7 +2379,7 @@ if (${T_TRACER})
|
||||
PHY_COMMON PHY PHY_UE PHY_NR PHY_NR_COMMON PHY_NR_UE PHY_RU PHY_MEX
|
||||
L2 L2_LTE L2_NR L2_LTE_NR L2_UE NR_L2_UE L2_UE_LTE_NR MAC_NR_COMMON MAC_UE_NR ngap
|
||||
CN_UTILS GTPV1U SCTP_CLIENT MME_APP LIB_NAS_UE NB_IoT SIMU OPENAIR0_LIB
|
||||
ldpc_orig ldpc_optim ldpc_optim8seg ldpc_t2 ldpc_cl ldpc_cuda ldpc dfts config_internals nr_common)
|
||||
ldpc_orig ldpc_optim ldpc_optim8seg ldpc_t2 ldpc_cl ldpc_cuda ldpc ldpc_slot_demo ldpc_slot_t2 ldpc_xdma dfts config_internals nr_common)
|
||||
if (TARGET ${i})
|
||||
add_dependencies(${i} generate_T)
|
||||
endif()
|
||||
|
||||
@@ -46,7 +46,7 @@ BUILD_DOXYGEN=0
|
||||
DISABLE_HARDWARE_DEPENDENCY="False"
|
||||
CMAKE_BUILD_TYPE="RelWithDebInfo"
|
||||
CMAKE_CMD="$CMAKE"
|
||||
OPTIONAL_LIBRARIES="telnetsrv enbscope uescope nrscope ldpc_cuda ldpc_t2 websrv oai_iqplayer"
|
||||
OPTIONAL_LIBRARIES="telnetsrv enbscope uescope nrscope ldpc_cuda ldpc_t2 ldpc_xdma websrv oai_iqplayer"
|
||||
TARGET_LIST=""
|
||||
|
||||
function print_help() {
|
||||
|
||||
@@ -74,11 +74,6 @@ If DPDK library was installed into custom path, you have to point to the right d
|
||||
```
|
||||
export PKG_CONFIG_PATH=/opt/dpdk-t2/lib64/pkgconfig/:$PKG_CONFIG_PATH
|
||||
```
|
||||
## Setup of T2-related DPDK EAL parameters
|
||||
To configure T2-related DPDK Environment Abstraction Layer (EAL) parameters, you can set the following parameters via the command line:
|
||||
- `ldpc_offload.dpdk_dev` - **mandatory** parameter, specifies PCI address of the T2 card. PCI address of the T2 card can be detected by `lspci | grep "Xilinx"` command.
|
||||
- `ldpc_offload.dpdk_cores_list` - CPU cores assigned to DPDK for T2 processing, by default set to *11-12*. Ensure that the CPU cores specified in *ldpc_offload.dpdk_cores_list* are available and not used by other processes to avoid conflicts.
|
||||
- `ldpc_offload.dpdk_prefix` - DPDK shared data file prefix, by default set to *b6*
|
||||
|
||||
# OAI Build
|
||||
OTA deployment is precisely described in the following tutorial:
|
||||
@@ -102,18 +97,39 @@ cd cmake_targets
|
||||
./build_oai -w USRP --ninja --gNB -P --build-lib "ldpc_t2" -C
|
||||
```
|
||||
|
||||
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*.
|
||||
Shared object file *libldpc_slot_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*
|
||||
|
||||
# Setup of T2-related DPDK EAL parameters
|
||||
To configure T2-related DPDK Environment Abstraction Layer (EAL) parameters, you can set the following parameters via the command line of PHY simulators or softmodem:
|
||||
- `nrLDPC_coding_t2.dpdk_dev` - **mandatory** parameter, specifies PCI address of the T2 card. PCI address of the T2 card can be detected by `lspci | grep "Xilinx"` command.
|
||||
- `nrLDPC_coding_t2.dpdk_core_list` - **mandatory** parameter, specifies CPU cores assigned to DPDK for T2 processing. Ensure that the CPU cores specified in *nrLDPC_coding_t2.dpdk_core_list* are available and not used by other processes to avoid conflicts.
|
||||
- `nrLDPC_coding_t2.dpdk_prefix` - DPDK shared data file prefix, by default set to *b6*.
|
||||
|
||||
**Note:** These parameters can also be provided in a configuration file:
|
||||
```
|
||||
nrLDPC_coding_t2 : {
|
||||
dpdk_dev : "41:00.0";
|
||||
dpdk_core_list : "14-15";
|
||||
};
|
||||
|
||||
loader : {
|
||||
ldpc : {
|
||||
shlibversion : "_slot_t2";
|
||||
};
|
||||
};
|
||||
```
|
||||
|
||||
# 5G PHY simulators
|
||||
|
||||
## nr_ulsim test
|
||||
Offload of the channel decoding to the T2 card is in nr_ulsim specified by *-o* option. Example command for running nr_ulsim with LDPC decoding offload to the T2 card:
|
||||
Offload of the channel decoding to the T2 card is in nr_ulsim specified by *--loader.ldpc.shlibversion _slot_t2* option. Example command for running nr_ulsim with LDPC decoding offload to the T2 card:
|
||||
```
|
||||
cd ~/openairinterface5g
|
||||
source oaienv
|
||||
cd cmake_targets/ran_build/build
|
||||
sudo ./nr_ulsim -n100 -s20 -m20 -r273 -R273 -o --ldpc_offload.dpdk_dev 01:00.0
|
||||
sudo ./nr_ulsim -n100 -s20 -m20 -r273 -R273 --loader.ldpc.shlibversion _slot_t2 --nrLDPC_coding_t2.dpdk_dev 01:00.0 --nrLDPC_coding_t2.dpdk_core_list 0-1
|
||||
```
|
||||
## nr_dlsim test
|
||||
Offload of the channel encoding to the AMD Xilinx T2 card is in nr_dlsim specified by *-c* option. Example command for running nr_dlsim with LDPC encoding offload to the T2 card:
|
||||
@@ -121,18 +137,18 @@ Offload of the channel encoding to the AMD Xilinx T2 card is in nr_dlsim specifi
|
||||
cd ~/openairinterface5g
|
||||
source oaienv
|
||||
cd cmake_targets/ran_build/build
|
||||
sudo ./nr_dlsim -n300 -s30 -R 106 -e 27 -c --ldpc_offload.dpdk_dev 01:00.0
|
||||
sudo ./nr_dlsim -n300 -s30 -R 106 -e 27 --loader.ldpc.shlibversion _slot_t2 --nrLDPC_coding_t2.dpdk_dev 01:00.0 --nrLDPC_coding_t2.dpdk_core_list 0-1
|
||||
```
|
||||
|
||||
# OTA test
|
||||
Offload of the channel encoding and decoding to the AMD Xilinx T2 card is enabled by *--ldpc-offload-enable* option.
|
||||
Offload of the channel encoding and decoding to the AMD Xilinx T2 card is enabled by *--loader.ldpc.shlibversion _slot_t2* 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 --ldpc_offload.dpdk_dev 01:00.0
|
||||
sudo ./nr-softmodem --sa -O ../../../targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.conf --loader.ldpc.shlibversion _slot_t2 --nrLDPC_coding_t2.dpdk_dev 01:00.0 --nrLDPC_coding_t2.dpdk_core_list 0-1
|
||||
```
|
||||
|
||||
# Limitations
|
||||
|
||||
155
doc/LDPC_XDMA_OFFLOAD_SETUP.md
Normal file
155
doc/LDPC_XDMA_OFFLOAD_SETUP.md
Normal file
@@ -0,0 +1,155 @@
|
||||
[TOC]
|
||||
|
||||
This documentation aims to provide a tutorial for Xilinx FPGA PCIe-XDMA integration into OAI and its usage. It can offload LDPC decoding to FPGA.
|
||||
|
||||
# Requirements
|
||||
|
||||
- XDMA driver
|
||||
|
||||
# XDMA Driver Build & Install
|
||||
|
||||
The *xdma_driver* directory contains the following:
|
||||
|
||||
```bash
|
||||
xdma_driver
|
||||
├── cmake
|
||||
├── FPGA_TEST_datasheet.txt
|
||||
├── include
|
||||
├── libfpga_0720_vt.so
|
||||
├── libfpga_8038_vt.so
|
||||
├── libfpga_ldpc.a
|
||||
├── libTHIRD_PARTY.a
|
||||
├── nr_ldpc_decoding_pym.h
|
||||
├── README.md
|
||||
├── tests
|
||||
├── xdma
|
||||
└── xdma_diag.h
|
||||
```
|
||||
|
||||
Before building the driver, ensure that your system recognizes the Xilinx device. You can check this using the `lspci` command:
|
||||
|
||||
```bash
|
||||
$ lspci | grep Xilinx
|
||||
01:00.0 Serial controller: Xilinx Corporation Device 8038
|
||||
```
|
||||
|
||||
Building and Installing the Driver
|
||||
|
||||
```
|
||||
cd xdma_driver/xdma
|
||||
sudo make clean
|
||||
sudo make install
|
||||
cd xdma_driver/tests
|
||||
sudo ./load_driver.sh
|
||||
```
|
||||
|
||||
# OAI Build
|
||||
|
||||
```bash
|
||||
# Get openairinterface5g source code
|
||||
git clone https://gitlab.eurecom.fr/oai/openairinterface5g.git ~/openairinterface5g
|
||||
cd ~/openairinterface5g
|
||||
|
||||
# Install OAI dependencies
|
||||
cd ~/openairinterface5g/cmake_targets
|
||||
./build_oai -I
|
||||
|
||||
# Build OAI gNB & UE
|
||||
cd ~/openairinterface5g
|
||||
source oaienv
|
||||
cd cmake_targets
|
||||
./build_oai --ninja -w SIMU --gNB --nrUE -P --build-lib "ldpc_xdma" -C -c
|
||||
```
|
||||
|
||||
Shared object file *libldpc_xdma.so* is created during the compilation. This object is conditionally compiled. Selection of the library to compile is done using `--build-lib ldpc_xdma`.
|
||||
|
||||
# 5G PHY simulators
|
||||
|
||||
The simulated test uses the option `--loader.ldpc.shlibversion _xdma` to select the XDMA version for loading into the LDPC interface. Additionally, the option `--nrLDPC_coding_xdma.num_threads_prepare` is used to specify the number of threads for preparing data before the LDPC processing, specifically for the deinterleaving and rate matching parts.
|
||||
|
||||
Another way to activate the feature is to add the `slot_xdma.conf` file with the following content:
|
||||
|
||||
```
|
||||
nrLDPC_coding_xdma : {
|
||||
num_threads_prepare : 2;
|
||||
};
|
||||
|
||||
loader : {
|
||||
ldpc : {
|
||||
shlibversion : "_xdma";
|
||||
};
|
||||
};
|
||||
|
||||
```
|
||||
|
||||
and use option `-O slot_xdma.conf`.
|
||||
|
||||
## nr_ulsim test
|
||||
|
||||
Example command for running nr_ulsim with LDPC decoding offload to the FPGA:
|
||||
|
||||
```bash
|
||||
cd ~/openairinterface5g/cmake_targets/ran_build/build
|
||||
sudo ./nr_ulsim -n100 -m28 -r273 -R273 -s22 -I10 -C8 -P --loader.ldpc.shlibversion _xdma --nrLDPC_coding_xdma.num_threads_prepare 2
|
||||
```
|
||||
|
||||
or
|
||||
|
||||
```
|
||||
sudo ./nr_ulsim -n100 -m28 -r273 -R273 -s22 -I10 -C8 -P -O slot_xdma.conf
|
||||
```
|
||||
|
||||
# Run
|
||||
|
||||
Both gNB and nrUE use the option `--loader.ldpc.shlibversion _xdma` to select the XDMA version for loading into the LDPC interface and `--nrLDPC_coding_xdma.num_threads_prepare` to specify the number of threads for preparing data before the LDPC processing, specifically for the deinterleaving and rate matching parts.
|
||||
|
||||
Another way to activate the feature is to add the following content to the `.conf` file you want to use:
|
||||
|
||||
```
|
||||
nrLDPC_coding_xdma : {
|
||||
num_threads_prepare : 2;
|
||||
};
|
||||
|
||||
loader : {
|
||||
ldpc : {
|
||||
shlibversion : "_xdma";
|
||||
};
|
||||
};
|
||||
|
||||
```
|
||||
|
||||
and use option `-O *.conf`.
|
||||
|
||||
## gNB
|
||||
|
||||
Example command using rfsim:
|
||||
|
||||
```bash
|
||||
cd ~/openairinterface5g/cmake_targets/ran_build/build
|
||||
sudo ./nr-softmodem --sa --rfsim --log_config.global_log_options level,nocolor,time -O ../../../ci-scripts/conf_files/gnb.sa.band78.106prb.rfsim.conf --loader.ldpc.shlibversion _xdma --nrLDPC_coding_xdma.num_threads_prepare 2
|
||||
```
|
||||
|
||||
or
|
||||
|
||||
```bash
|
||||
sudo ./nr-softmodem --sa --rfsim --log_config.global_log_options level,nocolor,time -O ../../../ci-scripts/conf_files/gnb.sa.band78.106prb.rfsim.conf
|
||||
```
|
||||
|
||||
if you have added the configuration to the `.conf` file.
|
||||
|
||||
## UE
|
||||
|
||||
Example command using rfsim:
|
||||
|
||||
```bash
|
||||
cd ~/openairinterface5g/cmake_targets/ran_build/build
|
||||
sudo ./nr-uesoftmodem --sa --rfsim -r 106 --numerology 1 --band 78 -C 3319680000 --ue-nb-ant-tx 1 --ue-nb-ant-rx 1 -O ../../../ci-scripts/conf_files/nrue1.uicc.cluCN.conf --rfsimulator.serveraddr 10.201.1.100 --loader.ldpc.shlibversion _xdma --nrLDPC_coding_xdma.num_threads_prepare 2
|
||||
```
|
||||
|
||||
or
|
||||
|
||||
```bash
|
||||
sudo ./nr-uesoftmodem --sa --rfsim -r 106 --numerology 1 --band 78 -C 3319680000 --ue-nb-ant-tx 1 --ue-nb-ant-rx 1 -O ../../../ci-scripts/conf_files/nrue1.uicc.cluCN.conf --rfsimulator.serveraddr 10.201.1.100
|
||||
```
|
||||
|
||||
if you have added the configuration to the `.conf` file.
|
||||
@@ -42,6 +42,7 @@
|
||||
|
||||
//#undef FRAME_LENGTH_COMPLEX_SAMPLES //there are two conflicting definitions, so we better make sure we don't use it at all
|
||||
#include "openair1/PHY/MODULATION/nr_modulation.h"
|
||||
#include "PHY/CODING/nrLDPC_coding_interface.h"
|
||||
#include "PHY/phy_vars_nr_ue.h"
|
||||
#include "PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h"
|
||||
#include "PHY/NR_TRANSPORT/nr_dlsch.h"
|
||||
@@ -386,6 +387,7 @@ configmodule_interface_t *uniqCfg = NULL;
|
||||
|
||||
// A global var to reduce the changes size
|
||||
ldpc_interface_t ldpc_interface = {0}, ldpc_interface_offload = {0};
|
||||
nrLDPC_coding_interface_t nrLDPC_coding_interface = {0};
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
@@ -422,10 +424,20 @@ int main(int argc, char **argv)
|
||||
|
||||
init_opt();
|
||||
|
||||
if (nrUE_params.ldpc_offload_flag)
|
||||
load_LDPClib("_t2", &ldpc_interface_offload);
|
||||
|
||||
load_LDPClib(NULL, &ldpc_interface);
|
||||
int nrLDPC_coding_interface_flag = 0;
|
||||
int ret_loader = load_nrLDPC_coding_interface(NULL, &nrLDPC_coding_interface);
|
||||
if (ret_loader >= 0) {
|
||||
nrLDPC_coding_interface_flag = 1;
|
||||
if (nrUE_params.ldpc_offload_flag)
|
||||
load_LDPClib("_t2", &ldpc_interface_offload);
|
||||
else
|
||||
load_LDPClib("", &ldpc_interface);
|
||||
} else {
|
||||
if (nrUE_params.ldpc_offload_flag)
|
||||
load_LDPClib("_t2", &ldpc_interface_offload);
|
||||
else
|
||||
load_LDPClib(NULL, &ldpc_interface);
|
||||
}
|
||||
|
||||
if (ouput_vcd) {
|
||||
vcd_signal_dumper_init("/tmp/openair_dump_nrUE.vcd");
|
||||
@@ -443,6 +455,7 @@ int main(int argc, char **argv)
|
||||
for (int CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) {
|
||||
PHY_vars_UE_g[inst][CC_id] = malloc(sizeof(*PHY_vars_UE_g[inst][CC_id]));
|
||||
memset(PHY_vars_UE_g[inst][CC_id], 0, sizeof(*PHY_vars_UE_g[inst][CC_id]));
|
||||
PHY_vars_UE_g[inst][CC_id]->nrLDPC_coding_interface_flag = nrLDPC_coding_interface_flag;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -82,6 +82,7 @@ typedef struct {
|
||||
int N_RB_DL;
|
||||
int ssb_start_subcarrier;
|
||||
int ldpc_offload_flag;
|
||||
int nrLDPC_coding_interface_flag;
|
||||
unsigned int ntn_koffset;
|
||||
double ntn_ta_common;
|
||||
int agc;
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
add_subdirectory(nr_phy_common)
|
||||
add_subdirectory(TOOLS)
|
||||
add_subdirectory(NR_TRANSPORT)
|
||||
add_subdirectory(CODING)
|
||||
|
||||
3
openair1/PHY/CODING/CMakeLists.txt
Normal file
3
openair1/PHY/CODING/CMakeLists.txt
Normal file
@@ -0,0 +1,3 @@
|
||||
if(ENABLE_TESTS)
|
||||
add_subdirectory(tests)
|
||||
endif()
|
||||
@@ -1,7 +1,12 @@
|
||||
# LDPC coder/decoder implementation
|
||||
The LDPC coder and decoder are implemented in a shared library, dynamically loaded at run-time using the [oai shared library loader](file://../../../../common/utils/DOC/loader.md). The code loading the LDPC library is in [nrLDPC_load.c](file://../nrLDPC_load.c), in function `load_nrLDPClib`, which must be called at init time.
|
||||
# LDPC coding implementation
|
||||
The LDPC encoder and decoder are implemented in a shared library, dynamically loaded at run-time using the [oai shared library loader](file://../../../../common/utils/DOC/loader.md).
|
||||
Two types of library are available with two different interfaces. There are libraries implementing the encoder and decoder of code segments and libraries implementing the encoder and decoder of slots.
|
||||
|
||||
## Selecting the LDPC library at run time
|
||||
## LDPC segment coding
|
||||
The interface of the library is defined in [nrLDPC_defs.h](file://../nrLDPC_defs.h).
|
||||
The code loading the LDPC library is in [nrLDPC_load.c](file://../nrLDPC_load.c), in function `load_nrLDPClib`, which must be called at init time.
|
||||
|
||||
### Selecting the LDPC library at run time
|
||||
|
||||
By default the function `int load_nrLDPClib(void)` looks for `libldpc.so`, this default behavior can be changed using the oai loader configuration options in the configuration file or from the command line as shown below:
|
||||
|
||||
@@ -118,7 +123,7 @@ At runtime, to successfully use hardware acceleration via OpenCL, you need to in
|
||||
------------------------------------------------------------
|
||||
```
|
||||
|
||||
A mechanism to select ldpc implementation is also available in the `ldpctest` phy simulator via the `-v`option, which can be used to specify the version of the ldpc shared library to be used.
|
||||
A mechanism to select ldpc implementation is also available in the `ldpctest` phy simulator via the `-v` option, which can be used to specify the version of the ldpc shared library to be used.
|
||||
|
||||
#### Examples of ldpc shared lib selection when running ldpctest:
|
||||
|
||||
@@ -196,4 +201,102 @@ Libraries implementing the LDPC algorithms must be named `libldpc<_version>.so`,
|
||||
|
||||
`libldpc_cl.so`is under development.
|
||||
|
||||
## LDPC slot coding
|
||||
The interface of the library is defined in [nrLDPC_coding_interface.h](file://../nrLDPC_coding_interface.h).
|
||||
The code loading the LDPC library is in [nrLDPC_coding_interface_load.c](file://../nrLDPC_coding_interface_load.c), in function `load_nrLDPC_coding_interface`, which must be called at init time.
|
||||
|
||||
### Selecting the LDPC library at run time
|
||||
|
||||
By default the function `int load_nrLDPC_coding_interface(void)` looks for `libldpc.so`.\
|
||||
If `libldpc.so` does not implement the LDPC slot decoder interface then the loader just fails which allows to fallback to the code segment decoding interface.\
|
||||
This default behavior can be changed using the oai loader configuration options in the configuration file or from the command line as shown below:
|
||||
|
||||
#### Examples of ldpc shared lib selection when running nr softmodem's:
|
||||
|
||||
loading `libldpc_slot_demo.so` instead of `libldpc.so`:
|
||||
|
||||
```
|
||||
./nr-softmodem -O libconfig:gnb.band78.tm1.106PRB.usrpx300.conf:dbgl5 --loader.ldpc.shlibversion _slot_demo
|
||||
.......................
|
||||
[CONFIG] loader.ldpc.shlibversion set to default value ""
|
||||
[LIBCONFIG] loader.ldpc: 2/2 parameters successfully set, (1 to default value)
|
||||
[CONFIG] shlibversion set to _slot_demo from command line
|
||||
[CONFIG] loader.ldpc 1 options set from command line
|
||||
shlib_path libldpc_slot_demo.so
|
||||
[LOADER] library libldpc_slot_demo.so successfully loaded
|
||||
........................
|
||||
```
|
||||
|
||||
*Note: `libldpc_slot_demo.so` is just to showcase the slot coding interface and uses a segment coding library behind.*
|
||||
*The segment coding library is `libldpc.so` by default but it can be chosen with option `--nrLDPC_coding_demo.segment_shlibversion` followed by the library version - like with `--loder.ldpc.shlibversion` in the segment coding case above -*
|
||||
|
||||
loading `libldpc_slot_t2.so` instead of `libldpc.so`:
|
||||
|
||||
`make ldpc_slot_t2`
|
||||
|
||||
This command creates the `libldpc_slot_t2.so` shared library.
|
||||
|
||||
```
|
||||
Building C object CMakeFiles/ldpc_slot_t2.dir/openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_coding_t2.c.o
|
||||
Linking C shared module libldpc_slot_t2.so
|
||||
```
|
||||
|
||||
At runtime, to successfully use the T2 board, you need to install vendor specific drivers and tools.\
|
||||
Please refer to the dedicated documentation at [LDPC_T2_OFFLOAD_SETUP.md](file://../../../../doc/LDPC_T2_OFFLOAD_SETUP.md).
|
||||
|
||||
`./nr-softmodem -O libconfig:gnb.band78.sa.fr1.106PRB.usrpb210.conf:dbgl5 --rfsim --rfsimulator.serveraddr server --sa --log_config.gtpu_log_level info --loader.ldpc.shlibversion _slot_t2 --nrLDPC_coding_t2.dpdk_dev 01:00.0 --nrLDPC_coding_t2.dpdk_core_list 0-1`
|
||||
|
||||
```
|
||||
|
||||
.......................
|
||||
[CONFIG] loader.ldpc.shlibversion set to default value ""
|
||||
[LIBCONFIG] loader.ldpc: 2/2 parameters successfully set, (1 to default value)
|
||||
[CONFIG] shlibversion set to _slot_t2 from command line
|
||||
[CONFIG] loader.ldpc 1 options set from command line
|
||||
shlib_path libldpc_slot_t2.so
|
||||
[LOADER] library libldpc_slot_t2.so successfully loaded
|
||||
........................
|
||||
```
|
||||
|
||||
loading `libldpc_xdma.so` instead of `libldpc.so`:
|
||||
|
||||
`make ldpc_xdma` or `ninja ldpc_xdma`
|
||||
|
||||
This command creates the `libldpc_xdma.so` shared library.
|
||||
|
||||
```
|
||||
ninja ldpc_xdma
|
||||
[2/2] Linking C shared module libldpc_xdma.so
|
||||
```
|
||||
|
||||
At runtime, to successfully use the xdma, you need to install vendor specific drivers and tools.\
|
||||
Please refer to the dedicated documentation at [LDPC_XDMA_OFFLOAD_SETUP.md](file://../../../../doc/LDPC_XDMA_OFFLOAD_SETUP.md).
|
||||
|
||||
`./nr-softmodem -O libconfig:gnb.band78.sa.fr1.106PRB.usrpb210.conf:dbgl5 --rfsim --rfsimulator.serveraddr server --sa --log_config.gtpu_log_level info --loader.ldpc.shlibversion _xdma --nrLDPC_coding_xdma.num_threads_prepare 2`
|
||||
|
||||
```
|
||||
.......................
|
||||
[CONFIG] loader.ldpc.shlibversion set to default value ""
|
||||
[LIBCONFIG] loader.ldpc: 2/2 parameters successfully set, (1 to default value)
|
||||
[CONFIG] shlibversion set to _xdma from command line
|
||||
[CONFIG] loader.ldpc 1 options set from command line
|
||||
shlib_path libldpc_xdma.so
|
||||
[LOADER] library libldpc_xdma.so successfully loaded
|
||||
........................
|
||||
```
|
||||
|
||||
#### Examples of ldpc shared lib selection when running ldpctest:
|
||||
|
||||
Slot decoding libraries cannot be used yet within ldpctest.
|
||||
But they can be used within nr_ulsim, nr_dlsim, nr_ulschsim and nr_dlschsim.
|
||||
|
||||
### LDPC libraries
|
||||
Libraries implementing the slotwise LDPC decoding must be named `libldpc<_version>.so`. They must implement four functions: `nrLDPC_coding_init`, `nrLDPC_coding_shutdown`, `nrLDPC_coding_decoder` and `nrLDPC_coding_encoder`. The prototypes for these functions is defined in [nrLDPC_coding_interface.h](file://../nrLDPC_coding_interface.h).
|
||||
|
||||
`libldpc_slot_demo.so` is completed.
|
||||
|
||||
`libldpc_slot_t2.so` is not implemented on this branch.
|
||||
|
||||
`libldpc_xdma.so` is completed.
|
||||
|
||||
[oai Wikis home](https://gitlab.eurecom.fr/oai/openairinterface5g/wikis/home)
|
||||
|
||||
247
openair1/PHY/CODING/nrLDPC_coding_interface.h
Normal file
247
openair1/PHY/CODING/nrLDPC_coding_interface.h
Normal file
@@ -0,0 +1,247 @@
|
||||
/*
|
||||
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.openairinterface.org/?page_id=698
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*-------------------------------------------------------------------------------
|
||||
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
#include "PHY/defs_gNB.h"
|
||||
|
||||
#ifndef __NRLDPC_CODING_INTERFACE__H__
|
||||
#define __NRLDPC_CODING_INTERFACE__H__
|
||||
|
||||
/**
|
||||
* \typedef nrLDPC_segment_decoding_parameters_t
|
||||
* \struct nrLDPC_segment_decoding_parameters_s
|
||||
* \brief decoding parameter of segments
|
||||
* \var E input llr segment size
|
||||
* \var R
|
||||
* \var llr input llr segment array
|
||||
* \var d Pointers to code blocks before LDPC decoding (38.212 V15.4.0 section 5.3.2)
|
||||
* \var d_to_be_cleared
|
||||
* pointer to the flag used to clear d properly
|
||||
* when true, clear d after rate dematching
|
||||
* \var c Pointers to code blocks after LDPC decoding (38.212 V15.4.0 section 5.2.2)
|
||||
* \var decodeSuccess
|
||||
* flag indicating that the decoding of the segment was successful
|
||||
* IT MUST BE FILLED BY THE IMPLEMENTATION
|
||||
*/
|
||||
typedef struct nrLDPC_segment_decoding_parameters_s{
|
||||
int E;
|
||||
uint8_t R;
|
||||
short *llr;
|
||||
int16_t *d;
|
||||
bool *d_to_be_cleared;
|
||||
uint8_t *c;
|
||||
bool decodeSuccess;
|
||||
} nrLDPC_segment_decoding_parameters_t;
|
||||
|
||||
/**
|
||||
* \typedef nrLDPC_TB_decoding_parameters_t
|
||||
* \struct nrLDPC_TB_decoding_parameters_s
|
||||
* \brief decoding parameter of transport blocks
|
||||
* \var xlsch_id ulsch or dlsch index
|
||||
* \var processedSegments
|
||||
* pointer to the number of succesfully decoded segments
|
||||
* it initially holds the total number of segments decoded after the previous HARQ round
|
||||
* it finally holds the total number of segments decoded after the current HARQ round
|
||||
* \var rnti RNTI
|
||||
* \var nb_rb number of resource blocks
|
||||
* \var Qm modulation order
|
||||
* \var mcs MCS
|
||||
* \var nb_layers number of layers
|
||||
* \var BG LDPC base graph id
|
||||
* \var rv_index
|
||||
* \var max_ldpc_iterations maximum number of LDPC iterations
|
||||
* \var abort_decode pointer to decode abort flag
|
||||
* \var G
|
||||
* \var tbslbrm Transport block size LBRM
|
||||
* \var A Transport block size (This is A from 38.212 V15.4.0 section 5.1)
|
||||
* \var K
|
||||
* \var Z lifting size
|
||||
* \var F filler bits size
|
||||
* \var C number of segments
|
||||
* \var segments array of segments parameters
|
||||
*/
|
||||
typedef struct nrLDPC_TB_decoding_parameters_s{
|
||||
|
||||
uint8_t xlsch_id;
|
||||
uint32_t *processedSegments;
|
||||
|
||||
uint16_t rnti;
|
||||
uint16_t nb_rb;
|
||||
uint8_t Qm;
|
||||
uint8_t mcs;
|
||||
uint8_t nb_layers;
|
||||
|
||||
uint8_t BG;
|
||||
uint8_t rv_index;
|
||||
uint8_t max_ldpc_iterations;
|
||||
decode_abort_t *abort_decode;
|
||||
|
||||
uint32_t G;
|
||||
uint32_t tbslbrm;
|
||||
uint32_t A;
|
||||
uint32_t K;
|
||||
uint32_t Z;
|
||||
uint32_t F;
|
||||
|
||||
uint32_t C;
|
||||
nrLDPC_segment_decoding_parameters_t *segments;
|
||||
} nrLDPC_TB_decoding_parameters_t;
|
||||
|
||||
/**
|
||||
* \typedef nrLDPC_slot_decoding_parameters_t
|
||||
* \struct nrLDPC_slot_decoding_parameters_s
|
||||
* \brief decoding parameter of slot
|
||||
* \var frame frame index
|
||||
* \var slot slot index
|
||||
* \var nb_TBs number of transport blocks
|
||||
* \var respDecode pointer to the queue for decoding tasks
|
||||
* \var threadPool pointer to the thread pool
|
||||
* \var TBs array of TBs decoding parameters
|
||||
*/
|
||||
typedef struct nrLDPC_slot_decoding_parameters_s{
|
||||
int frame;
|
||||
int slot;
|
||||
int nb_TBs;
|
||||
notifiedFIFO_t *respDecode;
|
||||
tpool_t *threadPool;
|
||||
nrLDPC_TB_decoding_parameters_t *TBs;
|
||||
} nrLDPC_slot_decoding_parameters_t;
|
||||
|
||||
/**
|
||||
* \typedef nrLDPC_segment_encoding_parameters_t
|
||||
* \struct nrLDPC_segment_encoding_parameters_s
|
||||
* \brief encoding parameter of segments
|
||||
* \var E input llr segment size
|
||||
* \var llr input llr segment array
|
||||
* \var c Pointers to code blocks after LDPC decoding (38.212 V15.4.0 section 5.2.2)
|
||||
* flag indicating that the decoding of the segment was successful
|
||||
* IT MUST BE FILLED BY THE IMPLEMENTATION
|
||||
*/
|
||||
typedef struct nrLDPC_segment_encoding_parameters_s{
|
||||
int E;
|
||||
unsigned char *output;
|
||||
uint8_t *c;
|
||||
} nrLDPC_segment_encoding_parameters_t;
|
||||
|
||||
/**
|
||||
* \typedef nrLDPC_TB_encoding_parameters_t
|
||||
* \struct nrLDPC_TB_encoding_parameters_s
|
||||
* \brief encoding parameter of transport blocks
|
||||
* \var xlsch_id ulsch or dlsch index
|
||||
* \var rnti RNTI
|
||||
* \var nb_rb number of resource blocks
|
||||
* \var Qm modulation order
|
||||
* \var mcs MCS
|
||||
* \var nb_layers number of layers
|
||||
* \var BG LDPC base graph id
|
||||
* \var rv_index
|
||||
* \var G
|
||||
* \var tbslbrm Transport block size LBRM
|
||||
* \var A Transport block size (This is A from 38.212 V15.4.0 section 5.1)
|
||||
* \var Kb
|
||||
* \var K
|
||||
* \var Z lifting size
|
||||
* \var F filler bits size
|
||||
* \var C number of segments
|
||||
* \var segments array of segments parameters
|
||||
*/
|
||||
typedef struct nrLDPC_TB_encoding_parameters_s{
|
||||
|
||||
uint8_t xlsch_id;
|
||||
|
||||
uint16_t rnti;
|
||||
uint16_t nb_rb;
|
||||
uint8_t Qm;
|
||||
uint8_t mcs;
|
||||
uint8_t nb_layers;
|
||||
|
||||
uint8_t BG;
|
||||
uint8_t rv_index;
|
||||
|
||||
uint32_t G;
|
||||
uint32_t tbslbrm;
|
||||
uint32_t A;
|
||||
uint32_t Kb;
|
||||
uint32_t K;
|
||||
uint32_t Z;
|
||||
uint32_t F;
|
||||
|
||||
uint32_t C;
|
||||
nrLDPC_segment_encoding_parameters_t *segments;
|
||||
} nrLDPC_TB_encoding_parameters_t;
|
||||
|
||||
/**
|
||||
* \typedef nrLDPC_slot_encoding_parameters_t
|
||||
* \struct nrLDPC_slot_encoding_parameters_s
|
||||
* \brief encoding parameter of slot
|
||||
* \var frame frame index
|
||||
* \var slot slot index
|
||||
* \var nb_TBs number of transport blocks
|
||||
* \var respEncode pointer to the queue for encoding tasks
|
||||
* \var threadPool pointer to the thread pool
|
||||
* \var tinput pointer to the input timer struct
|
||||
* \var tprep pointer to the preparation timer struct
|
||||
* \var tparity pointer to the parity timer struct
|
||||
* \var toutput pointer to the output timer struct
|
||||
* \var TBs array of TBs decoding parameters
|
||||
*/
|
||||
typedef struct nrLDPC_slot_encoding_parameters_s{
|
||||
int frame;
|
||||
int slot;
|
||||
int nb_TBs;
|
||||
notifiedFIFO_t *respEncode;
|
||||
tpool_t *threadPool;
|
||||
time_stats_t *tinput;
|
||||
time_stats_t *tprep;
|
||||
time_stats_t *tparity;
|
||||
time_stats_t *toutput;
|
||||
nrLDPC_TB_encoding_parameters_t *TBs;
|
||||
} nrLDPC_slot_encoding_parameters_t;
|
||||
|
||||
typedef int32_t(nrLDPC_coding_init_t)(void);
|
||||
typedef int32_t(nrLDPC_coding_shutdown_t)(void);
|
||||
|
||||
/**
|
||||
* \brief slot decoding function interface
|
||||
* \param nrLDPC_slot_decoding_parameters pointer to the structure holding the parameters necessary for decoding
|
||||
*/
|
||||
typedef int32_t(nrLDPC_coding_decoder_t)(nrLDPC_slot_decoding_parameters_t *nrLDPC_slot_decoding_parameters);
|
||||
|
||||
/**
|
||||
* \brief slot encoding function interface
|
||||
* \param nrLDPC_slot_encoding_parameters pointer to the structure holding the parameters necessary for encoding
|
||||
*/
|
||||
typedef int32_t(nrLDPC_coding_encoder_t)(nrLDPC_slot_encoding_parameters_t *nrLDPC_slot_encoding_parameters);
|
||||
|
||||
typedef struct nrLDPC_coding_interface_s {
|
||||
nrLDPC_coding_init_t *nrLDPC_coding_init;
|
||||
nrLDPC_coding_shutdown_t *nrLDPC_coding_shutdown;
|
||||
nrLDPC_coding_decoder_t *nrLDPC_coding_decoder;
|
||||
nrLDPC_coding_encoder_t *nrLDPC_coding_encoder;
|
||||
} nrLDPC_coding_interface_t;
|
||||
|
||||
int load_nrLDPC_coding_interface(char *version, nrLDPC_coding_interface_t *interface);
|
||||
int free_nrLDPC_coding_interface(nrLDPC_coding_interface_t *interface);
|
||||
|
||||
//TODO replace the global structure below
|
||||
// Global var to limit the rework of the dirty legacy code
|
||||
extern nrLDPC_coding_interface_t nrLDPC_coding_interface;
|
||||
|
||||
#endif
|
||||
292
openair1/PHY/CODING/nrLDPC_coding_interface_demo_decoder.c
Normal file
292
openair1/PHY/CODING/nrLDPC_coding_interface_demo_decoder.c
Normal file
@@ -0,0 +1,292 @@
|
||||
/*
|
||||
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||
* the OAI Public License, Version 1.0 (the "License"); you may not use this file
|
||||
* except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.openairinterface.org/?page_id=698
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*-------------------------------------------------------------------------------
|
||||
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
/*! \file PHY/CODING/nrLDPC_coding_interface_demo_decoder.c
|
||||
* \brief Top-level routines for decoding LDPC transport channels
|
||||
* \author Ahmed Hussein
|
||||
* \date 2019
|
||||
* \version 0.1
|
||||
* \company Fraunhofer IIS
|
||||
* \email: ahmed.hussein@iis.fraunhofer.de
|
||||
* \note
|
||||
* \warning
|
||||
*/
|
||||
|
||||
|
||||
// [from gNB coding]
|
||||
#include "PHY/defs_gNB.h"
|
||||
#include "PHY/CODING/coding_extern.h"
|
||||
#include "PHY/CODING/coding_defs.h"
|
||||
#include "PHY/CODING/lte_interleaver_inline.h"
|
||||
#include "PHY/CODING/nrLDPC_coding_interface.h"
|
||||
#include "PHY/CODING/nrLDPC_extern.h"
|
||||
#include "PHY/NR_TRANSPORT/nr_transport_common_proto.h"
|
||||
#include "PHY/NR_TRANSPORT/nr_transport_proto.h"
|
||||
#include "PHY/NR_TRANSPORT/nr_ulsch.h"
|
||||
#include "PHY/NR_TRANSPORT/nr_dlsch.h"
|
||||
#include "SCHED_NR/sched_nr.h"
|
||||
#include "SCHED_NR/fapi_nr_l1.h"
|
||||
#include "defs.h"
|
||||
#include "common/utils/LOG/vcd_signal_dumper.h"
|
||||
#include "common/utils/LOG/log.h"
|
||||
#include <syscall.h>
|
||||
//#define gNB_DEBUG_TRACE
|
||||
|
||||
#define OAI_LDPC_DECODER_MAX_NUM_LLR 27000 //26112 // NR_LDPC_NCOL_BG1*NR_LDPC_ZMAX = 68*384
|
||||
//#define DEBUG_CRC
|
||||
#ifdef DEBUG_CRC
|
||||
#define PRINT_CRC_CHECK(a) a
|
||||
#else
|
||||
#define PRINT_CRC_CHECK(a)
|
||||
#endif
|
||||
|
||||
#include "nfapi/open-nFAPI/nfapi/public_inc/nfapi_interface.h"
|
||||
#include "nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface.h"
|
||||
|
||||
/**
|
||||
* \typedef nrLDPC_decoding_parameters_t
|
||||
* \struct nrLDPC_decoding_parameters_s
|
||||
* \brief decoding parameter of transport blocks
|
||||
* \var decoderParams decoder parameters
|
||||
* \var Qm modulation order
|
||||
* \var Kc size of base graph input
|
||||
* \var rv_index
|
||||
* \var max_number_iterations maximum number of LDPC iterations
|
||||
* \var abort_decode pointer to decode abort flag
|
||||
* \var tbslbrm transport block size LBRM in bytes
|
||||
* \var A Transport block size (This is A from 38.212 V15.4.0 section 5.1)
|
||||
* \var K
|
||||
* \var Z lifting size
|
||||
* \var F filler bits size
|
||||
* \var r segment index in TB
|
||||
* \var E input llr segment size
|
||||
* \var C number of segments
|
||||
* \var llr input llr segment array
|
||||
* \var d Pointers to code blocks before LDPC decoding (38.212 V15.4.0 section 5.3.2)
|
||||
* \var d_to_be_cleared
|
||||
* pointer to the flag used to clear d properly
|
||||
* when true, clear d after rate dematching
|
||||
* \var c Pointers to code blocks after LDPC decoding (38.212 V15.4.0 section 5.2.2)
|
||||
* \var decodeSuccess pointer to the flag indicating that the decoding of the segment was successful
|
||||
*/
|
||||
typedef struct nrLDPC_decoding_parameters_s{
|
||||
|
||||
t_nrLDPC_dec_params decoderParms;
|
||||
|
||||
uint8_t Qm;
|
||||
|
||||
uint8_t Kc;
|
||||
uint8_t rv_index;
|
||||
decode_abort_t *abort_decode;
|
||||
|
||||
uint32_t tbslbrm;
|
||||
uint32_t A;
|
||||
uint32_t K;
|
||||
uint32_t Z;
|
||||
uint32_t F;
|
||||
|
||||
uint32_t C;
|
||||
|
||||
int E;
|
||||
short *llr;
|
||||
int16_t *d;
|
||||
bool *d_to_be_cleared;
|
||||
uint8_t *c;
|
||||
bool *decodeSuccess;
|
||||
uint32_t *processedSegments;
|
||||
} nrLDPC_decoding_parameters_t;
|
||||
|
||||
// Global var to limit the rework of the dirty legacy code
|
||||
ldpc_interface_t ldpc_interface_demo;
|
||||
|
||||
static void nr_process_decode_segment(void *arg)
|
||||
{
|
||||
nrLDPC_decoding_parameters_t *rdata = (nrLDPC_decoding_parameters_t *)arg;
|
||||
t_nrLDPC_dec_params *p_decoderParms = &rdata->decoderParms;
|
||||
const int Kr = rdata->K;
|
||||
const int Kr_bytes = Kr >> 3;
|
||||
const int K_bits_F = Kr - rdata->F;
|
||||
const int A = rdata->A;
|
||||
const int E = rdata->E;
|
||||
const int Qm = rdata->Qm;
|
||||
const int rv_index = rdata->rv_index;
|
||||
const uint8_t kc = rdata->Kc;
|
||||
short *ulsch_llr = rdata->llr;
|
||||
int8_t llrProcBuf[OAI_LDPC_DECODER_MAX_NUM_LLR] __attribute__((aligned(32)));
|
||||
|
||||
t_nrLDPC_time_stats procTime = {0};
|
||||
t_nrLDPC_time_stats *p_procTime = &procTime;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////////// nr_deinterleaving_ldpc ///////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//////////////////////////// ulsch_llr =====> ulsch_harq->e //////////////////////////////
|
||||
|
||||
/// code blocks after bit selection in rate matching for LDPC code (38.212 V15.4.0 section 5.4.2.1)
|
||||
int16_t harq_e[E];
|
||||
|
||||
nr_deinterleaving_ldpc(E, Qm, harq_e, ulsch_llr);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////////// nr_rate_matching_ldpc_rx ////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
///////////////////////// ulsch_harq->e =====> ulsch_harq->d /////////////////////////
|
||||
|
||||
|
||||
if (nr_rate_matching_ldpc_rx(rdata->tbslbrm,
|
||||
p_decoderParms->BG,
|
||||
p_decoderParms->Z,
|
||||
rdata->d,
|
||||
harq_e,
|
||||
rdata->C,
|
||||
rv_index,
|
||||
*rdata->d_to_be_cleared,
|
||||
E,
|
||||
rdata->F,
|
||||
Kr - rdata->F - 2 * (p_decoderParms->Z))
|
||||
== -1) {
|
||||
|
||||
LOG_E(PHY, "nrLDPC_coding_interface_demo_decoder.c: Problem in rate_matching\n");
|
||||
return;
|
||||
}
|
||||
|
||||
*rdata->d_to_be_cleared = false;
|
||||
|
||||
memset(rdata->c, 0, Kr_bytes);
|
||||
p_decoderParms->crc_type = crcType(rdata->C, A);
|
||||
p_decoderParms->E = lenWithCrc(rdata->C, A);
|
||||
// start_meas(&phy_vars_gNB->ulsch_ldpc_decoding_stats);
|
||||
|
||||
// set first 2*Z_c bits to zeros
|
||||
|
||||
int16_t z[68 * 384 + 16] __attribute__((aligned(16)));
|
||||
|
||||
memset(z, 0, 2 * rdata->Z * sizeof(*z));
|
||||
// set Filler bits
|
||||
memset(z + K_bits_F, 127, rdata->F * sizeof(*z));
|
||||
// Move coded bits before filler bits
|
||||
memcpy(z + 2 * rdata->Z, rdata->d, (K_bits_F - 2 * rdata->Z) * sizeof(*z));
|
||||
// skip filler bits
|
||||
memcpy(z + Kr, rdata->d + (Kr - 2 * rdata->Z), (kc * rdata->Z - Kr) * sizeof(*z));
|
||||
// Saturate coded bits before decoding into 8 bits values
|
||||
simde__m128i *pv = (simde__m128i *)&z;
|
||||
int8_t l[68 * 384 + 16] __attribute__((aligned(16)));
|
||||
simde__m128i *pl = (simde__m128i *)&l;
|
||||
for (int i = 0, j = 0; j < ((kc * rdata->Z) >> 4) + 1; i += 2, j++) {
|
||||
pl[j] = simde_mm_packs_epi16(pv[i], pv[i + 1]);
|
||||
}
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////////////// nrLDPC_decoder /////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////// pl =====> llrProcBuf //////////////////////////////////
|
||||
int decodeIterations =
|
||||
ldpc_interface_demo.LDPCdecoder(p_decoderParms, 0, 0, 0, l, llrProcBuf, p_procTime, rdata->abort_decode);
|
||||
|
||||
if (decodeIterations <= p_decoderParms->numMaxIter) {
|
||||
memcpy(rdata->c,llrProcBuf, Kr>>3);
|
||||
*rdata->decodeSuccess = true;
|
||||
*rdata->processedSegments = *rdata->processedSegments + 1;
|
||||
} else {
|
||||
*rdata->decodeSuccess = false;
|
||||
}
|
||||
}
|
||||
|
||||
int nrLDPC_prepare_TB_decoding(nrLDPC_slot_decoding_parameters_t *nrLDPC_slot_decoding_parameters, int pusch_id)
|
||||
{
|
||||
|
||||
nrLDPC_TB_decoding_parameters_t *nrLDPC_TB_decoding_parameters = &nrLDPC_slot_decoding_parameters->TBs[pusch_id];
|
||||
|
||||
*nrLDPC_TB_decoding_parameters->processedSegments = 0;
|
||||
t_nrLDPC_dec_params decParams = {.check_crc = check_crc};
|
||||
decParams.BG = nrLDPC_TB_decoding_parameters->BG;
|
||||
decParams.Z = nrLDPC_TB_decoding_parameters->Z;
|
||||
decParams.numMaxIter = nrLDPC_TB_decoding_parameters->max_ldpc_iterations;
|
||||
decParams.outMode = 0;
|
||||
|
||||
for (int r = 0; r < nrLDPC_TB_decoding_parameters->C; r++) {
|
||||
union ldpcReqUnion id = {.s = {nrLDPC_TB_decoding_parameters->rnti, nrLDPC_slot_decoding_parameters->frame, nrLDPC_slot_decoding_parameters->slot, 0, 0}};
|
||||
notifiedFIFO_elt_t *req = newNotifiedFIFO_elt(sizeof(nrLDPC_decoding_parameters_t), id.p, nrLDPC_slot_decoding_parameters->respDecode, &nr_process_decode_segment);
|
||||
nrLDPC_decoding_parameters_t *rdata = (nrLDPC_decoding_parameters_t *)NotifiedFifoData(req);
|
||||
decParams.R = nrLDPC_TB_decoding_parameters->segments[r].R;
|
||||
decParams.setCombIn = !nrLDPC_TB_decoding_parameters->segments[r].d_to_be_cleared;
|
||||
rdata->decoderParms = decParams;
|
||||
rdata->llr = nrLDPC_TB_decoding_parameters->segments[r].llr;
|
||||
rdata->Kc = decParams.BG == 2 ? 52 : 68;
|
||||
rdata->C = nrLDPC_TB_decoding_parameters->C;
|
||||
rdata->E = nrLDPC_TB_decoding_parameters->segments[r].E;
|
||||
rdata->A = nrLDPC_TB_decoding_parameters->A;
|
||||
rdata->Qm = nrLDPC_TB_decoding_parameters->Qm;
|
||||
rdata->K = nrLDPC_TB_decoding_parameters->K;
|
||||
rdata->Z = nrLDPC_TB_decoding_parameters->Z;
|
||||
rdata->F = nrLDPC_TB_decoding_parameters->F;
|
||||
rdata->rv_index = nrLDPC_TB_decoding_parameters->rv_index;
|
||||
rdata->tbslbrm = nrLDPC_TB_decoding_parameters->tbslbrm;
|
||||
rdata->abort_decode = nrLDPC_TB_decoding_parameters->abort_decode;
|
||||
rdata->d = nrLDPC_TB_decoding_parameters->segments[r].d;
|
||||
rdata->d_to_be_cleared = nrLDPC_TB_decoding_parameters->segments[r].d_to_be_cleared;
|
||||
rdata->c = nrLDPC_TB_decoding_parameters->segments[r].c;
|
||||
rdata->decodeSuccess = &nrLDPC_TB_decoding_parameters->segments[r].decodeSuccess;
|
||||
rdata->processedSegments = nrLDPC_TB_decoding_parameters->processedSegments;
|
||||
pushTpool(nrLDPC_slot_decoding_parameters->threadPool, req);
|
||||
LOG_D(PHY, "Added a block to decode, in pipe: %d\n", r);
|
||||
}
|
||||
return nrLDPC_TB_decoding_parameters->C;
|
||||
}
|
||||
|
||||
int32_t nrLDPC_coding_init(void){
|
||||
|
||||
char *segment_shlibversion = NULL;
|
||||
paramdef_t LoaderParams[] = {
|
||||
{"segment_shlibversion", NULL, 0, .strptr = &segment_shlibversion, .defstrval = "", TYPE_STRING, 0, NULL}
|
||||
};
|
||||
config_get(config_get_if(), LoaderParams, sizeofArray(LoaderParams), "nrLDPC_coding_demo");
|
||||
load_LDPClib(segment_shlibversion, &ldpc_interface_demo);
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
int32_t nrLDPC_coding_shutdown(void){
|
||||
|
||||
free_LDPClib(&ldpc_interface_demo);
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
int32_t nrLDPC_coding_decoder(nrLDPC_slot_decoding_parameters_t *nrLDPC_slot_decoding_parameters){
|
||||
|
||||
int nbDecode = 0;
|
||||
for (int pusch_id = 0; pusch_id < nrLDPC_slot_decoding_parameters->nb_TBs; pusch_id++) {
|
||||
nbDecode += nrLDPC_prepare_TB_decoding(nrLDPC_slot_decoding_parameters, pusch_id);
|
||||
}
|
||||
|
||||
return nbDecode;
|
||||
|
||||
}
|
||||
|
||||
218
openair1/PHY/CODING/nrLDPC_coding_interface_demo_encoder.c
Normal file
218
openair1/PHY/CODING/nrLDPC_coding_interface_demo_encoder.c
Normal file
@@ -0,0 +1,218 @@
|
||||
/*
|
||||
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||
* the OAI Public License, Version 1.0 (the "License"); you may not use this file
|
||||
* except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.openairinterface.org/?page_id=698
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*-------------------------------------------------------------------------------
|
||||
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
/*! \file PHY/CODING/nrLDPC_coding_interface_demo_encoder.c
|
||||
* \brief Top-level routines for implementing LDPC encoding of transport channels
|
||||
* \author H.Wang
|
||||
* \date 2018
|
||||
* \version 0.1
|
||||
* \company Eurecom
|
||||
* \email:
|
||||
* \note
|
||||
* \warning
|
||||
*/
|
||||
|
||||
#include "PHY/defs_gNB.h"
|
||||
#include "PHY/CODING/coding_extern.h"
|
||||
#include "PHY/CODING/coding_defs.h"
|
||||
#include "PHY/CODING/lte_interleaver_inline.h"
|
||||
#include "PHY/CODING/nrLDPC_coding_interface.h"
|
||||
#include "PHY/CODING/nrLDPC_extern.h"
|
||||
#include "PHY/NR_TRANSPORT/nr_transport_proto.h"
|
||||
#include "PHY/NR_TRANSPORT/nr_transport_common_proto.h"
|
||||
#include "PHY/NR_TRANSPORT/nr_dlsch.h"
|
||||
#include "SCHED_NR/sched_nr.h"
|
||||
#include "common/utils/LOG/vcd_signal_dumper.h"
|
||||
#include "common/utils/LOG/log.h"
|
||||
#include "common/utils/nr/nr_common.h"
|
||||
#include <syscall.h>
|
||||
#include <openair2/UTIL/OPT/opt.h>
|
||||
|
||||
//#define DEBUG_LDPC_ENCODING
|
||||
//#define DEBUG_LDPC_ENCODING_FREE 1
|
||||
|
||||
extern ldpc_interface_t ldpc_interface_demo;
|
||||
|
||||
typedef struct ldpc8blocks_args_s {
|
||||
nrLDPC_TB_encoding_parameters_t *nrLDPC_TB_encoding_parameters;
|
||||
encoder_implemparams_t impp;
|
||||
} ldpc8blocks_args_t;
|
||||
|
||||
static void ldpc8blocks_demo(void *p)
|
||||
{
|
||||
ldpc8blocks_args_t *args = (ldpc8blocks_args_t *)p;
|
||||
nrLDPC_TB_encoding_parameters_t *nrLDPC_TB_encoding_parameters = args->nrLDPC_TB_encoding_parameters;
|
||||
encoder_implemparams_t *impp = &args->impp;
|
||||
|
||||
uint8_t mod_order = nrLDPC_TB_encoding_parameters->Qm;
|
||||
uint16_t nb_rb = nrLDPC_TB_encoding_parameters->nb_rb;
|
||||
uint32_t A = nrLDPC_TB_encoding_parameters->A;
|
||||
|
||||
unsigned int G = nrLDPC_TB_encoding_parameters->G;
|
||||
LOG_D(PHY,"dlsch coding A %d Kr %d G %d (nb_rb %d, mod_order %d)\n",
|
||||
A,impp->K,G, nb_rb,(int)mod_order);
|
||||
// nrLDPC_encoder output is in "d"
|
||||
// let's make this interface happy!
|
||||
uint8_t tmp[8][68 * 384]__attribute__((aligned(32)));
|
||||
uint8_t *d[impp->n_segments];
|
||||
for (int rr=impp->macro_num*8, i=0; rr < impp->n_segments && rr < (impp->macro_num+1)*8; rr++,i++ )
|
||||
d[rr] = tmp[i];
|
||||
uint8_t *c[nrLDPC_TB_encoding_parameters->C];
|
||||
for (int r = 0; r < nrLDPC_TB_encoding_parameters->C; r++)
|
||||
c[r]=nrLDPC_TB_encoding_parameters->segments[r].c;
|
||||
ldpc_interface_demo.LDPCencoder(c, d, impp);
|
||||
// Compute where to place in output buffer that is concatenation of all segments
|
||||
uint32_t r_offset=0;
|
||||
for (int i=0; i < impp->macro_num*8; i++ )
|
||||
r_offset+=nrLDPC_TB_encoding_parameters->segments[i].E;
|
||||
for (int rr=impp->macro_num*8; rr < impp->n_segments && rr < (impp->macro_num+1)*8; rr++ ) {
|
||||
if (impp->F>0) {
|
||||
// writing into positions d[r][k-2Zc] as in clause 5.3.2 step 2) in 38.212
|
||||
memset(&d[rr][impp->K - impp->F - 2 * impp->Zc], NR_NULL, impp->F);
|
||||
}
|
||||
|
||||
#ifdef DEBUG_LDPC_ENCODING
|
||||
LOG_D(PHY,"rvidx in encoding = %d\n", rel15->rvIndex[0]);
|
||||
#endif
|
||||
uint32_t E = nrLDPC_TB_encoding_parameters->segments[rr].E;
|
||||
LOG_D(NR_PHY,
|
||||
"Rate Matching, Code segment %d/%d (coded bits (G) %u, E %d, Filler bits %d, Filler offset %d mod_order %d, nb_rb "
|
||||
"%d,nrOfLayer %d)...\n",
|
||||
rr,
|
||||
impp->n_segments,
|
||||
G,
|
||||
E,
|
||||
impp->F,
|
||||
impp->K - impp->F - 2 * impp->Zc,
|
||||
mod_order,
|
||||
nb_rb,
|
||||
nrLDPC_TB_encoding_parameters->nb_layers);
|
||||
|
||||
uint32_t Tbslbrm = nrLDPC_TB_encoding_parameters->tbslbrm;
|
||||
|
||||
uint8_t e[E];
|
||||
bzero (e, E);
|
||||
nr_rate_matching_ldpc(Tbslbrm,
|
||||
impp->BG,
|
||||
impp->Zc,
|
||||
d[rr],
|
||||
e,
|
||||
impp->n_segments,
|
||||
impp->F,
|
||||
impp->K - impp->F - 2 * impp->Zc,
|
||||
nrLDPC_TB_encoding_parameters->rv_index,
|
||||
E);
|
||||
if (impp->K - impp->F - 2 * impp->Zc > E) {
|
||||
LOG_E(PHY,
|
||||
"dlsch coding A %d Kr %d G %d (nb_rb %d, mod_order %d)\n",
|
||||
A,
|
||||
impp->K,
|
||||
G,
|
||||
nb_rb,
|
||||
(int)mod_order);
|
||||
|
||||
LOG_E(NR_PHY,
|
||||
"Rate Matching, Code segment %d/%d (coded bits (G) %u, E %d, Kr %d, Filler bits %d, Filler offset %d mod_order %d, "
|
||||
"nb_rb %d)...\n",
|
||||
rr,
|
||||
impp->n_segments,
|
||||
G,
|
||||
E,
|
||||
impp->K,
|
||||
impp->F,
|
||||
impp->K - impp->F - 2 * impp->Zc,
|
||||
mod_order,
|
||||
nb_rb);
|
||||
}
|
||||
#ifdef DEBUG_LDPC_ENCODING
|
||||
|
||||
for (int i =0; i<16; i++)
|
||||
printf("output ratematching e[%d]= %d r_offset %u\n", i,e[i], r_offset);
|
||||
|
||||
#endif
|
||||
nr_interleaving_ldpc(E,
|
||||
mod_order,
|
||||
e,
|
||||
impp->output+r_offset);
|
||||
#ifdef DEBUG_LDPC_ENCODING
|
||||
|
||||
for (int i =0; i<16; i++)
|
||||
printf("output interleaving f[%d]= %d r_offset %u\n", i,impp->output[i+r_offset], r_offset);
|
||||
|
||||
if (r==impp->n_segments-1)
|
||||
write_output("enc_output.m","enc",impp->output,G,1,4);
|
||||
|
||||
#endif
|
||||
r_offset += E;
|
||||
}
|
||||
}
|
||||
|
||||
static int nrLDPC_prepare_TB_encoding(nrLDPC_slot_encoding_parameters_t *nrLDPC_slot_encoding_parameters, int dlsch_id)
|
||||
{
|
||||
nrLDPC_TB_encoding_parameters_t *nrLDPC_TB_encoding_parameters = &nrLDPC_slot_encoding_parameters->TBs[dlsch_id];
|
||||
|
||||
encoder_implemparams_t impp;
|
||||
|
||||
impp.n_segments = nrLDPC_TB_encoding_parameters->C;
|
||||
impp.tinput = nrLDPC_slot_encoding_parameters->tinput;
|
||||
impp.tprep = nrLDPC_slot_encoding_parameters->tprep;
|
||||
impp.tparity = nrLDPC_slot_encoding_parameters->tparity;
|
||||
impp.toutput = nrLDPC_slot_encoding_parameters->toutput;
|
||||
impp.Kb = nrLDPC_TB_encoding_parameters->Kb;
|
||||
impp.Zc = nrLDPC_TB_encoding_parameters->Z;
|
||||
NR_DL_gNB_HARQ_t harq;
|
||||
impp.harq = &harq;
|
||||
impp.BG = nrLDPC_TB_encoding_parameters->BG;
|
||||
impp.output = nrLDPC_TB_encoding_parameters->segments->output;
|
||||
impp.K = nrLDPC_TB_encoding_parameters->K;
|
||||
impp.F = nrLDPC_TB_encoding_parameters->F;
|
||||
impp.Qm = nrLDPC_TB_encoding_parameters->Qm;
|
||||
impp.Tbslbrm = nrLDPC_TB_encoding_parameters->tbslbrm;
|
||||
impp.G = nrLDPC_TB_encoding_parameters->G;
|
||||
for (int r = 0; r < nrLDPC_TB_encoding_parameters->C; r++) {
|
||||
impp.perCB[r].E_cb = nrLDPC_TB_encoding_parameters->segments[r].E;
|
||||
}
|
||||
impp.rv = nrLDPC_TB_encoding_parameters->rv_index;
|
||||
|
||||
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(ldpc8blocks_args_t), j, nrLDPC_slot_encoding_parameters->respEncode, ldpc8blocks_demo);
|
||||
ldpc8blocks_args_t *perJobImpp = (ldpc8blocks_args_t *)NotifiedFifoData(req);
|
||||
impp.macro_num = j;
|
||||
perJobImpp->impp = impp;
|
||||
perJobImpp->nrLDPC_TB_encoding_parameters = nrLDPC_TB_encoding_parameters;
|
||||
pushTpool(nrLDPC_slot_encoding_parameters->threadPool, req);
|
||||
nbJobs++;
|
||||
}
|
||||
return nbJobs;
|
||||
}
|
||||
|
||||
int nrLDPC_coding_encoder(nrLDPC_slot_encoding_parameters_t *nrLDPC_slot_encoding_parameters)
|
||||
{
|
||||
|
||||
int nbEncode = 0;
|
||||
for (int dlsch_id = 0; dlsch_id < nrLDPC_slot_encoding_parameters->nb_TBs; dlsch_id++) {
|
||||
nbEncode += nrLDPC_prepare_TB_encoding(nrLDPC_slot_encoding_parameters, dlsch_id);
|
||||
}
|
||||
|
||||
return nbEncode;
|
||||
|
||||
}
|
||||
80
openair1/PHY/CODING/nrLDPC_coding_interface_load.c
Normal file
80
openair1/PHY/CODING/nrLDPC_coding_interface_load.c
Normal file
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
* 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 nrLDPC_load.c
|
||||
* \brief: load library implementing coding/decoding algorithms
|
||||
* \author Francois TABURET
|
||||
* \date 2020
|
||||
* \version 0.1
|
||||
* \company NOKIA BellLabs France
|
||||
* \email: francois.taburet@nokia-bell-labs.com
|
||||
* \note
|
||||
* \warning
|
||||
*/
|
||||
#define _GNU_SOURCE
|
||||
#include <sys/types.h>
|
||||
#include <stdlib.h>
|
||||
#include <malloc.h>
|
||||
#include "assertions.h"
|
||||
#include "common/utils/LOG/log.h"
|
||||
#include "PHY/CODING/nrLDPC_coding_interface.h"
|
||||
#include "PHY/CODING/nrLDPC_extern.h"
|
||||
#include "common/config/config_userapi.h"
|
||||
#include "common/utils/load_module_shlib.h"
|
||||
|
||||
/* arguments used when called from phy simulators exec's which do not use the config module */
|
||||
/* arg is used to initialize the config module so that the loader works as expected */
|
||||
char *arguments_phy_simulators[64]={"ldpctest",NULL};
|
||||
|
||||
int load_nrLDPC_coding_interface(char *version, nrLDPC_coding_interface_t *itf)
|
||||
{
|
||||
char *ptr = (char *)config_get_if();
|
||||
char libname[64] = "ldpc";
|
||||
|
||||
if (ptr == NULL) { // phy simulators, config module possibly not loaded
|
||||
uniqCfg = load_configmodule(1, arguments_phy_simulators, CONFIG_ENABLECMDLINEONLY);
|
||||
logInit();
|
||||
}
|
||||
/* function description array, to be used when loading the encoding/decoding shared lib */
|
||||
loader_shlibfunc_t shlib_fdesc[] = {{.fname = "nrLDPC_coding_init"},
|
||||
{.fname = "nrLDPC_coding_shutdown"},
|
||||
{.fname = "nrLDPC_coding_decoder"},
|
||||
{.fname = "nrLDPC_coding_encoder"}};
|
||||
int ret;
|
||||
ret = load_module_version_shlib(libname, version, shlib_fdesc, sizeofArray(shlib_fdesc), NULL);
|
||||
if(ret < 0){
|
||||
LOG_D(PHY, "NR ULSCH decoding module unavailable");
|
||||
return ret;
|
||||
}
|
||||
itf->nrLDPC_coding_init = (nrLDPC_coding_init_t *)shlib_fdesc[0].fptr;
|
||||
itf->nrLDPC_coding_shutdown = (nrLDPC_coding_shutdown_t *)shlib_fdesc[1].fptr;
|
||||
itf->nrLDPC_coding_decoder = (nrLDPC_coding_decoder_t *)shlib_fdesc[2].fptr;
|
||||
itf->nrLDPC_coding_encoder = (nrLDPC_coding_encoder_t *)shlib_fdesc[3].fptr;
|
||||
|
||||
AssertFatal(itf->nrLDPC_coding_init() == 0, "error starting LDPC library %s %s\n", libname, version);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int free_nrLDPC_coding_interface(nrLDPC_coding_interface_t *interface)
|
||||
{
|
||||
return interface->nrLDPC_coding_shutdown();
|
||||
}
|
||||
416
openair1/PHY/CODING/nrLDPC_coding_interface_xdma.c
Normal file
416
openair1/PHY/CODING/nrLDPC_coding_interface_xdma.c
Normal file
@@ -0,0 +1,416 @@
|
||||
/*
|
||||
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||
* the OAI Public License, Version 1.0 (the "License"); you may not use this
|
||||
* file except in compliance with the License. You may obtain a copy of the
|
||||
* License at
|
||||
*
|
||||
* http://www.openairinterface.org/?page_id=698
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* -------------------------------------------------------------------------------
|
||||
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
/*! \file PHY/NR_TRANSPORT/nr_ulsch_decoding.c
|
||||
* \brief Top-level routines for decoding LDPC (ULSCH) transport channels
|
||||
* from 38.212, V15.4.0 2018-12 \author Ahmed Hussein \date 2019 \version 0.1
|
||||
* \company Fraunhofer IIS
|
||||
* \email: ahmed.hussein@iis.fraunhofer.de
|
||||
* \note
|
||||
* \warning
|
||||
*/
|
||||
|
||||
// [from gNB coding]
|
||||
#include <syscall.h>
|
||||
|
||||
#include "PHY/CODING/coding_defs.h"
|
||||
#include "PHY/CODING/coding_extern.h"
|
||||
#include "PHY/CODING/lte_interleaver_inline.h"
|
||||
#include "PHY/CODING/nrLDPC_decoder/nrLDPC_decoder_offload_xdma.h"
|
||||
#include "PHY/CODING/nrLDPC_extern.h"
|
||||
#include "PHY/NR_TRANSPORT/nr_dlsch.h"
|
||||
#include "PHY/NR_TRANSPORT/nr_transport_common_proto.h"
|
||||
#include "PHY/NR_TRANSPORT/nr_transport_proto.h"
|
||||
#include "PHY/NR_TRANSPORT/nr_ulsch.h"
|
||||
#include "PHY/defs_gNB.h"
|
||||
#include "SCHED_NR/fapi_nr_l1.h"
|
||||
#include "SCHED_NR/sched_nr.h"
|
||||
#include "common/utils/LOG/log.h"
|
||||
#include "common/utils/LOG/vcd_signal_dumper.h"
|
||||
#include "defs.h"
|
||||
// #define DEBUG_ULSCH_DECODING
|
||||
// #define gNB_DEBUG_TRACE
|
||||
|
||||
#define OAI_UL_LDPC_MAX_NUM_LLR 27000 // 26112 // NR_LDPC_NCOL_BG1*NR_LDPC_ZMAX = 68*384
|
||||
// #define DEBUG_CRC
|
||||
#ifdef DEBUG_CRC
|
||||
#define PRINT_CRC_CHECK(a) a
|
||||
#else
|
||||
#define PRINT_CRC_CHECK(a)
|
||||
#endif
|
||||
|
||||
// extern double cpuf;
|
||||
|
||||
#include "nfapi/open-nFAPI/nfapi/public_inc/nfapi_interface.h"
|
||||
#include "nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface.h"
|
||||
|
||||
#include "nrLDPC_coding_interface.h"
|
||||
|
||||
#define DEMO_LDPCLIB_SUFFIX ""
|
||||
|
||||
// Global var to limit the rework of the dirty legacy code
|
||||
ldpc_interface_t ldpc_interface_demo;
|
||||
int num_threads_prepare_max = 0;
|
||||
|
||||
/*!
|
||||
* \typedef args_fpga_decode_prepare_t
|
||||
* \struct args_fpga_decode_prepare_s
|
||||
* \brief arguments structure for passing arguments to the nr_ulsch_FPGA_decoding_prepare_blocks function
|
||||
*/
|
||||
typedef struct args_fpga_decode_prepare_s {
|
||||
nrLDPC_TB_decoding_parameters_t *TB_params; /*!< transport blocks parameters */
|
||||
|
||||
int8_t *multi_indata; /*!< pointer to the head of the block destination array that is then passed to the FPGA decoding */
|
||||
int no_iteration_ldpc; /*!< pointer to the number of iteration set by this function */
|
||||
uint32_t r_first; /*!< index of the first block to be prepared within this function */
|
||||
uint32_t r_span; /*!< number of blocks to be prepared within this function */
|
||||
int r_offset; /*!< r index expressed in bits */
|
||||
int input_CBoffset; /*!< */
|
||||
int kc; /*!< */
|
||||
int K_bits_F; /*!< */
|
||||
} args_fpga_decode_prepare_t;
|
||||
|
||||
int32_t nrLDPC_coding_init(void);
|
||||
int32_t nrLDPC_coding_shutdown(void);
|
||||
int32_t nrLDPC_coding_decoder(nrLDPC_slot_decoding_parameters_t *slot_params, int frame_rx, int slot_rx);
|
||||
// int32_t nrLDPC_coding_encoder(void);
|
||||
int decoder_xdma(nrLDPC_TB_decoding_parameters_t *TB_params,
|
||||
int frame_rx,
|
||||
int slot_rx,
|
||||
tpool_t *ldpc_threadPool,
|
||||
notifiedFIFO_t *ldpc_respDecode);
|
||||
void nr_ulsch_FPGA_decoding_prepare_blocks(void *args);
|
||||
|
||||
int32_t nrLDPC_coding_init(void)
|
||||
{
|
||||
paramdef_t LoaderParams[] = {{"num_threads_prepare", NULL, 0, .iptr = &num_threads_prepare_max, .defintval = 0, TYPE_INT, 0, NULL}};
|
||||
config_get(config_get_if(), LoaderParams, sizeofArray(LoaderParams), "nrLDPC_coding_xdma");
|
||||
AssertFatal(num_threads_prepare_max != 0, "nrLDPC_coding_xdma.num_threads_prepare was not provided");
|
||||
|
||||
load_LDPClib(DEMO_LDPCLIB_SUFFIX, &ldpc_interface_demo);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t nrLDPC_coding_shutdown(void)
|
||||
{
|
||||
free_LDPClib(&ldpc_interface_demo);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t nrLDPC_coding_decoder(nrLDPC_slot_decoding_parameters_t *slot_params, int frame_rx, int slot_rx)
|
||||
{
|
||||
int nbDecode = 0;
|
||||
for (int ULSCH_id = 0; ULSCH_id < slot_params->nb_TBs; ULSCH_id++)
|
||||
nbDecode += decoder_xdma(&slot_params->TBs[ULSCH_id], frame_rx, slot_rx, slot_params->threadPool, slot_params->respDecode);
|
||||
return nbDecode;
|
||||
}
|
||||
|
||||
/*
|
||||
int32_t nrLDPC_coding_encoder(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
*/
|
||||
|
||||
int decoder_xdma(nrLDPC_TB_decoding_parameters_t *TB_params,
|
||||
int frame_rx,
|
||||
int slot_rx,
|
||||
tpool_t *ldpc_threadPool,
|
||||
notifiedFIFO_t *ldpc_respDecode)
|
||||
{
|
||||
const uint32_t Kr = TB_params->K;
|
||||
const uint32_t Kr_bytes = Kr >> 3;
|
||||
const int kc = TB_params->BG == 2 ? 52 : 68;
|
||||
int r_offset = 0, offset = 0;
|
||||
int K_bits_F = Kr - TB_params->F;
|
||||
|
||||
// FPGA parameter preprocessing
|
||||
static int8_t multi_indata[27000 * 25]; // FPGA input data
|
||||
static int8_t multi_outdata[1100 * 25]; // FPGA output data
|
||||
|
||||
int bg_len = TB_params->BG == 1 ? 22 : 10;
|
||||
|
||||
// Calc input CB offset
|
||||
int input_CBoffset = TB_params->Z * kc * 8;
|
||||
if ((input_CBoffset & 0x7F) == 0)
|
||||
input_CBoffset = input_CBoffset / 8;
|
||||
else
|
||||
input_CBoffset = 16 * ((input_CBoffset / 128) + 1);
|
||||
|
||||
DecIFConf dec_conf;
|
||||
dec_conf.Zc = TB_params->Z;
|
||||
dec_conf.BG = TB_params->BG;
|
||||
dec_conf.max_iter = TB_params->max_ldpc_iterations;
|
||||
dec_conf.numCB = TB_params->C;
|
||||
// input soft bits length, Zc x 66 - length of filler bits
|
||||
dec_conf.numChannelLls = (K_bits_F - 2 * TB_params->Z) + (kc * TB_params->Z - Kr);
|
||||
// filler bits length
|
||||
dec_conf.numFillerBits = TB_params->F;
|
||||
dec_conf.max_schedule = 0;
|
||||
dec_conf.SetIdx = 12;
|
||||
dec_conf.nRows = (dec_conf.BG == 1) ? 46 : 42;
|
||||
|
||||
int out_CBoffset = dec_conf.Zc * bg_len;
|
||||
if ((out_CBoffset & 0x7F) == 0)
|
||||
out_CBoffset = out_CBoffset / 8;
|
||||
else
|
||||
out_CBoffset = 16 * ((out_CBoffset / 128) + 1);
|
||||
|
||||
#ifdef LDPC_DATA
|
||||
printf("\n------------------------\n");
|
||||
printf("BG:\t\t%d\n", dec_conf.BG);
|
||||
printf("TB_params->C: %d\n", TB_params->C);
|
||||
printf("TB_params->K: %d\n", TB_params->K);
|
||||
printf("TB_params->Z: %d\n", TB_params->Z);
|
||||
printf("TB_params->F: %d\n", TB_params->F);
|
||||
printf("numChannelLls:\t %d = (%d - 2 * %d) + (%d * %d - %d)\n",
|
||||
dec_conf.numChannelLls,
|
||||
K_bits_F,
|
||||
TB_params->Z,
|
||||
kc,
|
||||
TB_params->Z,
|
||||
Kr);
|
||||
printf("numFillerBits:\t %d\n", TB_params->F);
|
||||
printf("------------------------\n");
|
||||
// ===================================
|
||||
// debug mode
|
||||
// ===================================
|
||||
FILE *fptr_llr, *fptr_ldpc;
|
||||
fptr_llr = fopen("../../../cmake_targets/log/ulsim_ldpc_llr.txt", "w");
|
||||
fptr_ldpc = fopen("../../../cmake_targets/log/ulsim_ldpc_output.txt", "w");
|
||||
// ===================================
|
||||
#endif
|
||||
|
||||
int length_dec = lenWithCrc(TB_params->C, TB_params->A);
|
||||
uint8_t crc_type = crcType(TB_params->C, TB_params->A);
|
||||
int no_iteration_ldpc = 2;
|
||||
|
||||
uint32_t num_threads_prepare = 0;
|
||||
uint32_t r_remaining = 0;
|
||||
|
||||
// start the prepare jobs
|
||||
for (uint32_t r = 0; r < TB_params->C; r++) {
|
||||
nrLDPC_segment_decoding_parameters_t *segment_params = &TB_params->segments[r];
|
||||
if (r_remaining == 0) {
|
||||
void (*nr_ulsch_FPGA_decoding_prepare_blocks_ptr)(void *) = &nr_ulsch_FPGA_decoding_prepare_blocks;
|
||||
// TODO: int nr_tti_rx = 0;
|
||||
union ldpcReqUnion id = {.s = {TB_params->rnti, frame_rx, slot_rx, 0, 0}};
|
||||
notifiedFIFO_elt_t *req =
|
||||
newNotifiedFIFO_elt(sizeof(args_fpga_decode_prepare_t), id.p, ldpc_respDecode, nr_ulsch_FPGA_decoding_prepare_blocks_ptr);
|
||||
args_fpga_decode_prepare_t *args = (args_fpga_decode_prepare_t *)NotifiedFifoData(req);
|
||||
args->TB_params = TB_params;
|
||||
args->multi_indata = multi_indata;
|
||||
args->no_iteration_ldpc = no_iteration_ldpc;
|
||||
args->r_first = r;
|
||||
uint32_t r_span_max = ((TB_params->C - r) % (num_threads_prepare_max - num_threads_prepare)) == 0
|
||||
? (TB_params->C - r) / (num_threads_prepare_max - num_threads_prepare)
|
||||
: ((TB_params->C - r) / (num_threads_prepare_max - num_threads_prepare)) + 1;
|
||||
uint32_t r_span = TB_params->C - r < r_span_max ? TB_params->C - r : r_span_max;
|
||||
args->r_span = r_span;
|
||||
args->r_offset = r_offset;
|
||||
args->input_CBoffset = input_CBoffset;
|
||||
args->kc = kc;
|
||||
args->K_bits_F = K_bits_F;
|
||||
|
||||
r_remaining = r_span;
|
||||
pushTpool(ldpc_threadPool, req);
|
||||
LOG_D(PHY, "Added %d block(s) to prepare for decoding, in pipe: %d to %d\n", r_span, r, r + r_span - 1);
|
||||
num_threads_prepare++;
|
||||
}
|
||||
r_offset += segment_params->E;
|
||||
offset += (Kr_bytes - (TB_params->F >> 3) - ((TB_params->C > 1) ? 3 : 0));
|
||||
r_remaining -= 1;
|
||||
}
|
||||
|
||||
// reset offset in order to properly fill the output array later
|
||||
offset = 0;
|
||||
|
||||
// wait for the prepare jobs to complete
|
||||
while (num_threads_prepare > 0) {
|
||||
notifiedFIFO_elt_t *req = (notifiedFIFO_elt_t *)pullTpool(ldpc_respDecode, ldpc_threadPool);
|
||||
if (req == NULL)
|
||||
LOG_E(PHY, "FPGA decoding preparation: pullTpool returned NULL\n");
|
||||
args_fpga_decode_prepare_t *args = (args_fpga_decode_prepare_t *)NotifiedFifoData(req);
|
||||
if (args->no_iteration_ldpc > TB_params->max_ldpc_iterations)
|
||||
no_iteration_ldpc = TB_params->max_ldpc_iterations + 1;
|
||||
num_threads_prepare -= 1;
|
||||
}
|
||||
|
||||
// launch decode with FPGA
|
||||
LOG_I(PHY, "Run the LDPC ------[FPGA version]------\n");
|
||||
//==================================================================
|
||||
// Xilinx FPGA LDPC decoding function -> nrLDPC_decoder_FPGA_PYM()
|
||||
//==================================================================
|
||||
// start_meas(&phy_vars_gNB->ulsch_ldpc_decoding_stats);
|
||||
nrLDPC_decoder_FPGA_PYM((int8_t *)&multi_indata[0], (int8_t *)&multi_outdata[0], dec_conf);
|
||||
// printf("Xilinx FPGA -> CB = %d\n", harq_process->C);
|
||||
// nrLDPC_decoder_FPGA_PYM((int8_t *)&temp_multi_indata[0], (int8_t *)&multi_outdata[0], dec_conf);
|
||||
// stop_meas(&phy_vars_gNB->ulsch_ldpc_decoding_stats);
|
||||
|
||||
*TB_params->processedSegments = 0;
|
||||
for (uint32_t r = 0; r < TB_params->C; r++) {
|
||||
// ------------------------------------------------------------
|
||||
// --------------------- copy FPGA output ---------------------
|
||||
// ------------------------------------------------------------
|
||||
nrLDPC_segment_decoding_parameters_t *segment_params = &TB_params->segments[r];
|
||||
if (check_crc((uint8_t *)multi_outdata, length_dec, crc_type)) {
|
||||
#ifdef DEBUG_CRC
|
||||
LOG_I(PHY, "Segment %d CRC OK\n", r);
|
||||
#endif
|
||||
no_iteration_ldpc = 2;
|
||||
} else {
|
||||
#ifdef DEBUG_CRC
|
||||
LOG_I(PHY, "segment %d CRC NOK\n", r);
|
||||
#endif
|
||||
no_iteration_ldpc = TB_params->max_ldpc_iterations + 1;
|
||||
}
|
||||
for (int i = 0; i < out_CBoffset; i++) {
|
||||
segment_params->c[i] = (uint8_t)multi_outdata[i + r * out_CBoffset];
|
||||
}
|
||||
segment_params->decodeSuccess = (no_iteration_ldpc <= TB_params->max_ldpc_iterations);
|
||||
if (segment_params->decodeSuccess) {
|
||||
*TB_params->processedSegments = *TB_params->processedSegments + 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \fn nr_ulsch_FPGA_decoding_prepare_blocks(void *args)
|
||||
* \brief prepare blocks for LDPC decoding on FPGA
|
||||
*
|
||||
* \param args pointer to the arguments of the function in a structure of type args_fpga_decode_prepare_t
|
||||
*/
|
||||
void nr_ulsch_FPGA_decoding_prepare_blocks(void *args)
|
||||
{
|
||||
// extract the arguments
|
||||
args_fpga_decode_prepare_t *arguments = (args_fpga_decode_prepare_t *)args;
|
||||
|
||||
nrLDPC_TB_decoding_parameters_t *TB_params = arguments->TB_params;
|
||||
|
||||
uint8_t Qm = TB_params->Qm;
|
||||
|
||||
uint8_t BG = TB_params->BG;
|
||||
uint8_t rv_index = TB_params->rv_index;
|
||||
uint8_t max_ldpc_iterations = TB_params->max_ldpc_iterations;
|
||||
|
||||
uint32_t tbslbrm = TB_params->tbslbrm;
|
||||
uint32_t Kr = TB_params->K;
|
||||
uint32_t Z = TB_params->Z;
|
||||
uint32_t F = TB_params->F;
|
||||
|
||||
uint32_t C = TB_params->C;
|
||||
|
||||
nrLDPC_segment_decoding_parameters_t *segment_params = &TB_params->segments[0];
|
||||
|
||||
short *ulsch_llr = segment_params->llr;
|
||||
|
||||
int8_t *multi_indata = arguments->multi_indata;
|
||||
int no_iteration_ldpc = arguments->no_iteration_ldpc;
|
||||
uint32_t r_first = arguments->r_first;
|
||||
uint32_t r_span = arguments->r_span;
|
||||
int r_offset = arguments->r_offset;
|
||||
int input_CBoffset = arguments->input_CBoffset;
|
||||
int kc = arguments->kc;
|
||||
int K_bits_F = arguments->K_bits_F;
|
||||
|
||||
int16_t z[68 * 384 + 16] __attribute__((aligned(16)));
|
||||
simde__m128i *pv = (simde__m128i *)&z;
|
||||
|
||||
// the function processes r_span blocks starting from block at index r_first in ulsch_llr
|
||||
for (uint32_t r = r_first; r < (r_first + r_span); r++) {
|
||||
nrLDPC_segment_decoding_parameters_t *segment_params = &TB_params->segments[r];
|
||||
// ----------------------- FPGA pre process ------------------------
|
||||
simde__m128i ones = simde_mm_set1_epi8(255); // Generate a vector with all elements set to 255
|
||||
simde__m128i *temp_multi_indata = (simde__m128i *)&multi_indata[r * input_CBoffset];
|
||||
// -----------------------------------------------------------------
|
||||
|
||||
// code blocks after bit selection in rate matching for LDPC code (38.212 V15.4.0 section 5.4.2.1)
|
||||
int16_t harq_e[segment_params->E];
|
||||
// -------------------------------------------------------------------------------------------
|
||||
// deinterleaving
|
||||
// -------------------------------------------------------------------------------------------
|
||||
// start_meas(&phy_vars_gNB->ulsch_deinterleaving_stats);
|
||||
nr_deinterleaving_ldpc(segment_params->E, Qm, harq_e, ulsch_llr + r_offset);
|
||||
// stop_meas(&phy_vars_gNB->ulsch_deinterleaving_stats);
|
||||
// -------------------------------------------------------------------------------------------
|
||||
// dematching
|
||||
// -------------------------------------------------------------------------------------------
|
||||
// start_meas(&phy_vars_gNB->ulsch_rate_unmatching_stats);
|
||||
if (nr_rate_matching_ldpc_rx(tbslbrm,
|
||||
BG,
|
||||
Z,
|
||||
segment_params->d,
|
||||
harq_e,
|
||||
C,
|
||||
rv_index,
|
||||
*segment_params->d_to_be_cleared,
|
||||
segment_params->E,
|
||||
F,
|
||||
Kr - F - 2 * Z)
|
||||
== -1) {
|
||||
// stop_meas(&phy_vars_gNB->ulsch_rate_unmatching_stats);
|
||||
LOG_E(PHY, "ulsch_decoding.c: Problem in rate_matching\n");
|
||||
no_iteration_ldpc = max_ldpc_iterations + 1;
|
||||
arguments->no_iteration_ldpc = no_iteration_ldpc;
|
||||
return;
|
||||
} else {
|
||||
// stop_meas(&phy_vars_gNB->ulsch_rate_unmatching_stats);
|
||||
}
|
||||
|
||||
*segment_params->d_to_be_cleared = false;
|
||||
|
||||
memset(segment_params->c, 0, Kr >> 3);
|
||||
|
||||
// set first 2*Z_c bits to zeros
|
||||
memset(&z[0], 0, 2 * Z * sizeof(int16_t));
|
||||
// set Filler bits
|
||||
memset((&z[0] + K_bits_F), 127, F * sizeof(int16_t));
|
||||
// Move coded bits before filler bits
|
||||
memcpy((&z[0] + 2 * Z), segment_params->d, (K_bits_F - 2 * Z) * sizeof(int16_t));
|
||||
// skip filler bits
|
||||
memcpy((&z[0] + Kr), segment_params->d + (Kr - 2 * Z), (kc * Z - Kr) * sizeof(int16_t));
|
||||
|
||||
// Saturate coded bits before decoding into 8 bits values
|
||||
for (int i = 0, j = 0; j < ((kc * Z) >> 4); i += 2, j++) {
|
||||
temp_multi_indata[j] =
|
||||
simde_mm_xor_si128(simde_mm_packs_epi16(pv[i], pv[i + 1]),
|
||||
simde_mm_cmpeq_epi32(ones,
|
||||
ones)); // Perform NOT operation and write the result to temp_multi_indata[j]
|
||||
}
|
||||
|
||||
// the last bytes before reaching "kc * harq_process->Z" should not be written 128 bits at a time to avoid overwritting the
|
||||
// following block in multi_indata
|
||||
simde__m128i tmp =
|
||||
simde_mm_xor_si128(simde_mm_packs_epi16(pv[2 * ((kc * Z) >> 4)], pv[2 * ((kc * Z) >> 4) + 1]),
|
||||
simde_mm_cmpeq_epi32(ones,
|
||||
ones)); // Perform NOT operation and write the result to temp_multi_indata[j]
|
||||
int8_t *tmp_p = (int8_t *)&tmp;
|
||||
for (int i = 0, j = ((kc * Z) & 0xfffffff0); j < kc * Z; i++, j++) {
|
||||
multi_indata[r * input_CBoffset + j] = tmp_p[i];
|
||||
}
|
||||
|
||||
r_offset += segment_params->E;
|
||||
}
|
||||
|
||||
arguments->no_iteration_ldpc = no_iteration_ldpc;
|
||||
}
|
||||
1108
openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_coding_t2.c
Normal file
1108
openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_coding_t2.c
Normal file
File diff suppressed because it is too large
Load Diff
966
openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_decoder_offload_xdma.c
Normal file
966
openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_decoder_offload_xdma.c
Normal file
@@ -0,0 +1,966 @@
|
||||
/*
|
||||
* This file is part of the Xilinx DMA IP Core driver tools for Linux
|
||||
*
|
||||
* Copyright (c) 2016-present, Xilinx, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under both the BSD-style license (found in the
|
||||
* LICENSE file in the root directory of this source tree) and the GPLv2 (found
|
||||
* in the COPYING file in the root directory of this source tree).
|
||||
* You may select, at your option, one of the above-listed licenses.
|
||||
*/
|
||||
|
||||
#define _BSD_SOURCE
|
||||
#define _XOPEN_SOURCE 500
|
||||
|
||||
#include <assert.h>
|
||||
#include <fcntl.h>
|
||||
#include <getopt.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <time.h>
|
||||
#include <byteswap.h>
|
||||
#include <signal.h>
|
||||
#include <ctype.h>
|
||||
#include <termios.h>
|
||||
|
||||
#include <sys/mman.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "xdma_diag.h"
|
||||
#include "nrLDPC_decoder_offload_xdma.h"
|
||||
|
||||
typedef unsigned long long U64;
|
||||
static struct option const long_opts[] = {{"device", required_argument, NULL, 'd'},
|
||||
{"address", required_argument, NULL, 'a'},
|
||||
{"size", required_argument, NULL, 's'},
|
||||
{"offset", required_argument, NULL, 'o'},
|
||||
{"count", required_argument, NULL, 'c'},
|
||||
{"data infile", required_argument, NULL, 'f'},
|
||||
{"data outfile", required_argument, NULL, 'w'},
|
||||
{"help", no_argument, NULL, 'h'},
|
||||
{"verbose", no_argument, NULL, 'v'},
|
||||
{0, 0, 0, 0}};
|
||||
#if 0
|
||||
/* ltoh: little to host */
|
||||
/* htol: little to host */
|
||||
#if __BYTE_ORDER == __LITTLE_ENDIAN
|
||||
#define ltohl(x) (x)
|
||||
#define ltohs(x) (x)
|
||||
#define htoll(x) (x)
|
||||
#define htols(x) (x)
|
||||
#elif __BYTE_ORDER == __BIG_ENDIAN
|
||||
#define ltohl(x) __bswap_32(x)
|
||||
#define ltohs(x) __bswap_16(x)
|
||||
#define htoll(x) __bswap_32(x)
|
||||
#define htols(x) __bswap_16(x)
|
||||
#endif
|
||||
|
||||
#define FATAL \
|
||||
do { \
|
||||
fprintf(stderr, "Error at line %d, file %s (%d) [%s]\n", __LINE__, __FILE__, errno, strerror(errno)); \
|
||||
exit(1); \
|
||||
} while (0)
|
||||
|
||||
#define MAP_SIZE (32 * 1024UL)
|
||||
#define MAP_MASK (MAP_SIZE - 1)
|
||||
|
||||
#define DEVICE_NAME_DEFAULT_READ "/dev/xdma0_c2h_1"
|
||||
#define DEVICE_NAME_DEFAULT_WRITE "/dev/xdma0_h2c_1"
|
||||
#define SIZE_DEFAULT (32)
|
||||
#define COUNT_DEFAULT (1)
|
||||
|
||||
#define OFFSET_DEC_IN 0x0000
|
||||
#define OFFSET_DEC_OUT 0x0004
|
||||
#define OFFSET_ENC_IN 0x0008
|
||||
#define OFFSET_ENC_OUT 0x000c
|
||||
#define OFFSET_RESET 0x0020
|
||||
|
||||
#define CB_PROCESS_NUMBER 12 // add by JW
|
||||
#endif
|
||||
void* map_base;
|
||||
int fd;
|
||||
int fd_enc_write, fd_enc_read;
|
||||
int fd_dec_write, fd_dec_read;
|
||||
char *allocated_write, *allocated_read;
|
||||
|
||||
// dma_from_device.c
|
||||
#if 0
|
||||
int test_dma_end_read();
|
||||
int test_dma_enc_write();
|
||||
#endif
|
||||
static int no_write = 0;
|
||||
|
||||
// [Start] #include "dma_utils.c" ===================================
|
||||
|
||||
/*
|
||||
* man 2 write:
|
||||
* On Linux, write() (and similar system calls) will transfer at most
|
||||
* 0x7ffff000 (2,147,479,552) bytes, returning the number of bytes
|
||||
* actually transferred. (This is true on both 32-bit and 64-bit
|
||||
* systems.)
|
||||
*/
|
||||
|
||||
#define RW_MAX_SIZE 0x7ffff000
|
||||
|
||||
int verbose = 0;
|
||||
|
||||
uint64_t getopt_integer(char* optarg)
|
||||
{
|
||||
int rc;
|
||||
uint64_t value;
|
||||
|
||||
rc = sscanf(optarg, "0x%lx", &value);
|
||||
if (rc <= 0)
|
||||
rc = sscanf(optarg, "%lu", &value);
|
||||
// printf("sscanf() = %d, value = 0x%lx\n", rc, value);
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
ssize_t read_to_buffer(char* fname, int fd, char* buffer, uint64_t size, uint64_t base)
|
||||
{
|
||||
ssize_t rc;
|
||||
uint64_t count = 0;
|
||||
char* buf = buffer;
|
||||
off_t offset = base;
|
||||
|
||||
while (count < size) {
|
||||
uint64_t bytes = size - count;
|
||||
|
||||
if (bytes > RW_MAX_SIZE)
|
||||
bytes = RW_MAX_SIZE;
|
||||
|
||||
if (offset) {
|
||||
rc = lseek(fd, offset, SEEK_SET);
|
||||
if (rc != offset) {
|
||||
fprintf(stderr, "%s, seek off 0x%lx != 0x%lx.\n", fname, rc, offset);
|
||||
perror("seek file");
|
||||
return -EIO;
|
||||
}
|
||||
}
|
||||
/* read data from file into memory buffer */
|
||||
rc = read(fd, buf, bytes);
|
||||
|
||||
if (rc != bytes) {
|
||||
fprintf(stderr, "%s, R off 0x%lx, 0x%lx != 0x%lx.\n", fname, count, rc, bytes);
|
||||
perror("read file");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
count += bytes;
|
||||
buf += bytes;
|
||||
offset += bytes;
|
||||
}
|
||||
|
||||
if (count != size) {
|
||||
fprintf(stderr, "%s, R failed 0x%lx != 0x%lx.\n", fname, count, size);
|
||||
return -EIO;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
ssize_t write_from_buffer(char* fname, int fd, char* buffer, uint64_t size, uint64_t base)
|
||||
{
|
||||
ssize_t rc;
|
||||
uint64_t count = 0;
|
||||
char* buf = buffer;
|
||||
off_t offset = base;
|
||||
|
||||
while (count < size) {
|
||||
uint64_t bytes = size - count;
|
||||
|
||||
if (bytes > RW_MAX_SIZE)
|
||||
bytes = RW_MAX_SIZE;
|
||||
|
||||
if (offset) {
|
||||
rc = lseek(fd, offset, SEEK_SET);
|
||||
if (rc != offset) {
|
||||
fprintf(stderr, "%s, seek off 0x%lx != 0x%lx.\n", fname, rc, offset);
|
||||
perror("seek file");
|
||||
return -EIO;
|
||||
}
|
||||
}
|
||||
|
||||
/* write data to file from memory buffer */
|
||||
rc = write(fd, buf, bytes);
|
||||
if (rc != bytes) {
|
||||
fprintf(stderr, "%s, W off 0x%lx, 0x%lx != 0x%lx.\n", fname, offset, rc, bytes);
|
||||
perror("write file");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
count += bytes;
|
||||
buf += bytes;
|
||||
offset += bytes;
|
||||
}
|
||||
|
||||
if (count != size) {
|
||||
fprintf(stderr, "%s, R failed 0x%lx != 0x%lx.\n", fname, count, size);
|
||||
return -EIO;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
/* Subtract timespec t2 from t1
|
||||
*
|
||||
* Both t1 and t2 must already be normalized
|
||||
* i.e. 0 <= nsec < 1000000000
|
||||
*/
|
||||
static int timespec_check(struct timespec* t)
|
||||
{
|
||||
if ((t->tv_nsec < 0) || (t->tv_nsec >= 1000000000))
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
void timespec_sub(struct timespec* t1, struct timespec* t2)
|
||||
{
|
||||
if (timespec_check(t1) < 0) {
|
||||
fprintf(stderr, "invalid time #1: %lld.%.9ld.\n", (long long)t1->tv_sec, t1->tv_nsec);
|
||||
return;
|
||||
}
|
||||
if (timespec_check(t2) < 0) {
|
||||
fprintf(stderr, "invalid time #2: %lld.%.9ld.\n", (long long)t2->tv_sec, t2->tv_nsec);
|
||||
return;
|
||||
}
|
||||
t1->tv_sec -= t2->tv_sec;
|
||||
t1->tv_nsec -= t2->tv_nsec;
|
||||
if (t1->tv_nsec >= 1000000000) {
|
||||
t1->tv_sec++;
|
||||
t1->tv_nsec -= 1000000000;
|
||||
} else if (t1->tv_nsec < 0) {
|
||||
t1->tv_sec--;
|
||||
t1->tv_nsec += 1000000000;
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
// [End] #include "dma_utils.c" ===================================
|
||||
|
||||
int test_dma_enc_read(char* EncOut, EncIPConf Confparam)
|
||||
{
|
||||
// U64 tTotal = MLogPhyTick();
|
||||
ssize_t rc;
|
||||
uint64_t i;
|
||||
|
||||
void* virt_addr;
|
||||
|
||||
uint64_t size;
|
||||
uint32_t writeval;
|
||||
|
||||
uint32_t Z_val;
|
||||
|
||||
uint16_t max_schedule, mb, id, bg, z_j, kb, z_a;
|
||||
uint16_t z_set;
|
||||
uint32_t ctrl_data;
|
||||
uint32_t CB_num = CB_PROCESS_NUMBER;
|
||||
|
||||
// this values should be given by Shane
|
||||
max_schedule = 0;
|
||||
mb = Confparam.mb;
|
||||
id = CB_num;
|
||||
bg = Confparam.BGSel - 1;
|
||||
z_set = Confparam.z_set - 1;
|
||||
z_j = Confparam.z_j;
|
||||
|
||||
if (z_set == 0)
|
||||
z_a = 2;
|
||||
else if (z_set == 1)
|
||||
z_a = 3;
|
||||
else if (z_set == 2)
|
||||
z_a = 5;
|
||||
else if (z_set == 3)
|
||||
z_a = 7;
|
||||
else if (z_set == 4)
|
||||
z_a = 9;
|
||||
else if (z_set == 5)
|
||||
z_a = 11;
|
||||
else if (z_set == 6)
|
||||
z_a = 13;
|
||||
else
|
||||
z_a = 15;
|
||||
|
||||
if (bg == 0)
|
||||
kb = 22;
|
||||
else if (bg == 1)
|
||||
kb = 10;
|
||||
else if (bg == 2)
|
||||
kb = 9;
|
||||
else if (bg == 3)
|
||||
kb = 8;
|
||||
else
|
||||
kb = 6;
|
||||
mb = Confparam.kb_1 + kb;
|
||||
Z_val = (unsigned int)(z_a << z_j);
|
||||
ctrl_data = (max_schedule << 30) | ((mb - kb) << 24) | (id << 19) | (bg << 6) | (z_set << 3) | z_j;
|
||||
// printf("max_schedule:%d (mb - kb):%d id:%d bg:%d z_set:%d z_j:%d\n",max_schedule,(mb - kb),id,bg,z_set,z_j);
|
||||
uint32_t OutDataNUM = Z_val * mb;
|
||||
uint32_t Out_dwNumItems_p128;
|
||||
uint32_t Out_dwNumItems;
|
||||
|
||||
if ((OutDataNUM & 0x7F) == 0)
|
||||
Out_dwNumItems_p128 = OutDataNUM >> 5;
|
||||
else
|
||||
Out_dwNumItems_p128 = ((OutDataNUM >> 7) + 1) << 2;
|
||||
// printf("0x%04x \n",Out_dwNumItems_p128);
|
||||
Out_dwNumItems = ((Out_dwNumItems_p128 << 2) * CB_num);
|
||||
// printf("0x%04x \n",Out_dwNumItems);
|
||||
// MLogPhyTask(PID_DL_FEC_GEN3_R1, tTotal, MLogPhyTick());
|
||||
size = Out_dwNumItems;
|
||||
writeval = ctrl_data;
|
||||
// printf("read : %d byte, ctrl : 0x%08x\n",size,writeval);
|
||||
|
||||
/* calculate the virtual address to be accessed */
|
||||
virt_addr = map_base + OFFSET_ENC_OUT;
|
||||
|
||||
/* swap 32-bit endianess if host is not little-endian */
|
||||
writeval = htoll(writeval);
|
||||
*((uint32_t*)virt_addr) = writeval;
|
||||
// MLogPhyTask(PID_DL_FEC_GEN3_R2, tTotal, MLogPhyTick());
|
||||
if (fd_enc_read < 0) {
|
||||
fprintf(stderr, "unable to open device %s, %d.\n", DEVICE_NAME_DEFAULT_ENC_READ, fd_enc_read);
|
||||
perror("open device");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* lseek & read data from AXI MM into buffer using SGDMA */
|
||||
rc = read_to_buffer(DEVICE_NAME_DEFAULT_ENC_READ, fd_enc_read, EncOut, size, 0);
|
||||
// rc = read_to_buffer(DEVICE_NAME_DEFAULT_ENC_READ, fd_enc_read, allocated_read, size, 0);
|
||||
// MLogPhyTask(PID_DL_FEC_GEN3_R3, tTotal, MLogPhyTick());
|
||||
if (rc < 0)
|
||||
goto out;
|
||||
|
||||
rc = 0;
|
||||
|
||||
out:
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
int test_dma_enc_write(char* data, EncIPConf Confparam)
|
||||
{
|
||||
uint64_t i;
|
||||
ssize_t rc;
|
||||
// U64 tTotal = MLogPhyTick();
|
||||
void* virt_addr;
|
||||
|
||||
uint64_t size;
|
||||
uint32_t writeval;
|
||||
|
||||
uint32_t Z_val;
|
||||
uint16_t max_schedule, mb, id, bg, z_j, kb, z_a;
|
||||
uint16_t z_set;
|
||||
uint32_t ctrl_data;
|
||||
uint32_t CB_num = CB_PROCESS_NUMBER;
|
||||
|
||||
// this values should be given by Shane
|
||||
max_schedule = 0;
|
||||
|
||||
mb = Confparam.mb;
|
||||
id = CB_num;
|
||||
bg = Confparam.BGSel - 1;
|
||||
z_set = Confparam.z_set - 1;
|
||||
z_j = Confparam.z_j;
|
||||
|
||||
if (z_set == 0)
|
||||
z_a = 2;
|
||||
else if (z_set == 1)
|
||||
z_a = 3;
|
||||
else if (z_set == 2)
|
||||
z_a = 5;
|
||||
else if (z_set == 3)
|
||||
z_a = 7;
|
||||
else if (z_set == 4)
|
||||
z_a = 9;
|
||||
else if (z_set == 5)
|
||||
z_a = 11;
|
||||
else if (z_set == 6)
|
||||
z_a = 13;
|
||||
else
|
||||
z_a = 15;
|
||||
|
||||
if (bg == 0)
|
||||
kb = 22;
|
||||
else if (bg == 1)
|
||||
kb = 10;
|
||||
else if (bg == 2)
|
||||
kb = 9;
|
||||
else if (bg == 3)
|
||||
kb = 8;
|
||||
else
|
||||
kb = 6;
|
||||
mb = Confparam.kb_1 + kb;
|
||||
Z_val = (unsigned int)(z_a << z_j);
|
||||
ctrl_data = (max_schedule << 30) | ((mb - kb) << 24) | (id << 19) | (bg << 6) | (z_set << 3) | z_j;
|
||||
// printf("max_schedule:%d (mb - kb):%d id:%d bg:%d z_set:%d z_j:%d\n",max_schedule,(mb - kb),id,bg,z_set,z_j);
|
||||
uint32_t InDataNUM = Z_val * kb;
|
||||
uint32_t In_dwNumItems_p128;
|
||||
uint32_t In_dwNumItems;
|
||||
|
||||
if ((InDataNUM & 0x7F) == 0)
|
||||
In_dwNumItems_p128 = InDataNUM >> 5;
|
||||
else
|
||||
In_dwNumItems_p128 = ((InDataNUM >> 7) + 1) << 2;
|
||||
|
||||
In_dwNumItems = ((In_dwNumItems_p128 << 2) * CB_num);
|
||||
// MLogPhyTask(PID_DL_FEC_GEN3_W1, tTotal, MLogPhyTick());
|
||||
size = In_dwNumItems;
|
||||
writeval = ctrl_data;
|
||||
|
||||
/* calculate the virtual address to be accessed */
|
||||
virt_addr = map_base + OFFSET_ENC_IN;
|
||||
|
||||
/* swap 32-bit endianess if host is not little-endian */
|
||||
writeval = htoll(writeval);
|
||||
*((uint32_t*)virt_addr) = writeval;
|
||||
// MLogPhyTask(PID_DL_FEC_GEN3_W2, tTotal, MLogPhyTick());
|
||||
if (fd_enc_write < 0) {
|
||||
fprintf(stderr, "unable to open device %s, %d.\n", DEVICE_NAME_DEFAULT_ENC_WRITE, fd_enc_write);
|
||||
perror("open device");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
rc = write_from_buffer(DEVICE_NAME_DEFAULT_ENC_WRITE, fd_enc_write, data, size, 0);
|
||||
// rc = write_from_buffer(DEVICE_NAME_DEFAULT_ENC_WRITE, fd_enc_write, allocated_write, size, 0);
|
||||
if (rc < 0)
|
||||
goto out;
|
||||
// MLogPhyTask(PID_DL_FEC_GEN3_W3, tTotal, MLogPhyTick());
|
||||
rc = 0;
|
||||
|
||||
out:
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
// int test_dma_dec_read(unsigned int *DecOut, DecIPConf Confparam)
|
||||
int test_dma_dec_read(char* DecOut, DecIPConf Confparam)
|
||||
{
|
||||
struct timespec read_start_2, read_end_2;
|
||||
ssize_t rc;
|
||||
uint64_t i;
|
||||
|
||||
void* virt_addr;
|
||||
|
||||
uint64_t size;
|
||||
uint32_t writeval;
|
||||
|
||||
uint32_t Z_val;
|
||||
|
||||
uint16_t max_schedule, mb, id, bg, z_j, kb, z_a, max_iter, sc_idx;
|
||||
uint16_t z_set;
|
||||
uint32_t ctrl_data;
|
||||
uint32_t CB_num = Confparam.CB_num; // CB_PROCESS_NUMBER_Dec;//
|
||||
|
||||
// this values should be given by Shane
|
||||
max_schedule = 0;
|
||||
mb = Confparam.mb;
|
||||
id = CB_num;
|
||||
bg = Confparam.BGSel - 1;
|
||||
z_set = Confparam.z_set - 1;
|
||||
z_j = Confparam.z_j;
|
||||
// max_iter = 4;
|
||||
max_iter = 8;
|
||||
sc_idx = 12;
|
||||
|
||||
if (z_set == 0)
|
||||
z_a = 2;
|
||||
else if (z_set == 1)
|
||||
z_a = 3;
|
||||
else if (z_set == 2)
|
||||
z_a = 5;
|
||||
else if (z_set == 3)
|
||||
z_a = 7;
|
||||
else if (z_set == 4)
|
||||
z_a = 9;
|
||||
else if (z_set == 5)
|
||||
z_a = 11;
|
||||
else if (z_set == 6)
|
||||
z_a = 13;
|
||||
else
|
||||
z_a = 15;
|
||||
|
||||
if (bg == 0)
|
||||
kb = 22;
|
||||
else if (bg == 1)
|
||||
kb = 10;
|
||||
else if (bg == 2)
|
||||
kb = 9;
|
||||
else if (bg == 3)
|
||||
kb = 8;
|
||||
else
|
||||
kb = 6;
|
||||
|
||||
Z_val = (unsigned int)(z_a << z_j);
|
||||
ctrl_data =
|
||||
(max_schedule << 30) | ((mb - kb) << 24) | (id << 19) | (max_iter << 13) | (sc_idx << 9) | (bg << 6) | (z_set) << 3 | z_j;
|
||||
|
||||
uint32_t OutDataNUM = Z_val * kb;
|
||||
uint32_t Out_dwNumItems_p128;
|
||||
uint32_t Out_dwNumItems;
|
||||
|
||||
if (CB_num & 0x01) // odd cb number
|
||||
{
|
||||
if ((OutDataNUM & 0xFF) == 0)
|
||||
Out_dwNumItems_p128 = OutDataNUM;
|
||||
else
|
||||
Out_dwNumItems_p128 = 256 * ((OutDataNUM / 256) + 1);
|
||||
|
||||
Out_dwNumItems = (Out_dwNumItems_p128 * CB_num) >> 3;
|
||||
// printf("Z_val%d CB_num%d OutDataNUM%d Out_dwNumItems_p128%d Out_dwNumItems%d\n" , Z_val, CB_num, OutDataNUM,
|
||||
// Out_dwNumItems_p128, Out_dwNumItems);
|
||||
} else {
|
||||
if ((OutDataNUM & 0x7F) == 0)
|
||||
Out_dwNumItems_p128 = OutDataNUM;
|
||||
else
|
||||
Out_dwNumItems_p128 = 128 * ((OutDataNUM / 128) + 1);
|
||||
|
||||
Out_dwNumItems = (Out_dwNumItems_p128 * CB_num) >> 3;
|
||||
// printf("Z_val%d CB_num%d OutDataNUM%d Out_dwNumItems_p128%d Out_dwNumItems%d\n" , Z_val, CB_num, OutDataNUM,
|
||||
// Out_dwNumItems_p128, Out_dwNumItems);
|
||||
if ((Out_dwNumItems & 0x1f) != 0)
|
||||
Out_dwNumItems = ((Out_dwNumItems + 31) >> 5) << 5;
|
||||
|
||||
// printf("Z_val%d kb%d OutDataNUM%d Out_dwNumItems_p128%d Out_dwNumItems%d CB_num=%d\n" , Z_val, kb, OutDataNUM,
|
||||
// Out_dwNumItems_p128, Out_dwNumItems, CB_num);
|
||||
}
|
||||
size = Out_dwNumItems;
|
||||
writeval = ctrl_data;
|
||||
|
||||
/* calculate the virtual address to be accessed */
|
||||
virt_addr = map_base + OFFSET_DEC_OUT;
|
||||
|
||||
/* swap 32-bit endianess if host is not little-endian */
|
||||
writeval = htoll(writeval);
|
||||
*((uint32_t*)virt_addr) = writeval;
|
||||
|
||||
if (fd_dec_read < 0) {
|
||||
fprintf(stderr, "unable to open device %s, %d.\n", DEVICE_NAME_DEFAULT_DEC_READ, fd_dec_read);
|
||||
perror("open device");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
// clock_gettime(CLOCK_MONOTONIC, &read_start_2);
|
||||
/* lseek & read data from AXI MM into buffer using SGDMA */
|
||||
rc = read_to_buffer(DEVICE_NAME_DEFAULT_DEC_READ, fd_dec_read, DecOut, size, 0);
|
||||
if (rc < 0)
|
||||
goto out;
|
||||
|
||||
rc = 0;
|
||||
// clock_gettime(CLOCK_MONOTONIC, &read_end_2);
|
||||
// timespec_sub(&read_end_2, &read_start_2);
|
||||
// printf("[2]read_to_buffer() time %.2f µsec\n", (float)(read_end_2.tv_nsec) / 1000);
|
||||
|
||||
out:
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
// int test_dma_dec_write(unsigned int *data, DecIPConf Confparam)
|
||||
int test_dma_dec_write(char* data, DecIPConf Confparam)
|
||||
{
|
||||
uint64_t i;
|
||||
ssize_t rc;
|
||||
|
||||
void* virt_addr;
|
||||
|
||||
uint64_t size;
|
||||
uint32_t writeval;
|
||||
|
||||
uint32_t Z_val;
|
||||
uint16_t max_schedule, mb, id, bg, z_j, kb, z_a, max_iter, sc_idx;
|
||||
uint16_t z_set;
|
||||
uint32_t ctrl_data;
|
||||
uint32_t CB_num = Confparam.CB_num; // CB_PROCESS_NUMBER_Dec;//
|
||||
|
||||
// this values should be given by Shane
|
||||
max_schedule = 0;
|
||||
mb = Confparam.mb;
|
||||
id = CB_num;
|
||||
bg = Confparam.BGSel - 1;
|
||||
z_set = Confparam.z_set - 1;
|
||||
z_j = Confparam.z_j;
|
||||
|
||||
// max_iter = 4;
|
||||
max_iter = 8;
|
||||
sc_idx = 12;
|
||||
|
||||
if (z_set == 0)
|
||||
z_a = 2;
|
||||
else if (z_set == 1)
|
||||
z_a = 3;
|
||||
else if (z_set == 2)
|
||||
z_a = 5;
|
||||
else if (z_set == 3)
|
||||
z_a = 7;
|
||||
else if (z_set == 4)
|
||||
z_a = 9;
|
||||
else if (z_set == 5)
|
||||
z_a = 11;
|
||||
else if (z_set == 6)
|
||||
z_a = 13;
|
||||
else
|
||||
z_a = 15;
|
||||
|
||||
if (bg == 0)
|
||||
kb = 22;
|
||||
else if (bg == 1)
|
||||
kb = 10;
|
||||
else if (bg == 2)
|
||||
kb = 9;
|
||||
else if (bg == 3)
|
||||
kb = 8;
|
||||
else
|
||||
kb = 6;
|
||||
|
||||
Z_val = (unsigned int)(z_a << z_j);
|
||||
ctrl_data =
|
||||
(max_schedule << 30) | ((mb - kb) << 24) | (id << 19) | (max_iter << 13) | (sc_idx << 9) | (bg << 6) | (z_set) << 3 | z_j;
|
||||
|
||||
uint32_t InDataNUM = Z_val * mb;
|
||||
uint32_t In_dwNumItems_p128;
|
||||
uint32_t In_dwNumItems;
|
||||
|
||||
InDataNUM = Z_val * mb * 8;
|
||||
if ((InDataNUM & 0x7F) == 0)
|
||||
In_dwNumItems_p128 = InDataNUM;
|
||||
else
|
||||
In_dwNumItems_p128 = 128 * ((InDataNUM / 128) + 1);
|
||||
|
||||
In_dwNumItems = (In_dwNumItems_p128 * CB_num) >> 3;
|
||||
if ((In_dwNumItems & 0x1f) != 0)
|
||||
In_dwNumItems = ((In_dwNumItems + 31) >> 5) << 5;
|
||||
|
||||
// printf("Z_val[%d] CB_num[%d] mb[%d] InDataNUM[%d] In_dwNumItems_p128[%d] In_dwNumItems[%d]\n" , Z_val, CB_num, mb, InDataNUM,
|
||||
// In_dwNumItems_p128, In_dwNumItems);
|
||||
size = In_dwNumItems;
|
||||
writeval = ctrl_data;
|
||||
|
||||
/* calculate the virtual address to be accessed */
|
||||
virt_addr = map_base + OFFSET_DEC_IN;
|
||||
|
||||
/* swap 32-bit endianess if host is not little-endian */
|
||||
writeval = htoll(writeval);
|
||||
*((uint32_t*)virt_addr) = writeval;
|
||||
|
||||
if (fd_dec_write < 0) {
|
||||
fprintf(stderr, "unable to open device %s, %d.\n", DEVICE_NAME_DEFAULT_DEC_WRITE, fd_dec_write);
|
||||
perror("open device");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
rc = write_from_buffer(DEVICE_NAME_DEFAULT_DEC_WRITE, fd_dec_write, data, size, 0);
|
||||
if (rc < 0)
|
||||
goto out;
|
||||
|
||||
rc = 0;
|
||||
|
||||
out:
|
||||
|
||||
return rc;
|
||||
}
|
||||
void test_dma_init()
|
||||
{
|
||||
/* access width */
|
||||
int access_width = 'w';
|
||||
char* device2 = "/dev/xdma0_user"; //
|
||||
uint32_t size1 = 24 * 1024;
|
||||
uint32_t size2 = 24 * 1024 * 3;
|
||||
|
||||
// printf("\n###################################################\n");
|
||||
if ((fd = open(device2, O_RDWR | O_SYNC)) == -1)
|
||||
FATAL;
|
||||
// printf("# CHARACTER DEVICE %s OPENED. #\n", device2);
|
||||
fflush(stdout);
|
||||
|
||||
/* map one page */
|
||||
map_base = mmap(0, MAP_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
|
||||
if (map_base == (void*)-1)
|
||||
FATAL;
|
||||
// printf("# MEMORY MAPPED AT ADDRESS %p. #\n", map_base);
|
||||
// printf("###################################################\n\n");
|
||||
|
||||
void* virt_addr;
|
||||
virt_addr = map_base + OFFSET_RESET;
|
||||
*((uint32_t*)virt_addr) = 1;
|
||||
|
||||
fd_enc_write = open(DEVICE_NAME_DEFAULT_ENC_WRITE, O_RDWR);
|
||||
fd_enc_read = open(DEVICE_NAME_DEFAULT_ENC_READ, O_RDWR);
|
||||
fd_dec_write = open(DEVICE_NAME_DEFAULT_DEC_WRITE, O_RDWR);
|
||||
fd_dec_read = open(DEVICE_NAME_DEFAULT_DEC_READ, O_RDWR);
|
||||
|
||||
fflush(stdout);
|
||||
|
||||
allocated_write = NULL;
|
||||
posix_memalign((void**)&allocated_write, 4096 /*alignment */, size1 + 4096);
|
||||
allocated_read = NULL;
|
||||
posix_memalign((void**)&allocated_read, 4096 /*alignment */, size2 + 4096);
|
||||
}
|
||||
void dma_reset()
|
||||
{
|
||||
char* device2 = "/dev/xdma0_user"; //
|
||||
|
||||
void* virt_addr;
|
||||
virt_addr = map_base + PCIE_OFF;
|
||||
*((uint32_t*)virt_addr) = 1;
|
||||
|
||||
if (munmap(map_base, MAP_SIZE) == -1)
|
||||
FATAL;
|
||||
close(fd_enc_write);
|
||||
close(fd_enc_read);
|
||||
close(fd_dec_write);
|
||||
close(fd_dec_read);
|
||||
close(fd);
|
||||
|
||||
// printf("\n###################################################\n");
|
||||
if ((fd = open(device2, O_RDWR | O_SYNC)) == -1)
|
||||
FATAL;
|
||||
// printf("# CHARACTER DEVICE %s OPENED. #\n", device2);
|
||||
fflush(stdout);
|
||||
|
||||
/* map one page */
|
||||
map_base = mmap(0, MAP_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
|
||||
if (map_base == (void*)-1)
|
||||
FATAL;
|
||||
// printf("# MEMORY MAPPED AT ADDRESS %p. #\n", map_base);
|
||||
// printf("###################################################\n\n");
|
||||
|
||||
// void *virt_addr;
|
||||
virt_addr = map_base + PCIE_OFF;
|
||||
*((uint32_t*)virt_addr) = 1;
|
||||
|
||||
// void *virt_addr;
|
||||
virt_addr = map_base + OFFSET_RESET;
|
||||
*((uint32_t*)virt_addr) = 1;
|
||||
|
||||
fd_enc_write = open(DEVICE_NAME_DEFAULT_ENC_WRITE, O_RDWR);
|
||||
fd_enc_read = open(DEVICE_NAME_DEFAULT_ENC_READ, O_RDWR);
|
||||
fd_dec_write = open(DEVICE_NAME_DEFAULT_DEC_WRITE, O_RDWR);
|
||||
fd_dec_read = open(DEVICE_NAME_DEFAULT_DEC_READ, O_RDWR);
|
||||
|
||||
fflush(stdout);
|
||||
}
|
||||
void test_dma_shutdown()
|
||||
{
|
||||
free(allocated_write);
|
||||
free(allocated_read);
|
||||
}
|
||||
#if 1
|
||||
// reg_rx.c
|
||||
int nrLDPC_decoder_FPGA_PYM(int8_t* buf_in, int8_t* buf_out, DecIFConf dec_conf)
|
||||
{
|
||||
struct timespec ts_start, ts_end; // evaluate core xdma run time
|
||||
struct timespec ts_start0, ts_end0; // ealuate time from input setting to output setting include xdma
|
||||
struct timespec read_start, read_end;
|
||||
struct timespec write_start, write_end;
|
||||
|
||||
int Zc;
|
||||
int nRows;
|
||||
int baseGraph;
|
||||
int CB_num;
|
||||
|
||||
DecIPConf Confparam;
|
||||
int z_a, z_tmp, ii, jj, i;
|
||||
int z_j = 0;
|
||||
|
||||
int numChannelLlrs; // input soft bits length, Zc x 66 - length of filler bits
|
||||
int numFillerBits; // filler bits length
|
||||
char in_softbits[26112 * 52 + 1]; // Random by default value, 52 is max CBs in UL 272RBs and 2 layers with 64QAM
|
||||
char out_MessageBytes[1056 * 52 + 1]; // 52 = max number of code block
|
||||
int iterationAtTermination; // output results
|
||||
int parityPassedAtTermination; // output results
|
||||
|
||||
// char buffer_in[26112 * 52 + 1];
|
||||
char buffer_out[1056 * 52 + 1];
|
||||
|
||||
int numMsgBits, numMsgBytes, input_CBoffset, output_CBoffset;
|
||||
|
||||
uint8_t i_LS;
|
||||
|
||||
static int init_flag = 0;
|
||||
if (init_flag == 0) {
|
||||
/*Init*/
|
||||
test_dma_init();
|
||||
init_flag = 1;
|
||||
} else {
|
||||
dma_reset();
|
||||
}
|
||||
|
||||
clock_gettime(CLOCK_MONOTONIC, &ts_start0); // time start0
|
||||
// LDPC input parameter
|
||||
Zc = dec_conf.Zc; // shifting size
|
||||
nRows = dec_conf.nRows; // number of Rows
|
||||
baseGraph = dec_conf.BG; // base graph
|
||||
CB_num = dec_conf.numCB; // 31 number of code block
|
||||
numChannelLlrs = dec_conf.numChannelLls; // input soft bits length, Zc x 66 - length of filler bits
|
||||
numFillerBits = dec_conf.numFillerBits; // filler bits length
|
||||
|
||||
// calc xdma LDPC parameter
|
||||
// calc i_LS
|
||||
if ((Zc % 15) == 0)
|
||||
i_LS = 7;
|
||||
else if ((Zc % 13) == 0)
|
||||
i_LS = 6;
|
||||
else if ((Zc % 11) == 0)
|
||||
i_LS = 5;
|
||||
else if ((Zc % 9) == 0)
|
||||
i_LS = 4;
|
||||
else if ((Zc % 7) == 0)
|
||||
i_LS = 3;
|
||||
else if ((Zc % 5) == 0)
|
||||
i_LS = 2;
|
||||
else if ((Zc % 3) == 0)
|
||||
i_LS = 1;
|
||||
else
|
||||
i_LS = 0;
|
||||
|
||||
// calc z_a
|
||||
if (i_LS == 0)
|
||||
z_a = 2;
|
||||
else
|
||||
z_a = i_LS * 2 + 1;
|
||||
|
||||
// calc z_j
|
||||
z_tmp = Zc / z_a;
|
||||
while (z_tmp % 2 == 0) {
|
||||
z_j = z_j + 1;
|
||||
z_tmp = z_tmp / 2;
|
||||
}
|
||||
|
||||
// calc CB_num and mb
|
||||
Confparam.CB_num = CB_num;
|
||||
if (baseGraph == 1)
|
||||
Confparam.mb = 22 + nRows;
|
||||
else
|
||||
Confparam.mb = 10 + nRows;
|
||||
|
||||
// set BGSel, z_set, z_j
|
||||
Confparam.BGSel = baseGraph;
|
||||
Confparam.z_set = i_LS + 1;
|
||||
Confparam.z_j = z_j;
|
||||
|
||||
// calc output numMsgBits
|
||||
if (baseGraph == 1)
|
||||
numMsgBits = Zc * 22 - numFillerBits;
|
||||
else
|
||||
numMsgBits = Zc * 10 - numFillerBits;
|
||||
|
||||
// Calc input CB offset
|
||||
input_CBoffset = Zc * Confparam.mb * 8;
|
||||
if ((input_CBoffset & 0x7F) == 0)
|
||||
input_CBoffset = input_CBoffset / 8;
|
||||
else
|
||||
input_CBoffset = 16 * ((input_CBoffset / 128) + 1);
|
||||
|
||||
// Calc output CB offset
|
||||
output_CBoffset = Zc * (Confparam.mb - nRows);
|
||||
if ((output_CBoffset & 0x7F) == 0)
|
||||
output_CBoffset = output_CBoffset / 8;
|
||||
else
|
||||
output_CBoffset = 16 * ((output_CBoffset / 128) + 1);
|
||||
|
||||
// memset(buf_in, 0, 26112 * 52 + 1);
|
||||
// memset(buf_out, 0, 27500); // memset(buffer_out, 0, 1056 * 52 + 1);
|
||||
|
||||
#if 1 // Input Setting FPGA
|
||||
// set input buffer_in from the llr output (in_softbits)
|
||||
// Arrange data format
|
||||
// for (jj = 0; jj < CB_num; jj++) {
|
||||
// for (ii = 0; ii < (numChannelLlrs + numFillerBits + Zc * 2); ii++) {
|
||||
// if (buf_in[ii + input_CBoffset * jj] == -128) {
|
||||
// buf_in[ii + input_CBoffset * jj] = -127;
|
||||
// }
|
||||
// if (ii < Zc * 2)
|
||||
// buf_in[ii + input_CBoffset * jj] = 0x00;
|
||||
// else if (ii < numMsgBits)
|
||||
// buf_in[ii + input_CBoffset * jj] = ((buf_in[ii - Zc * 2 + numChannelLlrs * jj]) ^ (0xFF)) + 1;
|
||||
// else if (ii < (numMsgBits + numFillerBits))
|
||||
// buf_in[ii + input_CBoffset * jj] = 0x80;
|
||||
// else
|
||||
// buf_in[ii + input_CBoffset * jj] = ((buf_in[ii - Zc * 2 - numFillerBits + numChannelLlrs * jj]) ^ (0xFF)) + 1;
|
||||
// }
|
||||
// printf("\nInput_LLR[%d] = ", jj);
|
||||
// for (i = 0; i < 20; i++) {
|
||||
// printf("%d,", buf_in[i + input_CBoffset * jj + 2 * Zc]);
|
||||
// }
|
||||
// }
|
||||
|
||||
// printf("input setting done\n");
|
||||
#endif // Input Setting FPGA
|
||||
|
||||
// LDPC accelerator start
|
||||
// printf("[%s] Start DMA write\n", __func__);
|
||||
// clock_gettime(CLOCK_MONOTONIC, &ts_start); // time start
|
||||
// ===================================================
|
||||
// printf("[%s] DMA write 0\n", __func__);
|
||||
// write into accelerator
|
||||
// clock_gettime(CLOCK_MONOTONIC, &write_start);
|
||||
if (test_dma_dec_write(buf_in, Confparam) != 0) {
|
||||
exit(1);
|
||||
printf("write exit!!\n");
|
||||
}
|
||||
// clock_gettime(CLOCK_MONOTONIC, &write_end);
|
||||
// timespec_sub(&write_end, &write_start);
|
||||
// printf("Write time %.2f µsec\n", (float)(write_end.tv_nsec) / 1000);
|
||||
// ===================================================
|
||||
// printf("[%s] DMA read 0\n", __func__);
|
||||
// read output of accelerator
|
||||
// clock_gettime(CLOCK_MONOTONIC, &read_start);
|
||||
if (test_dma_dec_read(buf_out, Confparam) != 0) {
|
||||
exit(1);
|
||||
printf("read exit!!\n");
|
||||
}
|
||||
// clock_gettime(CLOCK_MONOTONIC, &read_end);
|
||||
// timespec_sub(&read_end, &read_start);
|
||||
// printf("[1]Read time %.2f µsec\n", (float)(read_end.tv_nsec) / 1000);
|
||||
// // ===================================================
|
||||
// clock_gettime(CLOCK_MONOTONIC, &ts_end); // time end
|
||||
// printf("[%s] End DMA read\n", __func__);
|
||||
|
||||
// LDPC accelerator end
|
||||
// timespec_sub(&ts_end, &ts_start);
|
||||
// printf("[%s] finish DMA, CB_num[%d], total time %ld nsec\n", __func__, CB_num, ts_end.tv_nsec);
|
||||
|
||||
#if 1 // Output Setting FPGA
|
||||
// set output out_MessageBytes from the xdma output (buffer_out) , iterationAtTermination , parityPassedAtTermination
|
||||
for (jj = 0; jj < CB_num; jj++) {
|
||||
if ((numMsgBits & 0x7) == 0)
|
||||
numMsgBytes = numMsgBits / 8;
|
||||
else {
|
||||
numMsgBytes = (numMsgBits / 8) + 1;
|
||||
}
|
||||
iterationAtTermination = 1; // output
|
||||
parityPassedAtTermination = 1; // output
|
||||
// memcpy((int8_t*)&buf_out[output_CBoffset * jj], (int8_t*)&buffer_out[output_CBoffset * jj], numMsgBytes);
|
||||
|
||||
// -----------------------------------
|
||||
// Compare output information:
|
||||
// -----------------------------------
|
||||
// printf("buffer_out[%d] = ", jj);
|
||||
// for (i = 0; i < 10; i++) {
|
||||
// printf("%d, ", buffer_out[i + output_CBoffset * jj]);
|
||||
// }
|
||||
// printf("\n");
|
||||
// printf("buf_out[%d] = ", jj);
|
||||
// for (i = 0; i < 10; i++) {
|
||||
// printf("%d, ", buf_out[i + output_CBoffset * jj]);
|
||||
// }
|
||||
// printf("\n");
|
||||
}
|
||||
// printf("[%s] Output setting done\n", __func__);
|
||||
|
||||
#endif // Output Setting FPGA
|
||||
// clock_gettime(CLOCK_MONOTONIC, &ts_end0); // time end0
|
||||
// timespec_sub(&ts_end0, &ts_start0);
|
||||
// printf("[%s] finish LDPC, CB_num[%d], total time %ld nsec\n", __func__, CB_num, ts_end0.tv_nsec);
|
||||
// printf("Accelerator card is completed!\n");
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,35 @@
|
||||
/*! \file PHY/CODING/nrLDPC_decoder_offload_xdma/nrLDPC_decoder_offload_xdma.h
|
||||
* \briefFPGA accelerator integrated into OAI (for one and multi code block)
|
||||
* \author Sendren Xu, SY Yeh(fdragon), Hongming, Terng-Yin Hsu
|
||||
* \date 2022-05-31
|
||||
* \version 5.0
|
||||
* \email: summery19961210@gmail.com
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/**
|
||||
\brief LDPC input parameter
|
||||
\param Zc shifting size
|
||||
\param Rows
|
||||
\param baseGraph base graph
|
||||
\param CB_num number of code block
|
||||
\param numChannelLlrs input soft bits length, Zc x 66 - length of filler bits
|
||||
\param numFillerBits filler bits length
|
||||
*/
|
||||
|
||||
typedef struct {
|
||||
unsigned char max_schedule;
|
||||
unsigned char SetIdx;
|
||||
int Zc;
|
||||
unsigned char numCB;
|
||||
unsigned char BG;
|
||||
unsigned char max_iter;
|
||||
int nRows;
|
||||
int numChannelLls;
|
||||
int numFillerBits;
|
||||
} DecIFConf;
|
||||
|
||||
int nrLDPC_decoder_FPGA_8038(int8_t *buf_in, int8_t *buf_out, DecIFConf dec_conf);
|
||||
int nrLDPC_decoder_FPGA_PYM(int8_t *buf_in, int8_t *buf_out, DecIFConf dec_conf);
|
||||
// int nrLDPC_decoder_FPGA_PYM();
|
||||
116
openair1/PHY/CODING/nrLDPC_decoder/xdma_diag.h
Normal file
116
openair1/PHY/CODING/nrLDPC_decoder/xdma_diag.h
Normal file
@@ -0,0 +1,116 @@
|
||||
/*
|
||||
* This file is part of the Xilinx DMA IP Core driver tools for Linux
|
||||
*
|
||||
* Copyright (c) 2016-present, Xilinx, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under both the BSD-style license (found in the
|
||||
* LICENSE file in the root directory of this source tree) and the GPLv2 (found
|
||||
* in the COPYING file in the root directory of this source tree).
|
||||
* You may select, at your option, one of the above-listed licenses.
|
||||
*/
|
||||
#ifndef MODULES_TXCTRL_INC_XDMA_DIAG_H_
|
||||
#define MODULES_TXCTRL_INC_XDMA_DIAG_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// #define _BSD_SOURCE
|
||||
// #define _XOPEN_SOURCE 500
|
||||
// #include "../../LDPC/LDPC_api.h"
|
||||
|
||||
// #include "dma_utils.c"
|
||||
|
||||
/*static struct option const long_opts[] = {
|
||||
{"device", required_argument, NULL, 'd'},
|
||||
{"address", required_argument, NULL, 'a'},
|
||||
{"size", required_argument, NULL, 's'},
|
||||
{"offset", required_argument, NULL, 'o'},
|
||||
{"count", required_argument, NULL, 'c'},
|
||||
{"data infile", required_argument, NULL, 'f'},
|
||||
{"data outfile", required_argument, NULL, 'w'},
|
||||
{"help", no_argument, NULL, 'h'},
|
||||
{"verbose", no_argument, NULL, 'v'},
|
||||
{0, 0, 0, 0}
|
||||
};*/
|
||||
|
||||
typedef struct {
|
||||
unsigned char max_schedule; // max_schedule = 0;
|
||||
unsigned char mb; // mb = 32;
|
||||
unsigned char CB_num; // id = CB_num;
|
||||
unsigned char BGSel; // bg = 1;
|
||||
unsigned char z_set; // z_set = 0;
|
||||
unsigned char z_j; // z_j = 6;
|
||||
unsigned char max_iter; // max_iter = 8;
|
||||
unsigned char SetIdx; // sc_idx = 12;
|
||||
} DecIPConf;
|
||||
|
||||
typedef struct {
|
||||
int SetIdx;
|
||||
int NumCBSegm;
|
||||
int PayloadLen;
|
||||
int Z;
|
||||
int z_set;
|
||||
int z_j;
|
||||
int Kbmax;
|
||||
int BGSel;
|
||||
unsigned mb;
|
||||
unsigned char CB_num;
|
||||
unsigned char kb_1;
|
||||
} EncIPConf;
|
||||
|
||||
/* ltoh: little to host */
|
||||
/* htol: little to host */
|
||||
#if __BYTE_ORDER == __LITTLE_ENDIAN
|
||||
#define ltohl(x) (x)
|
||||
#define ltohs(x) (x)
|
||||
#define htoll(x) (x)
|
||||
#define htols(x) (x)
|
||||
#elif __BYTE_ORDER == __BIG_ENDIAN
|
||||
#define ltohl(x) __bswap_32(x)
|
||||
#define ltohs(x) __bswap_16(x)
|
||||
#define htoll(x) __bswap_32(x)
|
||||
#define htols(x) __bswap_16(x)
|
||||
#endif
|
||||
|
||||
#define FATAL \
|
||||
do { \
|
||||
fprintf(stderr, "Error at line %d, file %s (%d) [%s]\n", __LINE__, __FILE__, errno, strerror(errno)); \
|
||||
exit(1); \
|
||||
} while (0)
|
||||
|
||||
#define MAP_SIZE (32 * 1024UL)
|
||||
#define MAP_MASK (MAP_SIZE - 1)
|
||||
|
||||
#define DEVICE_NAME_DEFAULT_ENC_READ "/dev/xdma0_c2h_1"
|
||||
#define DEVICE_NAME_DEFAULT_ENC_WRITE "/dev/xdma0_h2c_1"
|
||||
#define DEVICE_NAME_DEFAULT_DEC_READ "/dev/xdma0_c2h_0"
|
||||
#define DEVICE_NAME_DEFAULT_DEC_WRITE "/dev/xdma0_h2c_0"
|
||||
#define SIZE_DEFAULT (32)
|
||||
#define COUNT_DEFAULT (1)
|
||||
|
||||
#define OFFSET_DEC_IN 0x0000
|
||||
#define OFFSET_DEC_OUT 0x0004
|
||||
#define OFFSET_ENC_IN 0x0008
|
||||
#define OFFSET_ENC_OUT 0x000c
|
||||
#define OFFSET_RESET 0x0020
|
||||
#define PCIE_OFF 0x0030
|
||||
|
||||
#define CB_PROCESS_NUMBER 24 // add by JW
|
||||
#define CB_PROCESS_NUMBER_Dec 24
|
||||
|
||||
// dma_from_device.c
|
||||
|
||||
int test_dma_enc_read(char *EncOut, EncIPConf Confparam);
|
||||
int test_dma_enc_write(char *data, EncIPConf Confparam);
|
||||
int test_dma_dec_read(char *DecOut, DecIPConf Confparam);
|
||||
int test_dma_dec_write(char *data, DecIPConf Confparam);
|
||||
void test_dma_init();
|
||||
void test_dma_shutdown();
|
||||
void dma_reset();
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
392
openair1/PHY/CODING/tests/CMakeLists.txt
Normal file
392
openair1/PHY/CODING/tests/CMakeLists.txt
Normal file
@@ -0,0 +1,392 @@
|
||||
####################################################################################
|
||||
###### nr_ulsim unit test ######
|
||||
####################################################################################
|
||||
set(default_ldpc "")
|
||||
set(slot_demo "--loader.ldpc.shlibversion" "_slot_demo")
|
||||
set(t2_offload_nr_ulsim "-o" "-O" "${CMAKE_CURRENT_SOURCE_DIR}/t2_offload.conf")
|
||||
set(slot_t2 "-O" "${CMAKE_CURRENT_SOURCE_DIR}/slot_t2.conf")
|
||||
set(slot_xdma "-O" "${CMAKE_CURRENT_SOURCE_DIR}/slot_xdma.conf")
|
||||
|
||||
set(NR_ULSIM_OPTION_TO_TEST_LIST
|
||||
default_ldpc
|
||||
slot_demo
|
||||
)
|
||||
|
||||
if (ENABLE_LDPC_T2)
|
||||
list(APPEND NR_ULSIM_OPTION_TO_TEST_LIST
|
||||
t2_offload_nr_ulsim
|
||||
slot_t2
|
||||
)
|
||||
endif()
|
||||
|
||||
if (ENABLE_LDPC_XDMA)
|
||||
list(APPEND NR_ULSIM_OPTION_TO_TEST_LIST
|
||||
slot_xdma
|
||||
)
|
||||
endif()
|
||||
|
||||
set(test_nr_ulsim_misc_test1 "-n100" "-m9" "-r106" "-s5")
|
||||
set(test_nr_ulsim_misc_test2 "-n100" "-m16" "-s10")
|
||||
set(test_nr_ulsim_misc_test3 "-n100" "-m28" "-s20")
|
||||
set(test_nr_ulsim_misc_test4 "-n100" "-m27" "-s25" "-q1")
|
||||
set(test_nr_ulsim_misc_test5 "-n100" "-m9" "-R217" "-r217" "-s5")
|
||||
set(test_nr_ulsim_misc_test6 "-n100" "-m9" "-R273" "-r273" "-s5")
|
||||
set(test_nr_ulsim_misc_test7 "-n100" "-s5" "-U0,1,1,1")
|
||||
set(test_nr_ulsim_misc_test8 "-n100" "-s5" "-T1,2" "-U0,2,1,1")
|
||||
set(test_nr_ulsim_misc_test9 "-n100" "-s5" "-T2,2" "-U1,2,1,1")
|
||||
set(test_nr_ulsim_misc_test10 "-n100" "-s5" "-a4" "-b8" "-T1,2" "-U1,3,1,1")
|
||||
set(test_nr_ulsim_misc_test11 "-n100" "-u0" "-m0" "-R25" "-r25" "-i1,0")
|
||||
set(test_nr_ulsim_misc_test12 "-n100" "-m0" "-S" "-0.6" "-i1,0")
|
||||
set(test_nr_ulsim_misc_test13 "-n100" "-m28" "-R106" "-r106" "-t90" "-s24" "-S24" "-d8")
|
||||
set(test_nr_ulsim_sc_test1 "-n100" "-s5" "-Z")
|
||||
set(test_nr_ulsim_sc_test2 "-n100" "-s5" "-Z" "-r75")
|
||||
set(test_nr_ulsim_sc_test3 "-n50" "-s5" "-Z" "-r216" "-R217")
|
||||
set(test_nr_ulsim_sc_test4 "-n50" "-s5" "-Z" "-r270" "-R273")
|
||||
set(test_nr_ulsim_sc_test5 "-n100" "-s5" "-Z" "-U0,2,1,2")
|
||||
set(test_nr_ulsim_mimo_test1 "-n100" "-m19" "-s10" "-S15" "-z2")
|
||||
set(test_nr_ulsim_mimo_test2 "-n100" "-m9" "-r106" "-s8" "-W2" "-y2" "-z2")
|
||||
set(test_nr_ulsim_mimo_test3 "-n100" "-m10" "-r106" "-s12" "-W2" "-y2" "-z2")
|
||||
set(test_nr_ulsim_mimo_test4 "-n100" "-m19" "-r106" "-s22" "-W2" "-y2" "-z2")
|
||||
set(test_nr_ulsim_mimo_test5 "-n100" "-m9" "-r106" "-s10" "-W4" "-y4" "-z4")
|
||||
set(test_nr_ulsim_3gpp_test1 "-n100" "-b14" "-I7" "-i0,1" "-gA,l,10" "-t70" "-u1" "-m20" "-R106" "-r106" "-U0,1,1,2" "-z2" "-s12.4" "-S12.4")
|
||||
set(test_nr_ulsim_3gpp_test2 "-n100" "-b14" "-I7" "-i0,1" "-gA,l,10" "-t70" "-u1" "-m20" "-R106" "-r106" "-U0,1,1,2" "-z4" "-s8.5" "-S8.5")
|
||||
set(test_nr_ulsim_3gpp_test3 "-n100" "-b14" "-I7" "-i0,1" "-gA,l,10" "-t70" "-u1" "-m20" "-R106" "-r106" "-U0,1,1,2" "-z8" "-s5.4" "-S5.4")
|
||||
set(test_nr_ulsim_3gpp_test4 "-n100" "-b14" "-I7" "-i0,1" "-gA,l,10" "-t70" "-u0" "-m20" "-R25" "-r25" "-U1,1,1,2" "-z2" "-s12.5" "-S12.5")
|
||||
set(test_nr_ulsim_3gpp_test5 "-n100" "-b14" "-I7" "-i0,1" "-gA,l,10" "-t70" "-u0" "-m20" "-R25" "-r25" "-U1,1,1,2" "-z4" "-s8.9" "-S8.9")
|
||||
set(test_nr_ulsim_3gpp_test6 "-n100" "-b14" "-I7" "-i0,1" "-gA,l,10" "-t70" "-u0" "-m20" "-R25" "-r25" "-U1,1,1,2" "-z8" "-s5.7" "-S5.7")
|
||||
set(test_nr_ulsim_3gpp_test7 "-n100" "-b14" "-I7" "-i0,1" "-gA,l,10" "-t70" "-u0" "-m20" "-R52" "-r52" "-U1,1,1,2" "-z2" "-s12.6" "-S12.6")
|
||||
set(test_nr_ulsim_3gpp_test8 "-n100" "-b14" "-I7" "-i0,1" "-gA,l,10" "-t70" "-u0" "-m20" "-R52" "-r52" "-U1,1,1,2" "-z4" "-s8.9" "-S8.9")
|
||||
set(test_nr_ulsim_3gpp_test9 "-n100" "-b14" "-I7" "-i0,1" "-gA,l,10" "-t70" "-u0" "-m20" "-R52" "-r52" "-U1,1,1,2" "-z8" "-s5.8" "-S5.8")
|
||||
set(test_nr_ulsim_3gpp_test10 "-n100" "-b14" "-I7" "-i0,1" "-gA,l,10" "-t70" "-u0" "-m20" "-R106" "-r106" "-U1,1,1,2" "-z2" "-s12.3" "-S12.3")
|
||||
set(test_nr_ulsim_3gpp_test11 "-n100" "-b14" "-I7" "-i0,1" "-gA,l,10" "-t70" "-u0" "-m20" "-R106" "-r106" "-U1,1,1,2" "-z4" "-s8.8" "-S8.8")
|
||||
set(test_nr_ulsim_3gpp_test12 "-n100" "-b14" "-I7" "-i0,1" "-gA,l,10" "-t70" "-u0" "-m20" "-R106" "-r106" "-U1,1,1,2" "-z8" "-s5.7" "-S5.7")
|
||||
set(test_nr_ulsim_3gpp_test13 "-n100" "-b14" "-I7" "-i0,1" "-gA,l,10" "-t70" "-u1" "-m20" "-R24" "-r24" "-U1,1,1,2" "-z2" "-s12.5" "-S12.5")
|
||||
set(test_nr_ulsim_3gpp_test14 "-n100" "-b14" "-I7" "-i0,1" "-gA,l,10" "-t70" "-u1" "-m20" "-R24" "-r24" "-U1,1,1,2" "-z4" "-s8.6" "-S8.6")
|
||||
set(test_nr_ulsim_3gpp_test15 "-n100" "-b14" "-I7" "-i0,1" "-gA,l,10" "-t70" "-u1" "-m20" "-R24" "-r24" "-U1,1,1,2" "-z8" "-s5.6" "-S5.6")
|
||||
set(test_nr_ulsim_3gpp_test16 "-n100" "-b14" "-I7" "-i0,1" "-gA,l,10" "-t70" "-u1" "-m20" "-R51" "-r51" "-U1,1,1,2" "-z2" "-s12.5" "-S12.5")
|
||||
set(test_nr_ulsim_3gpp_test17 "-n100" "-b14" "-I7" "-i0,1" "-gA,l,10" "-t70" "-u1" "-m20" "-R51" "-r51" "-U1,1,1,2" "-z4" "-s8.6" "-S8.6")
|
||||
set(test_nr_ulsim_3gpp_test18 "-n100" "-b14" "-I7" "-i0,1" "-gA,l,10" "-t70" "-u1" "-m20" "-R51" "-r51" "-U1,1,1,2" "-z8" "-s5.6" "-S5.6")
|
||||
set(test_nr_ulsim_3gpp_test19 "-n100" "-b14" "-I7" "-i0,1" "-gA,l,10" "-t70" "-u1" "-m20" "-R106" "-r106" "-U1,1,1,2" "-z2" "-s12.5" "-S12.5")
|
||||
set(test_nr_ulsim_3gpp_test20 "-n100" "-b14" "-I7" "-i0,1" "-gA,l,10" "-t70" "-u1" "-m20" "-R106" "-r106" "-U1,1,1,2" "-z4" "-s8.7" "-S8.7")
|
||||
set(test_nr_ulsim_3gpp_test21 "-n100" "-b14" "-I7" "-i0,1" "-gA,l,10" "-t70" "-u1" "-m20" "-R106" "-r106" "-U1,1,1,2" "-z8" "-s5.5" "-S5.5")
|
||||
set(test_nr_ulsim_3gpp_test22 "-n100" "-b14" "-I7" "-i0,1" "-gA,l,10" "-t70" "-u1" "-m20" "-R273" "-r273" "-U1,1,1,2" "-z2" "-s13.1" "-S13.1")
|
||||
set(test_nr_ulsim_3gpp_test23 "-n100" "-b14" "-I7" "-i0,1" "-gA,l,10" "-t70" "-u1" "-m20" "-R273" "-r273" "-U1,1,1,2" "-z4" "-s9.2" "-S9.2")
|
||||
set(test_nr_ulsim_3gpp_test24 "-n100" "-b14" "-I8" "-i0,1" "-gA,l,10" "-t70" "-u1" "-m20" "-R273" "-r273" "-U1,1,1,2" "-z8" "-s5.9" "-S5.9")
|
||||
set(test_nr_ulsim_3gpp_test25 "-n100" "-b14" "-I15" "-i0,1" "-gB,l" "-t70" "-u1" "-m2" "-R106" "-r106" "-U1,1,1,2" "-W2" "-y2" "-z2" "-s1.7" "-S1.7")
|
||||
set(test_nr_ulsim_3gpp_test26 "-n100" "-b14" "-I15" "-i0,1" "-gB,l" "-t70" "-u1" "-m2" "-R106" "-r106" "-U1,1,1,2" "-W2" "-y2" "-z4" "-s-2.1" "-S-2.1")
|
||||
set(test_nr_ulsim_3gpp_test27 "-n100" "-b14" "-I15" "-i0,1" "-gC,l" "-t70" "-u1" "-m16" "-R106" "-r106" "-U1,1,1,2" "-W2" "-y2" "-z2" "-s18.7" "-S18.7")
|
||||
set(test_nr_ulsim_3gpp_test28 "-n100" "-b14" "-I15" "-i0,1" "-gC,l" "-t70" "-u1" "-m16" "-R106" "-r106" "-U1,1,1,2" "-W2" "-y2" "-z4" "-s11.2" "-S11.2")
|
||||
|
||||
set(NR_ULSIM_TEST_CASE_OPTION_LIST
|
||||
test_nr_ulsim_misc_test1
|
||||
test_nr_ulsim_misc_test2
|
||||
test_nr_ulsim_misc_test3
|
||||
test_nr_ulsim_misc_test4
|
||||
test_nr_ulsim_misc_test5
|
||||
test_nr_ulsim_misc_test6
|
||||
test_nr_ulsim_misc_test7
|
||||
test_nr_ulsim_misc_test8
|
||||
test_nr_ulsim_misc_test9
|
||||
test_nr_ulsim_misc_test10
|
||||
test_nr_ulsim_misc_test11
|
||||
test_nr_ulsim_misc_test12
|
||||
test_nr_ulsim_misc_test13
|
||||
test_nr_ulsim_sc_test1
|
||||
test_nr_ulsim_sc_test2
|
||||
test_nr_ulsim_sc_test3
|
||||
test_nr_ulsim_sc_test4
|
||||
test_nr_ulsim_sc_test5
|
||||
test_nr_ulsim_mimo_test1
|
||||
test_nr_ulsim_mimo_test2
|
||||
test_nr_ulsim_mimo_test3
|
||||
test_nr_ulsim_mimo_test4
|
||||
test_nr_ulsim_mimo_test5
|
||||
test_nr_ulsim_3gpp_test1
|
||||
test_nr_ulsim_3gpp_test2
|
||||
test_nr_ulsim_3gpp_test3
|
||||
test_nr_ulsim_3gpp_test4
|
||||
test_nr_ulsim_3gpp_test5
|
||||
test_nr_ulsim_3gpp_test6
|
||||
test_nr_ulsim_3gpp_test7
|
||||
test_nr_ulsim_3gpp_test8
|
||||
test_nr_ulsim_3gpp_test9
|
||||
test_nr_ulsim_3gpp_test10
|
||||
test_nr_ulsim_3gpp_test11
|
||||
test_nr_ulsim_3gpp_test12
|
||||
test_nr_ulsim_3gpp_test13
|
||||
test_nr_ulsim_3gpp_test14
|
||||
test_nr_ulsim_3gpp_test15
|
||||
test_nr_ulsim_3gpp_test16
|
||||
test_nr_ulsim_3gpp_test17
|
||||
test_nr_ulsim_3gpp_test18
|
||||
test_nr_ulsim_3gpp_test19
|
||||
test_nr_ulsim_3gpp_test20
|
||||
test_nr_ulsim_3gpp_test21
|
||||
test_nr_ulsim_3gpp_test22
|
||||
test_nr_ulsim_3gpp_test23
|
||||
test_nr_ulsim_3gpp_test24
|
||||
test_nr_ulsim_3gpp_test25
|
||||
test_nr_ulsim_3gpp_test26
|
||||
test_nr_ulsim_3gpp_test27
|
||||
test_nr_ulsim_3gpp_test28
|
||||
)
|
||||
|
||||
foreach(NR_ULSIM_OPTION_TO_TEST IN LISTS NR_ULSIM_OPTION_TO_TEST_LIST)
|
||||
foreach(NR_ULSIM_TEST_CASE IN LISTS NR_ULSIM_TEST_CASE_OPTION_LIST)
|
||||
add_test(
|
||||
NAME ${NR_ULSIM_TEST_CASE}_${NR_ULSIM_OPTION_TO_TEST}
|
||||
COMMAND nr_ulsim -P -C1 ${${NR_ULSIM_TEST_CASE}} ${${NR_ULSIM_OPTION_TO_TEST}}
|
||||
COMMAND_EXPAND_LISTS
|
||||
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
|
||||
)
|
||||
endforeach()
|
||||
endforeach()
|
||||
|
||||
####################################################################################
|
||||
###### nr_ulschsim unit test ######
|
||||
####################################################################################
|
||||
|
||||
set(NR_ULSCHSIM_OPTION_TO_TEST_LIST
|
||||
default_ldpc
|
||||
slot_demo
|
||||
)
|
||||
|
||||
if (ENABLE_LDPC_T2)
|
||||
list(APPEND NR_ULSCHSIM_OPTION_TO_TEST_LIST
|
||||
slot_t2
|
||||
)
|
||||
endif()
|
||||
|
||||
if (ENABLE_LDPC_XDMA)
|
||||
list(APPEND NR_ULSCHSIM_OPTION_TO_TEST_LIST
|
||||
slot_xdma
|
||||
)
|
||||
endif()
|
||||
|
||||
set(test_nr_ulschsim_test1 "-R" "106" "-m9" "-s13" "-n100")
|
||||
set(test_nr_ulschsim_test2 "-R" "217" "-m15" "-s15" "-n100")
|
||||
set(test_nr_ulschsim_test3 "-R" "273" "-m19" "-s20" "-n100")
|
||||
set(test_nr_ulschsim_test4 "-R" "106" "-m9" "-s13" "-n100" "-y4" "-z4" "-W4")
|
||||
|
||||
set(NR_ULSCHSIM_TEST_CASE_OPTION_LIST
|
||||
test_nr_ulschsim_test1
|
||||
test_nr_ulschsim_test2
|
||||
test_nr_ulschsim_test3
|
||||
test_nr_ulschsim_test4
|
||||
)
|
||||
|
||||
foreach(NR_ULSCHSIM_OPTION_TO_TEST IN LISTS NR_ULSCHSIM_OPTION_TO_TEST_LIST)
|
||||
foreach(NR_ULSCHSIM_TEST_CASE IN LISTS NR_ULSCHSIM_TEST_CASE_OPTION_LIST)
|
||||
add_test(
|
||||
NAME ${NR_ULSCHSIM_TEST_CASE}_${NR_ULSCHSIM_OPTION_TO_TEST}
|
||||
COMMAND nr_ulschsim ${${NR_ULSCHSIM_TEST_CASE}} ${${NR_ULSCHSIM_OPTION_TO_TEST}}
|
||||
COMMAND_EXPAND_LISTS
|
||||
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
|
||||
)
|
||||
endforeach()
|
||||
endforeach()
|
||||
|
||||
####################################################################################
|
||||
###### nr_dlsim unit test ######
|
||||
####################################################################################
|
||||
set(t2_offload_nr_dlsim "-c" "-O" "${CMAKE_CURRENT_SOURCE_DIR}/t2_offload.conf")
|
||||
|
||||
set(NR_DLSIM_OPTION_TO_TEST_LIST
|
||||
default_ldpc
|
||||
slot_demo
|
||||
)
|
||||
|
||||
if (ENABLE_LDPC_T2)
|
||||
list(APPEND NR_DLSIM_OPTION_TO_TEST_LIST
|
||||
t2_offload_nr_dlsim
|
||||
slot_t2
|
||||
)
|
||||
endif()
|
||||
|
||||
if (ENABLE_LDPC_XDMA)
|
||||
list(APPEND NR_DLSIM_OPTION_TO_TEST_LIST
|
||||
slot_xdma
|
||||
)
|
||||
endif()
|
||||
|
||||
set(test_nr_dlsim_basic_test1 "-n100" "-R106" "-b106" "-s5")
|
||||
set(test_nr_dlsim_basic_test2 "-n100" "-R217" "-b217" "-s5")
|
||||
set(test_nr_dlsim_basic_test3 "-n100" "-R273" "-b273" "-s5")
|
||||
set(test_nr_dlsim_basic_test4 "-n100" "-s1" "-S2" "-t25")
|
||||
set(test_nr_dlsim_basic_test5 "-n100" "-s1" "-S2" "-t33")
|
||||
set(test_nr_dlsim_basic_test6 "-n100" "-s5" "-S7" "-t50")
|
||||
set(test_nr_dlsim_basic_test7 "-n100" "-m0" "-e0" "-R25" "-b25" "-i" "2" "1" "0")
|
||||
set(test_nr_dlsim_offset_test1 "-n100" "-R106" "-a25" "-s5")
|
||||
set(test_nr_dlsim_offset_test2 "-n100" "-R106" "-a51" "-s5")
|
||||
set(test_nr_dlsim_offset_test3 "-n100" "-R217" "-b100" "-s5")
|
||||
set(test_nr_dlsim_offset_test4 "-n100" "-R217" "-a80" "-s5")
|
||||
set(test_nr_dlsim_offset_test5 "-n100" "-R217" "-a110" "-s5" "-b100")
|
||||
set(test_nr_dlsim_mcs_mimo_test1 "-n100" "-e27" "-s30")
|
||||
set(test_nr_dlsim_mcs_mimo_test2 "-n100" "-e16" "-s11" "-S13")
|
||||
set(test_nr_dlsim_mcs_mimo_test3 "-n100" "-q1" "-e26" "-s30")
|
||||
set(test_nr_dlsim_mcs_mimo_test4 "-n100" "-e0 -t95" "-S-1.0" "-i" "2" "1" "0")
|
||||
set(test_nr_dlsim_mcs_mimo_test5 "-n10" "-s20" "-U" "3" "0" "0" "2" "-gA" "-x1" "-y4" "-z4")
|
||||
set(test_nr_dlsim_mcs_mimo_test6 "-n10" "-s20" "-U" "3" "0" "0" "2" "-gA" "-x2" "-y4" "-z4")
|
||||
set(test_nr_dlsim_mcs_mimo_test7 "-n10" "-s20" "-U" "3" "0" "0" "2" "-x4" "-y4" "-z4")
|
||||
set(test_nr_dlsim_dmrs_ptrs_test1 "-n100" "-s5" "-T" "2" "2" "2")
|
||||
set(test_nr_dlsim_dmrs_ptrs_test2 "-n100" "-s5" "-T" "2" "1" "2")
|
||||
set(test_nr_dlsim_dmrs_ptrs_test3 "-n100" "-s5" "-T" "2" "0" "4")
|
||||
set(test_nr_dlsim_dmrs_ptrs_test4 "-n100" "-s5" "-S7" "-U" "2" "0" "1")
|
||||
set(test_nr_dlsim_dmrs_ptrs_test5 "-n100" "-s5" "-S7" "-U" "2" "0" "2")
|
||||
set(test_nr_dlsim_dmrs_ptrs_test6 "-n100" "-s5" "-S7" "-U" "2" "1" "3")
|
||||
|
||||
set(NR_DLSIM_TEST_CASE_OPTION_LIST
|
||||
test_nr_dlsim_basic_test1
|
||||
test_nr_dlsim_basic_test2
|
||||
test_nr_dlsim_basic_test3
|
||||
test_nr_dlsim_basic_test4
|
||||
test_nr_dlsim_basic_test5
|
||||
test_nr_dlsim_basic_test6
|
||||
test_nr_dlsim_basic_test7
|
||||
test_nr_dlsim_offset_test1
|
||||
test_nr_dlsim_offset_test2
|
||||
test_nr_dlsim_offset_test3
|
||||
test_nr_dlsim_offset_test4
|
||||
test_nr_dlsim_offset_test5
|
||||
test_nr_dlsim_mcs_mimo_test1
|
||||
test_nr_dlsim_mcs_mimo_test2
|
||||
test_nr_dlsim_mcs_mimo_test3
|
||||
test_nr_dlsim_mcs_mimo_test4
|
||||
test_nr_dlsim_mcs_mimo_test5
|
||||
test_nr_dlsim_mcs_mimo_test6
|
||||
test_nr_dlsim_mcs_mimo_test7
|
||||
test_nr_dlsim_dmrs_ptrs_test1
|
||||
test_nr_dlsim_dmrs_ptrs_test2
|
||||
test_nr_dlsim_dmrs_ptrs_test3
|
||||
test_nr_dlsim_dmrs_ptrs_test4
|
||||
test_nr_dlsim_dmrs_ptrs_test5
|
||||
test_nr_dlsim_dmrs_ptrs_test6
|
||||
)
|
||||
|
||||
foreach(NR_DLSIM_OPTION_TO_TEST IN LISTS NR_DLSIM_OPTION_TO_TEST_LIST)
|
||||
foreach(NR_DLSIM_TEST_CASE IN LISTS NR_DLSIM_TEST_CASE_OPTION_LIST)
|
||||
add_test(
|
||||
NAME ${NR_DLSIM_TEST_CASE}_${NR_DLSIM_OPTION_TO_TEST}
|
||||
COMMAND nr_dlsim -P ${${NR_DLSIM_TEST_CASE}} ${${NR_DLSIM_OPTION_TO_TEST}}
|
||||
COMMAND_EXPAND_LISTS
|
||||
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
|
||||
)
|
||||
set_property(
|
||||
TEST ${NR_DLSIM_TEST_CASE}_${NR_DLSIM_OPTION_TO_TEST}
|
||||
PROPERTY PASS_REGULAR_EXPRESSION "PDSCH test OK"
|
||||
)
|
||||
endforeach()
|
||||
endforeach()
|
||||
|
||||
####################################################################################
|
||||
###### nr_dlschsim unit test ######
|
||||
####################################################################################
|
||||
|
||||
set(NR_DLSCHSIM_OPTION_TO_TEST_LIST
|
||||
default_ldpc
|
||||
slot_demo
|
||||
)
|
||||
|
||||
if (ENABLE_LDPC_T2)
|
||||
list(APPEND NR_DLSCHSIM_OPTION_TO_TEST_LIST
|
||||
slot_t2
|
||||
)
|
||||
endif()
|
||||
|
||||
if (ENABLE_LDPC_XDMA)
|
||||
list(APPEND NR_DLSCHSIM_OPTION_TO_TEST_LIST
|
||||
slot_xdma
|
||||
)
|
||||
endif()
|
||||
|
||||
set(test_nr_dlschsim_test1 "-R" "106" "-m9" "-s13" "-n100")
|
||||
set(test_nr_dlschsim_test2 "-R" "217" "-m15" "-s15" "-n100")
|
||||
set(test_nr_dlschsim_test3 "-R" "273" "-m19" "-s20" "-n100")
|
||||
|
||||
set(NR_DLSCHSIM_TEST_CASE_OPTION_LIST
|
||||
test_nr_dlschsim_test1
|
||||
test_nr_dlschsim_test2
|
||||
test_nr_dlschsim_test3
|
||||
)
|
||||
|
||||
foreach(NR_DLSCHSIM_OPTION_TO_TEST IN LISTS NR_DLSCHSIM_OPTION_TO_TEST_LIST)
|
||||
foreach(NR_DLSCHSIM_TEST_CASE IN LISTS NR_DLSCHSIM_TEST_CASE_OPTION_LIST)
|
||||
add_test(
|
||||
NAME ${NR_DLSCHSIM_TEST_CASE}_${NR_DLSCHSIM_OPTION_TO_TEST}
|
||||
COMMAND nr_dlschsim ${${NR_DLSCHSIM_TEST_CASE}} ${${NR_DLSCHSIM_OPTION_TO_TEST}}
|
||||
COMMAND_EXPAND_LISTS
|
||||
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
|
||||
)
|
||||
endforeach()
|
||||
endforeach()
|
||||
|
||||
####################################################################################
|
||||
###### nr-softmodem unit test ######
|
||||
####################################################################################
|
||||
set(default_ldpc "-O" "${CMAKE_CURRENT_SOURCE_DIR}/gnb.sa.band78.106prb.rfsim.2x2.conf")
|
||||
set(slot_demo "-O" "${CMAKE_CURRENT_SOURCE_DIR}/gnb.sa.band78.106prb.rfsim.2x2.conf" "--loader.ldpc.shlibversion" "_slot_demo")
|
||||
set(t2_offload "-O" "${CMAKE_CURRENT_SOURCE_DIR}/gnb.sa.band78.106prb.rfsim.2x2.t2_offload.conf" "--ldpc-offload-enable")
|
||||
set(slot_t2 "-O" "${CMAKE_CURRENT_SOURCE_DIR}/gnb.sa.band78.106prb.rfsim.2x2.slot_t2.conf")
|
||||
set(slot_xdma "-O" "${CMAKE_CURRENT_SOURCE_DIR}/gnb.sa.band78.106prb.rfsim.2x2.slot_xdma.conf")
|
||||
|
||||
set(NR_SOFTMODEM_OPTION_TO_TEST_LIST
|
||||
default_ldpc
|
||||
slot_demo
|
||||
)
|
||||
|
||||
if (ENABLE_LDPC_T2)
|
||||
list(APPEND NR_SOFTMODEM_OPTION_TO_TEST_LIST
|
||||
t2_offload
|
||||
slot_t2
|
||||
)
|
||||
endif()
|
||||
|
||||
if (ENABLE_LDPC_XDMA)
|
||||
list(APPEND NR_SOFTMODEM_OPTION_TO_TEST_LIST
|
||||
slot_xdma
|
||||
)
|
||||
endif()
|
||||
|
||||
foreach(NR_SOFTMODEM_OPTION_TO_TEST IN LISTS NR_SOFTMODEM_OPTION_TO_TEST_LIST)
|
||||
add_test(
|
||||
NAME two_ues_rfsim_${NR_SOFTMODEM_OPTION_TO_TEST}
|
||||
COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/two_ues_rfsim.sh ${${NR_SOFTMODEM_OPTION_TO_TEST}}
|
||||
COMMAND_EXPAND_LISTS
|
||||
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
|
||||
)
|
||||
endforeach()
|
||||
|
||||
####################################################################################
|
||||
###### nr-uesoftmodem unit test ######
|
||||
####################################################################################
|
||||
set(default_ldpc "-O" "${CMAKE_CURRENT_SOURCE_DIR}/nrue.uicc.1.conf")
|
||||
set(slot_demo "-O" "${CMAKE_CURRENT_SOURCE_DIR}/nrue.uicc.1.slot_demo.conf")
|
||||
set(slot_t2 "-O" "${CMAKE_CURRENT_SOURCE_DIR}/nrue.uicc.1.slot_t2.conf")
|
||||
set(slot_xdma "-O" "${CMAKE_CURRENT_SOURCE_DIR}/nrue.uicc.1.slot_xdma.conf")
|
||||
|
||||
set(NR_UESOFTMODEM_OPTION_TO_TEST_LIST
|
||||
default_ldpc
|
||||
slot_demo
|
||||
)
|
||||
|
||||
if (ENABLE_LDPC_T2)
|
||||
list(APPEND NR_UESOFTMODEM_OPTION_TO_TEST_LIST
|
||||
slot_t2
|
||||
)
|
||||
endif()
|
||||
|
||||
if (ENABLE_LDPC_XDMA)
|
||||
list(APPEND NR_UESOFTMODEM_OPTION_TO_TEST_LIST
|
||||
slot_xdma
|
||||
)
|
||||
endif()
|
||||
|
||||
foreach(NR_UESOFTMODEM_OPTION_TO_TEST IN LISTS NR_UESOFTMODEM_OPTION_TO_TEST_LIST)
|
||||
add_test(
|
||||
NAME ue_coding_rfsim_${NR_UESOFTMODEM_OPTION_TO_TEST}
|
||||
COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/ue_coding_rfsim.sh ${${NR_UESOFTMODEM_OPTION_TO_TEST}}
|
||||
COMMAND_EXPAND_LISTS
|
||||
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
|
||||
)
|
||||
endforeach()
|
||||
|
||||
268
openair1/PHY/CODING/tests/gnb.sa.band78.106prb.rfsim.2x2.conf
Normal file
268
openair1/PHY/CODING/tests/gnb.sa.band78.106prb.rfsim.2x2.conf
Normal file
@@ -0,0 +1,268 @@
|
||||
Active_gNBs = ( "gNB-OAI");
|
||||
# Asn1_verbosity, choice in: none, info, annoying
|
||||
Asn1_verbosity = "none";
|
||||
|
||||
gNBs =
|
||||
(
|
||||
{
|
||||
////////// Identification parameters:
|
||||
gNB_ID = 0xe00;
|
||||
gNB_name = "gNB-OAI";
|
||||
|
||||
// Tracking area code, 0x0000 and 0xfffe are reserved values
|
||||
tracking_area_code = 1;
|
||||
plmn_list = ({ mcc = 208; mnc = 99; mnc_length = 2; snssaiList = ({ sst = 1 }) });
|
||||
|
||||
nr_cellid = 12345678L;
|
||||
|
||||
////////// Physical parameters:
|
||||
|
||||
pdsch_AntennaPorts_XP = 2;
|
||||
pusch_AntennaPorts = 2;
|
||||
do_CSIRS = 1;
|
||||
do_SRS = 1;
|
||||
min_rxtxtime = 5;
|
||||
|
||||
servingCellConfigCommon = (
|
||||
{
|
||||
#spCellConfigCommon
|
||||
|
||||
physCellId = 0;
|
||||
|
||||
# downlinkConfigCommon
|
||||
#frequencyInfoDL
|
||||
# this is 3300.60 MHz + 53*12*30e-3 MHz = 3319.68
|
||||
absoluteFrequencySSB = 621312;
|
||||
dl_frequencyBand = 78;
|
||||
# this is 3300.60 MHz
|
||||
dl_absoluteFrequencyPointA = 620040;
|
||||
#scs-SpecificCarrierList
|
||||
dl_offstToCarrier = 0;
|
||||
# subcarrierSpacing
|
||||
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
|
||||
dl_subcarrierSpacing = 1;
|
||||
dl_carrierBandwidth = 106;
|
||||
#initialDownlinkBWP
|
||||
#genericParameters
|
||||
# this is RBstart=27,L=48 (275*(L-1))+RBstart
|
||||
initialDLBWPlocationAndBandwidth = 28875; # 6366 12925 12956 28875 12952
|
||||
# subcarrierSpacing
|
||||
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
|
||||
initialDLBWPsubcarrierSpacing = 1;
|
||||
#pdcch-ConfigCommon
|
||||
initialDLBWPcontrolResourceSetZero = 12;
|
||||
initialDLBWPsearchSpaceZero = 0;
|
||||
|
||||
#uplinkConfigCommon
|
||||
#frequencyInfoUL
|
||||
ul_frequencyBand = 78;
|
||||
#scs-SpecificCarrierList
|
||||
ul_offstToCarrier = 0;
|
||||
# subcarrierSpacing
|
||||
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
|
||||
ul_subcarrierSpacing = 1;
|
||||
ul_carrierBandwidth = 106;
|
||||
pMax = 20;
|
||||
#initialUplinkBWP
|
||||
#genericParameters
|
||||
initialULBWPlocationAndBandwidth = 28875;
|
||||
# subcarrierSpacing
|
||||
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
|
||||
initialULBWPsubcarrierSpacing = 1;
|
||||
#rach-ConfigCommon
|
||||
#rach-ConfigGeneric
|
||||
prach_ConfigurationIndex = 98;
|
||||
#prach_msg1_FDM
|
||||
#0 = one, 1=two, 2=four, 3=eight
|
||||
prach_msg1_FDM = 0;
|
||||
prach_msg1_FrequencyStart = 0;
|
||||
zeroCorrelationZoneConfig = 12;
|
||||
preambleReceivedTargetPower = -96;
|
||||
#preamblTransMax (0...10) = (3,4,5,6,7,8,10,20,50,100,200)
|
||||
preambleTransMax = 6;
|
||||
#powerRampingStep
|
||||
# 0=dB0,1=dB2,2=dB4,3=dB6
|
||||
powerRampingStep = 1;
|
||||
#ra_ReponseWindow
|
||||
#1,2,4,8,10,20,40,80
|
||||
ra_ResponseWindow = 4;
|
||||
#ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR
|
||||
#1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen
|
||||
ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 3;
|
||||
#oneHalf (0..15) 4,8,12,16,...60,64
|
||||
ssb_perRACH_OccasionAndCB_PreamblesPerSSB = 15;
|
||||
#ra_ContentionResolutionTimer
|
||||
#(0..7) 8,16,24,32,40,48,56,64
|
||||
ra_ContentionResolutionTimer = 7;
|
||||
rsrp_ThresholdSSB = 19;
|
||||
#prach-RootSequenceIndex_PR
|
||||
#1 = 839, 2 = 139
|
||||
prach_RootSequenceIndex_PR = 2;
|
||||
prach_RootSequenceIndex = 1;
|
||||
# SCS for msg1, can only be 15 for 30 kHz < 6 GHz, takes precendence over the one derived from prach-ConfigIndex
|
||||
#
|
||||
msg1_SubcarrierSpacing = 1,
|
||||
# restrictedSetConfig
|
||||
# 0=unrestricted, 1=restricted type A, 2=restricted type B
|
||||
restrictedSetConfig = 0,
|
||||
|
||||
msg3_DeltaPreamble = 1;
|
||||
p0_NominalWithGrant =-90;
|
||||
|
||||
# pucch-ConfigCommon setup :
|
||||
# pucchGroupHopping
|
||||
# 0 = neither, 1= group hopping, 2=sequence hopping
|
||||
pucchGroupHopping = 0;
|
||||
hoppingId = 40;
|
||||
p0_nominal = -70;
|
||||
# ssb_PositionsInBurs_BitmapPR
|
||||
# 1=short, 2=medium, 3=long
|
||||
ssb_PositionsInBurst_PR = 2;
|
||||
ssb_PositionsInBurst_Bitmap = 1;
|
||||
|
||||
# ssb_periodicityServingCell
|
||||
# 0 = ms5, 1=ms10, 2=ms20, 3=ms40, 4=ms80, 5=ms160, 6=spare2, 7=spare1
|
||||
ssb_periodicityServingCell = 2;
|
||||
|
||||
# dmrs_TypeA_position
|
||||
# 0 = pos2, 1 = pos3
|
||||
dmrs_TypeA_Position = 0;
|
||||
|
||||
# subcarrierSpacing
|
||||
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
|
||||
subcarrierSpacing = 1;
|
||||
|
||||
|
||||
#tdd-UL-DL-ConfigurationCommon
|
||||
# subcarrierSpacing
|
||||
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
|
||||
referenceSubcarrierSpacing = 1;
|
||||
# pattern1
|
||||
# dl_UL_TransmissionPeriodicity
|
||||
# 0=ms0p5, 1=ms0p625, 2=ms1, 3=ms1p25, 4=ms2, 5=ms2p5, 6=ms5, 7=ms10
|
||||
dl_UL_TransmissionPeriodicity = 6;
|
||||
nrofDownlinkSlots = 7;
|
||||
nrofDownlinkSymbols = 6;
|
||||
nrofUplinkSlots = 2;
|
||||
nrofUplinkSymbols = 4;
|
||||
|
||||
ssPBCH_BlockPower = -25;
|
||||
}
|
||||
|
||||
);
|
||||
|
||||
# ------- SCTP definitions
|
||||
SCTP :
|
||||
{
|
||||
# Number of streams to use in input/output
|
||||
SCTP_INSTREAMS = 2;
|
||||
SCTP_OUTSTREAMS = 2;
|
||||
};
|
||||
|
||||
|
||||
////////// AMF parameters:
|
||||
amf_ip_address = ( { ipv4 = "172.21.6.5";
|
||||
ipv6 = "192:168:30::17";
|
||||
active = "yes";
|
||||
preference = "ipv4";
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
NETWORK_INTERFACES :
|
||||
{
|
||||
GNB_INTERFACE_NAME_FOR_NG_AMF = "enp193s0f0";
|
||||
GNB_IPV4_ADDRESS_FOR_NG_AMF = "172.21.16.51/22";
|
||||
GNB_INTERFACE_NAME_FOR_NGU = "enp193s0f0";
|
||||
GNB_IPV4_ADDRESS_FOR_NGU = "172.21.16.51/22";
|
||||
GNB_PORT_FOR_S1U = 2152; # Spec 2152
|
||||
};
|
||||
|
||||
}
|
||||
);
|
||||
|
||||
MACRLCs = (
|
||||
{
|
||||
num_cc = 1;
|
||||
tr_s_preference = "local_L1";
|
||||
tr_n_preference = "local_RRC";
|
||||
#pusch_TargetSNRx10 = 150;
|
||||
#pucch_TargetSNRx10 = 200;
|
||||
dl_max_mcs = 16; # there are retransmissions if more
|
||||
}
|
||||
);
|
||||
|
||||
L1s = (
|
||||
{
|
||||
num_cc = 1;
|
||||
tr_n_preference = "local_mac";
|
||||
prach_dtx_threshold = 120;
|
||||
#pucch0_dtx_threshold = 120;
|
||||
}
|
||||
);
|
||||
|
||||
RUs = (
|
||||
{
|
||||
local_rf = "yes"
|
||||
nb_tx = 2
|
||||
nb_rx = 2
|
||||
att_tx = 0
|
||||
att_rx = 0;
|
||||
bands = [78];
|
||||
max_pdschReferenceSignalPower = -27;
|
||||
max_rxgain = 75;
|
||||
eNB_instances = [0];
|
||||
##beamforming 1x2 matrix: 1 layer x 2 antennas
|
||||
bf_weights = [0x00007fff, 0x0000];
|
||||
#clock_src = "internal";
|
||||
sdr_addrs = "mgmt_addr=192.168.10.2,addr=192.168.10.2,clock_source=internal,time_source=internal"
|
||||
}
|
||||
);
|
||||
|
||||
THREAD_STRUCT = (
|
||||
{
|
||||
#three config for level of parallelism "PARALLEL_SINGLE_THREAD", "PARALLEL_RU_L1_SPLIT", or "PARALLEL_RU_L1_TRX_SPLIT"
|
||||
parallel_config = "PARALLEL_SINGLE_THREAD";
|
||||
#two option for worker "WORKER_DISABLE" or "WORKER_ENABLE"
|
||||
worker_config = "WORKER_ENABLE";
|
||||
}
|
||||
);
|
||||
|
||||
rfsimulator :
|
||||
{
|
||||
serveraddr = "server";
|
||||
serverport = 4043;
|
||||
options = (); #("saviq"); or/and "chanmod"
|
||||
modelname = "AWGN";
|
||||
IQfile = "/tmp/rfsimulator.iqs";
|
||||
};
|
||||
|
||||
security = {
|
||||
# preferred ciphering algorithms
|
||||
# the first one of the list that an UE supports in chosen
|
||||
# valid values: nea0, nea1, nea2, nea3
|
||||
ciphering_algorithms = ( "nea0" );
|
||||
|
||||
# preferred integrity algorithms
|
||||
# the first one of the list that an UE supports in chosen
|
||||
# valid values: nia0, nia1, nia2, nia3
|
||||
integrity_algorithms = ( "nia2", "nia0" );
|
||||
|
||||
# setting 'drb_ciphering' to "no" disables ciphering for DRBs, no matter
|
||||
# what 'ciphering_algorithms' configures; same thing for 'drb_integrity'
|
||||
drb_ciphering = "yes";
|
||||
drb_integrity = "no";
|
||||
};
|
||||
|
||||
log_config :
|
||||
{
|
||||
global_log_level ="info";
|
||||
hw_log_level ="info";
|
||||
phy_log_level ="info";
|
||||
mac_log_level ="info";
|
||||
rlc_log_level ="info";
|
||||
pdcp_log_level ="info";
|
||||
rrc_log_level ="info";
|
||||
ngap_log_level ="debug";
|
||||
f1ap_log_level ="info";
|
||||
};
|
||||
@@ -0,0 +1,279 @@
|
||||
Active_gNBs = ( "gNB-OAI");
|
||||
# Asn1_verbosity, choice in: none, info, annoying
|
||||
Asn1_verbosity = "none";
|
||||
|
||||
gNBs =
|
||||
(
|
||||
{
|
||||
////////// Identification parameters:
|
||||
gNB_ID = 0xe00;
|
||||
gNB_name = "gNB-OAI";
|
||||
|
||||
// Tracking area code, 0x0000 and 0xfffe are reserved values
|
||||
tracking_area_code = 1;
|
||||
plmn_list = ({ mcc = 208; mnc = 99; mnc_length = 2; snssaiList = ({ sst = 1 }) });
|
||||
|
||||
nr_cellid = 12345678L;
|
||||
|
||||
////////// Physical parameters:
|
||||
|
||||
pdsch_AntennaPorts_XP = 2;
|
||||
pusch_AntennaPorts = 2;
|
||||
do_CSIRS = 1;
|
||||
do_SRS = 1;
|
||||
min_rxtxtime = 5;
|
||||
|
||||
servingCellConfigCommon = (
|
||||
{
|
||||
#spCellConfigCommon
|
||||
|
||||
physCellId = 0;
|
||||
|
||||
# downlinkConfigCommon
|
||||
#frequencyInfoDL
|
||||
# this is 3300.60 MHz + 53*12*30e-3 MHz = 3319.68
|
||||
absoluteFrequencySSB = 621312;
|
||||
dl_frequencyBand = 78;
|
||||
# this is 3300.60 MHz
|
||||
dl_absoluteFrequencyPointA = 620040;
|
||||
#scs-SpecificCarrierList
|
||||
dl_offstToCarrier = 0;
|
||||
# subcarrierSpacing
|
||||
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
|
||||
dl_subcarrierSpacing = 1;
|
||||
dl_carrierBandwidth = 106;
|
||||
#initialDownlinkBWP
|
||||
#genericParameters
|
||||
# this is RBstart=27,L=48 (275*(L-1))+RBstart
|
||||
initialDLBWPlocationAndBandwidth = 28875; # 6366 12925 12956 28875 12952
|
||||
# subcarrierSpacing
|
||||
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
|
||||
initialDLBWPsubcarrierSpacing = 1;
|
||||
#pdcch-ConfigCommon
|
||||
initialDLBWPcontrolResourceSetZero = 12;
|
||||
initialDLBWPsearchSpaceZero = 0;
|
||||
|
||||
#uplinkConfigCommon
|
||||
#frequencyInfoUL
|
||||
ul_frequencyBand = 78;
|
||||
#scs-SpecificCarrierList
|
||||
ul_offstToCarrier = 0;
|
||||
# subcarrierSpacing
|
||||
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
|
||||
ul_subcarrierSpacing = 1;
|
||||
ul_carrierBandwidth = 106;
|
||||
pMax = 20;
|
||||
#initialUplinkBWP
|
||||
#genericParameters
|
||||
initialULBWPlocationAndBandwidth = 28875;
|
||||
# subcarrierSpacing
|
||||
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
|
||||
initialULBWPsubcarrierSpacing = 1;
|
||||
#rach-ConfigCommon
|
||||
#rach-ConfigGeneric
|
||||
prach_ConfigurationIndex = 98;
|
||||
#prach_msg1_FDM
|
||||
#0 = one, 1=two, 2=four, 3=eight
|
||||
prach_msg1_FDM = 0;
|
||||
prach_msg1_FrequencyStart = 0;
|
||||
zeroCorrelationZoneConfig = 12;
|
||||
preambleReceivedTargetPower = -96;
|
||||
#preamblTransMax (0...10) = (3,4,5,6,7,8,10,20,50,100,200)
|
||||
preambleTransMax = 6;
|
||||
#powerRampingStep
|
||||
# 0=dB0,1=dB2,2=dB4,3=dB6
|
||||
powerRampingStep = 1;
|
||||
#ra_ReponseWindow
|
||||
#1,2,4,8,10,20,40,80
|
||||
ra_ResponseWindow = 4;
|
||||
#ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR
|
||||
#1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen
|
||||
ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 3;
|
||||
#oneHalf (0..15) 4,8,12,16,...60,64
|
||||
ssb_perRACH_OccasionAndCB_PreamblesPerSSB = 15;
|
||||
#ra_ContentionResolutionTimer
|
||||
#(0..7) 8,16,24,32,40,48,56,64
|
||||
ra_ContentionResolutionTimer = 7;
|
||||
rsrp_ThresholdSSB = 19;
|
||||
#prach-RootSequenceIndex_PR
|
||||
#1 = 839, 2 = 139
|
||||
prach_RootSequenceIndex_PR = 2;
|
||||
prach_RootSequenceIndex = 1;
|
||||
# SCS for msg1, can only be 15 for 30 kHz < 6 GHz, takes precendence over the one derived from prach-ConfigIndex
|
||||
#
|
||||
msg1_SubcarrierSpacing = 1,
|
||||
# restrictedSetConfig
|
||||
# 0=unrestricted, 1=restricted type A, 2=restricted type B
|
||||
restrictedSetConfig = 0,
|
||||
|
||||
msg3_DeltaPreamble = 1;
|
||||
p0_NominalWithGrant =-90;
|
||||
|
||||
# pucch-ConfigCommon setup :
|
||||
# pucchGroupHopping
|
||||
# 0 = neither, 1= group hopping, 2=sequence hopping
|
||||
pucchGroupHopping = 0;
|
||||
hoppingId = 40;
|
||||
p0_nominal = -70;
|
||||
# ssb_PositionsInBurs_BitmapPR
|
||||
# 1=short, 2=medium, 3=long
|
||||
ssb_PositionsInBurst_PR = 2;
|
||||
ssb_PositionsInBurst_Bitmap = 1;
|
||||
|
||||
# ssb_periodicityServingCell
|
||||
# 0 = ms5, 1=ms10, 2=ms20, 3=ms40, 4=ms80, 5=ms160, 6=spare2, 7=spare1
|
||||
ssb_periodicityServingCell = 2;
|
||||
|
||||
# dmrs_TypeA_position
|
||||
# 0 = pos2, 1 = pos3
|
||||
dmrs_TypeA_Position = 0;
|
||||
|
||||
# subcarrierSpacing
|
||||
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
|
||||
subcarrierSpacing = 1;
|
||||
|
||||
|
||||
#tdd-UL-DL-ConfigurationCommon
|
||||
# subcarrierSpacing
|
||||
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
|
||||
referenceSubcarrierSpacing = 1;
|
||||
# pattern1
|
||||
# dl_UL_TransmissionPeriodicity
|
||||
# 0=ms0p5, 1=ms0p625, 2=ms1, 3=ms1p25, 4=ms2, 5=ms2p5, 6=ms5, 7=ms10
|
||||
dl_UL_TransmissionPeriodicity = 6;
|
||||
nrofDownlinkSlots = 7;
|
||||
nrofDownlinkSymbols = 6;
|
||||
nrofUplinkSlots = 2;
|
||||
nrofUplinkSymbols = 4;
|
||||
|
||||
ssPBCH_BlockPower = -25;
|
||||
}
|
||||
|
||||
);
|
||||
|
||||
# ------- SCTP definitions
|
||||
SCTP :
|
||||
{
|
||||
# Number of streams to use in input/output
|
||||
SCTP_INSTREAMS = 2;
|
||||
SCTP_OUTSTREAMS = 2;
|
||||
};
|
||||
|
||||
|
||||
////////// AMF parameters:
|
||||
amf_ip_address = ( { ipv4 = "172.21.6.5";
|
||||
ipv6 = "192:168:30::17";
|
||||
active = "yes";
|
||||
preference = "ipv4";
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
NETWORK_INTERFACES :
|
||||
{
|
||||
GNB_INTERFACE_NAME_FOR_NG_AMF = "enp193s0f0";
|
||||
GNB_IPV4_ADDRESS_FOR_NG_AMF = "172.21.16.51/22";
|
||||
GNB_INTERFACE_NAME_FOR_NGU = "enp193s0f0";
|
||||
GNB_IPV4_ADDRESS_FOR_NGU = "172.21.16.51/22";
|
||||
GNB_PORT_FOR_S1U = 2152; # Spec 2152
|
||||
};
|
||||
|
||||
}
|
||||
);
|
||||
|
||||
MACRLCs = (
|
||||
{
|
||||
num_cc = 1;
|
||||
tr_s_preference = "local_L1";
|
||||
tr_n_preference = "local_RRC";
|
||||
#pusch_TargetSNRx10 = 150;
|
||||
#pucch_TargetSNRx10 = 200;
|
||||
dl_max_mcs = 16; # there are retransmissions if more
|
||||
}
|
||||
);
|
||||
|
||||
L1s = (
|
||||
{
|
||||
num_cc = 1;
|
||||
tr_n_preference = "local_mac";
|
||||
prach_dtx_threshold = 120;
|
||||
#pucch0_dtx_threshold = 120;
|
||||
}
|
||||
);
|
||||
|
||||
RUs = (
|
||||
{
|
||||
local_rf = "yes"
|
||||
nb_tx = 2
|
||||
nb_rx = 2
|
||||
att_tx = 0
|
||||
att_rx = 0;
|
||||
bands = [78];
|
||||
max_pdschReferenceSignalPower = -27;
|
||||
max_rxgain = 75;
|
||||
eNB_instances = [0];
|
||||
##beamforming 1x2 matrix: 1 layer x 2 antennas
|
||||
bf_weights = [0x00007fff, 0x0000];
|
||||
#clock_src = "internal";
|
||||
sdr_addrs = "mgmt_addr=192.168.10.2,addr=192.168.10.2,clock_source=internal,time_source=internal"
|
||||
}
|
||||
);
|
||||
|
||||
THREAD_STRUCT = (
|
||||
{
|
||||
#three config for level of parallelism "PARALLEL_SINGLE_THREAD", "PARALLEL_RU_L1_SPLIT", or "PARALLEL_RU_L1_TRX_SPLIT"
|
||||
parallel_config = "PARALLEL_SINGLE_THREAD";
|
||||
#two option for worker "WORKER_DISABLE" or "WORKER_ENABLE"
|
||||
worker_config = "WORKER_ENABLE";
|
||||
}
|
||||
);
|
||||
|
||||
rfsimulator :
|
||||
{
|
||||
serveraddr = "server";
|
||||
serverport = 4043;
|
||||
options = (); #("saviq"); or/and "chanmod"
|
||||
modelname = "AWGN";
|
||||
IQfile = "/tmp/rfsimulator.iqs";
|
||||
};
|
||||
|
||||
security = {
|
||||
# preferred ciphering algorithms
|
||||
# the first one of the list that an UE supports in chosen
|
||||
# valid values: nea0, nea1, nea2, nea3
|
||||
ciphering_algorithms = ( "nea0" );
|
||||
|
||||
# preferred integrity algorithms
|
||||
# the first one of the list that an UE supports in chosen
|
||||
# valid values: nia0, nia1, nia2, nia3
|
||||
integrity_algorithms = ( "nia2", "nia0" );
|
||||
|
||||
# setting 'drb_ciphering' to "no" disables ciphering for DRBs, no matter
|
||||
# what 'ciphering_algorithms' configures; same thing for 'drb_integrity'
|
||||
drb_ciphering = "yes";
|
||||
drb_integrity = "no";
|
||||
};
|
||||
|
||||
log_config :
|
||||
{
|
||||
global_log_level ="info";
|
||||
hw_log_level ="info";
|
||||
phy_log_level ="info";
|
||||
mac_log_level ="info";
|
||||
rlc_log_level ="info";
|
||||
pdcp_log_level ="info";
|
||||
rrc_log_level ="info";
|
||||
ngap_log_level ="debug";
|
||||
f1ap_log_level ="info";
|
||||
};
|
||||
|
||||
nrLDPC_coding_t2 : {
|
||||
dpdk_dev : "41:00.0";
|
||||
dpdk_core_list : "14-15";
|
||||
};
|
||||
|
||||
loader : {
|
||||
ldpc : {
|
||||
shlibversion : "_slot_t2";
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,278 @@
|
||||
Active_gNBs = ( "gNB-OAI");
|
||||
# Asn1_verbosity, choice in: none, info, annoying
|
||||
Asn1_verbosity = "none";
|
||||
|
||||
gNBs =
|
||||
(
|
||||
{
|
||||
////////// Identification parameters:
|
||||
gNB_ID = 0xe00;
|
||||
gNB_name = "gNB-OAI";
|
||||
|
||||
// Tracking area code, 0x0000 and 0xfffe are reserved values
|
||||
tracking_area_code = 1;
|
||||
plmn_list = ({ mcc = 208; mnc = 99; mnc_length = 2; snssaiList = ({ sst = 1 }) });
|
||||
|
||||
nr_cellid = 12345678L;
|
||||
|
||||
////////// Physical parameters:
|
||||
|
||||
pdsch_AntennaPorts_XP = 2;
|
||||
pusch_AntennaPorts = 2;
|
||||
do_CSIRS = 1;
|
||||
do_SRS = 1;
|
||||
min_rxtxtime = 5;
|
||||
|
||||
servingCellConfigCommon = (
|
||||
{
|
||||
#spCellConfigCommon
|
||||
|
||||
physCellId = 0;
|
||||
|
||||
# downlinkConfigCommon
|
||||
#frequencyInfoDL
|
||||
# this is 3300.60 MHz + 53*12*30e-3 MHz = 3319.68
|
||||
absoluteFrequencySSB = 621312;
|
||||
dl_frequencyBand = 78;
|
||||
# this is 3300.60 MHz
|
||||
dl_absoluteFrequencyPointA = 620040;
|
||||
#scs-SpecificCarrierList
|
||||
dl_offstToCarrier = 0;
|
||||
# subcarrierSpacing
|
||||
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
|
||||
dl_subcarrierSpacing = 1;
|
||||
dl_carrierBandwidth = 106;
|
||||
#initialDownlinkBWP
|
||||
#genericParameters
|
||||
# this is RBstart=27,L=48 (275*(L-1))+RBstart
|
||||
initialDLBWPlocationAndBandwidth = 28875; # 6366 12925 12956 28875 12952
|
||||
# subcarrierSpacing
|
||||
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
|
||||
initialDLBWPsubcarrierSpacing = 1;
|
||||
#pdcch-ConfigCommon
|
||||
initialDLBWPcontrolResourceSetZero = 12;
|
||||
initialDLBWPsearchSpaceZero = 0;
|
||||
|
||||
#uplinkConfigCommon
|
||||
#frequencyInfoUL
|
||||
ul_frequencyBand = 78;
|
||||
#scs-SpecificCarrierList
|
||||
ul_offstToCarrier = 0;
|
||||
# subcarrierSpacing
|
||||
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
|
||||
ul_subcarrierSpacing = 1;
|
||||
ul_carrierBandwidth = 106;
|
||||
pMax = 20;
|
||||
#initialUplinkBWP
|
||||
#genericParameters
|
||||
initialULBWPlocationAndBandwidth = 28875;
|
||||
# subcarrierSpacing
|
||||
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
|
||||
initialULBWPsubcarrierSpacing = 1;
|
||||
#rach-ConfigCommon
|
||||
#rach-ConfigGeneric
|
||||
prach_ConfigurationIndex = 98;
|
||||
#prach_msg1_FDM
|
||||
#0 = one, 1=two, 2=four, 3=eight
|
||||
prach_msg1_FDM = 0;
|
||||
prach_msg1_FrequencyStart = 0;
|
||||
zeroCorrelationZoneConfig = 12;
|
||||
preambleReceivedTargetPower = -96;
|
||||
#preamblTransMax (0...10) = (3,4,5,6,7,8,10,20,50,100,200)
|
||||
preambleTransMax = 6;
|
||||
#powerRampingStep
|
||||
# 0=dB0,1=dB2,2=dB4,3=dB6
|
||||
powerRampingStep = 1;
|
||||
#ra_ReponseWindow
|
||||
#1,2,4,8,10,20,40,80
|
||||
ra_ResponseWindow = 4;
|
||||
#ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR
|
||||
#1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen
|
||||
ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 3;
|
||||
#oneHalf (0..15) 4,8,12,16,...60,64
|
||||
ssb_perRACH_OccasionAndCB_PreamblesPerSSB = 15;
|
||||
#ra_ContentionResolutionTimer
|
||||
#(0..7) 8,16,24,32,40,48,56,64
|
||||
ra_ContentionResolutionTimer = 7;
|
||||
rsrp_ThresholdSSB = 19;
|
||||
#prach-RootSequenceIndex_PR
|
||||
#1 = 839, 2 = 139
|
||||
prach_RootSequenceIndex_PR = 2;
|
||||
prach_RootSequenceIndex = 1;
|
||||
# SCS for msg1, can only be 15 for 30 kHz < 6 GHz, takes precendence over the one derived from prach-ConfigIndex
|
||||
#
|
||||
msg1_SubcarrierSpacing = 1,
|
||||
# restrictedSetConfig
|
||||
# 0=unrestricted, 1=restricted type A, 2=restricted type B
|
||||
restrictedSetConfig = 0,
|
||||
|
||||
msg3_DeltaPreamble = 1;
|
||||
p0_NominalWithGrant =-90;
|
||||
|
||||
# pucch-ConfigCommon setup :
|
||||
# pucchGroupHopping
|
||||
# 0 = neither, 1= group hopping, 2=sequence hopping
|
||||
pucchGroupHopping = 0;
|
||||
hoppingId = 40;
|
||||
p0_nominal = -70;
|
||||
# ssb_PositionsInBurs_BitmapPR
|
||||
# 1=short, 2=medium, 3=long
|
||||
ssb_PositionsInBurst_PR = 2;
|
||||
ssb_PositionsInBurst_Bitmap = 1;
|
||||
|
||||
# ssb_periodicityServingCell
|
||||
# 0 = ms5, 1=ms10, 2=ms20, 3=ms40, 4=ms80, 5=ms160, 6=spare2, 7=spare1
|
||||
ssb_periodicityServingCell = 2;
|
||||
|
||||
# dmrs_TypeA_position
|
||||
# 0 = pos2, 1 = pos3
|
||||
dmrs_TypeA_Position = 0;
|
||||
|
||||
# subcarrierSpacing
|
||||
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
|
||||
subcarrierSpacing = 1;
|
||||
|
||||
|
||||
#tdd-UL-DL-ConfigurationCommon
|
||||
# subcarrierSpacing
|
||||
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
|
||||
referenceSubcarrierSpacing = 1;
|
||||
# pattern1
|
||||
# dl_UL_TransmissionPeriodicity
|
||||
# 0=ms0p5, 1=ms0p625, 2=ms1, 3=ms1p25, 4=ms2, 5=ms2p5, 6=ms5, 7=ms10
|
||||
dl_UL_TransmissionPeriodicity = 6;
|
||||
nrofDownlinkSlots = 7;
|
||||
nrofDownlinkSymbols = 6;
|
||||
nrofUplinkSlots = 2;
|
||||
nrofUplinkSymbols = 4;
|
||||
|
||||
ssPBCH_BlockPower = -25;
|
||||
}
|
||||
|
||||
);
|
||||
|
||||
# ------- SCTP definitions
|
||||
SCTP :
|
||||
{
|
||||
# Number of streams to use in input/output
|
||||
SCTP_INSTREAMS = 2;
|
||||
SCTP_OUTSTREAMS = 2;
|
||||
};
|
||||
|
||||
|
||||
////////// AMF parameters:
|
||||
amf_ip_address = ( { ipv4 = "172.21.6.5";
|
||||
ipv6 = "192:168:30::17";
|
||||
active = "yes";
|
||||
preference = "ipv4";
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
NETWORK_INTERFACES :
|
||||
{
|
||||
GNB_INTERFACE_NAME_FOR_NG_AMF = "enp193s0f0";
|
||||
GNB_IPV4_ADDRESS_FOR_NG_AMF = "172.21.16.51/22";
|
||||
GNB_INTERFACE_NAME_FOR_NGU = "enp193s0f0";
|
||||
GNB_IPV4_ADDRESS_FOR_NGU = "172.21.16.51/22";
|
||||
GNB_PORT_FOR_S1U = 2152; # Spec 2152
|
||||
};
|
||||
|
||||
}
|
||||
);
|
||||
|
||||
MACRLCs = (
|
||||
{
|
||||
num_cc = 1;
|
||||
tr_s_preference = "local_L1";
|
||||
tr_n_preference = "local_RRC";
|
||||
#pusch_TargetSNRx10 = 150;
|
||||
#pucch_TargetSNRx10 = 200;
|
||||
dl_max_mcs = 16; # there are retransmissions if more
|
||||
}
|
||||
);
|
||||
|
||||
L1s = (
|
||||
{
|
||||
num_cc = 1;
|
||||
tr_n_preference = "local_mac";
|
||||
prach_dtx_threshold = 120;
|
||||
#pucch0_dtx_threshold = 120;
|
||||
}
|
||||
);
|
||||
|
||||
RUs = (
|
||||
{
|
||||
local_rf = "yes"
|
||||
nb_tx = 2
|
||||
nb_rx = 2
|
||||
att_tx = 0
|
||||
att_rx = 0;
|
||||
bands = [78];
|
||||
max_pdschReferenceSignalPower = -27;
|
||||
max_rxgain = 75;
|
||||
eNB_instances = [0];
|
||||
##beamforming 1x2 matrix: 1 layer x 2 antennas
|
||||
bf_weights = [0x00007fff, 0x0000];
|
||||
#clock_src = "internal";
|
||||
sdr_addrs = "mgmt_addr=192.168.10.2,addr=192.168.10.2,clock_source=internal,time_source=internal"
|
||||
}
|
||||
);
|
||||
|
||||
THREAD_STRUCT = (
|
||||
{
|
||||
#three config for level of parallelism "PARALLEL_SINGLE_THREAD", "PARALLEL_RU_L1_SPLIT", or "PARALLEL_RU_L1_TRX_SPLIT"
|
||||
parallel_config = "PARALLEL_SINGLE_THREAD";
|
||||
#two option for worker "WORKER_DISABLE" or "WORKER_ENABLE"
|
||||
worker_config = "WORKER_ENABLE";
|
||||
}
|
||||
);
|
||||
|
||||
rfsimulator :
|
||||
{
|
||||
serveraddr = "server";
|
||||
serverport = 4043;
|
||||
options = (); #("saviq"); or/and "chanmod"
|
||||
modelname = "AWGN";
|
||||
IQfile = "/tmp/rfsimulator.iqs";
|
||||
};
|
||||
|
||||
security = {
|
||||
# preferred ciphering algorithms
|
||||
# the first one of the list that an UE supports in chosen
|
||||
# valid values: nea0, nea1, nea2, nea3
|
||||
ciphering_algorithms = ( "nea0" );
|
||||
|
||||
# preferred integrity algorithms
|
||||
# the first one of the list that an UE supports in chosen
|
||||
# valid values: nia0, nia1, nia2, nia3
|
||||
integrity_algorithms = ( "nia2", "nia0" );
|
||||
|
||||
# setting 'drb_ciphering' to "no" disables ciphering for DRBs, no matter
|
||||
# what 'ciphering_algorithms' configures; same thing for 'drb_integrity'
|
||||
drb_ciphering = "yes";
|
||||
drb_integrity = "no";
|
||||
};
|
||||
|
||||
log_config :
|
||||
{
|
||||
global_log_level ="info";
|
||||
hw_log_level ="info";
|
||||
phy_log_level ="info";
|
||||
mac_log_level ="info";
|
||||
rlc_log_level ="info";
|
||||
pdcp_log_level ="info";
|
||||
rrc_log_level ="info";
|
||||
ngap_log_level ="debug";
|
||||
f1ap_log_level ="info";
|
||||
};
|
||||
|
||||
nrLDPC_coding_xdma : {
|
||||
num_threads_prepare : 2;
|
||||
};
|
||||
|
||||
loader : {
|
||||
ldpc : {
|
||||
shlibversion : "_xdma";
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,273 @@
|
||||
Active_gNBs = ( "gNB-OAI");
|
||||
# Asn1_verbosity, choice in: none, info, annoying
|
||||
Asn1_verbosity = "none";
|
||||
|
||||
gNBs =
|
||||
(
|
||||
{
|
||||
////////// Identification parameters:
|
||||
gNB_ID = 0xe00;
|
||||
gNB_name = "gNB-OAI";
|
||||
|
||||
// Tracking area code, 0x0000 and 0xfffe are reserved values
|
||||
tracking_area_code = 1;
|
||||
plmn_list = ({ mcc = 208; mnc = 99; mnc_length = 2; snssaiList = ({ sst = 1 }) });
|
||||
|
||||
nr_cellid = 12345678L;
|
||||
|
||||
////////// Physical parameters:
|
||||
|
||||
pdsch_AntennaPorts_XP = 2;
|
||||
pusch_AntennaPorts = 2;
|
||||
do_CSIRS = 1;
|
||||
do_SRS = 1;
|
||||
min_rxtxtime = 5;
|
||||
|
||||
servingCellConfigCommon = (
|
||||
{
|
||||
#spCellConfigCommon
|
||||
|
||||
physCellId = 0;
|
||||
|
||||
# downlinkConfigCommon
|
||||
#frequencyInfoDL
|
||||
# this is 3300.60 MHz + 53*12*30e-3 MHz = 3319.68
|
||||
absoluteFrequencySSB = 621312;
|
||||
dl_frequencyBand = 78;
|
||||
# this is 3300.60 MHz
|
||||
dl_absoluteFrequencyPointA = 620040;
|
||||
#scs-SpecificCarrierList
|
||||
dl_offstToCarrier = 0;
|
||||
# subcarrierSpacing
|
||||
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
|
||||
dl_subcarrierSpacing = 1;
|
||||
dl_carrierBandwidth = 106;
|
||||
#initialDownlinkBWP
|
||||
#genericParameters
|
||||
# this is RBstart=27,L=48 (275*(L-1))+RBstart
|
||||
initialDLBWPlocationAndBandwidth = 28875; # 6366 12925 12956 28875 12952
|
||||
# subcarrierSpacing
|
||||
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
|
||||
initialDLBWPsubcarrierSpacing = 1;
|
||||
#pdcch-ConfigCommon
|
||||
initialDLBWPcontrolResourceSetZero = 12;
|
||||
initialDLBWPsearchSpaceZero = 0;
|
||||
|
||||
#uplinkConfigCommon
|
||||
#frequencyInfoUL
|
||||
ul_frequencyBand = 78;
|
||||
#scs-SpecificCarrierList
|
||||
ul_offstToCarrier = 0;
|
||||
# subcarrierSpacing
|
||||
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
|
||||
ul_subcarrierSpacing = 1;
|
||||
ul_carrierBandwidth = 106;
|
||||
pMax = 20;
|
||||
#initialUplinkBWP
|
||||
#genericParameters
|
||||
initialULBWPlocationAndBandwidth = 28875;
|
||||
# subcarrierSpacing
|
||||
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
|
||||
initialULBWPsubcarrierSpacing = 1;
|
||||
#rach-ConfigCommon
|
||||
#rach-ConfigGeneric
|
||||
prach_ConfigurationIndex = 98;
|
||||
#prach_msg1_FDM
|
||||
#0 = one, 1=two, 2=four, 3=eight
|
||||
prach_msg1_FDM = 0;
|
||||
prach_msg1_FrequencyStart = 0;
|
||||
zeroCorrelationZoneConfig = 12;
|
||||
preambleReceivedTargetPower = -96;
|
||||
#preamblTransMax (0...10) = (3,4,5,6,7,8,10,20,50,100,200)
|
||||
preambleTransMax = 6;
|
||||
#powerRampingStep
|
||||
# 0=dB0,1=dB2,2=dB4,3=dB6
|
||||
powerRampingStep = 1;
|
||||
#ra_ReponseWindow
|
||||
#1,2,4,8,10,20,40,80
|
||||
ra_ResponseWindow = 4;
|
||||
#ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR
|
||||
#1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen
|
||||
ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 3;
|
||||
#oneHalf (0..15) 4,8,12,16,...60,64
|
||||
ssb_perRACH_OccasionAndCB_PreamblesPerSSB = 15;
|
||||
#ra_ContentionResolutionTimer
|
||||
#(0..7) 8,16,24,32,40,48,56,64
|
||||
ra_ContentionResolutionTimer = 7;
|
||||
rsrp_ThresholdSSB = 19;
|
||||
#prach-RootSequenceIndex_PR
|
||||
#1 = 839, 2 = 139
|
||||
prach_RootSequenceIndex_PR = 2;
|
||||
prach_RootSequenceIndex = 1;
|
||||
# SCS for msg1, can only be 15 for 30 kHz < 6 GHz, takes precendence over the one derived from prach-ConfigIndex
|
||||
#
|
||||
msg1_SubcarrierSpacing = 1,
|
||||
# restrictedSetConfig
|
||||
# 0=unrestricted, 1=restricted type A, 2=restricted type B
|
||||
restrictedSetConfig = 0,
|
||||
|
||||
msg3_DeltaPreamble = 1;
|
||||
p0_NominalWithGrant =-90;
|
||||
|
||||
# pucch-ConfigCommon setup :
|
||||
# pucchGroupHopping
|
||||
# 0 = neither, 1= group hopping, 2=sequence hopping
|
||||
pucchGroupHopping = 0;
|
||||
hoppingId = 40;
|
||||
p0_nominal = -70;
|
||||
# ssb_PositionsInBurs_BitmapPR
|
||||
# 1=short, 2=medium, 3=long
|
||||
ssb_PositionsInBurst_PR = 2;
|
||||
ssb_PositionsInBurst_Bitmap = 1;
|
||||
|
||||
# ssb_periodicityServingCell
|
||||
# 0 = ms5, 1=ms10, 2=ms20, 3=ms40, 4=ms80, 5=ms160, 6=spare2, 7=spare1
|
||||
ssb_periodicityServingCell = 2;
|
||||
|
||||
# dmrs_TypeA_position
|
||||
# 0 = pos2, 1 = pos3
|
||||
dmrs_TypeA_Position = 0;
|
||||
|
||||
# subcarrierSpacing
|
||||
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
|
||||
subcarrierSpacing = 1;
|
||||
|
||||
|
||||
#tdd-UL-DL-ConfigurationCommon
|
||||
# subcarrierSpacing
|
||||
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
|
||||
referenceSubcarrierSpacing = 1;
|
||||
# pattern1
|
||||
# dl_UL_TransmissionPeriodicity
|
||||
# 0=ms0p5, 1=ms0p625, 2=ms1, 3=ms1p25, 4=ms2, 5=ms2p5, 6=ms5, 7=ms10
|
||||
dl_UL_TransmissionPeriodicity = 6;
|
||||
nrofDownlinkSlots = 7;
|
||||
nrofDownlinkSymbols = 6;
|
||||
nrofUplinkSlots = 2;
|
||||
nrofUplinkSymbols = 4;
|
||||
|
||||
ssPBCH_BlockPower = -25;
|
||||
}
|
||||
|
||||
);
|
||||
|
||||
# ------- SCTP definitions
|
||||
SCTP :
|
||||
{
|
||||
# Number of streams to use in input/output
|
||||
SCTP_INSTREAMS = 2;
|
||||
SCTP_OUTSTREAMS = 2;
|
||||
};
|
||||
|
||||
|
||||
////////// AMF parameters:
|
||||
amf_ip_address = ( { ipv4 = "172.21.6.5";
|
||||
ipv6 = "192:168:30::17";
|
||||
active = "yes";
|
||||
preference = "ipv4";
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
NETWORK_INTERFACES :
|
||||
{
|
||||
GNB_INTERFACE_NAME_FOR_NG_AMF = "enp193s0f0";
|
||||
GNB_IPV4_ADDRESS_FOR_NG_AMF = "172.21.16.51/22";
|
||||
GNB_INTERFACE_NAME_FOR_NGU = "enp193s0f0";
|
||||
GNB_IPV4_ADDRESS_FOR_NGU = "172.21.16.51/22";
|
||||
GNB_PORT_FOR_S1U = 2152; # Spec 2152
|
||||
};
|
||||
|
||||
}
|
||||
);
|
||||
|
||||
MACRLCs = (
|
||||
{
|
||||
num_cc = 1;
|
||||
tr_s_preference = "local_L1";
|
||||
tr_n_preference = "local_RRC";
|
||||
#pusch_TargetSNRx10 = 150;
|
||||
#pucch_TargetSNRx10 = 200;
|
||||
dl_max_mcs = 16; # there are retransmissions if more
|
||||
}
|
||||
);
|
||||
|
||||
L1s = (
|
||||
{
|
||||
num_cc = 1;
|
||||
tr_n_preference = "local_mac";
|
||||
prach_dtx_threshold = 120;
|
||||
#pucch0_dtx_threshold = 120;
|
||||
}
|
||||
);
|
||||
|
||||
RUs = (
|
||||
{
|
||||
local_rf = "yes"
|
||||
nb_tx = 2
|
||||
nb_rx = 2
|
||||
att_tx = 0
|
||||
att_rx = 0;
|
||||
bands = [78];
|
||||
max_pdschReferenceSignalPower = -27;
|
||||
max_rxgain = 75;
|
||||
eNB_instances = [0];
|
||||
##beamforming 1x2 matrix: 1 layer x 2 antennas
|
||||
bf_weights = [0x00007fff, 0x0000];
|
||||
#clock_src = "internal";
|
||||
sdr_addrs = "mgmt_addr=192.168.10.2,addr=192.168.10.2,clock_source=internal,time_source=internal"
|
||||
}
|
||||
);
|
||||
|
||||
THREAD_STRUCT = (
|
||||
{
|
||||
#three config for level of parallelism "PARALLEL_SINGLE_THREAD", "PARALLEL_RU_L1_SPLIT", or "PARALLEL_RU_L1_TRX_SPLIT"
|
||||
parallel_config = "PARALLEL_SINGLE_THREAD";
|
||||
#two option for worker "WORKER_DISABLE" or "WORKER_ENABLE"
|
||||
worker_config = "WORKER_ENABLE";
|
||||
}
|
||||
);
|
||||
|
||||
rfsimulator :
|
||||
{
|
||||
serveraddr = "server";
|
||||
serverport = 4043;
|
||||
options = (); #("saviq"); or/and "chanmod"
|
||||
modelname = "AWGN";
|
||||
IQfile = "/tmp/rfsimulator.iqs";
|
||||
};
|
||||
|
||||
security = {
|
||||
# preferred ciphering algorithms
|
||||
# the first one of the list that an UE supports in chosen
|
||||
# valid values: nea0, nea1, nea2, nea3
|
||||
ciphering_algorithms = ( "nea0" );
|
||||
|
||||
# preferred integrity algorithms
|
||||
# the first one of the list that an UE supports in chosen
|
||||
# valid values: nia0, nia1, nia2, nia3
|
||||
integrity_algorithms = ( "nia2", "nia0" );
|
||||
|
||||
# setting 'drb_ciphering' to "no" disables ciphering for DRBs, no matter
|
||||
# what 'ciphering_algorithms' configures; same thing for 'drb_integrity'
|
||||
drb_ciphering = "yes";
|
||||
drb_integrity = "no";
|
||||
};
|
||||
|
||||
log_config :
|
||||
{
|
||||
global_log_level ="info";
|
||||
hw_log_level ="info";
|
||||
phy_log_level ="info";
|
||||
mac_log_level ="info";
|
||||
rlc_log_level ="info";
|
||||
pdcp_log_level ="info";
|
||||
rrc_log_level ="info";
|
||||
ngap_log_level ="debug";
|
||||
f1ap_log_level ="info";
|
||||
};
|
||||
|
||||
ldpc_offload : {
|
||||
dpdk_dev : "41:00.0";
|
||||
dpdk_core_list : "14-15";
|
||||
};
|
||||
7
openair1/PHY/CODING/tests/nrue.uicc.1.conf
Normal file
7
openair1/PHY/CODING/tests/nrue.uicc.1.conf
Normal file
@@ -0,0 +1,7 @@
|
||||
uicc0 = {
|
||||
imsi = "208990100001132";
|
||||
key = "fec86ba6eb707ed08905757b1bb44b8f";
|
||||
opc= "C42449363BBAD02B66D16BC975D77CC1";
|
||||
dnn= "oai";
|
||||
nssai_sst=1;
|
||||
}
|
||||
13
openair1/PHY/CODING/tests/nrue.uicc.1.slot_demo.conf
Normal file
13
openair1/PHY/CODING/tests/nrue.uicc.1.slot_demo.conf
Normal file
@@ -0,0 +1,13 @@
|
||||
uicc0 = {
|
||||
imsi = "208990100001132";
|
||||
key = "fec86ba6eb707ed08905757b1bb44b8f";
|
||||
opc= "C42449363BBAD02B66D16BC975D77CC1";
|
||||
dnn= "oai";
|
||||
nssai_sst=1;
|
||||
}
|
||||
|
||||
loader : {
|
||||
ldpc : {
|
||||
shlibversion : "_slot_demo";
|
||||
};
|
||||
};
|
||||
18
openair1/PHY/CODING/tests/nrue.uicc.1.slot_t2.conf
Normal file
18
openair1/PHY/CODING/tests/nrue.uicc.1.slot_t2.conf
Normal file
@@ -0,0 +1,18 @@
|
||||
uicc0 = {
|
||||
imsi = "208990100001132";
|
||||
key = "fec86ba6eb707ed08905757b1bb44b8f";
|
||||
opc= "C42449363BBAD02B66D16BC975D77CC1";
|
||||
dnn= "oai";
|
||||
nssai_sst=1;
|
||||
}
|
||||
|
||||
nrLDPC_coding_t2 : {
|
||||
dpdk_dev : "41:00.0";
|
||||
dpdk_core_list : "14-15";
|
||||
};
|
||||
|
||||
loader : {
|
||||
ldpc : {
|
||||
shlibversion : "_slot_t2";
|
||||
};
|
||||
};
|
||||
17
openair1/PHY/CODING/tests/nrue.uicc.1.slot_xdma.conf
Normal file
17
openair1/PHY/CODING/tests/nrue.uicc.1.slot_xdma.conf
Normal file
@@ -0,0 +1,17 @@
|
||||
uicc0 = {
|
||||
imsi = "208990100001132";
|
||||
key = "fec86ba6eb707ed08905757b1bb44b8f";
|
||||
opc= "C42449363BBAD02B66D16BC975D77CC1";
|
||||
dnn= "oai";
|
||||
nssai_sst=1;
|
||||
}
|
||||
|
||||
nrLDPC_coding_xdma : {
|
||||
num_threads_prepare : 2;
|
||||
};
|
||||
|
||||
loader : {
|
||||
ldpc : {
|
||||
shlibversion : "_xdma";
|
||||
};
|
||||
};
|
||||
7
openair1/PHY/CODING/tests/nrue.uicc.2.conf
Normal file
7
openair1/PHY/CODING/tests/nrue.uicc.2.conf
Normal file
@@ -0,0 +1,7 @@
|
||||
uicc0 = {
|
||||
imsi = "208990100001133";
|
||||
key = "fec86ba6eb707ed08905757b1bb44b8f";
|
||||
opc= "C42449363BBAD02B66D16BC975D77CC1";
|
||||
dnn= "oai";
|
||||
nssai_sst=1;
|
||||
}
|
||||
10
openair1/PHY/CODING/tests/slot_t2.conf
Normal file
10
openair1/PHY/CODING/tests/slot_t2.conf
Normal file
@@ -0,0 +1,10 @@
|
||||
nrLDPC_coding_t2 : {
|
||||
dpdk_dev : "41:00.0";
|
||||
dpdk_core_list : "14-15";
|
||||
};
|
||||
|
||||
loader : {
|
||||
ldpc : {
|
||||
shlibversion : "_slot_t2";
|
||||
};
|
||||
};
|
||||
9
openair1/PHY/CODING/tests/slot_xdma.conf
Normal file
9
openair1/PHY/CODING/tests/slot_xdma.conf
Normal file
@@ -0,0 +1,9 @@
|
||||
nrLDPC_coding_xdma : {
|
||||
num_threads_prepare : 2;
|
||||
};
|
||||
|
||||
loader : {
|
||||
ldpc : {
|
||||
shlibversion : "_xdma";
|
||||
};
|
||||
};
|
||||
4
openair1/PHY/CODING/tests/t2_offload.conf
Normal file
4
openair1/PHY/CODING/tests/t2_offload.conf
Normal file
@@ -0,0 +1,4 @@
|
||||
ldpc_offload : {
|
||||
dpdk_dev : "41:00.0";
|
||||
dpdk_core_list : "14-15";
|
||||
};
|
||||
92
openair1/PHY/CODING/tests/two_ues_rfsim.sh
Executable file
92
openair1/PHY/CODING/tests/two_ues_rfsim.sh
Executable file
@@ -0,0 +1,92 @@
|
||||
#!/bin/bash
|
||||
|
||||
create_namespace() {
|
||||
local ue_id=$1
|
||||
local name="ue$ue_id"
|
||||
echo "creating namespace for UE ID ${ue_id} name ${name}"
|
||||
ip netns add $name
|
||||
ip link add v-eth$ue_id type veth peer name v-ue$ue_id
|
||||
ip link set v-ue$ue_id netns $name
|
||||
BASE_IP=$((200+ue_id))
|
||||
ip addr add 10.$BASE_IP.1.100/24 dev v-eth$ue_id
|
||||
ip link set v-eth$ue_id up
|
||||
iptables -t nat -A POSTROUTING -s 10.$BASE_IP.1.0/255.255.255.0 -o lo -j MASQUERADE
|
||||
iptables -A FORWARD -i lo -o v-eth$ue_id -j ACCEPT
|
||||
iptables -A FORWARD -o lo -i v-eth$ue_id -j ACCEPT
|
||||
ip netns exec $name ip link set dev lo up
|
||||
ip netns exec $name ip addr add 10.$BASE_IP.1.$ue_id/24 dev v-ue$ue_id
|
||||
ip netns exec $name ip link set v-ue$ue_id up
|
||||
}
|
||||
|
||||
delete_namespace() {
|
||||
local ue_id=$1
|
||||
local name="ue$ue_id"
|
||||
echo "deleting namespace for UE ID ${ue_id} name ${name}"
|
||||
ip link delete v-eth$ue_id
|
||||
ip netns delete $name
|
||||
}
|
||||
|
||||
usage () {
|
||||
echo "$1 <gnb_args>"
|
||||
}
|
||||
|
||||
prog_name=$(basename $0)
|
||||
|
||||
if [[ $(id -u) -ne 0 ]] ; then echo "Please run as root"; exit 1; fi
|
||||
if [[ $# -eq 0 ]]; then echo "error: no parameters given"; usage $prog_name; exit 1; fi
|
||||
|
||||
# Write gNB arguments
|
||||
GNB_ARGS=""
|
||||
for arg in $@
|
||||
do
|
||||
GNB_ARGS="${GNB_ARGS} ${arg}"
|
||||
done
|
||||
|
||||
# Launch gNB
|
||||
./nr-softmodem --sa --rfsim --log_config.global_log_options level,nocolor,time$GNB_ARGS &
|
||||
GNB_PID=$!
|
||||
|
||||
sleep 3
|
||||
|
||||
# Create 2 network namespaces
|
||||
create_namespace 1
|
||||
create_namespace 2
|
||||
|
||||
# Launch UE 1
|
||||
ip netns exec ue1 ./nr-uesoftmodem --sa --rfsim -r 106 --numerology 1 --band 78 -C 3319680000 --ue-nb-ant-tx 2 --ue-nb-ant-rx 2 -O ../../../openair1/PHY/CODING/tests/nrue.uicc.1.conf --rfsimulator.serveraddr 10.201.1.100 &
|
||||
UE1_PID=$!
|
||||
|
||||
sleep 3
|
||||
|
||||
# Launch UE 2
|
||||
ip netns exec ue2 ./nr-uesoftmodem --sa --rfsim -r 106 --numerology 1 --band 78 -C 3319680000 --ue-nb-ant-tx 2 --ue-nb-ant-rx 2 -O ../../../openair1/PHY/CODING/tests/nrue.uicc.2.conf --rfsimulator.serveraddr 10.202.1.100 &
|
||||
UE2_PID=$!
|
||||
|
||||
# Wait
|
||||
sleep 9
|
||||
|
||||
# Test phase using ping
|
||||
SUCCESS=0
|
||||
ip netns exec ue1 ping -c 5 -i 0.1 -w 1 12.1.1.1
|
||||
SUCCESS=$((${SUCCESS}+$?))
|
||||
ip netns exec ue2 ping -c 5 -i 0.1 -w 1 12.1.1.1
|
||||
SUCCESS=$((${SUCCESS}+$?))
|
||||
|
||||
# Stop UEs and gNB
|
||||
# SIGINT
|
||||
kill -2 ${UE1_PID}
|
||||
kill -2 ${UE2_PID}
|
||||
sleep 3
|
||||
kill -2 ${GNB_PID}
|
||||
sleep 3
|
||||
# SIGKILL
|
||||
kill -9 ${UE1_PID}
|
||||
kill -9 ${UE2_PID}
|
||||
kill -9 ${GNB_PID}
|
||||
|
||||
# Delete network namespaces
|
||||
delete_namespace 1
|
||||
delete_namespace 2
|
||||
|
||||
exit ${SUCCESS}
|
||||
|
||||
80
openair1/PHY/CODING/tests/ue_coding_rfsim.sh
Executable file
80
openair1/PHY/CODING/tests/ue_coding_rfsim.sh
Executable file
@@ -0,0 +1,80 @@
|
||||
#!/bin/bash
|
||||
|
||||
create_namespace() {
|
||||
local ue_id=$1
|
||||
local name="ue$ue_id"
|
||||
echo "creating namespace for UE ID ${ue_id} name ${name}"
|
||||
ip netns add $name
|
||||
ip link add v-eth$ue_id type veth peer name v-ue$ue_id
|
||||
ip link set v-ue$ue_id netns $name
|
||||
BASE_IP=$((200+ue_id))
|
||||
ip addr add 10.$BASE_IP.1.100/24 dev v-eth$ue_id
|
||||
ip link set v-eth$ue_id up
|
||||
iptables -t nat -A POSTROUTING -s 10.$BASE_IP.1.0/255.255.255.0 -o lo -j MASQUERADE
|
||||
iptables -A FORWARD -i lo -o v-eth$ue_id -j ACCEPT
|
||||
iptables -A FORWARD -o lo -i v-eth$ue_id -j ACCEPT
|
||||
ip netns exec $name ip link set dev lo up
|
||||
ip netns exec $name ip addr add 10.$BASE_IP.1.$ue_id/24 dev v-ue$ue_id
|
||||
ip netns exec $name ip link set v-ue$ue_id up
|
||||
}
|
||||
|
||||
delete_namespace() {
|
||||
local ue_id=$1
|
||||
local name="ue$ue_id"
|
||||
echo "deleting namespace for UE ID ${ue_id} name ${name}"
|
||||
ip link delete v-eth$ue_id
|
||||
ip netns delete $name
|
||||
}
|
||||
|
||||
usage () {
|
||||
echo "$1 <ue_args>"
|
||||
}
|
||||
|
||||
prog_name=$(basename $0)
|
||||
|
||||
if [[ $(id -u) -ne 0 ]] ; then echo "Please run as root"; exit 1; fi
|
||||
if [[ $# -eq 0 ]]; then echo "error: no parameters given"; usage $prog_name; exit 1; fi
|
||||
|
||||
# Launch gNB
|
||||
./nr-softmodem --sa --rfsim --log_config.global_log_options level,nocolor,time -O ../../../openair1/PHY/CODING/tests/gnb.sa.band78.106prb.rfsim.2x2.conf &
|
||||
GNB_PID=$!
|
||||
|
||||
sleep 3
|
||||
|
||||
# Create 1 network namespaces
|
||||
create_namespace 1
|
||||
|
||||
# Write UE arguments
|
||||
UE_ARGS=""
|
||||
for arg in $@
|
||||
do
|
||||
UE_ARGS="${UE_ARGS} ${arg}"
|
||||
done
|
||||
|
||||
# Launch UE 1
|
||||
ip netns exec ue1 ./nr-uesoftmodem --sa --rfsim -r 106 --numerology 1 --band 78 -C 3319680000 --ue-nb-ant-tx 2 --ue-nb-ant-rx 2 --rfsimulator.serveraddr 10.201.1.100 $UE_ARGS &
|
||||
UE1_PID=$!
|
||||
|
||||
# Wait
|
||||
sleep 9
|
||||
|
||||
# Test phase using ping
|
||||
SUCCESS=0
|
||||
ip netns exec ue1 ping -c 5 -i 0.1 -w 1 12.1.1.1
|
||||
SUCCESS=$((${SUCCESS}+$?))
|
||||
|
||||
# Stop UEs and gNB
|
||||
# SIGINT
|
||||
kill -2 ${UE1_PID}
|
||||
sleep 3
|
||||
kill -2 ${GNB_PID}
|
||||
sleep 3
|
||||
# SIGKILL
|
||||
kill -9 ${UE1_PID}
|
||||
kill -9 ${GNB_PID}
|
||||
|
||||
# Delete network namespaces
|
||||
delete_namespace 1
|
||||
|
||||
exit ${SUCCESS}
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
#include "PHY/defs_gNB.h"
|
||||
#include "PHY/NR_REFSIG/nr_refsig.h"
|
||||
#include "PHY/INIT/nr_phy_init.h"
|
||||
#include "PHY/CODING/nrLDPC_coding_interface.h"
|
||||
#include "PHY/CODING/nrPolar_tools/nr_polar_pbch_defs.h"
|
||||
#include "PHY/NR_TRANSPORT/nr_transport_proto.h"
|
||||
#include "PHY/NR_TRANSPORT/nr_transport_common_proto.h"
|
||||
@@ -40,6 +41,7 @@
|
||||
#include "PHY/NR_REFSIG/nr_refsig.h"
|
||||
#include "SCHED_NR/fapi_nr_l1.h"
|
||||
#include "PHY/NR_REFSIG/ul_ref_seq_nr.h"
|
||||
#include <string.h>
|
||||
|
||||
|
||||
int l1_north_init_gNB() {
|
||||
@@ -103,6 +105,7 @@ void reset_active_stats(PHY_VARS_gNB *gNB, int frame)
|
||||
|
||||
// A global var to reduce the changes size
|
||||
ldpc_interface_t ldpc_interface = {0}, ldpc_interface_offload = {0};
|
||||
nrLDPC_coding_interface_t nrLDPC_coding_interface = {0};
|
||||
|
||||
int phy_init_nr_gNB(PHY_VARS_gNB *gNB)
|
||||
{
|
||||
@@ -131,15 +134,25 @@ int phy_init_nr_gNB(PHY_VARS_gNB *gNB)
|
||||
|
||||
nr_init_fde(); // Init array for frequency equalization of transform precoding of PUSCH
|
||||
|
||||
load_LDPClib(NULL, &ldpc_interface);
|
||||
load_LDPClib("", &ldpc_interface); //TODO Is it safe to remove this?
|
||||
|
||||
gNB->nrLDPC_coding_interface_flag = 0;
|
||||
int ret_loader = load_nrLDPC_coding_interface(NULL, &nrLDPC_coding_interface);
|
||||
if (ret_loader >= 0) {
|
||||
gNB->nrLDPC_coding_interface_flag = 1;
|
||||
if (gNB->ldpc_offload_flag)
|
||||
load_LDPClib("_t2", &ldpc_interface_offload);
|
||||
else
|
||||
load_LDPClib("", &ldpc_interface);
|
||||
} else {
|
||||
if (gNB->ldpc_offload_flag)
|
||||
load_LDPClib("_t2", &ldpc_interface_offload);
|
||||
else
|
||||
load_LDPClib(NULL, &ldpc_interface);
|
||||
}
|
||||
|
||||
pthread_mutex_init(&gNB->UL_INFO.crc_rx_mutex, NULL);
|
||||
|
||||
if (gNB->ldpc_offload_flag)
|
||||
load_LDPClib("_t2", &ldpc_interface_offload);
|
||||
else
|
||||
load_LDPClib(NULL, &ldpc_interface);
|
||||
|
||||
gNB->max_nb_pdsch = MAX_MOBILES_PER_GNB;
|
||||
init_delay_table(fp->ofdm_symbol_size, MAX_DELAY_COMP, NR_MAX_OFDM_SYMBOL_SIZE, fp->delay_table);
|
||||
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
#include "nr_dlsch.h"
|
||||
#include "nr_dci.h"
|
||||
#include "nr_sch_dmrs.h"
|
||||
#include "PHY/CODING/nrLDPC_coding_interface.h"
|
||||
#include "PHY/MODULATION/nr_modulation.h"
|
||||
#include "PHY/NR_REFSIG/dmrs_nr.h"
|
||||
#include "PHY/NR_REFSIG/ptrs_nr.h"
|
||||
@@ -64,6 +65,9 @@ void nr_generate_pdsch(processingData_L1tx_t *msgTx, int frame, int slot)
|
||||
time_stats_t *dlsch_interleaving_stats=&gNB->dlsch_interleaving_stats;
|
||||
time_stats_t *dlsch_segmentation_stats=&gNB->dlsch_segmentation_stats;
|
||||
|
||||
unsigned char **output = calloc(msgTx->num_pdsch_slot, sizeof(unsigned char *));
|
||||
int slot_encoding_done = 0;
|
||||
|
||||
for (int dlsch_id=0; dlsch_id<msgTx->num_pdsch_slot; dlsch_id++) {
|
||||
NR_gNB_DLSCH_t *dlsch = msgTx->dlsch[dlsch_id];
|
||||
|
||||
@@ -98,18 +102,52 @@ void nr_generate_pdsch(processingData_L1tx_t *msgTx, int frame, int slot)
|
||||
}
|
||||
harq->unav_res = ptrsSymbPerSlot * n_ptrs;
|
||||
|
||||
if(slot_encoding_done)
|
||||
goto after_encoding;
|
||||
|
||||
/// CRC, coding, interleaving and rate matching
|
||||
AssertFatal(harq->pdu!=NULL,"harq->pdu is null\n");
|
||||
unsigned char output[rel15->rbSize * NR_SYMBOLS_PER_SLOT * NR_NB_SC_PER_RB * Qm * rel15->nrOfLayers] __attribute__((aligned(64)));
|
||||
bzero(output,rel15->rbSize * NR_SYMBOLS_PER_SLOT * NR_NB_SC_PER_RB * Qm * rel15->nrOfLayers);
|
||||
start_meas(dlsch_encoding_stats);
|
||||
int ret_memalign = posix_memalign((void **)&output[dlsch_id], 64, sizeof(unsigned char) * rel15->rbSize * NR_SYMBOLS_PER_SLOT * NR_NB_SC_PER_RB * Qm * rel15->nrOfLayers);
|
||||
if(ret_memalign){
|
||||
if(gNB->nrLDPC_coding_interface_flag)
|
||||
for(int i = 0; i < dlsch_id; i++)
|
||||
free(output[i]);
|
||||
return;
|
||||
}
|
||||
bzero(output[dlsch_id],rel15->rbSize * NR_SYMBOLS_PER_SLOT * NR_NB_SC_PER_RB * Qm * rel15->nrOfLayers);
|
||||
|
||||
if(gNB->nrLDPC_coding_interface_flag){
|
||||
if(dlsch_id == msgTx->num_pdsch_slot-1){
|
||||
start_meas(dlsch_encoding_stats);
|
||||
if (nr_dlsch_encoding_slot(gNB,
|
||||
msgTx,
|
||||
frame,
|
||||
slot,
|
||||
frame_parms,
|
||||
output,
|
||||
tinput,
|
||||
tprep,
|
||||
tparity,
|
||||
toutput,
|
||||
dlsch_rate_matching_stats,
|
||||
dlsch_interleaving_stats,
|
||||
dlsch_segmentation_stats) == -1) {
|
||||
return;
|
||||
}
|
||||
stop_meas(dlsch_encoding_stats);
|
||||
dlsch_id = -1;
|
||||
slot_encoding_done = 1;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
start_meas(dlsch_encoding_stats);
|
||||
if (nr_dlsch_encoding(gNB,
|
||||
frame,
|
||||
slot,
|
||||
harq,
|
||||
frame_parms,
|
||||
output,
|
||||
output[dlsch_id],
|
||||
tinput,
|
||||
tprep,
|
||||
tparity,
|
||||
@@ -119,6 +157,8 @@ void nr_generate_pdsch(processingData_L1tx_t *msgTx, int frame, int slot)
|
||||
dlsch_segmentation_stats) == -1)
|
||||
return;
|
||||
stop_meas(dlsch_encoding_stats);
|
||||
|
||||
after_encoding:
|
||||
#ifdef DEBUG_DLSCH
|
||||
printf("PDSCH encoding:\nPayload:\n");
|
||||
for (int i=0; i<harq->B>>7; i++) {
|
||||
@@ -129,14 +169,14 @@ void nr_generate_pdsch(processingData_L1tx_t *msgTx, int frame, int slot)
|
||||
printf("\nEncoded payload:\n");
|
||||
for (int i=0; i<encoded_length>>3; i++) {
|
||||
for (int j=0; j<8; j++)
|
||||
printf("%d", output[(i<<3)+j]);
|
||||
printf("%d", output[dlsch_id][(i<<3)+j]);
|
||||
printf("\t");
|
||||
}
|
||||
printf("\n");
|
||||
#endif
|
||||
|
||||
if (IS_SOFTMODEM_DLSIM)
|
||||
memcpy(harq->f, output, encoded_length);
|
||||
memcpy(harq->f, output[dlsch_id], encoded_length);
|
||||
|
||||
c16_t mod_symbs[rel15->NrOfCodewords][encoded_length];
|
||||
for (int codeWord = 0; codeWord < rel15->NrOfCodewords; codeWord++) {
|
||||
@@ -145,7 +185,9 @@ void nr_generate_pdsch(processingData_L1tx_t *msgTx, int frame, int slot)
|
||||
uint32_t scrambled_output[(encoded_length>>5)+4]; // modulator acces by 4 bytes in some cases
|
||||
memset(scrambled_output, 0, sizeof(scrambled_output));
|
||||
if ( encoded_length > rel15->rbSize * NR_SYMBOLS_PER_SLOT * NR_NB_SC_PER_RB * Qm * rel15->nrOfLayers) abort();
|
||||
nr_pdsch_codeword_scrambling(output, encoded_length, codeWord, rel15->dataScramblingId, rel15->rnti, scrambled_output);
|
||||
nr_pdsch_codeword_scrambling(output[dlsch_id], encoded_length, codeWord, rel15->dataScramblingId, rel15->rnti, scrambled_output);
|
||||
|
||||
free(output[dlsch_id]);
|
||||
|
||||
#ifdef DEBUG_DLSCH
|
||||
printf("PDSCH scrambling:\n");
|
||||
@@ -587,6 +629,9 @@ void nr_generate_pdsch(processingData_L1tx_t *msgTx, int frame, int slot)
|
||||
LOG_D(PHY,"beam index for PDSCH allocation already taken\n");
|
||||
}
|
||||
}// dlsch loop
|
||||
|
||||
free(output);
|
||||
|
||||
}
|
||||
|
||||
void dump_pdsch_stats(FILE *fd,PHY_VARS_gNB *gNB) {
|
||||
|
||||
@@ -57,6 +57,20 @@ int nr_dlsch_encoding(PHY_VARS_gNB *gNB,
|
||||
time_stats_t *dlsch_interleaving_stats,
|
||||
time_stats_t *dlsch_segmentation_stats);
|
||||
|
||||
int nr_dlsch_encoding_slot(PHY_VARS_gNB *gNB,
|
||||
processingData_L1tx_t *msgTx,
|
||||
int frame,
|
||||
uint8_t slot,
|
||||
NR_DL_FRAME_PARMS *frame_parms,
|
||||
unsigned char **output,
|
||||
time_stats_t *tinput,
|
||||
time_stats_t *tprep,
|
||||
time_stats_t *tparity,
|
||||
time_stats_t *toutput,
|
||||
time_stats_t *dlsch_rate_matching_stats,
|
||||
time_stats_t *dlsch_interleaving_stats,
|
||||
time_stats_t *dlsch_segmentation_stats);
|
||||
|
||||
void nr_emulate_dlsch_payload(uint8_t* payload, uint16_t size);
|
||||
|
||||
void dump_pdsch_stats(FILE *fd,PHY_VARS_gNB *gNB);
|
||||
|
||||
254
openair1/PHY/NR_TRANSPORT/nr_dlsch_coding_slot.c
Normal file
254
openair1/PHY/NR_TRANSPORT/nr_dlsch_coding_slot.c
Normal file
@@ -0,0 +1,254 @@
|
||||
/*
|
||||
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||
* the OAI Public License, Version 1.0 (the "License"); you may not use this file
|
||||
* except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.openairinterface.org/?page_id=698
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*-------------------------------------------------------------------------------
|
||||
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
/*! \file PHY/LTE_TRANSPORT/dlsch_coding.c
|
||||
* \brief Top-level routines for implementing LDPC-coded (DLSCH) transport channels from 38-212, 15.2
|
||||
* \author H.Wang
|
||||
* \date 2018
|
||||
* \version 0.1
|
||||
* \company Eurecom
|
||||
* \email:
|
||||
* \note
|
||||
* \warning
|
||||
*/
|
||||
|
||||
#include "PHY/defs_gNB.h"
|
||||
#include "PHY/CODING/coding_extern.h"
|
||||
#include "PHY/CODING/coding_defs.h"
|
||||
#include "PHY/CODING/lte_interleaver_inline.h"
|
||||
#include "PHY/CODING/nrLDPC_coding_interface.h"
|
||||
#include "PHY/CODING/nrLDPC_extern.h"
|
||||
#include "PHY/NR_TRANSPORT/nr_transport_proto.h"
|
||||
#include "PHY/NR_TRANSPORT/nr_transport_common_proto.h"
|
||||
#include "PHY/NR_TRANSPORT/nr_dlsch.h"
|
||||
#include "SCHED_NR/sched_nr.h"
|
||||
#include "common/utils/LOG/vcd_signal_dumper.h"
|
||||
#include "common/utils/LOG/log.h"
|
||||
#include "common/utils/nr/nr_common.h"
|
||||
#include <syscall.h>
|
||||
#include <openair2/UTIL/OPT/opt.h>
|
||||
|
||||
//#define DEBUG_DLSCH_CODING
|
||||
//#define DEBUG_DLSCH_FREE 1
|
||||
|
||||
int nr_dlsch_encoding_slot(PHY_VARS_gNB *gNB,
|
||||
processingData_L1tx_t *msgTx,
|
||||
int frame,
|
||||
uint8_t slot,
|
||||
NR_DL_FRAME_PARMS *frame_parms,
|
||||
unsigned char **output,
|
||||
time_stats_t *tinput,
|
||||
time_stats_t *tprep,
|
||||
time_stats_t *tparity,
|
||||
time_stats_t *toutput,
|
||||
time_stats_t *dlsch_rate_matching_stats,
|
||||
time_stats_t *dlsch_interleaving_stats,
|
||||
time_stats_t *dlsch_segmentation_stats)
|
||||
{
|
||||
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_gNB_DLSCH_ENCODING, VCD_FUNCTION_IN);
|
||||
|
||||
nrLDPC_slot_encoding_parameters_t nrLDPC_slot_encoding_parameters;
|
||||
nrLDPC_slot_encoding_parameters.frame = frame;
|
||||
nrLDPC_slot_encoding_parameters.slot = slot;
|
||||
nrLDPC_slot_encoding_parameters.nb_TBs = msgTx->num_pdsch_slot;
|
||||
//nrLDPC_slot_encoding_parameters.respEncode = &gNB->respEncode;
|
||||
nrLDPC_slot_encoding_parameters.threadPool = &gNB->threadPool;
|
||||
nrLDPC_slot_encoding_parameters.tinput = tinput;
|
||||
nrLDPC_slot_encoding_parameters.tprep = tprep;
|
||||
nrLDPC_slot_encoding_parameters.tparity = tparity;
|
||||
nrLDPC_slot_encoding_parameters.toutput = toutput;
|
||||
nrLDPC_TB_encoding_parameters_t TBs[msgTx->num_pdsch_slot];
|
||||
nrLDPC_slot_encoding_parameters.TBs = TBs;
|
||||
|
||||
int max_num_segments = 0;
|
||||
|
||||
for (int dlsch_id=0; dlsch_id<msgTx->num_pdsch_slot; dlsch_id++) {
|
||||
|
||||
NR_gNB_DLSCH_t *dlsch = msgTx->dlsch[dlsch_id];
|
||||
|
||||
NR_DL_gNB_HARQ_t *harq = &dlsch->harq_process;
|
||||
unsigned int crc=1;
|
||||
nfapi_nr_dl_tti_pdsch_pdu_rel15_t *rel15 = &harq->pdsch_pdu.pdsch_pdu_rel15;
|
||||
uint32_t A = rel15->TBSize[0]<<3;
|
||||
unsigned char *a=harq->pdu;
|
||||
if (rel15->rnti != SI_RNTI) {
|
||||
ws_trace_t tmp = {.nr = true,
|
||||
.direction = DIRECTION_DOWNLINK,
|
||||
.pdu_buffer = a,
|
||||
.pdu_buffer_size = rel15->TBSize[0],
|
||||
.ueid = 0,
|
||||
.rntiType = WS_C_RNTI,
|
||||
.rnti = rel15->rnti,
|
||||
.sysFrame = frame,
|
||||
.subframe = slot,
|
||||
.harq_pid = 0, // difficult to find the harq pid here
|
||||
.oob_event = 0,
|
||||
.oob_event_value = 0};
|
||||
trace_pdu(&tmp);
|
||||
}
|
||||
|
||||
NR_gNB_PHY_STATS_t *phy_stats = NULL;
|
||||
if (rel15->rnti != 0xFFFF)
|
||||
phy_stats = get_phy_stats(gNB, rel15->rnti);
|
||||
|
||||
if (phy_stats) {
|
||||
phy_stats->frame = frame;
|
||||
phy_stats->dlsch_stats.total_bytes_tx += rel15->TBSize[0];
|
||||
phy_stats->dlsch_stats.current_RI = rel15->nrOfLayers;
|
||||
phy_stats->dlsch_stats.current_Qm = rel15->qamModOrder[0];
|
||||
}
|
||||
|
||||
int max_bytes = MAX_NUM_NR_DLSCH_SEGMENTS_PER_LAYER*rel15->nrOfLayers*1056;
|
||||
int B;
|
||||
if (A > NR_MAX_PDSCH_TBS) {
|
||||
// Add 24-bit crc (polynomial A) to payload
|
||||
crc = crc24a(a,A)>>8;
|
||||
a[A>>3] = ((uint8_t *)&crc)[2];
|
||||
a[1+(A>>3)] = ((uint8_t *)&crc)[1];
|
||||
a[2+(A>>3)] = ((uint8_t *)&crc)[0];
|
||||
//printf("CRC %x (A %d)\n",crc,A);
|
||||
//printf("a0 %d a1 %d a2 %d\n", a[A>>3], a[1+(A>>3)], a[2+(A>>3)]);
|
||||
B = A + 24;
|
||||
// harq->b = a;
|
||||
AssertFatal((A / 8) + 4 <= max_bytes,
|
||||
"A %d is too big (A/8+4 = %d > %d)\n",
|
||||
A,
|
||||
(A / 8) + 4,
|
||||
max_bytes);
|
||||
memcpy(harq->b, a, (A / 8) + 4); // why is this +4 if the CRC is only 3 bytes?
|
||||
} else {
|
||||
// Add 16-bit crc (polynomial A) to payload
|
||||
crc = crc16(a,A)>>16;
|
||||
a[A>>3] = ((uint8_t *)&crc)[1];
|
||||
a[1+(A>>3)] = ((uint8_t *)&crc)[0];
|
||||
//printf("CRC %x (A %d)\n",crc,A);
|
||||
//printf("a0 %d a1 %d \n", a[A>>3], a[1+(A>>3)]);
|
||||
B = A + 16;
|
||||
// harq->b = a;
|
||||
AssertFatal((A / 8) + 3 <= max_bytes,
|
||||
"A %d is too big (A/8+3 = %d > %d)\n",
|
||||
A,
|
||||
(A / 8) + 3,
|
||||
max_bytes);
|
||||
memcpy(harq->b, a, (A / 8) + 3); // using 3 bytes to mimic the case of 24 bit crc
|
||||
}
|
||||
|
||||
nrLDPC_TB_encoding_parameters_t nrLDPC_TB_encoding_parameters;
|
||||
|
||||
nrLDPC_TB_encoding_parameters.xlsch_id = dlsch_id;
|
||||
nrLDPC_TB_encoding_parameters.BG = rel15->maintenance_parms_v3.ldpcBaseGraph;
|
||||
nrLDPC_TB_encoding_parameters.Z = harq->Z;
|
||||
nrLDPC_TB_encoding_parameters.A = A;
|
||||
start_meas(dlsch_segmentation_stats);
|
||||
nrLDPC_TB_encoding_parameters.Kb = nr_segmentation(harq->b,
|
||||
harq->c,
|
||||
B,
|
||||
&nrLDPC_TB_encoding_parameters.C,
|
||||
&nrLDPC_TB_encoding_parameters.K,
|
||||
&nrLDPC_TB_encoding_parameters.Z,
|
||||
&nrLDPC_TB_encoding_parameters.F,
|
||||
nrLDPC_TB_encoding_parameters.BG);
|
||||
stop_meas(dlsch_segmentation_stats);
|
||||
|
||||
if (nrLDPC_TB_encoding_parameters.C>MAX_NUM_NR_DLSCH_SEGMENTS_PER_LAYER*rel15->nrOfLayers) {
|
||||
LOG_E(PHY, "nr_segmentation.c: too many segments %d, B %d\n", nrLDPC_TB_encoding_parameters.C, B);
|
||||
return(-1);
|
||||
}
|
||||
max_num_segments = max(max_num_segments, nrLDPC_TB_encoding_parameters.C);
|
||||
|
||||
TBs[dlsch_id] = nrLDPC_TB_encoding_parameters;
|
||||
}
|
||||
|
||||
nrLDPC_segment_encoding_parameters_t segments[msgTx->num_pdsch_slot][max_num_segments];
|
||||
|
||||
for (int dlsch_id = 0; dlsch_id < msgTx->num_pdsch_slot; dlsch_id++) {
|
||||
NR_gNB_DLSCH_t *dlsch = msgTx->dlsch[dlsch_id];
|
||||
NR_DL_gNB_HARQ_t *harq = &dlsch->harq_process;
|
||||
nfapi_nr_dl_tti_pdsch_pdu_rel15_t *rel15 = &harq->pdsch_pdu.pdsch_pdu_rel15;
|
||||
|
||||
nrLDPC_TB_encoding_parameters_t nrLDPC_TB_encoding_parameters = TBs[dlsch_id];
|
||||
nrLDPC_TB_encoding_parameters.segments = segments[dlsch_id];
|
||||
|
||||
for (int r = 0; r < nrLDPC_TB_encoding_parameters.C; r++) {
|
||||
nrLDPC_TB_encoding_parameters.segments[r].c = harq->c[r];
|
||||
#ifdef DEBUG_DLSCH_CODING
|
||||
LOG_D(PHY, "Encoder: B %d F %d \n", harq->B, nrLDPC_TB_encoding_parameters.F);
|
||||
LOG_D(PHY, "start ldpc encoder segment %d/%d\n", r, nrLDPC_TB_encoding_parameters.C);
|
||||
LOG_D(PHY, "input %d %d %d %d %d \n", harq->c[r][0], harq->c[r][1], harq->c[r][2], harq->c[r][3], harq->c[r][4]);
|
||||
for (int cnt = 0; cnt < 22 * (nrLDPC_TB_encoding_parameters.Z) / 8; cnt++) {
|
||||
LOG_D(PHY, "%d ", harq->c[r][cnt]);
|
||||
}
|
||||
LOG_D(PHY, "\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
nrLDPC_TB_encoding_parameters.rnti = rel15->rnti;
|
||||
nrLDPC_TB_encoding_parameters.nb_rb = rel15->rbSize;
|
||||
nrLDPC_TB_encoding_parameters.Qm = rel15->qamModOrder[0];
|
||||
nrLDPC_TB_encoding_parameters.mcs = rel15->mcsIndex[0];
|
||||
nrLDPC_TB_encoding_parameters.nb_layers = rel15->nrOfLayers;
|
||||
nrLDPC_TB_encoding_parameters.rv_index = rel15->rvIndex[0];
|
||||
|
||||
int nb_re_dmrs =
|
||||
(rel15->dmrsConfigType == NFAPI_NR_DMRS_TYPE1) ? (6 * rel15->numDmrsCdmGrpsNoData) : (4 * rel15->numDmrsCdmGrpsNoData);
|
||||
nrLDPC_TB_encoding_parameters.G = nr_get_G(rel15->rbSize,
|
||||
rel15->NrOfSymbols,
|
||||
nb_re_dmrs,
|
||||
get_num_dmrs(rel15->dlDmrsSymbPos),
|
||||
harq->unav_res,
|
||||
rel15->qamModOrder[0],
|
||||
rel15->nrOfLayers);
|
||||
|
||||
nrLDPC_TB_encoding_parameters.tbslbrm = rel15->maintenance_parms_v3.tbSizeLbrmBytes;
|
||||
|
||||
int r_offset = 0;
|
||||
for (int r = 0; r < nrLDPC_TB_encoding_parameters.C; r++) {
|
||||
nrLDPC_TB_encoding_parameters.segments[r].E = nr_get_E(nrLDPC_TB_encoding_parameters.G,
|
||||
nrLDPC_TB_encoding_parameters.C,
|
||||
nrLDPC_TB_encoding_parameters.Qm,
|
||||
rel15->nrOfLayers,
|
||||
r);
|
||||
nrLDPC_TB_encoding_parameters.segments[r].output = output[dlsch_id] + r_offset;
|
||||
r_offset += nrLDPC_TB_encoding_parameters.segments[r].E;
|
||||
}
|
||||
|
||||
TBs[dlsch_id] = nrLDPC_TB_encoding_parameters;
|
||||
}
|
||||
notifiedFIFO_t nf;
|
||||
initNotifiedFIFO(&nf);
|
||||
nrLDPC_slot_encoding_parameters.respEncode = &nf;
|
||||
|
||||
int nbJobs = nrLDPC_coding_interface.nrLDPC_coding_encoder(&nrLDPC_slot_encoding_parameters);
|
||||
|
||||
if (nbJobs < 0)
|
||||
return -1;
|
||||
while (nbJobs) {
|
||||
notifiedFIFO_elt_t *req = pullTpool(&nf, &gNB->threadPool);
|
||||
if (req == NULL)
|
||||
break; // Tpool has been stopped
|
||||
delNotifiedFIFO_elt(req);
|
||||
nbJobs--;
|
||||
}
|
||||
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_gNB_DLSCH_ENCODING, VCD_FUNCTION_OUT);
|
||||
return 0;
|
||||
}
|
||||
@@ -64,6 +64,24 @@ int nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB,
|
||||
uint8_t harq_pid,
|
||||
uint32_t G);
|
||||
|
||||
/*! \brief Perform PUSCH decoding for the whole current received TTI. TS 38.212 V15.4.0 subclause 6.2
|
||||
@param phy_vars_gNB, Pointer to PHY data structure for gNB
|
||||
@param frame_parms, Pointer to frame descriptor structure
|
||||
@param frame, current received frame
|
||||
@param nr_tti_rx, current received TTI
|
||||
@param G
|
||||
@param ULSCH_ids, array of ULSCH ids
|
||||
@param nb_pusch, number of uplink shared channels
|
||||
*/
|
||||
|
||||
int nr_ulsch_decoding_slot(PHY_VARS_gNB *phy_vars_gNB,
|
||||
NR_DL_FRAME_PARMS *frame_parms,
|
||||
uint32_t frame,
|
||||
uint8_t nr_tti_rx,
|
||||
uint32_t *G,
|
||||
uint8_t *ULSCH_ids,
|
||||
int nb_pusch);
|
||||
|
||||
/*! \brief Perform PUSCH unscrambling. TS 38.211 V15.4.0 subclause 6.3.1.1
|
||||
@param llr, Pointer to llr bits
|
||||
@param size, length of llr bits
|
||||
|
||||
276
openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding_slot.c
Normal file
276
openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding_slot.c
Normal file
@@ -0,0 +1,276 @@
|
||||
/*
|
||||
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||
* the OAI Public License, Version 1.0 (the "License"); you may not use this file
|
||||
* except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.openairinterface.org/?page_id=698
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*-------------------------------------------------------------------------------
|
||||
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
/*! \file PHY/NR_TRANSPORT/nr_ulsch_decoding.c
|
||||
* \brief Top-level routines for decoding LDPC (ULSCH) transport channels from 38.212, V15.4.0 2018-12
|
||||
* \author Ahmed Hussein
|
||||
* \date 2019
|
||||
* \version 0.1
|
||||
* \company Fraunhofer IIS
|
||||
* \email: ahmed.hussein@iis.fraunhofer.de
|
||||
* \note
|
||||
* \warning
|
||||
*/
|
||||
|
||||
|
||||
// [from gNB coding]
|
||||
#include "PHY/defs_gNB.h"
|
||||
#include "PHY/CODING/coding_extern.h"
|
||||
#include "PHY/CODING/coding_defs.h"
|
||||
#include "PHY/CODING/lte_interleaver_inline.h"
|
||||
#include "PHY/CODING/nrLDPC_coding_interface.h"
|
||||
#include "PHY/CODING/nrLDPC_extern.h"
|
||||
#include "PHY/NR_TRANSPORT/nr_transport_common_proto.h"
|
||||
#include "PHY/NR_TRANSPORT/nr_transport_proto.h"
|
||||
#include "PHY/NR_TRANSPORT/nr_ulsch.h"
|
||||
#include "PHY/NR_TRANSPORT/nr_dlsch.h"
|
||||
#include "SCHED_NR/sched_nr.h"
|
||||
#include "SCHED_NR/fapi_nr_l1.h"
|
||||
#include "defs.h"
|
||||
#include "common/utils/LOG/vcd_signal_dumper.h"
|
||||
#include "common/utils/LOG/log.h"
|
||||
#include <syscall.h>
|
||||
//#define DEBUG_ULSCH_DECODING
|
||||
//#define gNB_DEBUG_TRACE
|
||||
|
||||
#define OAI_UL_LDPC_MAX_NUM_LLR 27000//26112 // NR_LDPC_NCOL_BG1*NR_LDPC_ZMAX = 68*384
|
||||
//#define DEBUG_CRC
|
||||
#ifdef DEBUG_CRC
|
||||
#define PRINT_CRC_CHECK(a) a
|
||||
#else
|
||||
#define PRINT_CRC_CHECK(a)
|
||||
#endif
|
||||
|
||||
//extern double cpuf;
|
||||
|
||||
int nr_ulsch_decoding_slot(PHY_VARS_gNB *phy_vars_gNB,
|
||||
NR_DL_FRAME_PARMS *frame_parms,
|
||||
uint32_t frame,
|
||||
uint8_t nr_tti_rx,
|
||||
uint32_t *G,
|
||||
uint8_t *ULSCH_ids,
|
||||
int nb_pusch)
|
||||
{
|
||||
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_gNB_ULSCH_DECODING, 1);
|
||||
|
||||
nrLDPC_slot_decoding_parameters_t nrLDPC_slot_decoding_parameters;
|
||||
nrLDPC_slot_decoding_parameters.frame = frame;
|
||||
nrLDPC_slot_decoding_parameters.slot = nr_tti_rx;
|
||||
nrLDPC_slot_decoding_parameters.nb_TBs = nb_pusch;
|
||||
nrLDPC_slot_decoding_parameters.threadPool = &phy_vars_gNB->threadPool;
|
||||
nrLDPC_slot_decoding_parameters.respDecode = &phy_vars_gNB->respDecode;
|
||||
nrLDPC_TB_decoding_parameters_t TBs[nb_pusch];
|
||||
nrLDPC_slot_decoding_parameters.TBs = TBs;
|
||||
|
||||
int max_num_segments = 0;
|
||||
|
||||
for (uint8_t pusch_id = 0; pusch_id < nb_pusch; pusch_id++) {
|
||||
uint8_t ULSCH_id = ULSCH_ids[pusch_id];
|
||||
NR_gNB_ULSCH_t *ulsch = &phy_vars_gNB->ulsch[ULSCH_id];
|
||||
NR_gNB_PUSCH *pusch = &phy_vars_gNB->pusch_vars[ULSCH_id];
|
||||
NR_UL_gNB_HARQ_t *harq_process = ulsch->harq_process;
|
||||
nfapi_nr_pusch_pdu_t *pusch_pdu = &phy_vars_gNB->ulsch[ULSCH_id].harq_process->ulsch_pdu;
|
||||
|
||||
nrLDPC_TB_decoding_parameters_t nrLDPC_TB_decoding_parameters;
|
||||
|
||||
nrLDPC_TB_decoding_parameters.G = G[pusch_id];
|
||||
|
||||
if (!harq_process) {
|
||||
LOG_E(PHY, "ulsch_decoding.c: NULL harq_process pointer\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
nrLDPC_TB_decoding_parameters.xlsch_id = ULSCH_id;
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
nrLDPC_TB_decoding_parameters.nb_rb = pusch_pdu->rb_size;
|
||||
nrLDPC_TB_decoding_parameters.Qm = pusch_pdu->qam_mod_order;
|
||||
nrLDPC_TB_decoding_parameters.mcs = pusch_pdu->mcs_index;
|
||||
nrLDPC_TB_decoding_parameters.nb_layers = pusch_pdu->nrOfLayers;
|
||||
// ------------------------------------------------------------------
|
||||
|
||||
nrLDPC_TB_decoding_parameters.processedSegments = &harq_process->processedSegments;
|
||||
harq_process->TBS = pusch_pdu->pusch_data.tb_size;
|
||||
|
||||
nrLDPC_TB_decoding_parameters.BG = pusch_pdu->maintenance_parms_v3.ldpcBaseGraph;
|
||||
nrLDPC_TB_decoding_parameters.A = (harq_process->TBS) << 3;
|
||||
NR_gNB_PHY_STATS_t *stats = get_phy_stats(phy_vars_gNB, ulsch->rnti);
|
||||
if (stats) {
|
||||
stats->frame = frame;
|
||||
stats->ulsch_stats.round_trials[harq_process->round]++;
|
||||
for (int aarx = 0; aarx < frame_parms->nb_antennas_rx; aarx++) {
|
||||
stats->ulsch_stats.power[aarx] = dB_fixed_x10(pusch->ulsch_power[aarx]);
|
||||
stats->ulsch_stats.noise_power[aarx] = dB_fixed_x10(pusch->ulsch_noise_power[aarx]);
|
||||
}
|
||||
if (!harq_process->harq_to_be_cleared) {
|
||||
stats->ulsch_stats.current_Qm = nrLDPC_TB_decoding_parameters.Qm;
|
||||
stats->ulsch_stats.current_RI = nrLDPC_TB_decoding_parameters.nb_layers;
|
||||
stats->ulsch_stats.total_bytes_tx += harq_process->TBS;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t harq_pid = ulsch->harq_pid;
|
||||
LOG_D(PHY,
|
||||
"ULSCH Decoding, harq_pid %d rnti %x TBS %d G %d mcs %d Nl %d nb_rb %d, Qm %d, Coderate %f RV %d round %d new RX %d\n",
|
||||
harq_pid,
|
||||
ulsch->rnti,
|
||||
nrLDPC_TB_decoding_parameters.A,
|
||||
nrLDPC_TB_decoding_parameters.G,
|
||||
nrLDPC_TB_decoding_parameters.mcs,
|
||||
nrLDPC_TB_decoding_parameters.nb_layers,
|
||||
nrLDPC_TB_decoding_parameters.nb_rb,
|
||||
nrLDPC_TB_decoding_parameters.Qm,
|
||||
pusch_pdu->target_code_rate / 10240.0f,
|
||||
pusch_pdu->pusch_data.rv_index,
|
||||
harq_process->round,
|
||||
harq_process->harq_to_be_cleared);
|
||||
|
||||
// [hna] Perform nr_segmenation with input and output set to NULL to calculate only (C, K, Z, F)
|
||||
nr_segmentation(NULL,
|
||||
NULL,
|
||||
lenWithCrc(1, nrLDPC_TB_decoding_parameters.A), // size in case of 1 segment
|
||||
&nrLDPC_TB_decoding_parameters.C,
|
||||
&nrLDPC_TB_decoding_parameters.K,
|
||||
&nrLDPC_TB_decoding_parameters.Z, // [hna] Z is Zc
|
||||
&nrLDPC_TB_decoding_parameters.F,
|
||||
nrLDPC_TB_decoding_parameters.BG);
|
||||
harq_process->C = nrLDPC_TB_decoding_parameters.C;
|
||||
harq_process->K = nrLDPC_TB_decoding_parameters.K;
|
||||
harq_process->Z = nrLDPC_TB_decoding_parameters.Z;
|
||||
harq_process->F = nrLDPC_TB_decoding_parameters.F;
|
||||
|
||||
uint16_t a_segments = MAX_NUM_NR_ULSCH_SEGMENTS_PER_LAYER * nrLDPC_TB_decoding_parameters.nb_layers; // number of segments to be allocated
|
||||
if (nrLDPC_TB_decoding_parameters.C > a_segments) {
|
||||
LOG_E(PHY, "nr_segmentation.c: too many segments %d, A %d\n", harq_process->C, nrLDPC_TB_decoding_parameters.A);
|
||||
return(-1);
|
||||
}
|
||||
if (nrLDPC_TB_decoding_parameters.nb_rb != 273) {
|
||||
a_segments = a_segments*nrLDPC_TB_decoding_parameters.nb_rb;
|
||||
a_segments = a_segments/273 +1;
|
||||
}
|
||||
if (nrLDPC_TB_decoding_parameters.C > a_segments) {
|
||||
LOG_E(PHY,"Illegal harq_process->C %d > %d\n",harq_process->C,a_segments);
|
||||
return -1;
|
||||
}
|
||||
max_num_segments = max(max_num_segments, nrLDPC_TB_decoding_parameters.C);
|
||||
|
||||
#ifdef DEBUG_ULSCH_DECODING
|
||||
printf("ulsch decoding nr segmentation Z %d\n", nrLDPC_TB_decoding_parameters.Z);
|
||||
if (!frame % 100)
|
||||
printf("K %d C %d Z %d \n",
|
||||
nrLDPC_TB_decoding_parameters.K,
|
||||
nrLDPC_TB_decoding_parameters.C,
|
||||
nrLDPC_TB_decoding_parameters.Z);
|
||||
printf("Segmentation: C %d, K %d\n",
|
||||
nrLDPC_TB_decoding_parameters.C,
|
||||
nrLDPC_TB_decoding_parameters.K);
|
||||
#endif
|
||||
|
||||
nrLDPC_TB_decoding_parameters.rnti = ulsch->rnti;
|
||||
nrLDPC_TB_decoding_parameters.max_ldpc_iterations = ulsch->max_ldpc_iterations;
|
||||
nrLDPC_TB_decoding_parameters.rv_index = pusch_pdu->pusch_data.rv_index;
|
||||
nrLDPC_TB_decoding_parameters.tbslbrm = pusch_pdu->maintenance_parms_v3.tbSizeLbrmBytes;
|
||||
nrLDPC_TB_decoding_parameters.abort_decode = &harq_process->abort_decode;
|
||||
set_abort(&harq_process->abort_decode, false);
|
||||
|
||||
TBs[pusch_id] = nrLDPC_TB_decoding_parameters;
|
||||
}
|
||||
|
||||
nrLDPC_segment_decoding_parameters_t segments[nb_pusch][max_num_segments];
|
||||
|
||||
for (uint8_t pusch_id = 0; pusch_id < nb_pusch; pusch_id++) {
|
||||
uint8_t ULSCH_id = ULSCH_ids[pusch_id];
|
||||
NR_gNB_ULSCH_t *ulsch = &phy_vars_gNB->ulsch[ULSCH_id];
|
||||
NR_UL_gNB_HARQ_t *harq_process = ulsch->harq_process;
|
||||
short *ulsch_llr = phy_vars_gNB->pusch_vars[ULSCH_id].llr;
|
||||
|
||||
nrLDPC_TB_decoding_parameters_t nrLDPC_TB_decoding_parameters = TBs[pusch_id];
|
||||
nrLDPC_TB_decoding_parameters.segments = segments[pusch_id];
|
||||
|
||||
uint32_t r_offset = 0;
|
||||
for (int r = 0; r < nrLDPC_TB_decoding_parameters.C; r++) {
|
||||
nrLDPC_segment_decoding_parameters_t nrLDPC_segment_decoding_parameters;
|
||||
nrLDPC_segment_decoding_parameters.E = nr_get_E(nrLDPC_TB_decoding_parameters.G,
|
||||
nrLDPC_TB_decoding_parameters.C,
|
||||
nrLDPC_TB_decoding_parameters.Qm,
|
||||
nrLDPC_TB_decoding_parameters.nb_layers,
|
||||
r);
|
||||
nrLDPC_segment_decoding_parameters.R = nr_get_R_ldpc_decoder(nrLDPC_TB_decoding_parameters.rv_index,
|
||||
nrLDPC_segment_decoding_parameters.E,
|
||||
nrLDPC_TB_decoding_parameters.BG,
|
||||
nrLDPC_TB_decoding_parameters.Z,
|
||||
&harq_process->llrLen,
|
||||
harq_process->round);
|
||||
nrLDPC_segment_decoding_parameters.llr = ulsch_llr + r_offset;
|
||||
nrLDPC_segment_decoding_parameters.d = harq_process->d[r];
|
||||
nrLDPC_segment_decoding_parameters.d_to_be_cleared = &harq_process->d_to_be_cleared[r];
|
||||
nrLDPC_segment_decoding_parameters.c = harq_process->c[r];
|
||||
nrLDPC_segment_decoding_parameters.decodeSuccess = false;
|
||||
|
||||
nrLDPC_TB_decoding_parameters.segments[r] = nrLDPC_segment_decoding_parameters;
|
||||
r_offset += nrLDPC_segment_decoding_parameters.E;
|
||||
}
|
||||
if (harq_process->harq_to_be_cleared) {
|
||||
for (int r = 0; r < nrLDPC_TB_decoding_parameters.C; r++) {
|
||||
harq_process->d_to_be_cleared[r] = true;
|
||||
}
|
||||
harq_process->harq_to_be_cleared = false;
|
||||
}
|
||||
|
||||
TBs[pusch_id] = nrLDPC_TB_decoding_parameters;
|
||||
}
|
||||
|
||||
int number_tasks_decode = nrLDPC_coding_interface.nrLDPC_coding_decoder(&nrLDPC_slot_decoding_parameters);
|
||||
|
||||
// Execute thread pool tasks if any
|
||||
while (number_tasks_decode > 0) {
|
||||
notifiedFIFO_elt_t *req = pullTpool(&phy_vars_gNB->respDecode, &phy_vars_gNB->threadPool);
|
||||
if (req == NULL)
|
||||
return -1; // Tpool has been stopped
|
||||
delNotifiedFIFO_elt(req);
|
||||
number_tasks_decode--;
|
||||
}
|
||||
|
||||
// post decode
|
||||
for (uint8_t pusch_id = 0; pusch_id < nb_pusch; pusch_id++) {
|
||||
uint8_t ULSCH_id = ULSCH_ids[pusch_id];
|
||||
NR_gNB_ULSCH_t *ulsch = &phy_vars_gNB->ulsch[ULSCH_id];
|
||||
NR_UL_gNB_HARQ_t *harq_process = ulsch->harq_process;
|
||||
|
||||
nrLDPC_TB_decoding_parameters_t nrLDPC_TB_decoding_parameters = TBs[pusch_id];
|
||||
|
||||
uint32_t offset = 0;
|
||||
for (int r = 0; r < nrLDPC_TB_decoding_parameters.C; r++) {
|
||||
nrLDPC_segment_decoding_parameters_t nrLDPC_segment_decoding_parameters = nrLDPC_TB_decoding_parameters.segments[r];
|
||||
// Copy c to b in case of decoding success
|
||||
if (nrLDPC_segment_decoding_parameters.decodeSuccess) {
|
||||
memcpy(harq_process->b + offset, harq_process->c[r], (harq_process->K >> 3) - (harq_process->F >> 3) - ((harq_process->C > 1) ? 3 : 0));
|
||||
} else {
|
||||
LOG_D(PHY, "uplink segment error %d/%d\n", r, harq_process->C);
|
||||
LOG_D(PHY, "ULSCH %d in error\n", ULSCH_id);
|
||||
}
|
||||
offset += ((harq_process->K >> 3) - (harq_process->F >> 3) - ((harq_process->C > 1) ? 3 : 0));
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
301
openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding_slot.c
Normal file
301
openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding_slot.c
Normal file
@@ -0,0 +1,301 @@
|
||||
/*
|
||||
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||
* the OAI Public License, Version 1.0 (the "License"); you may not use this file
|
||||
* except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.openairinterface.org/?page_id=698
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*-------------------------------------------------------------------------------
|
||||
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
/*! \file PHY/NR_UE_TRANSPORT/nr_dlsch_decoding_slot.c
|
||||
*/
|
||||
|
||||
#include "common/utils/LOG/vcd_signal_dumper.h"
|
||||
#include "PHY/defs_nr_UE.h"
|
||||
#include "SCHED_NR_UE/harq_nr.h"
|
||||
#include "PHY/phy_extern_nr_ue.h"
|
||||
#include "PHY/CODING/coding_extern.h"
|
||||
#include "PHY/CODING/coding_defs.h"
|
||||
#include "PHY/CODING/nrLDPC_coding_interface.h"
|
||||
#include "PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h"
|
||||
#include "SCHED_NR_UE/defs.h"
|
||||
#include "SIMULATION/TOOLS/sim.h"
|
||||
#include "executables/nr-uesoftmodem.h"
|
||||
#include "PHY/CODING/nrLDPC_extern.h"
|
||||
#include "common/utils/nr/nr_common.h"
|
||||
#include "openair1/PHY/TOOLS/phy_scope_interface.h"
|
||||
#include "nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface.h"
|
||||
|
||||
static extended_kpi_ue kpiStructure = {0};
|
||||
|
||||
/*! \brief Prepare necessary parameters for nrLDPC_coding_interface
|
||||
*/
|
||||
uint32_t nr_dlsch_decoding_slot(PHY_VARS_NR_UE *phy_vars_ue,
|
||||
const UE_nr_rxtx_proc_t *proc,
|
||||
NR_UE_DLSCH_t *dlsch,
|
||||
int16_t **dlsch_llr,
|
||||
uint8_t **b,
|
||||
int *G,
|
||||
int nb_dlsch,
|
||||
uint8_t *DLSCH_ids)
|
||||
{
|
||||
notifiedFIFO_t nf;
|
||||
initNotifiedFIFO(&nf);
|
||||
|
||||
nrLDPC_slot_decoding_parameters_t slot_decoding_params;
|
||||
slot_decoding_params.frame = proc->frame_rx;
|
||||
slot_decoding_params.slot = proc->nr_slot_rx;
|
||||
slot_decoding_params.nb_TBs = nb_dlsch;
|
||||
slot_decoding_params.threadPool = &get_nrUE_params()->Tpool;
|
||||
slot_decoding_params.respDecode = &nf;
|
||||
nrLDPC_TB_decoding_parameters_t TBs[nb_dlsch];
|
||||
slot_decoding_params.TBs = TBs;
|
||||
|
||||
int max_num_segments = 0;
|
||||
|
||||
for (uint8_t pdsch_id = 0; pdsch_id < nb_dlsch; pdsch_id++) {
|
||||
uint8_t DLSCH_id = DLSCH_ids[pdsch_id];
|
||||
fapi_nr_dl_config_dlsch_pdu_rel15_t *dlsch_config = &dlsch[DLSCH_id].dlsch_config;
|
||||
int harq_pid = dlsch_config->harq_process_nbr;
|
||||
NR_DL_UE_HARQ_t *harq_process = &phy_vars_ue->dl_harq_processes[DLSCH_id][harq_pid];
|
||||
uint8_t dmrs_Type = dlsch_config->dmrsConfigType;
|
||||
AssertFatal(dmrs_Type == 0 || dmrs_Type == 1, "Illegal dmrs_type %d\n", dmrs_Type);
|
||||
uint8_t nb_re_dmrs;
|
||||
|
||||
phy_vars_ue->dl_stats[harq_process->DLround]++;
|
||||
LOG_D(PHY, "Round %d RV idx %d\n", harq_process->DLround, dlsch->dlsch_config.rv);
|
||||
|
||||
if (dmrs_Type == NFAPI_NR_DMRS_TYPE1)
|
||||
nb_re_dmrs = 6 * dlsch_config->n_dmrs_cdm_groups;
|
||||
else
|
||||
nb_re_dmrs = 4 * dlsch_config->n_dmrs_cdm_groups;
|
||||
uint16_t dmrs_length = get_num_dmrs(dlsch_config->dlDmrsSymbPos);
|
||||
|
||||
if (!harq_process) {
|
||||
LOG_E(PHY, "dlsch_decoding_slot.c: NULL harq_process pointer\n");
|
||||
return dlsch[DLSCH_id].max_ldpc_iterations + 1;
|
||||
}
|
||||
|
||||
nrLDPC_TB_decoding_parameters_t *TB_decoding_params = &TBs[pdsch_id];
|
||||
|
||||
TB_decoding_params->xlsch_id = DLSCH_id;
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
TB_decoding_params->G = G[DLSCH_id];
|
||||
TB_decoding_params->nb_rb = dlsch_config->number_rbs;
|
||||
TB_decoding_params->Qm = dlsch_config->qamModOrder;
|
||||
TB_decoding_params->mcs = dlsch_config->mcs;
|
||||
TB_decoding_params->nb_layers = dlsch[DLSCH_id].Nl;
|
||||
TB_decoding_params->BG = dlsch_config->ldpcBaseGraph;
|
||||
TB_decoding_params->A = dlsch_config->TBS;
|
||||
// ------------------------------------------------------------------
|
||||
|
||||
TB_decoding_params->processedSegments = &harq_process->processedSegments;
|
||||
|
||||
float Coderate = (float)dlsch->dlsch_config.targetCodeRate / 10240.0f;
|
||||
|
||||
LOG_D(
|
||||
PHY,
|
||||
"%d.%d DLSCH %d Decoding, harq_pid %d TBS %d G %d nb_re_dmrs %d length dmrs %d mcs %d Nl %d nb_symb_sch %d nb_rb %d Qm %d "
|
||||
"Coderate %f\n",
|
||||
slot_decoding_params.frame,
|
||||
slot_decoding_params.slot,
|
||||
DLSCH_id,
|
||||
harq_pid,
|
||||
dlsch_config->TBS,
|
||||
TB_decoding_params->G,
|
||||
nb_re_dmrs,
|
||||
dmrs_length,
|
||||
TB_decoding_params->mcs,
|
||||
TB_decoding_params->nb_layers,
|
||||
dlsch_config->number_symbols,
|
||||
TB_decoding_params->nb_rb,
|
||||
TB_decoding_params->Qm,
|
||||
Coderate);
|
||||
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_DLSCH_SEGMENTATION, VCD_FUNCTION_IN);
|
||||
|
||||
if (harq_process->first_rx == 1) {
|
||||
// This is a new packet, so compute quantities regarding segmentation
|
||||
nr_segmentation(NULL,
|
||||
NULL,
|
||||
lenWithCrc(1, TB_decoding_params->A), // We give a max size in case of 1 segment
|
||||
&TB_decoding_params->C,
|
||||
&TB_decoding_params->K,
|
||||
&TB_decoding_params->Z, // [hna] Z is Zc
|
||||
&TB_decoding_params->F,
|
||||
TB_decoding_params->BG);
|
||||
harq_process->C = TB_decoding_params->C;
|
||||
harq_process->K = TB_decoding_params->K;
|
||||
harq_process->Z = TB_decoding_params->Z;
|
||||
harq_process->F = TB_decoding_params->F;
|
||||
|
||||
if (harq_process->C > MAX_NUM_NR_DLSCH_SEGMENTS_PER_LAYER * TB_decoding_params->nb_layers) {
|
||||
LOG_E(PHY, "nr_segmentation.c: too many segments %d, A %d\n", harq_process->C, TB_decoding_params->A);
|
||||
return dlsch[DLSCH_id].max_ldpc_iterations + 1;
|
||||
}
|
||||
|
||||
if (LOG_DEBUGFLAG(DEBUG_DLSCH_DECOD) && (!slot_decoding_params.frame % 100))
|
||||
LOG_I(PHY, "K %d C %d Z %d nl %d \n", harq_process->K, harq_process->C, harq_process->Z, TB_decoding_params->nb_layers);
|
||||
// clear HARQ buffer
|
||||
for (int i = 0; i < harq_process->C; i++)
|
||||
memset(harq_process->d[i], 0, 5 * 8448 * sizeof(int16_t));
|
||||
} else {
|
||||
// This is not a new packet, so retrieve previously computed quantities regarding segmentation
|
||||
TB_decoding_params->C = harq_process->C;
|
||||
TB_decoding_params->K = harq_process->K;
|
||||
TB_decoding_params->Z = harq_process->Z;
|
||||
TB_decoding_params->F = harq_process->F;
|
||||
}
|
||||
max_num_segments = max(max_num_segments, TB_decoding_params->C);
|
||||
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_DLSCH_SEGMENTATION, VCD_FUNCTION_OUT);
|
||||
|
||||
if (LOG_DEBUGFLAG(DEBUG_DLSCH_DECOD))
|
||||
LOG_I(PHY, "Segmentation: C %d, K %d\n", harq_process->C, harq_process->K);
|
||||
|
||||
TB_decoding_params->rnti = dlsch[DLSCH_id].rnti;
|
||||
TB_decoding_params->max_ldpc_iterations = dlsch[DLSCH_id].max_ldpc_iterations;
|
||||
TB_decoding_params->rv_index = dlsch_config->rv;
|
||||
TB_decoding_params->tbslbrm = dlsch_config->tbslbrm;
|
||||
TB_decoding_params->abort_decode = &harq_process->abort_decode;
|
||||
set_abort(&harq_process->abort_decode, false);
|
||||
}
|
||||
|
||||
nrLDPC_segment_decoding_parameters_t segments[nb_dlsch][max_num_segments];
|
||||
bool d_to_be_cleared[nb_dlsch][max_num_segments];
|
||||
|
||||
for (uint8_t pdsch_id = 0; pdsch_id < nb_dlsch; pdsch_id++) {
|
||||
uint8_t DLSCH_id = DLSCH_ids[pdsch_id];
|
||||
fapi_nr_dl_config_dlsch_pdu_rel15_t *dlsch_config = &dlsch[DLSCH_id].dlsch_config;
|
||||
int harq_pid = dlsch_config->harq_process_nbr;
|
||||
NR_DL_UE_HARQ_t *harq_process = &phy_vars_ue->dl_harq_processes[DLSCH_id][harq_pid];
|
||||
nrLDPC_TB_decoding_parameters_t *TB_decoding_params = &TBs[pdsch_id];
|
||||
TB_decoding_params->segments = segments[pdsch_id];
|
||||
|
||||
uint32_t r_offset = 0;
|
||||
for (int r = 0; r < TB_decoding_params->C; r++) {
|
||||
if (harq_process->first_rx == 1)
|
||||
d_to_be_cleared[pdsch_id][r] = true;
|
||||
else
|
||||
d_to_be_cleared[pdsch_id][r] = false;
|
||||
nrLDPC_segment_decoding_parameters_t *segment_decoding_params = &TB_decoding_params->segments[r];
|
||||
segment_decoding_params->E =
|
||||
nr_get_E(TB_decoding_params->G, TB_decoding_params->C, TB_decoding_params->Qm, TB_decoding_params->nb_layers, r);
|
||||
segment_decoding_params->R = nr_get_R_ldpc_decoder(TB_decoding_params->rv_index,
|
||||
segment_decoding_params->E,
|
||||
TB_decoding_params->BG,
|
||||
TB_decoding_params->Z,
|
||||
&harq_process->llrLen,
|
||||
harq_process->DLround);
|
||||
segment_decoding_params->llr = dlsch_llr[DLSCH_id] + r_offset;
|
||||
segment_decoding_params->d = harq_process->d[r];
|
||||
segment_decoding_params->d_to_be_cleared = &d_to_be_cleared[pdsch_id][r];
|
||||
segment_decoding_params->c = harq_process->c[r];
|
||||
segment_decoding_params->decodeSuccess = false;
|
||||
|
||||
r_offset += segment_decoding_params->E;
|
||||
}
|
||||
}
|
||||
|
||||
int number_tasks_decode = nrLDPC_coding_interface.nrLDPC_coding_decoder(&slot_decoding_params);
|
||||
|
||||
// Execute thread pool tasks if any
|
||||
while (number_tasks_decode > 0) {
|
||||
notifiedFIFO_elt_t *req = pullTpool(&nf, &get_nrUE_params()->Tpool);
|
||||
if (req == NULL)
|
||||
return dlsch[0].last_iteration_cnt; // Tpool has been stopped
|
||||
delNotifiedFIFO_elt(req);
|
||||
number_tasks_decode--;
|
||||
}
|
||||
|
||||
// post decode
|
||||
for (uint8_t pdsch_id = 0; pdsch_id < nb_dlsch; pdsch_id++) {
|
||||
uint8_t DLSCH_id = DLSCH_ids[pdsch_id];
|
||||
fapi_nr_dl_config_dlsch_pdu_rel15_t *dlsch_config = &dlsch[DLSCH_id].dlsch_config;
|
||||
int harq_pid = dlsch_config->harq_process_nbr;
|
||||
NR_DL_UE_HARQ_t *harq_process = &phy_vars_ue->dl_harq_processes[DLSCH_id][harq_pid];
|
||||
|
||||
nrLDPC_TB_decoding_parameters_t *TB_decoding_params = &TBs[pdsch_id];
|
||||
|
||||
uint32_t offset = 0;
|
||||
for (int r = 0; r < TB_decoding_params->C; r++) {
|
||||
nrLDPC_segment_decoding_parameters_t *segment_decoding_params = &TB_decoding_params->segments[r];
|
||||
if (segment_decoding_params->decodeSuccess) {
|
||||
memcpy(b[DLSCH_id] + offset,
|
||||
harq_process->c[r],
|
||||
(harq_process->K >> 3) - (harq_process->F >> 3) - ((harq_process->C > 1) ? 3 : 0));
|
||||
} else {
|
||||
LOG_D(PHY, "downlink segment error %d/%d\n", r, harq_process->C);
|
||||
LOG_D(PHY, "DLSCH %d in error\n", DLSCH_id);
|
||||
}
|
||||
offset += (harq_process->K >> 3) - (harq_process->F >> 3) - ((harq_process->C > 1) ? 3 : 0);
|
||||
}
|
||||
|
||||
kpiStructure.nb_total++;
|
||||
kpiStructure.blockSize = dlsch_config->TBS;
|
||||
kpiStructure.dl_mcs = dlsch_config->mcs;
|
||||
kpiStructure.nofRBs = dlsch_config->number_rbs;
|
||||
|
||||
if (harq_process->processedSegments == harq_process->C) {
|
||||
if (harq_process->C > 1) {
|
||||
int A = dlsch_config->TBS;
|
||||
/* check global CRC */
|
||||
// we have regrouped the transport block, so it is "1" segment
|
||||
if (!check_crc(b[DLSCH_id], lenWithCrc(1, A), crcType(1, A))) {
|
||||
harq_process->ack = 0;
|
||||
dlsch[DLSCH_id].last_iteration_cnt = dlsch[DLSCH_id].max_ldpc_iterations + 1;
|
||||
LOG_E(PHY,
|
||||
"Frame %d.%d LDPC global CRC fails, but individual LDPC CRC succeeded. %d segs\n",
|
||||
proc->frame_rx,
|
||||
proc->nr_slot_rx,
|
||||
harq_process->C);
|
||||
LOG_D(PHY, "DLSCH %d received nok\n", DLSCH_id);
|
||||
}
|
||||
// We search only a reccuring OAI error that propagates all 0 packets with a 0 CRC, so we do the check only if the 2 first
|
||||
// bytes of the CRC are 0 (it can be CRC16 or CRC24)
|
||||
const int sz = A / 8;
|
||||
if (b[DLSCH_id][sz] == 0 && b[DLSCH_id][sz + 1] == 0) {
|
||||
int i = 0;
|
||||
while (b[DLSCH_id][i] == 0 && i < sz)
|
||||
i++;
|
||||
if (i == sz) {
|
||||
LOG_E(PHY,
|
||||
"received all 0 pdu, consider it false reception, even if the TS 38.212 7.2.1 says only we should attach the "
|
||||
"corresponding CRC, and nothing prevents to have a all 0 packet\n");
|
||||
dlsch[DLSCH_id].last_iteration_cnt = dlsch[DLSCH_id].max_ldpc_iterations + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
harq_process->status = SCH_IDLE;
|
||||
harq_process->ack = 1;
|
||||
|
||||
// Same as gNB, set to max_ldpc_iterations is sufficient given that this variable is only used for checking for failure
|
||||
dlsch[DLSCH_id].last_iteration_cnt = dlsch[DLSCH_id].max_ldpc_iterations;
|
||||
LOG_D(PHY, "DLSCH %d received ok\n", DLSCH_id);
|
||||
} else {
|
||||
kpiStructure.nb_nack++;
|
||||
|
||||
harq_process->ack = 0;
|
||||
|
||||
// Same as gNB, set to max_ldpc_iterations + 1 is sufficient given that this variable is only used for checking for failure
|
||||
dlsch[DLSCH_id].last_iteration_cnt = dlsch[DLSCH_id].max_ldpc_iterations + 1;
|
||||
LOG_D(PHY, "DLSCH %d received nok\n", DLSCH_id);
|
||||
}
|
||||
}
|
||||
|
||||
return dlsch[0].last_iteration_cnt;
|
||||
}
|
||||
@@ -175,29 +175,29 @@ void nr_conjch0_mult_ch1(int *ch0,
|
||||
unsigned short nb_rb,
|
||||
unsigned char output_shift0);
|
||||
|
||||
/** \brief This is the top-level entry point for DLSCH decoding in UE. It should be replicated on several
|
||||
/** \brief This is the top-level entry point for DLSCH decoding in UE. It should be replicated on several
|
||||
threads (on multi-core machines) corresponding to different HARQ processes. The routine first
|
||||
computes the segmentation information, followed by rate dematching and sub-block deinterleaving the of the
|
||||
computes the segmentation information, followed by rate dematching and sub-block deinterleaving of the
|
||||
received LLRs computed by dlsch_demodulation for each transport block segment. It then calls the
|
||||
turbo-decoding algorithm for each segment and stops after either after unsuccesful decoding of at least
|
||||
one segment or correct decoding of all segments. Only the segment CRCs are check for the moment, the
|
||||
overall CRC is ignored. Finally transport block reassembly is performed.
|
||||
@param phy_vars_ue Pointer to ue variables
|
||||
@param proc
|
||||
@param eNB_id
|
||||
@param dlsch_llr Pointer to LLR values computed by dlsch_demodulation
|
||||
@param frame_parms Pointer to frame descriptor
|
||||
@param dlsch Pointer to DLSCH descriptor
|
||||
@param harq_process
|
||||
@param frame Frame number
|
||||
@param nb_symb_sch
|
||||
@param nr_slot_rx Slot number
|
||||
@param harq_pid
|
||||
@param b_size
|
||||
@param b
|
||||
LDPC decoding algorithm for each segment and stops after either unsuccesful decoding of at least
|
||||
one segment or correct decoding of all segments.Only the segment CRCs are checked for the moment, the
|
||||
overall CRC is ignored. Finally transport block reassembly is performed.
|
||||
@param[in] phy_vars_ue Pointer to ue variables
|
||||
@param[in] proc
|
||||
@param[in] eNB_id
|
||||
@param[in] dlsch_llr Pointer to LLR values computed by dlsch_demodulation
|
||||
@param[in] frame_parms Pointer to frame descriptor
|
||||
@param[in] dlsch Pointer to DLSCH descriptor
|
||||
@param[in] harq_process
|
||||
@param[in] frame Frame number
|
||||
@param[in] nb_symb_sch
|
||||
@param[in] nr_slot_rx Slot number
|
||||
@param[in] harq_pid
|
||||
@param[in] b_size
|
||||
@param[in] b
|
||||
@param[in] G
|
||||
@returns 0 on success, 1 on unsuccessful decoding
|
||||
*/
|
||||
|
||||
uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue,
|
||||
const UE_nr_rxtx_proc_t *proc,
|
||||
int eNB_id,
|
||||
@@ -213,6 +213,44 @@ uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue,
|
||||
uint8_t b[b_size],
|
||||
int G);
|
||||
|
||||
/** \brief This is the alternative top-level entry point for DLSCH decoding in UE.
|
||||
It handles all the HARQ processes in only one call. The routine first
|
||||
computes the segmentation information and then call LDPC decoder on the
|
||||
received LLRs computed by dlsch_demodulation.
|
||||
It stops after either unsuccesful decoding of at least
|
||||
one segment or correct decoding of all segments. Only the segment CRCs are checked for the moment, the
|
||||
overall CRC is ignored. Finally transport block reassembly is performed.
|
||||
@param[in] phy_vars_ue Pointer to ue variables
|
||||
@param[in] proc
|
||||
@param[in] dlsch_llr Pointers to LLR values computed by dlsch_demodulation
|
||||
@param[in] b
|
||||
@param[in] G array of Gs
|
||||
@param[in] nb_dlsch number of active downlink shared channels
|
||||
@param[in] DLSCH_ids array of active downlink shared channels
|
||||
@returns 0 on success, 1 on unsuccessful decoding
|
||||
*/
|
||||
uint32_t nr_dlsch_decoding_slot(PHY_VARS_NR_UE *phy_vars_ue,
|
||||
const UE_nr_rxtx_proc_t *proc,
|
||||
NR_UE_DLSCH_t *dlsch,
|
||||
short **dlsch_llr,
|
||||
uint8_t **b,
|
||||
int *G,
|
||||
int nb_dlsch,
|
||||
uint8_t *DLSCH_ids);
|
||||
|
||||
/** \brief This is the top-level entry point for ULSCH encoding in UE. It should be replicated on several
|
||||
threads (on multi-core machines) corresponding to different HARQ processes. The routine first
|
||||
computes the segmentation information, followed by LDPC encoding algorithm of the
|
||||
Transport Block for each transport block segment. It then calls the
|
||||
rate dematching and sub-block deinterleaving for each segment.
|
||||
@param[in] phy_vars_ue Pointer to ue variables
|
||||
@param[in] ulsch Pointer to ULSCH descriptor
|
||||
@param[in] frame_parms Pointer to frame descriptor
|
||||
@param[in] harq_pid HARQ process id
|
||||
@param[in] tb_size Transport Block size
|
||||
@param[in] G
|
||||
@returns 0 on success, -1 on unsuccessful decoding
|
||||
*/
|
||||
int nr_ulsch_encoding(PHY_VARS_NR_UE *ue,
|
||||
NR_UE_ULSCH_t *ulsch,
|
||||
NR_DL_FRAME_PARMS* frame_parms,
|
||||
@@ -220,6 +258,27 @@ int nr_ulsch_encoding(PHY_VARS_NR_UE *ue,
|
||||
uint32_t tb_size,
|
||||
unsigned int G);
|
||||
|
||||
/** \brief This is the alternative top-level entry point for ULSCH encoding in UE.
|
||||
It handles all the HARQ processes in only one call. The routine first
|
||||
computes the segmentation information, followed by LDPC encoding algorithm of the
|
||||
Transport Block.
|
||||
@param[in] phy_vars_ue pointer to ue variables
|
||||
@param[in] ulsch Pointer to ULSCH descriptor
|
||||
@param[in] frame frame index
|
||||
@param[in] slot slot index
|
||||
@param[in] G array of Gs
|
||||
@param[in] nb_ulsch number of uplink shared channels
|
||||
@param[in] ULSCH_ids array of uplink shared channel ids
|
||||
@returns 0 on success, -1 on unsuccessful decoding
|
||||
*/
|
||||
int nr_ulsch_encoding_slot(PHY_VARS_NR_UE *ue,
|
||||
NR_UE_ULSCH_t *ulsch,
|
||||
const uint32_t frame,
|
||||
const uint8_t slot,
|
||||
unsigned int *G,
|
||||
int nb_ulsch,
|
||||
uint8_t *ULSCH_ids);
|
||||
|
||||
/*! \brief Perform PUSCH scrambling. TS 38.211 V15.4.0 subclause 6.3.1.1
|
||||
@param[in] in Pointer to input bits
|
||||
@param[in] size of input bits
|
||||
@@ -240,8 +299,14 @@ void nr_pusch_codeword_scrambling(uint8_t *in,
|
||||
- scrambling
|
||||
- modulation
|
||||
- transform precoding
|
||||
@param[in] UE pointer to ue variables
|
||||
@param[in] harq_pid
|
||||
@param[in] frame frame index
|
||||
@param[in] slot slot index
|
||||
@param[in] gNB_id gNB index
|
||||
@param[in] phy_data PHY layer informations
|
||||
@param[in] c16_t
|
||||
*/
|
||||
|
||||
void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE,
|
||||
const unsigned char harq_pid,
|
||||
const uint32_t frame,
|
||||
@@ -250,6 +315,25 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE,
|
||||
nr_phy_data_tx_t *phy_data,
|
||||
c16_t **txdataF);
|
||||
|
||||
/** \brief Alternative entry point to UE uplink shared channels procedures.
|
||||
It handles all the HARQ processes in only one call.
|
||||
Performs the following functionalities:
|
||||
- encoding
|
||||
- scrambling
|
||||
- modulation
|
||||
- transform precoding
|
||||
@param[in] UE pointer to ue variables
|
||||
@param[in] frame frame index
|
||||
@param[in] slot slot index
|
||||
@param[in] phy_data PHY layer informations
|
||||
@param[in] c16_t
|
||||
*/
|
||||
void nr_ue_ulsch_procedures_slot(PHY_VARS_NR_UE *UE,
|
||||
const uint32_t frame,
|
||||
const uint8_t slot,
|
||||
nr_phy_data_tx_t *phy_data,
|
||||
c16_t **txdataF);
|
||||
|
||||
/** \brief This function does IFFT for PUSCH
|
||||
*/
|
||||
|
||||
|
||||
@@ -126,6 +126,8 @@ typedef struct {
|
||||
/// Last index of LLR buffer that contains information.
|
||||
/// Used for computing LDPC decoder R
|
||||
int llrLen;
|
||||
/// Number of segments processed so far
|
||||
uint32_t processedSegments;
|
||||
decode_abort_t abort_decode;
|
||||
} NR_DL_UE_HARQ_t;
|
||||
|
||||
|
||||
187
openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_coding_slot.c
Normal file
187
openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_coding_slot.c
Normal file
@@ -0,0 +1,187 @@
|
||||
/*
|
||||
* 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 PHY/NR_UE_TRANSPORT/nr_ulsch_coding_slot.c
|
||||
*/
|
||||
|
||||
#include "PHY/defs_UE.h"
|
||||
#include "PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h"
|
||||
#include "PHY/CODING/coding_defs.h"
|
||||
#include "PHY/CODING/coding_extern.h"
|
||||
#include "PHY/CODING/lte_interleaver_inline.h"
|
||||
#include "PHY/CODING/nrLDPC_extern.h"
|
||||
#include "PHY/CODING/nrLDPC_coding_interface.h"
|
||||
#include "PHY/NR_UE_TRANSPORT/nr_transport_ue.h"
|
||||
#include "executables/nr-uesoftmodem.h"
|
||||
#include "common/utils/LOG/vcd_signal_dumper.h"
|
||||
|
||||
int nr_ulsch_encoding_slot(PHY_VARS_NR_UE *ue,
|
||||
NR_UE_ULSCH_t *ulsch,
|
||||
const uint32_t frame,
|
||||
const uint8_t slot,
|
||||
unsigned int *G,
|
||||
int nb_ulsch,
|
||||
uint8_t *ULSCH_ids)
|
||||
{
|
||||
start_meas_nr_ue_phy(ue, ULSCH_ENCODING_STATS);
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_NR_UE_ULSCH_ENCODING, VCD_FUNCTION_IN);
|
||||
|
||||
notifiedFIFO_t nf;
|
||||
initNotifiedFIFO(&nf);
|
||||
|
||||
nrLDPC_slot_encoding_parameters_t slot_encoding_params;
|
||||
slot_encoding_params.frame = frame;
|
||||
slot_encoding_params.slot = slot;
|
||||
slot_encoding_params.nb_TBs = nb_ulsch;
|
||||
slot_encoding_params.respEncode = &nf;
|
||||
slot_encoding_params.threadPool = &get_nrUE_params()->Tpool;
|
||||
slot_encoding_params.tinput = NULL;
|
||||
slot_encoding_params.tprep = NULL;
|
||||
slot_encoding_params.tparity = NULL;
|
||||
slot_encoding_params.toutput = NULL;
|
||||
nrLDPC_TB_encoding_parameters_t TBs[nb_ulsch];
|
||||
slot_encoding_params.TBs = TBs;
|
||||
|
||||
int max_num_segments = 0;
|
||||
|
||||
for (uint8_t pusch_id = 0; pusch_id < nb_ulsch; pusch_id++) {
|
||||
uint8_t ULSCH_id = ULSCH_ids[pusch_id];
|
||||
uint8_t harq_pid = ulsch[ULSCH_id].pusch_pdu.pusch_data.harq_process_id;
|
||||
nrLDPC_TB_encoding_parameters_t *TB_encoding_params = &TBs[pusch_id];
|
||||
TB_encoding_params->xlsch_id = ULSCH_id;
|
||||
|
||||
/////////////////////////parameters and variables initialization/////////////////////////
|
||||
|
||||
unsigned int crc = 1;
|
||||
NR_UL_UE_HARQ_t *harq_process = &ue->ul_harq_processes[harq_pid];
|
||||
const nfapi_nr_ue_pusch_pdu_t *pusch_pdu = &ulsch->pusch_pdu;
|
||||
uint16_t nb_rb = pusch_pdu->rb_size;
|
||||
uint32_t A = pusch_pdu->pusch_data.tb_size << 3;
|
||||
uint8_t Qm = pusch_pdu->qam_mod_order;
|
||||
// target_code_rate is in 0.1 units
|
||||
float Coderate = (float)pusch_pdu->target_code_rate / 10240.0f;
|
||||
|
||||
LOG_D(NR_PHY, "ulsch coding nb_rb %d, Nl = %d\n", nb_rb, pusch_pdu->nrOfLayers);
|
||||
LOG_D(NR_PHY, "ulsch coding A %d G %d mod_order %d Coderate %f\n", A, G[pusch_id], Qm, Coderate);
|
||||
LOG_D(NR_PHY, "harq_pid %d, pusch_data.new_data_indicator %d\n", harq_pid, pusch_pdu->pusch_data.new_data_indicator);
|
||||
|
||||
///////////////////////// a---->| add CRC |---->b /////////////////////////
|
||||
|
||||
int max_payload_bytes = MAX_NUM_NR_ULSCH_SEGMENTS_PER_LAYER * pusch_pdu->nrOfLayers * 1056;
|
||||
int B;
|
||||
if (A > NR_MAX_PDSCH_TBS) {
|
||||
// Add 24-bit crc (polynomial A) to payload
|
||||
crc = crc24a(harq_process->payload_AB, A) >> 8;
|
||||
harq_process->payload_AB[A >> 3] = ((uint8_t *)&crc)[2];
|
||||
harq_process->payload_AB[1 + (A >> 3)] = ((uint8_t *)&crc)[1];
|
||||
harq_process->payload_AB[2 + (A >> 3)] = ((uint8_t *)&crc)[0];
|
||||
B = A + 24;
|
||||
AssertFatal((A / 8) + 4 <= max_payload_bytes, "A %d is too big (A/8+4 = %d > %d)\n", A, (A / 8) + 4, max_payload_bytes);
|
||||
} else {
|
||||
// Add 16-bit crc (polynomial A) to payload
|
||||
crc = crc16(harq_process->payload_AB, A) >> 16;
|
||||
harq_process->payload_AB[A >> 3] = ((uint8_t *)&crc)[1];
|
||||
harq_process->payload_AB[1 + (A >> 3)] = ((uint8_t *)&crc)[0];
|
||||
B = A + 16;
|
||||
AssertFatal((A / 8) + 3 <= max_payload_bytes, "A %d is too big (A/8+3 = %d > %d)\n", A, (A / 8) + 3, max_payload_bytes);
|
||||
}
|
||||
|
||||
///////////////////////// b---->| block segmentation |---->c /////////////////////////
|
||||
|
||||
harq_process->BG = pusch_pdu->ldpcBaseGraph;
|
||||
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_NR_SEGMENTATION, VCD_FUNCTION_IN);
|
||||
start_meas_nr_ue_phy(ue, ULSCH_SEGMENTATION_STATS);
|
||||
TB_encoding_params->Kb = nr_segmentation(harq_process->payload_AB,
|
||||
harq_process->c,
|
||||
B,
|
||||
&harq_process->C,
|
||||
&harq_process->K,
|
||||
&harq_process->Z,
|
||||
&harq_process->F,
|
||||
harq_process->BG);
|
||||
TB_encoding_params->C = harq_process->C;
|
||||
TB_encoding_params->K = harq_process->K;
|
||||
TB_encoding_params->Z = harq_process->Z;
|
||||
TB_encoding_params->F = harq_process->F;
|
||||
TB_encoding_params->BG = harq_process->BG;
|
||||
if (TB_encoding_params->C > MAX_NUM_NR_DLSCH_SEGMENTS_PER_LAYER * pusch_pdu->nrOfLayers) {
|
||||
LOG_E(PHY, "nr_segmentation.c: too many segments %d, B %d\n", TB_encoding_params->C, B);
|
||||
return (-1);
|
||||
}
|
||||
stop_meas_nr_ue_phy(ue, ULSCH_SEGMENTATION_STATS);
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_NR_SEGMENTATION, VCD_FUNCTION_OUT);
|
||||
max_num_segments = max(max_num_segments, TB_encoding_params->C);
|
||||
|
||||
TB_encoding_params->rnti = pusch_pdu->rnti;
|
||||
TB_encoding_params->nb_rb = nb_rb;
|
||||
TB_encoding_params->Qm = Qm;
|
||||
TB_encoding_params->mcs = pusch_pdu->mcs_index;
|
||||
TB_encoding_params->nb_layers = pusch_pdu->nrOfLayers;
|
||||
TB_encoding_params->rv_index = pusch_pdu->pusch_data.rv_index;
|
||||
TB_encoding_params->G = G[pusch_id];
|
||||
TB_encoding_params->tbslbrm = pusch_pdu->tbslbrm;
|
||||
TB_encoding_params->A = A;
|
||||
} // pusch_id
|
||||
|
||||
nrLDPC_segment_encoding_parameters_t segments[nb_ulsch][max_num_segments];
|
||||
|
||||
for (uint8_t pusch_id = 0; pusch_id < nb_ulsch; pusch_id++) {
|
||||
uint8_t ULSCH_id = ULSCH_ids[pusch_id];
|
||||
uint8_t harq_pid = ulsch[ULSCH_id].pusch_pdu.pusch_data.harq_process_id;
|
||||
nrLDPC_TB_encoding_parameters_t *TB_encoding_params = &TBs[pusch_id];
|
||||
NR_UL_UE_HARQ_t *harq_process = &ue->ul_harq_processes[harq_pid];
|
||||
TB_encoding_params->segments = segments[pusch_id];
|
||||
|
||||
int r_offset = 0;
|
||||
for (int r = 0; r < TB_encoding_params->C; r++) {
|
||||
nrLDPC_segment_encoding_parameters_t *segment_encoding_params = &TB_encoding_params->segments[r];
|
||||
segment_encoding_params->c = harq_process->c[r];
|
||||
segment_encoding_params->E =
|
||||
nr_get_E(TB_encoding_params->G, TB_encoding_params->C, TB_encoding_params->Qm, TB_encoding_params->nb_layers, r);
|
||||
segment_encoding_params->output = harq_process->f + r_offset;
|
||||
r_offset += segment_encoding_params->E;
|
||||
} // TB_encoding_params->C
|
||||
} // pusch_id
|
||||
|
||||
///////////////////////// | LDCP coding | ////////////////////////////////////
|
||||
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_LDPC_ENCODER_OPTIM, VCD_FUNCTION_IN);
|
||||
|
||||
int nbJobs = 0;
|
||||
nbJobs = nrLDPC_coding_interface.nrLDPC_coding_encoder(&slot_encoding_params);
|
||||
|
||||
if (nbJobs < 0)
|
||||
return -1;
|
||||
while (nbJobs) {
|
||||
notifiedFIFO_elt_t *req = pullTpool(&nf, &get_nrUE_params()->Tpool);
|
||||
if (req == NULL)
|
||||
break; // Tpool has been stopped
|
||||
delNotifiedFIFO_elt(req);
|
||||
nbJobs--;
|
||||
}
|
||||
|
||||
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_NR_UE_ULSCH_ENCODING, VCD_FUNCTION_OUT);
|
||||
stop_meas_nr_ue_phy(ue, ULSCH_LDPC_ENCODING_STATS);
|
||||
return 0;
|
||||
}
|
||||
@@ -85,6 +85,467 @@ void nr_pusch_codeword_scrambling(uint8_t *in, uint32_t size, uint32_t Nid, uint
|
||||
nr_codeword_scrambling(in, size, 0, Nid, n_RNTI, out);
|
||||
}
|
||||
|
||||
void nr_ue_ulsch_procedures_slot(PHY_VARS_NR_UE *UE,
|
||||
const uint32_t frame,
|
||||
const uint8_t slot,
|
||||
nr_phy_data_tx_t *phy_data,
|
||||
c16_t **txdataF)
|
||||
{
|
||||
|
||||
int harq_pid = phy_data->ulsch.pusch_pdu.pusch_data.harq_process_id;
|
||||
|
||||
if (UE->ul_harq_processes[harq_pid].ULstatus != ACTIVE)
|
||||
return;
|
||||
|
||||
uint8_t ULSCH_ids[1];
|
||||
unsigned int G[1];
|
||||
uint8_t pusch_id = 0;
|
||||
ULSCH_ids[pusch_id] = 0;
|
||||
LOG_D(PHY, "nr_ue_ulsch_procedures_slot hard_id %d %d.%d prepare for coding\n", harq_pid, frame, slot);
|
||||
|
||||
NR_UE_ULSCH_t *ulsch_ue = &phy_data->ulsch;
|
||||
NR_UL_UE_HARQ_t *harq_process_ul_ue = &UE->ul_harq_processes[harq_pid];
|
||||
const nfapi_nr_ue_pusch_pdu_t *pusch_pdu = &ulsch_ue->pusch_pdu;
|
||||
|
||||
uint16_t number_dmrs_symbols = 0;
|
||||
|
||||
uint16_t nb_rb = pusch_pdu->rb_size;
|
||||
uint8_t number_of_symbols = pusch_pdu->nr_of_symbols;
|
||||
uint8_t dmrs_type = pusch_pdu->dmrs_config_type;
|
||||
uint8_t cdm_grps_no_data = pusch_pdu->num_dmrs_cdm_grps_no_data;
|
||||
uint8_t nb_dmrs_re_per_rb = ((dmrs_type == pusch_dmrs_type1) ? 6 : 4) * cdm_grps_no_data;
|
||||
int start_symbol = pusch_pdu->start_symbol_index;
|
||||
uint16_t ul_dmrs_symb_pos = pusch_pdu->ul_dmrs_symb_pos;
|
||||
uint8_t mod_order = pusch_pdu->qam_mod_order;
|
||||
uint8_t Nl = pusch_pdu->nrOfLayers;
|
||||
uint32_t tb_size = pusch_pdu->pusch_data.tb_size;
|
||||
uint16_t rnti = pusch_pdu->rnti;
|
||||
|
||||
for (int i = start_symbol; i < start_symbol + number_of_symbols; i++) {
|
||||
if ((ul_dmrs_symb_pos >> i) & 0x01)
|
||||
number_dmrs_symbols += 1;
|
||||
}
|
||||
|
||||
///////////////////////PTRS parameters' initialization///////////////////
|
||||
|
||||
uint8_t L_ptrs, K_ptrs = 0;
|
||||
uint32_t unav_res = 0;
|
||||
if (pusch_pdu->pdu_bit_map & PUSCH_PDU_BITMAP_PUSCH_PTRS) {
|
||||
K_ptrs = pusch_pdu->pusch_ptrs.ptrs_freq_density;
|
||||
L_ptrs = 1 << pusch_pdu->pusch_ptrs.ptrs_time_density;
|
||||
|
||||
ulsch_ue->ptrs_symbols = 0;
|
||||
|
||||
set_ptrs_symb_idx(&ulsch_ue->ptrs_symbols, number_of_symbols, start_symbol, L_ptrs, ul_dmrs_symb_pos);
|
||||
int n_ptrs = (nb_rb + K_ptrs - 1) / K_ptrs;
|
||||
int ptrsSymbPerSlot = get_ptrs_symbols_in_slot(ulsch_ue->ptrs_symbols, start_symbol, number_of_symbols);
|
||||
unav_res = n_ptrs * ptrsSymbPerSlot;
|
||||
}
|
||||
|
||||
G[pusch_id] = nr_get_G(nb_rb, number_of_symbols, nb_dmrs_re_per_rb, number_dmrs_symbols, unav_res, mod_order, Nl);
|
||||
|
||||
ws_trace_t tmp = {.nr = true,
|
||||
.direction = DIRECTION_UPLINK,
|
||||
.pdu_buffer = harq_process_ul_ue->payload_AB,
|
||||
.pdu_buffer_size = tb_size,
|
||||
.ueid = 0,
|
||||
.rntiType = WS_C_RNTI,
|
||||
.rnti = rnti,
|
||||
.sysFrame = frame,
|
||||
.subframe = slot,
|
||||
.harq_pid = harq_pid,
|
||||
.oob_event = 0,
|
||||
.oob_event_value = 0};
|
||||
trace_pdu(&tmp);
|
||||
|
||||
/////////////////////////ULSCH coding/////////////////////////
|
||||
|
||||
if (nr_ulsch_encoding_slot(UE, &phy_data->ulsch, frame, slot, G, 1, ULSCH_ids) == -1)
|
||||
return;
|
||||
|
||||
LOG_D(PHY, "nr_ue_ulsch_procedures_slot hard_id %d %d.%d\n", harq_pid, frame, slot);
|
||||
|
||||
int Wf[2], Wt[2];
|
||||
int l_prime[2], delta;
|
||||
int i;
|
||||
int sample_offsetF, N_RE_prime;
|
||||
|
||||
NR_DL_FRAME_PARMS *frame_parms = &UE->frame_parms;
|
||||
|
||||
int N_PRB_oh = 0; // higher layer (RRC) parameter xOverhead in PUSCH-ServingCellConfig
|
||||
|
||||
AssertFatal(pusch_pdu->pusch_uci.harq_ack_bit_length == 0 && pusch_pdu->pusch_uci.csi_part1_bit_length == 0
|
||||
&& pusch_pdu->pusch_uci.csi_part2_bit_length == 0,
|
||||
"UCI on PUSCH not supported at PHY\n");
|
||||
|
||||
uint16_t start_rb = pusch_pdu->rb_start;
|
||||
uint16_t start_sc = frame_parms->first_carrier_offset + (start_rb + pusch_pdu->bwp_start) * NR_NB_SC_PER_RB;
|
||||
|
||||
if (start_sc >= frame_parms->ofdm_symbol_size)
|
||||
start_sc -= frame_parms->ofdm_symbol_size;
|
||||
|
||||
ulsch_ue->Nid_cell = frame_parms->Nid_cell;
|
||||
|
||||
LOG_D(PHY,
|
||||
"ulsch TX %x : start_rb %d nb_rb %d mod_order %d Nl %d Tpmi %d bwp_start %d start_sc %d start_symbol %d num_symbols %d "
|
||||
"cdmgrpsnodata %d "
|
||||
"num_dmrs %d dmrs_re_per_rb %d\n",
|
||||
rnti,
|
||||
start_rb,
|
||||
nb_rb,
|
||||
mod_order,
|
||||
Nl,
|
||||
pusch_pdu->Tpmi,
|
||||
pusch_pdu->bwp_start,
|
||||
start_sc,
|
||||
start_symbol,
|
||||
number_of_symbols,
|
||||
cdm_grps_no_data,
|
||||
number_dmrs_symbols,
|
||||
nb_dmrs_re_per_rb);
|
||||
// TbD num_of_mod_symbols is set but never used
|
||||
N_RE_prime = NR_NB_SC_PER_RB * number_of_symbols - nb_dmrs_re_per_rb * number_dmrs_symbols - N_PRB_oh;
|
||||
harq_process_ul_ue->num_of_mod_symbols = N_RE_prime * nb_rb;
|
||||
|
||||
/////////////////////////ULSCH scrambling/////////////////////////
|
||||
|
||||
uint32_t available_bits = G[pusch_id];
|
||||
// +1 because size can be not modulo 4
|
||||
uint32_t scrambled_output[available_bits / (8 * sizeof(uint32_t)) + 1];
|
||||
memset(scrambled_output, 0, sizeof(scrambled_output));
|
||||
|
||||
nr_pusch_codeword_scrambling(harq_process_ul_ue->f,
|
||||
available_bits,
|
||||
pusch_pdu->data_scrambling_id,
|
||||
rnti,
|
||||
false,
|
||||
scrambled_output);
|
||||
|
||||
/////////////////////////ULSCH modulation/////////////////////////
|
||||
|
||||
int max_num_re = Nl * number_of_symbols * nb_rb * NR_NB_SC_PER_RB;
|
||||
c16_t d_mod[max_num_re] __attribute__((aligned(16)));
|
||||
|
||||
nr_modulation(scrambled_output, // assume one codeword for the moment
|
||||
available_bits,
|
||||
mod_order,
|
||||
(int16_t *)d_mod);
|
||||
|
||||
/////////////////////////DMRS Modulation/////////////////////////
|
||||
|
||||
uint16_t n_dmrs = (pusch_pdu->bwp_start + start_rb + nb_rb) * ((dmrs_type == pusch_dmrs_type1) ? 6 : 4);
|
||||
c16_t mod_dmrs[n_dmrs] __attribute((aligned(16)));
|
||||
|
||||
/////////////////////////ULSCH layer mapping/////////////////////////
|
||||
|
||||
const int sz = available_bits / mod_order;
|
||||
c16_t tx_layers[Nl][sz];
|
||||
memset(tx_layers, 0, sizeof(tx_layers));
|
||||
|
||||
nr_ue_layer_mapping(d_mod, Nl, available_bits / mod_order, sz, tx_layers);
|
||||
|
||||
//////////////////////// ULSCH transform precoding ////////////////////////
|
||||
|
||||
l_prime[0] = 0; // single symbol ap 0
|
||||
|
||||
uint8_t u = 0, v = 0;
|
||||
c16_t *dmrs_seq = NULL;
|
||||
/// Transform-coded "y"-sequences (for definition see 38-211 V15.3.0 2018-09, subsection 6.3.1.4)
|
||||
c16_t y[max_num_re] __attribute__((aligned(16)));
|
||||
memset(y, 0, sizeof(y));
|
||||
|
||||
if (pusch_pdu->transform_precoding == transformPrecoder_enabled) {
|
||||
uint32_t nb_re_pusch = nb_rb * NR_NB_SC_PER_RB;
|
||||
uint32_t y_offset = 0;
|
||||
uint16_t num_dmrs_res_per_symbol = nb_rb * (NR_NB_SC_PER_RB / 2);
|
||||
|
||||
// Calculate index to dmrs seq array based on number of DMRS Subcarriers on this symbol
|
||||
int index = get_index_for_dmrs_lowpapr_seq(num_dmrs_res_per_symbol);
|
||||
u = pusch_pdu->dfts_ofdm.low_papr_group_number;
|
||||
v = pusch_pdu->dfts_ofdm.low_papr_sequence_number;
|
||||
dmrs_seq = dmrs_lowpaprtype1_ul_ref_sig[u][v][index];
|
||||
|
||||
AssertFatal(index >= 0,
|
||||
"Num RBs not configured according to 3GPP 38.211 section 6.3.1.4. For PUSCH with transform precoding, num RBs "
|
||||
"cannot be multiple "
|
||||
"of any other primenumber other than 2,3,5\n");
|
||||
AssertFatal(dmrs_seq != NULL, "DMRS low PAPR seq not found, check if DMRS sequences are generated");
|
||||
|
||||
LOG_D(PHY, "Transform Precoding params. u: %d, v: %d, index for dmrsseq: %d\n", u, v, index);
|
||||
|
||||
for (int l = start_symbol; l < start_symbol + number_of_symbols; l++) {
|
||||
if ((ul_dmrs_symb_pos >> l) & 0x01) /* In the symbol with DMRS no data would be transmitted CDM groups is 2*/
|
||||
continue;
|
||||
|
||||
nr_dft(&y[y_offset], &tx_layers[0][y_offset], nb_re_pusch);
|
||||
|
||||
y_offset = y_offset + nb_re_pusch;
|
||||
|
||||
LOG_D(PHY, "Transform precoding being done on data- symbol: %d, nb_re_pusch: %d, y_offset: %d\n", l, nb_re_pusch, y_offset);
|
||||
|
||||
#ifdef DEBUG_PUSCH_MAPPING
|
||||
printf("NR_ULSCH_UE: y_offset %u\t nb_re_pusch %u \t Symbol %d \t nb_rb %d \n", y_offset, nb_re_pusch, l, nb_rb);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef DEBUG_DFT_IDFT
|
||||
int32_t debug_symbols[MAX_NUM_NR_RE] __attribute__((aligned(16)));
|
||||
int offset = 0;
|
||||
printf("NR_ULSCH_UE: available_bits: %u, mod_order: %d", available_bits, mod_order);
|
||||
|
||||
for (int ll = 0; ll < (available_bits / mod_order); ll++) {
|
||||
debug_symbols[ll] = ulsch_ue->y[ll];
|
||||
}
|
||||
|
||||
printf("NR_ULSCH_UE: numSym: %d, num_dmrs_sym: %d", number_of_symbols, number_dmrs_symbols);
|
||||
for (int ll = 0; ll < (number_of_symbols - number_dmrs_symbols); ll++) {
|
||||
nr_idft(&debug_symbols[offset], nb_re_pusch);
|
||||
offset = offset + nb_re_pusch;
|
||||
}
|
||||
LOG_M("preDFT_all_symbols.m", "UE_preDFT", tx_layers[0], number_of_symbols * nb_re_pusch, 1, 1);
|
||||
LOG_M("postDFT_all_symbols.m", "UE_postDFT", y, number_of_symbols * nb_re_pusch, 1, 1);
|
||||
LOG_M("DEBUG_IDFT_SYMBOLS.m", "UE_Debug_IDFT", debug_symbols, number_of_symbols * nb_re_pusch, 1, 1);
|
||||
LOG_M("UE_DMRS_SEQ.m", "UE_DMRS_SEQ", dmrs_seq, nb_re_pusch, 1, 1);
|
||||
#endif
|
||||
}
|
||||
|
||||
/////////////////////////ULSCH RE mapping/////////////////////////
|
||||
|
||||
const int encoded_length = frame_parms->N_RB_UL * 14 * NR_NB_SC_PER_RB * mod_order * Nl;
|
||||
c16_t tx_precoding[Nl][encoded_length];
|
||||
memset(tx_precoding, 0, sizeof(tx_precoding));
|
||||
|
||||
for (int nl = 0; nl < Nl; nl++) {
|
||||
uint8_t k_prime = 0;
|
||||
uint16_t m = 0;
|
||||
|
||||
#ifdef DEBUG_PUSCH_MAPPING
|
||||
printf("NR_ULSCH_UE: Value of CELL ID %d /t, u %d \n", frame_parms->Nid_cell, u);
|
||||
#endif
|
||||
|
||||
int dmrs_port = get_dmrs_port(nl, pusch_pdu->dmrs_ports);
|
||||
// DMRS params for this dmrs port
|
||||
get_Wt(Wt, dmrs_port, dmrs_type);
|
||||
get_Wf(Wf, dmrs_port, dmrs_type);
|
||||
delta = get_delta(dmrs_port, dmrs_type);
|
||||
|
||||
for (int l = start_symbol; l < start_symbol + number_of_symbols; l++) {
|
||||
uint16_t k = start_sc;
|
||||
uint16_t n = 0;
|
||||
uint8_t is_dmrs_sym = 0;
|
||||
uint8_t is_ptrs_sym = 0;
|
||||
uint16_t dmrs_idx = 0, ptrs_idx = 0;
|
||||
|
||||
c16_t mod_ptrs[nb_rb] __attribute((aligned(16))); // assume maximum number of PTRS per pusch allocation
|
||||
|
||||
if ((ul_dmrs_symb_pos >> l) & 0x01) {
|
||||
is_dmrs_sym = 1;
|
||||
|
||||
if (pusch_pdu->transform_precoding == transformPrecoder_disabled) {
|
||||
if (dmrs_type == pusch_dmrs_type1)
|
||||
dmrs_idx = (pusch_pdu->bwp_start + start_rb) * 6;
|
||||
else
|
||||
dmrs_idx = (pusch_pdu->bwp_start + start_rb) * 4;
|
||||
|
||||
// TODO: performance improvement, we can skip the modulation of DMRS symbols outside the bandwidth part
|
||||
// Perform this on gold sequence, not required when SC FDMA operation is done,
|
||||
LOG_D(PHY, "DMRS in symbol %d\n", l);
|
||||
const uint32_t *gold = nr_gold_pusch(frame_parms->N_RB_UL,
|
||||
frame_parms->symbols_per_slot,
|
||||
pusch_pdu->ul_dmrs_scrambling_id,
|
||||
pusch_pdu->scid,
|
||||
slot,
|
||||
l);
|
||||
nr_modulation(gold,
|
||||
n_dmrs * 2,
|
||||
DMRS_MOD_ORDER,
|
||||
(int16_t *)mod_dmrs); // currently only codeword 0 is modulated. Qm = 2 as DMRS is QPSK modulated
|
||||
} else {
|
||||
dmrs_idx = 0;
|
||||
}
|
||||
} else if (pusch_pdu->pdu_bit_map & PUSCH_PDU_BITMAP_PUSCH_PTRS) {
|
||||
AssertFatal(pusch_pdu->transform_precoding == transformPrecoder_disabled,
|
||||
"PTRS NOT SUPPORTED IF TRANSFORM PRECODING IS ENABLED\n");
|
||||
|
||||
if (is_ptrs_symbol(l, ulsch_ue->ptrs_symbols)) {
|
||||
is_ptrs_sym = 1;
|
||||
const uint32_t *gold = nr_gold_pusch(frame_parms->N_RB_UL,
|
||||
frame_parms->symbols_per_slot,
|
||||
pusch_pdu->ul_dmrs_scrambling_id,
|
||||
pusch_pdu->scid,
|
||||
slot,
|
||||
l);
|
||||
nr_modulation(gold, nb_rb, DMRS_MOD_ORDER, (int16_t *)mod_ptrs);
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < nb_rb * NR_NB_SC_PER_RB; i++) {
|
||||
uint8_t is_dmrs = 0;
|
||||
uint8_t is_ptrs = 0;
|
||||
|
||||
sample_offsetF = l * frame_parms->ofdm_symbol_size + k;
|
||||
|
||||
if (is_dmrs_sym) {
|
||||
if (k == ((start_sc + get_dmrs_freq_idx_ul(n, k_prime, delta, dmrs_type)) % frame_parms->ofdm_symbol_size))
|
||||
is_dmrs = 1;
|
||||
} else if (is_ptrs_sym) {
|
||||
is_ptrs = is_ptrs_subcarrier(k,
|
||||
rnti,
|
||||
pusch_pdu->pusch_ptrs.ptrs_freq_density,
|
||||
nb_rb,
|
||||
pusch_pdu->pusch_ptrs.ptrs_ports_list[0].ptrs_re_offset,
|
||||
start_sc,
|
||||
frame_parms->ofdm_symbol_size);
|
||||
}
|
||||
|
||||
if (is_dmrs == 1) {
|
||||
// if transform precoding is enabled
|
||||
const int tmp = Wt[l_prime[0]] * Wf[k_prime] * AMP;
|
||||
if (pusch_pdu->transform_precoding == transformPrecoder_enabled)
|
||||
tx_precoding[nl][sample_offsetF] = c16mulRealShift(dmrs_seq[dmrs_idx], tmp, 15);
|
||||
else
|
||||
tx_precoding[nl][sample_offsetF] = c16mulRealShift(mod_dmrs[dmrs_idx], tmp, 15);
|
||||
|
||||
#ifdef DEBUG_PUSCH_MAPPING
|
||||
printf("DMRS: Layer: %d\t, dmrs_idx %d\t l %d \t k %d \t k_prime %d \t n %d \t dmrs: %d %d\n",
|
||||
nl,
|
||||
dmrs_idx,
|
||||
l,
|
||||
k,
|
||||
k_prime,
|
||||
n,
|
||||
tx_precoding[nl][sample_offsetF].r,
|
||||
tx_precoding[nl][sample_offsetF].i);
|
||||
#endif
|
||||
|
||||
dmrs_idx++;
|
||||
k_prime++;
|
||||
k_prime &= 1;
|
||||
n += (k_prime) ? 0 : 1;
|
||||
|
||||
} else if (is_ptrs == 1) {
|
||||
uint16_t beta_ptrs = 1; // temp value until power control is implemented
|
||||
tx_precoding[nl][sample_offsetF] = c16mulRealShift(mod_ptrs[ptrs_idx], beta_ptrs * AMP, 15);
|
||||
ptrs_idx++;
|
||||
} else if (!is_dmrs_sym
|
||||
|| allowed_xlsch_re_in_dmrs_symbol(k, start_sc, frame_parms->ofdm_symbol_size, cdm_grps_no_data, dmrs_type)) {
|
||||
if (pusch_pdu->transform_precoding == transformPrecoder_disabled)
|
||||
tx_precoding[nl][sample_offsetF] = tx_layers[nl][m];
|
||||
else
|
||||
tx_precoding[nl][sample_offsetF] = y[m];
|
||||
|
||||
#ifdef DEBUG_PUSCH_MAPPING
|
||||
printf("DATA: layer %d\t m %d\t l %d \t k %d \t tx_precoding: %d %d\n",
|
||||
nl,
|
||||
m,
|
||||
l,
|
||||
k,
|
||||
tx_precoding[nl][sample_offsetF].r,
|
||||
tx_precoding[nl][sample_offsetF].i);
|
||||
#endif
|
||||
|
||||
m++;
|
||||
|
||||
} else {
|
||||
tx_precoding[nl][sample_offsetF] = (c16_t){0};
|
||||
}
|
||||
|
||||
if (++k >= frame_parms->ofdm_symbol_size)
|
||||
k -= frame_parms->ofdm_symbol_size;
|
||||
} // for (i=0; i< nb_rb*NR_NB_SC_PER_RB; i++)
|
||||
} // for (l=start_symbol; l<start_symbol+number_of_symbols; l++)
|
||||
} // for (nl=0; nl < Nl; nl++)
|
||||
|
||||
/////////////////////////ULSCH precoding/////////////////////////
|
||||
|
||||
/// Layer Precoding and Antenna port mapping
|
||||
// tx_layers 0-3 are mapped on antenna ports
|
||||
// The precoding info is supported by nfapi such as num_prgs, prg_size, prgs_list and pm_idx
|
||||
// The same precoding matrix is applied on prg_size RBs, Thus
|
||||
// pmi = prgs_list[rbidx/prg_size].pm_idx, rbidx =0,...,rbSize-1
|
||||
|
||||
// The Precoding matrix:
|
||||
for (int ap = 0; ap < frame_parms->nb_antennas_tx; ap++) {
|
||||
for (int l = start_symbol; l < start_symbol + number_of_symbols; l++) {
|
||||
uint16_t k = start_sc;
|
||||
|
||||
for (int rb = 0; rb < nb_rb; rb++) {
|
||||
// get pmi info
|
||||
uint8_t pmi = pusch_pdu->Tpmi;
|
||||
|
||||
if (pmi == 0) { // unitary Precoding
|
||||
if (k + NR_NB_SC_PER_RB <= frame_parms->ofdm_symbol_size) { // RB does not cross DC
|
||||
if (ap < pusch_pdu->nrOfLayers)
|
||||
memcpy(&txdataF[ap][l * frame_parms->ofdm_symbol_size + k],
|
||||
&tx_precoding[ap][l * frame_parms->ofdm_symbol_size + k],
|
||||
NR_NB_SC_PER_RB * sizeof(c16_t));
|
||||
else
|
||||
memset(&txdataF[ap][l * frame_parms->ofdm_symbol_size + k], 0, NR_NB_SC_PER_RB * sizeof(int32_t));
|
||||
} else { // RB does cross DC
|
||||
int neg_length = frame_parms->ofdm_symbol_size - k;
|
||||
int pos_length = NR_NB_SC_PER_RB - neg_length;
|
||||
if (ap < pusch_pdu->nrOfLayers) {
|
||||
memcpy(&txdataF[ap][l * frame_parms->ofdm_symbol_size + k],
|
||||
&tx_precoding[ap][l * frame_parms->ofdm_symbol_size + k],
|
||||
neg_length * sizeof(c16_t));
|
||||
memcpy(&txdataF[ap][l * frame_parms->ofdm_symbol_size],
|
||||
&tx_precoding[ap][l * frame_parms->ofdm_symbol_size],
|
||||
pos_length * sizeof(int32_t));
|
||||
} else {
|
||||
memset(&txdataF[ap][l * frame_parms->ofdm_symbol_size + k], 0, neg_length * sizeof(int32_t));
|
||||
memset(&txdataF[ap][l * frame_parms->ofdm_symbol_size], 0, pos_length * sizeof(int32_t));
|
||||
}
|
||||
}
|
||||
k += NR_NB_SC_PER_RB;
|
||||
if (k >= frame_parms->ofdm_symbol_size) {
|
||||
k -= frame_parms->ofdm_symbol_size;
|
||||
}
|
||||
} else {
|
||||
// get the precoding matrix weights:
|
||||
const char *W_prec;
|
||||
switch (frame_parms->nb_antennas_tx) {
|
||||
case 1: // 1 antenna port
|
||||
W_prec = nr_W_1l_2p[pmi][ap];
|
||||
break;
|
||||
case 2: // 2 antenna ports
|
||||
if (pusch_pdu->nrOfLayers == 1) // 1 layer
|
||||
W_prec = nr_W_1l_2p[pmi][ap];
|
||||
else // 2 layers
|
||||
W_prec = nr_W_2l_2p[pmi][ap];
|
||||
break;
|
||||
case 4: // 4 antenna ports
|
||||
if (pusch_pdu->nrOfLayers == 1) // 1 layer
|
||||
W_prec = nr_W_1l_4p[pmi][ap];
|
||||
else if (pusch_pdu->nrOfLayers == 2) // 2 layers
|
||||
W_prec = nr_W_2l_4p[pmi][ap];
|
||||
else if (pusch_pdu->nrOfLayers == 3) // 3 layers
|
||||
W_prec = nr_W_3l_4p[pmi][ap];
|
||||
else // 4 layers
|
||||
W_prec = nr_W_4l_4p[pmi][ap];
|
||||
break;
|
||||
default:
|
||||
LOG_D(PHY, "Precoding 1,2, or 4 antenna ports are currently supported\n");
|
||||
W_prec = nr_W_1l_2p[pmi][ap];
|
||||
break;
|
||||
}
|
||||
|
||||
for (int i = 0; i < NR_NB_SC_PER_RB; i++) {
|
||||
int32_t re_offset = l * frame_parms->ofdm_symbol_size + k;
|
||||
txdataF[ap][re_offset] = nr_layer_precoder(encoded_length, tx_precoding, W_prec, pusch_pdu->nrOfLayers, re_offset);
|
||||
if (++k >= frame_parms->ofdm_symbol_size) {
|
||||
k -= frame_parms->ofdm_symbol_size;
|
||||
}
|
||||
}
|
||||
}
|
||||
} // RB loop
|
||||
} // symbol loop
|
||||
} // port loop
|
||||
|
||||
NR_UL_UE_HARQ_t *harq_process_ulsch = NULL;
|
||||
harq_process_ulsch = &UE->ul_harq_processes[harq_pid];
|
||||
harq_process_ulsch->ULstatus = SCH_IDLE;
|
||||
}
|
||||
|
||||
void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE,
|
||||
const unsigned char harq_pid,
|
||||
const uint32_t frame,
|
||||
|
||||
@@ -613,7 +613,9 @@ typedef struct PHY_VARS_gNB_s {
|
||||
/// OFDM symbol offset divisor for UL
|
||||
uint32_t ofdm_offset_divisor;
|
||||
|
||||
/// NR LDPC coding related
|
||||
int ldpc_offload_flag;
|
||||
int nrLDPC_coding_interface_flag; // Flag enabling NR LDPC coding module
|
||||
|
||||
int max_ldpc_iterations;
|
||||
/// indicate the channel estimation technique in time domain
|
||||
|
||||
@@ -484,6 +484,9 @@ typedef struct PHY_VARS_NR_UE_s {
|
||||
/// N0 (used for abstraction)
|
||||
double N0;
|
||||
|
||||
/// NR LDPC coding related
|
||||
int nrLDPC_coding_interface_flag; // Flag enabling NR LDPC coding module
|
||||
|
||||
uint8_t max_ldpc_iterations;
|
||||
|
||||
int ldpc_offload_enable;
|
||||
|
||||
@@ -378,6 +378,147 @@ static void nr_postDecode(PHY_VARS_gNB *gNB, notifiedFIFO_elt_t *req)
|
||||
}
|
||||
}
|
||||
|
||||
static int nr_ulsch_procedures_slot(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx)
|
||||
{
|
||||
NR_DL_FRAME_PARMS *frame_parms = &gNB->frame_parms;
|
||||
|
||||
int nb_pusch = 0;
|
||||
for (uint8_t ULSCH_id = 0; ULSCH_id < gNB->max_nb_pusch; ULSCH_id++) {
|
||||
NR_gNB_ULSCH_t *ulsch = &gNB->ulsch[ULSCH_id];
|
||||
if ((ulsch->active == true) && (ulsch->frame == frame_rx) && (ulsch->slot == slot_rx) && (ulsch->handled == 0)) {
|
||||
nb_pusch++;
|
||||
}
|
||||
}
|
||||
|
||||
if (nb_pusch == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t *ULSCH_ids = calloc(nb_pusch,sizeof(uint8_t));
|
||||
uint32_t *G = calloc(nb_pusch,sizeof(uint32_t));
|
||||
int pusch_id = 0;
|
||||
for (uint8_t ULSCH_id = 0; ULSCH_id < gNB->max_nb_pusch; ULSCH_id++) {
|
||||
|
||||
ULSCH_ids[pusch_id] = ULSCH_id;
|
||||
NR_gNB_ULSCH_t *ulsch = &gNB->ulsch[ULSCH_id];
|
||||
if ((ulsch->active == true) && (ulsch->frame == frame_rx) && (ulsch->slot == slot_rx) && (ulsch->handled == 0)) {
|
||||
|
||||
nfapi_nr_pusch_pdu_t *pusch_pdu = &gNB->ulsch[ULSCH_id].harq_process->ulsch_pdu;
|
||||
|
||||
uint16_t nb_re_dmrs;
|
||||
uint16_t start_symbol = pusch_pdu->start_symbol_index;
|
||||
uint16_t number_symbols = pusch_pdu->nr_of_symbols;
|
||||
|
||||
uint8_t number_dmrs_symbols = 0;
|
||||
for (int l = start_symbol; l < start_symbol + number_symbols; l++)
|
||||
number_dmrs_symbols += ((pusch_pdu->ul_dmrs_symb_pos)>>l)&0x01;
|
||||
|
||||
if (pusch_pdu->dmrs_config_type==pusch_dmrs_type1)
|
||||
nb_re_dmrs = 6*pusch_pdu->num_dmrs_cdm_grps_no_data;
|
||||
else
|
||||
nb_re_dmrs = 4*pusch_pdu->num_dmrs_cdm_grps_no_data;
|
||||
|
||||
G[pusch_id] = nr_get_G(pusch_pdu->rb_size,
|
||||
number_symbols,
|
||||
nb_re_dmrs,
|
||||
number_dmrs_symbols, // number of dmrs symbols irrespective of single or double symbol dmrs
|
||||
gNB->ulsch[ULSCH_id].unav_res,
|
||||
pusch_pdu->qam_mod_order,
|
||||
pusch_pdu->nrOfLayers);
|
||||
AssertFatal(G[pusch_id]>0,"G is 0 : rb_size %u, number_symbols %d, nb_re_dmrs %d, number_dmrs_symbols %d, qam_mod_order %u, nrOfLayer %u\n",
|
||||
pusch_pdu->rb_size,
|
||||
number_symbols,
|
||||
nb_re_dmrs,
|
||||
number_dmrs_symbols, // number of dmrs symbols irrespective of single or double symbol dmrs
|
||||
pusch_pdu->qam_mod_order,
|
||||
pusch_pdu->nrOfLayers);
|
||||
LOG_D(PHY,"rb_size %d, number_symbols %d, nb_re_dmrs %d, dmrs symbol positions %d, number_dmrs_symbols %d, qam_mod_order %d, nrOfLayer %d\n",
|
||||
pusch_pdu->rb_size,
|
||||
number_symbols,
|
||||
nb_re_dmrs,
|
||||
pusch_pdu->ul_dmrs_symb_pos,
|
||||
number_dmrs_symbols, // number of dmrs symbols irrespective of single or double symbol dmrs
|
||||
pusch_pdu->qam_mod_order,
|
||||
pusch_pdu->nrOfLayers);
|
||||
pusch_id++;
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------
|
||||
//--------------------- ULSCH decoding ---------------------
|
||||
//----------------------------------------------------------
|
||||
|
||||
int ret_nr_ulsch_decoding_slot =
|
||||
nr_ulsch_decoding_slot(gNB, frame_parms, frame_rx, slot_rx, G, ULSCH_ids, nb_pusch);
|
||||
|
||||
// CRC check per uplink shared channel
|
||||
for (pusch_id = 0; pusch_id < nb_pusch; pusch_id++) {
|
||||
uint8_t ULSCH_id = ULSCH_ids[pusch_id];
|
||||
NR_gNB_ULSCH_t *ulsch = &gNB->ulsch[ULSCH_id];
|
||||
NR_gNB_PUSCH *pusch = &gNB->pusch_vars[ULSCH_id];
|
||||
NR_UL_gNB_HARQ_t *ulsch_harq = ulsch->harq_process;
|
||||
nfapi_nr_pusch_pdu_t *pusch_pdu = &ulsch_harq->ulsch_pdu;
|
||||
|
||||
bool crc_valid = false;
|
||||
|
||||
// if all segments are done
|
||||
if (ulsch_harq->processedSegments == ulsch_harq->C) {
|
||||
if (ulsch_harq->C > 1) {
|
||||
crc_valid = check_crc(ulsch_harq->b, lenWithCrc(1, (ulsch_harq->TBS) << 3), crcType(1, (ulsch_harq->TBS) << 3));
|
||||
} else {
|
||||
// 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 (crc_valid && !check_abort(&ulsch_harq->abort_decode) && !pusch->DTX) {
|
||||
LOG_D(NR_PHY,
|
||||
"[gNB %d] ULSCH %d: Setting ACK for SFN/SF %d.%d (rnti %x, pid %d, ndi %d, status %d, round %d, TBS %d, Max interation "
|
||||
"(all seg) %d)\n",
|
||||
gNB->Mod_id,
|
||||
ULSCH_id,
|
||||
ulsch->frame,
|
||||
ulsch->slot,
|
||||
ulsch->rnti,
|
||||
ulsch->harq_pid,
|
||||
pusch_pdu->pusch_data.new_data_indicator,
|
||||
ulsch->active,
|
||||
ulsch_harq->round,
|
||||
ulsch_harq->TBS,
|
||||
ulsch->max_ldpc_iterations);
|
||||
nr_fill_indication(gNB, ulsch->frame, ulsch->slot, ULSCH_id, ulsch->harq_pid, 0, 0);
|
||||
LOG_D(PHY, "ULSCH received ok \n");
|
||||
ulsch->active = false;
|
||||
ulsch_harq->round = 0;
|
||||
ulsch->last_iteration_cnt = ulsch->max_ldpc_iterations; // Setting to max_ldpc_iterations is sufficient given that this variable is only used for checking for failure
|
||||
} else {
|
||||
LOG_D(PHY,
|
||||
"[gNB %d] ULSCH: Setting NAK for SFN/SF %d/%d (pid %d, ndi %d, status %d, round %d, RV %d, prb_start %d, prb_size %d, "
|
||||
"TBS %d)\n",
|
||||
gNB->Mod_id,
|
||||
ulsch->frame,
|
||||
ulsch->slot,
|
||||
ulsch->harq_pid,
|
||||
pusch_pdu->pusch_data.new_data_indicator,
|
||||
ulsch->active,
|
||||
ulsch_harq->round,
|
||||
ulsch_harq->ulsch_pdu.pusch_data.rv_index,
|
||||
ulsch_harq->ulsch_pdu.rb_start,
|
||||
ulsch_harq->ulsch_pdu.rb_size,
|
||||
ulsch_harq->TBS);
|
||||
nr_fill_indication(gNB, ulsch->frame, ulsch->slot, ULSCH_id, ulsch->harq_pid, 1, 0);
|
||||
ulsch->handled = 1;
|
||||
LOG_D(PHY, "ULSCH %d in error\n",ULSCH_id);
|
||||
ulsch->last_iteration_cnt = ulsch->max_ldpc_iterations + 1; // Setting to max_ldpc_iterations + 1 is sufficient given that this variable is only used for checking for failure
|
||||
}
|
||||
}
|
||||
|
||||
free(ULSCH_ids);
|
||||
free(G);
|
||||
return ret_nr_ulsch_decoding_slot;
|
||||
}
|
||||
|
||||
static int nr_ulsch_procedures(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, int ULSCH_id, uint8_t harq_pid)
|
||||
{
|
||||
NR_DL_FRAME_PARMS *frame_parms = &gNB->frame_parms;
|
||||
@@ -906,14 +1047,30 @@ int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx)
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_NR_RX_PUSCH, 0);
|
||||
// LOG_M("rxdataF_comp.m","rxF_comp",gNB->pusch_vars[0]->rxdataF_comp[0],6900,1,1);
|
||||
// LOG_M("rxdataF_ext.m","rxF_ext",gNB->pusch_vars[0]->rxdataF_ext[0],6900,1,1);
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_NR_ULSCH_PROCEDURES_RX, 1);
|
||||
int const tasks_added = nr_ulsch_procedures(gNB, frame_rx, slot_rx, ULSCH_id, ulsch->harq_pid);
|
||||
if (tasks_added > 0)
|
||||
totalDecode += tasks_added;
|
||||
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_NR_ULSCH_PROCEDURES_RX, 0);
|
||||
}
|
||||
}
|
||||
|
||||
if(gNB->nrLDPC_coding_interface_flag){
|
||||
int const ret_nr_ulsch_procedures_slot = nr_ulsch_procedures_slot(gNB, frame_rx, slot_rx);
|
||||
if (ret_nr_ulsch_procedures_slot != 0) {
|
||||
LOG_E(PHY,"Error in nr_ulsch_procedures_slot, returned %d\n",ret_nr_ulsch_procedures_slot);
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int ULSCH_id = 0; ULSCH_id < gNB->max_nb_pusch; ULSCH_id++) {
|
||||
NR_gNB_ULSCH_t *ulsch = &gNB->ulsch[ULSCH_id];
|
||||
|
||||
if ((ulsch->active == true) && (ulsch->frame == frame_rx) && (ulsch->slot == slot_rx) && (ulsch->handled == 0)) {
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_NR_ULSCH_PROCEDURES_RX, 1);
|
||||
int const tasks_added = nr_ulsch_procedures(gNB, frame_rx, slot_rx, ULSCH_id, ulsch->harq_pid);
|
||||
if (tasks_added > 0)
|
||||
totalDecode += tasks_added;
|
||||
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_NR_ULSCH_PROCEDURES_RX, 0);
|
||||
}
|
||||
}
|
||||
while (totalDecode > 0) {
|
||||
notifiedFIFO_elt_t *req = pullTpool(&gNB->respDecode, &gNB->threadPool);
|
||||
if (req == NULL)
|
||||
@@ -922,6 +1079,7 @@ int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx)
|
||||
delNotifiedFIFO_elt(req);
|
||||
totalDecode--;
|
||||
}
|
||||
}
|
||||
/* Do ULSCH decoding time measurement only when number of PUSCH is limited to 1
|
||||
* (valid for unitary physical simulators). ULSCH processing loop is then executed
|
||||
* only once, which ensures exactly one start and stop of the ULSCH decoding time
|
||||
|
||||
@@ -287,9 +287,14 @@ void phy_procedures_nrUE_TX(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, n
|
||||
|
||||
start_meas_nr_ue_phy(ue, PHY_PROC_TX);
|
||||
|
||||
int harq_pid = phy_data->ulsch.pusch_pdu.pusch_data.harq_process_id;
|
||||
if (ue->ul_harq_processes[harq_pid].ULstatus == ACTIVE)
|
||||
nr_ue_ulsch_procedures(ue, harq_pid, frame_tx, slot_tx, gNB_id, phy_data, (c16_t **)&txdataF);
|
||||
if (ue->nrLDPC_coding_interface_flag) {
|
||||
nr_ue_ulsch_procedures_slot(ue, frame_tx, slot_tx, phy_data, (c16_t **)&txdataF);
|
||||
} else {
|
||||
int harq_pid = phy_data->ulsch.pusch_pdu.pusch_data.harq_process_id;
|
||||
if (ue->ul_harq_processes[harq_pid].ULstatus == ACTIVE) {
|
||||
nr_ue_ulsch_procedures(ue, harq_pid, frame_tx, slot_tx, gNB_id, phy_data, (c16_t **)&txdataF);
|
||||
}
|
||||
}
|
||||
|
||||
ue_srs_procedures_nr(ue, proc, (c16_t **)&txdataF);
|
||||
|
||||
@@ -679,6 +684,153 @@ static uint32_t compute_csi_rm_unav_res(fapi_nr_dl_config_dlsch_pdu_rel15_t *dls
|
||||
return unav_res;
|
||||
}
|
||||
|
||||
/*! \brief Process the whole DLSCH slot
|
||||
*/
|
||||
static bool nr_ue_dlsch_procedures_slot(PHY_VARS_NR_UE *ue,
|
||||
const UE_nr_rxtx_proc_t *proc,
|
||||
NR_UE_DLSCH_t dlsch[2],
|
||||
int16_t *llr[2]) {
|
||||
if (dlsch[0].active == false) {
|
||||
LOG_E(PHY, "DLSCH should be active when calling this function\n");
|
||||
return true;
|
||||
}
|
||||
|
||||
bool dec = false;
|
||||
int harq_pid = dlsch[0].dlsch_config.harq_process_nbr;
|
||||
int frame_rx = proc->frame_rx;
|
||||
int nr_slot_rx = proc->nr_slot_rx;
|
||||
uint32_t ret = UINT32_MAX;
|
||||
NR_DL_UE_HARQ_t *dl_harq0 = &ue->dl_harq_processes[0][harq_pid];
|
||||
NR_DL_UE_HARQ_t *dl_harq1 = &ue->dl_harq_processes[1][harq_pid];
|
||||
uint16_t dmrs_len = get_num_dmrs(dlsch[0].dlsch_config.dlDmrsSymbPos);
|
||||
nr_downlink_indication_t dl_indication;
|
||||
fapi_nr_rx_indication_t rx_ind = {0};
|
||||
uint16_t number_pdus = 1;
|
||||
|
||||
uint8_t is_cw0_active = dl_harq0->status;
|
||||
uint8_t is_cw1_active = dl_harq1->status;
|
||||
int nb_dlsch = 0;
|
||||
if (is_cw0_active == ACTIVE) nb_dlsch++;
|
||||
if (is_cw1_active == ACTIVE) nb_dlsch++;
|
||||
uint16_t nb_symb_sch = dlsch[0].dlsch_config.number_symbols;
|
||||
uint8_t dmrs_type = dlsch[0].dlsch_config.dmrsConfigType;
|
||||
|
||||
uint8_t nb_re_dmrs;
|
||||
if (dmrs_type == NFAPI_NR_DMRS_TYPE1) {
|
||||
nb_re_dmrs = 6 * dlsch[0].dlsch_config.n_dmrs_cdm_groups;
|
||||
} else {
|
||||
nb_re_dmrs = 4 * dlsch[0].dlsch_config.n_dmrs_cdm_groups;
|
||||
}
|
||||
|
||||
LOG_D(PHY, "AbsSubframe %d.%d Start LDPC Decoder for CW0 [harq_pid %d] ? %d \n", frame_rx % 1024, nr_slot_rx, harq_pid, is_cw0_active);
|
||||
LOG_D(PHY, "AbsSubframe %d.%d Start LDPC Decoder for CW1 [harq_pid %d] ? %d \n", frame_rx % 1024, nr_slot_rx, harq_pid, is_cw1_active);
|
||||
|
||||
// exit dlsch procedures as there are no active dlsch
|
||||
if (is_cw0_active != ACTIVE && is_cw1_active != ACTIVE) {
|
||||
// don't wait anymore
|
||||
LOG_E(NR_PHY, "Internal error nr_ue_dlsch_procedure() called but no active cw on slot %d, harq %d\n", nr_slot_rx, harq_pid);
|
||||
const int ack_nack_slot = (proc->nr_slot_rx + dlsch[0].dlsch_config.k1_feedback) % ue->frame_parms.slots_per_frame;
|
||||
send_dl_done_to_tx_thread(ue->tx_resume_ind_fifo + ack_nack_slot, proc->nr_slot_rx);
|
||||
return false;
|
||||
}
|
||||
|
||||
int G[2];
|
||||
uint8_t DLSCH_ids[nb_dlsch];
|
||||
int pdsch_id = 0;
|
||||
for (uint8_t DLSCH_id = 0; DLSCH_id < 2; DLSCH_id++) {
|
||||
NR_DL_UE_HARQ_t *dl_harq = &ue->dl_harq_processes[DLSCH_id][harq_pid];
|
||||
if (dl_harq->status != ACTIVE) continue;
|
||||
|
||||
DLSCH_ids[pdsch_id++] = DLSCH_id;
|
||||
fapi_nr_dl_config_dlsch_pdu_rel15_t *dlsch_config = &dlsch[DLSCH_id].dlsch_config;
|
||||
uint32_t unav_res = 0;
|
||||
if (dlsch_config->pduBitmap & 0x1) {
|
||||
uint16_t ptrsSymbPos = 0;
|
||||
set_ptrs_symb_idx(&ptrsSymbPos, dlsch_config->number_symbols, dlsch_config->start_symbol, 1 << dlsch_config->PTRSTimeDensity,
|
||||
dlsch_config->dlDmrsSymbPos);
|
||||
int n_ptrs = (dlsch_config->number_rbs + dlsch_config->PTRSFreqDensity - 1) / dlsch_config->PTRSFreqDensity;
|
||||
int ptrsSymbPerSlot = get_ptrs_symbols_in_slot(ptrsSymbPos, dlsch_config->start_symbol, dlsch_config->number_symbols);
|
||||
unav_res = n_ptrs * ptrsSymbPerSlot;
|
||||
}
|
||||
unav_res += compute_csi_rm_unav_res(dlsch_config);
|
||||
G[DLSCH_id] = nr_get_G(dlsch_config->number_rbs, nb_symb_sch, nb_re_dmrs, dmrs_len, unav_res, dlsch_config->qamModOrder, dlsch[DLSCH_id].Nl);
|
||||
|
||||
start_meas_nr_ue_phy(ue, DLSCH_UNSCRAMBLING_STATS);
|
||||
nr_dlsch_unscrambling(llr[DLSCH_id], G[DLSCH_id], 0, dlsch[DLSCH_id].dlsch_config.dlDataScramblingId, dlsch[DLSCH_id].rnti);
|
||||
stop_meas_nr_ue_phy(ue, DLSCH_UNSCRAMBLING_STATS);
|
||||
}
|
||||
|
||||
// create memory to store decoder output
|
||||
int a_segments = MAX_NUM_NR_DLSCH_SEGMENTS_PER_LAYER * NR_MAX_NB_LAYERS; // number of segments to be allocated
|
||||
int num_rb = dlsch[0].dlsch_config.number_rbs;
|
||||
if (num_rb != 273) {
|
||||
a_segments = a_segments * num_rb;
|
||||
a_segments = (a_segments / 273) + 1;
|
||||
}
|
||||
uint32_t dlsch_bytes = a_segments * 1056; // allocated bytes per segment
|
||||
__attribute__((aligned(32))) uint8_t p_b_0[dlsch_bytes];
|
||||
__attribute__((aligned(32))) uint8_t p_b_1[dlsch_bytes];
|
||||
uint8_t *p_b[2] = {p_b_0, p_b_1};
|
||||
|
||||
start_meas_nr_ue_phy(ue, DLSCH_DECODING_STATS);
|
||||
ret = nr_dlsch_decoding_slot(ue, proc, dlsch, llr, p_b, G, nb_dlsch, DLSCH_ids);
|
||||
stop_meas_nr_ue_phy(ue, DLSCH_DECODING_STATS);
|
||||
|
||||
if (ret < ue->max_ldpc_iterations + 1) dec = true;
|
||||
|
||||
int ind_type = -1;
|
||||
switch (dlsch[0].rnti_type) {
|
||||
case TYPE_RA_RNTI_:
|
||||
ind_type = FAPI_NR_RX_PDU_TYPE_RAR;
|
||||
break;
|
||||
|
||||
case TYPE_SI_RNTI_:
|
||||
ind_type = FAPI_NR_RX_PDU_TYPE_SIB;
|
||||
break;
|
||||
|
||||
case TYPE_C_RNTI_:
|
||||
ind_type = FAPI_NR_RX_PDU_TYPE_DLSCH;
|
||||
break;
|
||||
|
||||
default:
|
||||
AssertFatal(true, "Invalid DLSCH type %d\n", dlsch[0].rnti_type);
|
||||
break;
|
||||
}
|
||||
|
||||
nr_fill_dl_indication(&dl_indication, NULL, &rx_ind, proc, ue, NULL);
|
||||
nr_fill_rx_indication(&rx_ind, ind_type, ue, &dlsch[0], NULL, number_pdus, proc, NULL, p_b[0]);
|
||||
|
||||
LOG_D(PHY, "DL PDU length in bits: %d, in bytes: %d \n", dlsch[0].dlsch_config.TBS, dlsch[0].dlsch_config.TBS / 8);
|
||||
if (cpumeas(CPUMEAS_GETSTATE)) {
|
||||
LOG_D(PHY,
|
||||
" --> Unscrambling %5.3f\n",
|
||||
ue->phy_cpu_stats.cpu_time_stats[DLSCH_UNSCRAMBLING_STATS].p_time / (cpuf * 1000.0));
|
||||
LOG_D(PHY,
|
||||
"AbsSubframe %d.%d --> LDPC Decoding %5.3f\n",
|
||||
frame_rx % 1024,
|
||||
nr_slot_rx,
|
||||
ue->phy_cpu_stats.cpu_time_stats[DLSCH_DECODING_STATS].p_time / (cpuf * 1000.0));
|
||||
}
|
||||
|
||||
// send to mac
|
||||
if (ue->if_inst && ue->if_inst->dl_indication) {
|
||||
ue->if_inst->dl_indication(&dl_indication);
|
||||
}
|
||||
|
||||
// DLSCH decoding finished! don't wait anymore in Tx process, we know if we should answer ACK/NACK PUCCH
|
||||
if (dlsch[0].rnti_type == TYPE_C_RNTI_) {
|
||||
const int ack_nack_slot = (proc->nr_slot_rx + dlsch[0].dlsch_config.k1_feedback) % ue->frame_parms.slots_per_frame;
|
||||
send_dl_done_to_tx_thread(ue->tx_resume_ind_fifo + ack_nack_slot, proc->nr_slot_rx);
|
||||
}
|
||||
|
||||
if (ue->phy_sim_dlsch_b && is_cw0_active == ACTIVE)
|
||||
memcpy(ue->phy_sim_dlsch_b, p_b[0], dlsch_bytes);
|
||||
else if (ue->phy_sim_dlsch_b && is_cw1_active == ACTIVE)
|
||||
memcpy(ue->phy_sim_dlsch_b, p_b[1], dlsch_bytes);
|
||||
|
||||
return dec;
|
||||
}
|
||||
|
||||
static bool nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue,
|
||||
const UE_nr_rxtx_proc_t *proc,
|
||||
NR_UE_DLSCH_t dlsch[2],
|
||||
@@ -1135,8 +1287,12 @@ void pdsch_processing(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, nr_phy_
|
||||
|
||||
start_meas_nr_ue_phy(ue, DLSCH_PROCEDURES_STATS);
|
||||
|
||||
if (ret_pdsch >= 0)
|
||||
nr_ue_dlsch_procedures(ue, proc, dlsch, llr, G);
|
||||
if (ret_pdsch >= 0) {
|
||||
if (ue->nrLDPC_coding_interface_flag)
|
||||
nr_ue_dlsch_procedures_slot(ue, proc, dlsch, llr);
|
||||
else
|
||||
nr_ue_dlsch_procedures(ue, proc, dlsch, llr, G);
|
||||
}
|
||||
else {
|
||||
LOG_E(NR_PHY, "Demodulation impossible, internal error\n");
|
||||
send_dl_done_to_tx_thread(
|
||||
|
||||
@@ -380,7 +380,7 @@ int main(int argc, char **argv)
|
||||
RC.gNB[0] = calloc(1, sizeof(PHY_VARS_gNB));
|
||||
gNB = RC.gNB[0];
|
||||
initNamedTpool(gNBthreads, &gNB->threadPool, true, "gNB-tpool");
|
||||
initFloatingCoresTpool(dlsch_threads, &nrUE_params.Tpool, false, "UE-tpool");
|
||||
initFloatingCoresTpool(dlsch_threads, &nrUE_params.Tpool, false, "UE-tpool");
|
||||
//gNB_config = &gNB->gNB_config;
|
||||
frame_parms = &gNB->frame_parms; //to be initialized I suppose (maybe not necessary for PBCH)
|
||||
frame_parms->nb_antennas_tx = n_tx;
|
||||
@@ -430,6 +430,9 @@ int main(int argc, char **argv)
|
||||
|
||||
//nr_init_frame_parms_ue(&UE->frame_parms);
|
||||
//init_nr_ue_transport(UE, 0);
|
||||
|
||||
UE->nrLDPC_coding_interface_flag = gNB->nrLDPC_coding_interface_flag;
|
||||
|
||||
NR_UE_DLSCH_t dlsch_ue[NR_MAX_NB_LAYERS > 4? 2:1] = {0};
|
||||
int num_codeword = NR_MAX_NB_LAYERS > 4? 2:1;
|
||||
nr_ue_dlsch_init(dlsch_ue, num_codeword, 5);
|
||||
@@ -513,7 +516,13 @@ int main(int argc, char **argv)
|
||||
unsigned char output[rel15->rbSize * NR_SYMBOLS_PER_SLOT * NR_NB_SC_PER_RB * 8 * NR_MAX_NB_LAYERS] __attribute__((aligned(32)));
|
||||
bzero(output,rel15->rbSize * NR_SYMBOLS_PER_SLOT * NR_NB_SC_PER_RB * 8 * NR_MAX_NB_LAYERS);
|
||||
if (input_fd == NULL) {
|
||||
nr_dlsch_encoding(gNB, frame, slot, &dlsch->harq_process, frame_parms,output,NULL,NULL,NULL,NULL,NULL,NULL,NULL);
|
||||
if (gNB->nrLDPC_coding_interface_flag) {
|
||||
msgDataTx.num_pdsch_slot = 1;
|
||||
unsigned char *p_output = output;
|
||||
nr_dlsch_encoding_slot(gNB, &msgDataTx, frame, slot, frame_parms, &p_output, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
|
||||
} else {
|
||||
nr_dlsch_encoding(gNB, frame, slot, &dlsch->harq_process, frame_parms, output, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
for (SNR = snr0; SNR < snr1; SNR += snr_step) {
|
||||
@@ -569,20 +578,35 @@ int main(int argc, char **argv)
|
||||
}
|
||||
uint32_t dlsch_bytes = a_segments*1056; // allocated bytes per segment
|
||||
__attribute__ ((aligned(32))) uint8_t b[dlsch_bytes];
|
||||
ret = nr_dlsch_decoding(UE,
|
||||
&proc,
|
||||
0,
|
||||
channel_output_fixed,
|
||||
&UE->frame_parms,
|
||||
dlsch0_ue,
|
||||
harq_process,
|
||||
frame,
|
||||
nb_symb_sch,
|
||||
slot,
|
||||
harq_pid,
|
||||
dlsch_bytes,
|
||||
b,
|
||||
available_bits);
|
||||
if (gNB->nrLDPC_coding_interface_flag) {
|
||||
uint8_t DLSCH_ids[1] = {0};
|
||||
short *p_channel_output_fixed = channel_output_fixed;
|
||||
uint8_t *p_b = b;
|
||||
int available_bits_array[1] = { available_bits };
|
||||
ret = nr_dlsch_decoding_slot(UE,
|
||||
&proc,
|
||||
dlsch0_ue,
|
||||
&p_channel_output_fixed,
|
||||
&p_b,
|
||||
available_bits_array,
|
||||
1,
|
||||
DLSCH_ids);
|
||||
} else {
|
||||
ret = nr_dlsch_decoding(UE,
|
||||
&proc,
|
||||
0,
|
||||
channel_output_fixed,
|
||||
&UE->frame_parms,
|
||||
dlsch0_ue,
|
||||
harq_process,
|
||||
frame,
|
||||
nb_symb_sch,
|
||||
slot,
|
||||
harq_pid,
|
||||
dlsch_bytes,
|
||||
b,
|
||||
available_bits);
|
||||
}
|
||||
|
||||
vcd_signal_dumper_dump_function_by_name(VCD_SIGNAL_DUMPER_FUNCTIONS_DLSCH_DECODING0, VCD_FUNCTION_OUT);
|
||||
|
||||
|
||||
@@ -38,6 +38,7 @@
|
||||
#include "PHY/defs_nr_UE.h"
|
||||
#include "PHY/phy_vars_nr_ue.h"
|
||||
#include "PHY/types.h"
|
||||
#include "PHY/CODING/nrLDPC_coding_interface.h"
|
||||
#include "PHY/INIT/nr_phy_init.h"
|
||||
#include "PHY/MODULATION/modulation_eNB.h"
|
||||
#include "PHY/MODULATION/nr_modulation.h"
|
||||
@@ -842,6 +843,8 @@ int main(int argc, char **argv)
|
||||
|
||||
init_nr_ue_transport(UE);
|
||||
|
||||
UE->nrLDPC_coding_interface_flag = gNB->nrLDPC_coding_interface_flag;
|
||||
|
||||
nr_l2_init_ue(1);
|
||||
UE_mac = get_mac_inst(0);
|
||||
ue_init_config_request(UE_mac, mu);
|
||||
@@ -1291,6 +1294,9 @@ int main(int argc, char **argv)
|
||||
if (gNB->ldpc_offload_flag)
|
||||
free_LDPClib(&ldpc_interface_offload);
|
||||
|
||||
if (gNB->nrLDPC_coding_interface_flag)
|
||||
free_nrLDPC_coding_interface(&nrLDPC_coding_interface);
|
||||
|
||||
if (output_fd)
|
||||
fclose(output_fd);
|
||||
|
||||
|
||||
@@ -449,6 +449,12 @@ int main(int argc, char **argv)
|
||||
|
||||
nr_init_ul_harq_processes(UE->ul_harq_processes, NR_MAX_ULSCH_HARQ_PROCESSES, UE->frame_parms.N_RB_UL, UE->frame_parms.nb_antennas_tx);
|
||||
|
||||
UE->nrLDPC_coding_interface_flag = gNB->nrLDPC_coding_interface_flag;
|
||||
|
||||
if (UE->nrLDPC_coding_interface_flag) {
|
||||
initFloatingCoresTpool(1, &nrUE_params.Tpool, false, "UE-tpool");
|
||||
}
|
||||
|
||||
unsigned char harq_pid = 0;
|
||||
unsigned int TBS = 8424;
|
||||
unsigned int available_bits;
|
||||
@@ -531,7 +537,12 @@ int main(int argc, char **argv)
|
||||
unsigned int G = available_bits;
|
||||
|
||||
if (input_fd == NULL) {
|
||||
nr_ulsch_encoding(UE, ulsch_ue, frame_parms, harq_pid, TBS>>3, G);
|
||||
if (UE->nrLDPC_coding_interface_flag) {
|
||||
uint8_t ULSCH_ids[] = {0};
|
||||
nr_ulsch_encoding_slot(UE, ulsch_ue, 0, 0, &G, 1, ULSCH_ids);
|
||||
} else {
|
||||
nr_ulsch_encoding(UE, ulsch_ue, frame_parms, harq_pid, TBS>>3, G);
|
||||
}
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
@@ -595,18 +606,26 @@ int main(int argc, char **argv)
|
||||
exit(-1);
|
||||
#endif
|
||||
|
||||
int nbDecode = nr_ulsch_decoding(gNB, UE_id, channel_output_fixed, frame_parms, rel15_ul, frame, subframe, harq_pid, G);
|
||||
int nb_ok = 0;
|
||||
if (nbDecode > 0)
|
||||
while (nbDecode > 0) {
|
||||
notifiedFIFO_elt_t *req = pullTpool(&gNB->respDecode, &gNB->threadPool);
|
||||
ret = nr_postDecode_sim(gNB, req, &nb_ok);
|
||||
delNotifiedFIFO_elt(req);
|
||||
nbDecode--;
|
||||
}
|
||||
if (gNB->nrLDPC_coding_interface_flag) {
|
||||
nr_ulsch_decoding_slot(gNB, frame_parms, frame, subframe, &G, &UE_id, 1);
|
||||
bool crc_valid = check_crc(harq_process_gNB->b, lenWithCrc(1, (harq_process_gNB->TBS) << 3), crcType(1, (harq_process_gNB->TBS) << 3));
|
||||
if (!crc_valid) {
|
||||
n_errors++;
|
||||
}
|
||||
} else {
|
||||
int nbDecode = nr_ulsch_decoding(gNB, UE_id, channel_output_fixed, frame_parms, rel15_ul, frame, subframe, harq_pid, G);
|
||||
int nb_ok = 0;
|
||||
if (nbDecode > 0)
|
||||
while (nbDecode > 0) {
|
||||
notifiedFIFO_elt_t *req = pullTpool(&gNB->respDecode, &gNB->threadPool);
|
||||
ret = nr_postDecode_sim(gNB, req, &nb_ok);
|
||||
delNotifiedFIFO_elt(req);
|
||||
nbDecode--;
|
||||
}
|
||||
|
||||
if (ret)
|
||||
n_errors++;
|
||||
if (ret)
|
||||
n_errors++;
|
||||
}
|
||||
}
|
||||
|
||||
printf("*****************************************\n");
|
||||
|
||||
@@ -35,6 +35,7 @@
|
||||
#include "PHY/defs_nr_UE.h"
|
||||
#include "PHY/phy_vars_nr_ue.h"
|
||||
#include "PHY/types.h"
|
||||
#include "PHY/CODING/nrLDPC_coding_interface.h"
|
||||
#include "PHY/INIT/nr_phy_init.h"
|
||||
#include "PHY/MODULATION/modulation_UE.h"
|
||||
#include "PHY/MODULATION/nr_modulation.h"
|
||||
@@ -703,6 +704,8 @@ int main(int argc, char *argv[])
|
||||
|
||||
init_nr_ue_transport(UE);
|
||||
|
||||
UE->nrLDPC_coding_interface_flag = gNB->nrLDPC_coding_interface_flag;
|
||||
|
||||
//Configure UE
|
||||
nr_l2_init_ue(1);
|
||||
NR_UE_MAC_INST_t* UE_mac = get_mac_inst(0);
|
||||
@@ -717,6 +720,10 @@ int main(int argc, char *argv[])
|
||||
|
||||
UE_mac->if_module = nr_ue_if_module_init(0);
|
||||
|
||||
if (UE->nrLDPC_coding_interface_flag) {
|
||||
initFloatingCoresTpool(threadCnt, &nrUE_params.Tpool, false, "UE-tpool");
|
||||
}
|
||||
|
||||
nr_ue_phy_config_request(&UE_mac->phy_config);
|
||||
|
||||
unsigned char harq_pid = 0;
|
||||
@@ -1619,6 +1626,9 @@ int main(int argc, char *argv[])
|
||||
if (gNB->ldpc_offload_flag)
|
||||
free_LDPClib(&ldpc_interface_offload);
|
||||
|
||||
if (gNB->nrLDPC_coding_interface_flag)
|
||||
free_nrLDPC_coding_interface(&nrLDPC_coding_interface);
|
||||
|
||||
if (output_fd)
|
||||
fclose(output_fd);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user