fixed AVX2 issue for cnProc code generator. Some cleanup in formatting and deleting unused files.

This commit is contained in:
Raymond Knopp
2022-06-12 23:23:07 +02:00
parent aabd9c6c4e
commit f6bb869c0b
8 changed files with 982 additions and 5489 deletions
File diff suppressed because it is too large Load Diff
-505
View File
@@ -1,505 +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 nrLDPC_decoder.c
* \brief Defines the LDPC decoder
* \author Sebastian Wagner (TCL Communications) Email: <mailto:sebastian.wagner@tcl.com>
* \date 30-09-2019
* \version 2.0
* \note
* \warning
*/
#include <stdint.h>
#include <immintrin.h>
#include "nrLDPCdecoder_defs.h"
#include "nrLDPC_types.h"
#include "nrLDPC_init.h"
#include "nrLDPC_mPass.h"
#include "nrLDPC_cnProc.h"
#include "nrLDPC_bnProc.h"
#define NR_LDPC_ENABLE_PARITY_CHECK
#define NR_LDPC_PROFILER_DETAIL
#ifdef NR_LDPC_DEBUG_MODE
#include "nrLDPC_tools/nrLDPC_debug.h"
#endif
static inline uint32_t nrLDPC_decoder_core(int8_t* p_llr, int8_t* p_out, t_nrLDPC_procBuf* p_procBuf, uint32_t numLLR, t_nrLDPC_lut* p_lut, t_nrLDPC_dec_params* p_decParams, t_nrLDPC_time_stats* p_profiler);
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* p_profiler)
{
uint32_t numLLR;
uint32_t numIter = 0;
t_nrLDPC_lut lut;
t_nrLDPC_lut* p_lut = &lut;
//printf("p_procBuf->cnProcBuf = %p\n", p_procBuf->cnProcBuf);
// Initialize decoder core(s) with correct LUTs
numLLR = nrLDPC_init(p_decParams, p_lut);
// Launch LDPC decoder core for one segment
numIter = nrLDPC_decoder_core(p_llr, p_out, p_procBuf, numLLR, p_lut, p_decParams, p_profiler);
return numIter;
}
/**
\brief Performs LDPC decoding of one code block
\param p_llr Input LLRs
\param p_out Output vector
\param numLLR Number of LLRs
\param p_lut Pointer to decoder LUTs
\param p_decParams LDPC decoder parameters
\param p_profiler LDPC profiler statistics
*/
static inline uint32_t nrLDPC_decoder_core(int8_t* p_llr, int8_t* p_out, t_nrLDPC_procBuf* p_procBuf, 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;
// Minimum number of iterations is 1
// 0 iterations means hard-decision on input LLRs
uint32_t i = 1;
// Initialize with parity check fail != 0
int32_t pcRes = 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 = p_procBuf->llrProcBuf;
// Clear llrProcBuf
memset(p_llrOut,0, NR_LDPC_MAX_NUM_LLR*sizeof(int8_t));
}
// Initialization
#ifdef NR_LDPC_PROFILER_DETAIL
start_meas(&p_profiler->llr2llrProcBuf);
#endif
nrLDPC_llr2llrProcBuf(p_lut, p_llr, p_procBuf, Z, BG);
#ifdef NR_LDPC_PROFILER_DETAIL
stop_meas(&p_profiler->llr2llrProcBuf);
#endif
#ifdef NR_LDPC_DEBUG_MODE
nrLDPC_debug_initBuffer2File(nrLDPC_buffers_LLR_PROC);
nrLDPC_debug_writeBuffer2File(nrLDPC_buffers_LLR_PROC, p_procBuf);
#endif
#ifdef NR_LDPC_PROFILER_DETAIL
start_meas(&p_profiler->llr2CnProcBuf);
#endif
if (BG == 1)
{
nrLDPC_llr2CnProcBuf_BG1(p_lut, p_llr, p_procBuf, Z);
}
else
{
nrLDPC_llr2CnProcBuf_BG2(p_lut, p_llr, p_procBuf, Z);
}
#ifdef NR_LDPC_PROFILER_DETAIL
stop_meas(&p_profiler->llr2CnProcBuf);
#endif
#ifdef NR_LDPC_DEBUG_MODE
nrLDPC_debug_initBuffer2File(nrLDPC_buffers_CN_PROC);
nrLDPC_debug_writeBuffer2File(nrLDPC_buffers_CN_PROC, p_procBuf);
#endif
// First iteration
// CN processing
#ifdef NR_LDPC_PROFILER_DETAIL
start_meas(&p_profiler->cnProc);
#endif
if (BG == 1)
{
#ifdef __AVX512BW__
nrLDPC_cnProc_BG1_AVX512(p_lut, p_procBuf, Z);
#else
nrLDPC_cnProc_BG1(p_lut, p_procBuf, Z);
#endif
}
else
{
nrLDPC_cnProc_BG2(p_lut, p_procBuf, Z);
}
#ifdef NR_LDPC_PROFILER_DETAIL
stop_meas(&p_profiler->cnProc);
#endif
#ifdef NR_LDPC_DEBUG_MODE
nrLDPC_debug_initBuffer2File(nrLDPC_buffers_CN_PROC_RES);
nrLDPC_debug_writeBuffer2File(nrLDPC_buffers_CN_PROC_RES, p_procBuf);
#endif
#ifdef NR_LDPC_PROFILER_DETAIL
start_meas(&p_profiler->cn2bnProcBuf);
#endif
if (BG == 1)
{
nrLDPC_cn2bnProcBuf_BG1(p_lut, p_procBuf, Z);
}
else
{
nrLDPC_cn2bnProcBuf_BG2(p_lut, p_procBuf, Z);
}
#ifdef NR_LDPC_PROFILER_DETAIL
stop_meas(&p_profiler->cn2bnProcBuf);
#endif
#ifdef NR_LDPC_DEBUG_MODE
nrLDPC_debug_initBuffer2File(nrLDPC_buffers_BN_PROC);
nrLDPC_debug_writeBuffer2File(nrLDPC_buffers_BN_PROC, p_procBuf);
#endif
// BN processing
#ifdef NR_LDPC_PROFILER_DETAIL
start_meas(&p_profiler->bnProcPc);
#endif
nrLDPC_bnProcPc(p_lut, p_procBuf, Z);
#ifdef NR_LDPC_PROFILER_DETAIL
stop_meas(&p_profiler->bnProcPc);
#endif
#ifdef NR_LDPC_DEBUG_MODE
nrLDPC_debug_initBuffer2File(nrLDPC_buffers_LLR_RES);
nrLDPC_debug_writeBuffer2File(nrLDPC_buffers_LLR_RES, p_procBuf);
#endif
#ifdef NR_LDPC_PROFILER_DETAIL
start_meas(&p_profiler->bnProc);
#endif
nrLDPC_bnProc(p_lut, p_procBuf, Z);
#ifdef NR_LDPC_PROFILER_DETAIL
stop_meas(&p_profiler->bnProc);
#endif
#ifdef NR_LDPC_DEBUG_MODE
nrLDPC_debug_initBuffer2File(nrLDPC_buffers_BN_PROC_RES);
nrLDPC_debug_writeBuffer2File(nrLDPC_buffers_BN_PROC_RES, p_procBuf);
#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, p_procBuf, Z);
}
else
{
nrLDPC_bn2cnProcBuf_BG2(p_lut, p_procBuf, Z);
}
#ifdef NR_LDPC_PROFILER_DETAIL
stop_meas(&p_profiler->bn2cnProcBuf);
#endif
#ifdef NR_LDPC_DEBUG_MODE
nrLDPC_debug_writeBuffer2File(nrLDPC_buffers_CN_PROC, p_procBuf);
#endif
// Parity Check not necessary here since it will fail
// because first 2 cols/BNs in BG are punctured and cannot be
// estimated after only one iteration
// First iteration finished
while ( (i < (numMaxIter-1)) && (pcRes != 0) )
{
// Increase iteration counter
i++;
// CN processing
#ifdef NR_LDPC_PROFILER_DETAIL
start_meas(&p_profiler->cnProc);
#endif
if (BG == 1)
{
#ifdef __AVX512BW__
nrLDPC_cnProc_BG1_AVX512(p_lut, p_procBuf, Z);
#else
nrLDPC_cnProc_BG1(p_lut, p_procBuf, Z);
#endif
}
else
{
nrLDPC_cnProc_BG2(p_lut, p_procBuf, Z);
}
#ifdef NR_LDPC_PROFILER_DETAIL
stop_meas(&p_profiler->cnProc);
#endif
#ifdef NR_LDPC_DEBUG_MODE
nrLDPC_debug_writeBuffer2File(nrLDPC_buffers_CN_PROC_RES, p_procBuf);
#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, p_procBuf, Z);
}
else
{
nrLDPC_cn2bnProcBuf_BG2(p_lut, p_procBuf, Z);
}
#ifdef NR_LDPC_PROFILER_DETAIL
stop_meas(&p_profiler->cn2bnProcBuf);
#endif
#ifdef NR_LDPC_DEBUG_MODE
nrLDPC_debug_writeBuffer2File(nrLDPC_buffers_BN_PROC, p_procBuf);
#endif
// BN Processing
#ifdef NR_LDPC_PROFILER_DETAIL
start_meas(&p_profiler->bnProcPc);
#endif
nrLDPC_bnProcPc(p_lut, p_procBuf, Z);
#ifdef NR_LDPC_PROFILER_DETAIL
stop_meas(&p_profiler->bnProcPc);
#endif
#ifdef NR_LDPC_DEBUG_MODE
nrLDPC_debug_writeBuffer2File(nrLDPC_buffers_LLR_RES, p_procBuf);
#endif
#ifdef NR_LDPC_PROFILER_DETAIL
start_meas(&p_profiler->bnProc);
#endif
nrLDPC_bnProc(p_lut, p_procBuf, Z);
#ifdef NR_LDPC_PROFILER_DETAIL
stop_meas(&p_profiler->bnProc);
#endif
#ifdef NR_LDPC_DEBUG_MODE
nrLDPC_debug_writeBuffer2File(nrLDPC_buffers_BN_PROC_RES, p_procBuf);
#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, p_procBuf, Z);
}
else
{
nrLDPC_bn2cnProcBuf_BG2(p_lut, p_procBuf, Z);
}
#ifdef NR_LDPC_PROFILER_DETAIL
stop_meas(&p_profiler->bn2cnProcBuf);
#endif
#ifdef NR_LDPC_DEBUG_MODE
nrLDPC_debug_writeBuffer2File(nrLDPC_buffers_CN_PROC, p_procBuf);
#endif
// Parity Check
#ifdef NR_LDPC_ENABLE_PARITY_CHECK
#ifdef NR_LDPC_PROFILER_DETAIL
start_meas(&p_profiler->cnProcPc);
#endif
if (BG == 1)
{
pcRes = nrLDPC_cnProcPc_BG1(p_lut, p_procBuf, Z);
}
else
{
pcRes = nrLDPC_cnProcPc_BG2(p_lut, p_procBuf, Z);
}
#ifdef NR_LDPC_PROFILER_DETAIL
stop_meas(&p_profiler->cnProcPc);
#endif
#endif
}
// Last iteration
if ( (i < numMaxIter) && (pcRes != 0) )
{
// Increase iteration counter
i++;
// CN processing
#ifdef NR_LDPC_PROFILER_DETAIL
start_meas(&p_profiler->cnProc);
#endif
if (BG == 1)
{
#ifdef __AVX512BW__
nrLDPC_cnProc_BG1_AVX512(p_lut, p_procBuf, Z);
#else
nrLDPC_cnProc_BG1(p_lut, p_procBuf, Z);
#endif
}
else
{
nrLDPC_cnProc_BG2(p_lut, p_procBuf, Z);
}
#ifdef NR_LDPC_PROFILER_DETAIL
stop_meas(&p_profiler->cnProc);
#endif
#ifdef NR_LDPC_DEBUG_MODE
nrLDPC_debug_writeBuffer2File(nrLDPC_buffers_CN_PROC_RES, p_procBuf);
#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, p_procBuf, Z);
}
else
{
nrLDPC_cn2bnProcBuf_BG2(p_lut, p_procBuf, Z);
}
#ifdef NR_LDPC_PROFILER_DETAIL
stop_meas(&p_profiler->cn2bnProcBuf);
#endif
#ifdef NR_LDPC_DEBUG_MODE
nrLDPC_debug_writeBuffer2File(nrLDPC_buffers_BN_PROC, p_procBuf);
#endif
// BN Processing
#ifdef NR_LDPC_PROFILER_DETAIL
start_meas(&p_profiler->bnProcPc);
#endif
nrLDPC_bnProcPc(p_lut, p_procBuf, Z);
#ifdef NR_LDPC_PROFILER_DETAIL
stop_meas(&p_profiler->bnProcPc);
#endif
#ifdef NR_LDPC_DEBUG_MODE
nrLDPC_debug_writeBuffer2File(nrLDPC_buffers_LLR_RES, p_procBuf);
#endif
// If parity check not enabled, no need to send the BN proc results
// back to CNs
#ifdef NR_LDPC_ENABLE_PARITY_CHECK
#ifdef NR_LDPC_PROFILER_DETAIL
start_meas(&p_profiler->bnProc);
#endif
nrLDPC_bnProc(p_lut, p_procBuf, Z);
#ifdef NR_LDPC_PROFILER_DETAIL
stop_meas(&p_profiler->bnProc);
#endif
#ifdef NR_LDPC_DEBUG_MODE
nrLDPC_debug_writeBuffer2File(nrLDPC_buffers_BN_PROC_RES, p_procBuf);
#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, p_procBuf, Z);
}
else
{
nrLDPC_bn2cnProcBuf_BG2(p_lut, p_procBuf, Z);
}
#ifdef NR_LDPC_PROFILER_DETAIL
stop_meas(&p_profiler->bn2cnProcBuf);
#endif
#ifdef NR_LDPC_DEBUG_MODE
nrLDPC_debug_writeBuffer2File(nrLDPC_buffers_CN_PROC, p_procBuf);
#endif
// Parity Check
#ifdef NR_LDPC_PROFILER_DETAIL
start_meas(&p_profiler->cnProcPc);
#endif
if (BG == 1)
{
pcRes = nrLDPC_cnProcPc_BG1(p_lut, p_procBuf, Z);
}
else
{
pcRes = nrLDPC_cnProcPc_BG2(p_lut, p_procBuf, Z);
}
#ifdef NR_LDPC_PROFILER_DETAIL
stop_meas(&p_profiler->cnProcPc);
#endif
#endif
}
// If maximum number of iterations reached an PC still fails increase number of iterations
// Thus, i > numMaxIter indicates that PC has failed
#ifdef NR_LDPC_ENABLE_PARITY_CHECK
if (pcRes != 0)
{
i++;
}
#endif
// Assign results from processing buffer to output
#ifdef NR_LDPC_PROFILER_DETAIL
start_meas(&p_profiler->llrRes2llrOut);
#endif
nrLDPC_llrRes2llrOut(p_lut, p_llrOut, p_procBuf, Z, BG);
#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
return i;
}
@@ -39,337 +39,9 @@
\param Z Lifting size
*/
#define conditional_negate(a,b,z) _mm512_mask_sub_epi8(a,_mm512_movepi8_mask(b),z,a)
#ifdef __AVX512BW__
static inline void nrLDPC_cnProc_BG2_AVX512(t_nrLDPC_lut* p_lut, int8_t* cnProcBuf, int8_t* cnProcBufRes, uint16_t Z)
{
const uint8_t* lut_numCnInCnGroups = p_lut->numCnInCnGroups;
const uint32_t* lut_startAddrCnGroups = p_lut->startAddrCnGroups;
__m512i* p_cnProcBuf;
__m512i* p_cnProcBufRes;
// Number of CNs in Groups
uint32_t M;
uint32_t i;
uint32_t j;
uint32_t k;
// Offset to each bit within a group in terms of 32 Byte
uint32_t bitOffsetInGroup;
__m512i zmm0, min, sgn, zeros;
zeros = _mm512_setzero_si512();
// maxLLR = _mm512_set1_epi8((char)127);
__m512i* p_cnProcBufResBit;
const __m512i* p_ones = (__m512i*) ones512_epi8;
const __m512i* p_maxLLR = (__m512i*) maxLLR512_epi8;
// LUT with offsets for bits that need to be processed
// 1. bit proc requires LLRs of 2. and 3. bit, 2.bits of 1. and 3. etc.
// Offsets are in units of bitOffsetInGroup
const uint8_t lut_idxCnProcG3[3][2] = {{72,144}, {0,144}, {0,72}};
// =====================================================================
// Process group with 3 BNs
if (lut_numCnInCnGroups[0] > 0)
{
// Number of groups of 32 CNs for parallel processing
// Ceil for values not divisible by 32
M = (lut_numCnInCnGroups[0]*Z + 63)>>6;
// Set the offset to each bit within a group in terms of 32 Byte
bitOffsetInGroup = (lut_numCnInCnGroups_BG2_R15[0]*NR_LDPC_ZMAX)>>6;
// Set pointers to start of group 3
p_cnProcBuf = (__m512i*) &cnProcBuf [lut_startAddrCnGroups[0]];
p_cnProcBufRes = (__m512i*) &cnProcBufRes[lut_startAddrCnGroups[0]];
// Loop over every BN
for (j=0; j<3; j++)
{
// Set of results pointer to correct BN address
p_cnProcBufResBit = p_cnProcBufRes + (j*bitOffsetInGroup);
__m512i *pj0 = &p_cnProcBuf[(lut_idxCnProcG3[j][0]/2)];
__m512i *pj1 = &p_cnProcBuf[(lut_idxCnProcG3[j][1]/2)];
// Loop over CNs
for (i=0; i<M; i++)
{
// Abs and sign of 32 CNs (first BN)
// zmm0 = p_cnProcBuf[lut_idxCnProcG3[j][0] + i];
zmm0 = pj0[i];
sgn = _mm512_xor_si512(*p_ones, zmm0);
min = _mm512_abs_epi8(zmm0);
// 32 CNs of second BN
// zmm0 = p_cnProcBuf[(lut_idxCnProcG3[j][1]/2) + i];
zmm0 = pj1[i];
min = _mm512_min_epu8(min, _mm512_abs_epi8(zmm0));
sgn = _mm512_xor_si512(sgn, zmm0);
// Store result
min = _mm512_min_epu8(min, *p_maxLLR); // 128 in epi8 is -127
*p_cnProcBufResBit = conditional_negate(min, sgn,zeros);
p_cnProcBufResBit++;
//p_cnProcBufResBit[i]=_mm512_sign_epi8(min, sgn);
}
}
}
// =====================================================================
// Process group with 4 BNs
// Offset is 20*384/32 = 240
const uint16_t lut_idxCnProcG4[4][3] = {{240,480,720}, {0,480,720}, {0,240,720}, {0,240,480}};
if (lut_numCnInCnGroups[1] > 0)
{
// Number of groups of 32 CNs for parallel processing
// Ceil for values not divisible by 32
M = (lut_numCnInCnGroups[1]*Z + 63)>>6;
// Set the offset to each bit within a group in terms of 32 Byte
bitOffsetInGroup = (lut_numCnInCnGroups_BG2_R15[1]*NR_LDPC_ZMAX)>>6;
// Set pointers to start of group 4
p_cnProcBuf = (__m512i*) &cnProcBuf [lut_startAddrCnGroups[1]];
p_cnProcBufRes = (__m512i*) &cnProcBufRes[lut_startAddrCnGroups[1]];
// Loop over every BN
for (j=0; j<4; j++)
{
// Set of results pointer to correct BN address
p_cnProcBufResBit = p_cnProcBufRes + (j*bitOffsetInGroup);
// Loop over CNs
for (i=0; i<M; i++)
{
// Abs and sign of 32 CNs (first BN)
zmm0 = p_cnProcBuf[(lut_idxCnProcG4[j][0]/2) + i];
sgn = _mm512_xor_si512(*p_ones, zmm0);
min = _mm512_abs_epi8(zmm0);
// Loop over BNs
for (k=1; k<3; k++)
{
zmm0 = p_cnProcBuf[(lut_idxCnProcG4[j][k]/2) + i];
min = _mm512_min_epu8(min, _mm512_abs_epi8(zmm0));
sgn = _mm512_xor_si512(sgn, zmm0);
}
// Store result
min = _mm512_min_epu8(min, *p_maxLLR); // 128 in epi8 is -127
*p_cnProcBufResBit = conditional_negate(min, sgn,zeros);
p_cnProcBufResBit++;
}
}
}
// =====================================================================
// Process group with 5 BNs
// Offset is 9*384/32 = 108
const uint16_t lut_idxCnProcG5[5][4] = {{108,216,324,432}, {0,216,324,432},
{0,108,324,432}, {0,108,216,432}, {0,108,216,324}};
if (lut_numCnInCnGroups[2] > 0)
{
// Number of groups of 32 CNs for parallel processing
// Ceil for values not divisible by 32
M = (lut_numCnInCnGroups[2]*Z + 63)>>6;
// Set the offset to each bit within a group in terms of 32 Byte
bitOffsetInGroup = (lut_numCnInCnGroups_BG2_R15[2]*NR_LDPC_ZMAX)>>6;
// Set pointers to start of group 5
p_cnProcBuf = (__m512i*) &cnProcBuf [lut_startAddrCnGroups[2]];
p_cnProcBufRes = (__m512i*) &cnProcBufRes[lut_startAddrCnGroups[2]];
// Loop over every BN
for (j=0; j<5; j++)
{
// Set of results pointer to correct BN address
p_cnProcBufResBit = p_cnProcBufRes + (j*bitOffsetInGroup);
// Loop over CNs
for (i=0; i<M; i++)
{
// Abs and sign of 32 CNs (first BN)
zmm0 = p_cnProcBuf[(lut_idxCnProcG5[j][0]/2) + i];
sgn = _mm512_xor_si512(*p_ones, zmm0);
min = _mm512_abs_epi8(zmm0);
// Loop over BNs
for (k=1; k<4; k++)
{
zmm0 = p_cnProcBuf[(lut_idxCnProcG5[j][k]/2) + i];
min = _mm512_min_epu8(min, _mm512_abs_epi8(zmm0));
sgn = _mm512_xor_si512(sgn, zmm0);
}
// Store result
min = _mm512_min_epu8(min, *p_maxLLR); // 128 in epi8 is -127
*p_cnProcBufResBit = conditional_negate(min, sgn,zeros);
p_cnProcBufResBit++;
}
}
}
// =====================================================================
// Process group with 6 BNs
// Offset is 3*384/32 = 36
const uint16_t lut_idxCnProcG6[6][5] = {{36,72,108,144,180}, {0,72,108,144,180},
{0,36,108,144,180}, {0,36,72,144,180},
{0,36,72,108,180}, {0,36,72,108,144}};
if (lut_numCnInCnGroups[3] > 0)
{
// Number of groups of 32 CNs for parallel processing
// Ceil for values not divisible by 32
M = (lut_numCnInCnGroups[3]*Z + 63)>>6;
// Set the offset to each bit within a group in terms of 32 Byte
bitOffsetInGroup = (lut_numCnInCnGroups_BG2_R15[3]*NR_LDPC_ZMAX)>>6;
// Set pointers to start of group 6
p_cnProcBuf = (__m512i*) &cnProcBuf [lut_startAddrCnGroups[3]];
p_cnProcBufRes = (__m512i*) &cnProcBufRes[lut_startAddrCnGroups[3]];
// Loop over every BN
for (j=0; j<6; j++)
{
// Set of results pointer to correct BN address
p_cnProcBufResBit = p_cnProcBufRes + (j*bitOffsetInGroup);
// Loop over CNs
for (i=0; i<M; i++)
{
// Abs and sign of 32 CNs (first BN)
zmm0 = p_cnProcBuf[(lut_idxCnProcG6[j][0]/2) + i];
sgn = _mm512_xor_si512(*p_ones, zmm0);
min = _mm512_abs_epi8(zmm0);
// Loop over BNs
for (k=1; k<5; k++)
{
zmm0 = p_cnProcBuf[(lut_idxCnProcG6[j][k]/2) + i];
min = _mm512_min_epu8(min, _mm512_abs_epi8(zmm0));
sgn = _mm512_xor_si512(sgn, zmm0);
}
// Store result
min = _mm512_min_epu8(min, *p_maxLLR); // 128 in epi8 is -127
*p_cnProcBufResBit = conditional_negate(min, sgn,zeros);
p_cnProcBufResBit++;
}
}
}
// =====================================================================
// Process group with 8 BNs
// Offset is 2*384/32 = 24
const uint8_t lut_idxCnProcG8[8][7] = {{24,48,72,96,120,144,168}, {0,48,72,96,120,144,168},
{0,24,72,96,120,144,168}, {0,24,48,96,120,144,168},
{0,24,48,72,120,144,168}, {0,24,48,72,96,144,168},
{0,24,48,72,96,120,168}, {0,24,48,72,96,120,144}};
if (lut_numCnInCnGroups[4] > 0)
{
// Number of groups of 32 CNs for parallel processing
// Ceil for values not divisible by 32
M = (lut_numCnInCnGroups[4]*Z + 63)>>6;
// Set the offset to each bit within a group in terms of 32 Byte
bitOffsetInGroup = (lut_numCnInCnGroups_BG2_R15[4]*NR_LDPC_ZMAX)>>6;
// Set pointers to start of group 8
p_cnProcBuf = (__m512i*) &cnProcBuf [lut_startAddrCnGroups[4]];
p_cnProcBufRes = (__m512i*) &cnProcBufRes[lut_startAddrCnGroups[4]];
// Loop over every BN
for (j=0; j<8; j++)
{
// Set of results pointer to correct BN address
p_cnProcBufResBit = p_cnProcBufRes + (j*bitOffsetInGroup);
// Loop over CNs
for (i=0; i<M; i++)
{
// Abs and sign of 32 CNs (first BN)
zmm0 = p_cnProcBuf[(lut_idxCnProcG8[j][0]/2) + i];
sgn = _mm512_xor_si512(*p_ones, zmm0);
min = _mm512_abs_epi8(zmm0);
// Loop over BNs
for (k=1; k<7; k++)
{
zmm0 = p_cnProcBuf[(lut_idxCnProcG8[j][k]/2) + i];
min = _mm512_min_epu8(min, _mm512_abs_epi8(zmm0));
sgn = _mm512_xor_si512(sgn, zmm0);
}
// Store result
min = _mm512_min_epu8(min, *p_maxLLR); // 128 in epi8 is -127
*p_cnProcBufResBit = conditional_negate(min, sgn,zeros);
p_cnProcBufResBit++;
}
}
}
// =====================================================================
// Process group with 10 BNs
// Offset is 2*384/32 = 24
const uint8_t lut_idxCnProcG10[10][9] = {{24,48,72,96,120,144,168,192,216}, {0,48,72,96,120,144,168,192,216},
{0,24,72,96,120,144,168,192,216}, {0,24,48,96,120,144,168,192,216},
{0,24,48,72,120,144,168,192,216}, {0,24,48,72,96,144,168,192,216},
{0,24,48,72,96,120,168,192,216}, {0,24,48,72,96,120,144,192,216},
{0,24,48,72,96,120,144,168,216}, {0,24,48,72,96,120,144,168,192}};
if (lut_numCnInCnGroups[5] > 0)
{
// Number of groups of 32 CNs for parallel processing
// Ceil for values not divisible by 32
M = (lut_numCnInCnGroups[5]*Z + 63)>>6;
// Set the offset to each bit within a group in terms of 32 Byte
bitOffsetInGroup = (lut_numCnInCnGroups_BG2_R15[5]*NR_LDPC_ZMAX)>>6;
// Set pointers to start of group 10
p_cnProcBuf = (__m512i*) &cnProcBuf [lut_startAddrCnGroups[5]];
p_cnProcBufRes = (__m512i*) &cnProcBufRes[lut_startAddrCnGroups[5]];
// Loop over every BN
for (j=0; j<10; j++)
{
// Set of results pointer to correct BN address
p_cnProcBufResBit = p_cnProcBufRes + (j*bitOffsetInGroup);
// Loop over CNs
for (i=0; i<M; i++)
{
// Abs and sign of 32 CNs (first BN)
zmm0 = p_cnProcBuf[(lut_idxCnProcG10[j][0]/2) + i];
sgn = _mm512_xor_si512(*p_ones, zmm0);
min = _mm512_abs_epi8(zmm0);
// Loop over BNs
for (k=1; k<9; k++)
{
zmm0 = p_cnProcBuf[(lut_idxCnProcG10[j][k]/2) + i];
min = _mm512_min_epu8(min, _mm512_abs_epi8(zmm0));
sgn = _mm512_xor_si512(sgn, zmm0);
}
// Store result
min = _mm512_min_epu8(min, *p_maxLLR); // 128 in epi8 is -127
*p_cnProcBufResBit = conditional_negate(min, sgn,zeros);
p_cnProcBufResBit++;
}
}
}
}
#include "nrLDPC_cnProc_avx512.h"
#else
@@ -441,9 +113,9 @@ static inline void nrLDPC_cnProc_BG2(t_nrLDPC_lut* p_lut, int8_t* cnProcBuf, int
// Store result
min = _mm256_min_epu8(min, *p_maxLLR); // 128 in epi8 is -127
*p_cnProcBufResBit = _mm256_sign_epi8(min, sgn);
p_cnProcBufResBit++;
//p_cnProcBufResBit[i]=_mm256_sign_epi8(min, sgn);
//*p_cnProcBufResBit = _mm256_sign_epi8(min, sgn);
//p_cnProcBufResBit++;
p_cnProcBufResBit[i]=_mm256_sign_epi8(min, sgn);
}
}
}
@@ -700,7 +372,6 @@ static inline void nrLDPC_cnProc_BG2(t_nrLDPC_lut* p_lut, int8_t* cnProcBuf, int
}
#endif
/**
\brief Performs CN processing for BG1 on the CN processing buffer and stores the results in the CN processing results buffer.
@@ -708,511 +379,8 @@ static inline void nrLDPC_cnProc_BG2(t_nrLDPC_lut* p_lut, int8_t* cnProcBuf, int
\param Z Lifting size
*/
#ifdef __AVX512BW__
static inline void nrLDPC_cnProc_BG1_AVX512(t_nrLDPC_lut* p_lut, t_nrLDPC_procBuf* p_procBuf, uint16_t Z)
{
const uint8_t* lut_numCnInCnGroups = p_lut->numCnInCnGroups;
const uint32_t* lut_startAddrCnGroups = p_lut->startAddrCnGroups;
int8_t* cnProcBuf = p_procBuf->cnProcBuf;
int8_t* cnProcBufRes = p_procBuf->cnProcBufRes;
__m512i* p_cnProcBuf;
__m512i* p_cnProcBufRes;
// Number of CNs in Groups
uint32_t M;
uint32_t i;
uint32_t j;
uint32_t k;
// Offset to each bit within a group in terms of 32 Byte
uint32_t bitOffsetInGroup;
__m512i zmm0, min, sgn, zeros;
zeros = _mm512_setzero_si512();
// maxLLR = _mm512_set1_epi8((char)127);
__m512i* p_cnProcBufResBit;
const __m512i* p_ones = (__m512i*) ones512_epi8;
const __m512i* p_maxLLR = (__m512i*) maxLLR512_epi8;
// LUT with offsets for bits that need to be processed
// 1. bit proc requires LLRs of 2. and 3. bit, 2.bits of 1. and 3. etc.
// Offsets are in units of bitOffsetInGroup (1*384/32)
const uint8_t lut_idxCnProcG3[3][2] = {{12,24}, {0,24}, {0,12}};
// =====================================================================
// Process group with 3 BNs
if (lut_numCnInCnGroups[0] > 0)
{
// Number of groups of 32 CNs for parallel processing
// Ceil for values not divisible by 32
M = (lut_numCnInCnGroups[0]*Z + 63)>>6;
// Set the offset to each bit within a group in terms of 32 Byte
bitOffsetInGroup = (lut_numCnInCnGroups_BG1_R13[0]*NR_LDPC_ZMAX)>>6;
// Set pointers to start of group 3
p_cnProcBuf = (__m512i*) &cnProcBuf [lut_startAddrCnGroups[0]];
p_cnProcBufRes = (__m512i*) &cnProcBufRes[lut_startAddrCnGroups[0]];
// Loop over every BN
for (j=0; j<3; j++)
{
// Set of results pointer to correct BN address
p_cnProcBufResBit = p_cnProcBufRes + (j*bitOffsetInGroup);
// Loop over CNs
for (i=0; i<M; i++)
{
// Abs and sign of 32 CNs (first BN)
zmm0 = p_cnProcBuf[(lut_idxCnProcG3[j][0]/2) + i];
sgn = _mm512_xor_si512(*p_ones, zmm0);
min = _mm512_abs_epi8(zmm0);
// 32 CNs of second BN
zmm0 = p_cnProcBuf[(lut_idxCnProcG3[j][1]/2) + i];
min = _mm512_min_epu8(min, _mm512_abs_epi8(zmm0));
sgn = _mm512_xor_si512(sgn, zmm0);
// Store result
min = _mm512_min_epu8(min, *p_maxLLR); // 128 in epi8 is -127
*p_cnProcBufResBit = conditional_negate(min, sgn,zeros);
p_cnProcBufResBit++;
}
}
}
// =====================================================================
// Process group with 4 BNs
// Offset is 5*384/32 = 60
const uint8_t lut_idxCnProcG4[4][3] = {{60,120,180}, {0,120,180}, {0,60,180}, {0,60,120}};
if (lut_numCnInCnGroups[1] > 0)
{
// Number of groups of 32 CNs for parallel processing
// Ceil for values not divisible by 32
M = (lut_numCnInCnGroups[1]*Z + 63)>>6;
// Set the offset to each bit within a group in terms of 32 Byte
bitOffsetInGroup = (lut_numCnInCnGroups_BG1_R13[1]*NR_LDPC_ZMAX)>>6;
// Set pointers to start of group 4
p_cnProcBuf = (__m512i*) &cnProcBuf [lut_startAddrCnGroups[1]];
p_cnProcBufRes = (__m512i*) &cnProcBufRes[lut_startAddrCnGroups[1]];
// Loop over every BN
for (j=0; j<4; j++)
{
// Set of results pointer to correct BN address
p_cnProcBufResBit = p_cnProcBufRes + (j*bitOffsetInGroup);
// Loop over CNs
for (i=0; i<M; i++)
{
// Abs and sign of 32 CNs (first BN)
zmm0 = p_cnProcBuf[(lut_idxCnProcG4[j][0]/2) + i];
sgn = _mm512_xor_si512(*p_ones, zmm0);
min = _mm512_abs_epi8(zmm0);
// Loop over BNs
for (k=1; k<3; k++)
{
zmm0 = p_cnProcBuf[(lut_idxCnProcG4[j][k]/2) + i];
min = _mm512_min_epu8(min, _mm512_abs_epi8(zmm0));
sgn = _mm512_xor_si512(sgn, zmm0);
}
// Store result
min = _mm512_min_epu8(min, *p_maxLLR); // 128 in epi8 is -127
*p_cnProcBufResBit = conditional_negate(min, sgn,zeros);
p_cnProcBufResBit++;
}
}
}
// =====================================================================
// Process group with 5 BNs
// Offset is 18*384/32 = 216
const uint16_t lut_idxCnProcG5[5][4] = {{216,432,648,864}, {0,432,648,864},
{0,216,648,864}, {0,216,432,864}, {0,216,432,648}};
if (lut_numCnInCnGroups[2] > 0)
{
// Number of groups of 32 CNs for parallel processing
// Ceil for values not divisible by 32
M = (lut_numCnInCnGroups[2]*Z + 63)>>6;
// Set the offset to each bit within a group in terms of 32 Byte
bitOffsetInGroup = (lut_numCnInCnGroups_BG1_R13[2]*NR_LDPC_ZMAX)>>6;
// Set pointers to start of group 5
p_cnProcBuf = (__m512i*) &cnProcBuf [lut_startAddrCnGroups[2]];
p_cnProcBufRes = (__m512i*) &cnProcBufRes[lut_startAddrCnGroups[2]];
// Loop over every BN
for (j=0; j<5; j++)
{
// Set of results pointer to correct BN address
p_cnProcBufResBit = p_cnProcBufRes + (j*bitOffsetInGroup);
// Loop over CNs
for (i=0; i<M; i++)
{
// Abs and sign of 32 CNs (first BN)
zmm0 = p_cnProcBuf[(lut_idxCnProcG5[j][0]/2) + i];
sgn = _mm512_xor_si512(*p_ones, zmm0);
min = _mm512_abs_epi8(zmm0);
// Loop over BNs
for (k=1; k<4; k++)
{
zmm0 = p_cnProcBuf[(lut_idxCnProcG5[j][k]/2) + i];
min = _mm512_min_epu8(min, _mm512_abs_epi8(zmm0));
sgn = _mm512_xor_si512(sgn, zmm0);
}
// Store result
min = _mm512_min_epu8(min, *p_maxLLR); // 128 in epi8 is -127
*p_cnProcBufResBit = conditional_negate(min, sgn,zeros);
p_cnProcBufResBit++;
}
}
}
// =====================================================================
// Process group with 6 BNs
// Offset is 8*384/32 = 96
const uint16_t lut_idxCnProcG6[6][5] = {{96,192,288,384,480}, {0,192,288,384,480},
{0,96,288,384,480}, {0,96,192,384,480},
{0,96,192,288,480}, {0,96,192,288,384}};
if (lut_numCnInCnGroups[3] > 0)
{
// Number of groups of 32 CNs for parallel processing
// Ceil for values not divisible by 32
M = (lut_numCnInCnGroups[3]*Z + 63)>>6;
// Set the offset to each bit within a group in terms of 32 Byte
bitOffsetInGroup = (lut_numCnInCnGroups_BG1_R13[3]*NR_LDPC_ZMAX)>>6;
// Set pointers to start of group 6
p_cnProcBuf = (__m512i*) &cnProcBuf [lut_startAddrCnGroups[3]];
p_cnProcBufRes = (__m512i*) &cnProcBufRes[lut_startAddrCnGroups[3]];
// Loop over every BN
for (j=0; j<6; j++)
{
// Set of results pointer to correct BN address
p_cnProcBufResBit = p_cnProcBufRes + (j*bitOffsetInGroup);
// Loop over CNs
for (i=0; i<M; i++)
{
// Abs and sign of 32 CNs (first BN)
zmm0 = p_cnProcBuf[(lut_idxCnProcG6[j][0]/2) + i];
sgn = _mm512_xor_si512(*p_ones, zmm0);
min = _mm512_abs_epi8(zmm0);
// Loop over BNs
for (k=1; k<5; k++)
{
zmm0 = p_cnProcBuf[(lut_idxCnProcG6[j][k]/2) + i];
min = _mm512_min_epu8(min, _mm512_abs_epi8(zmm0));
sgn = _mm512_xor_si512(sgn, zmm0);
}
// Store result
min = _mm512_min_epu8(min, *p_maxLLR); // 128 in epi8 is -127
*p_cnProcBufResBit = conditional_negate(min, sgn,zeros);
p_cnProcBufResBit++;
}
}
}
// =====================================================================
// Process group with 7 BNs
// Offset is 5*384/32 = 60
const uint16_t lut_idxCnProcG7[7][6] = {{60,120,180,240,300,360}, {0,120,180,240,300,360},
{0,60,180,240,300,360}, {0,60,120,240,300,360},
{0,60,120,180,300,360}, {0,60,120,180,240,360},
{0,60,120,180,240,300}};
if (lut_numCnInCnGroups[4] > 0)
{
// Number of groups of 32 CNs for parallel processing
// Ceil for values not divisible by 32
M = (lut_numCnInCnGroups[4]*Z + 63)>>6;
// Set the offset to each bit within a group in terms of 32 Byte
bitOffsetInGroup = (lut_numCnInCnGroups_BG1_R13[4]*NR_LDPC_ZMAX)>>6;
// Set pointers to start of group 7
p_cnProcBuf = (__m512i*) &cnProcBuf [lut_startAddrCnGroups[4]];
p_cnProcBufRes = (__m512i*) &cnProcBufRes[lut_startAddrCnGroups[4]];
// Loop over every BN
for (j=0; j<7; j++)
{
// Set of results pointer to correct BN address
p_cnProcBufResBit = p_cnProcBufRes + (j*bitOffsetInGroup);
// Loop over CNs
for (i=0; i<M; i++)
{
// Abs and sign of 32 CNs (first BN)
zmm0 = p_cnProcBuf[(lut_idxCnProcG7[j][0]/2) + i];
sgn = _mm512_xor_si512(*p_ones, zmm0);
min = _mm512_abs_epi8(zmm0);
// Loop over BNs
for (k=1; k<6; k++)
{
zmm0 = p_cnProcBuf[(lut_idxCnProcG7[j][k]/2) + i];
min = _mm512_min_epu8(min, _mm512_abs_epi8(zmm0));
sgn = _mm512_xor_si512(sgn, zmm0);
}
// Store result
min = _mm512_min_epu8(min, *p_maxLLR); // 128 in epi8 is -127
*p_cnProcBufResBit = conditional_negate(min, sgn,zeros);
p_cnProcBufResBit++;
}
}
}
// =====================================================================
// Process group with 8 BNs
// Offset is 2*384/32 = 24
const uint8_t lut_idxCnProcG8[8][7] = {{24,48,72,96,120,144,168}, {0,48,72,96,120,144,168},
{0,24,72,96,120,144,168}, {0,24,48,96,120,144,168},
{0,24,48,72,120,144,168}, {0,24,48,72,96,144,168},
{0,24,48,72,96,120,168}, {0,24,48,72,96,120,144}};
if (lut_numCnInCnGroups[5] > 0)
{
// Number of groups of 32 CNs for parallel processing
// Ceil for values not divisible by 32
M = (lut_numCnInCnGroups[5]*Z + 63)>>6;
// Set the offset to each bit within a group in terms of 32 Byte
bitOffsetInGroup = (lut_numCnInCnGroups_BG1_R13[5]*NR_LDPC_ZMAX)>>6;
// Set pointers to start of group 8
p_cnProcBuf = (__m512i*) &cnProcBuf [lut_startAddrCnGroups[5]];
p_cnProcBufRes = (__m512i*) &cnProcBufRes[lut_startAddrCnGroups[5]];
// Loop over every BN
for (j=0; j<8; j++)
{
// Set of results pointer to correct BN address
p_cnProcBufResBit = p_cnProcBufRes + (j*bitOffsetInGroup);
// Loop over CNs
for (i=0; i<M; i++)
{
// Abs and sign of 32 CNs (first BN)
zmm0 = p_cnProcBuf[(lut_idxCnProcG8[j][0]/2) + i];
sgn = _mm512_xor_si512(*p_ones, zmm0);
min = _mm512_abs_epi8(zmm0);
// Loop over BNs
for (k=1; k<7; k++)
{
zmm0 = p_cnProcBuf[(lut_idxCnProcG8[j][k]/2) + i];
min = _mm512_min_epu8(min, _mm512_abs_epi8(zmm0));
sgn = _mm512_xor_si512(sgn, zmm0);
}
// Store result
min = _mm512_min_epu8(min, *p_maxLLR); // 128 in epi8 is -127
*p_cnProcBufResBit = conditional_negate(min, sgn,zeros);
p_cnProcBufResBit++;
}
}
}
// =====================================================================
// Process group with 9 BNs
// Offset is 2*384/32 = 24
const uint8_t lut_idxCnProcG9[9][8] = {{24,48,72,96,120,144,168,192}, {0,48,72,96,120,144,168,192},
{0,24,72,96,120,144,168,192}, {0,24,48,96,120,144,168,192},
{0,24,48,72,120,144,168,192}, {0,24,48,72,96,144,168,192},
{0,24,48,72,96,120,168,192}, {0,24,48,72,96,120,144,192},
{0,24,48,72,96,120,144,168}};
if (lut_numCnInCnGroups[6] > 0)
{
// Number of groups of 32 CNs for parallel processing
// Ceil for values not divisible by 32
M = (lut_numCnInCnGroups[6]*Z + 63)>>6;
// Set the offset to each bit within a group in terms of 32 Byte
bitOffsetInGroup = (lut_numCnInCnGroups_BG1_R13[6]*NR_LDPC_ZMAX)>>6;
// Set pointers to start of group 9
p_cnProcBuf = (__m512i*) &cnProcBuf [lut_startAddrCnGroups[6]];
p_cnProcBufRes = (__m512i*) &cnProcBufRes[lut_startAddrCnGroups[6]];
// Loop over every BN
for (j=0; j<9; j++)
{
// Set of results pointer to correct BN address
p_cnProcBufResBit = p_cnProcBufRes + (j*bitOffsetInGroup);
// Loop over CNs
for (i=0; i<M; i++)
{
// Abs and sign of 32 CNs (first BN)
zmm0 = p_cnProcBuf[(lut_idxCnProcG9[j][0]/2) + i];
sgn = _mm512_xor_si512(*p_ones, zmm0);
min = _mm512_abs_epi8(zmm0);
// Loop over BNs
for (k=1; k<8; k++)
{
zmm0 = p_cnProcBuf[(lut_idxCnProcG9[j][k]/2) + i];
min = _mm512_min_epu8(min, _mm512_abs_epi8(zmm0));
sgn = _mm512_xor_si512(sgn, zmm0);
}
// Store result
min = _mm512_min_epu8(min, *p_maxLLR); // 128 in epi8 is -127
*p_cnProcBufResBit = conditional_negate(min, sgn,zeros);
p_cnProcBufResBit++;
}
}
}
// =====================================================================
// Process group with 10 BNs
// Offset is 1*384/32 = 12
const uint8_t lut_idxCnProcG10[10][9] = {{12,24,36,48,60,72,84,96,108}, {0,24,36,48,60,72,84,96,108},
{0,12,36,48,60,72,84,96,108}, {0,12,24,48,60,72,84,96,108},
{0,12,24,36,60,72,84,96,108}, {0,12,24,36,48,72,84,96,108},
{0,12,24,36,48,60,84,96,108}, {0,12,24,36,48,60,72,96,108},
{0,12,24,36,48,60,72,84,108}, {0,12,24,36,48,60,72,84,96}};
if (lut_numCnInCnGroups[7] > 0)
{
// Number of groups of 32 CNs for parallel processing
// Ceil for values not divisible by 32
M = (lut_numCnInCnGroups[7]*Z + 63)>>6;
// Set the offset to each bit within a group in terms of 32 Byte
bitOffsetInGroup = (lut_numCnInCnGroups_BG1_R13[7]*NR_LDPC_ZMAX)>>6;
// Set pointers to start of group 10
p_cnProcBuf = (__m512i*) &cnProcBuf [lut_startAddrCnGroups[7]];
p_cnProcBufRes = (__m512i*) &cnProcBufRes[lut_startAddrCnGroups[7]];
// Loop over every BN
for (j=0; j<10; j++)
{
// Set of results pointer to correct BN address
p_cnProcBufResBit = p_cnProcBufRes + (j*bitOffsetInGroup);
// Loop over CNs
for (i=0; i<M; i++)
{
// Abs and sign of 32 CNs (first BN)
zmm0 = p_cnProcBuf[(lut_idxCnProcG10[j][0]/2) + i];
sgn = _mm512_xor_si512(*p_ones, zmm0);
min = _mm512_abs_epi8(zmm0);
// Loop over BNs
for (k=1; k<9; k++)
{
zmm0 = p_cnProcBuf[(lut_idxCnProcG10[j][k]/2) + i];
min = _mm512_min_epu8(min, _mm512_abs_epi8(zmm0));
sgn = _mm512_xor_si512(sgn, zmm0);
}
// Store result
min = _mm512_min_epu8(min, *p_maxLLR); // 128 in epi8 is -127
*p_cnProcBufResBit = conditional_negate(min, sgn,zeros);
p_cnProcBufResBit++;
}
}
}
// =====================================================================
// Process group with 19 BNs
// Offset is 4*384/32 = 12
const uint16_t lut_idxCnProcG19[19][18] = {{48,96,144,192,240,288,336,384,432,480,528,576,624,672,720,768,816,864}, {0,96,144,192,240,288,336,384,432,480,528,576,624,672,720,768,816,864},
{0,48,144,192,240,288,336,384,432,480,528,576,624,672,720,768,816,864}, {0,48,96,192,240,288,336,384,432,480,528,576,624,672,720,768,816,864},
{0,48,96,144,240,288,336,384,432,480,528,576,624,672,720,768,816,864}, {0,48,96,144,192,288,336,384,432,480,528,576,624,672,720,768,816,864},
{0,48,96,144,192,240,336,384,432,480,528,576,624,672,720,768,816,864}, {0,48,96,144,192,240,288,384,432,480,528,576,624,672,720,768,816,864},
{0,48,96,144,192,240,288,336,432,480,528,576,624,672,720,768,816,864}, {0,48,96,144,192,240,288,336,384,480,528,576,624,672,720,768,816,864},
{0,48,96,144,192,240,288,336,384,432,528,576,624,672,720,768,816,864}, {0,48,96,144,192,240,288,336,384,432,480,576,624,672,720,768,816,864},
{0,48,96,144,192,240,288,336,384,432,480,528,624,672,720,768,816,864}, {0,48,96,144,192,240,288,336,384,432,480,528,576,672,720,768,816,864},
{0,48,96,144,192,240,288,336,384,432,480,528,576,624,720,768,816,864}, {0,48,96,144,192,240,288,336,384,432,480,528,576,624,672,768,816,864},
{0,48,96,144,192,240,288,336,384,432,480,528,576,624,672,720,816,864}, {0,48,96,144,192,240,288,336,384,432,480,528,576,624,672,720,768,864},
{0,48,96,144,192,240,288,336,384,432,480,528,576,624,672,720,768,816}};
if (lut_numCnInCnGroups[8] > 0)
{
// Number of groups of 32 CNs for parallel processing
// Ceil for values not divisible by 32
M = (lut_numCnInCnGroups[8]*Z + 63)>>6;
// Set the offset to each bit within a group in terms of 32 Byte
bitOffsetInGroup = (lut_numCnInCnGroups_BG1_R13[8]*NR_LDPC_ZMAX)>>6;
// Set pointers to start of group 19
p_cnProcBuf = (__m512i*) &cnProcBuf [lut_startAddrCnGroups[8]];
p_cnProcBufRes = (__m512i*) &cnProcBufRes[lut_startAddrCnGroups[8]];
// Loop over every BN
for (j=0; j<19; j++)
{
// Set of results pointer to correct BN address
p_cnProcBufResBit = p_cnProcBufRes + (j*bitOffsetInGroup);
// Loop over CNs
for (i=0; i<M; i++)
{
// Abs and sign of 32 CNs (first BN)
zmm0 = p_cnProcBuf[(lut_idxCnProcG19[j][0]/2) + i];
sgn = _mm512_xor_si512(*p_ones, zmm0);
min = _mm512_abs_epi8(zmm0);
// Loop over BNs
for (k=1; k<18; k++)
{
zmm0 = p_cnProcBuf[(lut_idxCnProcG19[j][k]/2) + i];
min = _mm512_min_epu8(min, _mm512_abs_epi8(zmm0));
sgn = _mm512_xor_si512(sgn, zmm0);
}
// Store result
min = _mm512_min_epu8(min, *p_maxLLR); // 128 in epi8 is -127
*p_cnProcBufResBit = conditional_negate(min, sgn,zeros);
p_cnProcBufResBit++;
}
}
}
}
#else
/**
\brief Performs CN processing for BG1 on the CN processing buffer and stores the results in the CN processing results buffer.
\param p_lut Pointer to decoder LUTs
@@ -1708,6 +876,7 @@ static inline void nrLDPC_cnProc_BG1(t_nrLDPC_lut* p_lut, int8_t* cnProcBuf, int
}
}
#endif
/**
\brief Performs parity check for BG1 on the CN processing buffer. Stops as soon as error is detected.
@@ -0,0 +1,865 @@
/*
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenAirInterface Software Alliance licenses this file to You under
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
* except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.openairinterface.org/?page_id=698
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*-------------------------------------------------------------------------------
* For more information about the OpenAirInterface (OAI) Software Alliance:
* contact@openairinterface.org
*/
/*!\file nrLDPC_cnProc_avx512.h
* \brief Defines the functions for check node processing
* \author Sebastian Wagner (TCL Communications) Email: <mailto:sebastian.wagner@tcl.com>
* \date 30-09-2021
* \version 1.0
* \note
* \warning
*/
#ifndef __NR_LDPC_CNPROC__H__
#define __NR_LDPC_CNPROC__H__
#define conditional_negate(a,b,z) _mm512_mask_sub_epi8(a,_mm512_movepi8_mask(b),z,a)
static inline void nrLDPC_cnProc_BG2_AVX512(t_nrLDPC_lut* p_lut, int8_t* cnProcBuf, int8_t* cnProcBufRes, uint16_t Z)
{
const uint8_t* lut_numCnInCnGroups = p_lut->numCnInCnGroups;
const uint32_t* lut_startAddrCnGroups = p_lut->startAddrCnGroups;
__m512i* p_cnProcBuf;
__m512i* p_cnProcBufRes;
// Number of CNs in Groups
uint32_t M;
uint32_t i;
uint32_t j;
uint32_t k;
// Offset to each bit within a group in terms of 32 Byte
uint32_t bitOffsetInGroup;
__m512i zmm0, min, sgn, zeros;
zeros = _mm512_setzero_si512();
// maxLLR = _mm512_set1_epi8((char)127);
__m512i* p_cnProcBufResBit;
const __m512i* p_ones = (__m512i*) ones512_epi8;
const __m512i* p_maxLLR = (__m512i*) maxLLR512_epi8;
// LUT with offsets for bits that need to be processed
// 1. bit proc requires LLRs of 2. and 3. bit, 2.bits of 1. and 3. etc.
// Offsets are in units of bitOffsetInGroup
const uint8_t lut_idxCnProcG3[3][2] = {{72,144}, {0,144}, {0,72}};
// =====================================================================
// Process group with 3 BNs
if (lut_numCnInCnGroups[0] > 0)
{
// Number of groups of 32 CNs for parallel processing
// Ceil for values not divisible by 32
M = (lut_numCnInCnGroups[0]*Z + 63)>>6;
// Set the offset to each bit within a group in terms of 32 Byte
bitOffsetInGroup = (lut_numCnInCnGroups_BG2_R15[0]*NR_LDPC_ZMAX)>>6;
// Set pointers to start of group 3
p_cnProcBuf = (__m512i*) &cnProcBuf [lut_startAddrCnGroups[0]];
p_cnProcBufRes = (__m512i*) &cnProcBufRes[lut_startAddrCnGroups[0]];
// Loop over every BN
for (j=0; j<3; j++)
{
// Set of results pointer to correct BN address
p_cnProcBufResBit = p_cnProcBufRes + (j*bitOffsetInGroup);
__m512i *pj0 = &p_cnProcBuf[(lut_idxCnProcG3[j][0]/2)];
__m512i *pj1 = &p_cnProcBuf[(lut_idxCnProcG3[j][1]/2)];
// Loop over CNs
for (i=0; i<M; i++)
{
// Abs and sign of 32 CNs (first BN)
// zmm0 = p_cnProcBuf[lut_idxCnProcG3[j][0] + i];
zmm0 = pj0[i];
sgn = _mm512_xor_si512(*p_ones, zmm0);
min = _mm512_abs_epi8(zmm0);
// 32 CNs of second BN
// zmm0 = p_cnProcBuf[(lut_idxCnProcG3[j][1]/2) + i];
zmm0 = pj1[i];
min = _mm512_min_epu8(min, _mm512_abs_epi8(zmm0));
sgn = _mm512_xor_si512(sgn, zmm0);
// Store result
min = _mm512_min_epu8(min, *p_maxLLR); // 128 in epi8 is -127
*p_cnProcBufResBit = conditional_negate(min, sgn,zeros);
p_cnProcBufResBit++;
//p_cnProcBufResBit[i]=_mm512_sign_epi8(min, sgn);
}
}
}
// =====================================================================
// Process group with 4 BNs
// Offset is 20*384/32 = 240
const uint16_t lut_idxCnProcG4[4][3] = {{240,480,720}, {0,480,720}, {0,240,720}, {0,240,480}};
if (lut_numCnInCnGroups[1] > 0)
{
// Number of groups of 32 CNs for parallel processing
// Ceil for values not divisible by 32
M = (lut_numCnInCnGroups[1]*Z + 63)>>6;
// Set the offset to each bit within a group in terms of 32 Byte
bitOffsetInGroup = (lut_numCnInCnGroups_BG2_R15[1]*NR_LDPC_ZMAX)>>6;
// Set pointers to start of group 4
p_cnProcBuf = (__m512i*) &cnProcBuf [lut_startAddrCnGroups[1]];
p_cnProcBufRes = (__m512i*) &cnProcBufRes[lut_startAddrCnGroups[1]];
// Loop over every BN
for (j=0; j<4; j++)
{
// Set of results pointer to correct BN address
p_cnProcBufResBit = p_cnProcBufRes + (j*bitOffsetInGroup);
// Loop over CNs
for (i=0; i<M; i++)
{
// Abs and sign of 32 CNs (first BN)
zmm0 = p_cnProcBuf[(lut_idxCnProcG4[j][0]/2) + i];
sgn = _mm512_xor_si512(*p_ones, zmm0);
min = _mm512_abs_epi8(zmm0);
// Loop over BNs
for (k=1; k<3; k++)
{
zmm0 = p_cnProcBuf[(lut_idxCnProcG4[j][k]/2) + i];
min = _mm512_min_epu8(min, _mm512_abs_epi8(zmm0));
sgn = _mm512_xor_si512(sgn, zmm0);
}
// Store result
min = _mm512_min_epu8(min, *p_maxLLR); // 128 in epi8 is -127
*p_cnProcBufResBit = conditional_negate(min, sgn,zeros);
p_cnProcBufResBit++;
}
}
}
// =====================================================================
// Process group with 5 BNs
// Offset is 9*384/32 = 108
const uint16_t lut_idxCnProcG5[5][4] = {{108,216,324,432}, {0,216,324,432},
{0,108,324,432}, {0,108,216,432}, {0,108,216,324}};
if (lut_numCnInCnGroups[2] > 0)
{
// Number of groups of 32 CNs for parallel processing
// Ceil for values not divisible by 32
M = (lut_numCnInCnGroups[2]*Z + 63)>>6;
// Set the offset to each bit within a group in terms of 32 Byte
bitOffsetInGroup = (lut_numCnInCnGroups_BG2_R15[2]*NR_LDPC_ZMAX)>>6;
// Set pointers to start of group 5
p_cnProcBuf = (__m512i*) &cnProcBuf [lut_startAddrCnGroups[2]];
p_cnProcBufRes = (__m512i*) &cnProcBufRes[lut_startAddrCnGroups[2]];
// Loop over every BN
for (j=0; j<5; j++)
{
// Set of results pointer to correct BN address
p_cnProcBufResBit = p_cnProcBufRes + (j*bitOffsetInGroup);
// Loop over CNs
for (i=0; i<M; i++)
{
// Abs and sign of 32 CNs (first BN)
zmm0 = p_cnProcBuf[(lut_idxCnProcG5[j][0]/2) + i];
sgn = _mm512_xor_si512(*p_ones, zmm0);
min = _mm512_abs_epi8(zmm0);
// Loop over BNs
for (k=1; k<4; k++)
{
zmm0 = p_cnProcBuf[(lut_idxCnProcG5[j][k]/2) + i];
min = _mm512_min_epu8(min, _mm512_abs_epi8(zmm0));
sgn = _mm512_xor_si512(sgn, zmm0);
}
// Store result
min = _mm512_min_epu8(min, *p_maxLLR); // 128 in epi8 is -127
*p_cnProcBufResBit = conditional_negate(min, sgn,zeros);
p_cnProcBufResBit++;
}
}
}
// =====================================================================
// Process group with 6 BNs
// Offset is 3*384/32 = 36
const uint16_t lut_idxCnProcG6[6][5] = {{36,72,108,144,180}, {0,72,108,144,180},
{0,36,108,144,180}, {0,36,72,144,180},
{0,36,72,108,180}, {0,36,72,108,144}};
if (lut_numCnInCnGroups[3] > 0)
{
// Number of groups of 32 CNs for parallel processing
// Ceil for values not divisible by 32
M = (lut_numCnInCnGroups[3]*Z + 63)>>6;
// Set the offset to each bit within a group in terms of 32 Byte
bitOffsetInGroup = (lut_numCnInCnGroups_BG2_R15[3]*NR_LDPC_ZMAX)>>6;
// Set pointers to start of group 6
p_cnProcBuf = (__m512i*) &cnProcBuf [lut_startAddrCnGroups[3]];
p_cnProcBufRes = (__m512i*) &cnProcBufRes[lut_startAddrCnGroups[3]];
// Loop over every BN
for (j=0; j<6; j++)
{
// Set of results pointer to correct BN address
p_cnProcBufResBit = p_cnProcBufRes + (j*bitOffsetInGroup);
// Loop over CNs
for (i=0; i<M; i++)
{
// Abs and sign of 32 CNs (first BN)
zmm0 = p_cnProcBuf[(lut_idxCnProcG6[j][0]/2) + i];
sgn = _mm512_xor_si512(*p_ones, zmm0);
min = _mm512_abs_epi8(zmm0);
// Loop over BNs
for (k=1; k<5; k++)
{
zmm0 = p_cnProcBuf[(lut_idxCnProcG6[j][k]/2) + i];
min = _mm512_min_epu8(min, _mm512_abs_epi8(zmm0));
sgn = _mm512_xor_si512(sgn, zmm0);
}
// Store result
min = _mm512_min_epu8(min, *p_maxLLR); // 128 in epi8 is -127
*p_cnProcBufResBit = conditional_negate(min, sgn,zeros);
p_cnProcBufResBit++;
}
}
}
// =====================================================================
// Process group with 8 BNs
// Offset is 2*384/32 = 24
const uint8_t lut_idxCnProcG8[8][7] = {{24,48,72,96,120,144,168}, {0,48,72,96,120,144,168},
{0,24,72,96,120,144,168}, {0,24,48,96,120,144,168},
{0,24,48,72,120,144,168}, {0,24,48,72,96,144,168},
{0,24,48,72,96,120,168}, {0,24,48,72,96,120,144}};
if (lut_numCnInCnGroups[4] > 0)
{
// Number of groups of 32 CNs for parallel processing
// Ceil for values not divisible by 32
M = (lut_numCnInCnGroups[4]*Z + 63)>>6;
// Set the offset to each bit within a group in terms of 32 Byte
bitOffsetInGroup = (lut_numCnInCnGroups_BG2_R15[4]*NR_LDPC_ZMAX)>>6;
// Set pointers to start of group 8
p_cnProcBuf = (__m512i*) &cnProcBuf [lut_startAddrCnGroups[4]];
p_cnProcBufRes = (__m512i*) &cnProcBufRes[lut_startAddrCnGroups[4]];
// Loop over every BN
for (j=0; j<8; j++)
{
// Set of results pointer to correct BN address
p_cnProcBufResBit = p_cnProcBufRes + (j*bitOffsetInGroup);
// Loop over CNs
for (i=0; i<M; i++)
{
// Abs and sign of 32 CNs (first BN)
zmm0 = p_cnProcBuf[(lut_idxCnProcG8[j][0]/2) + i];
sgn = _mm512_xor_si512(*p_ones, zmm0);
min = _mm512_abs_epi8(zmm0);
// Loop over BNs
for (k=1; k<7; k++)
{
zmm0 = p_cnProcBuf[(lut_idxCnProcG8[j][k]/2) + i];
min = _mm512_min_epu8(min, _mm512_abs_epi8(zmm0));
sgn = _mm512_xor_si512(sgn, zmm0);
}
// Store result
min = _mm512_min_epu8(min, *p_maxLLR); // 128 in epi8 is -127
*p_cnProcBufResBit = conditional_negate(min, sgn,zeros);
p_cnProcBufResBit++;
}
}
}
// =====================================================================
// Process group with 10 BNs
// Offset is 2*384/32 = 24
const uint8_t lut_idxCnProcG10[10][9] = {{24,48,72,96,120,144,168,192,216}, {0,48,72,96,120,144,168,192,216},
{0,24,72,96,120,144,168,192,216}, {0,24,48,96,120,144,168,192,216},
{0,24,48,72,120,144,168,192,216}, {0,24,48,72,96,144,168,192,216},
{0,24,48,72,96,120,168,192,216}, {0,24,48,72,96,120,144,192,216},
{0,24,48,72,96,120,144,168,216}, {0,24,48,72,96,120,144,168,192}};
if (lut_numCnInCnGroups[5] > 0)
{
// Number of groups of 32 CNs for parallel processing
// Ceil for values not divisible by 32
M = (lut_numCnInCnGroups[5]*Z + 63)>>6;
// Set the offset to each bit within a group in terms of 32 Byte
bitOffsetInGroup = (lut_numCnInCnGroups_BG2_R15[5]*NR_LDPC_ZMAX)>>6;
// Set pointers to start of group 10
p_cnProcBuf = (__m512i*) &cnProcBuf [lut_startAddrCnGroups[5]];
p_cnProcBufRes = (__m512i*) &cnProcBufRes[lut_startAddrCnGroups[5]];
// Loop over every BN
for (j=0; j<10; j++)
{
// Set of results pointer to correct BN address
p_cnProcBufResBit = p_cnProcBufRes + (j*bitOffsetInGroup);
// Loop over CNs
for (i=0; i<M; i++)
{
// Abs and sign of 32 CNs (first BN)
zmm0 = p_cnProcBuf[(lut_idxCnProcG10[j][0]/2) + i];
sgn = _mm512_xor_si512(*p_ones, zmm0);
min = _mm512_abs_epi8(zmm0);
// Loop over BNs
for (k=1; k<9; k++)
{
zmm0 = p_cnProcBuf[(lut_idxCnProcG10[j][k]/2) + i];
min = _mm512_min_epu8(min, _mm512_abs_epi8(zmm0));
sgn = _mm512_xor_si512(sgn, zmm0);
}
// Store result
min = _mm512_min_epu8(min, *p_maxLLR); // 128 in epi8 is -127
*p_cnProcBufResBit = conditional_negate(min, sgn,zeros);
p_cnProcBufResBit++;
}
}
}
}
static inline void nrLDPC_cnProc_BG1_AVX512(t_nrLDPC_lut* p_lut, t_nrLDPC_procBuf* p_procBuf, uint16_t Z)
{
const uint8_t* lut_numCnInCnGroups = p_lut->numCnInCnGroups;
const uint32_t* lut_startAddrCnGroups = p_lut->startAddrCnGroups;
int8_t* cnProcBuf = p_procBuf->cnProcBuf;
int8_t* cnProcBufRes = p_procBuf->cnProcBufRes;
__m512i* p_cnProcBuf;
__m512i* p_cnProcBufRes;
// Number of CNs in Groups
uint32_t M;
uint32_t i;
uint32_t j;
uint32_t k;
// Offset to each bit within a group in terms of 32 Byte
uint32_t bitOffsetInGroup;
__m512i zmm0, min, sgn, zeros;
zeros = _mm512_setzero_si512();
// maxLLR = _mm512_set1_epi8((char)127);
__m512i* p_cnProcBufResBit;
const __m512i* p_ones = (__m512i*) ones512_epi8;
const __m512i* p_maxLLR = (__m512i*) maxLLR512_epi8;
// LUT with offsets for bits that need to be processed
// 1. bit proc requires LLRs of 2. and 3. bit, 2.bits of 1. and 3. etc.
// Offsets are in units of bitOffsetInGroup (1*384/32)
const uint8_t lut_idxCnProcG3[3][2] = {{12,24}, {0,24}, {0,12}};
// =====================================================================
// Process group with 3 BNs
if (lut_numCnInCnGroups[0] > 0)
{
// Number of groups of 32 CNs for parallel processing
// Ceil for values not divisible by 32
M = (lut_numCnInCnGroups[0]*Z + 63)>>6;
// Set the offset to each bit within a group in terms of 32 Byte
bitOffsetInGroup = (lut_numCnInCnGroups_BG1_R13[0]*NR_LDPC_ZMAX)>>6;
// Set pointers to start of group 3
p_cnProcBuf = (__m512i*) &cnProcBuf [lut_startAddrCnGroups[0]];
p_cnProcBufRes = (__m512i*) &cnProcBufRes[lut_startAddrCnGroups[0]];
// Loop over every BN
for (j=0; j<3; j++)
{
// Set of results pointer to correct BN address
p_cnProcBufResBit = p_cnProcBufRes + (j*bitOffsetInGroup);
// Loop over CNs
for (i=0; i<M; i++)
{
// Abs and sign of 32 CNs (first BN)
zmm0 = p_cnProcBuf[(lut_idxCnProcG3[j][0]/2) + i];
sgn = _mm512_xor_si512(*p_ones, zmm0);
min = _mm512_abs_epi8(zmm0);
// 32 CNs of second BN
zmm0 = p_cnProcBuf[(lut_idxCnProcG3[j][1]/2) + i];
min = _mm512_min_epu8(min, _mm512_abs_epi8(zmm0));
sgn = _mm512_xor_si512(sgn, zmm0);
// Store result
min = _mm512_min_epu8(min, *p_maxLLR); // 128 in epi8 is -127
*p_cnProcBufResBit = conditional_negate(min, sgn,zeros);
p_cnProcBufResBit++;
}
}
}
// =====================================================================
// Process group with 4 BNs
// Offset is 5*384/32 = 60
const uint8_t lut_idxCnProcG4[4][3] = {{60,120,180}, {0,120,180}, {0,60,180}, {0,60,120}};
if (lut_numCnInCnGroups[1] > 0)
{
// Number of groups of 32 CNs for parallel processing
// Ceil for values not divisible by 32
M = (lut_numCnInCnGroups[1]*Z + 63)>>6;
// Set the offset to each bit within a group in terms of 32 Byte
bitOffsetInGroup = (lut_numCnInCnGroups_BG1_R13[1]*NR_LDPC_ZMAX)>>6;
// Set pointers to start of group 4
p_cnProcBuf = (__m512i*) &cnProcBuf [lut_startAddrCnGroups[1]];
p_cnProcBufRes = (__m512i*) &cnProcBufRes[lut_startAddrCnGroups[1]];
// Loop over every BN
for (j=0; j<4; j++)
{
// Set of results pointer to correct BN address
p_cnProcBufResBit = p_cnProcBufRes + (j*bitOffsetInGroup);
// Loop over CNs
for (i=0; i<M; i++)
{
// Abs and sign of 32 CNs (first BN)
zmm0 = p_cnProcBuf[(lut_idxCnProcG4[j][0]/2) + i];
sgn = _mm512_xor_si512(*p_ones, zmm0);
min = _mm512_abs_epi8(zmm0);
// Loop over BNs
for (k=1; k<3; k++)
{
zmm0 = p_cnProcBuf[(lut_idxCnProcG4[j][k]/2) + i];
min = _mm512_min_epu8(min, _mm512_abs_epi8(zmm0));
sgn = _mm512_xor_si512(sgn, zmm0);
}
// Store result
min = _mm512_min_epu8(min, *p_maxLLR); // 128 in epi8 is -127
*p_cnProcBufResBit = conditional_negate(min, sgn,zeros);
p_cnProcBufResBit++;
}
}
}
// =====================================================================
// Process group with 5 BNs
// Offset is 18*384/32 = 216
const uint16_t lut_idxCnProcG5[5][4] = {{216,432,648,864}, {0,432,648,864},
{0,216,648,864}, {0,216,432,864}, {0,216,432,648}};
if (lut_numCnInCnGroups[2] > 0)
{
// Number of groups of 32 CNs for parallel processing
// Ceil for values not divisible by 32
M = (lut_numCnInCnGroups[2]*Z + 63)>>6;
// Set the offset to each bit within a group in terms of 32 Byte
bitOffsetInGroup = (lut_numCnInCnGroups_BG1_R13[2]*NR_LDPC_ZMAX)>>6;
// Set pointers to start of group 5
p_cnProcBuf = (__m512i*) &cnProcBuf [lut_startAddrCnGroups[2]];
p_cnProcBufRes = (__m512i*) &cnProcBufRes[lut_startAddrCnGroups[2]];
// Loop over every BN
for (j=0; j<5; j++)
{
// Set of results pointer to correct BN address
p_cnProcBufResBit = p_cnProcBufRes + (j*bitOffsetInGroup);
// Loop over CNs
for (i=0; i<M; i++)
{
// Abs and sign of 32 CNs (first BN)
zmm0 = p_cnProcBuf[(lut_idxCnProcG5[j][0]/2) + i];
sgn = _mm512_xor_si512(*p_ones, zmm0);
min = _mm512_abs_epi8(zmm0);
// Loop over BNs
for (k=1; k<4; k++)
{
zmm0 = p_cnProcBuf[(lut_idxCnProcG5[j][k]/2) + i];
min = _mm512_min_epu8(min, _mm512_abs_epi8(zmm0));
sgn = _mm512_xor_si512(sgn, zmm0);
}
// Store result
min = _mm512_min_epu8(min, *p_maxLLR); // 128 in epi8 is -127
*p_cnProcBufResBit = conditional_negate(min, sgn,zeros);
p_cnProcBufResBit++;
}
}
}
// =====================================================================
// Process group with 6 BNs
// Offset is 8*384/32 = 96
const uint16_t lut_idxCnProcG6[6][5] = {{96,192,288,384,480}, {0,192,288,384,480},
{0,96,288,384,480}, {0,96,192,384,480},
{0,96,192,288,480}, {0,96,192,288,384}};
if (lut_numCnInCnGroups[3] > 0)
{
// Number of groups of 32 CNs for parallel processing
// Ceil for values not divisible by 32
M = (lut_numCnInCnGroups[3]*Z + 63)>>6;
// Set the offset to each bit within a group in terms of 32 Byte
bitOffsetInGroup = (lut_numCnInCnGroups_BG1_R13[3]*NR_LDPC_ZMAX)>>6;
// Set pointers to start of group 6
p_cnProcBuf = (__m512i*) &cnProcBuf [lut_startAddrCnGroups[3]];
p_cnProcBufRes = (__m512i*) &cnProcBufRes[lut_startAddrCnGroups[3]];
// Loop over every BN
for (j=0; j<6; j++)
{
// Set of results pointer to correct BN address
p_cnProcBufResBit = p_cnProcBufRes + (j*bitOffsetInGroup);
// Loop over CNs
for (i=0; i<M; i++)
{
// Abs and sign of 32 CNs (first BN)
zmm0 = p_cnProcBuf[(lut_idxCnProcG6[j][0]/2) + i];
sgn = _mm512_xor_si512(*p_ones, zmm0);
min = _mm512_abs_epi8(zmm0);
// Loop over BNs
for (k=1; k<5; k++)
{
zmm0 = p_cnProcBuf[(lut_idxCnProcG6[j][k]/2) + i];
min = _mm512_min_epu8(min, _mm512_abs_epi8(zmm0));
sgn = _mm512_xor_si512(sgn, zmm0);
}
// Store result
min = _mm512_min_epu8(min, *p_maxLLR); // 128 in epi8 is -127
*p_cnProcBufResBit = conditional_negate(min, sgn,zeros);
p_cnProcBufResBit++;
}
}
}
// =====================================================================
// Process group with 7 BNs
// Offset is 5*384/32 = 60
const uint16_t lut_idxCnProcG7[7][6] = {{60,120,180,240,300,360}, {0,120,180,240,300,360},
{0,60,180,240,300,360}, {0,60,120,240,300,360},
{0,60,120,180,300,360}, {0,60,120,180,240,360},
{0,60,120,180,240,300}};
if (lut_numCnInCnGroups[4] > 0)
{
// Number of groups of 32 CNs for parallel processing
// Ceil for values not divisible by 32
M = (lut_numCnInCnGroups[4]*Z + 63)>>6;
// Set the offset to each bit within a group in terms of 32 Byte
bitOffsetInGroup = (lut_numCnInCnGroups_BG1_R13[4]*NR_LDPC_ZMAX)>>6;
// Set pointers to start of group 7
p_cnProcBuf = (__m512i*) &cnProcBuf [lut_startAddrCnGroups[4]];
p_cnProcBufRes = (__m512i*) &cnProcBufRes[lut_startAddrCnGroups[4]];
// Loop over every BN
for (j=0; j<7; j++)
{
// Set of results pointer to correct BN address
p_cnProcBufResBit = p_cnProcBufRes + (j*bitOffsetInGroup);
// Loop over CNs
for (i=0; i<M; i++)
{
// Abs and sign of 32 CNs (first BN)
zmm0 = p_cnProcBuf[(lut_idxCnProcG7[j][0]/2) + i];
sgn = _mm512_xor_si512(*p_ones, zmm0);
min = _mm512_abs_epi8(zmm0);
// Loop over BNs
for (k=1; k<6; k++)
{
zmm0 = p_cnProcBuf[(lut_idxCnProcG7[j][k]/2) + i];
min = _mm512_min_epu8(min, _mm512_abs_epi8(zmm0));
sgn = _mm512_xor_si512(sgn, zmm0);
}
// Store result
min = _mm512_min_epu8(min, *p_maxLLR); // 128 in epi8 is -127
*p_cnProcBufResBit = conditional_negate(min, sgn,zeros);
p_cnProcBufResBit++;
}
}
}
// =====================================================================
// Process group with 8 BNs
// Offset is 2*384/32 = 24
const uint8_t lut_idxCnProcG8[8][7] = {{24,48,72,96,120,144,168}, {0,48,72,96,120,144,168},
{0,24,72,96,120,144,168}, {0,24,48,96,120,144,168},
{0,24,48,72,120,144,168}, {0,24,48,72,96,144,168},
{0,24,48,72,96,120,168}, {0,24,48,72,96,120,144}};
if (lut_numCnInCnGroups[5] > 0)
{
// Number of groups of 32 CNs for parallel processing
// Ceil for values not divisible by 32
M = (lut_numCnInCnGroups[5]*Z + 63)>>6;
// Set the offset to each bit within a group in terms of 32 Byte
bitOffsetInGroup = (lut_numCnInCnGroups_BG1_R13[5]*NR_LDPC_ZMAX)>>6;
// Set pointers to start of group 8
p_cnProcBuf = (__m512i*) &cnProcBuf [lut_startAddrCnGroups[5]];
p_cnProcBufRes = (__m512i*) &cnProcBufRes[lut_startAddrCnGroups[5]];
// Loop over every BN
for (j=0; j<8; j++)
{
// Set of results pointer to correct BN address
p_cnProcBufResBit = p_cnProcBufRes + (j*bitOffsetInGroup);
// Loop over CNs
for (i=0; i<M; i++)
{
// Abs and sign of 32 CNs (first BN)
zmm0 = p_cnProcBuf[(lut_idxCnProcG8[j][0]/2) + i];
sgn = _mm512_xor_si512(*p_ones, zmm0);
min = _mm512_abs_epi8(zmm0);
// Loop over BNs
for (k=1; k<7; k++)
{
zmm0 = p_cnProcBuf[(lut_idxCnProcG8[j][k]/2) + i];
min = _mm512_min_epu8(min, _mm512_abs_epi8(zmm0));
sgn = _mm512_xor_si512(sgn, zmm0);
}
// Store result
min = _mm512_min_epu8(min, *p_maxLLR); // 128 in epi8 is -127
*p_cnProcBufResBit = conditional_negate(min, sgn,zeros);
p_cnProcBufResBit++;
}
}
}
// =====================================================================
// Process group with 9 BNs
// Offset is 2*384/32 = 24
const uint8_t lut_idxCnProcG9[9][8] = {{24,48,72,96,120,144,168,192}, {0,48,72,96,120,144,168,192},
{0,24,72,96,120,144,168,192}, {0,24,48,96,120,144,168,192},
{0,24,48,72,120,144,168,192}, {0,24,48,72,96,144,168,192},
{0,24,48,72,96,120,168,192}, {0,24,48,72,96,120,144,192},
{0,24,48,72,96,120,144,168}};
if (lut_numCnInCnGroups[6] > 0)
{
// Number of groups of 32 CNs for parallel processing
// Ceil for values not divisible by 32
M = (lut_numCnInCnGroups[6]*Z + 63)>>6;
// Set the offset to each bit within a group in terms of 32 Byte
bitOffsetInGroup = (lut_numCnInCnGroups_BG1_R13[6]*NR_LDPC_ZMAX)>>6;
// Set pointers to start of group 9
p_cnProcBuf = (__m512i*) &cnProcBuf [lut_startAddrCnGroups[6]];
p_cnProcBufRes = (__m512i*) &cnProcBufRes[lut_startAddrCnGroups[6]];
// Loop over every BN
for (j=0; j<9; j++)
{
// Set of results pointer to correct BN address
p_cnProcBufResBit = p_cnProcBufRes + (j*bitOffsetInGroup);
// Loop over CNs
for (i=0; i<M; i++)
{
// Abs and sign of 32 CNs (first BN)
zmm0 = p_cnProcBuf[(lut_idxCnProcG9[j][0]/2) + i];
sgn = _mm512_xor_si512(*p_ones, zmm0);
min = _mm512_abs_epi8(zmm0);
// Loop over BNs
for (k=1; k<8; k++)
{
zmm0 = p_cnProcBuf[(lut_idxCnProcG9[j][k]/2) + i];
min = _mm512_min_epu8(min, _mm512_abs_epi8(zmm0));
sgn = _mm512_xor_si512(sgn, zmm0);
}
// Store result
min = _mm512_min_epu8(min, *p_maxLLR); // 128 in epi8 is -127
*p_cnProcBufResBit = conditional_negate(min, sgn,zeros);
p_cnProcBufResBit++;
}
}
}
// =====================================================================
// Process group with 10 BNs
// Offset is 1*384/32 = 12
const uint8_t lut_idxCnProcG10[10][9] = {{12,24,36,48,60,72,84,96,108}, {0,24,36,48,60,72,84,96,108},
{0,12,36,48,60,72,84,96,108}, {0,12,24,48,60,72,84,96,108},
{0,12,24,36,60,72,84,96,108}, {0,12,24,36,48,72,84,96,108},
{0,12,24,36,48,60,84,96,108}, {0,12,24,36,48,60,72,96,108},
{0,12,24,36,48,60,72,84,108}, {0,12,24,36,48,60,72,84,96}};
if (lut_numCnInCnGroups[7] > 0)
{
// Number of groups of 32 CNs for parallel processing
// Ceil for values not divisible by 32
M = (lut_numCnInCnGroups[7]*Z + 63)>>6;
// Set the offset to each bit within a group in terms of 32 Byte
bitOffsetInGroup = (lut_numCnInCnGroups_BG1_R13[7]*NR_LDPC_ZMAX)>>6;
// Set pointers to start of group 10
p_cnProcBuf = (__m512i*) &cnProcBuf [lut_startAddrCnGroups[7]];
p_cnProcBufRes = (__m512i*) &cnProcBufRes[lut_startAddrCnGroups[7]];
// Loop over every BN
for (j=0; j<10; j++)
{
// Set of results pointer to correct BN address
p_cnProcBufResBit = p_cnProcBufRes + (j*bitOffsetInGroup);
// Loop over CNs
for (i=0; i<M; i++)
{
// Abs and sign of 32 CNs (first BN)
zmm0 = p_cnProcBuf[(lut_idxCnProcG10[j][0]/2) + i];
sgn = _mm512_xor_si512(*p_ones, zmm0);
min = _mm512_abs_epi8(zmm0);
// Loop over BNs
for (k=1; k<9; k++)
{
zmm0 = p_cnProcBuf[(lut_idxCnProcG10[j][k]/2) + i];
min = _mm512_min_epu8(min, _mm512_abs_epi8(zmm0));
sgn = _mm512_xor_si512(sgn, zmm0);
}
// Store result
min = _mm512_min_epu8(min, *p_maxLLR); // 128 in epi8 is -127
*p_cnProcBufResBit = conditional_negate(min, sgn,zeros);
p_cnProcBufResBit++;
}
}
}
// =====================================================================
// Process group with 19 BNs
// Offset is 4*384/32 = 12
const uint16_t lut_idxCnProcG19[19][18] = {{48,96,144,192,240,288,336,384,432,480,528,576,624,672,720,768,816,864}, {0,96,144,192,240,288,336,384,432,480,528,576,624,672,720,768,816,864},
{0,48,144,192,240,288,336,384,432,480,528,576,624,672,720,768,816,864}, {0,48,96,192,240,288,336,384,432,480,528,576,624,672,720,768,816,864},
{0,48,96,144,240,288,336,384,432,480,528,576,624,672,720,768,816,864}, {0,48,96,144,192,288,336,384,432,480,528,576,624,672,720,768,816,864},
{0,48,96,144,192,240,336,384,432,480,528,576,624,672,720,768,816,864}, {0,48,96,144,192,240,288,384,432,480,528,576,624,672,720,768,816,864},
{0,48,96,144,192,240,288,336,432,480,528,576,624,672,720,768,816,864}, {0,48,96,144,192,240,288,336,384,480,528,576,624,672,720,768,816,864},
{0,48,96,144,192,240,288,336,384,432,528,576,624,672,720,768,816,864}, {0,48,96,144,192,240,288,336,384,432,480,576,624,672,720,768,816,864},
{0,48,96,144,192,240,288,336,384,432,480,528,624,672,720,768,816,864}, {0,48,96,144,192,240,288,336,384,432,480,528,576,672,720,768,816,864},
{0,48,96,144,192,240,288,336,384,432,480,528,576,624,720,768,816,864}, {0,48,96,144,192,240,288,336,384,432,480,528,576,624,672,768,816,864},
{0,48,96,144,192,240,288,336,384,432,480,528,576,624,672,720,816,864}, {0,48,96,144,192,240,288,336,384,432,480,528,576,624,672,720,768,864},
{0,48,96,144,192,240,288,336,384,432,480,528,576,624,672,720,768,816}};
if (lut_numCnInCnGroups[8] > 0)
{
// Number of groups of 32 CNs for parallel processing
// Ceil for values not divisible by 32
M = (lut_numCnInCnGroups[8]*Z + 63)>>6;
// Set the offset to each bit within a group in terms of 32 Byte
bitOffsetInGroup = (lut_numCnInCnGroups_BG1_R13[8]*NR_LDPC_ZMAX)>>6;
// Set pointers to start of group 19
p_cnProcBuf = (__m512i*) &cnProcBuf [lut_startAddrCnGroups[8]];
p_cnProcBufRes = (__m512i*) &cnProcBufRes[lut_startAddrCnGroups[8]];
// Loop over every BN
for (j=0; j<19; j++)
{
// Set of results pointer to correct BN address
p_cnProcBufResBit = p_cnProcBufRes + (j*bitOffsetInGroup);
// Loop over CNs
for (i=0; i<M; i++)
{
// Abs and sign of 32 CNs (first BN)
zmm0 = p_cnProcBuf[(lut_idxCnProcG19[j][0]/2) + i];
sgn = _mm512_xor_si512(*p_ones, zmm0);
min = _mm512_abs_epi8(zmm0);
// Loop over BNs
for (k=1; k<18; k++)
{
zmm0 = p_cnProcBuf[(lut_idxCnProcG19[j][k]/2) + i];
min = _mm512_min_epu8(min, _mm512_abs_epi8(zmm0));
sgn = _mm512_xor_si512(sgn, zmm0);
}
// Store result
min = _mm512_min_epu8(min, *p_maxLLR); // 128 in epi8 is -127
*p_cnProcBufResBit = conditional_negate(min, sgn,zeros);
p_cnProcBufResBit++;
}
}
}
}
#endif
@@ -33,8 +33,10 @@
#include "nrLDPC_mPass.h"
#include "nrLDPC_cnProc.h"
#include "nrLDPC_bnProc.h"
#define UNROLL_CN_PROC 1
#define UNROLL_BN_PROC 1
#define UNROLL_BN_PROC_PC 1
#define UNROLL_BN2CN_PROC 1
/*----------------------------------------------------------------------
| cn processing files -->AVX512
/----------------------------------------------------------------------*/
@@ -197,14 +199,8 @@ static inline uint32_t nrLDPC_decoder_core(int8_t* p_llr, int8_t* p_out, uint32_
#ifdef NR_LDPC_PROFILER_DETAIL
start_meas(&p_profiler->llr2CnProcBuf);
#endif
if (BG == 1)
{
nrLDPC_llr2CnProcBuf_BG1(p_lut, p_llr, cnProcBuf, Z);
}
else
{
nrLDPC_llr2CnProcBuf_BG2(p_lut, p_llr, cnProcBuf, Z);
}
if (BG == 1) nrLDPC_llr2CnProcBuf_BG1(p_lut, p_llr, cnProcBuf, Z);
else nrLDPC_llr2CnProcBuf_BG2(p_lut, p_llr, cnProcBuf, Z);
#ifdef NR_LDPC_PROFILER_DETAIL
stop_meas(&p_profiler->llr2CnProcBuf);
#endif
@@ -220,8 +216,10 @@ static inline uint32_t nrLDPC_decoder_core(int8_t* p_llr, int8_t* p_out, uint32_
#ifdef NR_LDPC_PROFILER_DETAIL
start_meas(&p_profiler->cnProc);
#endif
if (BG==1)
{
if (BG==1) {
#ifndef UNROLL_CN_PROC
nrLDPC_cnProc_BG1(p_lut, cnProcBuf, cnProcBufRes, Z);
#else
switch (R)
{
case 13:
@@ -232,7 +230,7 @@ static inline uint32_t nrLDPC_decoder_core(int8_t* p_llr, int8_t* p_out, uint32_
nrLDPC_cnProc_BG1_R13_AVX2(cnProcBuf, cnProcBufRes, Z);
#endif
break;
}
}
case 23:
{
@@ -242,7 +240,7 @@ static inline uint32_t nrLDPC_decoder_core(int8_t* p_llr, int8_t* p_out, uint32_
nrLDPC_cnProc_BG1_R23_AVX2(cnProcBuf, cnProcBufRes, Z);
#endif
break;
}
}
case 89:
{
@@ -252,14 +250,15 @@ static inline uint32_t nrLDPC_decoder_core(int8_t* p_llr, int8_t* p_out, uint32_
nrLDPC_cnProc_BG1_R89_AVX2(cnProcBuf, cnProcBufRes, Z);
#endif
break;
}
}
}
}
else
{
switch (R)
{
#endif
} else {
#ifndef UNROLL_CN_PROC
nrLDPC_cnProc_BG2(p_lut, cnProcBuf, cnProcBufRes, Z);
#else
switch (R) {
case 15:
{
#ifdef __AVX512BW__
@@ -268,8 +267,7 @@ static inline uint32_t nrLDPC_decoder_core(int8_t* p_llr, int8_t* p_out, uint32_
nrLDPC_cnProc_BG2_R15_AVX2(cnProcBuf, cnProcBufRes, Z);
#endif
break;
}
}
case 13:
{
#ifdef __AVX512BW__
@@ -278,8 +276,7 @@ static inline uint32_t nrLDPC_decoder_core(int8_t* p_llr, int8_t* p_out, uint32_
nrLDPC_cnProc_BG2_R13_AVX2(cnProcBuf, cnProcBufRes, Z);
#endif
break;
}
}
case 23:
{
#ifdef __AVX512BW__
@@ -288,10 +285,11 @@ static inline uint32_t nrLDPC_decoder_core(int8_t* p_llr, int8_t* p_out, uint32_
nrLDPC_cnProc_BG2_R23_AVX2(cnProcBuf, cnProcBufRes, Z);
#endif
break;
}
}
}
}
#endif
}
#ifdef NR_LDPC_PROFILER_DETAIL
stop_meas(&p_profiler->cnProc);
#endif
@@ -304,14 +302,8 @@ static inline uint32_t nrLDPC_decoder_core(int8_t* p_llr, int8_t* p_out, uint32_
#ifdef NR_LDPC_PROFILER_DETAIL
start_meas(&p_profiler->cn2bnProcBuf);
#endif
if (BG == 1)
{
nrLDPC_cn2bnProcBuf_BG1(p_lut, cnProcBufRes, bnProcBuf, Z);
}
else
{
nrLDPC_cn2bnProcBuf_BG2(p_lut, cnProcBufRes, bnProcBuf, Z);
}
if (BG == 1) nrLDPC_cn2bnProcBuf_BG1(p_lut, cnProcBufRes, bnProcBuf, Z);
else nrLDPC_cn2bnProcBuf_BG2(p_lut, cnProcBufRes, bnProcBuf, Z);
#ifdef NR_LDPC_PROFILER_DETAIL
stop_meas(&p_profiler->cn2bnProcBuf);
#endif
@@ -326,12 +318,12 @@ static inline uint32_t nrLDPC_decoder_core(int8_t* p_llr, int8_t* p_out, uint32_
start_meas(&p_profiler->bnProcPc);
#endif
//nrLDPC_bnProcPc(p_lut, p_procBuf, Z);
if (BG==1)
{
switch (R)
{
#ifndef UNROLL_BN_PROC_PC
nrLDPC_bnProcPc(p_lut, bnProcBuf, bnProcBufRes, llrProcBuf, llrRes, Z);
#else
if (BG==1) {
switch (R) {
case 13:
{
nrLDPC_bnProcPc_BG1_R13_AVX2(bnProcBuf,bnProcBufRes,llrRes, llrProcBuf, Z);
@@ -348,34 +340,27 @@ static inline uint32_t nrLDPC_decoder_core(int8_t* p_llr, int8_t* p_out, uint32_
break;
}
}
}
else
{
switch (R)
{
} else {
switch (R) {
case 15:
{
nrLDPC_bnProcPc_BG2_R15_AVX2(bnProcBuf,bnProcBufRes, llrRes, llrProcBuf, Z);
break;
}
case 13:
{
nrLDPC_bnProcPc_BG2_R13_AVX2(bnProcBuf,bnProcBufRes,llrRes,llrProcBuf, Z);
break;
}
case 23:
{
nrLDPC_bnProcPc_BG2_R23_AVX2(bnProcBuf,bnProcBufRes,llrRes, llrProcBuf, Z);
break;
}
}
}
}
#endif
#ifdef NR_LDPC_PROFILER_DETAIL
stop_meas(&p_profiler->bnProcPc);
@@ -389,13 +374,12 @@ static inline uint32_t nrLDPC_decoder_core(int8_t* p_llr, int8_t* p_out, uint32_
#ifdef NR_LDPC_PROFILER_DETAIL
start_meas(&p_profiler->bnProc);
#endif
// nrLDPC_bnProc(p_lut, p_procBuf, Z);
if (BG==1)
{
switch (R)
{
if (BG==1) {
#ifndef UNROLL_BN_PROC
nrLDPC_bnProc(p_lut, bnProcBuf, bnProcBufRes, llrRes, Z);
#else
switch (R) {
case 13:
{
#ifdef __AVX512BW__
@@ -424,11 +408,12 @@ if (BG==1)
break;
}
}
}
else
{
switch (R)
{
#endif
} else {
#ifndef UNROLL_BN2CN_PROC
nrLDPC_bn2cnProcBuf_BG2(p_lut, bnProcBufRes, cnProcBuf, Z);
#else
switch (R) {
case 15:
{
#ifdef __AVX512BW__
@@ -439,7 +424,6 @@ if (BG==1)
break;
}
case 13:
{
#ifdef __AVX512BW__
nrLDPC_bnProc_BG2_R13_AVX512(bnProcBuf, bnProcBufRes,llrRes, Z);
@@ -450,7 +434,6 @@ if (BG==1)
}
case 23:
{
#ifdef __AVX512BW__
nrLDPC_bnProc_BG2_R23_AVX512(bnProcBuf, bnProcBufRes,llrRes, Z);
@@ -459,9 +442,8 @@ if (BG==1)
#endif
break;
}
}
#endif
}
#ifdef NR_LDPC_PROFILER_DETAIL
@@ -477,14 +459,8 @@ if (BG==1)
#ifdef NR_LDPC_PROFILER_DETAIL
start_meas(&p_profiler->bn2cnProcBuf);
#endif
if (BG == 1)
{
nrLDPC_bn2cnProcBuf_BG1(p_lut, bnProcBufRes, cnProcBuf, Z);
}
else
{
nrLDPC_bn2cnProcBuf_BG2(p_lut, bnProcBufRes, cnProcBuf, Z);
}
if (BG == 1) nrLDPC_bn2cnProcBuf_BG1(p_lut, bnProcBufRes, cnProcBuf, Z);
else nrLDPC_bn2cnProcBuf_BG2(p_lut, bnProcBufRes, cnProcBuf, Z);
#ifdef NR_LDPC_PROFILER_DETAIL
stop_meas(&p_profiler->bn2cnProcBuf);
#endif
@@ -499,8 +475,7 @@ if (BG==1)
// First iteration finished
while ( (i < numMaxIter) && (pcRes != 0) )
{
while ( (i < numMaxIter) && (pcRes != 0) ) {
// Increase iteration counter
i++;
@@ -508,10 +483,11 @@ if (BG==1)
#ifdef NR_LDPC_PROFILER_DETAIL
start_meas(&p_profiler->cnProc);
#endif
if (BG==1)
{
switch (R)
{
if (BG==1) {
#ifndef UNROLL_CN_PROC
nrLDPC_cnProc_BG1(p_lut, cnProcBuf, cnProcBufRes, Z);
#else
switch (R) {
case 13:
{
#ifdef __AVX512BW__
@@ -520,8 +496,7 @@ if (BG==1)
nrLDPC_cnProc_BG1_R13_AVX2(cnProcBuf, cnProcBufRes, Z);
#endif
break;
}
}
case 23:
{
#ifdef __AVX512BW__
@@ -530,8 +505,7 @@ if (BG==1)
nrLDPC_cnProc_BG1_R23_AVX2(cnProcBuf, cnProcBufRes, Z);
#endif
break;
}
}
case 89:
{
#ifdef __AVX512BW__
@@ -540,14 +514,14 @@ if (BG==1)
nrLDPC_cnProc_BG1_R89_AVX2(cnProcBuf, cnProcBufRes, Z);
#endif
break;
}
}
}
}
else
{
switch (R)
{
#endif
} else {
#ifndef UNROLL_CN_PROC
nrLDPC_cnProc_BG2(p_lut, cnProcBuf, cnProcBufRes, Z);
#else
switch (R) {
case 15:
{
#ifdef __AVX512BW__
@@ -556,8 +530,7 @@ if (BG==1)
nrLDPC_cnProc_BG2_R15_AVX2(cnProcBuf, cnProcBufRes, Z);
#endif
break;
}
}
case 13:
{
#ifdef __AVX512BW__
@@ -566,8 +539,7 @@ if (BG==1)
nrLDPC_cnProc_BG2_R13_AVX2(cnProcBuf, cnProcBufRes, Z);
#endif
break;
}
}
case 23:
{
#ifdef __AVX512BW__
@@ -576,9 +548,10 @@ if (BG==1)
nrLDPC_cnProc_BG2_R23_AVX2(cnProcBuf, cnProcBufRes, Z);
#endif
break;
}
}
}
#endif
}
}
#ifdef NR_LDPC_PROFILER_DETAIL
stop_meas(&p_profiler->cnProc);
#endif
@@ -591,14 +564,8 @@ if (BG==1)
#ifdef NR_LDPC_PROFILER_DETAIL
start_meas(&p_profiler->cn2bnProcBuf);
#endif
if (BG == 1)
{
nrLDPC_cn2bnProcBuf_BG1(p_lut, cnProcBufRes, bnProcBuf, Z);
}
else
{
nrLDPC_cn2bnProcBuf_BG2(p_lut, cnProcBufRes, bnProcBuf, Z);
}
if (BG == 1) nrLDPC_cn2bnProcBuf_BG1(p_lut, cnProcBufRes, bnProcBuf, Z);
else nrLDPC_cn2bnProcBuf_BG2(p_lut, cnProcBufRes, bnProcBuf, Z);
#ifdef NR_LDPC_PROFILER_DETAIL
stop_meas(&p_profiler->cn2bnProcBuf);
#endif
@@ -612,11 +579,11 @@ if (BG==1)
start_meas(&p_profiler->bnProcPc);
#endif
//nrLDPC_bnProcPc(p_lut, p_procBuf, Z);
if (BG==1)
{
switch (R)
{
#ifndef UNROLL_BN_PROC_PC
nrLDPC_bnProcPc(p_lut, bnProcBuf, bnProcBufRes, llrProcBuf, llrRes, Z);
#else
if (BG==1) {
switch (R) {
case 13:
{
nrLDPC_bnProcPc_BG1_R13_AVX2(bnProcBuf,bnProcBufRes,llrRes, llrProcBuf, Z);
@@ -632,36 +599,28 @@ if (BG==1)
nrLDPC_bnProcPc_BG1_R89_AVX2(bnProcBuf,bnProcBufRes, llrRes, llrProcBuf, Z);
break;
}
}
}
else
{
switch (R)
{
}
} else {
switch (R)
{
case 15:
{
nrLDPC_bnProcPc_BG2_R15_AVX2(bnProcBuf,bnProcBufRes,llrRes, llrProcBuf, Z);
break;
}
case 13:
case 13:
{
nrLDPC_bnProcPc_BG2_R13_AVX2(bnProcBuf,bnProcBufRes,llrRes, llrProcBuf, Z);
break;
}
case 23:
{
nrLDPC_bnProcPc_BG2_R23_AVX2(bnProcBuf,bnProcBufRes,llrRes, llrProcBuf, Z);
break;
}
}
}
}
#endif
#ifdef NR_LDPC_PROFILER_DETAIL
stop_meas(&p_profiler->bnProcPc);
#endif
@@ -673,13 +632,11 @@ if (BG==1)
#ifdef NR_LDPC_PROFILER_DETAIL
start_meas(&p_profiler->bnProc);
#endif
// nrLDPC_bnProc(p_lut, p_procBuf, Z);
if (BG==1)
{
switch (R)
{
#ifndef UNROLL_BN_PROC
nrLDPC_bnProc(p_lut, bnProcBuf, bnProcBufRes, llrRes, Z);
#else
if (BG==1) {
switch (R) {
case 13:
{
#ifdef __AVX512BW__
@@ -707,12 +664,10 @@ if (BG==1)
#endif
break;
}
}
}
else
{
switch (R)
{
}
} else {
switch (R)
{
case 15:
{
#ifdef __AVX512BW__
@@ -723,7 +678,6 @@ if (BG==1)
break;
}
case 13:
{
#ifdef __AVX512BW__
nrLDPC_bnProc_BG2_R13_AVX512(bnProcBuf, bnProcBufRes,llrRes, Z);
@@ -732,9 +686,7 @@ if (BG==1)
#endif
break;
}
case 23:
{
#ifdef __AVX512BW__
nrLDPC_bnProc_BG2_R23_AVX512(bnProcBuf, bnProcBufRes,llrRes, Z);
@@ -743,10 +695,9 @@ if (BG==1)
#endif
break;
}
}
}
}
#endif
@@ -762,14 +713,8 @@ if (BG==1)
#ifdef NR_LDPC_PROFILER_DETAIL
start_meas(&p_profiler->bn2cnProcBuf);
#endif
if (BG == 1)
{
nrLDPC_bn2cnProcBuf_BG1(p_lut, bnProcBufRes, cnProcBuf, Z);
}
else
{
nrLDPC_bn2cnProcBuf_BG2(p_lut, bnProcBufRes, cnProcBuf, Z);
}
if (BG == 1) nrLDPC_bn2cnProcBuf_BG1(p_lut, bnProcBufRes, cnProcBuf, Z);
else nrLDPC_bn2cnProcBuf_BG2(p_lut, bnProcBufRes, cnProcBuf, Z);
#ifdef NR_LDPC_PROFILER_DETAIL
stop_meas(&p_profiler->bn2cnProcBuf);
#endif
@@ -778,360 +723,37 @@ if (BG==1)
nrLDPC_debug_writeBuffer2File(nrLDPC_buffers_CN_PROC, cnProcBuf);
#endif
// Parity Check
// Parity Check
#ifdef NR_LDPC_ENABLE_PARITY_CHECK
#ifdef NR_LDPC_PROFILER_DETAIL
start_meas(&p_profiler->cnProcPc);
start_meas(&p_profiler->cnProcPc);
#endif
if (BG == 1)
{
pcRes = nrLDPC_cnProcPc_BG1(p_lut, cnProcBuf, cnProcBufRes, Z);
}
else
{
pcRes = nrLDPC_cnProcPc_BG2(p_lut, cnProcBuf,cnProcBufRes, Z);
}
if (BG == 1) pcRes = nrLDPC_cnProcPc_BG1(p_lut, cnProcBuf, cnProcBufRes, Z);
else pcRes = nrLDPC_cnProcPc_BG2(p_lut, cnProcBuf, cnProcBufRes, Z);
#ifdef NR_LDPC_PROFILER_DETAIL
stop_meas(&p_profiler->cnProcPc);
stop_meas(&p_profiler->cnProcPc);
#endif
#endif
}
// Last iteration
if ( (i < numMaxIter) && (pcRes != 0) )
{
// Increase iteration counter
i++;
// CN processing
#ifdef NR_LDPC_PROFILER_DETAIL
start_meas(&p_profiler->cnProc);
#endif
if (BG==1)
{
switch (R)
{
case 13:
{
#ifdef __AVX512BW__
nrLDPC_cnProc_BG1_R13_AVX512( cnProcBuf, cnProcBufRes, Z);
#else
nrLDPC_cnProc_BG1_R13_AVX2( cnProcBuf, cnProcBufRes, Z);
#endif
break;
}
case 23:
{
#ifdef __AVX512BW__
nrLDPC_cnProc_BG1_R23_AVX512( cnProcBuf, cnProcBufRes, Z);
#else
nrLDPC_cnProc_BG1_R23_AVX2( cnProcBuf, cnProcBufRes, Z);
#endif
break;
}
case 89:
{
#ifdef __AVX512BW__
nrLDPC_cnProc_BG1_R89_AVX512( cnProcBuf, cnProcBufRes, Z);
#else
nrLDPC_cnProc_BG1_R89_AVX2( cnProcBuf, cnProcBufRes, Z);
#endif
break;
}
}
}
else
{
switch (R)
{
case 15:
{
#ifdef __AVX512BW__
nrLDPC_cnProc_BG2_R15_AVX512( cnProcBuf, cnProcBufRes, Z);
#else
nrLDPC_cnProc_BG2_R15_AVX2( cnProcBuf, cnProcBufRes, Z);
#endif
break;
}
case 13:
{
#ifdef __AVX512BW__
nrLDPC_cnProc_BG2_R13_AVX512( cnProcBuf, cnProcBufRes, Z);
#else
nrLDPC_cnProc_BG2_R13_AVX2( cnProcBuf, cnProcBufRes, Z);
#endif
break;
}
case 23:
{
#ifdef __AVX512BW__
nrLDPC_cnProc_BG2_R23_AVX512( cnProcBuf, cnProcBufRes, Z);
#else
nrLDPC_cnProc_BG2_R23_AVX2( cnProcBuf, cnProcBufRes, Z);
#endif
break;
}
}
}
#ifdef NR_LDPC_PROFILER_DETAIL
stop_meas(&p_profiler->cnProc);
#endif
#ifdef NR_LDPC_DEBUG_MODE
nrLDPC_debug_writeBuffer2File(nrLDPC_buffers_CN_PROC_RES, p_procBuf);
#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, cnProcBufRes, bnProcBuf, Z);
}
else
{
nrLDPC_cn2bnProcBuf_BG2(p_lut, cnProcBufRes, bnProcBuf, Z);
}
#ifdef NR_LDPC_PROFILER_DETAIL
stop_meas(&p_profiler->cn2bnProcBuf);
#endif
#ifdef NR_LDPC_DEBUG_MODE
nrLDPC_debug_writeBuffer2File(nrLDPC_buffers_BN_PROC, p_procBuf);
#endif
// BN Processing
#ifdef NR_LDPC_PROFILER_DETAIL
start_meas(&p_profiler->bnProcPc);
#endif
// nrLDPC_bnProcPc(p_lut, p_procBuf, Z);
if (BG==1)
{
switch (R)
{
case 13:
{
nrLDPC_bnProcPc_BG1_R13_AVX2( bnProcBuf,bnProcBufRes,llrRes, llrProcBuf, Z);
break;
}
case 23:
{
nrLDPC_bnProcPc_BG1_R23_AVX2( bnProcBuf,bnProcBufRes, llrRes, llrProcBuf, Z);
break;
}
case 89:
{
nrLDPC_bnProcPc_BG1_R89_AVX2( bnProcBuf,bnProcBufRes, llrRes, llrProcBuf, Z);
break;
}
}
}
else
{
switch (R)
{
case 15:
{
nrLDPC_bnProcPc_BG2_R15_AVX2( bnProcBuf,bnProcBufRes, llrRes, llrProcBuf, Z);
break;
}
case 13:
{
nrLDPC_bnProcPc_BG2_R13_AVX2( bnProcBuf,bnProcBufRes,llrRes, llrProcBuf, Z);
break;
}
case 23:
{
nrLDPC_bnProcPc_BG2_R23_AVX2( bnProcBuf,bnProcBufRes,llrRes, llrProcBuf, Z);
break;
}
}
}
#ifdef NR_LDPC_PROFILER_DETAIL
stop_meas(&p_profiler->bnProcPc);
#endif
#ifdef NR_LDPC_DEBUG_MODE
nrLDPC_debug_writeBuffer2File(nrLDPC_buffers_LLR_RES, p_procBuf);
#endif
// If parity check not enabled, no need to send the BN proc results
// back to CNs
#ifdef NR_LDPC_ENABLE_PARITY_CHECK
#ifdef NR_LDPC_PROFILER_DETAIL
start_meas(&p_profiler->bnProc);
#endif
//nrLDPC_bnProc(p_lut, p_procBuf, Z);
if (BG==1)
{
switch (R)
{
case 13:
{
#ifdef __AVX512BW__
nrLDPC_bnProc_BG1_R13_AVX512( bnProcBuf, bnProcBufRes,llrRes, Z);
#else
nrLDPC_bnProc_BG1_R13_AVX2( bnProcBuf, bnProcBufRes,llrRes, Z);
#endif
break;
}
case 23:
{
#ifdef __AVX512BW__
nrLDPC_bnProc_BG1_R23_AVX512( bnProcBuf, bnProcBufRes,llrRes, Z);
#else
nrLDPC_bnProc_BG1_R23_AVX2( bnProcBuf, bnProcBufRes,llrRes, Z);
#endif
break;
}
case 89:
{
#ifdef __AVX512BW__
nrLDPC_bnProc_BG1_R89_AVX512( bnProcBuf, bnProcBufRes,llrRes, Z);
#else
nrLDPC_bnProc_BG1_R89_AVX2( bnProcBuf, bnProcBufRes,llrRes, Z);
#endif
break;
}
}
}
else
{
switch (R)
{
case 15:
{
#ifdef __AVX512BW__
nrLDPC_bnProc_BG2_R15_AVX512( bnProcBuf, bnProcBufRes,llrRes, Z);
#else
nrLDPC_bnProc_BG2_R15_AVX2( bnProcBuf, bnProcBufRes,llrRes, Z);
#endif
break;
}
case 13:
{
#ifdef __AVX512BW__
nrLDPC_bnProc_BG2_R13_AVX512( bnProcBuf, bnProcBufRes,llrRes, Z);
#else
nrLDPC_bnProc_BG2_R13_AVX2( bnProcBuf, bnProcBufRes,llrRes, Z);
#endif
break;
}
case 23:
{
#ifdef __AVX512BW__
nrLDPC_bnProc_BG2_R23_AVX512( bnProcBuf, bnProcBufRes,llrRes, Z);
#else
nrLDPC_bnProc_BG2_R23_AVX2( bnProcBuf, bnProcBufRes,llrRes, Z);
#endif
break;
}
}
}
#ifdef NR_LDPC_PROFILER_DETAIL
stop_meas(&p_profiler->bnProc);
#endif
#ifdef NR_LDPC_DEBUG_MODE
nrLDPC_debug_writeBuffer2File(nrLDPC_buffers_BN_PROC_RES, p_procBuf);
#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, bnProcBufRes, cnProcBuf, Z);
}
else
{
nrLDPC_bn2cnProcBuf_BG2(p_lut, bnProcBufRes, cnProcBuf, Z);
}
#ifdef NR_LDPC_PROFILER_DETAIL
stop_meas(&p_profiler->bn2cnProcBuf);
#endif
#ifdef NR_LDPC_DEBUG_MODE
nrLDPC_debug_writeBuffer2File(nrLDPC_buffers_CN_PROC, p_procBuf);
#endif
// Parity Check
#ifdef NR_LDPC_PROFILER_DETAIL
start_meas(&p_profiler->cnProcPc);
#endif
if (BG == 1)
{
pcRes = nrLDPC_cnProcPc_BG1(p_lut, cnProcBuf, cnProcBufRes, Z);
}
else
{
pcRes = nrLDPC_cnProcPc_BG2(p_lut, cnProcBuf, cnProcBufRes, Z);
}
#ifdef NR_LDPC_PROFILER_DETAIL
stop_meas(&p_profiler->cnProcPc);
#endif
#endif
}
// If maximum number of iterations reached an PC still fails increase number of iterations
// Thus, i > numMaxIter indicates that PC has failed
#ifdef NR_LDPC_ENABLE_PARITY_CHECK
if (pcRes != 0)
{
i++;
}
#endif
} // end while
// Last iteration
if (pcRes != 0) i++;
// Assign results from processing buffer to output
#ifdef NR_LDPC_PROFILER_DETAIL
start_meas(&p_profiler->llrRes2llrOut);
start_meas(&p_profiler->llrRes2llrOut);
#endif
nrLDPC_llrRes2llrOut(p_lut, p_llrOut, llrRes, Z, BG);
nrLDPC_llrRes2llrOut(p_lut, p_llrOut, llrRes, Z, BG);
#ifdef NR_LDPC_PROFILER_DETAIL
stop_meas(&p_profiler->llrRes2llrOut);
stop_meas(&p_profiler->llrRes2llrOut);
#endif
// Hard-decision
#ifdef NR_LDPC_PROFILER_DETAIL
start_meas(&p_profiler->llr2bit);
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);
}
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
@@ -41,15 +41,6 @@
\param Z Lifting size
\param cshift Circular shift
*/
//more faster memcpy by using "rep movsb", which on modern processors is highly optimized
void *memcpy1(void *dst, const void *src, size_t n)
{
void *ret = dst;
asm volatile("rep movsb" : "+D" (dst) : "c"(n), "S"(src) : "cc", "memory");
return ret;
}
static inline void *nrLDPC_inv_circ_memcpy(int8_t *str1, const int8_t *str2, uint16_t Z, uint16_t cshift)
{
File diff suppressed because it is too large Load Diff
@@ -96,7 +96,7 @@ void nrLDPC_cnProc_BG1_generator_AVX2(const char* dir, int R)
// for (i=0; i<M; i++,iprime++)
// {
fprintf(fd," for (int i=0;i<M;i+=2) {\n");
fprintf(fd," for (int i=0;i<M;i++) {\n");
// Abs and sign of 32 CNs (first BN)
// ymm0 = p_cnProcBuf[lut_idxCnProcG3[j][0] + i];
fprintf(fd," ymm0 = ((__m256i*)cnProcBuf)[%d+i];\n",(lut_startAddrCnGroups[0]>>5)+lut_idxCnProcG3[j][0]);