Commit 1036f0ed authored by Hongzhi Wang's avatar Hongzhi Wang

adding nr ue ldpc offload

parent 9881036c
......@@ -247,6 +247,7 @@ add_boolean_option(T_TRACER True "Activate the T tracer, a debugging
add_boolean_option(UE_AUTOTEST_TRACE False "Activate UE autotest specific logs")
add_boolean_option(UE_DEBUG_TRACE False "Activate UE debug trace")
add_boolean_option(UE_TIMING_TRACE False "Activate UE timing trace")
add_boolean_option(LDPC_FPGA_OFFLOAD False "Activate UE LDPC trace")
add_boolean_option(DISABLE_LOG_X False "Deactivate all LOG_* macros")
add_boolean_option(USRP_REC_PLAY False "Enable USRP record playback mode")
add_boolean_option(UE_NAS_USE_TUN False "Enable UE NAS TUN device instead of ue_ip.ko")
......@@ -1425,6 +1426,7 @@ set(PHY_SRC_UE
${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c
${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/nr_ulsch_coding.c
${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c
${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding_ldpc_offload.c
${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/nr_dlsch_llr_computation.c
${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_tbs_tools.c
${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_sch_dmrs.c
......@@ -2549,6 +2551,20 @@ target_link_libraries (nr-uesoftmodem pthread m ${CONFIG_LIBRARIES} rt crypt ${C
target_link_libraries (nr-uesoftmodem ${LIB_LMS_LIBRARIES})
target_link_libraries (nr-uesoftmodem ${T_LIB})
# LDPC Decoder Offload : SYRTEM
#####################################################
if (${LDPC_FPGA_OFFLOAD})
set (LDPC_OFFLOAD_DIR ${OPENAIR_DIR}/targets/ARCH/LDPC_OFFLOAD/slib)
include_directories ("${LDPC_OFFLOAD_DIR}")
LINK_DIRECTORIES("${LDPC_OFFLOAD_DIR}")
set(LDPC_OFFLOAD_LIB "ldpc_decoder_offload")
endif (${LDPC_FPGA_OFFLOAD})
if (${LDPC_FPGA_OFFLOAD})
message( "Linking LDPC_OFFLOAD lib" )
target_link_libraries( nr-uesoftmodem ${OPENAIR_TARGETS}/ARCH/LDPC_OFFLOAD/slib/libldpc_decoder_offload.so )
endif (${LDPC_FPGA_OFFLOAD})
# nr-uesoftmodem-nos1
#######################################
......
......@@ -64,6 +64,7 @@ CMAKE_CMD="$CMAKE"
UE_AUTOTEST_TRACE="False"
UE_DEBUG_TRACE="False"
UE_TIMING_TRACE="False"
LDPC_FPGA_OFFLOAD="False"
USRP_REC_PLAY="False"
BUILD_ECLIPSE=0
NR="False"
......@@ -143,6 +144,8 @@ Options
Disables the T tracer.
--disable-hardware-dependency
Disable HW dependency during installation
--ldpc_fpga_offload
Enables LDPC decoding offload in FPGA.
--ue-autotest-trace
Enable specific traces for UE autotest framework
--ue-trace
......@@ -332,6 +335,10 @@ function main() {
echo_info "Disabling hardware dependency for compiling software"
DISABLE_HARDWARE_DEPENDENCY="True"
shift 1;;
--ldpc_fpga_offload)
LDPC_FPGA_OFFLOAD="True"
echo_info "Enabling the usage of LDPC decoding offload in FPGA"
shift 1;;
--ue-autotest-trace)
UE_AUTOTEST_TRACE="True"
echo_info "Enabling autotest specific trace for UE"
......@@ -563,6 +570,7 @@ function main() {
echo "set ( UE_AUTOTEST_TRACE $UE_AUTOTEST_TRACE )" >> $cmake_file
echo "set ( UE_DEBUG_TRACE $UE_DEBUG_TRACE )" >> $cmake_file
echo "set ( UE_TIMING_TRACE $UE_TIMING_TRACE )" >> $cmake_file
echo "set ( LDPC_FPGA_OFFLOAD $LDPC_FPGA_OFFLOAD)" >> $cmake_file
echo "set ( USRP_REC_PLAY $USRP_REC_PLAY )" >> $cmake_file
echo 'include(${CMAKE_CURRENT_SOURCE_DIR}/../CMakeLists.txt)' >> $cmake_file
cd $DIR/$build_dir/build
......
......@@ -122,6 +122,59 @@ int32_t uplink_frequency_offset[MAX_NUM_CCs][4];
extern int16_t nr_dlsch_demod_shift;
#if LDPC_FPGA_OFFLOAD
#include <dlfcn.h>
#include "ldpc_decoder_offload.h"
typedef uint8_t (*syr_ldpc_offload_initfunc_t)(void);
typedef uint8_t (*syr_ldpc_offload_finifunc_t)(void);
typedef uint8_t (*syr_ldpc_offload_decodefunc_t)(int16_t *y,
uint8_t *decoded_bytes,
uint16_t n,
uint16_t interleaver_f1,
uint16_t interleaver_f2,
uint8_t max_iterations,
uint8_t crc_type,
uint8_t F,
time_stats_t *init_stats,
time_stats_t *alpha_stats,
time_stats_t *beta_stats,
time_stats_t *gamma_stats,
time_stats_t *ext_stats,
time_stats_t *intl1_stats,
time_stats_t *intl2_stats);
syr_ldpc_offload_initfunc_t syr_init_funct;
syr_ldpc_offload_finifunc_t syr_fini_funct;
//syr_ldpc_offload_decodefunc_t syr_ldpc_decode_funct;
typedef session_t (*threegpp_nr_ldpc_decode_start_t)(session_desc_t *session_desc);
threegpp_nr_ldpc_decode_start_t threegpp_nr_ldpc_decode_start_funct;
typedef int32_t (*threegpp_nr_ldpc_decode_putq_t)( session_t fd,
int16_t *y_16bits,
uint8_t *decoded_bytes,
uint8_t r,
uint16_t n,
uint8_t max_iterations,
uint8_t crc_type);
threegpp_nr_ldpc_decode_putq_t threegpp_nr_ldpc_decode_putq_funct;
typedef int32_t (*threegpp_nr_ldpc_decode_getq_t)( session_t fd,
uint8_t *decoded_bytes,
uint8_t r,
uint8_t crc_type,
uint8_t *crc_status,
uint8_t *nb_iterations
);
threegpp_nr_ldpc_decode_getq_t threegpp_nr_ldpc_decode_getq_funct;
typedef int32_t (*threegpp_nr_ldpc_decode_stop_t)( session_t fd);
threegpp_nr_ldpc_decode_stop_t threegpp_nr_ldpc_decode_stop_funct;
typedef int32_t (*threegpp_nr_ldpc_decode_run_t)( session_t fd);
threegpp_nr_ldpc_decode_run_t threegpp_nr_ldpc_decode_run_funct;
#endif
int UE_scan = 0;
int UE_scan_carrier = 0;
int UE_fo_compensation = 0;
......@@ -789,6 +842,105 @@ int main( int argc, char **argv ) {
#endif
}
#if LDPC_FPGA_OFFLOAD
void *syr_handle = NULL;;
uint8_t syr_ret = 0;
syr_handle = dlopen("libldpc_decoder_offload.so", RTLD_LAZY);
if (!syr_handle)
{
fprintf(stderr,"Unable to locate libldpc_decoder_offload.so: HW device set to NONE_DEV.\n");
fprintf(stderr,"%s\n",dlerror());
exit_fun("Error loading ldpc decoder offload device");
}
syr_init_funct = dlsym(syr_handle,"phy_threegppnr_ldpc_decoder_offload_init");
if (syr_init_funct != NULL )
{
syr_ret = syr_init_funct();
if (syr_ret < 0)
{
fprintf(stderr, "%s %d:ldpc decoder offload device intialization failed %s\n", __FILE__, __LINE__, dlerror());
exit_fun("Error loading ldpc decoder offload device");
}
}
else
{
fprintf(stderr, "%s %d:ldpc decoder offload device init function not found %s\n", __FILE__, __LINE__, dlerror());
exit_fun("Error ldpc decoder offload device init function not found");
}
syr_fini_funct = dlsym(syr_handle,"phy_threegppnr_ldpc_decoder_offload_fini");
if (syr_fini_funct == NULL )
{
fprintf(stderr, "%s %d:ldpc decoder offload device fini function not found %s\n", __FILE__, __LINE__, dlerror());
exit_fun("Error ldpc decoder offload device fini function not found");
}
#if 0
syr_ldpc_decode_funct = dlsym(syr_handle,"phy_threegppnr_ldpc_decoder_offload");
if (syr_ldpc_decode_funct == NULL )
{
fprintf(stderr, "%s %d:ldpc decoder offload device decode function not found %s\n", __FILE__, __LINE__, dlerror());
exit_fun("Error ldpc decoder offload device decode function not found");
}
#endif
threegpp_nr_ldpc_decode_start_funct = dlsym(syr_handle,"threegpp_nr_ldpc_decode_start");
if (threegpp_nr_ldpc_decode_start_funct == NULL )
{
printf("%s %d:threegpp_nr_ldpc_decode_start function not found %s\n", __FILE__, __LINE__, dlerror());
exit(-1);
}
threegpp_nr_ldpc_decode_putq_funct = dlsym(syr_handle,"threegpp_nr_ldpc_decode_putq");
if (threegpp_nr_ldpc_decode_putq_funct == NULL )
{
printf("%s %d:threegpp_nr_ldpc_decode_putq function not found %s\n", __FILE__, __LINE__, dlerror());
exit(-1);
}
threegpp_nr_ldpc_decode_getq_funct = dlsym(syr_handle,"threegpp_nr_ldpc_decode_getq");
if (threegpp_nr_ldpc_decode_getq_funct == NULL )
{
printf("%s %d:threegpp_nr_ldpc_decode_getq function not found %s\n", __FILE__, __LINE__, dlerror());
exit(-1);
}
threegpp_nr_ldpc_decode_stop_funct = dlsym(syr_handle,"threegpp_nr_ldpc_decode_stop");
if (threegpp_nr_ldpc_decode_stop_funct == NULL )
{
printf("%s %d:threegpp_nr_ldpc_decode_stop function not found %s\n", __FILE__, __LINE__, dlerror());
exit(-1);
}
threegpp_nr_ldpc_decode_run_funct = dlsym(syr_handle,"threegpp_nr_ldpc_decode_run");
if (threegpp_nr_ldpc_decode_run_funct == NULL )
{
printf("%s %d:threegpp_nr_ldpc_decode_run function not found %s\n", __FILE__, __LINE__, dlerror());
exit(-1);
}
#if 0 // Test
int16_t y[8448]; // 22.Zc -> 22x128 x 3 LLR16bits -> 8448 int16_t
uint8_t decoded_bytes[352]; // 22.Zc bits -> 352 bytes
uint16_t n = 2816; // code_block size = 2816
memset(y, 0x7F, 8448 * sizeof(int16_t));
memset(decoded_bytes, 0, 352 * sizeof(uint8_t));
syr_ret = syr_ldpc_decode_funct(y, decoded_bytes, n, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
if (syr_ret < 0)
{
fprintf(stderr, "%s %d:ldpc decoder offload device intialization failed %s\n", __FILE__, __LINE__, dlerror());
exit_fun("Error loading ldpc decoder offload device");
}
#endif
#endif
// wait for end of program
printf("TYPE <CTRL-C> TO TERMINATE\n");
init_NR_UE(1);
......
/*
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenAirInterface Software Alliance licenses this file to You under
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
* except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.openairinterface.org/?page_id=698
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*-------------------------------------------------------------------------------
* For more information about the OpenAirInterface (OAI) Software Alliance:
* contact@openairinterface.org
*/
/*! \file PHY/LTE_TRANSPORT/dlsch_decoding.c
* \brief Top-level routines for decoding LDPC-coded (DLSCH) transport channels from 38-212
* \author R. Knopp
* \date 2011
* \version 0.1
* \company Eurecom
* \email: knopp@eurecom.fr
* \note
* \warning
*/
#include "common/utils/LOG/vcd_signal_dumper.h"
//#include "defs.h"
#include "PHY/defs_nr_UE.h"
#include "PHY/phy_extern.h"
#include "PHY/CODING/coding_extern.h"
#include "SCHED_NR_UE/defs.h"
#include "SIMULATION/TOOLS/sim.h"
#include "executables/nr-uesoftmodem.h"
#include "PHY/CODING/nrLDPC_decoder/nrLDPC_decoder.h"
//#include "PHY/CODING/nrLDPC_types.h"
//#define DEBUG_DLSCH_DECODING
#if LDPC_FPGA_OFFLOAD
static uint64_t nb_total_decod = 0;
static uint64_t nb_error_decod = 0;
uint64_t total_decod = 0;
uint64_t total_decod_error = 0;
uint64_t total_decod_error_crc = 0;
uint64_t total_decod_it = 0;
typedef struct ldpc_stat_per_subframe{
uint64_t ldpc_block_decod_count;
uint64_t ldpc_block_decod_error;
uint64_t ldpc_block_decod_error_crc;
uint64_t ldpc_block_decod_it;
uint64_t ldpc_block_decod_max_it;
uint64_t ldpc_tb_error_block_max;
} ldpc_stat_per_subframe_t;
int ldpc_stat_flag = 0;
ldpc_stat_per_subframe_t g_ldpc_stat_per_subframe_array[10];
//#define DLSIM_DECOD_CHECK
#ifdef DLSIM_DECOD_CHECK
extern uint16_t dlsch_coding_c[16][22*384];
extern uint8_t dlsch_coding_d[16][96+(22*384*3)+12];
extern uint16_t dlsch_decoding_d[16][96+(22*384*3)+12];
void debug_check_decoder_input_buff( uint32_t Kr, uint32_t Zc, uint32_t r , LTE_DL_UE_HARQ_t *harq_process );
#endif
#if LDPC_FPGA_OFFLOAD
#include <dlfcn.h>
#include "ldpc_decoder_offload.h"
typedef session_t (*threegpp_nr_ldpc_decode_start_t)(session_desc_t *session_desc);
extern threegpp_nr_ldpc_decode_start_t threegpp_nr_ldpc_decode_start_funct;
typedef int32_t (*threegpp_nr_ldpc_decode_putq_t)( session_t fd,
int16_t *y_16bits,
uint8_t *decoded_bytes,
uint8_t r,
uint16_t n,
uint8_t max_iterations,
uint8_t crc_type);
extern threegpp_nr_ldpc_decode_putq_t threegpp_nr_ldpc_decode_putq_funct;
typedef int32_t (*threegpp_nr_ldpc_decode_getq_t)( session_t fd,
uint8_t *decoded_bytes,
uint8_t r,
uint8_t crc_type,
uint8_t *crc_status,
uint8_t *nb_iterations
);
extern threegpp_nr_ldpc_decode_getq_t threegpp_nr_ldpc_decode_getq_funct;
typedef int32_t (*threegpp_nr_ldpc_decode_stop_t)( session_t fd);
extern threegpp_nr_ldpc_decode_stop_t threegpp_nr_ldpc_decode_stop_funct;
typedef int32_t (*threegpp_nr_ldpc_decode_run_t)( session_t fd);
extern threegpp_nr_ldpc_decode_run_t threegpp_nr_ldpc_decode_run_funct;
#endif
//#define DEBUG_LLR_STATS
#ifdef DEBUG_LLR_STATS
static int16_t llr_max = 0;
static int16_t llr_min = 0;
static uint16_t llr_cnt = 0;
static double llr_p_mean = 0.0;
static double llr_p_cnt = 0.0;
static double llr_n_mean = 0.0;
static double llr_n_cnt = 0.0;
static double llr_p_mean1 = 0.0;
static double llr_p_cnt1 = 0.0;
static double llr_n_mean1 = 0.0;
static double llr_n_cnt1 = 0.0;
static void debug_llr_stats(void);
#endif
extern double cpuf;
// static uint32_t dbg_counter = 0;
// static uint8_t current_sf = 0;
uint32_t nr_dlsch_decoding_ldpc_offload(PHY_VARS_NR_UE *phy_vars_ue,
short *dlsch_llr,
NR_DL_FRAME_PARMS *frame_parms,
NR_UE_DLSCH_t *dlsch,
NR_DL_UE_HARQ_t *harq_process,
uint32_t frame,
uint16_t nb_symb_sch,
uint8_t nr_tti_rx,
uint8_t harq_pid,
uint8_t is_crnti,
uint8_t llr8_flag)
{
#if UE_TIMING_TRACE
time_stats_t *dlsch_rate_unmatching_stats=&phy_vars_ue->dlsch_rate_unmatching_stats;
time_stats_t *dlsch_turbo_decoding_stats=&phy_vars_ue->dlsch_turbo_decoding_stats;
time_stats_t *dlsch_deinterleaving_stats=&phy_vars_ue->dlsch_deinterleaving_stats;
#endif
uint8_t no_iteration_ldpc;
uint8_t crc_status_ldpc;
uint32_t A,E;
uint32_t G;
uint32_t ret,offset;
short dummy_w[MAX_NUM_DLSCH_SEGMENTS][3*(8448+64)];
uint32_t r,r_offset=0,Kr,Kr_bytes,err_flag=0, K_bytes_F;
uint8_t crc_type;
t_nrLDPC_dec_params decParams;
t_nrLDPC_dec_params* p_decParams = &decParams;
uint8_t kb;
uint8_t kc;
uint8_t Ilbrm = 0;
uint32_t Tbslbrm = 950984;
uint16_t nb_rb = 30;
double Coderate = 0.0;
//nfapi_nr_config_request_t *cfg = &phy_vars_ue->nrUE_config;
//uint8_t dmrs_type = cfg->pdsch_config.dmrs_type.value;
uint8_t nb_re_dmrs = 6; //(dmrs_type==NFAPI_NR_DMRS_TYPE1)?6:4;
uint16_t length_dmrs = 1; //cfg->pdsch_config.dmrs_max_length.value;
uint8_t iteration_max;
session_t ldpc_decoder_fd;
session_desc_t ldpc_decod_session_param;
uint32_t lpdc_decod_return;
#ifndef __AVX2__
AssertFatal (0, "dlsch_decoding_ldpc_offload - platform not supported (no AVX2)\n");
#endif
if (!dlsch_llr) {
printf("dlsch_decoding.c: NULL dlsch_llr pointer\n");
return(dlsch->max_ldpc_iterations);
}
if (!harq_process) {
printf("dlsch_decoding.c: NULL harq_process pointer\n");
return(dlsch->max_ldpc_iterations);
}
if (!frame_parms) {
printf("dlsch_decoding.c: NULL frame_parms pointer\n");
return(dlsch->max_ldpc_iterations);
}
/*if (nr_tti_rx> (10*frame_parms->ttis_per_subframe-1)) {
printf("dlsch_decoding.c: Illegal subframe index %d\n",nr_tti_rx);
return(dlsch->max_ldpc_iterations);
}
if (dlsch->harq_ack[nr_tti_rx].ack != 2) {
LOG_D(PHY, "[UE %d] DLSCH @ SF%d : ACK bit is %d instead of DTX even before PDSCH is decoded!\n",
phy_vars_ue->Mod_id, nr_tti_rx, dlsch->harq_ack[nr_tti_rx].ack);
}
if (llr8_flag != 0) {
AssertFatal (harq_process->TBS >= 256 , "Mismatch flag nbRB=%d TBS=%d mcs=%d Qm=%d RIV=%d round=%d \n",
harq_process->nb_rb, harq_process->TBS,harq_process->mcs,harq_process->Qm,harq_process->rvidx,harq_process->round);
}*/
err_flag = 0;
iteration_max = 0;
r_offset = 0;
nb_rb = harq_process->nb_rb;
harq_process->trials[harq_process->round]++;
harq_process->TBS = nr_compute_tbs(harq_process->mcs,nb_rb,nb_symb_sch,nb_re_dmrs,length_dmrs, harq_process->Nl);
A = harq_process->TBS;
ret = dlsch->max_ldpc_iterations;
harq_process->G = nr_get_G(nb_rb, nb_symb_sch, nb_re_dmrs, length_dmrs, harq_process->Qm,harq_process->Nl);
G = harq_process->G;
#ifdef DEBUG_DLSCH_DECODING
printf("\nDLSCH Decoding, harq_pid %d DCINdi %d round %d\n",harq_pid,harq_process->DCINdi, harq_process->round );
#endif
if (harq_process->round == 0) {
// printf("dlsch_decoding_ldpc_offload : Segmentation in (proc %d ) %d/%d \n",
// phy_vars_ue->current_thread_id[nr_tti_rx],
// frame,
// nr_tti_rx);
// fflush(stdout);
// This is a new packet, so compute quantities regarding segmentation
harq_process->B = A+24;
nr_segmentation(NULL,
NULL,
harq_process->B,
&harq_process->C,
&harq_process->K,
&harq_process->Z, // [hna] Z is Zc
&harq_process->F);
}
p_decParams->Z = harq_process->Z;
Coderate = (float) A /(float) G;
if ((A <=292) || ((A<=3824) && (Coderate <= 0.6667)) || Coderate <= 0.25)
{
p_decParams->BG = 2;
if (Coderate < 0.3333){
p_decParams->R = 15;
kc = 52;
}
else if (Coderate <0.6667){
p_decParams->R = 13;
kc = 32;
}
else {
p_decParams->R = 23;
kc = 17;
}
}
else{
p_decParams->BG = 1;
if (Coderate < 0.6667){
p_decParams->R = 13;
kc = 68;
}
else if (Coderate <0.8889){
p_decParams->R = 23;
kc = 35;
}
else {
p_decParams->R = 89;
kc = 27;
}
}
// Select CRC type
if (harq_process->C == 1)
crc_type = CRC24_A;
else
crc_type = CRC24_B;
p_decParams->numMaxIter = dlsch->max_ldpc_iterations;
p_decParams->outMode= 0;
#ifdef DEBUG_DLSCH_DECODING
printf("p_decParams Kplus=%d Z=%d BG=%d, R=%d, MaxIt.=%d \n",harq_process->Kplus,harq_process->Z,p_decParams->BG,p_decParams->R,p_decParams->numMaxIter);
#endif
ldpc_decod_session_param.proc_nb = phy_vars_ue->current_thread_id[nr_tti_rx];
ldpc_decod_session_param.frame = frame;
ldpc_decod_session_param.nr_tti_rx = nr_tti_rx;
ldpc_decod_session_param.BG = p_decParams->BG;
ldpc_decod_session_param.R = p_decParams->R;
ldpc_decod_session_param.Zc = harq_process->Z;
ldpc_decod_session_param.max_decoding_iterations= p_decParams->numMaxIter;
ldpc_decod_session_param.C = harq_process->C;
ldpc_decod_session_param.crc_type = crc_type;
ldpc_decod_session_param.mcs = harq_process->mcs;
ldpc_decoder_fd = threegpp_nr_ldpc_decode_start_funct(&ldpc_decod_session_param);
if( ldpc_decoder_fd == NULL )
{
printf("dlsch_decoding: Error getting FPGA decod session!!!\n");
harq_process->harq_ack.ack = 0;
harq_process->harq_ack.harq_id = harq_pid;
harq_process->harq_ack.send_harq_status = 1;
harq_process->errors[harq_process->round]++;
harq_process->round++;
// If we have reach harq max round or no mac (phytest mode) -> set harq process in idle mode
if ((harq_process->round >= dlsch->Mdlharq) || (phy_vars_ue->mac_enabled==0) )
{
harq_process->status = SCH_IDLE;
harq_process->round = 0;
}
if(is_crnti)
{
LOG_D(PHY,"[UE %d] DLSCH: Setting NACK for nr_tti_rx %d (pid %d, pid status %d, round %d/Max %d, TBS %d)\n",
phy_vars_ue->Mod_id,
nr_tti_rx,
harq_pid, harq_process->status, harq_process->round, dlsch->Mdlharq, harq_process->TBS);
}
return((1+dlsch->max_ldpc_iterations));
}
unsigned char bw_scaling =1;
switch (frame_parms->N_RB_DL) {
case 106:
bw_scaling =2;
break;
default:
bw_scaling =1;
break;
}
if (harq_process->C > MAX_NUM_DLSCH_SEGMENTS/bw_scaling) {
printf("Illegal harq_process->C %d > %d\n",harq_process->C,MAX_NUM_DLSCH_SEGMENTS/bw_scaling);
return( (1+dlsch->max_ldpc_iterations) );
}
#ifdef DEBUG_DLSCH_DECODING
printf("Segmentation: C %d, K %d\n",harq_process->C,harq_process->K);
#endif
/* ---------------------------------------------------------------------- */
/* ---------------------------------------------------------------------- */
/* LOOP OVER SEGMENTS */
/* ---------------------------------------------------------------------- */
/* ---------------------------------------------------------------------- */
#if UE_TIMING_TRACE
opp_enabled=1; // enable openair performance monitor
#endif
Kr = harq_process->K;
Kr_bytes = Kr>>3;
K_bytes_F = Kr_bytes-(harq_process->F>>3);
Tbslbrm = nr_compute_tbs(28,nb_rb,frame_parms->symbols_per_slot,0,0, harq_process->Nl);
for (r=0; r<harq_process->C; r++) {
E = nr_get_E(G, harq_process->C, harq_process->Qm, harq_process->Nl, r);
#if UE_TIMING_TRACE
start_meas(dlsch_deinterleaving_stats);
#endif
nr_deinterleaving_ldpc(E,
harq_process->Qm,
harq_process->w[r], // [hna] w is e
dlsch_llr+r_offset);
//for (int i =0; i<16; i++)
// printf("rx output deinterleaving w[%d]= %d r_offset %d\n", i,harq_process->w[r][i], r_offset);
#if UE_TIMING_TRACE
stop_meas(dlsch_deinterleaving_stats);
#endif
#if UE_TIMING_TRACE
start_meas(dlsch_rate_unmatching_stats);
#endif
#ifdef DEBUG_DLSCH_DECODING
LOG_D(PHY,"HARQ_PID %d Rate Matching Segment %d (coded bits %d,unpunctured/repeated bits %d, TBS %d, mod_order %d, nb_rb %d, Nl %d, rv %d, round %d)...\n",
harq_pid,r, G,
Kr*3,
harq_process->TBS,
harq_process->Qm,
harq_process->nb_rb,
harq_process->Nl,
harq_process->rvidx,
harq_process->round);
#endif
if (nr_rate_matching_ldpc_rx(Ilbrm,
Tbslbrm,
p_decParams->BG,
p_decParams->Z,
harq_process->d[r],
harq_process->w[r],
harq_process->C,
harq_process->rvidx,
(harq_process->round==0)?1:0,
E)==-1) {
#if UE_TIMING_TRACE
stop_meas(dlsch_rate_unmatching_stats);
#endif
LOG_E(PHY,"dlsch_decoding.c: Problem in rate_matching\n");
return(dlsch->max_ldpc_iterations);
} else {
#if UE_TIMING_TRACE
stop_meas(dlsch_rate_unmatching_stats);
#endif
}
//for (int i =0; i<16; i++)
// printf("rx output ratematching d[%d]= %d r_offset %d\n", i,harq_process->d[r][i], r_offset);
r_offset += E;
#ifdef DEBUG_DLSCH_DECODING
if (r==0) {
write_output("decoder_llr.m","decllr",dlsch_llr,G,1,0);
write_output("decoder_in.m","dec",&harq_process->d[0][0],(3*8*Kr_bytes)+12,1,0);
}
printf("decoder input(segment %d) :",r);
int i;
for (i=0;i<(3*8*Kr_bytes)+12;i++)
printf("%d : %d\n",i,harq_process->d[r][i]);
printf("\n");
#endif
// printf("Clearing c, %p\n",harq_process->c[r]);
memset(harq_process->c[r],0,Kr_bytes);
/* CLEARING OUTPUT BUFFER */
/* ---------------------------------------------------------------------- */
memset(harq_process->c[r],0,Kr_bytes);
/* Compute LLRs 16 statistics -> usefull for 8bits conversion dynamic */
#ifdef DEBUG_LLR_STATS
debug_llr_stats();
#endif
/* DECODING PROCESS */
/* ---------------------------------------------------------------------- */
// LDPC Decoder
#ifdef DLSIM_DECOD_CHECK
debug_check_decoder_input_buff( Kr, harq_process->Z , r , harq_process );
#endif
lpdc_decod_return = threegpp_nr_ldpc_decode_putq_funct( ldpc_decoder_fd,
&harq_process->d[r],
harq_process->c[r],
r,
Kr,
dlsch->max_ldpc_iterations,
crc_type
);
if (lpdc_decod_return){
printf("dlsch_decoding_ldpc_offload putq FAILED %s() %s:%d\n",
__FUNCTION__,
__FILE__,
__LINE__);
lpdc_decod_return = threegpp_nr_ldpc_decode_stop_funct(ldpc_decoder_fd);
return((1+dlsch->max_ldpc_iterations));
}
} // r Segments LOOP
#if 1
lpdc_decod_return = threegpp_nr_ldpc_decode_run_funct(ldpc_decoder_fd);
if (lpdc_decod_return)
{
printf("dlsch_decoding_ldpc_offload run FAILED %s() %s:%d !!!!!!!!!!\n",
__FUNCTION__,
__FILE__,
__LINE__);
lpdc_decod_return = threegpp_nr_ldpc_decode_stop_funct(ldpc_decoder_fd);
return((1+dlsch->max_ldpc_iterations));
}
// Wait for decoding offload ending
for (r=0; r<harq_process->C; r++)
{
nb_total_decod++;
total_decod ++;
g_ldpc_stat_per_subframe_array[nr_tti_rx].ldpc_block_decod_count ++;
// If no errors try to get next segment
// if ( ! err_flag )
// {
//VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_LDPC_DECOD_GETQ0+(phy_vars_ue->current_thread_id[nr_tti_rx]), 1);
lpdc_decod_return = threegpp_nr_ldpc_decode_getq_funct( ldpc_decoder_fd,
harq_process->c[r],
r,
crc_type,
&crc_status_ldpc,
&no_iteration_ldpc
);
//VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_LDPC_DECOD_GETQ0+(phy_vars_ue->current_thread_id[nr_tti_rx]), 0);
total_decod_it += no_iteration_ldpc;
g_ldpc_stat_per_subframe_array[nr_tti_rx].ldpc_block_decod_it += no_iteration_ldpc;
if ( lpdc_decod_return != LDPC_DECODER_OFFLOAD_OK )
{
nb_error_decod++;
total_decod_error++;
g_ldpc_stat_per_subframe_array[nr_tti_rx].ldpc_block_decod_error++;
err_flag++;
lpdc_decod_return = threegpp_nr_ldpc_decode_stop_funct(ldpc_decoder_fd);
return((1+dlsch->max_ldpc_iterations));
}
else if ( !crc_status_ldpc )
{
nb_error_decod++;
total_decod_error++;
total_decod_error_crc++;
err_flag++;
g_ldpc_stat_per_subframe_array[nr_tti_rx].ldpc_block_decod_error++;
g_ldpc_stat_per_subframe_array[nr_tti_rx].ldpc_block_decod_error_crc++;
// If CRC has failed it is likely that we will get max_iteration
iteration_max = (1+dlsch->max_ldpc_iterations);
LOG_W(PHY,"AbsSubframe %d.%d CRC failed, segment %d/%d \n",frame%1024,nr_tti_rx,r,harq_process->C-1);
}
else
{
if( iteration_max < no_iteration_ldpc )
iteration_max = no_iteration_ldpc;
}
if(!(total_decod%100000))
{
ldpc_stat_flag = 1;
}
} // r Segments LOOP
if( !nr_tti_rx && !(frame%1000) && ldpc_stat_flag) {
printf("\nLDPC BLER %f (%.6f %%) error %ld total %ld\n", (float)nb_error_decod/(float)nb_total_decod, (float)(nb_error_decod*100.0)/(float)nb_total_decod, nb_error_decod, nb_total_decod);
nb_error_decod = 0;
nb_total_decod = 0;
printf("ldpc_decode_getq total=%ld err=%ld (%.6f %%) crc_err=%ld it=%ld mean it.=%ld \n",
total_decod, total_decod_error, (float)total_decod_error/total_decod*100 ,total_decod_error_crc, total_decod_it, total_decod_it/total_decod );
for ( int dbg_loop=0; dbg_loop<10; dbg_loop++)
{
printf(" ldpc_stat subfram=%d %.4ld/%ld (%.2f %%) crc_err=%4.4ld it=%2.2ld mean it.=%ld max it.=%ld max_iterationblock_err=%ld\n",
dbg_loop,
g_ldpc_stat_per_subframe_array[dbg_loop].ldpc_block_decod_error,
g_ldpc_stat_per_subframe_array[dbg_loop].ldpc_block_decod_count,
(float)g_ldpc_stat_per_subframe_array[dbg_loop].ldpc_block_decod_error/(g_ldpc_stat_per_subframe_array[dbg_loop].ldpc_block_decod_count+1)*100 ,
g_ldpc_stat_per_subframe_array[dbg_loop].ldpc_block_decod_error_crc,
g_ldpc_stat_per_subframe_array[dbg_loop].ldpc_block_decod_it,
g_ldpc_stat_per_subframe_array[dbg_loop].ldpc_block_decod_it/(g_ldpc_stat_per_subframe_array[dbg_loop].ldpc_block_decod_count+1),
g_ldpc_stat_per_subframe_array[dbg_loop].ldpc_block_decod_max_it,
g_ldpc_stat_per_subframe_array[dbg_loop].ldpc_tb_error_block_max);
g_ldpc_stat_per_subframe_array[dbg_loop].ldpc_block_decod_count = 0;
g_ldpc_stat_per_subframe_array[dbg_loop].ldpc_block_decod_error = 0;
g_ldpc_stat_per_subframe_array[dbg_loop].ldpc_block_decod_error_crc = 0;
g_ldpc_stat_per_subframe_array[dbg_loop].ldpc_block_decod_it = 0;
g_ldpc_stat_per_subframe_array[dbg_loop].ldpc_block_decod_max_it = 0;
g_ldpc_stat_per_subframe_array[dbg_loop].ldpc_tb_error_block_max = 0;
}
printf("\n");
}
if(g_ldpc_stat_per_subframe_array[nr_tti_rx].ldpc_block_decod_max_it < iteration_max)
g_ldpc_stat_per_subframe_array[nr_tti_rx].ldpc_block_decod_max_it = iteration_max;
if( g_ldpc_stat_per_subframe_array[nr_tti_rx].ldpc_tb_error_block_max < err_flag )
g_ldpc_stat_per_subframe_array[nr_tti_rx].ldpc_tb_error_block_max = err_flag;
lpdc_decod_return = threegpp_nr_ldpc_decode_stop_funct(ldpc_decoder_fd);
#endif
// If we detect an error
if (err_flag)
ret = (1+dlsch->max_ldpc_iterations);
else
ret = iteration_max;
if (err_flag || ret == (1+dlsch->max_ldpc_iterations) )
{
#if UE_DEBUG_TRACE
LOG_I(PHY,"[UE %d] DLSCH: Setting NAK for SFN/SF %d/%d (pid %d, status %d, round %d, TBS %d, mcs %d) Kr %d r %d harq_process->round %d\n",
phy_vars_ue->Mod_id, frame, nr_tti_rx, harq_pid,harq_process->status, harq_process->round,harq_process->TBS,harq_process->mcs,Kr,r,harq_process->round);
#endif
harq_process->harq_ack.ack = 0;
harq_process->harq_ack.harq_id = harq_pid;
harq_process->harq_ack.send_harq_status = 1;
harq_process->errors[harq_process->round]++;
harq_process->round++;
// If we have reach harq max round or no mac (phytest mode) -> set harq process in idle mode
if ((harq_process->round >= dlsch->Mdlharq) || (phy_vars_ue->mac_enabled==0) )
{
harq_process->status = SCH_IDLE;
harq_process->round = 0;
}
if(is_crnti)
{
LOG_D(PHY,"[UE %d] DLSCH: Setting NACK for nr_tti_rx %d (pid %d, pid status %d, round %d/Max %d, TBS %d)\n",
phy_vars_ue->Mod_id,
nr_tti_rx,
harq_pid, harq_process->status, harq_process->round, dlsch->Mdlharq, harq_process->TBS);
}
return((1+dlsch->max_ldpc_iterations));
}
else
{
#if UE_DEBUG_TRACE
LOG_I(PHY,"[UE %d] DLSCH: Setting ACK for nr_tti_rx %d TBS %d mcs %d nb_rb %d harq_process->round %d\n",
phy_vars_ue->Mod_id,nr_tti_rx,harq_process->TBS,harq_process->mcs,harq_process->nb_rb, harq_process->round);
#endif
harq_process->status = SCH_IDLE;
harq_process->round = 0;
harq_process->harq_ack.ack = 1;
harq_process->harq_ack.harq_id = harq_pid;
harq_process->harq_ack.send_harq_status = 1;
if(is_crnti)
{
LOG_D(PHY,"[UE %d] DLSCH: Setting ACK for nr_tti_rx %d (pid %d, round %d, TBS %d)\n",
phy_vars_ue->Mod_id,
nr_tti_rx,
harq_pid, harq_process->round, harq_process->TBS);
}
}
// Reassembly of Transport block here
offset = 0;
Kr = harq_process->K;
Kr_bytes = Kr>>3;
for (r=0; r<harq_process->C; r++) {
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));
#ifdef DEBUG_DLSCH_DECODING
printf("Segment %d : Kr= %d bytes\n",r,Kr_bytes);
printf("copied %d bytes to b sequence (harq_pid %d)\n",
(Kr_bytes - (harq_process->F>>3)-((harq_process->C>1)?3:0)),harq_pid);
printf("b[0] = %x,c[%d] = %x\n",
harq_process->b[offset],
harq_process->F>>3,
harq_process->c[r]);
#endif
}
dlsch->last_iteration_cnt = ret;
return(ret);
}
#ifdef DEBUG_LLR_STATS
void debug_llr_stats(void)
{
// first LLR seems to be buggous, wait a little before compute statistics
if (llr_cnt > 1024)
{
llr_p_mean1 = 0.0;
llr_p_cnt1 = 0.0;
llr_n_mean1 = 0.0;
llr_n_cnt1 = 0.0;
for (int i = 0; i < Kr*3; i++)
{
if (harq_process->d[r][96+i] > llr_max)
llr_max = harq_process->d[r][96+i];
if (harq_process->d[r][96+i] < llr_min)
llr_min = harq_process->d[r][96+i];
if (harq_process->d[r][96+i] > 0)
{
llr_p_mean1 += harq_process->d[r][96+i];
llr_p_cnt1 += 1.0;
}
if (harq_process->d[r][96+i] < 0)
{
llr_n_mean1 += harq_process->d[r][96+i];
llr_n_cnt1 += 1.0;
}
}
llr_n_mean += llr_n_mean1;
llr_n_cnt += llr_n_cnt1;
llr_p_mean += llr_p_mean1;
llr_p_cnt += llr_p_mean1;
}
llr_cnt++;
if ( !(llr_cnt%4096) )
{
printf("LDPC decoding LLRmax=%d LLRmin=%d pLLRmean=%lf (cnt:%lf) nLLRmean=%lf (cnt:%lf) pLLRmean1=%lf (cnt1:%lf) nLLRmean1=%lf (cnt1:%lf)\n",
llr_max,
llr_min,
(llr_p_mean/llr_p_cnt),
llr_p_cnt,
(llr_n_mean/llr_n_cnt),
llr_n_cnt,
(llr_p_mean1/llr_p_cnt1),
llr_p_cnt1,
(llr_n_mean1/llr_n_cnt1),
llr_n_cnt1);
}
return;
}
#endif
#ifdef DLSIM_DECOD_CHECK
static uint32_t failure_cnt = 0;
static uint32_t total_cnt = 0;
void debug_check_decoder_input_buff( uint32_t Kr, uint32_t Zc, uint32_t r , LTE_DL_UE_HARQ_t *harq_process )
{
uint32_t failure = 0;
uint32_t poncture = 0;
uint32_t failure_systematic = 0;
uint32_t poncture_systematic = 0;
uint32_t failure_parity89 = 0;
uint32_t poncture_parity89 = 0;
uint32_t failure_parity13 = 0;
uint32_t poncture_parity13 = 0;
total_cnt++;
// LLR coded data
for (int i = 0; i < (Kr*3); i++)
{
uint8_t bit = ((uint16_t *)harq_process->d[r])[96+i]&0x8000 ? 0 : 1;
// Check for Poncturing
if (!((uint16_t *)harq_process->d[r])[96+i]){
poncture++;
if (i < Zc*20)
poncture_systematic++;
else if (i < Zc*25)
poncture_parity89++;
else{
//poncture_parity13++;
}
}
// Check for erronous position
if ((bit-dlsch_coding_d[r][96+i]) || (!((uint16_t *)harq_process->d[r])[96+i]) ) {
if (i< Zc*20){
failure++;
failure_systematic++;
}
else if (i< Zc*25){
failure++;
failure_parity89++;
}
else{
//failure++;
//failure_parity13++;
}
}
}
if (failure)
{
failure_cnt++;
#if 1
printf("!! SYRTEM failure_cnt = %d/%d - r=%d - failure=%d/%d sys=%d parity89=%d parity13=%d !!!\n",
failure_cnt, total_cnt, r,
failure, Kr*3, failure_systematic, failure_parity89, failure_parity13 );
printf("!! SYRTEM %d - r=%d - poncture=%d sys=%d parity89=%d parity13=%d !!!\n",
Kr*3, r,
poncture, poncture_systematic, poncture_parity89, poncture_parity13 );
#endif
}
return;
}
#endif
#endif // LDPC_FPGA_OFFLOAD
......@@ -1804,6 +1804,18 @@ uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue,
uint8_t is_crnti,
uint8_t llr8_flag);
uint32_t nr_dlsch_decoding_ldpc_offload(PHY_VARS_NR_UE *phy_vars_ue,
short *dlsch_llr,
NR_DL_FRAME_PARMS *frame_parms,
NR_UE_DLSCH_t *dlsch,
NR_DL_UE_HARQ_t *harq_process,
uint32_t frame,
uint16_t nb_symb_sch,
uint8_t nr_tti_rx,
uint8_t harq_pid,
uint8_t is_crnti,
uint8_t llr8_flag);
int nr_extract_dci_info(PHY_VARS_NR_UE *ue,
uint8_t eNB_id,
lte_frame_type_t frame_type,
......
......@@ -3673,6 +3673,20 @@ void nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue,
dlsch0->harq_processes[harq_pid]->TBS>256?1:0);
LOG_T(PHY,"UE_DLSCH_PARALLELISATION is defined, ret = %d\n", ret);
#else
#if LDPC_FPGA_OFFLOAD
ret = nr_dlsch_decoding_ldpc_offload(ue,
pdsch_vars->llr[0],
&ue->frame_parms,
dlsch0,
dlsch0->harq_processes[harq_pid],
frame_rx,
nb_symb_sch,
nr_tti_rx,
harq_pid,
pdsch==PDSCH?1:0,
dlsch0->harq_processes[harq_pid]->TBS>256?1:0);
//printf("start cW0 dlsch decoding\n");
#else
ret = nr_dlsch_decoding(ue,
pdsch_vars->llr[0],
&ue->frame_parms,
......@@ -3686,6 +3700,7 @@ void nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue,
dlsch0->harq_processes[harq_pid]->TBS>256?1:0);
LOG_T(PHY,"UE_DLSCH_PARALLELISATION is NOT defined, ret = %d\n", ret);
//printf("start cW0 dlsch decoding\n");
#endif
#endif
#if UE_TIMING_TRACE
......
/* ============================================================================
*
* file ldpc_decoder_offload.h
* author B.ROBERT
* date Jan 10, 2018
*
* brief LDPC Decoder Offload interface header.
*
* Infos:
* - Project : syr_ldpc_offload_lib
* - Software :
* - CVS domain : syrtemplatform5g
* - CVS component :
*
* ============================================================================
* Statement of Ownership
* ----------------------
* Copyright (c) 2018-2019 SYRTEM S.a.r.l All Rights Reserved
*
* This software is furnished under licence and may be used and copied only
* in accordance with the terms of such license and with the inclusion of the
* above COPYRIGHT notice. This SOFTWARE or any other copies thereof may not
* be provided or otherwise made available to any other person. No title to
* and ownership of the SOFTWARE is hereby transferred.
*
* The information in this SOFTWARE is subject to change without notice and
* should not be constructed as a commitment by SYRTEM.
*
* SYRTEM assumes no responsability for the use or reliability of its SOFTWARE
* on equipment or platform not explicitly validated by SYRTEM.
*
* ============================================================================
* Reference documents :
* -------------------
*
* ==========================================================================*/
#ifndef __LDPC_DECODER_OFFLOAD_LIB_H__
#define __LDPC_DECODER_OFFLOAD_LIB_H__
#define LDPC_DECODER_OFFLOAD_OK (0)
#define LDPC_DECODER_OFFLOAD_ERROR (-1)
#define LDPC_DECODER_OFFLOAD_BAD_PARAMETER (-2)
#define LDPC_DECODER_OFFLOAD_PRECONDITION_NOT_MET (-3)
#define LDPC_DECODER_OFFLOAD_NOT_SUPPORTED (-4)
#define LDPC_DECODER_OFFLOAD_NO_CONTEXT (-5)
#define LDPC_DECODER_OFFLOAD_DEVICE_NOT_FOUND (-6)
#define LDPC_DECODER_OFFLOAD_CHANNEL_NOT_FOUND (-7)
#define LDPC_DECODER_OFFLOAD_BUFFER_NOT_CREATED (-8)
#define LDPC_DECODER_OFFLOAD_INITCFG_FAILED (-9)
#define LDPC_DECODER_OFFLOAD_SELF_TEST_FAILED (-10)
#define LDPC_DECODER_OFFLOAD_SYRIQ_INIT_FAILED (-11)
#define LDPC_DECODER_OFFLOAD_TH_INIT_FAILED (-12)
#define LDPC_DECODER_OFFLOAD_DECOD_REQ_NULL (-20)
#define LDPC_DECODER_OFFLOAD_ERROR_TIMEOUT (-30)
typedef void *session_t;
typedef struct session_desc_s
{
uint32_t proc_nb;
uint32_t frame;
uint32_t nr_tti_rx; // ~ tti number
uint32_t BG;
uint32_t R;
uint8_t coderate; // 0x01:BG1 8/9 27.Zc
// 0x2A:BG1 1/3 68.Zc,
// 0x43:BG2 2/3 17.Zc,
// 0x66:BG2 1/5 52.Zc,
uint32_t Zc; // 128, 160, 224, 256, 384
uint8_t max_decoding_iterations;
uint32_t C;
uint8_t crc_type;
uint8_t mcs;
} session_desc_t;
typedef enum ldpc_msgtype_e
{
LDPC_DECODING_OFFLOAD_REQ,
LDPC_DECODING_OFFLOAD_CONF
} ldpc_msgtype_t;
typedef struct decode_req_s
{
ldpc_msgtype_t msg_type;
uint32_t proc_nb;
uint32_t r; // seg. index from 1 to 16 max
int16_t *data; // 16bit LLR buffer pointer
} decode_req_t;
typedef struct decode_conf_s
{
ldpc_msgtype_t msg_type;
uint32_t proc_nb;
uint32_t segment_no; // from 1 to 16 max
uint32_t crc24_check;
uint32_t nb_iterations;
uint8_t *data; // Hard decoded bits buffer pointer
} decode_conf_t;
session_t threegpp_nr_ldpc_decode_start(session_desc_t *session_desc);
int32_t threegpp_nr_ldpc_decode_putq( session_t fd,
int16_t *y_16bits,
uint8_t *decoded_bytes,
uint8_t r,
uint16_t n,
uint8_t max_iterations,
uint8_t crc_type
);
int32_t threegpp_nr_ldpc_decode_getq( session_t fd,
uint8_t *decoded_bytes,
uint8_t r,
uint8_t crc_type,
uint8_t *crc_status,
uint8_t *nb_iterations
);
int32_t threegpp_nr_ldpc_decode_stop(session_t fd);
int32_t threegpp_nr_ldpc_decode_run(session_t fd);
/*!
\brief This routine performs max-logmap detection for the 3GPP turbo code (with termination). It is optimized for SIMD processing and 16-bit
LLR arithmetic, and requires SSE2,SSSE3 and SSE4.1 (gcc >=4.3 and appropriate CPU)
@param y LLR input (16-bit precision)
@param decoded_bytes Pointer to decoded output
@param n number of coded bits (including tail bits)
@param max_iterations The maximum number of iterations to perform
@param interleaver_f1 F1 generator
@param interleaver_f2 F2 generator
@param crc_type Length of 3GPPLTE crc (CRC24a,CRC24b,CRC16,CRC8)
@param F Number of filler bits at start of packet
@returns number of iterations used (this is 1+max if incorrect crc or if crc_len=0)
*/
uint8_t phy_threegppnr_ldpc_decoder_offload(int16_t *y,
uint8_t *decoded_bytes,
uint16_t n,
uint16_t interleaver_f1,
uint16_t interleaver_f2,
uint8_t max_iterations,
uint8_t crc_type,
uint8_t F,
time_stats_t *init_stats,
time_stats_t *alpha_stats,
time_stats_t *beta_stats,
time_stats_t *gamma_stats,
time_stats_t *ext_stats,
time_stats_t *intl1_stats,
time_stats_t *intl2_stats);
uint8_t phy_threegppnr_ldpc_decoder_offload_init(void);
uint8_t phy_threegppnr_ldpc_decoder_offload_fini(void);
#endif // __LDPC_DECODER_OFFLOAD_LIB_H__
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment