/*============================================================================== * nrLDPC_decoder.c * * Defines the LDPC decoder * p_llrOut = output LLRs aligned on 32 byte boundaries * * Author: Sebastian Wagner * Date: 17-11-2017 * ===============================================================================*/ #include <stdint.h> #include <immintrin.h> #include "nrLDPC_defs.h" #include "nrLDPC_types.h" #include "nrLDPC_init.h" #include "nrLDPC_mPass.h" #include "nrLDPC_cnProc.h" #include "nrLDPC_bnProc.h" static inline void nrLDPC_decoder_core(int8_t* p_llr, int8_t* p_out, uint32_t numLLR, t_nrLDPC_lut* p_lut, t_nrLDPC_dec_params* p_decParams, t_nrLDPC_time_stats* p_profiler); void nrLDPC_decoder(t_nrLDPC_dec_params* p_decParams, int8_t* p_llr, int8_t* p_out, t_nrLDPC_time_stats* p_profiler) { uint32_t numLLR; t_nrLDPC_lut lut; t_nrLDPC_lut* p_lut = &lut; // Initialize decoder core(s) with correct LUTs numLLR = nrLDPC_init(p_decParams, p_lut); // Launch LDPC decoder core for one segment nrLDPC_decoder_core(p_llr, p_out, numLLR, p_lut, p_decParams, p_profiler); } static inline void nrLDPC_decoder_core(int8_t* p_llr, int8_t* p_out, uint32_t numLLR, t_nrLDPC_lut* p_lut, t_nrLDPC_dec_params* p_decParams, t_nrLDPC_time_stats* p_profiler) { uint16_t Z = p_decParams->Z; uint8_t BG = p_decParams->BG; uint8_t numMaxIter = p_decParams->numMaxIter; e_nrLDPC_outMode outMode = p_decParams->outMode; uint32_t i = 1; int8_t* p_llrOut; if (outMode == nrLDPC_outMode_LLRINT8) { p_llrOut = p_out; } else { // Use LLR processing buffer as temporary output buffer p_llrOut = (int8_t*) llrProcBuf; } // Initialization #ifdef NR_LDPC_PROFILER_DETAIL start_meas(&p_profiler->llr2llrProcBuf); #endif nrLDPC_llr2llrProcBuf(p_lut, p_llr, Z, BG); #ifdef NR_LDPC_PROFILER_DETAIL stop_meas(&p_profiler->llr2llrProcBuf); #endif #ifdef NR_LDPC_PROFILER_DETAIL start_meas(&p_profiler->llr2CnProcBuf); #endif nrLDPC_llr2CnProcBuf(p_lut, p_llr, numLLR, Z, BG); #ifdef NR_LDPC_PROFILER_DETAIL stop_meas(&p_profiler->llr2CnProcBuf); #endif // First iteration #ifdef NR_LDPC_PROFILER_DETAIL start_meas(&p_profiler->cnProc); #endif if (BG == 1) { nrLDPC_cnProc_BG1(p_lut, Z); } else { nrLDPC_cnProc(p_lut, Z); } #ifdef NR_LDPC_PROFILER_DETAIL stop_meas(&p_profiler->cnProc); #endif #ifdef NR_LDPC_PROFILER_DETAIL start_meas(&p_profiler->cn2bnProcBuf); #endif if (BG == 1) { nrLDPC_cn2bnProcBuf_BG1(p_lut, Z); } else { nrLDPC_cn2bnProcBuf(p_lut, Z); } #ifdef NR_LDPC_PROFILER_DETAIL stop_meas(&p_profiler->cn2bnProcBuf); #endif #ifdef NR_LDPC_PROFILER_DETAIL start_meas(&p_profiler->bnProcPc); #endif nrLDPC_bnProcPc(p_lut, Z); #ifdef NR_LDPC_PROFILER_DETAIL stop_meas(&p_profiler->bnProcPc); #endif // Parity check should occur here // First iteration finished while (i < numMaxIter) { // BN processing #ifdef NR_LDPC_PROFILER_DETAIL start_meas(&p_profiler->bnProc); #endif nrLDPC_bnProc(p_lut, Z); #ifdef NR_LDPC_PROFILER_DETAIL stop_meas(&p_profiler->bnProc); #endif // BN results to CN processing buffer #ifdef NR_LDPC_PROFILER_DETAIL start_meas(&p_profiler->bn2cnProcBuf); #endif if (BG == 1) { nrLDPC_bn2cnProcBuf_BG1(p_lut, Z); } else { nrLDPC_bn2cnProcBuf(p_lut, Z); } #ifdef NR_LDPC_PROFILER_DETAIL stop_meas(&p_profiler->bn2cnProcBuf); #endif // CN processing #ifdef NR_LDPC_PROFILER_DETAIL start_meas(&p_profiler->cnProc); #endif if (BG == 1) { nrLDPC_cnProc_BG1(p_lut, Z); } else { nrLDPC_cnProc(p_lut, Z); } #ifdef NR_LDPC_PROFILER_DETAIL stop_meas(&p_profiler->cnProc); #endif // Send CN results back to BNs #ifdef NR_LDPC_PROFILER_DETAIL start_meas(&p_profiler->cn2bnProcBuf); #endif if (BG == 1) { nrLDPC_cn2bnProcBuf_BG1(p_lut, Z); } else { nrLDPC_cn2bnProcBuf(p_lut, Z); } #ifdef NR_LDPC_PROFILER_DETAIL stop_meas(&p_profiler->cn2bnProcBuf); #endif #ifdef NR_LDPC_PROFILER_DETAIL start_meas(&p_profiler->bnProcPc); #endif nrLDPC_bnProcPc(p_lut, Z); #ifdef NR_LDPC_PROFILER_DETAIL stop_meas(&p_profiler->bnProcPc); #endif // Do parity check i++; } // Assign results from processing buffer to output #ifdef NR_LDPC_PROFILER_DETAIL start_meas(&p_profiler->llrRes2llrOut); #endif nrLDPC_llrRes2llrOut(p_lut, p_llrOut, numLLR); #ifdef NR_LDPC_PROFILER_DETAIL stop_meas(&p_profiler->llrRes2llrOut); #endif // Hard-decision #ifdef NR_LDPC_PROFILER_DETAIL start_meas(&p_profiler->llr2bit); #endif 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); } #ifdef NR_LDPC_PROFILER_DETAIL stop_meas(&p_profiler->llr2bit); #endif }