mirror of
https://gitlab.eurecom.fr/oai/openairinterface5g.git
synced 2026-07-13 20:50:28 +00:00
Compare commits
27 Commits
pucch2_deb
...
t2-offload
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
23a9634ea5 | ||
|
|
1dab8f9770 | ||
|
|
a6616fec71 | ||
|
|
5867d4db39 | ||
|
|
b47fcfc8b9 | ||
|
|
630dc0295a | ||
|
|
585044c9f5 | ||
|
|
59f640a9c4 | ||
|
|
5ba6411d88 | ||
|
|
784bf75e4c | ||
|
|
c8d75cfde2 | ||
|
|
bb55895865 | ||
|
|
d53af9c632 | ||
|
|
73cb5f4c38 | ||
|
|
528bf3be84 | ||
|
|
e248c3508c | ||
|
|
e2a372e88e | ||
|
|
a3b4d69f8b | ||
|
|
3e750fe9f6 | ||
|
|
60ed140a3e | ||
|
|
942b43a763 | ||
|
|
f95d778f71 | ||
|
|
148052dd5a | ||
|
|
a4c00c4d9d | ||
|
|
6ddfc64e59 | ||
|
|
94fe7808da | ||
|
|
a8763de019 |
@@ -483,20 +483,21 @@ target_link_libraries(shlib_loader PRIVATE CONFIG_LIB)
|
||||
|
||||
##########################################################
|
||||
|
||||
# LDPC offload library
|
||||
# LDPC offload library - AMD T2 Accelerator Card
|
||||
##########################################################
|
||||
|
||||
add_boolean_option(ENABLE_LDPC_T1 OFF "Build support for LDPC Offload to T1 library" OFF)
|
||||
if (ENABLE_LDPC_T1)
|
||||
pkg_check_modules(LIBDPDK_T1 REQUIRED libdpdk=20.05.0)
|
||||
find_library(T1 NAMES rte_pmd_hpac_sdfec_pmd REQUIRED)
|
||||
if (NOT T1)
|
||||
message(FATAL_ERROR "Library rte_pmd_hpac_sdfec_pmd for T1 offload not found")
|
||||
add_boolean_option(ENABLE_LDPC_T2 OFF "Build support for LDPC Offload to T2 library" OFF)
|
||||
set(ENV{PKG_CONFIG_PATH} "$ENV{PKG_CONFIG_PATH}:/usr/local/lib/x86_64-linux-gnu/pkgconfig")
|
||||
if (ENABLE_LDPC_T2)
|
||||
pkg_check_modules(LIBDPDK_OFFLOAD REQUIRED libdpdk=20.11.7)
|
||||
find_library(PMD_T2 NAMES rte_baseband_accl_ldpc HINTS "/opt/dpdk-t2/lib/x86_64-linux-gnu/")
|
||||
if (NOT PMD_T2)
|
||||
message(FATAL_ERROR "could not find PMD T2")
|
||||
endif()
|
||||
add_library(ldpc_t1 MODULE ${OPENAIR1_DIR}/PHY/CODING/nrLDPC_decoder/nrLDPC_decoder_offload.c)
|
||||
set_target_properties(ldpc_t1 PROPERTIES COMPILE_FLAGS "-DALLOW_EXPERIMENTAL_API")
|
||||
target_compile_options(ldpc_t1 PRIVATE ${LIBDPDK_T1_CFLAGS})
|
||||
target_link_libraries(ldpc_t1 ${LIBDPDK_T1_LDFLAGS} ${T1})
|
||||
message(STATUS "T2 build: use ${PMD_T2}")
|
||||
add_library(ldpc_t2 MODULE ${OPENAIR1_DIR}/PHY/CODING/nrLDPC_decoder/nrLDPC_decoder_offload.c)
|
||||
set_target_properties(ldpc_t2 PROPERTIES COMPILE_FLAGS "-DALLOW_EXPERIMENTAL_API -DOFFLOAD_T2")
|
||||
target_link_libraries(ldpc_t2 ${LIBDPDK_OFFLOAD_LDFLAGS} ${PMD_T2})
|
||||
endif()
|
||||
|
||||
##########################################################
|
||||
@@ -808,19 +809,30 @@ set(PHY_LDPC_ORIG_SRC
|
||||
${OPENAIR1_DIR}/PHY/CODING/nrLDPC_decoder/nrLDPC_decoder.c
|
||||
${OPENAIR1_DIR}/PHY/CODING/nrLDPC_encoder/ldpc_encoder.c
|
||||
)
|
||||
add_library(ldpc_orig MODULE ${PHY_LDPC_ORIG_SRC} )
|
||||
target_link_libraries(ldpc_orig PRIVATE ldpc_gen_HEADERS)
|
||||
|
||||
set(PHY_LDPC_OPTIM_SRC
|
||||
${OPENAIR1_DIR}/PHY/CODING/nrLDPC_decoder/nrLDPC_decoder.c
|
||||
${OPENAIR1_DIR}/PHY/CODING/nrLDPC_encoder/ldpc_encoder_optim.c
|
||||
)
|
||||
)
|
||||
add_library(ldpc_optim MODULE ${PHY_LDPC_OPTIM_SRC} )
|
||||
target_link_libraries(ldpc_optim PRIVATE ldpc_gen_HEADERS)
|
||||
|
||||
set(PHY_LDPC_OPTIM8SEG_SRC
|
||||
${OPENAIR1_DIR}/PHY/CODING/nrLDPC_decoder/nrLDPC_decoder.c
|
||||
${OPENAIR1_DIR}/PHY/CODING/nrLDPC_encoder/ldpc_encoder_optim8seg.c
|
||||
)
|
||||
add_library(ldpc_optim8seg MODULE ${PHY_LDPC_OPTIM8SEG_SRC} )
|
||||
target_link_libraries(ldpc_optim8seg PRIVATE ldpc_gen_HEADERS)
|
||||
|
||||
set(PHY_LDPC_OPTIM8SEGMULTI_SRC
|
||||
${OPENAIR1_DIR}/PHY/CODING/nrLDPC_decoder/nrLDPC_decoder.c
|
||||
${OPENAIR1_DIR}/PHY/CODING/nrLDPC_encoder/ldpc_encoder_optim8segmulti.c
|
||||
)
|
||||
)
|
||||
add_library(ldpc MODULE ${PHY_LDPC_OPTIM8SEGMULTI_SRC} )
|
||||
target_link_libraries(ldpc PRIVATE ldpc_gen_HEADERS)
|
||||
|
||||
set(PHY_LDPC_CUDA_SRC
|
||||
${OPENAIR1_DIR}/PHY/CODING/nrLDPC_decoder_LYC/nrLDPC_decoder_LYC.cu
|
||||
${OPENAIR1_DIR}/PHY/CODING/nrLDPC_encoder/ldpc_encoder_optim8segmulti.c
|
||||
@@ -834,21 +846,13 @@ add_custom_target( nrLDPC_decoder_kernels_CL
|
||||
COMMAND gcc ${OPENAIR1_DIR}/PHY/CODING/nrLDPC_decoder/nrLDPC_decoder_CL.c -dD -DNRLDPC_KERNEL_SOURCE -E -o ${CMAKE_CURRENT_BINARY_DIR}/nrLDPC_decoder_kernels_CL.clc
|
||||
SOURCES ${OPENAIR1_DIR}/PHY/CODING/nrLDPC_decoder/nrLDPC_decoder_CL.c
|
||||
)
|
||||
|
||||
set(PHY_NR_CODINGIF
|
||||
${OPENAIR1_DIR}/PHY/CODING/nrLDPC_load.c;
|
||||
)
|
||||
|
||||
add_library(ldpc_orig MODULE ${PHY_LDPC_ORIG_SRC} )
|
||||
target_link_libraries(ldpc_orig PRIVATE ldpc_gen_HEADERS)
|
||||
add_library(ldpc_optim MODULE ${PHY_LDPC_OPTIM_SRC} )
|
||||
target_link_libraries(ldpc_optim PRIVATE ldpc_gen_HEADERS)
|
||||
add_library(ldpc_optim8seg MODULE ${PHY_LDPC_OPTIM8SEG_SRC} )
|
||||
target_link_libraries(ldpc_optim8seg PRIVATE ldpc_gen_HEADERS)
|
||||
add_library(ldpc_cl MODULE ${PHY_LDPC_CL_SRC} )
|
||||
target_link_libraries(ldpc_cl OpenCL)
|
||||
add_dependencies(ldpc_cl nrLDPC_decoder_kernels_CL)
|
||||
|
||||
set(PHY_NR_CODINGIF
|
||||
${OPENAIR1_DIR}/PHY/CODING/nrLDPC_load.c
|
||||
)
|
||||
|
||||
##############################################
|
||||
# Base CUDA setting
|
||||
@@ -866,13 +870,6 @@ if (ENABLE_LDPC_CUDA)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
add_library(ldpc MODULE ${PHY_LDPC_OPTIM8SEGMULTI_SRC} )
|
||||
target_link_libraries(ldpc PRIVATE ldpc_gen_HEADERS)
|
||||
|
||||
add_library(ldpc_parityCheck MODULE ${PHY_LDPC_OPTIM8SEGMULTI_SRC} )
|
||||
target_compile_definitions(ldpc_parityCheck PUBLIC NR_LDPC_ENABLE_PARITY_CHECK)
|
||||
target_link_libraries(ldpc_parityCheck PRIVATE ldpc_gen_HEADERS)
|
||||
|
||||
add_library(coding MODULE ${PHY_TURBOSRC} )
|
||||
|
||||
add_library(dfts MODULE ${OPENAIR1_DIR}/PHY/TOOLS/oai_dfts.c ${OPENAIR1_DIR}/PHY/TOOLS/oai_dfts_neon.c)
|
||||
@@ -2085,6 +2082,10 @@ if (ENABLE_LDPC_T1)
|
||||
add_dependencies(nr-softmodem ldpc_t1)
|
||||
endif()
|
||||
|
||||
if (ENABLE_LDPC_T2)
|
||||
add_dependencies(nr-softmodem ldpc_t2)
|
||||
endif()
|
||||
|
||||
# force the generation of ASN.1 so that we don't need to wait during the build
|
||||
target_link_libraries(nr-softmodem PRIVATE
|
||||
asn1_lte_rrc asn1_nr_rrc asn1_s1ap asn1_ngap asn1_m2ap asn1_m3ap asn1_x2ap asn1_f1ap asn1_lpp)
|
||||
@@ -2203,12 +2204,12 @@ add_executable(ldpctest
|
||||
${OPENAIR1_DIR}/PHY/CODING/TESTBENCH/ldpctest.c
|
||||
)
|
||||
|
||||
add_dependencies( ldpctest ldpc_orig ldpc_optim ldpc_optim8seg ldpc ldpc_parityCheck)
|
||||
add_dependencies(ldpctest ldpc_orig ldpc_optim ldpc_optim8seg ldpc)
|
||||
if (ENABLE_LDPC_CUDA)
|
||||
add_dependencies(ldpctest ldpc_cuda)
|
||||
endif()
|
||||
target_link_libraries(ldpctest PRIVATE
|
||||
-Wl,--start-group UTIL SIMU PHY_NR PHY_COMMON PHY_NR_COMMON -Wl,--end-group
|
||||
-Wl,--start-group UTIL SIMU PHY_COMMON PHY_NR_COMMON -Wl,--end-group
|
||||
m pthread dl shlib_loader ${T_LIB}
|
||||
)
|
||||
|
||||
@@ -2302,6 +2303,10 @@ if (ENABLE_LDPC_T1)
|
||||
add_dependencies(nr_ulsim ldpc_t1)
|
||||
endif()
|
||||
|
||||
if (ENABLE_LDPC_T2)
|
||||
add_dependencies(nr_ulsim ldpc_t2)
|
||||
endif()
|
||||
|
||||
target_link_libraries(nr_ulsim PRIVATE
|
||||
-Wl,--start-group UTIL SIMU SIMU_ETH PHY_COMMON PHY_NR_COMMON PHY_NR PHY_NR_UE SCHED_NR_LIB SCHED_NR_UE_LIB MAC_UE_NR MAC_NR_COMMON nr_rrc CONFIG_LIB L2_NR HASHTABLE x2ap SECURITY ngap -lz -Wl,--end-group
|
||||
m pthread ${T_LIB} ITTI dl shlib_loader
|
||||
|
||||
@@ -46,7 +46,7 @@ BUILD_DOXYGEN=0
|
||||
DISABLE_HARDWARE_DEPENDENCY="False"
|
||||
CMAKE_BUILD_TYPE="RelWithDebInfo"
|
||||
CMAKE_CMD="$CMAKE"
|
||||
OPTIONAL_LIBRARIES="telnetsrv enbscope uescope nrscope nrqtscope ldpc_cuda ldpc_t1 websrv oai_iqplayer"
|
||||
OPTIONAL_LIBRARIES="telnetsrv enbscope uescope nrscope nrqtscope ldpc_cuda ldpc_t1 ldpc_t2 websrv oai_iqplayer"
|
||||
TARGET_LIST=""
|
||||
|
||||
function print_help() {
|
||||
|
||||
@@ -183,7 +183,8 @@ Some libraries have further dependencies and might not build on every system:
|
||||
- `enbscope`, `uescope`, `nrscope`: libforms/X
|
||||
- `nrqtscope`: Qt5
|
||||
- `ldpc_cuda`: CUDA
|
||||
- `ldpc_t1`: DPDK and VVDN T1
|
||||
- `ldpc_t1`: lib for LDPC decoding offload to AMD Xilinx T1
|
||||
- `ldpc_t2`: lib for LDPC encoding/decoding offload to AMD Xilinx T2
|
||||
- `websrv`: npm and others
|
||||
|
||||
# Running `cmake` directly
|
||||
|
||||
81
doc/LDPC_OFFLOAD_SETUP.md
Normal file
81
doc/LDPC_OFFLOAD_SETUP.md
Normal file
@@ -0,0 +1,81 @@
|
||||
<table style="border-collapse: collapse; border: none;">
|
||||
<tr style="border-collapse: collapse; border: none;">
|
||||
<td style="border-collapse: collapse; border: none;">
|
||||
<a href="http://www.openairinterface.org/">
|
||||
<img src="./images/oai_final_logo.png" alt="" border=3 height=50 width=150>
|
||||
</img>
|
||||
</a>
|
||||
</td>
|
||||
<td style="border-collapse: collapse; border: none; vertical-align: center;">
|
||||
<b><font size = "5">OAI T1/T2 LDPC offload</font></b>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
**Table of Contents**
|
||||
|
||||
[[_TOC_]]
|
||||
|
||||
This documentation aims to provide a tutorial for AMD Xilinx T2 Telco card integration into OAI and its usage.
|
||||
## Prerequisites
|
||||
Offload of the channel decoding was tested with the T2 card in following setup:
|
||||
|
||||
**AMD Xilinx T2 card**
|
||||
- bitstream image and PMD driver provided by AccelerComm
|
||||
- DPDK 20.11.3 with patch from Accelercomm (also tested with DPDK 20.11.7
|
||||
version)
|
||||
- tested on RHEL7.9, RHEL9.2, Ubuntu 20.04, Ubuntu 22.04
|
||||
|
||||
|
||||
## DPDK setup
|
||||
|
||||
- check the presence of the card on the host
|
||||
- `lspci | grep "Xilinx"`
|
||||
- binding of the device with igb_uio driver
|
||||
- `./dpdk-devbind.py -b igb_uio <address of the PCI of the card>`
|
||||
- hugepages setup (10 x 1GB hugepages)
|
||||
- `./dpdk-hugepages.py -p 1G --setup 10G`
|
||||
|
||||
*Note: Commands to run from dpdk/usertool folder*
|
||||
|
||||
## Compilation
|
||||
Deployment of the OAI is precisely described in the following tutorials.
|
||||
- [BUILD](https://gitlab.eurecom.fr/oai/openairinterface5g/-/blob/develop/doc/BUILD.md)
|
||||
- [NR_SA_CN5G_gNB_USRP_COTS_UE_Tutorial](https://gitlab.eurecom.fr/oai/openairinterface5g/-/blob/develop/doc/NR_SA_Tutorial_COTS_UE.md)
|
||||
|
||||
Shared object file *libldpc_t2.so* is created during the compilation. This objects is conditionally compiled. Selection of the library to compile is done using *--build-lib ldpc_t2*. Sample command to build OAI with support for LDPC offload to T2 card is:
|
||||
|
||||
`./build_oai -P --gNB -w USRP --build-lib "ldpc_t2" --ninja`
|
||||
|
||||
*Required DPDK version has to be installed on the host, prior to the build of OAI*
|
||||
|
||||
## nr_ulsim test
|
||||
Offload of the channel decoding is in nr_ulsim specified by *-o* option followed by the version of the card. Example command for running nr_ulsim with offload to the T2 card:
|
||||
|
||||
`./nr_ulsim -n100 -s20 -m20 -r273 -o _t2`
|
||||
|
||||
|
||||
### LDPC encoding/decoding with CPU/GPU
|
||||
Available LDPC implementations and loading particular libraries is well described in *openair1/PHY/CODING/DOC/LDPCImplementation.md*. Default library for LDPC processing is called `libldpc.so`. Sample command for running nr-softmodem with selected library (in this case we want to replace `libldpc.so` by `libldpc_optim.so` library):
|
||||
`./nr-softmodem -O config_file.conf --sa --loader.ldpc.shlibversion _optim`
|
||||
Available options:
|
||||
- --loader.ldpc.shlibversion _optim8seg
|
||||
- --loader.ldpc.shlibversion _optim
|
||||
- --loader.ldpc.shlibversion _orig
|
||||
- --loader.ldpc.shlibversion _cuda
|
||||
- --loader.ldpc.shlibversion _cl
|
||||
|
||||
|
||||
### LDPC decoding offload to AMD Xilinx T1 and T2 accelerator cards
|
||||
Library for the LDPC decoder is selected by *--ldpc.shlibversion* option, followed by the version of the card - *_t2*. Sample command for running nr_ulsim with offload to the T2 card:
|
||||
|
||||
`./nr-softmodem -O config_file.conf --sa --ldpc.shlibversion _t2`
|
||||
|
||||
## Limitations
|
||||
### AMD Xilinx T1 card
|
||||
- offload of the LDPC decoding implemented only for MCS > 9, decoding of the smaller TBs on the T1 card leads to blocking of the card
|
||||
- HARQ is not functional with LDPC decoding offload to the T1 card (restricted in the code to avoid blocking of the card)
|
||||
- LDPC encoding offload not implemented for the T1 card
|
||||
- not supported in current develop branch, please checkout to *2023.w41*
|
||||
### AMD Xilinx T2 card
|
||||
- offload of the LDPC encoding implemented only for MCS > 9, encoding in case of MCS < 9 leads to the blocking of the card, there is still an ongoing work to fix this issue
|
||||
@@ -427,6 +427,9 @@ static void get_channel_model_mode() {
|
||||
|
||||
int NB_UE_INST = 1;
|
||||
|
||||
// A global var to reduce the changes size
|
||||
ldpc_interface_t ldpc_interface = {0}, ldpc_interface_offload = {0};
|
||||
|
||||
int main( int argc, char **argv ) {
|
||||
int set_exe_prio = 1;
|
||||
if (checkIfFedoraDistribution())
|
||||
@@ -466,8 +469,8 @@ int main( int argc, char **argv ) {
|
||||
itti_init(TASK_MAX, tasks_info);
|
||||
|
||||
init_opt() ;
|
||||
load_nrLDPClib(NULL);
|
||||
|
||||
load_LDPClib(NULL, &ldpc_interface);
|
||||
|
||||
if (ouput_vcd) {
|
||||
vcd_signal_dumper_init("/tmp/openair_dump_nrUE.vcd");
|
||||
}
|
||||
|
||||
@@ -42,6 +42,7 @@
|
||||
|
||||
#define NR_LDPC_PROFILER_DETAIL
|
||||
#define NR_LDPC_ENABLE_PARITY_CHECK
|
||||
ldpc_interface_t ldpc_orig, ldpc_toCompare;
|
||||
|
||||
// 4-bit quantizer
|
||||
int8_t quantize4bit(double D,double x)
|
||||
@@ -77,49 +78,48 @@ int8_t quantize8bit(double D,double x)
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
double n_iter_mean[400];
|
||||
double n_iter_std[400];
|
||||
int n_iter_max[400];
|
||||
double snr[400];
|
||||
double ber[400];
|
||||
double bler[400];
|
||||
double n_iter_mean;
|
||||
double n_iter_std;
|
||||
int n_iter_max;
|
||||
double snr;
|
||||
double ber;
|
||||
double bler;
|
||||
} n_iter_stats_t;
|
||||
|
||||
nrLDPC_encoderfunc_t encoder_orig;
|
||||
typedef struct {
|
||||
unsigned int errors;
|
||||
unsigned int errors_bit;
|
||||
double errors_bit_uncoded;
|
||||
unsigned int crc_misses;
|
||||
time_stats_t time_optim;
|
||||
time_stats_t time_decoder;
|
||||
n_iter_stats_t dec_iter;
|
||||
} one_measurement_t;
|
||||
|
||||
short lift_size[51]= {2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,20,22,24,26,28,30,32,36,40,44,48,52,56,60,64,72,80,88,96,104,112,120,128,144,160,176,192,208,224,240,256,288,320,352,384};
|
||||
|
||||
int test_ldpc(short max_iterations,
|
||||
int nom_rate,
|
||||
int denom_rate,
|
||||
double SNR,
|
||||
uint8_t qbits,
|
||||
short block_length,
|
||||
unsigned int ntrials,
|
||||
int n_segments,
|
||||
unsigned int *errors,
|
||||
unsigned int *errors_bit,
|
||||
double *errors_bit_uncoded,
|
||||
unsigned int *crc_misses,
|
||||
time_stats_t *time_optim,
|
||||
time_stats_t *time_decoder,
|
||||
n_iter_stats_t *dec_iter,
|
||||
int nsnr)
|
||||
one_measurement_t test_ldpc(short max_iterations,
|
||||
int nom_rate,
|
||||
int denom_rate,
|
||||
double SNR,
|
||||
unsigned char qbits,
|
||||
short block_length,
|
||||
unsigned int ntrials,
|
||||
int n_segments)
|
||||
{
|
||||
one_measurement_t ret = {0};
|
||||
reset_meas(&ret.time_optim);
|
||||
reset_meas(&ret.time_decoder);
|
||||
//clock initiate
|
||||
//time_stats_t time,time_optim,tinput,tprep,tparity,toutput, time_decoder;
|
||||
time_stats_t time, tinput,tprep,tparity,toutput;
|
||||
double n_iter_mean = 0;
|
||||
double n_iter_std = 0;
|
||||
int n_iter_max = 0;
|
||||
unsigned int segment_bler = 0;
|
||||
|
||||
double sigma;
|
||||
sigma = 1.0/sqrt(2*SNR);
|
||||
opp_enabled=1;
|
||||
//short test_input[block_length];
|
||||
uint8_t *test_input[MAX_NUM_NR_DLSCH_SEGMENTS_PER_LAYER*NR_MAX_NB_LAYERS]={NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL};;
|
||||
//short *c; //padded codeword
|
||||
uint8_t *test_input[MAX_NUM_NR_DLSCH_SEGMENTS_PER_LAYER * NR_MAX_NB_LAYERS];
|
||||
uint8_t estimated_output[MAX_NUM_DLSCH_SEGMENTS][block_length];
|
||||
memset(estimated_output, 0, sizeof(estimated_output));
|
||||
uint8_t *channel_input[MAX_NUM_DLSCH_SEGMENTS];
|
||||
@@ -128,11 +128,8 @@ int test_ldpc(short max_iterations,
|
||||
double modulated_input[MAX_NUM_DLSCH_SEGMENTS][68 * 384] = { 0 };
|
||||
int8_t channel_output_fixed[MAX_NUM_DLSCH_SEGMENTS][68 * 384] = { 0 };
|
||||
short BG=0,nrows=0;//,ncols;
|
||||
int no_punctured_columns,removed_bit;
|
||||
int i1,Zc,Kb=0;
|
||||
int i1, Kb = 0;
|
||||
int R_ind = 0;
|
||||
//Table of possible lifting sizes
|
||||
//short lift_size[51]= {2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,20,22,24,26,28,30,32,36,40,44,48,52,56,60,64,72,80,88,96,104,112,120,128,144,160,176,192,208,224,240,256,288,320,352,384};
|
||||
//int n_segments=1;
|
||||
int code_rate_vec[8] = {15, 13, 25, 12, 23, 34, 56, 89};
|
||||
//double code_rate_actual_vec[8] = {0.2, 0.33333, 0.4, 0.5, 0.66667, 0.73333, 0.81481, 0.88};
|
||||
@@ -143,24 +140,17 @@ int test_ldpc(short max_iterations,
|
||||
|
||||
int32_t n_iter = 0;
|
||||
|
||||
*errors=0;
|
||||
*errors_bit=0;
|
||||
*errors_bit_uncoded=0;
|
||||
*crc_misses=0;
|
||||
|
||||
// generate input block
|
||||
for(int j=0;j<MAX_NUM_DLSCH_SEGMENTS;j++) {
|
||||
test_input[j]=(uint8_t *)malloc16(sizeof(uint8_t) * block_length/8);
|
||||
memset(test_input[j], 0, sizeof(uint8_t) * block_length / 8);
|
||||
channel_input[j] = (uint8_t *)malloc16(sizeof(uint8_t) * 68*384);
|
||||
memset(channel_input[j], 0, sizeof(uint8_t) * 68 * 384);
|
||||
channel_input_optim[j] = (uint8_t *)malloc16(sizeof(uint8_t) * 68*384);
|
||||
memset(channel_input_optim[j], 0, sizeof(uint8_t) * 68 * 384);
|
||||
test_input[j] = malloc16(block_length / 8);
|
||||
memset(test_input[j], 0, block_length / 8);
|
||||
channel_input[j] = malloc16(68 * 384);
|
||||
memset(channel_input[j], 0, 68 * 384);
|
||||
channel_input_optim[j] = malloc16(68 * 384);
|
||||
memset(channel_input_optim[j], 0, 68 * 384);
|
||||
}
|
||||
|
||||
reset_meas(&time);
|
||||
reset_meas(time_optim);
|
||||
reset_meas(time_decoder);
|
||||
reset_meas(&tinput);
|
||||
reset_meas(&tprep);
|
||||
reset_meas(&tparity);
|
||||
@@ -178,243 +168,220 @@ int test_ldpc(short max_iterations,
|
||||
reset_meas(&decoder_profiler.llr2bit);
|
||||
//reset_meas(&decoder_profiler.total);
|
||||
|
||||
for (int j=0;j<MAX_NUM_DLSCH_SEGMENTS;j++) {
|
||||
for (int i=0; i<block_length/8; i++) {
|
||||
test_input[j][i]=(uint8_t) rand();
|
||||
//test_input[j][i]=j%256;
|
||||
//test_input[j][i]=252;
|
||||
}
|
||||
}
|
||||
// Fill a input packet with random values
|
||||
for (int j = 0; j < MAX_NUM_DLSCH_SEGMENTS; j++)
|
||||
for (int i = 0; i < block_length / 8; i++)
|
||||
test_input[j][i] = (uint8_t)rand();
|
||||
|
||||
//determine number of bits in codeword
|
||||
if (block_length>3840)
|
||||
{
|
||||
if (block_length > 3840) {
|
||||
BG = 1;
|
||||
Kb = 22;
|
||||
nrows = 46; //parity check bits
|
||||
//ncols=22; //info bits
|
||||
}
|
||||
else if (block_length<=3840)
|
||||
{
|
||||
nrows = 46; // parity check bits
|
||||
// ncols=22; //info bits
|
||||
} else {
|
||||
BG = 2;
|
||||
nrows = 42; //parity check bits
|
||||
//ncols=10; // info bits
|
||||
|
||||
if (block_length>640)
|
||||
nrows = 42; // parity check bits
|
||||
// ncols=10; // info bits
|
||||
if (block_length > 640)
|
||||
Kb = 10;
|
||||
else if (block_length>560)
|
||||
else if (block_length > 560)
|
||||
Kb = 9;
|
||||
else if (block_length>192)
|
||||
else if (block_length > 192)
|
||||
Kb = 8;
|
||||
else
|
||||
Kb = 6;
|
||||
}
|
||||
|
||||
if (nom_rate == 1)
|
||||
if (denom_rate == 5)
|
||||
if (BG == 2)
|
||||
R_ind = 0;
|
||||
else
|
||||
printf("Not supported");
|
||||
else if (denom_rate == 3)
|
||||
R_ind = 1;
|
||||
else if (denom_rate == 2)
|
||||
//R_ind = 3;
|
||||
printf("Not supported");
|
||||
else
|
||||
printf("Not supported");
|
||||
bool error = false;
|
||||
switch (nom_rate) {
|
||||
case 1:
|
||||
if (denom_rate == 5)
|
||||
if (BG == 2)
|
||||
R_ind = 0;
|
||||
else
|
||||
error = true;
|
||||
else if (denom_rate == 3)
|
||||
R_ind = 1;
|
||||
else if (denom_rate == 2)
|
||||
// R_ind = 3;
|
||||
error = true;
|
||||
else
|
||||
error = true;
|
||||
break;
|
||||
case 2:
|
||||
if (denom_rate == 5)
|
||||
// R_ind = 2;
|
||||
error = true;
|
||||
else if (denom_rate == 3)
|
||||
R_ind = 4;
|
||||
else
|
||||
error = true;
|
||||
break;
|
||||
case 22:
|
||||
if (denom_rate == 25 && BG == 1)
|
||||
R_ind = 7;
|
||||
else
|
||||
error = true;
|
||||
break;
|
||||
default:
|
||||
error = true;
|
||||
}
|
||||
|
||||
else if (nom_rate == 2)
|
||||
if (denom_rate == 5)
|
||||
//R_ind = 2;
|
||||
printf("Not supported");
|
||||
else if (denom_rate == 3)
|
||||
R_ind = 4;
|
||||
else
|
||||
printf("Not supported");
|
||||
if (error) {
|
||||
printf("Not supported: nom_rate: %d, denom_rate: %d\n", nom_rate, denom_rate);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
else if ((nom_rate == 22) && (denom_rate == 30))
|
||||
//R_ind = 5;
|
||||
printf("Not supported");
|
||||
else if ((nom_rate == 22) && (denom_rate == 27))
|
||||
//R_ind = 6;
|
||||
printf("Not supported");
|
||||
else if ((nom_rate == 22) && (denom_rate == 25))
|
||||
if (BG == 1)
|
||||
R_ind = 7;
|
||||
else
|
||||
printf("Not supported");
|
||||
else
|
||||
printf("Not supported");
|
||||
|
||||
//find minimum value in all sets of lifting size
|
||||
Zc=0;
|
||||
|
||||
for (i1=0; i1 < 51; i1++)
|
||||
{
|
||||
if (lift_size[i1] >= (double) block_length/Kb)
|
||||
{
|
||||
// find minimum value in all sets of lifting size
|
||||
int Zc = 0;
|
||||
const short lift_size[51] = {2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 18, 20,
|
||||
22, 24, 26, 28, 30, 32, 36, 40, 44, 48, 52, 56, 60, 64, 72, 80, 88,
|
||||
96, 104, 112, 120, 128, 144, 160, 176, 192, 208, 224, 240, 256, 288, 320, 352, 384};
|
||||
for (i1 = 0; i1 < 51; i1++) {
|
||||
if (lift_size[i1] >= (double)block_length / Kb) {
|
||||
Zc = lift_size[i1];
|
||||
//printf("%d\n",Zc);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
printf("ldpc_test: codeword_length %d, n_segments %d, block_length %d, BG %d, Zc %d, Kb %d\n",n_segments *block_length, n_segments, block_length, BG, Zc, Kb);
|
||||
no_punctured_columns=(int)((nrows-2)*Zc+block_length-block_length*(1/((float)nom_rate/(float)denom_rate)))/Zc;
|
||||
const int no_punctured_columns =
|
||||
(int)((nrows - 2) * Zc + block_length - block_length * (1 / ((float)nom_rate / (float)denom_rate))) / Zc;
|
||||
// printf("puncture:%d\n",no_punctured_columns);
|
||||
removed_bit=(nrows-no_punctured_columns-2) * Zc+block_length-(int)(block_length/((float)nom_rate/(float)denom_rate));
|
||||
encoder_implemparams_t impp=INIT0_LDPCIMPLEMPARAMS;
|
||||
const int removed_bit =
|
||||
(nrows - no_punctured_columns - 2) * Zc + block_length - (int)(block_length / ((float)nom_rate / (float)denom_rate));
|
||||
|
||||
printf("nrows: %d\n", nrows);
|
||||
printf("no_punctured_columns: %d\n", no_punctured_columns);
|
||||
printf("removed_bit: %d\n", removed_bit);
|
||||
printf("To: %d\n", (Kb + nrows - no_punctured_columns) * Zc - removed_bit);
|
||||
printf("number of undecoded bits: %d\n", (Kb + nrows - no_punctured_columns - 2) * Zc - removed_bit);
|
||||
|
||||
encoder_implemparams_t impp = {.Zc = Zc, .Kb = Kb, .E = block_length, .BG = BG, .Kr = block_length, .K = block_length};
|
||||
impp.gen_code = 2;
|
||||
|
||||
if (ntrials==0)
|
||||
encoder_orig(test_input,channel_input, Zc, BG, block_length, BG, &impp);
|
||||
ldpc_orig.LDPCencoder(test_input, channel_input, &impp);
|
||||
impp.gen_code=0;
|
||||
decode_abort_t dec_abort;
|
||||
init_abort(&dec_abort);
|
||||
for (int trial=0; trial < ntrials; trial++)
|
||||
{
|
||||
segment_bler = 0;
|
||||
for (int trial = 0; trial < ntrials; trial++) {
|
||||
unsigned int segment_bler = 0;
|
||||
//// encoder
|
||||
start_meas(&time);
|
||||
for(int j=0;j<n_segments;j++) {
|
||||
encoder_orig(&(test_input[j]), &(channel_input[j]),Zc,Kb,block_length,BG,&impp);
|
||||
for (int j = 0; j < n_segments; j++) {
|
||||
ldpc_orig.LDPCencoder(&test_input[j], &channel_input[j], &impp);
|
||||
}
|
||||
stop_meas(&time);
|
||||
|
||||
/* start_meas(time_optim);
|
||||
ldpc_encoder_optim_8seg(test_input,channel_input_optim,Zc,Kb,block_length,BG,n_segments,&tinput,&tprep,&tparity,&toutput);
|
||||
for(j=0;j<n_segments;j++) {
|
||||
ldpc_encoder_optim(test_input[j],channel_input_optim[j],Zc,Kb,block_length,BG,&tinput,&tprep,&tparity,&toutput);
|
||||
}
|
||||
stop_meas(time_optim);*/
|
||||
impp.n_segments=n_segments;
|
||||
for(int j=0;j<(n_segments/8+1);j++) {
|
||||
start_meas(time_optim);
|
||||
impp.macro_num=j;
|
||||
nrLDPC_encoder(test_input,channel_input_optim,Zc,Kb,block_length, BG, &impp);
|
||||
stop_meas(time_optim);
|
||||
}
|
||||
|
||||
if (ntrials==1)
|
||||
for (int j=0;j<n_segments;j++)
|
||||
for (int i = 0; i < block_length+(nrows-no_punctured_columns) * Zc - removed_bit; i++)
|
||||
if (channel_input[j][i]!=channel_input_optim[j][i]) {
|
||||
printf("differ in seg %d pos %d (%u,%u)\n", j, i, channel_input[j][i], channel_input_optim[j][i]);
|
||||
return (-1);
|
||||
}
|
||||
//else{
|
||||
// printf("NOT differ in seg %d pos %d (%d,%d)\n",j,i,channel_input[j][i],channel_input_optim[j][i]);
|
||||
// }
|
||||
if (trial== 0) {
|
||||
printf("nrows: %d\n", nrows);
|
||||
printf("no_punctured_columns: %d\n", no_punctured_columns);
|
||||
printf("removed_bit: %d\n", removed_bit);
|
||||
printf("To: %d\n", (Kb+nrows-no_punctured_columns) * Zc-removed_bit);
|
||||
printf("number of undecoded bits: %d\n", (Kb+nrows-no_punctured_columns-2) * Zc-removed_bit);
|
||||
impp.n_segments = n_segments;
|
||||
for (int j = 0; j < (n_segments / 8 + 1); j++) {
|
||||
start_meas(&ret.time_optim);
|
||||
impp.macro_num = j;
|
||||
ldpc_toCompare.LDPCencoder(test_input, channel_input_optim, &impp);
|
||||
stop_meas(&ret.time_optim);
|
||||
}
|
||||
|
||||
if (1) { // Transmitting one segment
|
||||
for(int j=0;j<n_segments;j++) {
|
||||
for (int i = 2*Zc; i < (Kb+nrows-no_punctured_columns) * Zc-removed_bit; i++) {
|
||||
if (ntrials == 1)
|
||||
for (int j = 0; j < n_segments; j++)
|
||||
for (int i = 0; i < block_length + (nrows - no_punctured_columns) * Zc - removed_bit; i++)
|
||||
if (channel_input[j][i] != channel_input_optim[j][i]) {
|
||||
printf("differ in seg %d pos %d (%u,%u)\n", j, i, channel_input[j][i], channel_input_optim[j][i]);
|
||||
return ret;
|
||||
}
|
||||
|
||||
for (int j = 0; j < n_segments; j++) {
|
||||
for (int i = 2 * Zc; i < (Kb + nrows - no_punctured_columns) * Zc - removed_bit; i++) {
|
||||
#ifdef DEBUG_CODER
|
||||
if ((i&0xf)==0)
|
||||
printf("\ne %d..%d: ",i,i+15);
|
||||
if ((i & 0xf) == 0)
|
||||
printf("\ne %d..%d: ", i, i + 15);
|
||||
#endif
|
||||
|
||||
if (channel_input_optim[j][i-2*Zc]==0)
|
||||
modulated_input[j][i]=1.0;///sqrt(2); //QPSK
|
||||
else
|
||||
modulated_input[j][i]=-1.0;///sqrt(2);
|
||||
if (channel_input_optim[j][i - 2 * Zc] == 0)
|
||||
modulated_input[j][i] = 1.0; /// sqrt(2); //QPSK
|
||||
else
|
||||
modulated_input[j][i] = -1.0; /// sqrt(2);
|
||||
|
||||
///channel_output[i] = modulated_input[i] + gaussdouble(0.0,1.0) * 1/sqrt(2*SNR);
|
||||
//channel_output_fixed[i] = (int8_t) ((channel_output[i]*128)<0?(channel_output[i]*128-0.5):(channel_output[i]*128+0.5)); //fixed point 9-7
|
||||
//printf("llr[%d]=%d\n",i,channel_output_fixed[i]);
|
||||
channel_output_fixed[j][i] =
|
||||
(int8_t)quantize(sigma / 4.0 / 4.0, modulated_input[j][i] + sigma * gaussdouble(0.0, 1.0), qbits);
|
||||
|
||||
//channel_output_fixed[i] = (int8_t)quantize(sigma/4.0,(2.0*modulated_input[i]) - 1.0 + sigma*gaussdouble(0.0,1.0),qbits);
|
||||
channel_output_fixed[j][i] = (int8_t)quantize(sigma/4.0/4.0,modulated_input[j][i] + sigma*gaussdouble(0.0,1.0),qbits);
|
||||
//channel_output_fixed[i] = (int8_t)quantize8bit(sigma/4.0,(2.0*modulated_input[i]) - 1.0 + sigma*gaussdouble(0.0,1.0));
|
||||
//printf("llr[%d]=%d\n",i,channel_output_fixed[i]);
|
||||
//printf("channel_output_fixed[%d]: %d\n",i,channel_output_fixed[i]);
|
||||
// Uncoded BER
|
||||
uint8_t channel_output_uncoded = channel_output_fixed[j][i] < 0 ? 1 /* QPSK demod */ : 0;
|
||||
if (channel_output_uncoded != channel_input_optim[j][i - 2 * Zc])
|
||||
ret.errors_bit_uncoded++;
|
||||
}
|
||||
|
||||
|
||||
//Uncoded BER
|
||||
uint8_t channel_output_uncoded = channel_output_fixed[j][i]<0 ? 1 /* QPSK demod */ : 0;
|
||||
|
||||
if (channel_output_uncoded != channel_input_optim[j][i-2*Zc])
|
||||
*errors_bit_uncoded = (*errors_bit_uncoded) + 1;
|
||||
|
||||
}
|
||||
|
||||
#ifdef DEBUG_CODER
|
||||
printf("\n");
|
||||
exit(-1);
|
||||
#endif
|
||||
|
||||
decParams[j].BG=BG;
|
||||
decParams[j].Z=Zc;
|
||||
decParams[j].R=code_rate_vec[R_ind];//13;
|
||||
decParams[j].numMaxIter=max_iterations;
|
||||
decParams[j].BG = BG;
|
||||
decParams[j].Z = Zc;
|
||||
decParams[j].R = code_rate_vec[R_ind]; // 13;
|
||||
decParams[j].numMaxIter = max_iterations;
|
||||
decParams[j].outMode = nrLDPC_outMode_BIT;
|
||||
decParams[j].block_length=block_length;
|
||||
nrLDPC_initcall(&decParams[j], (int8_t*)channel_output_fixed[j], (int8_t*)estimated_output[j]);
|
||||
}
|
||||
for(int j=0;j<n_segments;j++) {
|
||||
start_meas(time_decoder);
|
||||
set_abort(&dec_abort, false);
|
||||
n_iter = nrLDPC_decoder(&decParams[j],
|
||||
(int8_t *)channel_output_fixed[j],
|
||||
(int8_t *)estimated_output[j],
|
||||
&decoder_profiler,
|
||||
&dec_abort);
|
||||
stop_meas(time_decoder);
|
||||
//count errors
|
||||
if ( memcmp(estimated_output[j], test_input[j], block_length/8 ) != 0 ) {
|
||||
segment_bler++;
|
||||
}
|
||||
for (int i=0; i<block_length; i++)
|
||||
{
|
||||
uint8_t estoutputbit = (estimated_output[j][i/8]&(1<<(i&7)))>>(i&7);
|
||||
uint8_t inputbit = (test_input[j][i/8]&(1<<(i&7)))>>(i&7); // Further correct for multiple segments
|
||||
if (estoutputbit != inputbit)
|
||||
*errors_bit = (*errors_bit) + 1;
|
||||
}
|
||||
|
||||
n_iter_mean += n_iter;
|
||||
n_iter_std += pow(n_iter-1,2);
|
||||
|
||||
if ( n_iter > n_iter_max )
|
||||
n_iter_max = n_iter;
|
||||
|
||||
} // end segments
|
||||
|
||||
if (segment_bler != 0)
|
||||
*errors = (*errors) + 1;
|
||||
|
||||
decParams[j].E = block_length;
|
||||
ldpc_toCompare.LDPCinit();
|
||||
}
|
||||
for (int j = 0; j < n_segments; j++) {
|
||||
start_meas(&ret.time_decoder);
|
||||
set_abort(&dec_abort, false);
|
||||
|
||||
n_iter = ldpc_toCompare.LDPCdecoder(&decParams[j],
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
(int8_t *)channel_output_fixed[j],
|
||||
(int8_t *)estimated_output[j],
|
||||
&decoder_profiler,
|
||||
&dec_abort);
|
||||
stop_meas(&ret.time_decoder);
|
||||
// count errors
|
||||
if (memcmp(estimated_output[j], test_input[j], block_length / 8) != 0) {
|
||||
segment_bler++;
|
||||
}
|
||||
for (int i = 0; i < block_length; i++) {
|
||||
unsigned char estoutputbit = (estimated_output[j][i / 8] & (1 << (i & 7))) >> (i & 7);
|
||||
unsigned char inputbit = (test_input[j][i / 8] & (1 << (i & 7))) >> (i & 7); // Further correct for multiple segments
|
||||
if (estoutputbit != inputbit)
|
||||
ret.errors_bit++;
|
||||
}
|
||||
|
||||
n_iter_mean += n_iter;
|
||||
n_iter_std += pow(n_iter - 1, 2);
|
||||
|
||||
if (n_iter > n_iter_max)
|
||||
n_iter_max = n_iter;
|
||||
|
||||
} // end segments
|
||||
|
||||
if (segment_bler != 0)
|
||||
ret.errors++;
|
||||
}
|
||||
|
||||
|
||||
dec_iter->n_iter_mean[nsnr] = n_iter_mean/(double)ntrials/(double)n_segments - 1;
|
||||
dec_iter->n_iter_std[nsnr] = sqrt(n_iter_std/(double)ntrials/(double)n_segments - pow(n_iter_mean/(double)ntrials/(double)n_segments - 1,2));
|
||||
dec_iter->n_iter_max[nsnr] = n_iter_max -1;
|
||||
|
||||
*errors_bit_uncoded = *errors_bit_uncoded / (double)((Kb+nrows-no_punctured_columns-2) * Zc-removed_bit);
|
||||
|
||||
for(int j=0;j<MAX_NUM_DLSCH_SEGMENTS;j++) {
|
||||
|
||||
ret.dec_iter.n_iter_mean = n_iter_mean / (double)ntrials / (double)n_segments - 1;
|
||||
ret.dec_iter.n_iter_std =
|
||||
sqrt(n_iter_std / (double)ntrials / (double)n_segments - pow(n_iter_mean / (double)ntrials / (double)n_segments - 1, 2));
|
||||
ret.dec_iter.n_iter_max = n_iter_max - 1;
|
||||
|
||||
ret.errors_bit_uncoded = ret.errors_bit_uncoded / (double)((Kb + nrows - no_punctured_columns - 2) * Zc - removed_bit);
|
||||
|
||||
for (int j = 0; j < MAX_NUM_DLSCH_SEGMENTS; j++) {
|
||||
free(test_input[j]);
|
||||
free(channel_input[j]);
|
||||
free(channel_input_optim[j]);
|
||||
}
|
||||
|
||||
|
||||
print_meas(&time,"ldpc_encoder",NULL,NULL);
|
||||
print_meas(time_optim,"ldpc_encoder_optim",NULL,NULL);
|
||||
print_meas(&ret.time_optim, "ldpc_encoder_optim", NULL, NULL);
|
||||
print_meas(&tinput,"ldpc_encoder_optim(input)",NULL,NULL);
|
||||
print_meas(&tprep,"ldpc_encoder_optim(prep)",NULL,NULL);
|
||||
print_meas(&tparity,"ldpc_encoder_optim(parity)",NULL,NULL);
|
||||
print_meas(&toutput,"ldpc_encoder_optim(output)",NULL,NULL);
|
||||
printf("\n");
|
||||
print_meas(time_decoder,"ldpc_decoder",NULL,NULL);
|
||||
print_meas(&ret.time_decoder, "ldpc_decoder", NULL, NULL);
|
||||
print_meas(&decoder_profiler.llr2llrProcBuf,"llr2llrProcBuf",NULL,NULL);
|
||||
print_meas(&decoder_profiler.llr2CnProcBuf,"llr2CnProcBuf",NULL,NULL);
|
||||
print_meas(&decoder_profiler.cnProc,"cnProc (per iteration)",NULL,NULL);
|
||||
@@ -427,17 +394,14 @@ int test_ldpc(short max_iterations,
|
||||
print_meas(&decoder_profiler.llr2bit,"llr2bit",NULL,NULL);
|
||||
printf("\n");
|
||||
|
||||
return *errors;
|
||||
return ret;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
|
||||
unsigned int errors, errors_bit, crc_misses;
|
||||
double errors_bit_uncoded;
|
||||
short block_length=8448; // decoder supports length: 1201 -> 1280, 2401 -> 2560
|
||||
// default to check output inside ldpc, the NR version checks the outer CRC defined by 3GPP
|
||||
char *ldpc_version = "_parityCheck";
|
||||
char *ldpc_version = "";
|
||||
/* version of the ldpc decoder library to use (XXX suffix to use when loading libldpc_XXX.so */
|
||||
short max_iterations=5;
|
||||
int n_segments=1;
|
||||
@@ -445,25 +409,22 @@ int main(int argc, char *argv[])
|
||||
|
||||
int nom_rate=1;
|
||||
int denom_rate=3;
|
||||
double SNR0=-2.0,SNR,SNR_lin;
|
||||
double SNR0=-2.0;
|
||||
uint8_t qbits=8;
|
||||
unsigned int decoded_errors[10000]; // initiate the size of matrix equivalent to size of SNR
|
||||
int c,i=0, i1 = 0;
|
||||
int c, i = 0;
|
||||
|
||||
int n_trials = 1;
|
||||
double SNR_step = 0.1;
|
||||
|
||||
randominit(0);
|
||||
int test_uncoded= 0;
|
||||
n_iter_stats_t dec_iter[400] = {0};
|
||||
|
||||
time_stats_t time_optim[10], time_decoder[10];
|
||||
n_iter_stats_t dec_iter;
|
||||
|
||||
short BG=0,Zc,Kb=0;
|
||||
short BG = 0, Zc;
|
||||
|
||||
while ((c = getopt (argc, argv, "q:r:s:S:l:G:n:d:i:t:u:hv:")) != -1)
|
||||
switch (c)
|
||||
{
|
||||
switch (c) {
|
||||
case 'q':
|
||||
qbits = atoi(optarg);
|
||||
break;
|
||||
@@ -508,29 +469,29 @@ int main(int argc, char *argv[])
|
||||
test_uncoded = atoi(optarg);
|
||||
break;
|
||||
case 'v':
|
||||
ldpc_version=strdup(optarg);
|
||||
ldpc_version = strdup(optarg);
|
||||
break;
|
||||
case 'h':
|
||||
default:
|
||||
printf("CURRENTLY SUPPORTED CODE RATES: \n");
|
||||
printf("BG1 (blocklength > 3840): 1/3, 2/3, 22/25 (8/9) \n");
|
||||
printf("BG2 (blocklength <= 3840): 1/5, 1/3, 2/3 \n\n");
|
||||
printf("-h This message\n");
|
||||
printf("-q Quantization bits, Default: 8\n");
|
||||
printf("-r Nominator rate, (1, 2, 22), Default: 1\n");
|
||||
printf("-d Denominator rate, (3, 5, 25), Default: 1\n");
|
||||
printf("-l Block length (l > 3840 -> BG1, rest BG2 ), Default: 8448\n");
|
||||
printf("-G give 1 to run cuda for LDPC, Default: 0\n");
|
||||
printf("-n Number of simulation trials, Default: 1\n");
|
||||
//printf("-M MCS2 for TB 2\n");
|
||||
printf("-s SNR per information bit (EbNo) in dB, Default: -2\n");
|
||||
printf("-S Number of segments (Maximum: 8), Default: 1\n");
|
||||
printf("-t SNR simulation step, Default: 0.1\n");
|
||||
printf("-i Max decoder iterations, Default: 5\n");
|
||||
printf("-u Set SNR per coded bit, Default: 0\n");
|
||||
printf("-v XXX Set ldpc shared library version. libldpc_XXX.so will be used \n");
|
||||
exit(1);
|
||||
break;
|
||||
printf("CURRENTLY SUPPORTED CODE RATES: \n");
|
||||
printf("BG1 (blocklength > 3840): 1/3, 2/3, 22/25 (8/9) \n");
|
||||
printf("BG2 (blocklength <= 3840): 1/5, 1/3, 2/3 \n\n");
|
||||
printf("-h This message\n");
|
||||
printf("-q Quantization bits, Default: 8\n");
|
||||
printf("-r Nominator rate, (1, 2, 22), Default: 1\n");
|
||||
printf("-d Denominator rate, (3, 5, 25), Default: 1\n");
|
||||
printf("-l Block length (l > 3840 -> BG1, rest BG2 ), Default: 8448\n");
|
||||
printf("-G give 1 to run cuda for LDPC, Default: 0\n");
|
||||
printf("-n Number of simulation trials, Default: 1\n");
|
||||
// printf("-M MCS2 for TB 2\n");
|
||||
printf("-s SNR per information bit (EbNo) in dB, Default: -2\n");
|
||||
printf("-S Number of segments (Maximum: 8), Default: 1\n");
|
||||
printf("-t SNR simulation step, Default: 0.1\n");
|
||||
printf("-i Max decoder iterations, Default: 5\n");
|
||||
printf("-u Set SNR per coded bit, Default: 0\n");
|
||||
printf("-v XXX Set ldpc shared library version. libldpc_XXX.so will be used \n");
|
||||
exit(1);
|
||||
break;
|
||||
}
|
||||
//printf("the decoder supports BG2, Kb=10, Z=128 & 256\n");
|
||||
//printf(" range of blocklength: 1201 -> 1280, 2401 -> 2560\n");
|
||||
@@ -538,48 +499,13 @@ int main(int argc, char *argv[])
|
||||
printf("n_trials %d: \n", n_trials);
|
||||
printf("SNR0 %f: \n", SNR0);
|
||||
|
||||
load_nrLDPClib(ldpc_version);
|
||||
load_nrLDPClib_ref("_orig", &encoder_orig);
|
||||
load_LDPClib(ldpc_version, &ldpc_toCompare);
|
||||
load_LDPClib("_orig", &ldpc_orig);
|
||||
//for (block_length=8;block_length<=MAX_BLOCK_LENGTH;block_length+=8)
|
||||
|
||||
|
||||
//determine number of bits in codeword
|
||||
if (block_length>3840)
|
||||
{
|
||||
BG = 1;
|
||||
Kb = 22;
|
||||
//nrows=46; //parity check bits
|
||||
//ncols=22; //info bits
|
||||
}
|
||||
else if (block_length<=3840)
|
||||
{
|
||||
BG = 2;
|
||||
//nrows=42; //parity check bits
|
||||
//ncols=10; // info bits
|
||||
|
||||
if (block_length>640)
|
||||
Kb = 10;
|
||||
else if (block_length>560)
|
||||
Kb = 9;
|
||||
else if (block_length>192)
|
||||
Kb = 8;
|
||||
else
|
||||
Kb = 6;
|
||||
}
|
||||
|
||||
//find minimum value in all sets of lifting size
|
||||
Zc=0;
|
||||
|
||||
for (i1=0; i1 < 51; i1++)
|
||||
{
|
||||
if (lift_size[i1] >= (double) block_length/Kb)
|
||||
{
|
||||
Zc = lift_size[i1];
|
||||
//printf("%d\n",Zc);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
char fname[200];
|
||||
sprintf(fname,"ldpctest_BG_%d_Zc_%d_rate_%d-%d_block_length_%d_maxit_%d.txt",BG,Zc,nom_rate,denom_rate,block_length, max_iterations);
|
||||
FILE *fd=fopen(fname,"w");
|
||||
@@ -587,75 +513,72 @@ int main(int argc, char *argv[])
|
||||
|
||||
fprintf(fd,"SNR BLER BER UNCODED_BER ENCODER_MEAN ENCODER_STD ENCODER_MAX DECODER_TIME_MEAN DECODER_TIME_STD DECODER_TIME_MAX DECODER_ITER_MEAN DECODER_ITER_STD DECODER_ITER_MAX\n");
|
||||
|
||||
for (SNR=SNR0;SNR<SNR0+20.0;SNR+=SNR_step) {
|
||||
//reset_meas(&time_optim);
|
||||
//reset_meas(&time_decoder);
|
||||
//n_iter_stats_t dec_iter = {0, 0, 0};
|
||||
for (double SNR = SNR0; SNR < SNR0 + 20.0; SNR += SNR_step) {
|
||||
double SNR_lin;
|
||||
if (test_uncoded == 1)
|
||||
SNR_lin = pow(10,SNR/10.0);
|
||||
SNR_lin = pow(10, SNR / 10.0);
|
||||
else
|
||||
SNR_lin = pow(10,SNR/10.0)*nom_rate/denom_rate;
|
||||
SNR_lin = pow(10, SNR / 10.0) * nom_rate / denom_rate;
|
||||
printf("Linear SNR: %f\n", SNR_lin);
|
||||
decoded_errors[i]=test_ldpc(max_iterations,
|
||||
nom_rate,
|
||||
denom_rate,
|
||||
SNR_lin, // noise standard deviation
|
||||
qbits,
|
||||
block_length, // block length bytes
|
||||
n_trials,
|
||||
n_segments,
|
||||
&errors,
|
||||
&errors_bit,
|
||||
&errors_bit_uncoded,
|
||||
&crc_misses,
|
||||
time_optim,
|
||||
time_decoder,
|
||||
&dec_iter,
|
||||
i);
|
||||
|
||||
dec_iter.snr[i] = SNR;
|
||||
dec_iter.ber[i] = (float)errors_bit/(float)n_trials/(float)block_length/(double)n_segments;
|
||||
dec_iter.bler[i] = (float)decoded_errors[i]/(float)n_trials;
|
||||
printf("SNR %f, BLER %f (%u/%d)\n", SNR, dec_iter.bler[i], decoded_errors[i], n_trials);
|
||||
printf("SNR %f, BER %f (%u/%d)\n", SNR, dec_iter.ber[i], decoded_errors[i], n_trials);
|
||||
printf("SNR %f, Uncoded BER %f (%u/%d)\n",SNR, errors_bit_uncoded/(float)n_trials/(double)n_segments, decoded_errors[i], n_trials);
|
||||
printf("SNR %f, Mean iterations: %f\n",SNR, dec_iter.n_iter_mean[i]);
|
||||
printf("SNR %f, Std iterations: %f\n",SNR, dec_iter.n_iter_std[i]);
|
||||
printf("SNR %f, Max iterations: %d\n",SNR, dec_iter.n_iter_max[i]);
|
||||
one_measurement_t res = test_ldpc(max_iterations,
|
||||
nom_rate,
|
||||
denom_rate,
|
||||
SNR_lin, // noise standard deviation
|
||||
qbits,
|
||||
block_length, // block length bytes
|
||||
n_trials,
|
||||
n_segments);
|
||||
decoded_errors[i] = res.errors;
|
||||
dec_iter[i] = res.dec_iter;
|
||||
dec_iter[i].snr = SNR;
|
||||
dec_iter[i].ber = (float)res.errors_bit / (float)n_trials / (float)block_length / (double)n_segments;
|
||||
dec_iter[i].bler = (float)decoded_errors[i] / (float)n_trials;
|
||||
printf("SNR %f, BLER %f (%u/%d)\n", SNR, dec_iter[i].bler, decoded_errors[i], n_trials);
|
||||
printf("SNR %f, BER %f (%u/%d)\n", SNR, dec_iter[i].ber, decoded_errors[i], n_trials);
|
||||
printf("SNR %f, Uncoded BER %f (%u/%d)\n",
|
||||
SNR,
|
||||
res.errors_bit_uncoded / (float)n_trials / (double)n_segments,
|
||||
decoded_errors[i],
|
||||
n_trials);
|
||||
printf("SNR %f, Mean iterations: %f\n", SNR, dec_iter[i].n_iter_mean);
|
||||
printf("SNR %f, Std iterations: %f\n", SNR, dec_iter[i].n_iter_std);
|
||||
printf("SNR %f, Max iterations: %d\n", SNR, dec_iter[i].n_iter_max);
|
||||
printf("\n");
|
||||
printf("Encoding time mean: %15.3f us\n",(double)time_optim->diff/time_optim->trials/1000.0/get_cpu_freq_GHz());
|
||||
printf("Encoding time std: %15.3f us\n",sqrt((double)time_optim->diff_square/time_optim->trials/pow(1000,2)/pow(get_cpu_freq_GHz(),2)-pow((double)time_optim->diff/time_optim->trials/1000.0/get_cpu_freq_GHz(),2)));
|
||||
printf("Encoding time max: %15.3f us\n",(double)time_optim->max/1000.0/get_cpu_freq_GHz());
|
||||
printf("Encoding time mean: %15.3f us\n",(double)res.time_optim.diff/res.time_optim.trials/1000.0/get_cpu_freq_GHz());
|
||||
printf("Encoding time std: %15.3f us\n",sqrt((double)res.time_optim.diff_square/res.time_optim.trials/pow(1000,2)/pow(get_cpu_freq_GHz(),2)-pow((double)res.time_optim.diff/res.time_optim.trials/1000.0/get_cpu_freq_GHz(),2)));
|
||||
printf("Encoding time max: %15.3f us\n",(double)res.time_optim.max/1000.0/get_cpu_freq_GHz());
|
||||
printf("\n");
|
||||
printf("Decoding time mean: %15.3f us\n",(double)time_decoder->diff/time_decoder->trials/1000.0/get_cpu_freq_GHz());
|
||||
printf("Decoding time std: %15.3f us\n",sqrt((double)time_decoder->diff_square/time_decoder->trials/pow(1000,2)/pow(get_cpu_freq_GHz(),2)-pow((double)time_decoder->diff/time_decoder->trials/1000.0/get_cpu_freq_GHz(),2)));
|
||||
printf("Decoding time max: %15.3f us\n",(double)time_decoder->max/1000.0/get_cpu_freq_GHz());
|
||||
printf("Decoding time mean: %15.3f us\n",(double)res.time_decoder.diff/res.time_decoder.trials/1000.0/get_cpu_freq_GHz());
|
||||
printf("Decoding time std: %15.3f us\n",sqrt((double)res.time_decoder.diff_square/res.time_decoder.trials/pow(1000,2)/pow(get_cpu_freq_GHz(),2)-pow((double)res.time_decoder.diff/res.time_decoder.trials/1000.0/get_cpu_freq_GHz(),2)));
|
||||
printf("Decoding time max: %15.3f us\n",(double)res.time_decoder.max/1000.0/get_cpu_freq_GHz());
|
||||
|
||||
fprintf(fd,"%f %f %f %f %f %f %f %f %f %f %f %f %d \n",
|
||||
SNR,
|
||||
(double)decoded_errors[i]/(double)n_trials ,
|
||||
(double)errors_bit/(double)n_trials/(double)block_length/(double)n_segments ,
|
||||
errors_bit_uncoded/(double)n_trials/(double)n_segments ,
|
||||
(double)time_optim->diff/time_optim->trials/1000.0/get_cpu_freq_GHz(),
|
||||
sqrt((double)time_optim->diff_square/time_optim->trials/pow(1000,2)/pow(get_cpu_freq_GHz(),2)-pow((double)time_optim->diff/time_optim->trials/1000.0/get_cpu_freq_GHz(),2)),
|
||||
(double)time_optim->max/1000.0/get_cpu_freq_GHz(),
|
||||
(double)time_decoder->diff/time_decoder->trials/1000.0/get_cpu_freq_GHz(),
|
||||
sqrt((double)time_decoder->diff_square/time_decoder->trials/pow(1000,2)/pow(get_cpu_freq_GHz(),2)-pow((double)time_decoder->diff/time_decoder->trials/1000.0/get_cpu_freq_GHz(),2)),
|
||||
(double)time_decoder->max/1000.0/get_cpu_freq_GHz(),
|
||||
dec_iter.n_iter_mean[i],
|
||||
dec_iter.n_iter_std[i],
|
||||
dec_iter.n_iter_max[i]
|
||||
);
|
||||
fprintf(fd,
|
||||
"%f %f %f %f %f %f %f %f %f %f %f %f %d \n",
|
||||
SNR,
|
||||
(double)decoded_errors[i] / (double)n_trials,
|
||||
(double)res.errors_bit / (double)n_trials / (double)block_length / (double)n_segments,
|
||||
res.errors_bit_uncoded / (double)n_trials / (double)n_segments,
|
||||
(double)res.time_optim.diff / res.time_optim.trials / 1000.0 / get_cpu_freq_GHz(),
|
||||
sqrt((double)res.time_optim.diff_square / res.time_optim.trials / pow(1000, 2) / pow(get_cpu_freq_GHz(), 2)
|
||||
- pow((double)res.time_optim.diff / res.time_optim.trials / 1000.0 / get_cpu_freq_GHz(), 2)),
|
||||
(double)res.time_optim.max / 1000.0 / get_cpu_freq_GHz(),
|
||||
(double)res.time_decoder.diff / res.time_decoder.trials / 1000.0 / get_cpu_freq_GHz(),
|
||||
sqrt((double)res.time_decoder.diff_square / res.time_decoder.trials / pow(1000, 2) / pow(get_cpu_freq_GHz(), 2)
|
||||
- pow((double)res.time_decoder.diff / res.time_decoder.trials / 1000.0 / get_cpu_freq_GHz(), 2)),
|
||||
(double)res.time_decoder.max / 1000.0 / get_cpu_freq_GHz(),
|
||||
dec_iter[i].n_iter_mean,
|
||||
dec_iter[i].n_iter_std,
|
||||
dec_iter[i].n_iter_max);
|
||||
|
||||
i=i+1;
|
||||
if (decoded_errors[i-1] == 0) break;
|
||||
|
||||
if (decoded_errors[i - 1] == 0)
|
||||
break;
|
||||
}
|
||||
fclose(fd);
|
||||
LOG_M("ldpctestStats.m","SNR",&dec_iter.snr[0],i,1,7);
|
||||
LOG_MM("ldpctestStats.m","BLER",&dec_iter.bler[0],i,1,7);
|
||||
LOG_MM("ldpctestStats.m","BER",&dec_iter.ber[0],i,1,7);
|
||||
LOG_MM("ldpctestStats.m","meanIter",&dec_iter.n_iter_mean[0],i,1,7);
|
||||
LOG_M("ldpctestStats.m", "SNR", &dec_iter[0].snr, i, 1, 7);
|
||||
LOG_MM("ldpctestStats.m", "BLER", &dec_iter[0].bler, i, 1, 7);
|
||||
LOG_MM("ldpctestStats.m", "BER", &dec_iter[0].ber, i, 1, 7);
|
||||
LOG_MM("ldpctestStats.m", "meanIter", &dec_iter[0].n_iter_mean, i, 1, 7);
|
||||
|
||||
loader_reset();
|
||||
logTerm();
|
||||
|
||||
@@ -133,14 +133,24 @@
|
||||
#include "bnProc128/nrLDPC_bnProc_BG2_R23_128.h"
|
||||
#endif
|
||||
|
||||
//#define NR_LDPC_ENABLE_PARITY_CHECK
|
||||
//#define NR_LDPC_PROFILER_DETAIL(a) a
|
||||
#define NR_LDPC_PROFILER_DETAIL(a)
|
||||
|
||||
#include "openair1/PHY/CODING/nrLDPC_extern.h"
|
||||
|
||||
#ifdef NR_LDPC_DEBUG_MODE
|
||||
#include "nrLDPC_tools/nrLDPC_debug.h"
|
||||
#endif
|
||||
|
||||
// decoder interface
|
||||
/**
|
||||
\brief LDPC decoder API type definition
|
||||
\param p_decParams LDPC decoder parameters
|
||||
\param p_llr Input LLRs
|
||||
\param p_llrOut Output vector
|
||||
\param p_profiler LDPC profiler statistics
|
||||
*/
|
||||
|
||||
static inline uint32_t nrLDPC_decoder_core(int8_t* p_llr,
|
||||
int8_t* p_out,
|
||||
uint32_t numLLR,
|
||||
@@ -148,13 +158,25 @@ static inline uint32_t nrLDPC_decoder_core(int8_t* p_llr,
|
||||
t_nrLDPC_dec_params* p_decParams,
|
||||
t_nrLDPC_time_stats* p_profiler,
|
||||
decode_abort_t* ab);
|
||||
void nrLDPC_initcall(t_nrLDPC_dec_params* p_decParams, int8_t* p_llr, int8_t* p_out) {
|
||||
|
||||
int32_t LDPCinit()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
int32_t nrLDPC_decod(t_nrLDPC_dec_params* p_decParams,
|
||||
int8_t* p_llr,
|
||||
int8_t* p_out,
|
||||
t_nrLDPC_time_stats* p_profiler,
|
||||
decode_abort_t* ab)
|
||||
|
||||
int32_t LDPCshutdown()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t LDPCdecoder(t_nrLDPC_dec_params* p_decParams,
|
||||
uint8_t harq_pid,
|
||||
uint8_t ulsch_id,
|
||||
uint8_t C,
|
||||
int8_t* p_llr,
|
||||
int8_t* p_out,
|
||||
t_nrLDPC_time_stats* p_profiler,
|
||||
decode_abort_t* ab)
|
||||
{
|
||||
uint32_t numLLR;
|
||||
t_nrLDPC_lut lut;
|
||||
@@ -817,31 +839,30 @@ static inline uint32_t nrLDPC_decoder_core(int8_t* p_llr,
|
||||
#endif
|
||||
|
||||
// Parity Check
|
||||
#ifdef NR_LDPC_ENABLE_PARITY_CHECK
|
||||
NR_LDPC_PROFILER_DETAIL(start_meas(&p_profiler->cnProcPc));
|
||||
if (BG == 1)
|
||||
pcRes = nrLDPC_cnProcPc_BG1(p_lut, cnProcBuf, cnProcBufRes, Z);
|
||||
else
|
||||
pcRes = nrLDPC_cnProcPc_BG2(p_lut, cnProcBuf, cnProcBufRes, Z);
|
||||
NR_LDPC_PROFILER_DETAIL(stop_meas(&p_profiler->cnProcPc));
|
||||
#else
|
||||
if (numIter > 2) {
|
||||
int8_t llrOut[NR_LDPC_MAX_NUM_LLR] __attribute__((aligned(64))) = {0};
|
||||
int8_t* p_llrOut = outMode == nrLDPC_outMode_LLRINT8 ? p_out : llrOut;
|
||||
nrLDPC_llrRes2llrOut(p_lut, p_llrOut, llrRes, Z, BG);
|
||||
if (outMode == nrLDPC_outMode_BIT)
|
||||
nrLDPC_llr2bitPacked(p_out, p_llrOut, numLLR);
|
||||
else // if (outMode == nrLDPC_outMode_BITINT8)
|
||||
nrLDPC_llr2bit(p_out, p_llrOut, numLLR);
|
||||
if (check_crc((uint8_t*)p_out, p_decParams->block_length, p_decParams->crc_type)) {
|
||||
LOG_D(PHY, "Segment CRC OK, exiting LDPC decoder\n");
|
||||
break;
|
||||
if (!p_decParams->check_crc) {
|
||||
NR_LDPC_PROFILER_DETAIL(start_meas(&p_profiler->cnProcPc));
|
||||
if (BG == 1)
|
||||
pcRes = nrLDPC_cnProcPc_BG1(p_lut, cnProcBuf, cnProcBufRes, Z);
|
||||
else
|
||||
pcRes = nrLDPC_cnProcPc_BG2(p_lut, cnProcBuf, cnProcBufRes, Z);
|
||||
NR_LDPC_PROFILER_DETAIL(stop_meas(&p_profiler->cnProcPc));
|
||||
} else {
|
||||
if (numIter > 2) {
|
||||
int8_t llrOut[NR_LDPC_MAX_NUM_LLR] __attribute__((aligned(64))) = {0};
|
||||
int8_t* p_llrOut = outMode == nrLDPC_outMode_LLRINT8 ? p_out : llrOut;
|
||||
nrLDPC_llrRes2llrOut(p_lut, p_llrOut, llrRes, Z, BG);
|
||||
if (outMode == nrLDPC_outMode_BIT)
|
||||
nrLDPC_llr2bitPacked(p_out, p_llrOut, numLLR);
|
||||
else // if (outMode == nrLDPC_outMode_BITINT8)
|
||||
nrLDPC_llr2bit(p_out, p_llrOut, numLLR);
|
||||
if (p_decParams->check_crc((uint8_t*)p_out, p_decParams->E, p_decParams->crc_type)) {
|
||||
LOG_D(PHY, "Segment CRC OK, exiting LDPC decoder\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#ifdef NR_LDPC_ENABLE_PARITY_CHECK
|
||||
{
|
||||
if (!p_decParams->check_crc) {
|
||||
int8_t llrOut[NR_LDPC_MAX_NUM_LLR] __attribute__((aligned(64))) = {0};
|
||||
int8_t* p_llrOut = outMode == nrLDPC_outMode_LLRINT8 ? p_out : llrOut;
|
||||
// Assign results from processing buffer to output
|
||||
@@ -856,7 +877,6 @@ static inline uint32_t nrLDPC_decoder_core(int8_t* p_llr,
|
||||
nrLDPC_llr2bit(p_out, p_llrOut, numLLR);
|
||||
NR_LDPC_PROFILER_DETAIL(stop_meas(&p_profiler->llr2bit));
|
||||
}
|
||||
#endif
|
||||
return numIter;
|
||||
}
|
||||
|
||||
|
||||
@@ -47,8 +47,7 @@ typedef struct{
|
||||
#include <unistd.h>
|
||||
#include <sys/stat.h>
|
||||
#include <CL/opencl.h>
|
||||
#include "PHY/CODING/nrLDPC_decoder/nrLDPC_types.h"
|
||||
#include "PHY/CODING/nrLDPC_decoder/nrLDPCdecoder_defs.h"
|
||||
#include "openair1/PHY/CODING/nrLDPC_extern.h"
|
||||
#include "assertions.h"
|
||||
#include "common/utils/LOG/log.h"
|
||||
|
||||
@@ -328,18 +327,23 @@ int ldpc_autoinit(void) { // called by the library loader
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void nrLDPC_initcall(t_nrLDPC_dec_params* p_decParams, int8_t* p_llr, int8_t* p_out) {
|
||||
set_compact_BG(p_decParams->Z,p_decParams->BG);
|
||||
// init_LLR_DMA(p_decParams, p_llr, p_out);
|
||||
int32_t LDPCshutdown()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t nrLDPC_decod(t_nrLDPC_dec_params *p_decParams,
|
||||
int8_t *p_llr,
|
||||
int8_t *p_out,
|
||||
t_nrLDPC_procBuf *p_procBuf,
|
||||
t_nrLDPC_time_stats *time_decoder,
|
||||
decode_abort_t *ab)
|
||||
int32_t LDPCinit()
|
||||
{
|
||||
// init_LLR_DMA(p_decParams, p_llr, p_out);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t LDPCdecoder(t_nrLDPC_dec_params *p_decParams,
|
||||
int8_t *p_llr,
|
||||
int8_t *p_out,
|
||||
t_nrLDPC_procBuf *p_procBuf,
|
||||
t_nrLDPC_time_stats *time_decoder,
|
||||
decode_abort_t *ab)
|
||||
{
|
||||
uint16_t Zc = p_decParams->Z;
|
||||
uint8_t BG = p_decParams->BG;
|
||||
@@ -362,9 +366,11 @@ int32_t nrLDPC_decod(t_nrLDPC_dec_params *p_decParams,
|
||||
int memorySize_llr = col * Zc * sizeof(char) * MC;
|
||||
// cudaCheck( cudaMemcpyToSymbol(dev_const_llr, p_llr, memorySize_llr_cuda) );
|
||||
// cudaCheck( cudaMemcpyToSymbol(dev_llr, p_llr, memorySize_llr_cuda) );
|
||||
int rt = clEnqueueWriteBuffer(ocl.runtime[0].queue[0], ocl.runtime[0].dev_const_llr, CL_TRUE, 0,
|
||||
memorySize_llr, p_llr, 0, NULL, NULL);
|
||||
AssertFatal(rt == CL_SUCCESS, "Error %d moving p_llr data to read only memory in pltf %i dev %i\n" , (int)rt, 0,0);
|
||||
set_compact_BG(p_decParams->Z, p_decParams->BG);
|
||||
|
||||
int rt =
|
||||
clEnqueueWriteBuffer(ocl.runtime[0].queue[0], ocl.runtime[0].dev_const_llr, CL_TRUE, 0, memorySize_llr, p_llr, 0, NULL, NULL);
|
||||
AssertFatal(rt == CL_SUCCESS, "Error %d moving p_llr data to read only memory in pltf %i dev %i\n" , (int)rt, 0,0);
|
||||
rt = clEnqueueWriteBuffer(ocl.runtime[0].queue[0], ocl.runtime[0].dev_llr, CL_TRUE, 0,
|
||||
memorySize_llr, p_llr, 0, NULL, NULL);
|
||||
AssertFatal(rt == CL_SUCCESS, "Error %d moving p_llr data to read-write memory in pltf %i dev %i\n" , (int)rt, 0,0);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -85,15 +85,17 @@ typedef struct nrLDPC_dec_params {
|
||||
uint8_t BG; /**< Base graph */
|
||||
uint16_t Z; /**< Lifting size */
|
||||
uint8_t R; /**< Decoding rate: Format 15,13,... for code rates 1/5, 1/3,... */
|
||||
uint16_t F; /**< Filler bits */
|
||||
uint8_t Qm; /**< Modulation */
|
||||
uint8_t rv;
|
||||
uint8_t numMaxIter; /**< Maximum number of iterations */
|
||||
int block_length;
|
||||
int E;
|
||||
e_nrLDPC_outMode outMode; /**< Output format */
|
||||
int crc_type;
|
||||
int (*check_crc)(uint8_t* decoded_bytes, uint32_t n, uint8_t crc_type);
|
||||
} t_nrLDPC_dec_params;
|
||||
|
||||
/**
|
||||
Structure containing LDPC decoder parameters.
|
||||
*/
|
||||
typedef struct nrLDPCoffload_params {
|
||||
uint8_t BG; /**< Base graph */
|
||||
uint16_t Z;
|
||||
|
||||
@@ -524,15 +524,21 @@ int ldpc_autoinit(void) { // called by the library loader
|
||||
return 0;
|
||||
}
|
||||
|
||||
extern "C"
|
||||
void nrLDPC_initcall(t_nrLDPC_dec_params* p_decParams, int8_t* p_llr, int8_t* p_out) {
|
||||
set_compact_BG(p_decParams->Z,p_decParams->BG);
|
||||
init_LLR_DMA(p_decParams, p_llr, p_out);
|
||||
extern "C" void LDPCinit(t_nrLDPC_dec_params* p_decParams, int8_t* p_llr, int8_t* p_out)
|
||||
{
|
||||
set_compact_BG(p_decParams->Z, p_decParams->BG);
|
||||
init_LLR_DMA(p_decParams, p_llr, p_out);
|
||||
}
|
||||
|
||||
extern "C" void LDPCshutdown()
|
||||
{
|
||||
}
|
||||
|
||||
extern "C"
|
||||
int32_t nrLDPC_decod(t_nrLDPC_dec_params* p_decParams, int8_t* p_llr, int8_t* p_out,t_nrLDPC_procBuf* p_procBuf, t_nrLDPC_time_stats *time_decoder)
|
||||
extern "C" int32_t LDPCdecoder(t_nrLDPC_dec_params* p_decParams,
|
||||
int8_t* p_llr,
|
||||
int8_t* p_out,
|
||||
t_nrLDPC_procBuf* p_procBuf,
|
||||
t_nrLDPC_time_stats* time_decoder)
|
||||
{
|
||||
uint16_t Zc = p_decParams->Z;
|
||||
uint8_t BG = p_decParams->BG;
|
||||
|
||||
@@ -47,7 +47,7 @@ typedef struct {
|
||||
time_stats_t *toutput;
|
||||
int Kr;
|
||||
uint32_t Kb;
|
||||
uint32_t *Zc;
|
||||
uint32_t Zc;
|
||||
void *harq;
|
||||
/// Encoder BG
|
||||
uint8_t BG;
|
||||
@@ -57,13 +57,16 @@ typedef struct {
|
||||
uint32_t K;
|
||||
/// Number of "Filler" bits
|
||||
uint32_t F;
|
||||
/// LDPC-code outputs
|
||||
uint8_t *d[MAX_NUM_NR_DLSCH_SEGMENTS_PER_LAYER*NR_MAX_NB_LAYERS];
|
||||
/// Modulation order
|
||||
uint8_t Qm;
|
||||
uint32_t E;
|
||||
unsigned int G;
|
||||
// Redundancy version index
|
||||
uint8_t rv;
|
||||
} encoder_implemparams_t;
|
||||
#define INIT0_LDPCIMPLEMPARAMS {0,0,0,NULL,NULL,NULL,NULL}
|
||||
typedef void(*nrLDPC_initcallfunc_t)(t_nrLDPC_dec_params *p_decParams, int8_t *p_llr, int8_t *p_out);
|
||||
typedef int(*nrLDPC_encoderfunc_t)(unsigned char **,unsigned char **,int,int,short, short, encoder_implemparams_t *);
|
||||
//============================================================================================================================
|
||||
|
||||
typedef int32_t(LDPC_initfunc_t)(void);
|
||||
typedef int32_t(LDPC_shutdownfunc_t)(void);
|
||||
// decoder interface
|
||||
/**
|
||||
\brief LDPC decoder API type definition
|
||||
@@ -73,8 +76,14 @@ typedef int(*nrLDPC_encoderfunc_t)(unsigned char **,unsigned char **,int,int,sho
|
||||
\param p_profiler LDPC profiler statistics
|
||||
*/
|
||||
|
||||
typedef int32_t (*nrLDPC_decoderfunc_t)(t_nrLDPC_dec_params *, int8_t *, int8_t *, t_nrLDPC_time_stats *, decode_abort_t *ab);
|
||||
typedef int32_t(*nrLDPC_decoffloadfunc_t)(t_nrLDPC_dec_params* , uint8_t, uint8_t, uint8_t , uint8_t, uint16_t, uint32_t, uint8_t, int8_t*, int8_t* ,uint8_t);
|
||||
typedef int32_t(*nrLDPC_dectopfunc_t)(void);
|
||||
typedef int32_t(LDPC_decoderfunc_t)(t_nrLDPC_dec_params *p_decParams,
|
||||
uint8_t harq_pid,
|
||||
uint8_t ulsch_id,
|
||||
uint8_t C,
|
||||
int8_t *p_llr,
|
||||
int8_t *p_out,
|
||||
t_nrLDPC_time_stats *,
|
||||
decode_abort_t *ab);
|
||||
typedef int32_t(LDPC_encoderfunc_t)(uint8_t **, uint8_t **, encoder_implemparams_t *);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -38,44 +38,29 @@
|
||||
#include "defs.h"
|
||||
#include "assertions.h"
|
||||
#include "openair1/PHY/CODING/nrLDPC_defs.h"
|
||||
#include "openair1/PHY/CODING/nrLDPC_extern.h"
|
||||
#include "ldpc_generate_coefficient.c"
|
||||
|
||||
|
||||
int ldpc_encoder_orig(uint8_t *test_input,uint8_t *channel_input,int Zc,int Kb,short block_length, short BG,uint8_t gen_code)
|
||||
int LDPCencoder(unsigned char **inputArray, unsigned char **outputArray, encoder_implemparams_t *impp)
|
||||
{
|
||||
const unsigned char *input = inputArray[0];
|
||||
// channel input is the output of this function!
|
||||
unsigned char *output = outputArray[0];
|
||||
const int Zc = impp->Zc;
|
||||
const int Kb = impp->Kb;
|
||||
const short block_length = impp->K;
|
||||
const short BG = impp->BG;
|
||||
const uint8_t gen_code = impp->gen_code;
|
||||
uint8_t c[22*384]; //padded input, unpacked, max size
|
||||
uint8_t d[68*384]; //coded output, unpacked, max size
|
||||
uint8_t channel_temp,temp;
|
||||
short *Gen_shift_values, *no_shift_values, *pointer_shift_values;
|
||||
|
||||
short nrows = 46;//parity check bits
|
||||
short ncols = 22;//info bits
|
||||
|
||||
uint8_t d[68 * 384]; // coded output, unpacked, max size
|
||||
|
||||
int i,i1,i2,i3,i4,i5,temp_prime,var;
|
||||
int no_punctured_columns,removed_bit,rate=3;
|
||||
int no_punctured_columns, removed_bit;
|
||||
int nind=0;
|
||||
int indlist[1000];
|
||||
int indlist2[1000];
|
||||
|
||||
//determine number of bits in codeword
|
||||
//if (block_length>3840)
|
||||
if (BG==1)
|
||||
{
|
||||
nrows=46; //parity check bits
|
||||
ncols=22; //info bits
|
||||
rate=3;
|
||||
}
|
||||
//else if (block_length<=3840)
|
||||
else if (BG==2)
|
||||
{
|
||||
//BG=2;
|
||||
nrows=42; //parity check bits
|
||||
ncols=10; // info bits
|
||||
rate=5;
|
||||
}
|
||||
|
||||
Gen_shift_values=choose_generator_matrix(BG,Zc);
|
||||
const short *Gen_shift_values = choose_generator_matrix(BG, Zc);
|
||||
if (Gen_shift_values==NULL) {
|
||||
printf("ldpc_encoder_orig: could not find generator matrix\n");
|
||||
return(-1);
|
||||
@@ -83,21 +68,14 @@ int ldpc_encoder_orig(uint8_t *test_input,uint8_t *channel_input,int Zc,int Kb,s
|
||||
|
||||
//printf("ldpc_encoder_orig: BG %d, Zc %d, Kb %d\n",BG, Zc, Kb);
|
||||
|
||||
AssertFatal(BG <= 2, "BG %d is not supported yet\n", BG);
|
||||
// load base graph of generator matrix
|
||||
if (BG==1)
|
||||
{
|
||||
no_shift_values=(short *) no_shift_values_BG1;
|
||||
pointer_shift_values=(short *) pointer_shift_values_BG1;
|
||||
}
|
||||
else if (BG==2)
|
||||
{
|
||||
no_shift_values=(short *) no_shift_values_BG2;
|
||||
pointer_shift_values=(short *) pointer_shift_values_BG2;
|
||||
}
|
||||
else {
|
||||
AssertFatal(0,"BG %d is not supported yet\n",BG);
|
||||
}
|
||||
|
||||
const short nrows = BG == 1 ? 46 : 42;
|
||||
const short ncols = BG == 1 ? 22 : 10;
|
||||
const short rate = BG == 1 ? 3 : 5;
|
||||
const short *no_shift_values = BG == 1 ? no_shift_values_BG1 : no_shift_values_BG2;
|
||||
const short *pointer_shift_values = BG == 1 ? pointer_shift_values_BG1 : pointer_shift_values_BG2;
|
||||
|
||||
no_punctured_columns=(int)((nrows-2)*Zc+block_length-block_length*rate)/Zc;
|
||||
removed_bit=(nrows-no_punctured_columns-2) * Zc+block_length-(block_length*rate);
|
||||
//printf("%d\n",no_punctured_columns);
|
||||
@@ -108,9 +86,9 @@ int ldpc_encoder_orig(uint8_t *test_input,uint8_t *channel_input,int Zc,int Kb,s
|
||||
|
||||
for (i=0; i<block_length; i++)
|
||||
{
|
||||
//c[i] = test_input[i/8]<<(i%8);
|
||||
//c[i]=c[i]>>7&1;
|
||||
c[i]=(test_input[i/8]&(128>>(i&7)))>>(7-(i&7));
|
||||
// c[i] = input[i/8]<<(i%8);
|
||||
// c[i]=c[i]>>7&1;
|
||||
c[i] = (input[i / 8] & (128 >> (i & 7))) >> (7 - (i & 7));
|
||||
}
|
||||
|
||||
// parity check part
|
||||
@@ -188,10 +166,9 @@ int ldpc_encoder_orig(uint8_t *test_input,uint8_t *channel_input,int Zc,int Kb,s
|
||||
fprintf(fd2," c2=&csimd[i2];\n");
|
||||
fprintf(fd2," d2=&dsimd[i2];\n");
|
||||
|
||||
for (i1=0; i1 < nrows; i1++)
|
||||
for (i1 = 0; i1 < nrows; i1++)
|
||||
|
||||
{
|
||||
channel_temp=0;
|
||||
fprintf(fd,"\n//row: %d\n",i1);
|
||||
fprintf(fd2,"\n//row: %d\n",i1);
|
||||
fprintf(fd," d2[%d]=",(Zc*i1)>>shift);
|
||||
@@ -225,8 +202,7 @@ int ldpc_encoder_orig(uint8_t *test_input,uint8_t *channel_input,int Zc,int Kb,s
|
||||
fprintf(fd2,"c2[%d]",indlist2[i4]);
|
||||
for (i4=0;i4<nind-1;i4++) { fprintf(fd,")"); fprintf(fd2,")"); }
|
||||
fprintf(fd,";\n");
|
||||
fprintf(fd2,";\n");
|
||||
|
||||
fprintf(fd2, ";\n");
|
||||
}
|
||||
fprintf(fd," }\n}\n");
|
||||
fprintf(fd2," }\n}\n");
|
||||
@@ -243,40 +219,33 @@ int ldpc_encoder_orig(uint8_t *test_input,uint8_t *channel_input,int Zc,int Kb,s
|
||||
//rotate matrix here
|
||||
for (i5=0; i5 < Kb; i5++)
|
||||
{
|
||||
temp = c[i5*Zc];
|
||||
memmove(&c[i5*Zc], &c[i5*Zc+1], (Zc-1)*sizeof(uint8_t));
|
||||
c[i5*Zc+Zc-1] = temp;
|
||||
const int temp = c[i5 * Zc];
|
||||
memmove(&c[i5 * Zc], &c[i5 * Zc + 1], Zc - 1);
|
||||
c[i5 * Zc + Zc - 1] = temp;
|
||||
}
|
||||
|
||||
// calculate each row in base graph
|
||||
for (i1=0; i1 < nrows-no_punctured_columns; i1++)
|
||||
{
|
||||
channel_temp=0;
|
||||
unsigned char channel_temp = 0;
|
||||
|
||||
for (i3=0; i3 < Kb; i3++)
|
||||
{
|
||||
temp_prime=i1 * ncols + i3;
|
||||
for (i3 = 0; i3 < Kb; i3++) {
|
||||
temp_prime = i1 * ncols + i3;
|
||||
|
||||
for (i4=0; i4 < no_shift_values[temp_prime]; i4++)
|
||||
{
|
||||
channel_temp = channel_temp ^ c[ i3*Zc + Gen_shift_values[ pointer_shift_values[temp_prime]+i4 ] ];
|
||||
for (i4 = 0; i4 < no_shift_values[temp_prime]; i4++) {
|
||||
channel_temp = channel_temp ^ c[i3 * Zc + Gen_shift_values[pointer_shift_values[temp_prime] + i4]];
|
||||
}
|
||||
}
|
||||
|
||||
d[i2+i1*Zc]=channel_temp;
|
||||
//channel_input[t+i1*Zc]=channel_temp;
|
||||
// output[t+i1*Zc]=channel_temp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// information part and puncture columns
|
||||
memcpy(&channel_input[0], &c[2*Zc], (block_length-2*Zc)*sizeof(uint8_t));
|
||||
memcpy(&channel_input[block_length-2*Zc], &d[0], ((nrows-no_punctured_columns) * Zc-removed_bit)*sizeof(uint8_t));
|
||||
//memcpy(channel_input,c,Kb*Zc*sizeof(uint8_t));
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int nrLDPC_encod(uint8_t **test_input,uint8_t **channel_input,int Zc,int Kb,short block_length, short BG, encoder_implemparams_t *impp) {
|
||||
return ldpc_encoder_orig(test_input[0],channel_input[0],Zc,Kb,block_length,BG,impp->gen_code);
|
||||
memcpy(&output[0], &c[2 * Zc], block_length - 2 * Zc);
|
||||
memcpy(&output[block_length - 2 * Zc], &d[0], (nrows - no_punctured_columns) * Zc - removed_bit);
|
||||
// memcpy(output,c,Kb*Zc*sizeof(unsigned char));
|
||||
return block_length - 2 * Zc + (nrows - no_punctured_columns) * Zc - removed_bit;
|
||||
}
|
||||
|
||||
@@ -1,656 +0,0 @@
|
||||
/*
|
||||
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.openairinterface.org/?page_id=698
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*-------------------------------------------------------------------------------
|
||||
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
/*!\file ldpc_encoder2.c
|
||||
* \brief Defines the optimized LDPC encoder
|
||||
* \author Florian Kaltenberger, Raymond Knopp, Kien le Trung (Eurecom)
|
||||
* \email openair_tech@eurecom.fr
|
||||
* \date 27-03-2018
|
||||
* \version 1.0
|
||||
* \note
|
||||
* \warning
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <types.h>
|
||||
#include "assertions.h"
|
||||
#include "common/utils/LOG/log.h"
|
||||
#include "time_meas.h"
|
||||
#include "defs.h"
|
||||
#include "PHY/sse_intrin.h"
|
||||
|
||||
#include "ldpc384_byte.c"
|
||||
#include "ldpc352_byte.c"
|
||||
#include "ldpc320_byte.c"
|
||||
#include "ldpc288_byte.c"
|
||||
#include "ldpc256_byte.c"
|
||||
#include "ldpc240_byte.c"
|
||||
#include "ldpc224_byte.c"
|
||||
#include "ldpc208_byte.c"
|
||||
#include "ldpc192_byte.c"
|
||||
#include "ldpc176_byte.c"
|
||||
#include "ldpc384_byte_128.c"
|
||||
#include "ldpc352_byte_128.c"
|
||||
#include "ldpc320_byte_128.c"
|
||||
#include "ldpc288_byte_128.c"
|
||||
#include "ldpc256_byte_128.c"
|
||||
#include "ldpc224_byte_128.c"
|
||||
#include "ldpc192_byte_128.c"
|
||||
#include "ldpc_BG2_Zc384_byte.c"
|
||||
#include "ldpc_BG2_Zc352_byte.c"
|
||||
#include "ldpc_BG2_Zc320_byte.c"
|
||||
#include "ldpc_BG2_Zc288_byte.c"
|
||||
#include "ldpc_BG2_Zc256_byte.c"
|
||||
#include "ldpc_BG2_Zc240_byte.c"
|
||||
#include "ldpc_BG2_Zc224_byte.c"
|
||||
#include "ldpc_BG2_Zc208_byte.c"
|
||||
#include "ldpc_BG2_Zc192_byte.c"
|
||||
#include "ldpc_BG2_Zc176_byte.c"
|
||||
#include "ldpc_BG2_Zc160_byte.c"
|
||||
#include "ldpc_BG2_Zc144_byte.c"
|
||||
#include "ldpc_BG2_Zc128_byte.c"
|
||||
#include "ldpc_BG2_Zc120_byte.c"
|
||||
#include "ldpc_BG2_Zc112_byte.c"
|
||||
#include "ldpc_BG2_Zc104_byte.c"
|
||||
#include "ldpc_BG2_Zc96_byte.c"
|
||||
#include "ldpc_BG2_Zc88_byte.c"
|
||||
#include "ldpc_BG2_Zc80_byte.c"
|
||||
#include "ldpc_BG2_Zc72_byte.c"
|
||||
|
||||
|
||||
|
||||
void encode_parity_check_part_optim(uint8_t *c,uint8_t *d, short BG,short Zc,short Kb)
|
||||
{
|
||||
|
||||
if (BG==1)
|
||||
{
|
||||
switch (Zc)
|
||||
{
|
||||
case 2: break;
|
||||
case 3: break;
|
||||
case 4: break;
|
||||
case 5: break;
|
||||
case 6: break;
|
||||
case 7: break;
|
||||
case 8: break;
|
||||
case 9: break;
|
||||
case 10: break;
|
||||
case 11: break;
|
||||
case 12: break;
|
||||
case 13: break;
|
||||
case 14: break;
|
||||
case 15: break;
|
||||
case 16: break;
|
||||
case 18: break;
|
||||
case 20: break;
|
||||
case 22: break;
|
||||
case 24: break;
|
||||
case 26: break;
|
||||
case 28: break;
|
||||
case 30: break;
|
||||
case 32: break;
|
||||
case 36: break;
|
||||
case 40: break;
|
||||
case 44: break;
|
||||
case 48: break;
|
||||
case 52: break;
|
||||
case 56: break;
|
||||
case 60: break;
|
||||
case 64: break;
|
||||
case 72: break;
|
||||
case 80: break;
|
||||
case 88: break;
|
||||
case 96: break;
|
||||
case 104: break;
|
||||
case 112: break;
|
||||
case 120: break;
|
||||
case 128: break;
|
||||
case 144: break;
|
||||
case 160: break;
|
||||
case 176: ldpc176_byte(c,d); break;
|
||||
case 192: ldpc192_byte(c,d); break;
|
||||
case 208: ldpc208_byte(c,d); break;
|
||||
case 224: ldpc224_byte(c,d); break;
|
||||
case 240: ldpc240_byte(c,d); break;
|
||||
case 256: ldpc256_byte(c,d); break;
|
||||
case 288: ldpc288_byte(c,d); break;
|
||||
case 320: ldpc320_byte(c,d); break;
|
||||
case 352: ldpc352_byte(c,d); break;
|
||||
case 384: ldpc384_byte(c,d); break;
|
||||
default: AssertFatal(0,"BG %d Zc %d is not supported yet\n",BG,Zc); break;
|
||||
}
|
||||
}
|
||||
else if (BG==2) {
|
||||
switch (Zc)
|
||||
{
|
||||
case 2: break;
|
||||
case 3: break;
|
||||
case 4: break;
|
||||
case 5: break;
|
||||
case 6: break;
|
||||
case 7: break;
|
||||
case 8: break;
|
||||
case 9: break;
|
||||
case 10: break;
|
||||
case 11: break;
|
||||
case 12: break;
|
||||
case 13: break;
|
||||
case 14: break;
|
||||
case 15: break;
|
||||
case 16: break;
|
||||
case 18: break;
|
||||
case 20: break;
|
||||
case 22: break;
|
||||
case 24: break;
|
||||
case 26: break;
|
||||
case 28: break;
|
||||
case 30: break;
|
||||
case 32: break;
|
||||
case 36: break;
|
||||
case 40: break;
|
||||
case 44: break;
|
||||
case 48: break;
|
||||
case 52: break;
|
||||
case 56: break;
|
||||
case 60: break;
|
||||
case 64: break;
|
||||
case 72: ldpc_BG2_Zc72_byte(c,d); break;
|
||||
case 80: ldpc_BG2_Zc80_byte(c,d); break;
|
||||
case 88: ldpc_BG2_Zc88_byte(c,d); break;
|
||||
case 96: ldpc_BG2_Zc96_byte(c,d); break;
|
||||
case 104: ldpc_BG2_Zc104_byte(c,d); break;
|
||||
case 112: ldpc_BG2_Zc112_byte(c,d); break;
|
||||
case 120: ldpc_BG2_Zc120_byte(c,d); break;
|
||||
case 128: ldpc_BG2_Zc128_byte(c,d); break;
|
||||
case 144: ldpc_BG2_Zc144_byte(c,d); break;
|
||||
case 160: ldpc_BG2_Zc160_byte(c,d); break;
|
||||
case 176: ldpc_BG2_Zc176_byte(c,d); break;
|
||||
case 192: ldpc_BG2_Zc192_byte(c,d); break;
|
||||
case 208: ldpc_BG2_Zc208_byte(c,d); break;
|
||||
case 224: ldpc_BG2_Zc224_byte(c,d); break;
|
||||
case 240: ldpc_BG2_Zc240_byte(c,d); break;
|
||||
case 256: ldpc_BG2_Zc256_byte(c,d); break;
|
||||
case 288: ldpc_BG2_Zc288_byte(c,d); break;
|
||||
case 320: ldpc_BG2_Zc320_byte(c,d); break;
|
||||
case 352: ldpc_BG2_Zc352_byte(c,d); break;
|
||||
case 384: ldpc_BG2_Zc384_byte(c,d); break;
|
||||
default: AssertFatal(0,"BG %d Zc %d is not supported yet\n",BG,Zc); break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
AssertFatal(0,"BG %d is not supported yet\n",BG);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
int ldpc_encoder_optim(unsigned char *test_input,unsigned char *channel_input,int Zc,int Kb,short block_length,short BG,time_stats_t *tinput,time_stats_t *tprep,time_stats_t *tparity,time_stats_t *toutput)
|
||||
{
|
||||
|
||||
short nrows=0,ncols=0;
|
||||
int i,i1,rate=3;
|
||||
int no_punctured_columns,removed_bit;
|
||||
|
||||
int simd_size;
|
||||
|
||||
//determine number of bits in codeword
|
||||
//if (block_length>3840)
|
||||
if (BG==1)
|
||||
{
|
||||
//BG=1;
|
||||
nrows=46; //parity check bits
|
||||
ncols=22; //info bits
|
||||
rate=3;
|
||||
}
|
||||
//else if (block_length<=3840)
|
||||
else if (BG==2)
|
||||
{
|
||||
//BG=2;
|
||||
nrows=42; //parity check bits
|
||||
ncols=10; // info bits
|
||||
rate=5;
|
||||
|
||||
}
|
||||
|
||||
|
||||
#ifdef DEBUG_LDPC
|
||||
LOG_D(PHY,"ldpc_encoder_optim_8seg: BG %d, Zc %d, Kb %d, block_length %d\n",BG,Zc,Kb,block_length);
|
||||
LOG_D(PHY,"ldpc_encoder_optim_8seg: PDU %x %x %x %x\n",test_input[0],test_input[1],test_input[2],test_input[3]);
|
||||
#endif
|
||||
|
||||
if ((Zc&31) > 0) simd_size = 16;
|
||||
else simd_size = 32;
|
||||
|
||||
unsigned char c[22*Zc] __attribute__((aligned(32))); //padded input, unpacked, max size
|
||||
unsigned char d[46*Zc] __attribute__((aligned(32))); //coded parity part output, unpacked, max size
|
||||
|
||||
unsigned char c_extension[2*22*Zc*simd_size] __attribute__((aligned(32))); //double size matrix of c
|
||||
|
||||
// calculate number of punctured bits
|
||||
no_punctured_columns=(int)((nrows-2)*Zc+block_length-block_length*rate)/Zc;
|
||||
removed_bit=(nrows-no_punctured_columns-2) * Zc+block_length-(int)(block_length*rate);
|
||||
// printf("%d\n",no_punctured_columns);
|
||||
// printf("%d\n",removed_bit);
|
||||
// unpack input
|
||||
memset(c,0,sizeof(unsigned char) * ncols * Zc);
|
||||
memset(d,0,sizeof(unsigned char) * nrows * Zc);
|
||||
|
||||
if(tinput != NULL) start_meas(tinput);
|
||||
for (i=0; i<block_length; i++) {
|
||||
c[i] = (test_input[i/8]&(128>>(i&7)))>>(7-(i&7));
|
||||
//printf("c(%d,%d)=%d\n",j,i,temp);
|
||||
}
|
||||
|
||||
if(tinput != NULL) stop_meas(tinput);
|
||||
|
||||
if ((BG==1 && Zc>176) || (BG==2 && Zc>64)) {
|
||||
// extend matrix
|
||||
if(tprep != NULL) start_meas(tprep);
|
||||
for (i1=0; i1 < ncols; i1++)
|
||||
{
|
||||
memcpy(&c_extension[2*i1*Zc], &c[i1*Zc], Zc*sizeof(unsigned char));
|
||||
memcpy(&c_extension[(2*i1+1)*Zc], &c[i1*Zc], Zc*sizeof(unsigned char));
|
||||
}
|
||||
for (i1=1;i1<simd_size;i1++) {
|
||||
memcpy(&c_extension[(2*ncols*Zc*i1)], &c_extension[i1], (2*ncols*Zc*sizeof(unsigned char))-i1);
|
||||
// memset(&c_extension[(2*ncols*Zc*i1)],0,i1);
|
||||
/*
|
||||
printf("shift %d: ",i1);
|
||||
for (int j=0;j<64;j++) printf("%d ",c_extension[(2*ncols*Zc*i1)+j]);
|
||||
printf("\n");
|
||||
*/
|
||||
}
|
||||
if(tprep != NULL) stop_meas(tprep);
|
||||
//parity check part
|
||||
if(tparity != NULL) start_meas(tparity);
|
||||
encode_parity_check_part_optim(c_extension, d, BG, Zc, Kb);
|
||||
if(tparity != NULL) stop_meas(tparity);
|
||||
}
|
||||
else {
|
||||
if (encode_parity_check_part_orig(c, d, BG, Zc, Kb, block_length)!=0) {
|
||||
printf("Problem with encoder\n");
|
||||
return(-1);
|
||||
}
|
||||
}
|
||||
if(toutput != NULL) start_meas(toutput);
|
||||
// information part and puncture columns
|
||||
memcpy(&channel_input[0], &c[2*Zc], (block_length-2*Zc)*sizeof(unsigned char));
|
||||
memcpy(&channel_input[block_length-2*Zc], &d[0], ((nrows-no_punctured_columns) * Zc-removed_bit)*sizeof(unsigned char));
|
||||
|
||||
if(toutput != NULL) stop_meas(toutput);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ldpc_encoder_optim_8seg(unsigned char **test_input,unsigned char **channel_input,int Zc,int Kb,short block_length,short BG,int n_segments,time_stats_t *tinput,time_stats_t *tprep,time_stats_t *tparity,time_stats_t *toutput)
|
||||
{
|
||||
|
||||
short nrows=0,ncols=0;
|
||||
int i,i1,j,rate=3;
|
||||
int no_punctured_columns,removed_bit;
|
||||
char temp;
|
||||
int simd_size;
|
||||
|
||||
simde__m256i shufmask = simde_mm256_set_epi64x(0x0303030303030303, 0x0202020202020202, 0x0101010101010101, 0x0000000000000000);
|
||||
simde__m256i andmask = simde_mm256_set1_epi64x(0x0102040810204080); // every 8 bits -> 8 bytes, pattern repeats.
|
||||
simde__m256i zero256 = simde_mm256_setzero_si256();
|
||||
simde__m256i masks[8];
|
||||
register simde__m256i c256;
|
||||
masks[0] = simde_mm256_set1_epi8(0x1);
|
||||
masks[1] = simde_mm256_set1_epi8(0x2);
|
||||
masks[2] = simde_mm256_set1_epi8(0x4);
|
||||
masks[3] = simde_mm256_set1_epi8(0x8);
|
||||
masks[4] = simde_mm256_set1_epi8(0x10);
|
||||
masks[5] = simde_mm256_set1_epi8(0x20);
|
||||
masks[6] = simde_mm256_set1_epi8(0x40);
|
||||
masks[7] = simde_mm256_set1_epi8(0x80);
|
||||
|
||||
AssertFatal(n_segments>0&&n_segments<=8,"0 < n_segments %d <= 8\n",n_segments);
|
||||
|
||||
//determine number of bits in codeword
|
||||
//if (block_length>3840)
|
||||
if (BG==1)
|
||||
{
|
||||
nrows=46; //parity check bits
|
||||
ncols=22; //info bits
|
||||
rate=3;
|
||||
}
|
||||
//else if (block_length<=3840)
|
||||
else if (BG==2)
|
||||
{
|
||||
//BG=2;
|
||||
nrows=42; //parity check bits
|
||||
ncols=10; // info bits
|
||||
rate=5;
|
||||
|
||||
}
|
||||
|
||||
#ifdef DEBUG_LDPC
|
||||
LOG_D(PHY,"ldpc_encoder_optim_8seg: BG %d, Zc %d, Kb %d, block_length %d, segments %d\n",BG,Zc,Kb,block_length,n_segments);
|
||||
LOG_D(PHY,"ldpc_encoder_optim_8seg: PDU (seg 0) %x %x %x %x\n",test_input[0][0],test_input[0][1],test_input[0][2],test_input[0][3]);
|
||||
#endif
|
||||
|
||||
AssertFatal(Zc>0,"no valid Zc found for block length %d\n",block_length);
|
||||
|
||||
if ((Zc&31) > 0) simd_size = 16;
|
||||
else simd_size = 32;
|
||||
|
||||
unsigned char c[22*Zc] __attribute__((aligned(32))); //padded input, unpacked, max size
|
||||
unsigned char d[46*Zc] __attribute__((aligned(32))); //coded parity part output, unpacked, max size
|
||||
|
||||
unsigned char c_extension[2*22*Zc*simd_size] __attribute__((aligned(32))); //double size matrix of c
|
||||
|
||||
// calculate number of punctured bits
|
||||
no_punctured_columns=(int)((nrows-2)*Zc+block_length-block_length*rate)/Zc;
|
||||
removed_bit=(nrows-no_punctured_columns-2) * Zc+block_length-(int)(block_length*rate);
|
||||
// printf("%d\n",no_punctured_columns);
|
||||
// printf("%d\n",removed_bit);
|
||||
// unpack input
|
||||
memset(c,0,sizeof(unsigned char) * ncols * Zc);
|
||||
memset(d,0,sizeof(unsigned char) * nrows * Zc);
|
||||
|
||||
if(tinput != NULL) start_meas(tinput);
|
||||
#if 0
|
||||
for (i=0; i<block_length; i++) {
|
||||
for (j=0; j<n_segments; j++) {
|
||||
|
||||
temp = (test_input[j][i/8]&(128>>(i&7)))>>(7-(i&7));
|
||||
//printf("c(%d,%d)=%d\n",j,i,temp);
|
||||
c[i] |= (temp << j);
|
||||
}
|
||||
}
|
||||
#else
|
||||
for (i=0; i<block_length>>5; i++) {
|
||||
c256 = simde_mm256_and_si256(simde_mm256_cmpeq_epi8(simde_mm256_andnot_si256(simde_mm256_shuffle_epi8(simde_mm256_set1_epi32(((uint32_t*)test_input[0])[i]), shufmask),andmask),zero256),masks[0]);
|
||||
for (j=1; j<n_segments; j++) {
|
||||
c256 = simde_mm256_or_si256(simde_mm256_and_si256(simde_mm256_cmpeq_epi8(simde_mm256_andnot_si256(simde_mm256_shuffle_epi8(simde_mm256_set1_epi32(((uint32_t*)test_input[j])[i]), shufmask),andmask),zero256),masks[j]),c256);
|
||||
}
|
||||
((simde__m256i *)c)[i] = c256;
|
||||
}
|
||||
|
||||
for (i=(block_length>>5)<<5;i<block_length;i++) {
|
||||
for (j=0; j<n_segments; j++) {
|
||||
|
||||
temp = (test_input[j][i/8]&(128>>(i&7)))>>(7-(i&7));
|
||||
//printf("c(%d,%d)=%d\n",j,i,temp);
|
||||
c[i] |= (temp << j);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if(tinput != NULL) stop_meas(tinput);
|
||||
|
||||
if ((BG==1 && Zc>176) || (BG==2 && Zc>64)) {
|
||||
// extend matrix
|
||||
if(tprep != NULL) start_meas(tprep);
|
||||
for (i1=0; i1 < ncols; i1++)
|
||||
{
|
||||
memcpy(&c_extension[2*i1*Zc], &c[i1*Zc], Zc*sizeof(unsigned char));
|
||||
memcpy(&c_extension[(2*i1+1)*Zc], &c[i1*Zc], Zc*sizeof(unsigned char));
|
||||
}
|
||||
for (i1=1;i1<simd_size;i1++) {
|
||||
memcpy(&c_extension[(2*ncols*Zc*i1)], &c_extension[i1], (2*ncols*Zc*sizeof(unsigned char))-i1);
|
||||
// memset(&c_extension[(2*ncols*Zc*i1)],0,i1);
|
||||
/*
|
||||
printf("shift %d: ",i1);
|
||||
for (int j=0;j<64;j++) printf("%d ",c_extension[(2*ncols*Zc*i1)+j]);
|
||||
printf("\n");
|
||||
*/
|
||||
}
|
||||
if(tprep != NULL) stop_meas(tprep);
|
||||
//parity check part
|
||||
if(tparity != NULL) start_meas(tparity);
|
||||
encode_parity_check_part_optim(c_extension, d, BG, Zc, Kb);
|
||||
if(tparity != NULL) stop_meas(tparity);
|
||||
}
|
||||
else {
|
||||
if (encode_parity_check_part_orig(c, d, BG, Zc, Kb, block_length)!=0) {
|
||||
printf("Problem with encoder\n");
|
||||
return(-1);
|
||||
}
|
||||
}
|
||||
if(toutput != NULL) start_meas(toutput);
|
||||
// information part and puncture columns
|
||||
/*
|
||||
memcpy(&channel_input[0], &c[2*Zc], (block_length-2*Zc)*sizeof(unsigned char));
|
||||
memcpy(&channel_input[block_length-2*Zc], &d[0], ((nrows-no_punctured_columns) * Zc-removed_bit)*sizeof(unsigned char));
|
||||
*/
|
||||
if ((((2*Zc)&31) == 0) && (((block_length-(2*Zc))&31) == 0)) {
|
||||
//AssertFatal(((2*Zc)&31) == 0,"2*Zc needs to be a multiple of 32 for now\n");
|
||||
//AssertFatal(((block_length-(2*Zc))&31) == 0,"block_length-(2*Zc) needs to be a multiple of 32 for now\n");
|
||||
uint32_t l1 = (block_length-(2*Zc))>>5;
|
||||
uint32_t l2 = ((nrows-no_punctured_columns) * Zc-removed_bit)>>5;
|
||||
simde__m256i *c256p = (simde__m256i *)&c[2 * Zc];
|
||||
simde__m256i *d256p = (simde__m256i *)&d[0];
|
||||
// if (((block_length-(2*Zc))&31)>0) l1++;
|
||||
|
||||
for (i=0;i<l1;i++)
|
||||
for (j = 0; j < n_segments; j++)
|
||||
((simde__m256i *)channel_input[j])[i] = simde_mm256_and_si256(simde_mm256_srai_epi16(c256p[i], j), masks[0]);
|
||||
|
||||
// if ((((nrows-no_punctured_columns) * Zc-removed_bit)&31)>0) l2++;
|
||||
|
||||
for (i1=0;i1<l2;i1++,i++)
|
||||
for (j = 0; j < n_segments; j++)
|
||||
((simde__m256i *)channel_input[j])[i] = simde_mm256_and_si256(simde_mm256_srai_epi16(d256p[i1], j), masks[0]);
|
||||
}
|
||||
else {
|
||||
#ifdef DEBUG_LDPC
|
||||
LOG_W(PHY,"using non-optimized version\n");
|
||||
#endif
|
||||
// do non-SIMD version
|
||||
for (i=0;i<(block_length-2*Zc);i++)
|
||||
for (j=0; j<n_segments; j++)
|
||||
channel_input[j][i] = (c[2*Zc+i]>>j)&1;
|
||||
for (i=0;i<((nrows-no_punctured_columns) * Zc-removed_bit);i++)
|
||||
for (j=0; j<n_segments; j++)
|
||||
channel_input[j][block_length-2*Zc+i] = (d[i]>>j)&1;
|
||||
}
|
||||
|
||||
if(toutput != NULL) stop_meas(toutput);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ldpc_encoder_optim_8seg_multi(unsigned char **test_input,unsigned char **channel_input,int Zc,int Kb,short block_length, short BG, int n_segments,unsigned int macro_num, time_stats_t *tinput,time_stats_t *tprep,time_stats_t *tparity,time_stats_t *toutput)
|
||||
{
|
||||
|
||||
short nrows=0,ncols=0;
|
||||
int i,i1,j,rate=3;
|
||||
int no_punctured_columns,removed_bit;
|
||||
//Table of possible lifting sizes
|
||||
char temp;
|
||||
int simd_size;
|
||||
unsigned int macro_segment, macro_segment_end;
|
||||
|
||||
|
||||
macro_segment = 8*macro_num;
|
||||
macro_segment_end = (n_segments > 8*(macro_num+1)) ? 8*(macro_num+1) : n_segments;
|
||||
//macro_segment_end = macro_segment + (n_segments > 8 ? 8 : n_segments);
|
||||
//printf("macro_segment: %d\n", macro_segment);
|
||||
//printf("macro_segment_end: %d\n", macro_segment_end );
|
||||
|
||||
simde__m256i shufmask = simde_mm256_set_epi64x(0x0303030303030303, 0x0202020202020202, 0x0101010101010101, 0x0000000000000000);
|
||||
simde__m256i andmask = simde_mm256_set1_epi64x(0x0102040810204080); // every 8 bits -> 8 bytes, pattern repeats.
|
||||
simde__m256i zero256 = simde_mm256_setzero_si256();
|
||||
simde__m256i masks[8];
|
||||
register simde__m256i c256;
|
||||
masks[0] = simde_mm256_set1_epi8(0x1);
|
||||
masks[1] = simde_mm256_set1_epi8(0x2);
|
||||
masks[2] = simde_mm256_set1_epi8(0x4);
|
||||
masks[3] = simde_mm256_set1_epi8(0x8);
|
||||
masks[4] = simde_mm256_set1_epi8(0x10);
|
||||
masks[5] = simde_mm256_set1_epi8(0x20);
|
||||
masks[6] = simde_mm256_set1_epi8(0x40);
|
||||
masks[7] = simde_mm256_set1_epi8(0x80);
|
||||
|
||||
//determine number of bits in codeword
|
||||
if (BG==1)
|
||||
{
|
||||
nrows=46; //parity check bits
|
||||
ncols=22; //info bits
|
||||
rate=3;
|
||||
}
|
||||
else if (BG==2)
|
||||
{
|
||||
nrows=42; //parity check bits
|
||||
ncols=10; // info bits
|
||||
rate=5;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_LDPC
|
||||
LOG_D(PHY,"ldpc_encoder_optim_8seg: BG %d, Zc %d, Kb %d, block_length %d, segments %d\n",BG,Zc,Kb,block_length,n_segments);
|
||||
LOG_D(PHY,"ldpc_encoder_optim_8seg: PDU (seg 0) %x %x %x %x\n",test_input[0][0],test_input[0][1],test_input[0][2],test_input[0][3]);
|
||||
#endif
|
||||
|
||||
AssertFatal(Zc>0,"no valid Zc found for block length %d\n",block_length);
|
||||
|
||||
if ((Zc&31) > 0) simd_size = 16;
|
||||
else simd_size = 32;
|
||||
|
||||
unsigned char c[22*Zc] __attribute__((aligned(32))); //padded input, unpacked, max size
|
||||
unsigned char d[46*Zc] __attribute__((aligned(32))); //coded parity part output, unpacked, max size
|
||||
|
||||
unsigned char c_extension[2*22*Zc*simd_size] __attribute__((aligned(32))); //double size matrix of c
|
||||
|
||||
// calculate number of punctured bits
|
||||
no_punctured_columns=(int)((nrows-2)*Zc+block_length-block_length*rate)/Zc;
|
||||
removed_bit=(nrows-no_punctured_columns-2) * Zc+block_length-(int)(block_length*rate);
|
||||
//printf("%d\n",no_punctured_columns);
|
||||
//printf("%d\n",removed_bit);
|
||||
// unpack input
|
||||
memset(c,0,sizeof(unsigned char) * ncols * Zc);
|
||||
memset(d,0,sizeof(unsigned char) * nrows * Zc);
|
||||
|
||||
if(tinput != NULL) start_meas(tinput);
|
||||
#if 0
|
||||
for (i=0; i<block_length; i++) {
|
||||
//for (j=0; j<n_segments; j++) {
|
||||
for (j=macro_segment; j < macro_segment_end; j++) {
|
||||
|
||||
temp = (test_input[j][i/8]&(1<<(i&7)))>>(i&7);
|
||||
//printf("c(%d,%d)=%d\n",j,i,temp);
|
||||
c[i] |= (temp << (j-macro_segment));
|
||||
}
|
||||
}
|
||||
#else
|
||||
for (i=0; i<block_length>>5; i++) {
|
||||
c256 = simde_mm256_and_si256(simde_mm256_cmpeq_epi8(simde_mm256_andnot_si256(simde_mm256_shuffle_epi8(simde_mm256_set1_epi32(((uint32_t*)test_input[macro_segment])[i]), shufmask),andmask),zero256),masks[0]);
|
||||
//for (j=1; j<n_segments; j++) {
|
||||
for (j=macro_segment+1; j < macro_segment_end; j++) {
|
||||
c256 = simde_mm256_or_si256(simde_mm256_and_si256(simde_mm256_cmpeq_epi8(simde_mm256_andnot_si256(simde_mm256_shuffle_epi8(simde_mm256_set1_epi32(((uint32_t*)test_input[j])[i]), shufmask),andmask),zero256),masks[j-macro_segment]),c256);
|
||||
}
|
||||
((simde__m256i *)c)[i] = c256;
|
||||
}
|
||||
|
||||
for (i=(block_length>>5)<<5;i<block_length;i++) {
|
||||
//for (j=0; j<n_segments; j++) {
|
||||
for (j=macro_segment; j < macro_segment_end; j++) {
|
||||
|
||||
temp = (test_input[j][i/8]&(128>>(i&7)))>>(7-(i&7));
|
||||
//printf("c(%d,%d)=%d\n",j,i,temp);
|
||||
c[i] |= (temp << (j-macro_segment));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if(tinput != NULL) stop_meas(tinput);
|
||||
|
||||
if ((BG==1 && Zc>176) || (BG==2 && Zc>64)) {
|
||||
// extend matrix
|
||||
if(tprep != NULL) start_meas(tprep);
|
||||
for (i1=0; i1 < ncols; i1++)
|
||||
{
|
||||
memcpy(&c_extension[2*i1*Zc], &c[i1*Zc], Zc*sizeof(unsigned char));
|
||||
memcpy(&c_extension[(2*i1+1)*Zc], &c[i1*Zc], Zc*sizeof(unsigned char));
|
||||
}
|
||||
for (i1=1;i1<simd_size;i1++) {
|
||||
memcpy(&c_extension[(2*ncols*Zc*i1)], &c_extension[i1], (2*ncols*Zc*sizeof(unsigned char))-i1);
|
||||
// memset(&c_extension[(2*ncols*Zc*i1)],0,i1);
|
||||
/*
|
||||
printf("shift %d: ",i1);
|
||||
for (int j=0;j<64;j++) printf("%d ",c_extension[(2*ncols*Zc*i1)+j]);
|
||||
printf("\n");
|
||||
*/
|
||||
}
|
||||
if(tprep != NULL) stop_meas(tprep);
|
||||
//parity check part
|
||||
if(tparity != NULL) start_meas(tparity);
|
||||
encode_parity_check_part_optim(c_extension, d, BG, Zc, Kb);
|
||||
if(tparity != NULL) stop_meas(tparity);
|
||||
}
|
||||
else {
|
||||
if (encode_parity_check_part_orig(c, d, BG, Zc, Kb, block_length)!=0) {
|
||||
printf("Problem with encoder\n");
|
||||
return(-1);
|
||||
}
|
||||
}
|
||||
if(toutput != NULL) start_meas(toutput);
|
||||
// information part and puncture columns
|
||||
/*
|
||||
memcpy(&channel_input[0], &c[2*Zc], (block_length-2*Zc)*sizeof(unsigned char));
|
||||
memcpy(&channel_input[block_length-2*Zc], &d[0], ((nrows-no_punctured_columns) * Zc-removed_bit)*sizeof(unsigned char));
|
||||
*/
|
||||
if ((((2*Zc)&31) == 0) && (((block_length-(2*Zc))&31) == 0)) {
|
||||
//AssertFatal(((2*Zc)&31) == 0,"2*Zc needs to be a multiple of 32 for now\n");
|
||||
//AssertFatal(((block_length-(2*Zc))&31) == 0,"block_length-(2*Zc) needs to be a multiple of 32 for now\n");
|
||||
uint32_t l1 = (block_length-(2*Zc))>>5;
|
||||
uint32_t l2 = ((nrows-no_punctured_columns) * Zc-removed_bit)>>5;
|
||||
simde__m256i *c256p = (simde__m256i *)&c[2 * Zc];
|
||||
simde__m256i *d256p = (simde__m256i *)&d[0];
|
||||
// if (((block_length-(2*Zc))&31)>0) l1++;
|
||||
|
||||
for (i=0;i<l1;i++)
|
||||
// for (j=0;j<n_segments;j++) ((simde__m256i *)channel_input[j])[i] =
|
||||
// simde_mm256_and_si256(simde_mm256_srai_epi16(c256p[i],j),masks[0]);
|
||||
for (j = macro_segment; j < macro_segment_end; j++)
|
||||
((simde__m256i *)channel_input[j])[i] =
|
||||
simde_mm256_and_si256(simde_mm256_srai_epi16(c256p[i], j - macro_segment), masks[0]);
|
||||
|
||||
// if ((((nrows-no_punctured_columns) * Zc-removed_bit)&31)>0) l2++;
|
||||
|
||||
for (i1=0;i1<l2;i1++,i++)
|
||||
// for (j=0;j<n_segments;j++) ((simde__m256i *)channel_input[j])[i] =
|
||||
// simde_mm256_and_si256(simde_mm256_srai_epi16(d256p[i1],j),masks[0]);
|
||||
for (j = macro_segment; j < macro_segment_end; j++)
|
||||
((simde__m256i *)channel_input[j])[i] =
|
||||
simde_mm256_and_si256(simde_mm256_srai_epi16(d256p[i1], j - macro_segment), masks[0]);
|
||||
}
|
||||
else {
|
||||
#ifdef DEBUG_LDPC
|
||||
LOG_W(PHY,"using non-optimized version\n");
|
||||
#endif
|
||||
// do non-SIMD version
|
||||
for (i=0;i<(block_length-2*Zc);i++)
|
||||
//for (j=0; j<n_segments; j++)
|
||||
for (j=macro_segment; j < macro_segment_end; j++)
|
||||
channel_input[j][i] = (c[2*Zc+i]>>(j-macro_segment))&1;
|
||||
for (i=0;i<((nrows-no_punctured_columns) * Zc-removed_bit);i++)
|
||||
//for (j=0; j<n_segments; j++)
|
||||
for (j=macro_segment; j < macro_segment_end; j++)
|
||||
channel_input[j][block_length-2*Zc+i] = (d[i]>>(j-macro_segment))&1;
|
||||
}
|
||||
|
||||
if(toutput != NULL) stop_meas(toutput);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -37,15 +37,17 @@
|
||||
#include "common/utils/LOG/log.h"
|
||||
#include "time_meas.h"
|
||||
#include "openair1/PHY/CODING/nrLDPC_defs.h"
|
||||
#include "openair1/PHY/CODING/nrLDPC_extern.h"
|
||||
#include "ldpc_encode_parity_check.c"
|
||||
#include "ldpc_generate_coefficient.c"
|
||||
|
||||
|
||||
|
||||
int nrLDPC_encod(unsigned char **test_input,unsigned char **channel_input,int Zc,int Kb,short block_length, short BG, encoder_implemparams_t *impp)
|
||||
int LDPCencoder(uint8_t **test_input, uint8_t **channel_input, encoder_implemparams_t *impp)
|
||||
{
|
||||
|
||||
short nrows=0,ncols=0;
|
||||
int Zc = impp->Zc;
|
||||
int Kb = impp->Kb;
|
||||
int block_length = impp->K;
|
||||
int BG = impp->BG;
|
||||
int nrows=0,ncols=0;
|
||||
int rate=3;
|
||||
int no_punctured_columns,removed_bit;
|
||||
|
||||
@@ -79,17 +81,17 @@ int nrLDPC_encod(unsigned char **test_input,unsigned char **channel_input,int Zc
|
||||
if ((Zc&31) > 0) simd_size = 16;
|
||||
else simd_size = 32;
|
||||
|
||||
unsigned char c[22*Zc] __attribute__((aligned(32))); //padded input, unpacked, max size
|
||||
unsigned char d[46*Zc] __attribute__((aligned(32))); //coded parity part output, unpacked, max size
|
||||
uint8_t c[22*Zc] __attribute__((aligned(32))); //padded input, unpacked, max size
|
||||
uint8_t d[46*Zc] __attribute__((aligned(32))); //coded parity part output, unpacked, max size
|
||||
|
||||
// calculate number of punctured bits
|
||||
no_punctured_columns=(int)((nrows-2)*Zc+block_length-block_length*rate)/Zc;
|
||||
removed_bit=(nrows-no_punctured_columns-2) * Zc+block_length-(int)(block_length*rate);
|
||||
removed_bit = (nrows - no_punctured_columns - 2) * Zc + block_length - block_length * rate;
|
||||
// printf("%d\n",no_punctured_columns);
|
||||
// printf("%d\n",removed_bit);
|
||||
// unpack input
|
||||
memset(c,0,sizeof(unsigned char) * ncols * Zc);
|
||||
memset(d,0,sizeof(unsigned char) * nrows * Zc);
|
||||
memset(c, 0, sizeof(c));
|
||||
memset(d, 0, sizeof(d));
|
||||
|
||||
if(impp->tinput != NULL) start_meas(impp->tinput);
|
||||
for (int i=0; i<block_length; i++) {
|
||||
|
||||
@@ -37,13 +37,17 @@
|
||||
#include "common/utils/LOG/log.h"
|
||||
#include "time_meas.h"
|
||||
#include "openair1/PHY/CODING/nrLDPC_defs.h"
|
||||
#include "openair1/PHY/CODING/nrLDPC_extern.h"
|
||||
#include "ldpc_encode_parity_check.c"
|
||||
#include "ldpc_generate_coefficient.c"
|
||||
#include "PHY/sse_intrin.h"
|
||||
|
||||
|
||||
int nrLDPC_encod(unsigned char **test_input,unsigned char **channel_input,int Zc,int Kb,short block_length, short BG, encoder_implemparams_t *impp)
|
||||
int LDPCencoder(uint8_t **test_input, uint8_t **channel_input, encoder_implemparams_t *impp)
|
||||
{
|
||||
int Zc = impp->Zc;
|
||||
int Kb = impp->Kb;
|
||||
short block_length = impp->K;
|
||||
short BG = impp->BG;
|
||||
|
||||
short nrows=0,ncols=0;
|
||||
int i,i1,j,rate=3;
|
||||
|
||||
@@ -38,15 +38,19 @@
|
||||
#include "time_meas.h"
|
||||
#include "openair1/PHY/CODING/nrLDPC_defs.h"
|
||||
#include "PHY/sse_intrin.h"
|
||||
#include "openair1/PHY/CODING/nrLDPC_extern.h"
|
||||
|
||||
#include "ldpc_encode_parity_check.c"
|
||||
#include "ldpc_generate_coefficient.c"
|
||||
|
||||
|
||||
int nrLDPC_encod(unsigned char **input,unsigned char **output,int Zc,int Kb,short block_length, short BG, encoder_implemparams_t *impp)
|
||||
int LDPCencoder(uint8_t **input, uint8_t **output, encoder_implemparams_t *impp)
|
||||
{
|
||||
//set_log(PHY, 4);
|
||||
|
||||
|
||||
int Zc = impp->Zc;
|
||||
int Kb = impp->Kb;
|
||||
short block_length = impp->K;
|
||||
short BG = impp->BG;
|
||||
|
||||
int nrows=0,ncols=0;
|
||||
int rate=3;
|
||||
|
||||
@@ -18,28 +18,29 @@
|
||||
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
#ifndef _NRLDPC_EXTERN_H__
|
||||
#define _NRLDPC_EXTERN_H__
|
||||
#include "openair1/PHY/CODING/nrLDPC_defs.h"
|
||||
|
||||
#ifdef LDPC_LOADER
|
||||
nrLDPC_decoderfunc_t nrLDPC_decoder;
|
||||
nrLDPC_encoderfunc_t nrLDPC_encoder;
|
||||
nrLDPC_initcallfunc_t nrLDPC_initcall;
|
||||
nrLDPC_decoffloadfunc_t nrLDPC_decoder_offload;
|
||||
nrLDPC_dectopfunc_t top_testsuite;
|
||||
#else
|
||||
/* ldpc coder/decoder API*/
|
||||
typedef struct ldpc_interface_s {
|
||||
LDPC_initfunc_t *LDPCinit;
|
||||
LDPC_shutdownfunc_t *LDPCshutdown;
|
||||
LDPC_decoderfunc_t *LDPCdecoder;
|
||||
LDPC_encoderfunc_t *LDPCencoder;
|
||||
} ldpc_interface_t;
|
||||
|
||||
// Global var to limit the rework of the dirty legacy code
|
||||
extern ldpc_interface_t ldpc_interface, ldpc_interface_offload;
|
||||
|
||||
/* functions to load the LDPC shared lib, implemented in openair1/PHY/CODING/nrLDPC_load.c */
|
||||
int load_nrLDPClib(char *version);
|
||||
int load_nrLDPClib_offload(void);
|
||||
int free_nrLDPClib_offload(void);
|
||||
int load_nrLDPClib_ref(char *libversion, nrLDPC_encoderfunc_t *nrLDPC_encoder_ptr); // for ldpctest
|
||||
/* ldpc coder/decoder functions, as loaded by load_nrLDPClib(). */
|
||||
extern nrLDPC_initcallfunc_t nrLDPC_initcall;
|
||||
int load_LDPClib(char *version, ldpc_interface_t *);
|
||||
int free_LDPClib(ldpc_interface_t *ldpc_interface);
|
||||
|
||||
extern nrLDPC_decoderfunc_t nrLDPC_decoder;
|
||||
extern nrLDPC_encoderfunc_t nrLDPC_encoder;
|
||||
extern nrLDPC_decoffloadfunc_t nrLDPC_decoder_offload;
|
||||
|
||||
extern nrLDPC_dectopfunc_t top_testsuite;
|
||||
LDPC_initfunc_t LDPCinit;
|
||||
LDPC_shutdownfunc_t LDPCshutdown;
|
||||
LDPC_decoderfunc_t LDPCdecoder;
|
||||
LDPC_encoderfunc_t LDPCencoder;
|
||||
|
||||
// inline functions:
|
||||
#endif
|
||||
|
||||
@@ -35,20 +35,16 @@
|
||||
#include <malloc.h>
|
||||
#include "assertions.h"
|
||||
#include "common/utils/LOG/log.h"
|
||||
#define LDPC_LOADER
|
||||
#include "PHY/CODING/nrLDPC_extern.h"
|
||||
#include "common/config/config_userapi.h"
|
||||
#include "common/utils/load_module_shlib.h"
|
||||
|
||||
|
||||
/* function description array, to be used when loading the encoding/decoding shared lib */
|
||||
static loader_shlibfunc_t shlib_fdesc[3];
|
||||
#include "common/config/config_userapi.h"
|
||||
#include "common/utils/load_module_shlib.h"
|
||||
|
||||
/* arguments used when called from phy simulators exec's which do not use the config module */
|
||||
/* arg is used to initialize the config module so that the loader works as expected */
|
||||
char *arg[64]={"ldpctest",NULL};
|
||||
|
||||
int load_nrLDPClib(char *version) {
|
||||
int load_LDPClib(char *version, ldpc_interface_t *itf)
|
||||
{
|
||||
char *ptr = (char *)config_get_if();
|
||||
char libname[64] = "ldpc";
|
||||
|
||||
@@ -56,76 +52,25 @@ int load_nrLDPClib(char *version) {
|
||||
load_configmodule(1, arg, CONFIG_ENABLECMDLINEONLY);
|
||||
logInit();
|
||||
}
|
||||
shlib_fdesc[0].fname = "nrLDPC_decod";
|
||||
shlib_fdesc[1].fname = "nrLDPC_encod";
|
||||
shlib_fdesc[2].fname = "nrLDPC_initcall";
|
||||
/* function description array, to be used when loading the encoding/decoding shared lib */
|
||||
loader_shlibfunc_t shlib_fdesc[] = {{.fname = "LDPCinit"},
|
||||
{.fname = "LDPCshutdown"},
|
||||
{.fname = "LDPCdecoder"},
|
||||
{.fname = "LDPCencoder"}};
|
||||
int ret;
|
||||
ret = load_module_version_shlib(libname, version, shlib_fdesc, sizeofArray(shlib_fdesc), NULL);
|
||||
AssertFatal((ret >= 0), "Error loading ldpc decoder");
|
||||
nrLDPC_decoder = (nrLDPC_decoderfunc_t)shlib_fdesc[0].fptr;
|
||||
nrLDPC_encoder = (nrLDPC_encoderfunc_t)shlib_fdesc[1].fptr;
|
||||
nrLDPC_initcall = (nrLDPC_initcallfunc_t)shlib_fdesc[2].fptr;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int load_nrLDPClib_offload(void) {
|
||||
loader_shlibfunc_t shlib_decoffload_fdesc;
|
||||
|
||||
shlib_decoffload_fdesc.fname = "nrLDPC_decod_offload";
|
||||
int ret=load_module_shlib("ldpc_t1",&shlib_decoffload_fdesc,1,NULL);
|
||||
AssertFatal( (ret >= 0),"Error loading ldpc decoder offload");
|
||||
nrLDPC_decoder_offload = (nrLDPC_decoffloadfunc_t)shlib_decoffload_fdesc.fptr;
|
||||
|
||||
t_nrLDPC_dec_params decParams;
|
||||
t_nrLDPC_dec_params* p_decParams = &decParams;
|
||||
int8_t l[68*384];
|
||||
int8_t llrProcBuf[22*384];
|
||||
|
||||
p_decParams->Z = 384;
|
||||
p_decParams->BG = 1;
|
||||
|
||||
AssertFatal(nrLDPC_decoder_offload(p_decParams,0, 0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
25344,
|
||||
8,
|
||||
l,
|
||||
llrProcBuf, 0)>=0,
|
||||
"error loading LDPC decoder offload library\n");
|
||||
itf->LDPCinit = (LDPC_initfunc_t *)shlib_fdesc[0].fptr;
|
||||
itf->LDPCshutdown = (LDPC_shutdownfunc_t *)shlib_fdesc[1].fptr;
|
||||
itf->LDPCdecoder = (LDPC_decoderfunc_t *)shlib_fdesc[2].fptr;
|
||||
itf->LDPCencoder = (LDPC_encoderfunc_t *)shlib_fdesc[3].fptr;
|
||||
|
||||
AssertFatal(itf->LDPCinit() == 0, "error starting LDPC library %s %s\n", libname, version);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int free_nrLDPClib_offload(void) {
|
||||
t_nrLDPC_dec_params decParams;
|
||||
t_nrLDPC_dec_params* p_decParams = &decParams;
|
||||
int8_t l[68*384];
|
||||
int8_t llrProcBuf[22*384];
|
||||
|
||||
p_decParams->Z = 384;
|
||||
p_decParams->BG = 1;
|
||||
|
||||
nrLDPC_decoder_offload(p_decParams,0,0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
25344,
|
||||
8,
|
||||
l,
|
||||
llrProcBuf, 2);
|
||||
return 0;
|
||||
int free_LDPClib(ldpc_interface_t *ldpc_interface)
|
||||
{
|
||||
return ldpc_interface->LDPCshutdown();
|
||||
}
|
||||
|
||||
int load_nrLDPClib_ref(char *libversion, nrLDPC_encoderfunc_t * nrLDPC_encoder_ptr) {
|
||||
loader_shlibfunc_t shlib_encoder_fdesc;
|
||||
|
||||
shlib_encoder_fdesc.fname = "nrLDPC_encod";
|
||||
int ret=load_module_version_shlib("ldpc",libversion,&shlib_encoder_fdesc,1,NULL);
|
||||
AssertFatal( (ret >= 0),"Error loading ldpc encoder %s\n",(libversion==NULL)?"":libversion);
|
||||
*nrLDPC_encoder_ptr = (nrLDPC_encoderfunc_t)shlib_encoder_fdesc.fptr;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -501,6 +501,9 @@ int init_codebook_gNB(PHY_VARS_gNB *gNB) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// A global var to reduce the changes size
|
||||
ldpc_interface_t ldpc_interface = {0}, ldpc_interface_offload = {0};
|
||||
|
||||
int phy_init_nr_gNB(PHY_VARS_gNB *gNB)
|
||||
{
|
||||
// shortcuts
|
||||
@@ -528,11 +531,10 @@ int phy_init_nr_gNB(PHY_VARS_gNB *gNB)
|
||||
|
||||
nr_init_fde(); // Init array for frequency equalization of transform precoding of PUSCH
|
||||
|
||||
load_nrLDPClib(NULL);
|
||||
load_LDPClib(NULL, &ldpc_interface);
|
||||
|
||||
if (gNB->ldpc_offload_flag)
|
||||
load_nrLDPClib_offload();
|
||||
|
||||
load_LDPClib("_t2", &ldpc_interface_offload);
|
||||
gNB->max_nb_pdsch = MAX_MOBILES_PER_GNB;
|
||||
|
||||
init_codebook_gNB(gNB);
|
||||
|
||||
@@ -162,7 +162,6 @@ void clean_gNB_dlsch(NR_gNB_DLSCH_t *dlsch) {
|
||||
void ldpc8blocks( void *p) {
|
||||
encoder_implemparams_t *impp=(encoder_implemparams_t *) p;
|
||||
NR_DL_gNB_HARQ_t *harq = (NR_DL_gNB_HARQ_t *)impp->harq;
|
||||
uint16_t Kr= impp->K;
|
||||
nfapi_nr_dl_tti_pdsch_pdu_rel15_t *rel15 = &harq->pdsch_pdu.pdsch_pdu_rel15;
|
||||
uint8_t mod_order = rel15->qamModOrder[0];
|
||||
uint16_t nb_rb = rel15->rbSize;
|
||||
@@ -182,9 +181,10 @@ void ldpc8blocks( void *p) {
|
||||
// nrLDPC_encoder output is in "d"
|
||||
// let's make this interface happy!
|
||||
uint8_t tmp[8][68 * 384]__attribute__((aligned(32)));
|
||||
uint8_t *d[impp->n_segments];
|
||||
for (int rr=impp->macro_num*8, i=0; rr < impp->n_segments && rr < (impp->macro_num+1)*8; rr++,i++ )
|
||||
impp->d[rr]=tmp[i];
|
||||
nrLDPC_encoder(harq->c,impp->d,*impp->Zc, impp->Kb,Kr,impp->BG,impp);
|
||||
d[rr] = tmp[i];
|
||||
ldpc_interface.LDPCencoder(harq->c, d, impp);
|
||||
// Compute where to place in output buffer that is concatenation of all segments
|
||||
uint32_t r_offset=0;
|
||||
for (int i=0; i < impp->macro_num*8; i++ )
|
||||
@@ -192,7 +192,7 @@ void ldpc8blocks( void *p) {
|
||||
for (int rr=impp->macro_num*8; rr < impp->n_segments && rr < (impp->macro_num+1)*8; rr++ ) {
|
||||
if (impp->F>0) {
|
||||
// writing into positions d[r][k-2Zc] as in clause 5.3.2 step 2) in 38.212
|
||||
memset(&impp->d[rr][Kr-impp->F-2*(*impp->Zc)], NR_NULL, impp->F);
|
||||
memset(&d[rr][impp->K - impp->F - 2 * impp->Zc], NR_NULL, impp->F);
|
||||
}
|
||||
|
||||
#ifdef DEBUG_DLSCH_CODING
|
||||
@@ -200,14 +200,18 @@ void ldpc8blocks( void *p) {
|
||||
#endif
|
||||
uint32_t E = nr_get_E(G, impp->n_segments, mod_order, rel15->nrOfLayers, rr);
|
||||
//#ifdef DEBUG_DLSCH_CODING
|
||||
LOG_D(NR_PHY,"Rate Matching, Code segment %d/%d (coded bits (G) %u, E %d, Filler bits %d, Filler offset %d mod_order %d, nb_rb %d,nrOfLayer %d)...\n",
|
||||
LOG_D(NR_PHY,
|
||||
"Rate Matching, Code segment %d/%d (coded bits (G) %u, E %d, Filler bits %d, Filler offset %d mod_order %d, nb_rb "
|
||||
"%d,nrOfLayer %d)...\n",
|
||||
rr,
|
||||
impp->n_segments,
|
||||
G,
|
||||
E,
|
||||
impp->F,
|
||||
Kr-impp->F-2*(*impp->Zc),
|
||||
mod_order,nb_rb,rel15->nrOfLayers);
|
||||
impp->K - impp->F - 2 * impp->Zc,
|
||||
mod_order,
|
||||
nb_rb,
|
||||
rel15->nrOfLayers);
|
||||
|
||||
uint32_t Tbslbrm = rel15->maintenance_parms_v3.tbSizeLbrmBytes;
|
||||
|
||||
@@ -215,27 +219,38 @@ void ldpc8blocks( void *p) {
|
||||
bzero (e, E);
|
||||
nr_rate_matching_ldpc(Tbslbrm,
|
||||
impp->BG,
|
||||
*impp->Zc,
|
||||
impp->d[rr],
|
||||
impp->Zc,
|
||||
d[rr],
|
||||
e,
|
||||
impp->n_segments,
|
||||
impp->F,
|
||||
Kr-impp->F-2*(*impp->Zc),
|
||||
impp->K - impp->F - 2 * impp->Zc,
|
||||
rel15->rvIndex[0],
|
||||
E);
|
||||
if (Kr-impp->F-2*(*impp->Zc)> E) {
|
||||
LOG_E(PHY,"dlsch coding A %d Kr %d G %d (nb_rb %d, nb_symb_sch %d, nb_re_dmrs %d, length_dmrs %d, mod_order %d)\n",
|
||||
A,impp->K,G, nb_rb,nb_symb_sch,nb_re_dmrs,length_dmrs,(int)mod_order);
|
||||
|
||||
LOG_E(NR_PHY,"Rate Matching, Code segment %d/%d (coded bits (G) %u, E %d, Kr %d, Filler bits %d, Filler offset %d mod_order %d, nb_rb %d)...\n",
|
||||
rr,
|
||||
impp->n_segments,
|
||||
G,
|
||||
E,
|
||||
Kr,
|
||||
impp->F,
|
||||
Kr-impp->F-2*(*impp->Zc),
|
||||
mod_order,nb_rb);
|
||||
if (impp->K - impp->F - 2 * impp->Zc > E) {
|
||||
LOG_E(PHY,
|
||||
"dlsch coding A %d Kr %d G %d (nb_rb %d, nb_symb_sch %d, nb_re_dmrs %d, length_dmrs %d, mod_order %d)\n",
|
||||
A,
|
||||
impp->K,
|
||||
G,
|
||||
nb_rb,
|
||||
nb_symb_sch,
|
||||
nb_re_dmrs,
|
||||
length_dmrs,
|
||||
(int)mod_order);
|
||||
|
||||
LOG_E(NR_PHY,
|
||||
"Rate Matching, Code segment %d/%d (coded bits (G) %u, E %d, Kr %d, Filler bits %d, Filler offset %d mod_order %d, "
|
||||
"nb_rb %d)...\n",
|
||||
rr,
|
||||
impp->n_segments,
|
||||
G,
|
||||
E,
|
||||
impp->K,
|
||||
impp->F,
|
||||
impp->K - impp->F - 2 * impp->Zc,
|
||||
mod_order,
|
||||
nb_rb);
|
||||
}
|
||||
#ifdef DEBUG_DLSCH_CODING
|
||||
|
||||
@@ -278,7 +293,7 @@ int nr_dlsch_encoding(PHY_VARS_gNB *gNB,
|
||||
impp.output=output;
|
||||
unsigned int crc=1;
|
||||
nfapi_nr_dl_tti_pdsch_pdu_rel15_t *rel15 = &harq->pdsch_pdu.pdsch_pdu_rel15;
|
||||
impp.Zc = &harq->Z;
|
||||
impp.Zc = harq->Z;
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_gNB_DLSCH_ENCODING, VCD_FUNCTION_IN);
|
||||
uint32_t A = rel15->TBSize[0]<<3;
|
||||
unsigned char *a=harq->pdu;
|
||||
@@ -334,14 +349,13 @@ int nr_dlsch_encoding(PHY_VARS_gNB *gNB,
|
||||
impp.BG = rel15->maintenance_parms_v3.ldpcBaseGraph;
|
||||
|
||||
start_meas(dlsch_segmentation_stats);
|
||||
impp.Kb = nr_segmentation(harq->b, harq->c, B, &impp.n_segments, &impp.K, impp.Zc, &impp.F, impp.BG);
|
||||
impp.Kb = nr_segmentation(harq->b, harq->c, B, &impp.n_segments, &impp.K, &impp.Zc, &impp.F, impp.BG);
|
||||
stop_meas(dlsch_segmentation_stats);
|
||||
|
||||
if (impp.n_segments>MAX_NUM_NR_DLSCH_SEGMENTS_PER_LAYER*rel15->nrOfLayers) {
|
||||
LOG_E(PHY, "nr_segmentation.c: too many segments %d, B %d\n", impp.n_segments, B);
|
||||
return(-1);
|
||||
}
|
||||
|
||||
for (int r=0; r<impp.n_segments; r++) {
|
||||
//d_tmp[r] = &harq->d[r][0];
|
||||
//channel_input[r] = &harq->d[r][0];
|
||||
@@ -364,26 +378,59 @@ int nr_dlsch_encoding(PHY_VARS_gNB *gNB,
|
||||
impp.tinput = tinput;
|
||||
impp.tparity = tparity;
|
||||
impp.toutput = toutput;
|
||||
|
||||
impp.harq=harq;
|
||||
notifiedFIFO_t nf;
|
||||
initNotifiedFIFO(&nf);
|
||||
int nbJobs=0;
|
||||
for(int j=0; j<(impp.n_segments/8+((impp.n_segments&7)==0 ? 0 : 1)); j++) {
|
||||
notifiedFIFO_elt_t *req=newNotifiedFIFO_elt(sizeof(impp), j, &nf, ldpc8blocks);
|
||||
encoder_implemparams_t* perJobImpp=(encoder_implemparams_t*)NotifiedFifoData(req);
|
||||
*perJobImpp=impp;
|
||||
perJobImpp->macro_num=j;
|
||||
pushTpool(&gNB->threadPool, req);
|
||||
nbJobs++;
|
||||
}
|
||||
while(nbJobs) {
|
||||
notifiedFIFO_elt_t *req=pullTpool(&nf, &gNB->threadPool);
|
||||
if (req == NULL)
|
||||
break; // Tpool has been stopped
|
||||
delNotifiedFIFO_elt(req);
|
||||
nbJobs--;
|
||||
|
||||
impp.harq = harq;
|
||||
if (gNB->ldpc_offload_flag && *rel15->mcsIndex > 2 && *rel15->mcsIndex != 10) {
|
||||
impp.Qm = rel15->qamModOrder[0];
|
||||
impp.rv = rel15->rvIndex[0];
|
||||
int nb_re_dmrs =
|
||||
(rel15->dmrsConfigType == NFAPI_NR_DMRS_TYPE1) ? (6 * rel15->numDmrsCdmGrpsNoData) : (4 * rel15->numDmrsCdmGrpsNoData);
|
||||
impp.G = nr_get_G(rel15->rbSize,
|
||||
rel15->NrOfSymbols,
|
||||
nb_re_dmrs,
|
||||
get_num_dmrs(rel15->dlDmrsSymbPos),
|
||||
rel15->qamModOrder[0],
|
||||
rel15->nrOfLayers);
|
||||
uint8_t tmp[68 * 384] __attribute__((aligned(32)));
|
||||
uint8_t *d = tmp;
|
||||
int r_offset = 0;
|
||||
for (int r = 0; r < impp.n_segments; r++) {
|
||||
impp.E = nr_get_E(impp.G, impp.n_segments, impp.Qm, rel15->nrOfLayers, r);
|
||||
impp.Kr = impp.K;
|
||||
ldpc_interface_offload.LDPCencoder(&harq->c[r], &d, &impp);
|
||||
uint8_t e[impp.E];
|
||||
bzero(e, impp.E);
|
||||
nr_rate_matching_ldpc(rel15->maintenance_parms_v3.tbSizeLbrmBytes,
|
||||
impp.BG,
|
||||
impp.Zc,
|
||||
tmp,
|
||||
e,
|
||||
impp.n_segments,
|
||||
impp.F,
|
||||
impp.K - impp.F - 2 * impp.Zc,
|
||||
impp.rv,
|
||||
impp.E);
|
||||
nr_interleaving_ldpc(impp.E, impp.Qm, e, impp.output + r_offset);
|
||||
r_offset += impp.E;
|
||||
}
|
||||
} else {
|
||||
notifiedFIFO_t nf;
|
||||
initNotifiedFIFO(&nf);
|
||||
int nbJobs = 0;
|
||||
for (int j = 0; j < (impp.n_segments / 8 + ((impp.n_segments & 7) == 0 ? 0 : 1)); j++) {
|
||||
notifiedFIFO_elt_t *req = newNotifiedFIFO_elt(sizeof(impp), j, &nf, ldpc8blocks);
|
||||
encoder_implemparams_t *perJobImpp = (encoder_implemparams_t *)NotifiedFifoData(req);
|
||||
*perJobImpp = impp;
|
||||
perJobImpp->macro_num = j;
|
||||
pushTpool(&gNB->threadPool, req);
|
||||
nbJobs++;
|
||||
}
|
||||
while (nbJobs) {
|
||||
notifiedFIFO_elt_t *req = pullTpool(&nf, &gNB->threadPool);
|
||||
if (req == NULL)
|
||||
break; // Tpool has been stopped
|
||||
delNotifiedFIFO_elt(req);
|
||||
nbJobs--;
|
||||
}
|
||||
}
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_gNB_DLSCH_ENCODING, VCD_FUNCTION_OUT);
|
||||
return 0;
|
||||
|
||||
@@ -187,7 +187,7 @@ static void nr_processULSegment(void *arg)
|
||||
|
||||
memset(ulsch_harq->c[r], 0, Kr_bytes);
|
||||
p_decoderParms->crc_type = crcType(ulsch_harq->C, A);
|
||||
p_decoderParms->block_length = lenWithCrc(ulsch_harq->C, A);
|
||||
p_decoderParms->E = p_decoderParms->block_length = lenWithCrc(ulsch_harq->C, A);
|
||||
// start_meas(&phy_vars_gNB->ulsch_ldpc_decoding_stats);
|
||||
|
||||
// set first 2*Z_c bits to zeros
|
||||
@@ -215,7 +215,8 @@ static void nr_processULSegment(void *arg)
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////// pl =====> llrProcBuf //////////////////////////////////
|
||||
rdata->decodeIterations = nrLDPC_decoder(p_decoderParms, l, llrProcBuf, p_procTime, &ulsch_harq->abort_decode);
|
||||
rdata->decodeIterations =
|
||||
ldpc_interface.LDPCdecoder(p_decoderParms, 0, 0, 0, l, llrProcBuf, p_procTime, &ulsch_harq->abort_decode);
|
||||
|
||||
if (rdata->decodeIterations <= p_decoderParms->numMaxIter)
|
||||
memcpy(ulsch_harq->c[r],llrProcBuf, Kr>>3);
|
||||
@@ -231,22 +232,20 @@ int decode_offload(PHY_VARS_gNB *phy_vars_gNB,
|
||||
{
|
||||
NR_gNB_ULSCH_t *ulsch = &phy_vars_gNB->ulsch[ULSCH_id];
|
||||
NR_UL_gNB_HARQ_t *harq_process = ulsch->harq_process;
|
||||
int8_t llrProcBuf[22 * 384] __attribute__((aligned(32)));
|
||||
int16_t z_ol[68 * 384] __attribute__((aligned(32)));
|
||||
int8_t l_ol[68 * 384] __attribute__((aligned(32)));
|
||||
int16_t z_ol[68 * 384 + 16] __attribute__((aligned(16)));
|
||||
int8_t l_ol[68 * 384 + 16] __attribute__((aligned(16)));
|
||||
uint8_t Qm = pusch_pdu->qam_mod_order;
|
||||
uint8_t n_layers = pusch_pdu->nrOfLayers;
|
||||
const int Kr = harq_process->K;
|
||||
const int Kr_bytes = Kr >> 3;
|
||||
uint32_t A = (harq_process->TBS) << 3;
|
||||
const int kc = decParams->BG == 2 ? 52 : 68;
|
||||
const uint32_t A = (harq_process->TBS) << 3;
|
||||
ulsch->max_ldpc_iterations = 20;
|
||||
int decodeIterations = 2;
|
||||
int dtx_det = 0;
|
||||
int r_offset = 0, offset = 0;
|
||||
for (int r = 0; r < harq_process->C; r++) {
|
||||
int E = nr_get_E(G, harq_process->C, Qm, n_layers, r);
|
||||
memset(harq_process->c[r], 0, Kr_bytes);
|
||||
|
||||
decParams->R = nr_get_R_ldpc_decoder(pusch_pdu->pusch_data.rv_index,
|
||||
E,
|
||||
decParams->BG,
|
||||
@@ -254,49 +253,24 @@ int decode_offload(PHY_VARS_gNB *phy_vars_gNB,
|
||||
&harq_process->llrLen,
|
||||
harq_process->round);
|
||||
|
||||
if ((dtx_det == 0) && (pusch_pdu->pusch_data.rv_index == 0)) {
|
||||
memcpy(z_ol, ulsch_llr + r_offset, E * sizeof(short));
|
||||
simde__m128i *pv_ol128 = (simde__m128i *)&z_ol;
|
||||
simde__m128i *pl_ol128 = (simde__m128i *)&l_ol;
|
||||
for (int i = 0, j = 0; j < ((kc * harq_process->Z) >> 4) + 1; i += 2, j++) {
|
||||
pl_ol128[j] = simde_mm_packs_epi16(pv_ol128[i], pv_ol128[i + 1]);
|
||||
}
|
||||
|
||||
int ret = nrLDPC_decoder_offload(decParams,
|
||||
harq_pid,
|
||||
ULSCH_id,
|
||||
r,
|
||||
pusch_pdu->pusch_data.rv_index,
|
||||
harq_process->F,
|
||||
E,
|
||||
Qm,
|
||||
(int8_t *)&pl_ol128[0],
|
||||
llrProcBuf,
|
||||
1);
|
||||
if (ret < 0) {
|
||||
LOG_E(PHY, "ulsch_decoding.c: Problem in LDPC decoder offload\n");
|
||||
|
||||
decodeIterations = ulsch->max_ldpc_iterations + 1;
|
||||
return -1;
|
||||
}
|
||||
for (int m = 0; m < Kr >> 3; m++) {
|
||||
harq_process->c[r][m] = (uint8_t)llrProcBuf[m];
|
||||
}
|
||||
|
||||
if (check_crc((uint8_t *)llrProcBuf, lenWithCrc(harq_process->C, A), crcType(harq_process->C, A))) {
|
||||
PRINT_CRC_CHECK(LOG_I(PHY, "Segment %d CRC OK\n", r));
|
||||
decodeIterations = 2;
|
||||
} else {
|
||||
PRINT_CRC_CHECK(LOG_I(PHY, "segment %d CRC NOK\n", r));
|
||||
decodeIterations = ulsch->max_ldpc_iterations + 1;
|
||||
}
|
||||
|
||||
r_offset += E;
|
||||
} else {
|
||||
dtx_det = 0;
|
||||
decodeIterations = ulsch->max_ldpc_iterations + 1;
|
||||
memcpy(z_ol, ulsch_llr + r_offset, E * sizeof(short));
|
||||
simde__m128i *pv_ol128 = (simde__m128i *)&z_ol;
|
||||
simde__m128i *pl_ol128 = (simde__m128i *)&l_ol;
|
||||
for (int i = 0, j = 0; j < ((kc * harq_process->Z) >> 4) + 1; i += 2, j++) {
|
||||
pl_ol128[j] = simde_mm_packs_epi16(pv_ol128[i], pv_ol128[i + 1]);
|
||||
}
|
||||
bool decodeSuccess = (decodeIterations <= ulsch->max_ldpc_iterations);
|
||||
decParams->E = E;
|
||||
decParams->rv = pusch_pdu->pusch_data.rv_index;
|
||||
decParams->F = harq_process->F;
|
||||
decParams->Qm = Qm;
|
||||
decodeIterations =
|
||||
ldpc_interface_offload
|
||||
.LDPCdecoder(decParams, harq_pid, ULSCH_id, r, (int8_t *)&pl_ol128[0], (int8_t *)harq_process->c[r], NULL, NULL);
|
||||
if (decodeIterations < 0) {
|
||||
LOG_E(PHY, "ulsch_decoding.c: Problem in LDPC decoder offload\n");
|
||||
return -1;
|
||||
}
|
||||
bool decodeSuccess = check_crc((uint8_t *)harq_process->c[r], lenWithCrc(harq_process->C, A), crcType(harq_process->C, A));
|
||||
if (decodeSuccess) {
|
||||
memcpy(harq_process->b + offset, harq_process->c[r], Kr_bytes - (harq_process->F >> 3) - ((harq_process->C > 1) ? 3 : 0));
|
||||
offset += (Kr_bytes - (harq_process->F >> 3) - ((harq_process->C > 1) ? 3 : 0));
|
||||
@@ -304,36 +278,42 @@ int decode_offload(PHY_VARS_gNB *phy_vars_gNB,
|
||||
} else {
|
||||
LOG_D(PHY, "uplink segment error %d/%d\n", r, harq_process->C);
|
||||
LOG_D(PHY, "ULSCH %d in error\n", ULSCH_id);
|
||||
break; // don't even attempt to decode other segments
|
||||
}
|
||||
r_offset += E;
|
||||
}
|
||||
bool crc_valid = false;
|
||||
if (harq_process->processedSegments == harq_process->C) {
|
||||
// When the number of code blocks is 1 (C = 1) and ulsch_harq->processedSegments = 1, we can assume a good TB because of the
|
||||
// CRC check made by the LDPC for early termination, so, no need to perform CRC check twice for a single code block
|
||||
crc_valid = true;
|
||||
if (harq_process->C > 1) {
|
||||
crc_valid = check_crc(harq_process->b, lenWithCrc(1, A), crcType(1, A));
|
||||
}
|
||||
}
|
||||
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_gNB_ULSCH_DECODING, 0);
|
||||
|
||||
if (harq_process->processedSegments == harq_process->C) {
|
||||
if (crc_valid) {
|
||||
LOG_D(PHY, "ULSCH: Setting ACK for slot %d TBS %d\n", ulsch->slot, harq_process->TBS);
|
||||
ulsch->active = false;
|
||||
harq_process->round = 0;
|
||||
|
||||
LOG_D(PHY, "ULSCH received ok \n");
|
||||
nr_fill_indication(phy_vars_gNB, ulsch->frame, ulsch->slot, ULSCH_id, harq_pid, 0, 0);
|
||||
|
||||
} else {
|
||||
LOG_D(PHY,
|
||||
"[gNB %d] ULSCH: Setting NAK for SFN/SF %d/%d (pid %d, status %d, round %d, TBS %d)\n",
|
||||
phy_vars_gNB->Mod_id,
|
||||
ulsch->frame,
|
||||
ulsch->slot,
|
||||
harq_pid,
|
||||
ulsch->active,
|
||||
harq_process->round,
|
||||
harq_process->TBS);
|
||||
"[gNB %d] ULSCH: Setting NAK for SFN/SF %d/%d (pid %d, status %d, round %d, TBS %d)\n",
|
||||
phy_vars_gNB->Mod_id,
|
||||
ulsch->frame,
|
||||
ulsch->slot,
|
||||
harq_pid,
|
||||
ulsch->active,
|
||||
harq_process->round,
|
||||
harq_process->TBS);
|
||||
ulsch->handled = 1;
|
||||
decodeIterations = ulsch->max_ldpc_iterations + 1;
|
||||
LOG_D(PHY, "ULSCH %d in error\n", ULSCH_id);
|
||||
nr_fill_indication(phy_vars_gNB, ulsch->frame, ulsch->slot, ULSCH_id, harq_pid, 1, 0);
|
||||
}
|
||||
|
||||
ulsch->last_iteration_cnt = decodeIterations;
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_gNB_ULSCH_DECODING,0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -373,7 +353,7 @@ int nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB,
|
||||
harq_process->processedSegments = 0;
|
||||
harq_process->TBS = pusch_pdu->pusch_data.tb_size;
|
||||
|
||||
t_nrLDPC_dec_params decParams = {0};
|
||||
t_nrLDPC_dec_params decParams = {.check_crc = check_crc};
|
||||
decParams.BG = pusch_pdu->maintenance_parms_v3.ldpcBaseGraph;
|
||||
const uint32_t A = (harq_process->TBS) << 3;
|
||||
NR_gNB_PHY_STATS_t *stats = get_phy_stats(phy_vars_gNB, ulsch->rnti);
|
||||
@@ -447,7 +427,7 @@ int nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB,
|
||||
harq_process->harq_to_be_cleared = false;
|
||||
}
|
||||
|
||||
if (phy_vars_gNB->ldpc_offload_flag && mcs > 9)
|
||||
if (phy_vars_gNB->ldpc_offload_flag)
|
||||
return decode_offload(phy_vars_gNB, ULSCH_id, ulsch_llr, pusch_pdu, &decParams, harq_pid, G);
|
||||
|
||||
uint32_t offset = 0, r_offset = 0;
|
||||
|
||||
@@ -256,10 +256,10 @@ static void nr_processDLSegment(void *arg)
|
||||
}
|
||||
|
||||
//VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_DLSCH_LDPC, VCD_FUNCTION_IN);
|
||||
p_decoderParms->block_length = lenWithCrc(harq_process->C, A);
|
||||
p_decoderParms->E = p_decoderParms->block_length = lenWithCrc(harq_process->C, A);
|
||||
p_decoderParms->crc_type = crcType(harq_process->C, A);
|
||||
nrLDPC_initcall(p_decoderParms, (int8_t *)&pl[0], LDPCoutput);
|
||||
rdata->decodeIterations = nrLDPC_decoder(p_decoderParms, (int8_t *)&pl[0], LDPCoutput, &procTime, &harq_process->abort_decode);
|
||||
rdata->decodeIterations =
|
||||
ldpc_interface.LDPCdecoder(p_decoderParms, 0, 0, 0, l, LDPCoutput, &procTime, &harq_process->abort_decode);
|
||||
//VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_DLSCH_LDPC, VCD_FUNCTION_OUT);
|
||||
|
||||
if (rdata->decodeIterations <= dlsch->max_ldpc_iterations)
|
||||
@@ -286,7 +286,7 @@ uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue,
|
||||
uint32_t ret,offset;
|
||||
uint32_t r,r_offset=0,Kr=8424,Kr_bytes;
|
||||
t_nrLDPC_dec_params decParams;
|
||||
t_nrLDPC_dec_params *p_decParams = &decParams;
|
||||
decParams.check_crc = check_crc;
|
||||
|
||||
if (!harq_process) {
|
||||
LOG_E(PHY,"dlsch_decoding.c: NULL harq_process pointer\n");
|
||||
@@ -360,8 +360,8 @@ uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue,
|
||||
|
||||
LOG_D(PHY,"%d.%d DLSCH Decoding, harq_pid %d TBS %d (%d) G %d nb_re_dmrs %d length dmrs %d mcs %d Nl %d nb_symb_sch %d nb_rb %d Qm %d Coderate %f\n",
|
||||
frame,nr_slot_rx,harq_pid,A,A/8,G, nb_re_dmrs, dmrs_length, dlsch->dlsch_config.mcs, dlsch->Nl, nb_symb_sch, nb_rb, dlsch->dlsch_config.qamModOrder, Coderate);
|
||||
p_decParams->BG = get_BG(A, dlsch->dlsch_config.targetCodeRate);
|
||||
unsigned int kc = p_decParams->BG == 2 ? 52 : 68;
|
||||
decParams.BG = get_BG(A, dlsch->dlsch_config.targetCodeRate);
|
||||
unsigned int kc = decParams.BG == 2 ? 52 : 68;
|
||||
|
||||
if (harq_process->first_rx == 1) {
|
||||
// This is a new packet, so compute quantities regarding segmentation
|
||||
@@ -372,7 +372,7 @@ uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue,
|
||||
&harq_process->K,
|
||||
&harq_process->Z, // [hna] Z is Zc
|
||||
&harq_process->F,
|
||||
p_decParams->BG);
|
||||
decParams.BG);
|
||||
|
||||
if (harq_process->C>MAX_NUM_NR_DLSCH_SEGMENTS_PER_LAYER*dlsch->Nl) {
|
||||
LOG_E(PHY, "nr_segmentation.c: too many segments %d, A %d\n", harq_process->C, A);
|
||||
@@ -387,11 +387,9 @@ uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue,
|
||||
}
|
||||
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_DLSCH_SEGMENTATION, VCD_FUNCTION_OUT);
|
||||
p_decParams->Z = harq_process->Z;
|
||||
//printf("dlsch decoding nr segmentation Z %d\n", p_decParams->Z);
|
||||
//printf("coderate %f kc %d \n", Coderate, kc);
|
||||
p_decParams->numMaxIter = dlsch->max_ldpc_iterations;
|
||||
p_decParams->outMode= 0;
|
||||
decParams.Z = harq_process->Z;
|
||||
decParams.numMaxIter = dlsch->max_ldpc_iterations;
|
||||
decParams.outMode = 0;
|
||||
r_offset = 0;
|
||||
uint16_t a_segments = MAX_NUM_NR_DLSCH_SEGMENTS_PER_LAYER*dlsch->Nl; //number of segments to be allocated
|
||||
|
||||
@@ -408,7 +406,7 @@ uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue,
|
||||
if (LOG_DEBUGFLAG(DEBUG_DLSCH_DECOD))
|
||||
LOG_I(PHY,"Segmentation: C %d, K %d\n",harq_process->C,harq_process->K);
|
||||
|
||||
Kr = harq_process->K; // [hna] overwrites this line "Kr = p_decParams->Z*kb"
|
||||
Kr = harq_process->K;
|
||||
Kr_bytes = Kr>>3;
|
||||
offset = 0;
|
||||
notifiedFIFO_t nf;
|
||||
|
||||
@@ -57,11 +57,10 @@ int nr_ulsch_encoding(PHY_VARS_NR_UE *ue,
|
||||
NR_UL_UE_HARQ_t *harq_process = &ue->ul_harq_processes[harq_pid];
|
||||
uint16_t nb_rb = ulsch->pusch_pdu.rb_size;
|
||||
uint32_t A = tb_size << 3;
|
||||
uint32_t *pz = &harq_process->Z;
|
||||
uint8_t mod_order = ulsch->pusch_pdu.qam_mod_order;
|
||||
uint16_t Kr=0;
|
||||
uint32_t r_offset=0;
|
||||
uint32_t F=0;
|
||||
uint16_t Kr = 0;
|
||||
uint32_t r_offset = 0;
|
||||
uint32_t F = 0;
|
||||
// target_code_rate is in 0.1 units
|
||||
float Coderate = (float) ulsch->pusch_pdu.target_code_rate / 10240.0f;
|
||||
|
||||
@@ -72,9 +71,11 @@ int nr_ulsch_encoding(PHY_VARS_NR_UE *ue,
|
||||
|
||||
LOG_D(NR_PHY, "ulsch coding nb_rb %d, Nl = %d\n", nb_rb, ulsch->pusch_pdu.nrOfLayers);
|
||||
LOG_D(NR_PHY, "ulsch coding A %d G %d mod_order %d Coderate %f\n", A, G, mod_order, Coderate);
|
||||
LOG_D(NR_PHY, "harq_pid %d harq_process->ndi %d, pusch_data.new_data_indicator %d\n",
|
||||
harq_pid,harq_process->ndi,ulsch->pusch_pdu.pusch_data.new_data_indicator);
|
||||
|
||||
LOG_D(NR_PHY,
|
||||
"harq_pid %d harq_process->ndi %d, pusch_data.new_data_indicator %d\n",
|
||||
harq_pid,
|
||||
harq_process->ndi,
|
||||
ulsch->pusch_pdu.pusch_data.new_data_indicator);
|
||||
if (harq_process->first_tx == 1 ||
|
||||
harq_process->ndi != ulsch->pusch_pdu.pusch_data.new_data_indicator) { // this is a new packet
|
||||
#ifdef DEBUG_ULSCH_CODING
|
||||
@@ -140,7 +141,7 @@ int nr_ulsch_encoding(PHY_VARS_NR_UE *ue,
|
||||
B,
|
||||
&harq_process->C,
|
||||
&harq_process->K,
|
||||
pz,
|
||||
&harq_process->Z,
|
||||
&harq_process->F,
|
||||
harq_process->BG);
|
||||
|
||||
@@ -161,7 +162,7 @@ int nr_ulsch_encoding(PHY_VARS_NR_UE *ue,
|
||||
///////////////////////// c---->| LDCP coding |---->d /////////////////////////
|
||||
///////////
|
||||
|
||||
//printf("segment Z %d k %d Kr %d BG %d\n", *pz,harq_process->K,Kr,BG);
|
||||
// printf("segment Z %d k %d Kr %d BG %d\n", harq_process->Z,harq_process->K,Kr,BG);
|
||||
|
||||
//start_meas(te_stats);
|
||||
for (int r=0; r<harq_process->C; r++) {
|
||||
@@ -170,7 +171,7 @@ int nr_ulsch_encoding(PHY_VARS_NR_UE *ue,
|
||||
printf("Encoder: B %d F %d \n", B, harq_process->F);
|
||||
printf("start ldpc encoder segment %d/%d\n",r,harq_process->C);
|
||||
printf("input %d %d %d %d %d \n", harq_process->c[r][0], harq_process->c[r][1], harq_process->c[r][2],harq_process->c[r][3], harq_process->c[r][4]);
|
||||
for (int cnt =0 ; cnt < 22*(*pz)/8; cnt ++){
|
||||
for (int cnt = 0; cnt < 22 * harq_process->Z / 8; cnt++) {
|
||||
printf("%d ", harq_process->c[r][cnt]);
|
||||
}
|
||||
printf("\n");
|
||||
@@ -183,28 +184,39 @@ int nr_ulsch_encoding(PHY_VARS_NR_UE *ue,
|
||||
//for (int i=0;i<68*384;i++)
|
||||
// printf("channel_input[%d]=%d\n",i,channel_input[i]);
|
||||
|
||||
/*printf("output %d %d %d %d %d \n", harq_process->d[0][0], harq_process->d[0][1], harq_process->d[r][2],harq_process->d[0][3], harq_process->d[0][4]);
|
||||
for (int cnt =0 ; cnt < 66*(*pz); cnt ++){
|
||||
printf("%d \n", harq_process->d[0][cnt]);
|
||||
/*printf("output %d %d %d %d %d \n", harq_process->d[0][0], harq_process->d[0][1], harq_process->d[r][2],harq_process->d[0][3],
|
||||
harq_process->d[0][4]); for (int cnt =0 ; cnt < 66*harq_process->Z; cnt ++){ printf("%d \n", harq_process->d[0][cnt]);
|
||||
}
|
||||
printf("\n");*/
|
||||
encoder_implemparams_t impp = {
|
||||
.n_segments=harq_process->C,
|
||||
.macro_num=0,
|
||||
.tinput = NULL,
|
||||
.tprep = NULL,
|
||||
.tparity = NULL,
|
||||
.toutput = NULL};
|
||||
encoder_implemparams_t impp = {.n_segments = harq_process->C,
|
||||
.macro_num = 0,
|
||||
.K = harq_process->K,
|
||||
.Kb = Kb,
|
||||
.Zc = harq_process->Z,
|
||||
.BG = harq_process->BG,
|
||||
.tinput = NULL,
|
||||
.tprep = NULL,
|
||||
.tparity = NULL,
|
||||
.toutput = NULL};
|
||||
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_LDPC_ENCODER_OPTIM, VCD_FUNCTION_IN);
|
||||
|
||||
start_meas(&ue->ulsch_ldpc_encoding_stats);
|
||||
for(int j = 0; j < (harq_process->C/8 + 1); j++) {
|
||||
impp.macro_num = j;
|
||||
nrLDPC_encoder(harq_process->c,harq_process->d,*pz,Kb,Kr,harq_process->BG,&impp);
|
||||
}
|
||||
stop_meas(&ue->ulsch_ldpc_encoding_stats);
|
||||
|
||||
// ldpc_interface_offload.LDPCencoder=NULL;
|
||||
if (ldpc_interface_offload.LDPCencoder)
|
||||
for (int j = 0; j < harq_process->C; j++) {
|
||||
impp.macro_num = j;
|
||||
impp.E = nr_get_E(G, harq_process->C, mod_order, ulsch->pusch_pdu.nrOfLayers, j);
|
||||
impp.Kr = Kr;
|
||||
ldpc_interface_offload.LDPCencoder(&harq_process->c[j], &harq_process->d[j], &impp);
|
||||
}
|
||||
else
|
||||
for (int j = 0; j < (harq_process->C / 8 + 1); j++) {
|
||||
impp.macro_num = j;
|
||||
impp.E = nr_get_E(G, harq_process->C, mod_order, ulsch->pusch_pdu.nrOfLayers, j);
|
||||
impp.Kr = Kr;
|
||||
ldpc_interface.LDPCencoder(harq_process->c, harq_process->d, &impp);
|
||||
}
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_LDPC_ENCODER_OPTIM, VCD_FUNCTION_OUT);
|
||||
|
||||
//stop_meas(te_stats);
|
||||
@@ -224,7 +236,7 @@ int nr_ulsch_encoding(PHY_VARS_NR_UE *ue,
|
||||
|
||||
for (int r=0; r<harq_process->C; r++) { // looping over C segments
|
||||
if (harq_process->F>0) {
|
||||
for (int k=(Kr-F-2*(*pz)); k<Kr-2*(*pz); k++) {
|
||||
for (int k = Kr - F - 2 * harq_process->Z; k < Kr - 2 * harq_process->Z; k++) {
|
||||
harq_process->d[r][k] = NR_NULL;
|
||||
//if (k<(Kr-F+8))
|
||||
//printf("r %d filler bits [%d] = %d \n", r,k, harq_process->d[r][k]);
|
||||
@@ -249,14 +261,15 @@ int nr_ulsch_encoding(PHY_VARS_NR_UE *ue,
|
||||
start_meas(&ue->ulsch_rate_matching_stats);
|
||||
if (nr_rate_matching_ldpc(ulsch->pusch_pdu.tbslbrm,
|
||||
harq_process->BG,
|
||||
*pz,
|
||||
harq_process->Z,
|
||||
harq_process->d[r],
|
||||
harq_process->e+r_offset,
|
||||
harq_process->e + r_offset,
|
||||
harq_process->C,
|
||||
F,
|
||||
Kr-F-2*(*pz),
|
||||
Kr - F - 2 * harq_process->Z,
|
||||
ulsch->pusch_pdu.pusch_data.rv_index,
|
||||
E) == -1)
|
||||
E)
|
||||
== -1)
|
||||
return -1;
|
||||
|
||||
stop_meas(&ue->ulsch_rate_matching_stats);
|
||||
|
||||
@@ -296,6 +296,7 @@ int main(int argc, char **argv)
|
||||
uint8_t n_tx=1,n_rx=1;
|
||||
uint8_t round;
|
||||
uint8_t num_rounds = 4;
|
||||
int ldpc_offload_flag = 0;
|
||||
char gNBthreads[128]="n";
|
||||
|
||||
channel_desc_t *gNB2UE;
|
||||
@@ -358,7 +359,7 @@ int main(int argc, char **argv)
|
||||
|
||||
FILE *scg_fd=NULL;
|
||||
|
||||
while ((c = getopt(argc, argv, "f:hA:p:f:g:i:n:s:S:t:v:x:y:z:o:M:N:F:GR:d:PI:L:a:b:e:m:w:T:U:q:X:Y:Z:")) != -1) {
|
||||
while ((c = getopt(argc, argv, "f:hA:p:f:g:i:n:s:S:t:v:x:y:z:o:M:N:F:GR:d:PI:L:a:b:e:m:w:T:U:q:X:Y:Z:c")) != -1) {
|
||||
switch (c) {
|
||||
case 'f':
|
||||
scg_fd = fopen(optarg,"r");
|
||||
@@ -403,6 +404,10 @@ int main(int argc, char **argv)
|
||||
n_trials = atoi(optarg);
|
||||
break;
|
||||
|
||||
case 'c':
|
||||
ldpc_offload_flag = 1;
|
||||
break;
|
||||
|
||||
case 's':
|
||||
snr0 = atof(optarg);
|
||||
printf("Setting SNR0 to %f\n",snr0);
|
||||
@@ -547,7 +552,31 @@ int main(int argc, char **argv)
|
||||
|
||||
default:
|
||||
case 'h':
|
||||
printf("%s -h(elp)\n", argv[0]);
|
||||
printf("%s -h(elp) -p(extended_prefix) -N cell_id -f output_filename -F input_filename -g channel_model -n n_frames -s snr0 -S snr1 -x transmission_mode -y TXant -z RXant -i Intefrence0 -j Interference1 -A interpolation_file -C(alibration offset dB) -N CellId\n",
|
||||
argv[0]);
|
||||
printf("-h This message\n");
|
||||
printf("-L <log level, 0(errors), 1(warning), 2(analysis), 3(info), 4(debug), 5(trace)>\n");
|
||||
//printf("-p Use extended prefix mode\n");
|
||||
//printf("-d Use TDD\n");
|
||||
printf("-n Number of frames to simulate\n");
|
||||
printf("-s Starting SNR, runs from SNR0 to SNR0 + 5 dB. If n_frames is 1 then just SNR is simulated\n");
|
||||
printf("-S Ending SNR, runs from SNR0 to SNR1\n");
|
||||
//printf("-t Delay spread for multipath channel\n");
|
||||
printf("-g Channel model: [A] TDLA30, [B] TDLB100, [C] TDLC300, e.g. -g A\n");
|
||||
printf("-o Introduce delay in terms of number of samples\n");
|
||||
printf("-y Number of TX antennas used in gNB\n");
|
||||
printf("-z Number of RX antennas used in UE\n");
|
||||
printf("-x Num of layer for PDSCH\n");
|
||||
printf("-p Precoding matrix index\n");
|
||||
printf("-i Change channel estimation technique. Arguments list: Frequency domain {0:Linear interpolation, 1:PRB based averaging}, Time domain {0:Estimates of last DMRS symbol, 1:Average of DMRS symbols}\n");
|
||||
//printf("-j Relative strength of second intefering gNB (in dB) - cell_id mod 3 = 2\n");
|
||||
printf("-R N_RB_DL\n");
|
||||
printf("-O oversampling factor (1,2,4,8,16)\n");
|
||||
printf("-c ldpc offload flag\n");
|
||||
printf("-A Interpolation_filname Run with Abstraction to generate Scatter plot using interpolation polynomial in file\n");
|
||||
//printf("-C Generate Calibration information for Abstraction (effective SNR adjustment to remove Pe bias w.r.t. AWGN)\n");
|
||||
printf("-f raw file containing RRC configuration (generated by gNB)\n");
|
||||
printf("-F Input filename (.txt format) for RX conformance testing\n");
|
||||
printf("-a Start PRB for PDSCH\n");
|
||||
printf("-b Number of PRB for PDSCH\n");
|
||||
printf("-d number of dlsch threads, 0: no dlsch parallelization\n");
|
||||
@@ -602,6 +631,7 @@ int main(int argc, char **argv)
|
||||
|
||||
gNB = RC.gNB[0];
|
||||
gNB->ofdm_offset_divisor = UINT_MAX;
|
||||
gNB->ldpc_offload_flag = ldpc_offload_flag;
|
||||
frame_parms = &gNB->frame_parms; //to be initialized I suppose (maybe not necessary for PBCH)
|
||||
frame_parms->nb_antennas_tx = n_tx;
|
||||
frame_parms->nb_antennas_rx = n_rx;
|
||||
@@ -1305,7 +1335,10 @@ int main(int argc, char **argv)
|
||||
free(UE->phy_sim_pdsch_dl_ch_estimates);
|
||||
free(UE->phy_sim_pdsch_dl_ch_estimates_ext);
|
||||
free(UE->phy_sim_dlsch_b);
|
||||
|
||||
|
||||
if (gNB->ldpc_offload_flag)
|
||||
free_LDPClib(&ldpc_interface_offload);
|
||||
|
||||
if (output_fd)
|
||||
fclose(output_fd);
|
||||
|
||||
|
||||
@@ -800,14 +800,12 @@ int main(int argc, char *argv[])
|
||||
printf("[ULSIM]: CDM groups: %u, dmrs_config_type: %d, num_rbs: %u, nb_symb_sch: %u\n", num_dmrs_cdm_grps_no_data, dmrs_config_type, nb_rb, nb_symb_sch);
|
||||
printf("[ULSIM]: MCS: %d, mod order: %u, code_rate: %u\n", Imcs, mod_order, code_rate);
|
||||
printf("[ULSIM]: VALUE OF G: %u, TBS: %u\n", available_bits, TBS);
|
||||
|
||||
|
||||
|
||||
uint8_t ulsch_input_buffer[TBS/8];
|
||||
|
||||
ulsch_input_buffer[0] = 0x31;
|
||||
for (i = 1; i < TBS/8; i++) {
|
||||
ulsch_input_buffer[i] = (unsigned char) uniformrandom();
|
||||
ulsch_input_buffer[i] = (uint8_t)rand();
|
||||
}
|
||||
|
||||
uint8_t ptrs_time_density = get_L_ptrs(ptrs_mcs1, ptrs_mcs2, ptrs_mcs3, Imcs, mcs_table);
|
||||
@@ -1624,7 +1622,7 @@ int main(int argc, char *argv[])
|
||||
|
||||
free_MIB_NR(mib);
|
||||
if (gNB->ldpc_offload_flag)
|
||||
free_nrLDPClib_offload();
|
||||
free_LDPClib(&ldpc_interface_offload);
|
||||
|
||||
if (output_fd)
|
||||
fclose(output_fd);
|
||||
|
||||
Reference in New Issue
Block a user