/*============================================================================== * nrLDPC_bnProc.h * * Defines the functions for bit node processing * * Author: Sebastian Wagner * Date: 17-11-2017 * ===============================================================================*/ #ifndef __NR_LDPC_BNPROC__H__ #define __NR_LDPC_BNPROC__H__ static inline void nrLDPC_bnProcPc(t_nrLDPC_lut* p_lut, uint16_t Z) { const uint8_t* lut_numBnInBnGroups = p_lut->numBnInBnGroups; const uint32_t* lut_startAddrBnGroups = p_lut->startAddrBnGroups; const uint16_t* lut_startAddrBnGroupsLlr = p_lut->startAddrBnGroupsLlr; __m128i* p_bnProcBuf; __m256i* p_bnProcBufRes; __m128i* p_llrProcBuf; __m256i* p_llrProcBuf256; __m256i* p_llrRes; // Number of BNs in Groups uint32_t M; //uint32_t M32rem; uint32_t i,j; uint32_t k; // Offset to each bit within a group in terms of 32 Byte uint32_t cnOffsetInGroup; uint8_t idxBnGroup = 0; __m256i ymm0, ymm1, ymmRes0, ymmRes1; // ===================================================================== // Process group with 1 CN // There is always a BN group with 1 CN // Number of groups of 32 BNs for parallel processing M = (lut_numBnInBnGroups[0]*Z + 31)>>5; p_bnProcBuf = (__m128i*) &bnProcBuf [lut_startAddrBnGroups [idxBnGroup]]; p_bnProcBufRes = (__m256i*) &bnProcBufRes [lut_startAddrBnGroups [idxBnGroup]]; p_llrProcBuf = (__m128i*) &llrProcBuf [lut_startAddrBnGroupsLlr[idxBnGroup]]; p_llrProcBuf256 = (__m256i*) &llrProcBuf [lut_startAddrBnGroupsLlr[idxBnGroup]]; p_llrRes = (__m256i*) &llrRes [lut_startAddrBnGroupsLlr[idxBnGroup]]; // Loop over BNs for (i=0,j=0; i<M; i++,j+=2) { // Store results in bnProcBufRes of first CN for further processing for next iteration // In case parity check fails p_bnProcBufRes[i] = p_llrProcBuf256[i]; // First 16 LLRs of first CN ymm0 = _mm256_cvtepi8_epi16(p_bnProcBuf [j]); ymm1 = _mm256_cvtepi8_epi16(p_llrProcBuf[j]); ymmRes0 = _mm256_adds_epi16(ymm0, ymm1); // Second 16 LLRs of first CN ymm0 = _mm256_cvtepi8_epi16(p_bnProcBuf [j+1]); ymm1 = _mm256_cvtepi8_epi16(p_llrProcBuf[j+1]); ymmRes1 = _mm256_adds_epi16(ymm0, ymm1); // Pack results back to epi8 ymm0 = _mm256_packs_epi16(ymmRes0, ymmRes1); // ymm0 = [ymmRes1[255:128] ymmRes0[255:128] ymmRes1[127:0] ymmRes0[127:0]] // p_llrRes = [ymmRes1[255:128] ymmRes1[127:0] ymmRes0[255:128] ymmRes0[127:0]] *p_llrRes = _mm256_permute4x64_epi64(ymm0, 0xD8); // Next result p_llrRes++; } // ===================================================================== // Process group with 2 CNs if (lut_numBnInBnGroups[1] > 0) { // If elements in group move to next address idxBnGroup++; // Number of groups of 32 BNs for parallel processing M = (lut_numBnInBnGroups[1]*Z + 31)>>5; // Set the offset to each CN within a group in terms of 16 Byte cnOffsetInGroup = (lut_numBnInBnGroups[1]*NR_LDPC_ZMAX)>>4; // Set pointers to start of group 2 p_bnProcBuf = (__m128i*) &bnProcBuf [lut_startAddrBnGroups [idxBnGroup]]; p_llrProcBuf = (__m128i*) &llrProcBuf [lut_startAddrBnGroupsLlr[idxBnGroup]]; p_llrRes = (__m256i*) &llrRes [lut_startAddrBnGroupsLlr[idxBnGroup]]; // Loop over BNs for (i=0,j=0; i<M; i++,j+=2) { // First 16 LLRs of first CN ymmRes0 = _mm256_cvtepi8_epi16(p_bnProcBuf[j]); ymmRes1 = _mm256_cvtepi8_epi16(p_bnProcBuf[j+1]); // Loop over CNs for (k=1; k<2; k++) { ymm0 = _mm256_cvtepi8_epi16(p_bnProcBuf[k*cnOffsetInGroup + j]); ymmRes0 = _mm256_adds_epi16(ymmRes0, ymm0); ymm1 = _mm256_cvtepi8_epi16(p_bnProcBuf[k*cnOffsetInGroup + j+1]); ymmRes1 = _mm256_adds_epi16(ymmRes1, ymm1); } // Add LLR from receiver input ymm0 = _mm256_cvtepi8_epi16(p_llrProcBuf[j]); ymmRes0 = _mm256_adds_epi16(ymmRes0, ymm0); ymm1 = _mm256_cvtepi8_epi16(p_llrProcBuf[j+1]); ymmRes1 = _mm256_adds_epi16(ymmRes1, ymm1); // Pack results back to epi8 ymm0 = _mm256_packs_epi16(ymmRes0, ymmRes1); // ymm0 = [ymmRes1[255:128] ymmRes0[255:128] ymmRes1[127:0] ymmRes0[127:0]] // p_llrRes = [ymmRes1[255:128] ymmRes1[127:0] ymmRes0[255:128] ymmRes0[127:0]] *p_llrRes = _mm256_permute4x64_epi64(ymm0, 0xD8); // Next result p_llrRes++; } } // ===================================================================== // Process group with 3 CNs if (lut_numBnInBnGroups[2] > 0) { // If elements in group move to next address idxBnGroup++; // Number of groups of 32 BNs for parallel processing M = (lut_numBnInBnGroups[2]*Z + 31)>>5; // Set the offset to each CN within a group in terms of 16 Byte cnOffsetInGroup = (lut_numBnInBnGroups[2]*NR_LDPC_ZMAX)>>4; // Set pointers to start of group 3 p_bnProcBuf = (__m128i*) &bnProcBuf [lut_startAddrBnGroups [idxBnGroup]]; p_llrProcBuf = (__m128i*) &llrProcBuf [lut_startAddrBnGroupsLlr[idxBnGroup]]; p_llrRes = (__m256i*) &llrRes [lut_startAddrBnGroupsLlr[idxBnGroup]]; // Loop over BNs for (i=0,j=0; i<M; i++,j+=2) { // First 16 LLRs of first CN ymmRes0 = _mm256_cvtepi8_epi16(p_bnProcBuf[j]); ymmRes1 = _mm256_cvtepi8_epi16(p_bnProcBuf[j+1]); // Loop over CNs for (k=1; k<3; k++) { ymm0 = _mm256_cvtepi8_epi16(p_bnProcBuf[k*cnOffsetInGroup + j]); ymmRes0 = _mm256_adds_epi16(ymmRes0, ymm0); ymm1 = _mm256_cvtepi8_epi16(p_bnProcBuf[k*cnOffsetInGroup + j+1]); ymmRes1 = _mm256_adds_epi16(ymmRes1, ymm1); } // Add LLR from receiver input ymm0 = _mm256_cvtepi8_epi16(p_llrProcBuf[j]); ymmRes0 = _mm256_adds_epi16(ymmRes0, ymm0); ymm1 = _mm256_cvtepi8_epi16(p_llrProcBuf[j+1]); ymmRes1 = _mm256_adds_epi16(ymmRes1, ymm1); // Pack results back to epi8 ymm0 = _mm256_packs_epi16(ymmRes0, ymmRes1); // ymm0 = [ymmRes1[255:128] ymmRes0[255:128] ymmRes1[127:0] ymmRes0[127:0]] // p_llrRes = [ymmRes1[255:128] ymmRes1[127:0] ymmRes0[255:128] ymmRes0[127:0]] *p_llrRes = _mm256_permute4x64_epi64(ymm0, 0xD8); // Next result p_llrRes++; } } // ===================================================================== // Process group with 4 CNs if (lut_numBnInBnGroups[3] > 0) { // If elements in group move to next address idxBnGroup++; // Number of groups of 32 BNs for parallel processing M = (lut_numBnInBnGroups[3]*Z + 31)>>5; // Set the offset to each CN within a group in terms of 16 Byte cnOffsetInGroup = (lut_numBnInBnGroups[3]*NR_LDPC_ZMAX)>>4; // Set pointers to start of group 4 p_bnProcBuf = (__m128i*) &bnProcBuf [lut_startAddrBnGroups [idxBnGroup]]; p_llrProcBuf = (__m128i*) &llrProcBuf [lut_startAddrBnGroupsLlr[idxBnGroup]]; p_llrRes = (__m256i*) &llrRes [lut_startAddrBnGroupsLlr[idxBnGroup]]; // Loop over BNs for (i=0,j=0; i<M; i++,j+=2) { // First 16 LLRs of first CN ymmRes0 = _mm256_cvtepi8_epi16(p_bnProcBuf[j]); ymmRes1 = _mm256_cvtepi8_epi16(p_bnProcBuf[j+1]); // Loop over CNs for (k=1; k<4; k++) { ymm0 = _mm256_cvtepi8_epi16(p_bnProcBuf[k*cnOffsetInGroup + j]); ymmRes0 = _mm256_adds_epi16(ymmRes0, ymm0); ymm1 = _mm256_cvtepi8_epi16(p_bnProcBuf[k*cnOffsetInGroup + j+1]); ymmRes1 = _mm256_adds_epi16(ymmRes1, ymm1); } // Add LLR from receiver input ymm0 = _mm256_cvtepi8_epi16(p_llrProcBuf[j]); ymmRes0 = _mm256_adds_epi16(ymmRes0, ymm0); ymm1 = _mm256_cvtepi8_epi16(p_llrProcBuf[j+1]); ymmRes1 = _mm256_adds_epi16(ymmRes1, ymm1); // Pack results back to epi8 ymm0 = _mm256_packs_epi16(ymmRes0, ymmRes1); // ymm0 = [ymmRes1[255:128] ymmRes0[255:128] ymmRes1[127:0] ymmRes0[127:0]] // p_llrRes = [ymmRes1[255:128] ymmRes1[127:0] ymmRes0[255:128] ymmRes0[127:0]] *p_llrRes = _mm256_permute4x64_epi64(ymm0, 0xD8); // Next result p_llrRes++; } } // ===================================================================== // Process group with 5 CNs if (lut_numBnInBnGroups[4] > 0) { // If elements in group move to next address idxBnGroup++; // Number of groups of 32 BNs for parallel processing M = (lut_numBnInBnGroups[4]*Z + 31)>>5; // Set the offset to each CN within a group in terms of 16 Byte cnOffsetInGroup = (lut_numBnInBnGroups[4]*NR_LDPC_ZMAX)>>4; // Set pointers to start of group 5 p_bnProcBuf = (__m128i*) &bnProcBuf [lut_startAddrBnGroups [idxBnGroup]]; p_llrProcBuf = (__m128i*) &llrProcBuf [lut_startAddrBnGroupsLlr[idxBnGroup]]; p_llrRes = (__m256i*) &llrRes [lut_startAddrBnGroupsLlr[idxBnGroup]]; // Loop over BNs for (i=0,j=0; i<M; i++,j+=2) { // First 16 LLRs of first CN ymmRes0 = _mm256_cvtepi8_epi16(p_bnProcBuf[j]); ymmRes1 = _mm256_cvtepi8_epi16(p_bnProcBuf[j+1]); // Loop over CNs for (k=1; k<5; k++) { ymm0 = _mm256_cvtepi8_epi16(p_bnProcBuf[k*cnOffsetInGroup + j]); ymmRes0 = _mm256_adds_epi16(ymmRes0, ymm0); ymm1 = _mm256_cvtepi8_epi16(p_bnProcBuf[k*cnOffsetInGroup + j+1]); ymmRes1 = _mm256_adds_epi16(ymmRes1, ymm1); } // Add LLR from receiver input ymm0 = _mm256_cvtepi8_epi16(p_llrProcBuf[j]); ymmRes0 = _mm256_adds_epi16(ymmRes0, ymm0); ymm1 = _mm256_cvtepi8_epi16(p_llrProcBuf[j+1]); ymmRes1 = _mm256_adds_epi16(ymmRes1, ymm1); // Pack results back to epi8 ymm0 = _mm256_packs_epi16(ymmRes0, ymmRes1); // ymm0 = [ymmRes1[255:128] ymmRes0[255:128] ymmRes1[127:0] ymmRes0[127:0]] // p_llrRes = [ymmRes1[255:128] ymmRes1[127:0] ymmRes0[255:128] ymmRes0[127:0]] *p_llrRes = _mm256_permute4x64_epi64(ymm0, 0xD8); // Next result p_llrRes++; } } // ===================================================================== // Process group with 6 CNs if (lut_numBnInBnGroups[5] > 0) { // If elements in group move to next address idxBnGroup++; // Number of groups of 32 BNs for parallel processing M = (lut_numBnInBnGroups[5]*Z + 31)>>5; // Set the offset to each CN within a group in terms of 16 Byte cnOffsetInGroup = (lut_numBnInBnGroups[5]*NR_LDPC_ZMAX)>>4; // Set pointers to start of group 6 p_bnProcBuf = (__m128i*) &bnProcBuf [lut_startAddrBnGroups [idxBnGroup]]; p_llrProcBuf = (__m128i*) &llrProcBuf [lut_startAddrBnGroupsLlr[idxBnGroup]]; p_llrRes = (__m256i*) &llrRes [lut_startAddrBnGroupsLlr[idxBnGroup]]; // Loop over BNs for (i=0,j=0; i<M; i++,j+=2) { // First 16 LLRs of first CN ymmRes0 = _mm256_cvtepi8_epi16(p_bnProcBuf[j]); ymmRes1 = _mm256_cvtepi8_epi16(p_bnProcBuf[j+1]); // Loop over CNs for (k=1; k<6; k++) { ymm0 = _mm256_cvtepi8_epi16(p_bnProcBuf[k*cnOffsetInGroup + j]); ymmRes0 = _mm256_adds_epi16(ymmRes0, ymm0); ymm1 = _mm256_cvtepi8_epi16(p_bnProcBuf[k*cnOffsetInGroup + j+1]); ymmRes1 = _mm256_adds_epi16(ymmRes1, ymm1); } // Add LLR from receiver input ymm0 = _mm256_cvtepi8_epi16(p_llrProcBuf[j]); ymmRes0 = _mm256_adds_epi16(ymmRes0, ymm0); ymm1 = _mm256_cvtepi8_epi16(p_llrProcBuf[j+1]); ymmRes1 = _mm256_adds_epi16(ymmRes1, ymm1); // Pack results back to epi8 ymm0 = _mm256_packs_epi16(ymmRes0, ymmRes1); // ymm0 = [ymmRes1[255:128] ymmRes0[255:128] ymmRes1[127:0] ymmRes0[127:0]] // p_llrRes = [ymmRes1[255:128] ymmRes1[127:0] ymmRes0[255:128] ymmRes0[127:0]] *p_llrRes = _mm256_permute4x64_epi64(ymm0, 0xD8); // Next result p_llrRes++; } } // ===================================================================== // Process group with 7 CNs if (lut_numBnInBnGroups[6] > 0) { // If elements in group move to next address idxBnGroup++; // Number of groups of 32 BNs for parallel processing M = (lut_numBnInBnGroups[6]*Z + 31)>>5; // Set the offset to each CN within a group in terms of 16 Byte cnOffsetInGroup = (lut_numBnInBnGroups[6]*NR_LDPC_ZMAX)>>4; // Set pointers to start of group 7 p_bnProcBuf = (__m128i*) &bnProcBuf [lut_startAddrBnGroups [idxBnGroup]]; p_llrProcBuf = (__m128i*) &llrProcBuf [lut_startAddrBnGroupsLlr[idxBnGroup]]; p_llrRes = (__m256i*) &llrRes [lut_startAddrBnGroupsLlr[idxBnGroup]]; // Loop over BNs for (i=0,j=0; i<M; i++,j+=2) { // First 16 LLRs of first CN ymmRes0 = _mm256_cvtepi8_epi16(p_bnProcBuf[j]); ymmRes1 = _mm256_cvtepi8_epi16(p_bnProcBuf[j+1]); // Loop over CNs for (k=1; k<7; k++) { ymm0 = _mm256_cvtepi8_epi16(p_bnProcBuf[k*cnOffsetInGroup + j]); ymmRes0 = _mm256_adds_epi16(ymmRes0, ymm0); ymm1 = _mm256_cvtepi8_epi16(p_bnProcBuf[k*cnOffsetInGroup + j+1]); ymmRes1 = _mm256_adds_epi16(ymmRes1, ymm1); } // Add LLR from receiver input ymm0 = _mm256_cvtepi8_epi16(p_llrProcBuf[j]); ymmRes0 = _mm256_adds_epi16(ymmRes0, ymm0); ymm1 = _mm256_cvtepi8_epi16(p_llrProcBuf[j+1]); ymmRes1 = _mm256_adds_epi16(ymmRes1, ymm1); // Pack results back to epi8 ymm0 = _mm256_packs_epi16(ymmRes0, ymmRes1); // ymm0 = [ymmRes1[255:128] ymmRes0[255:128] ymmRes1[127:0] ymmRes0[127:0]] // p_llrRes = [ymmRes1[255:128] ymmRes1[127:0] ymmRes0[255:128] ymmRes0[127:0]] *p_llrRes = _mm256_permute4x64_epi64(ymm0, 0xD8); // Next result p_llrRes++; } } // ===================================================================== // Process group with 8 CNs if (lut_numBnInBnGroups[7] > 0) { // If elements in group move to next address idxBnGroup++; // Number of groups of 32 BNs for parallel processing M = (lut_numBnInBnGroups[7]*Z + 31)>>5; // Set the offset to each CN within a group in terms of 16 Byte cnOffsetInGroup = (lut_numBnInBnGroups[7]*NR_LDPC_ZMAX)>>4; // Set pointers to start of group 8 p_bnProcBuf = (__m128i*) &bnProcBuf [lut_startAddrBnGroups [idxBnGroup]]; p_llrProcBuf = (__m128i*) &llrProcBuf [lut_startAddrBnGroupsLlr[idxBnGroup]]; p_llrRes = (__m256i*) &llrRes [lut_startAddrBnGroupsLlr[idxBnGroup]]; // Loop over BNs for (i=0,j=0; i<M; i++,j+=2) { // First 16 LLRs of first CN ymmRes0 = _mm256_cvtepi8_epi16(p_bnProcBuf[j]); ymmRes1 = _mm256_cvtepi8_epi16(p_bnProcBuf[j+1]); // Loop over CNs for (k=1; k<8; k++) { ymm0 = _mm256_cvtepi8_epi16(p_bnProcBuf[k*cnOffsetInGroup + j]); ymmRes0 = _mm256_adds_epi16(ymmRes0, ymm0); ymm1 = _mm256_cvtepi8_epi16(p_bnProcBuf[k*cnOffsetInGroup + j+1]); ymmRes1 = _mm256_adds_epi16(ymmRes1, ymm1); } // Add LLR from receiver input ymm0 = _mm256_cvtepi8_epi16(p_llrProcBuf[j]); ymmRes0 = _mm256_adds_epi16(ymmRes0, ymm0); ymm1 = _mm256_cvtepi8_epi16(p_llrProcBuf[j+1]); ymmRes1 = _mm256_adds_epi16(ymmRes1, ymm1); // Pack results back to epi8 ymm0 = _mm256_packs_epi16(ymmRes0, ymmRes1); // ymm0 = [ymmRes1[255:128] ymmRes0[255:128] ymmRes1[127:0] ymmRes0[127:0]] // p_llrRes = [ymmRes1[255:128] ymmRes1[127:0] ymmRes0[255:128] ymmRes0[127:0]] *p_llrRes = _mm256_permute4x64_epi64(ymm0, 0xD8); // Next result p_llrRes++; } } // ===================================================================== // Process group with 9 CNs if (lut_numBnInBnGroups[8] > 0) { // If elements in group move to next address idxBnGroup++; // Number of groups of 32 BNs for parallel processing M = (lut_numBnInBnGroups[8]*Z + 31)>>5; // Set the offset to each CN within a group in terms of 16 Byte cnOffsetInGroup = (lut_numBnInBnGroups[8]*NR_LDPC_ZMAX)>>4; // Set pointers to start of group 9 p_bnProcBuf = (__m128i*) &bnProcBuf [lut_startAddrBnGroups [idxBnGroup]]; p_llrProcBuf = (__m128i*) &llrProcBuf [lut_startAddrBnGroupsLlr[idxBnGroup]]; p_llrRes = (__m256i*) &llrRes [lut_startAddrBnGroupsLlr[idxBnGroup]]; // Loop over BNs for (i=0,j=0; i<M; i++,j+=2) { // First 16 LLRs of first CN ymmRes0 = _mm256_cvtepi8_epi16(p_bnProcBuf[j]); ymmRes1 = _mm256_cvtepi8_epi16(p_bnProcBuf[j+1]); // Loop over CNs for (k=1; k<9; k++) { ymm0 = _mm256_cvtepi8_epi16(p_bnProcBuf[k*cnOffsetInGroup + j]); ymmRes0 = _mm256_adds_epi16(ymmRes0, ymm0); ymm1 = _mm256_cvtepi8_epi16(p_bnProcBuf[k*cnOffsetInGroup + j+1]); ymmRes1 = _mm256_adds_epi16(ymmRes1, ymm1); } // Add LLR from receiver input ymm0 = _mm256_cvtepi8_epi16(p_llrProcBuf[j]); ymmRes0 = _mm256_adds_epi16(ymmRes0, ymm0); ymm1 = _mm256_cvtepi8_epi16(p_llrProcBuf[j+1]); ymmRes1 = _mm256_adds_epi16(ymmRes1, ymm1); // Pack results back to epi8 ymm0 = _mm256_packs_epi16(ymmRes0, ymmRes1); // ymm0 = [ymmRes1[255:128] ymmRes0[255:128] ymmRes1[127:0] ymmRes0[127:0]] // p_llrRes = [ymmRes1[255:128] ymmRes1[127:0] ymmRes0[255:128] ymmRes0[127:0]] *p_llrRes = _mm256_permute4x64_epi64(ymm0, 0xD8); // Next result p_llrRes++; } } // ===================================================================== // Process group with 10 CNs if (lut_numBnInBnGroups[9] > 0) { // If elements in group move to next address idxBnGroup++; // Number of groups of 32 BNs for parallel processing M = (lut_numBnInBnGroups[9]*Z + 31)>>5; // Set the offset to each CN within a group in terms of 16 Byte cnOffsetInGroup = (lut_numBnInBnGroups[9]*NR_LDPC_ZMAX)>>4; // Set pointers to start of group 10 p_bnProcBuf = (__m128i*) &bnProcBuf [lut_startAddrBnGroups [idxBnGroup]]; p_llrProcBuf = (__m128i*) &llrProcBuf [lut_startAddrBnGroupsLlr[idxBnGroup]]; p_llrRes = (__m256i*) &llrRes [lut_startAddrBnGroupsLlr[idxBnGroup]]; // Loop over BNs for (i=0,j=0; i<M; i++,j+=2) { // First 16 LLRs of first CN ymmRes0 = _mm256_cvtepi8_epi16(p_bnProcBuf[j]); ymmRes1 = _mm256_cvtepi8_epi16(p_bnProcBuf[j+1]); // Loop over CNs for (k=1; k<10; k++) { ymm0 = _mm256_cvtepi8_epi16(p_bnProcBuf[k*cnOffsetInGroup + j]); ymmRes0 = _mm256_adds_epi16(ymmRes0, ymm0); ymm1 = _mm256_cvtepi8_epi16(p_bnProcBuf[k*cnOffsetInGroup + j+1]); ymmRes1 = _mm256_adds_epi16(ymmRes1, ymm1); } // Add LLR from receiver input ymm0 = _mm256_cvtepi8_epi16(p_llrProcBuf[j]); ymmRes0 = _mm256_adds_epi16(ymmRes0, ymm0); ymm1 = _mm256_cvtepi8_epi16(p_llrProcBuf[j+1]); ymmRes1 = _mm256_adds_epi16(ymmRes1, ymm1); // Pack results back to epi8 ymm0 = _mm256_packs_epi16(ymmRes0, ymmRes1); // ymm0 = [ymmRes1[255:128] ymmRes0[255:128] ymmRes1[127:0] ymmRes0[127:0]] // p_llrRes = [ymmRes1[255:128] ymmRes1[127:0] ymmRes0[255:128] ymmRes0[127:0]] *p_llrRes = _mm256_permute4x64_epi64(ymm0, 0xD8); // Next result p_llrRes++; } } // ===================================================================== // Process group with 11 CNs if (lut_numBnInBnGroups[10] > 0) { // If elements in group move to next address idxBnGroup++; // Number of groups of 32 BNs for parallel processing M = (lut_numBnInBnGroups[10]*Z + 31)>>5; // Set the offset to each CN within a group in terms of 16 Byte cnOffsetInGroup = (lut_numBnInBnGroups[10]*NR_LDPC_ZMAX)>>4; // Set pointers to start of group 11 p_bnProcBuf = (__m128i*) &bnProcBuf [lut_startAddrBnGroups [idxBnGroup]]; p_llrProcBuf = (__m128i*) &llrProcBuf [lut_startAddrBnGroupsLlr[idxBnGroup]]; p_llrRes = (__m256i*) &llrRes [lut_startAddrBnGroupsLlr[idxBnGroup]]; // Loop over BNs for (i=0,j=0; i<M; i++,j+=2) { // First 16 LLRs of first CN ymmRes0 = _mm256_cvtepi8_epi16(p_bnProcBuf[j]); ymmRes1 = _mm256_cvtepi8_epi16(p_bnProcBuf[j+1]); // Loop over CNs for (k=1; k<11; k++) { ymm0 = _mm256_cvtepi8_epi16(p_bnProcBuf[k*cnOffsetInGroup + j]); ymmRes0 = _mm256_adds_epi16(ymmRes0, ymm0); ymm1 = _mm256_cvtepi8_epi16(p_bnProcBuf[k*cnOffsetInGroup + j+1]); ymmRes1 = _mm256_adds_epi16(ymmRes1, ymm1); } // Add LLR from receiver input ymm0 = _mm256_cvtepi8_epi16(p_llrProcBuf[j]); ymmRes0 = _mm256_adds_epi16(ymmRes0, ymm0); ymm1 = _mm256_cvtepi8_epi16(p_llrProcBuf[j+1]); ymmRes1 = _mm256_adds_epi16(ymmRes1, ymm1); // Pack results back to epi8 ymm0 = _mm256_packs_epi16(ymmRes0, ymmRes1); // ymm0 = [ymmRes1[255:128] ymmRes0[255:128] ymmRes1[127:0] ymmRes0[127:0]] // p_llrRes = [ymmRes1[255:128] ymmRes1[127:0] ymmRes0[255:128] ymmRes0[127:0]] *p_llrRes = _mm256_permute4x64_epi64(ymm0, 0xD8); // Next result p_llrRes++; } } // ===================================================================== // Process group with 12 CNs if (lut_numBnInBnGroups[11] > 0) { // If elements in group move to next address idxBnGroup++; // Number of groups of 32 BNs for parallel processing M = (lut_numBnInBnGroups[11]*Z + 31)>>5; // Set the offset to each CN within a group in terms of 16 Byte cnOffsetInGroup = (lut_numBnInBnGroups[11]*NR_LDPC_ZMAX)>>4; // Set pointers to start of group 12 p_bnProcBuf = (__m128i*) &bnProcBuf [lut_startAddrBnGroups [idxBnGroup]]; p_llrProcBuf = (__m128i*) &llrProcBuf [lut_startAddrBnGroupsLlr[idxBnGroup]]; p_llrRes = (__m256i*) &llrRes [lut_startAddrBnGroupsLlr[idxBnGroup]]; // Loop over BNs for (i=0,j=0; i<M; i++,j+=2) { // First 16 LLRs of first CN ymmRes0 = _mm256_cvtepi8_epi16(p_bnProcBuf[j]); ymmRes1 = _mm256_cvtepi8_epi16(p_bnProcBuf[j+1]); // Loop over CNs for (k=1; k<12; k++) { ymm0 = _mm256_cvtepi8_epi16(p_bnProcBuf[k*cnOffsetInGroup + j]); ymmRes0 = _mm256_adds_epi16(ymmRes0, ymm0); ymm1 = _mm256_cvtepi8_epi16(p_bnProcBuf[k*cnOffsetInGroup + j+1]); ymmRes1 = _mm256_adds_epi16(ymmRes1, ymm1); } // Add LLR from receiver input ymm0 = _mm256_cvtepi8_epi16(p_llrProcBuf[j]); ymmRes0 = _mm256_adds_epi16(ymmRes0, ymm0); ymm1 = _mm256_cvtepi8_epi16(p_llrProcBuf[j+1]); ymmRes1 = _mm256_adds_epi16(ymmRes1, ymm1); // Pack results back to epi8 ymm0 = _mm256_packs_epi16(ymmRes0, ymmRes1); // ymm0 = [ymmRes1[255:128] ymmRes0[255:128] ymmRes1[127:0] ymmRes0[127:0]] // p_llrRes = [ymmRes1[255:128] ymmRes1[127:0] ymmRes0[255:128] ymmRes0[127:0]] *p_llrRes = _mm256_permute4x64_epi64(ymm0, 0xD8); // Next result p_llrRes++; } } // ===================================================================== // Process group with 13 CNs if (lut_numBnInBnGroups[12] > 0) { // If elements in group move to next address idxBnGroup++; // Number of groups of 32 BNs for parallel processing M = (lut_numBnInBnGroups[12]*Z + 31)>>5; // Set the offset to each CN within a group in terms of 16 Byte cnOffsetInGroup = (lut_numBnInBnGroups[12]*NR_LDPC_ZMAX)>>4; // Set pointers to start of group 13 p_bnProcBuf = (__m128i*) &bnProcBuf [lut_startAddrBnGroups [idxBnGroup]]; p_llrProcBuf = (__m128i*) &llrProcBuf [lut_startAddrBnGroupsLlr[idxBnGroup]]; p_llrRes = (__m256i*) &llrRes [lut_startAddrBnGroupsLlr[idxBnGroup]]; // Loop over BNs for (i=0,j=0; i<M; i++,j+=2) { // First 16 LLRs of first CN ymmRes0 = _mm256_cvtepi8_epi16(p_bnProcBuf[j]); ymmRes1 = _mm256_cvtepi8_epi16(p_bnProcBuf[j+1]); // Loop over CNs for (k=1; k<13; k++) { ymm0 = _mm256_cvtepi8_epi16(p_bnProcBuf[k*cnOffsetInGroup + j]); ymmRes0 = _mm256_adds_epi16(ymmRes0, ymm0); ymm1 = _mm256_cvtepi8_epi16(p_bnProcBuf[k*cnOffsetInGroup + j+1]); ymmRes1 = _mm256_adds_epi16(ymmRes1, ymm1); } // Add LLR from receiver input ymm0 = _mm256_cvtepi8_epi16(p_llrProcBuf[j]); ymmRes0 = _mm256_adds_epi16(ymmRes0, ymm0); ymm1 = _mm256_cvtepi8_epi16(p_llrProcBuf[j+1]); ymmRes1 = _mm256_adds_epi16(ymmRes1, ymm1); // Pack results back to epi8 ymm0 = _mm256_packs_epi16(ymmRes0, ymmRes1); // ymm0 = [ymmRes1[255:128] ymmRes0[255:128] ymmRes1[127:0] ymmRes0[127:0]] // p_llrRes = [ymmRes1[255:128] ymmRes1[127:0] ymmRes0[255:128] ymmRes0[127:0]] *p_llrRes = _mm256_permute4x64_epi64(ymm0, 0xD8); // Next result p_llrRes++; } } // ===================================================================== // Process group with 14 CNs if (lut_numBnInBnGroups[13] > 0) { // If elements in group move to next address idxBnGroup++; // Number of groups of 32 BNs for parallel processing M = (lut_numBnInBnGroups[13]*Z + 31)>>5; // Set the offset to each CN within a group in terms of 16 Byte cnOffsetInGroup = (lut_numBnInBnGroups[13]*NR_LDPC_ZMAX)>>4; // Set pointers to start of group 14 p_bnProcBuf = (__m128i*) &bnProcBuf [lut_startAddrBnGroups [idxBnGroup]]; p_llrProcBuf = (__m128i*) &llrProcBuf [lut_startAddrBnGroupsLlr[idxBnGroup]]; p_llrRes = (__m256i*) &llrRes [lut_startAddrBnGroupsLlr[idxBnGroup]]; // Loop over BNs for (i=0,j=0; i<M; i++,j+=2) { // First 16 LLRs of first CN ymmRes0 = _mm256_cvtepi8_epi16(p_bnProcBuf[j]); ymmRes1 = _mm256_cvtepi8_epi16(p_bnProcBuf[j+1]); // Loop over CNs for (k=1; k<14; k++) { ymm0 = _mm256_cvtepi8_epi16(p_bnProcBuf[k*cnOffsetInGroup + j]); ymmRes0 = _mm256_adds_epi16(ymmRes0, ymm0); ymm1 = _mm256_cvtepi8_epi16(p_bnProcBuf[k*cnOffsetInGroup + j+1]); ymmRes1 = _mm256_adds_epi16(ymmRes1, ymm1); } // Add LLR from receiver input ymm0 = _mm256_cvtepi8_epi16(p_llrProcBuf[j]); ymmRes0 = _mm256_adds_epi16(ymmRes0, ymm0); ymm1 = _mm256_cvtepi8_epi16(p_llrProcBuf[j+1]); ymmRes1 = _mm256_adds_epi16(ymmRes1, ymm1); // Pack results back to epi8 ymm0 = _mm256_packs_epi16(ymmRes0, ymmRes1); // ymm0 = [ymmRes1[255:128] ymmRes0[255:128] ymmRes1[127:0] ymmRes0[127:0]] // p_llrRes = [ymmRes1[255:128] ymmRes1[127:0] ymmRes0[255:128] ymmRes0[127:0]] *p_llrRes = _mm256_permute4x64_epi64(ymm0, 0xD8); // Next result p_llrRes++; } } // ===================================================================== // Process group with 15 CNs if (lut_numBnInBnGroups[14] > 0) { // If elements in group move to next address idxBnGroup++; // Number of groups of 32 BNs for parallel processing M = (lut_numBnInBnGroups[14]*Z + 31)>>5; // Set the offset to each CN within a group in terms of 16 Byte cnOffsetInGroup = (lut_numBnInBnGroups[14]*NR_LDPC_ZMAX)>>4; // Set pointers to start of group 15 p_bnProcBuf = (__m128i*) &bnProcBuf [lut_startAddrBnGroups [idxBnGroup]]; p_llrProcBuf = (__m128i*) &llrProcBuf [lut_startAddrBnGroupsLlr[idxBnGroup]]; p_llrRes = (__m256i*) &llrRes [lut_startAddrBnGroupsLlr[idxBnGroup]]; // Loop over BNs for (i=0,j=0; i<M; i++,j+=2) { // First 16 LLRs of first CN ymmRes0 = _mm256_cvtepi8_epi16(p_bnProcBuf[j]); ymmRes1 = _mm256_cvtepi8_epi16(p_bnProcBuf[j+1]); // Loop over CNs for (k=1; k<15; k++) { ymm0 = _mm256_cvtepi8_epi16(p_bnProcBuf[k*cnOffsetInGroup + j]); ymmRes0 = _mm256_adds_epi16(ymmRes0, ymm0); ymm1 = _mm256_cvtepi8_epi16(p_bnProcBuf[k*cnOffsetInGroup + j+1]); ymmRes1 = _mm256_adds_epi16(ymmRes1, ymm1); } // Add LLR from receiver input ymm0 = _mm256_cvtepi8_epi16(p_llrProcBuf[j]); ymmRes0 = _mm256_adds_epi16(ymmRes0, ymm0); ymm1 = _mm256_cvtepi8_epi16(p_llrProcBuf[j+1]); ymmRes1 = _mm256_adds_epi16(ymmRes1, ymm1); // Pack results back to epi8 ymm0 = _mm256_packs_epi16(ymmRes0, ymmRes1); // ymm0 = [ymmRes1[255:128] ymmRes0[255:128] ymmRes1[127:0] ymmRes0[127:0]] // p_llrRes = [ymmRes1[255:128] ymmRes1[127:0] ymmRes0[255:128] ymmRes0[127:0]] *p_llrRes = _mm256_permute4x64_epi64(ymm0, 0xD8); // Next result p_llrRes++; } } // ===================================================================== // Process group with 16 CNs if (lut_numBnInBnGroups[15] > 0) { // If elements in group move to next address idxBnGroup++; // Number of groups of 32 BNs for parallel processing M = (lut_numBnInBnGroups[15]*Z + 31)>>5; // Set the offset to each CN within a group in terms of 16 Byte cnOffsetInGroup = (lut_numBnInBnGroups[15]*NR_LDPC_ZMAX)>>4; // Set pointers to start of group 16 p_bnProcBuf = (__m128i*) &bnProcBuf [lut_startAddrBnGroups [idxBnGroup]]; p_llrProcBuf = (__m128i*) &llrProcBuf [lut_startAddrBnGroupsLlr[idxBnGroup]]; p_llrRes = (__m256i*) &llrRes [lut_startAddrBnGroupsLlr[idxBnGroup]]; // Loop over BNs for (i=0,j=0; i<M; i++,j+=2) { // First 16 LLRs of first CN ymmRes0 = _mm256_cvtepi8_epi16(p_bnProcBuf[j]); ymmRes1 = _mm256_cvtepi8_epi16(p_bnProcBuf[j+1]); // Loop over CNs for (k=1; k<16; k++) { ymm0 = _mm256_cvtepi8_epi16(p_bnProcBuf[k*cnOffsetInGroup + j]); ymmRes0 = _mm256_adds_epi16(ymmRes0, ymm0); ymm1 = _mm256_cvtepi8_epi16(p_bnProcBuf[k*cnOffsetInGroup + j+1]); ymmRes1 = _mm256_adds_epi16(ymmRes1, ymm1); } // Add LLR from receiver input ymm0 = _mm256_cvtepi8_epi16(p_llrProcBuf[j]); ymmRes0 = _mm256_adds_epi16(ymmRes0, ymm0); ymm1 = _mm256_cvtepi8_epi16(p_llrProcBuf[j+1]); ymmRes1 = _mm256_adds_epi16(ymmRes1, ymm1); // Pack results back to epi8 ymm0 = _mm256_packs_epi16(ymmRes0, ymmRes1); // ymm0 = [ymmRes1[255:128] ymmRes0[255:128] ymmRes1[127:0] ymmRes0[127:0]] // p_llrRes = [ymmRes1[255:128] ymmRes1[127:0] ymmRes0[255:128] ymmRes0[127:0]] *p_llrRes = _mm256_permute4x64_epi64(ymm0, 0xD8); // Next result p_llrRes++; } } // ===================================================================== // Process group with 17 CNs if (lut_numBnInBnGroups[16] > 0) { // If elements in group move to next address idxBnGroup++; // Number of groups of 32 BNs for parallel processing M = (lut_numBnInBnGroups[16]*Z + 31)>>5; // Set the offset to each CN within a group in terms of 16 Byte cnOffsetInGroup = (lut_numBnInBnGroups[16]*NR_LDPC_ZMAX)>>4; // Set pointers to start of group 16 p_bnProcBuf = (__m128i*) &bnProcBuf [lut_startAddrBnGroups [idxBnGroup]]; p_llrProcBuf = (__m128i*) &llrProcBuf [lut_startAddrBnGroupsLlr[idxBnGroup]]; p_llrRes = (__m256i*) &llrRes [lut_startAddrBnGroupsLlr[idxBnGroup]]; // Loop over BNs for (i=0,j=0; i<M; i++,j+=2) { // First 16 LLRs of first CN ymmRes0 = _mm256_cvtepi8_epi16(p_bnProcBuf[j]); ymmRes1 = _mm256_cvtepi8_epi16(p_bnProcBuf[j+1]); // Loop over CNs for (k=1; k<17; k++) { ymm0 = _mm256_cvtepi8_epi16(p_bnProcBuf[k*cnOffsetInGroup + j]); ymmRes0 = _mm256_adds_epi16(ymmRes0, ymm0); ymm1 = _mm256_cvtepi8_epi16(p_bnProcBuf[k*cnOffsetInGroup + j+1]); ymmRes1 = _mm256_adds_epi16(ymmRes1, ymm1); } // Add LLR from receiver input ymm0 = _mm256_cvtepi8_epi16(p_llrProcBuf[j]); ymmRes0 = _mm256_adds_epi16(ymmRes0, ymm0); ymm1 = _mm256_cvtepi8_epi16(p_llrProcBuf[j+1]); ymmRes1 = _mm256_adds_epi16(ymmRes1, ymm1); // Pack results back to epi8 ymm0 = _mm256_packs_epi16(ymmRes0, ymmRes1); // ymm0 = [ymmRes1[255:128] ymmRes0[255:128] ymmRes1[127:0] ymmRes0[127:0]] // p_llrRes = [ymmRes1[255:128] ymmRes1[127:0] ymmRes0[255:128] ymmRes0[127:0]] *p_llrRes = _mm256_permute4x64_epi64(ymm0, 0xD8); // Next result p_llrRes++; } } // ===================================================================== // Process group with 18 CNs if (lut_numBnInBnGroups[17] > 0) { // If elements in group move to next address idxBnGroup++; // Number of groups of 32 BNs for parallel processing M = (lut_numBnInBnGroups[17]*Z + 31)>>5; // Set the offset to each CN within a group in terms of 16 Byte cnOffsetInGroup = (lut_numBnInBnGroups[17]*NR_LDPC_ZMAX)>>4; // Set pointers to start of group 18 p_bnProcBuf = (__m128i*) &bnProcBuf [lut_startAddrBnGroups [idxBnGroup]]; p_llrProcBuf = (__m128i*) &llrProcBuf [lut_startAddrBnGroupsLlr[idxBnGroup]]; p_llrRes = (__m256i*) &llrRes [lut_startAddrBnGroupsLlr[idxBnGroup]]; // Loop over BNs for (i=0,j=0; i<M; i++,j+=2) { // First 16 LLRs of first CN ymmRes0 = _mm256_cvtepi8_epi16(p_bnProcBuf[j]); ymmRes1 = _mm256_cvtepi8_epi16(p_bnProcBuf[j+1]); // Loop over CNs for (k=1; k<18; k++) { ymm0 = _mm256_cvtepi8_epi16(p_bnProcBuf[k*cnOffsetInGroup + j]); ymmRes0 = _mm256_adds_epi16(ymmRes0, ymm0); ymm1 = _mm256_cvtepi8_epi16(p_bnProcBuf[k*cnOffsetInGroup + j+1]); ymmRes1 = _mm256_adds_epi16(ymmRes1, ymm1); } // Add LLR from receiver input ymm0 = _mm256_cvtepi8_epi16(p_llrProcBuf[j]); ymmRes0 = _mm256_adds_epi16(ymmRes0, ymm0); ymm1 = _mm256_cvtepi8_epi16(p_llrProcBuf[j+1]); ymmRes1 = _mm256_adds_epi16(ymmRes1, ymm1); // Pack results back to epi8 ymm0 = _mm256_packs_epi16(ymmRes0, ymmRes1); // ymm0 = [ymmRes1[255:128] ymmRes0[255:128] ymmRes1[127:0] ymmRes0[127:0]] // p_llrRes = [ymmRes1[255:128] ymmRes1[127:0] ymmRes0[255:128] ymmRes0[127:0]] *p_llrRes = _mm256_permute4x64_epi64(ymm0, 0xD8); // Next result p_llrRes++; } } // ===================================================================== // Process group with 19 CNs if (lut_numBnInBnGroups[18] > 0) { // If elements in group move to next address idxBnGroup++; // Number of groups of 32 BNs for parallel processing M = (lut_numBnInBnGroups[18]*Z + 31)>>5; // Set the offset to each CN within a group in terms of 16 Byte cnOffsetInGroup = (lut_numBnInBnGroups[18]*NR_LDPC_ZMAX)>>4; // Set pointers to start of group 19 p_bnProcBuf = (__m128i*) &bnProcBuf [lut_startAddrBnGroups [idxBnGroup]]; p_llrProcBuf = (__m128i*) &llrProcBuf [lut_startAddrBnGroupsLlr[idxBnGroup]]; p_llrRes = (__m256i*) &llrRes [lut_startAddrBnGroupsLlr[idxBnGroup]]; // Loop over BNs for (i=0,j=0; i<M; i++,j+=2) { // First 16 LLRs of first CN ymmRes0 = _mm256_cvtepi8_epi16(p_bnProcBuf[j]); ymmRes1 = _mm256_cvtepi8_epi16(p_bnProcBuf[j+1]); // Loop over CNs for (k=1; k<19; k++) { ymm0 = _mm256_cvtepi8_epi16(p_bnProcBuf[k*cnOffsetInGroup + j]); ymmRes0 = _mm256_adds_epi16(ymmRes0, ymm0); ymm1 = _mm256_cvtepi8_epi16(p_bnProcBuf[k*cnOffsetInGroup + j+1]); ymmRes1 = _mm256_adds_epi16(ymmRes1, ymm1); } // Add LLR from receiver input ymm0 = _mm256_cvtepi8_epi16(p_llrProcBuf[j]); ymmRes0 = _mm256_adds_epi16(ymmRes0, ymm0); ymm1 = _mm256_cvtepi8_epi16(p_llrProcBuf[j+1]); ymmRes1 = _mm256_adds_epi16(ymmRes1, ymm1); // Pack results back to epi8 ymm0 = _mm256_packs_epi16(ymmRes0, ymmRes1); // ymm0 = [ymmRes1[255:128] ymmRes0[255:128] ymmRes1[127:0] ymmRes0[127:0]] // p_llrRes = [ymmRes1[255:128] ymmRes1[127:0] ymmRes0[255:128] ymmRes0[127:0]] *p_llrRes = _mm256_permute4x64_epi64(ymm0, 0xD8); // Next result p_llrRes++; } } // ===================================================================== // Process group with 20 CNs if (lut_numBnInBnGroups[19] > 0) { // If elements in group move to next address idxBnGroup++; // Number of groups of 32 BNs for parallel processing M = (lut_numBnInBnGroups[19]*Z + 31)>>5; // Set the offset to each CN within a group in terms of 16 Byte cnOffsetInGroup = (lut_numBnInBnGroups[19]*NR_LDPC_ZMAX)>>4; // Set pointers to start of group 20 p_bnProcBuf = (__m128i*) &bnProcBuf [lut_startAddrBnGroups [idxBnGroup]]; p_llrProcBuf = (__m128i*) &llrProcBuf [lut_startAddrBnGroupsLlr[idxBnGroup]]; p_llrRes = (__m256i*) &llrRes [lut_startAddrBnGroupsLlr[idxBnGroup]]; // Loop over BNs for (i=0,j=0; i<M; i++,j+=2) { // First 16 LLRs of first CN ymmRes0 = _mm256_cvtepi8_epi16(p_bnProcBuf[j]); ymmRes1 = _mm256_cvtepi8_epi16(p_bnProcBuf[j+1]); // Loop over CNs for (k=1; k<20; k++) { ymm0 = _mm256_cvtepi8_epi16(p_bnProcBuf[k*cnOffsetInGroup + j]); ymmRes0 = _mm256_adds_epi16(ymmRes0, ymm0); ymm1 = _mm256_cvtepi8_epi16(p_bnProcBuf[k*cnOffsetInGroup + j+1]); ymmRes1 = _mm256_adds_epi16(ymmRes1, ymm1); } // Add LLR from receiver input ymm0 = _mm256_cvtepi8_epi16(p_llrProcBuf[j]); ymmRes0 = _mm256_adds_epi16(ymmRes0, ymm0); ymm1 = _mm256_cvtepi8_epi16(p_llrProcBuf[j+1]); ymmRes1 = _mm256_adds_epi16(ymmRes1, ymm1); // Pack results back to epi8 ymm0 = _mm256_packs_epi16(ymmRes0, ymmRes1); // ymm0 = [ymmRes1[255:128] ymmRes0[255:128] ymmRes1[127:0] ymmRes0[127:0]] // p_llrRes = [ymmRes1[255:128] ymmRes1[127:0] ymmRes0[255:128] ymmRes0[127:0]] *p_llrRes = _mm256_permute4x64_epi64(ymm0, 0xD8); // Next result p_llrRes++; } } // ===================================================================== // Process group with 21 CNs if (lut_numBnInBnGroups[20] > 0) { // If elements in group move to next address idxBnGroup++; // Number of groups of 32 BNs for parallel processing M = (lut_numBnInBnGroups[20]*Z + 31)>>5; // Set the offset to each CN within a group in terms of 16 Byte cnOffsetInGroup = (lut_numBnInBnGroups[20]*NR_LDPC_ZMAX)>>4; // Set pointers to start of group 21 p_bnProcBuf = (__m128i*) &bnProcBuf [lut_startAddrBnGroups [idxBnGroup]]; p_llrProcBuf = (__m128i*) &llrProcBuf [lut_startAddrBnGroupsLlr[idxBnGroup]]; p_llrRes = (__m256i*) &llrRes [lut_startAddrBnGroupsLlr[idxBnGroup]]; // Loop over BNs for (i=0,j=0; i<M; i++,j+=2) { // First 16 LLRs of first CN ymmRes0 = _mm256_cvtepi8_epi16(p_bnProcBuf[j]); ymmRes1 = _mm256_cvtepi8_epi16(p_bnProcBuf[j+1]); // Loop over CNs for (k=1; k<21; k++) { ymm0 = _mm256_cvtepi8_epi16(p_bnProcBuf[k*cnOffsetInGroup + j]); ymmRes0 = _mm256_adds_epi16(ymmRes0, ymm0); ymm1 = _mm256_cvtepi8_epi16(p_bnProcBuf[k*cnOffsetInGroup + j+1]); ymmRes1 = _mm256_adds_epi16(ymmRes1, ymm1); } // Add LLR from receiver input ymm0 = _mm256_cvtepi8_epi16(p_llrProcBuf[j]); ymmRes0 = _mm256_adds_epi16(ymmRes0, ymm0); ymm1 = _mm256_cvtepi8_epi16(p_llrProcBuf[j+1]); ymmRes1 = _mm256_adds_epi16(ymmRes1, ymm1); // Pack results back to epi8 ymm0 = _mm256_packs_epi16(ymmRes0, ymmRes1); // ymm0 = [ymmRes1[255:128] ymmRes0[255:128] ymmRes1[127:0] ymmRes0[127:0]] // p_llrRes = [ymmRes1[255:128] ymmRes1[127:0] ymmRes0[255:128] ymmRes0[127:0]] *p_llrRes = _mm256_permute4x64_epi64(ymm0, 0xD8); // Next result p_llrRes++; } } // ===================================================================== // Process group with 22 CNs if (lut_numBnInBnGroups[21] > 0) { // If elements in group move to next address idxBnGroup++; // Number of groups of 32 BNs for parallel processing M = (lut_numBnInBnGroups[21]*Z + 31)>>5; // Set the offset to each CN within a group in terms of 16 Byte cnOffsetInGroup = (lut_numBnInBnGroups[21]*NR_LDPC_ZMAX)>>4; // Set pointers to start of group 22 p_bnProcBuf = (__m128i*) &bnProcBuf [lut_startAddrBnGroups [idxBnGroup]]; p_llrProcBuf = (__m128i*) &llrProcBuf [lut_startAddrBnGroupsLlr[idxBnGroup]]; p_llrRes = (__m256i*) &llrRes [lut_startAddrBnGroupsLlr[idxBnGroup]]; // Loop over BNs for (i=0,j=0; i<M; i++,j+=2) { // First 16 LLRs of first CN ymmRes0 = _mm256_cvtepi8_epi16(p_bnProcBuf[j]); ymmRes1 = _mm256_cvtepi8_epi16(p_bnProcBuf[j+1]); // Loop over CNs for (k=1; k<22; k++) { ymm0 = _mm256_cvtepi8_epi16(p_bnProcBuf[k*cnOffsetInGroup + j]); ymmRes0 = _mm256_adds_epi16(ymmRes0, ymm0); ymm1 = _mm256_cvtepi8_epi16(p_bnProcBuf[k*cnOffsetInGroup + j+1]); ymmRes1 = _mm256_adds_epi16(ymmRes1, ymm1); } // Add LLR from receiver input ymm0 = _mm256_cvtepi8_epi16(p_llrProcBuf[j]); ymmRes0 = _mm256_adds_epi16(ymmRes0, ymm0); ymm1 = _mm256_cvtepi8_epi16(p_llrProcBuf[j+1]); ymmRes1 = _mm256_adds_epi16(ymmRes1, ymm1); // Pack results back to epi8 ymm0 = _mm256_packs_epi16(ymmRes0, ymmRes1); // ymm0 = [ymmRes1[255:128] ymmRes0[255:128] ymmRes1[127:0] ymmRes0[127:0]] // p_llrRes = [ymmRes1[255:128] ymmRes1[127:0] ymmRes0[255:128] ymmRes0[127:0]] *p_llrRes = _mm256_permute4x64_epi64(ymm0, 0xD8); // Next result p_llrRes++; } } // ===================================================================== // Process group with 23 CNs if (lut_numBnInBnGroups[22] > 0) { // If elements in group move to next address idxBnGroup++; // Number of groups of 32 BNs for parallel processing M = (lut_numBnInBnGroups[22]*Z + 31)>>5; // Set the offset to each CN within a group in terms of 16 Byte cnOffsetInGroup = (lut_numBnInBnGroups[22]*NR_LDPC_ZMAX)>>4; // Set pointers to start of group 23 p_bnProcBuf = (__m128i*) &bnProcBuf [lut_startAddrBnGroups [idxBnGroup]]; p_llrProcBuf = (__m128i*) &llrProcBuf [lut_startAddrBnGroupsLlr[idxBnGroup]]; p_llrRes = (__m256i*) &llrRes [lut_startAddrBnGroupsLlr[idxBnGroup]]; // Loop over BNs for (i=0,j=0; i<M; i++,j+=2) { // First 16 LLRs of first CN ymmRes0 = _mm256_cvtepi8_epi16(p_bnProcBuf[j]); ymmRes1 = _mm256_cvtepi8_epi16(p_bnProcBuf[j+1]); // Loop over CNs for (k=1; k<23; k++) { ymm0 = _mm256_cvtepi8_epi16(p_bnProcBuf[k*cnOffsetInGroup + j]); ymmRes0 = _mm256_adds_epi16(ymmRes0, ymm0); ymm1 = _mm256_cvtepi8_epi16(p_bnProcBuf[k*cnOffsetInGroup + j+1]); ymmRes1 = _mm256_adds_epi16(ymmRes1, ymm1); } // Add LLR from receiver input ymm0 = _mm256_cvtepi8_epi16(p_llrProcBuf[j]); ymmRes0 = _mm256_adds_epi16(ymmRes0, ymm0); ymm1 = _mm256_cvtepi8_epi16(p_llrProcBuf[j+1]); ymmRes1 = _mm256_adds_epi16(ymmRes1, ymm1); // Pack results back to epi8 ymm0 = _mm256_packs_epi16(ymmRes0, ymmRes1); // ymm0 = [ymmRes1[255:128] ymmRes0[255:128] ymmRes1[127:0] ymmRes0[127:0]] // p_llrRes = [ymmRes1[255:128] ymmRes1[127:0] ymmRes0[255:128] ymmRes0[127:0]] *p_llrRes = _mm256_permute4x64_epi64(ymm0, 0xD8); // Next result p_llrRes++; } } // ===================================================================== // Process group with 24 CNs if (lut_numBnInBnGroups[23] > 0) { // If elements in group move to next address idxBnGroup++; // Number of groups of 32 BNs for parallel processing M = (lut_numBnInBnGroups[23]*Z + 31)>>5; // Set the offset to each CN within a group in terms of 16 Byte cnOffsetInGroup = (lut_numBnInBnGroups[23]*NR_LDPC_ZMAX)>>4; // Set pointers to start of group 24 p_bnProcBuf = (__m128i*) &bnProcBuf [lut_startAddrBnGroups [idxBnGroup]]; p_llrProcBuf = (__m128i*) &llrProcBuf [lut_startAddrBnGroupsLlr[idxBnGroup]]; p_llrRes = (__m256i*) &llrRes [lut_startAddrBnGroupsLlr[idxBnGroup]]; // Loop over BNs for (i=0,j=0; i<M; i++,j+=2) { // First 16 LLRs of first CN ymmRes0 = _mm256_cvtepi8_epi16(p_bnProcBuf[j]); ymmRes1 = _mm256_cvtepi8_epi16(p_bnProcBuf[j+1]); // Loop over CNs for (k=1; k<24; k++) { ymm0 = _mm256_cvtepi8_epi16(p_bnProcBuf[k*cnOffsetInGroup + j]); ymmRes0 = _mm256_adds_epi16(ymmRes0, ymm0); ymm1 = _mm256_cvtepi8_epi16(p_bnProcBuf[k*cnOffsetInGroup + j+1]); ymmRes1 = _mm256_adds_epi16(ymmRes1, ymm1); } // Add LLR from receiver input ymm0 = _mm256_cvtepi8_epi16(p_llrProcBuf[j]); ymmRes0 = _mm256_adds_epi16(ymmRes0, ymm0); ymm1 = _mm256_cvtepi8_epi16(p_llrProcBuf[j+1]); ymmRes1 = _mm256_adds_epi16(ymmRes1, ymm1); // Pack results back to epi8 ymm0 = _mm256_packs_epi16(ymmRes0, ymmRes1); // ymm0 = [ymmRes1[255:128] ymmRes0[255:128] ymmRes1[127:0] ymmRes0[127:0]] // p_llrRes = [ymmRes1[255:128] ymmRes1[127:0] ymmRes0[255:128] ymmRes0[127:0]] *p_llrRes = _mm256_permute4x64_epi64(ymm0, 0xD8); // Next result p_llrRes++; } } // ===================================================================== // Process group with 25 CNs if (lut_numBnInBnGroups[24] > 0) { // If elements in group move to next address idxBnGroup++; // Number of groups of 32 BNs for parallel processing M = (lut_numBnInBnGroups[24]*Z + 31)>>5; // Set the offset to each CN within a group in terms of 16 Byte cnOffsetInGroup = (lut_numBnInBnGroups[24]*NR_LDPC_ZMAX)>>4; // Set pointers to start of group 25 p_bnProcBuf = (__m128i*) &bnProcBuf [lut_startAddrBnGroups [idxBnGroup]]; p_llrProcBuf = (__m128i*) &llrProcBuf [lut_startAddrBnGroupsLlr[idxBnGroup]]; p_llrRes = (__m256i*) &llrRes [lut_startAddrBnGroupsLlr[idxBnGroup]]; // Loop over BNs for (i=0,j=0; i<M; i++,j+=2) { // First 16 LLRs of first CN ymmRes0 = _mm256_cvtepi8_epi16(p_bnProcBuf[j]); ymmRes1 = _mm256_cvtepi8_epi16(p_bnProcBuf[j+1]); // Loop over CNs for (k=1; k<25; k++) { ymm0 = _mm256_cvtepi8_epi16(p_bnProcBuf[k*cnOffsetInGroup + j]); ymmRes0 = _mm256_adds_epi16(ymmRes0, ymm0); ymm1 = _mm256_cvtepi8_epi16(p_bnProcBuf[k*cnOffsetInGroup + j+1]); ymmRes1 = _mm256_adds_epi16(ymmRes1, ymm1); } // Add LLR from receiver input ymm0 = _mm256_cvtepi8_epi16(p_llrProcBuf[j]); ymmRes0 = _mm256_adds_epi16(ymmRes0, ymm0); ymm1 = _mm256_cvtepi8_epi16(p_llrProcBuf[j+1]); ymmRes1 = _mm256_adds_epi16(ymmRes1, ymm1); // Pack results back to epi8 ymm0 = _mm256_packs_epi16(ymmRes0, ymmRes1); // ymm0 = [ymmRes1[255:128] ymmRes0[255:128] ymmRes1[127:0] ymmRes0[127:0]] // p_llrRes = [ymmRes1[255:128] ymmRes1[127:0] ymmRes0[255:128] ymmRes0[127:0]] *p_llrRes = _mm256_permute4x64_epi64(ymm0, 0xD8); // Next result p_llrRes++; } } // ===================================================================== // Process group with 26 CNs if (lut_numBnInBnGroups[25] > 0) { // If elements in group move to next address idxBnGroup++; // Number of groups of 32 BNs for parallel processing M = (lut_numBnInBnGroups[25]*Z + 31)>>5; // Set the offset to each CN within a group in terms of 16 Byte cnOffsetInGroup = (lut_numBnInBnGroups[25]*NR_LDPC_ZMAX)>>4; // Set pointers to start of group 26 p_bnProcBuf = (__m128i*) &bnProcBuf [lut_startAddrBnGroups [idxBnGroup]]; p_llrProcBuf = (__m128i*) &llrProcBuf [lut_startAddrBnGroupsLlr[idxBnGroup]]; p_llrRes = (__m256i*) &llrRes [lut_startAddrBnGroupsLlr[idxBnGroup]]; // Loop over BNs for (i=0,j=0; i<M; i++,j+=2) { // First 16 LLRs of first CN ymmRes0 = _mm256_cvtepi8_epi16(p_bnProcBuf[j]); ymmRes1 = _mm256_cvtepi8_epi16(p_bnProcBuf[j+1]); // Loop over CNs for (k=1; k<26; k++) { ymm0 = _mm256_cvtepi8_epi16(p_bnProcBuf[k*cnOffsetInGroup + j]); ymmRes0 = _mm256_adds_epi16(ymmRes0, ymm0); ymm1 = _mm256_cvtepi8_epi16(p_bnProcBuf[k*cnOffsetInGroup + j+1]); ymmRes1 = _mm256_adds_epi16(ymmRes1, ymm1); } // Add LLR from receiver input ymm0 = _mm256_cvtepi8_epi16(p_llrProcBuf[j]); ymmRes0 = _mm256_adds_epi16(ymmRes0, ymm0); ymm1 = _mm256_cvtepi8_epi16(p_llrProcBuf[j+1]); ymmRes1 = _mm256_adds_epi16(ymmRes1, ymm1); // Pack results back to epi8 ymm0 = _mm256_packs_epi16(ymmRes0, ymmRes1); // ymm0 = [ymmRes1[255:128] ymmRes0[255:128] ymmRes1[127:0] ymmRes0[127:0]] // p_llrRes = [ymmRes1[255:128] ymmRes1[127:0] ymmRes0[255:128] ymmRes0[127:0]] *p_llrRes = _mm256_permute4x64_epi64(ymm0, 0xD8); // Next result p_llrRes++; } } // ===================================================================== // Process group with 27 CNs if (lut_numBnInBnGroups[26] > 0) { // If elements in group move to next address idxBnGroup++; // Number of groups of 32 BNs for parallel processing M = (lut_numBnInBnGroups[26]*Z + 31)>>5; // Set the offset to each CN within a group in terms of 16 Byte cnOffsetInGroup = (lut_numBnInBnGroups[26]*NR_LDPC_ZMAX)>>4; // Set pointers to start of group 27 p_bnProcBuf = (__m128i*) &bnProcBuf [lut_startAddrBnGroups [idxBnGroup]]; p_llrProcBuf = (__m128i*) &llrProcBuf [lut_startAddrBnGroupsLlr[idxBnGroup]]; p_llrRes = (__m256i*) &llrRes [lut_startAddrBnGroupsLlr[idxBnGroup]]; // Loop over BNs for (i=0,j=0; i<M; i++,j+=2) { // First 16 LLRs of first CN ymmRes0 = _mm256_cvtepi8_epi16(p_bnProcBuf[j]); ymmRes1 = _mm256_cvtepi8_epi16(p_bnProcBuf[j+1]); // Loop over CNs for (k=1; k<27; k++) { ymm0 = _mm256_cvtepi8_epi16(p_bnProcBuf[k*cnOffsetInGroup + j]); ymmRes0 = _mm256_adds_epi16(ymmRes0, ymm0); ymm1 = _mm256_cvtepi8_epi16(p_bnProcBuf[k*cnOffsetInGroup + j+1]); ymmRes1 = _mm256_adds_epi16(ymmRes1, ymm1); } // Add LLR from receiver input ymm0 = _mm256_cvtepi8_epi16(p_llrProcBuf[j]); ymmRes0 = _mm256_adds_epi16(ymmRes0, ymm0); ymm1 = _mm256_cvtepi8_epi16(p_llrProcBuf[j+1]); ymmRes1 = _mm256_adds_epi16(ymmRes1, ymm1); // Pack results back to epi8 ymm0 = _mm256_packs_epi16(ymmRes0, ymmRes1); // ymm0 = [ymmRes1[255:128] ymmRes0[255:128] ymmRes1[127:0] ymmRes0[127:0]] // p_llrRes = [ymmRes1[255:128] ymmRes1[127:0] ymmRes0[255:128] ymmRes0[127:0]] *p_llrRes = _mm256_permute4x64_epi64(ymm0, 0xD8); // Next result p_llrRes++; } } // ===================================================================== // Process group with 28 CNs if (lut_numBnInBnGroups[27] > 0) { // If elements in group move to next address idxBnGroup++; // Number of groups of 32 BNs for parallel processing M = (lut_numBnInBnGroups[27]*Z + 31)>>5; // Set the offset to each CN within a group in terms of 16 Byte cnOffsetInGroup = (lut_numBnInBnGroups[27]*NR_LDPC_ZMAX)>>4; // Set pointers to start of group 28 p_bnProcBuf = (__m128i*) &bnProcBuf [lut_startAddrBnGroups [idxBnGroup]]; p_llrProcBuf = (__m128i*) &llrProcBuf [lut_startAddrBnGroupsLlr[idxBnGroup]]; p_llrRes = (__m256i*) &llrRes [lut_startAddrBnGroupsLlr[idxBnGroup]]; // Loop over BNs for (i=0,j=0; i<M; i++,j+=2) { // First 16 LLRs of first CN ymmRes0 = _mm256_cvtepi8_epi16(p_bnProcBuf[j]); ymmRes1 = _mm256_cvtepi8_epi16(p_bnProcBuf[j+1]); // Loop over CNs for (k=1; k<28; k++) { ymm0 = _mm256_cvtepi8_epi16(p_bnProcBuf[k*cnOffsetInGroup + j]); ymmRes0 = _mm256_adds_epi16(ymmRes0, ymm0); ymm1 = _mm256_cvtepi8_epi16(p_bnProcBuf[k*cnOffsetInGroup + j+1]); ymmRes1 = _mm256_adds_epi16(ymmRes1, ymm1); } // Add LLR from receiver input ymm0 = _mm256_cvtepi8_epi16(p_llrProcBuf[j]); ymmRes0 = _mm256_adds_epi16(ymmRes0, ymm0); ymm1 = _mm256_cvtepi8_epi16(p_llrProcBuf[j+1]); ymmRes1 = _mm256_adds_epi16(ymmRes1, ymm1); // Pack results back to epi8 ymm0 = _mm256_packs_epi16(ymmRes0, ymmRes1); // ymm0 = [ymmRes1[255:128] ymmRes0[255:128] ymmRes1[127:0] ymmRes0[127:0]] // p_llrRes = [ymmRes1[255:128] ymmRes1[127:0] ymmRes0[255:128] ymmRes0[127:0]] *p_llrRes = _mm256_permute4x64_epi64(ymm0, 0xD8); // Next result p_llrRes++; } } // ===================================================================== // Process group with 29 CNs if (lut_numBnInBnGroups[28] > 0) { // If elements in group move to next address idxBnGroup++; // Number of groups of 32 BNs for parallel processing M = (lut_numBnInBnGroups[28]*Z + 31)>>5; // Set the offset to each CN within a group in terms of 16 Byte cnOffsetInGroup = (lut_numBnInBnGroups[28]*NR_LDPC_ZMAX)>>4; // Set pointers to start of group 29 p_bnProcBuf = (__m128i*) &bnProcBuf [lut_startAddrBnGroups [idxBnGroup]]; p_llrProcBuf = (__m128i*) &llrProcBuf [lut_startAddrBnGroupsLlr[idxBnGroup]]; p_llrRes = (__m256i*) &llrRes [lut_startAddrBnGroupsLlr[idxBnGroup]]; // Loop over BNs for (i=0,j=0; i<M; i++,j+=2) { // First 16 LLRs of first CN ymmRes0 = _mm256_cvtepi8_epi16(p_bnProcBuf[j]); ymmRes1 = _mm256_cvtepi8_epi16(p_bnProcBuf[j+1]); // Loop over CNs for (k=1; k<29; k++) { ymm0 = _mm256_cvtepi8_epi16(p_bnProcBuf[k*cnOffsetInGroup + j]); ymmRes0 = _mm256_adds_epi16(ymmRes0, ymm0); ymm1 = _mm256_cvtepi8_epi16(p_bnProcBuf[k*cnOffsetInGroup + j+1]); ymmRes1 = _mm256_adds_epi16(ymmRes1, ymm1); } // Add LLR from receiver input ymm0 = _mm256_cvtepi8_epi16(p_llrProcBuf[j]); ymmRes0 = _mm256_adds_epi16(ymmRes0, ymm0); ymm1 = _mm256_cvtepi8_epi16(p_llrProcBuf[j+1]); ymmRes1 = _mm256_adds_epi16(ymmRes1, ymm1); // Pack results back to epi8 ymm0 = _mm256_packs_epi16(ymmRes0, ymmRes1); // ymm0 = [ymmRes1[255:128] ymmRes0[255:128] ymmRes1[127:0] ymmRes0[127:0]] // p_llrRes = [ymmRes1[255:128] ymmRes1[127:0] ymmRes0[255:128] ymmRes0[127:0]] *p_llrRes = _mm256_permute4x64_epi64(ymm0, 0xD8); // Next result p_llrRes++; } } // ===================================================================== // Process group with 30 CNs if (lut_numBnInBnGroups[29] > 0) { // If elements in group move to next address idxBnGroup++; // Number of groups of 32 BNs for parallel processing M = (lut_numBnInBnGroups[29]*Z + 31)>>5; // Set the offset to each CN within a group in terms of 16 Byte cnOffsetInGroup = (lut_numBnInBnGroups[29]*NR_LDPC_ZMAX)>>4; // Set pointers to start of group 30 p_bnProcBuf = (__m128i*) &bnProcBuf [lut_startAddrBnGroups [idxBnGroup]]; p_llrProcBuf = (__m128i*) &llrProcBuf [lut_startAddrBnGroupsLlr[idxBnGroup]]; p_llrRes = (__m256i*) &llrRes [lut_startAddrBnGroupsLlr[idxBnGroup]]; // Loop over BNs for (i=0,j=0; i<M; i++,j+=2) { // First 16 LLRs of first CN ymmRes0 = _mm256_cvtepi8_epi16(p_bnProcBuf[j]); ymmRes1 = _mm256_cvtepi8_epi16(p_bnProcBuf[j+1]); // Loop over CNs for (k=1; k<30; k++) { ymm0 = _mm256_cvtepi8_epi16(p_bnProcBuf[k*cnOffsetInGroup + j]); ymmRes0 = _mm256_adds_epi16(ymmRes0, ymm0); ymm1 = _mm256_cvtepi8_epi16(p_bnProcBuf[k*cnOffsetInGroup + j+1]); ymmRes1 = _mm256_adds_epi16(ymmRes1, ymm1); } // Add LLR from receiver input ymm0 = _mm256_cvtepi8_epi16(p_llrProcBuf[j]); ymmRes0 = _mm256_adds_epi16(ymmRes0, ymm0); ymm1 = _mm256_cvtepi8_epi16(p_llrProcBuf[j+1]); ymmRes1 = _mm256_adds_epi16(ymmRes1, ymm1); // Pack results back to epi8 ymm0 = _mm256_packs_epi16(ymmRes0, ymmRes1); // ymm0 = [ymmRes1[255:128] ymmRes0[255:128] ymmRes1[127:0] ymmRes0[127:0]] // p_llrRes = [ymmRes1[255:128] ymmRes1[127:0] ymmRes0[255:128] ymmRes0[127:0]] *p_llrRes = _mm256_permute4x64_epi64(ymm0, 0xD8); // Next result p_llrRes++; } } } static inline void nrLDPC_bnProc(t_nrLDPC_lut* p_lut, uint16_t Z) { // BN Processing calculating the values to send back to the CNs for next iteration // bnProcBufRes contains the sum of all edges to each BN at the start of each group const uint8_t* lut_numBnInBnGroups = p_lut->numBnInBnGroups; const uint32_t* lut_startAddrBnGroups = p_lut->startAddrBnGroups; const uint16_t* lut_startAddrBnGroupsLlr = p_lut->startAddrBnGroupsLlr; __m256i* p_bnProcBuf; __m256i* p_bnProcBufRes; __m256i* p_llrRes; __m256i* p_res; // Number of BNs in Groups uint32_t M; //uint32_t M32rem; uint32_t i; uint32_t k; // Offset to each bit within a group in terms of 32 Byte uint32_t cnOffsetInGroup; uint8_t idxBnGroup = 0; // ===================================================================== // Process group with 1 CN // Already done in bnProcBufPc // ===================================================================== // Process group with 2 CNs if (lut_numBnInBnGroups[1] > 0) { // If elements in group move to next address idxBnGroup++; // Number of groups of 32 BNs for parallel processing M = (lut_numBnInBnGroups[1]*Z + 31)>>5; // Set the offset to each CN within a group in terms of 32 Byte cnOffsetInGroup = (lut_numBnInBnGroups[1]*NR_LDPC_ZMAX)>>5; // Set pointers to start of group 2 p_bnProcBuf = (__m256i*) &bnProcBuf [lut_startAddrBnGroups[idxBnGroup]]; p_bnProcBufRes = (__m256i*) &bnProcBufRes[lut_startAddrBnGroups[idxBnGroup]]; // Loop over CNs for (k=0; k<2; k++) { p_res = &p_bnProcBufRes[k*cnOffsetInGroup]; p_llrRes = (__m256i*) &llrRes[lut_startAddrBnGroupsLlr[idxBnGroup]]; // Loop over BNs for (i=0; i<M; i++) { *p_res = _mm256_subs_epi8(*p_llrRes, p_bnProcBuf[k*cnOffsetInGroup + i]); p_res++; p_llrRes++; } } } // ===================================================================== // Process group with 3 CNs if (lut_numBnInBnGroups[2] > 0) { // If elements in group move to next address idxBnGroup++; // Number of groups of 32 BNs for parallel processing M = (lut_numBnInBnGroups[2]*Z + 31)>>5; // Set the offset to each CN within a group in terms of 32 Byte cnOffsetInGroup = (lut_numBnInBnGroups[2]*NR_LDPC_ZMAX)>>5; // Set pointers to start of group 3 p_bnProcBuf = (__m256i*) &bnProcBuf [lut_startAddrBnGroups[idxBnGroup]]; p_bnProcBufRes = (__m256i*) &bnProcBufRes[lut_startAddrBnGroups[idxBnGroup]]; // Loop over CNs for (k=0; k<3; k++) { p_res = &p_bnProcBufRes[k*cnOffsetInGroup]; p_llrRes = (__m256i*) &llrRes[lut_startAddrBnGroupsLlr[idxBnGroup]]; // Loop over BNs for (i=0; i<M; i++) { *p_res = _mm256_subs_epi8(*p_llrRes, p_bnProcBuf[k*cnOffsetInGroup + i]); p_res++; p_llrRes++; } } } // ===================================================================== // Process group with 4 CNs if (lut_numBnInBnGroups[3] > 0) { // If elements in group move to next address idxBnGroup++; // Number of groups of 32 BNs for parallel processing M = (lut_numBnInBnGroups[3]*Z + 31)>>5; // Set the offset to each CN within a group in terms of 32 Byte cnOffsetInGroup = (lut_numBnInBnGroups[3]*NR_LDPC_ZMAX)>>5; // Set pointers to start of group 4 p_bnProcBuf = (__m256i*) &bnProcBuf [lut_startAddrBnGroups[idxBnGroup]]; p_bnProcBufRes = (__m256i*) &bnProcBufRes[lut_startAddrBnGroups[idxBnGroup]]; // Loop over CNs for (k=0; k<4; k++) { p_res = &p_bnProcBufRes[k*cnOffsetInGroup]; p_llrRes = (__m256i*) &llrRes[lut_startAddrBnGroupsLlr[idxBnGroup]]; // Loop over BNs for (i=0; i<M; i++) { *p_res = _mm256_subs_epi8(*p_llrRes, p_bnProcBuf[k*cnOffsetInGroup + i]); p_res++; p_llrRes++; } } } // ===================================================================== // Process group with 5 CNs if (lut_numBnInBnGroups[4] > 0) { // If elements in group move to next address idxBnGroup++; // Number of groups of 32 BNs for parallel processing M = (lut_numBnInBnGroups[4]*Z + 31)>>5; // Set the offset to each CN within a group in terms of 32 Byte cnOffsetInGroup = (lut_numBnInBnGroups[4]*NR_LDPC_ZMAX)>>5; // Set pointers to start of group 5 p_bnProcBuf = (__m256i*) &bnProcBuf [lut_startAddrBnGroups[idxBnGroup]]; p_bnProcBufRes = (__m256i*) &bnProcBufRes[lut_startAddrBnGroups[idxBnGroup]]; // Loop over CNs for (k=0; k<5; k++) { p_res = &p_bnProcBufRes[k*cnOffsetInGroup]; p_llrRes = (__m256i*) &llrRes [lut_startAddrBnGroupsLlr[idxBnGroup]]; // Loop over BNs for (i=0; i<M; i++) { *p_res = _mm256_subs_epi8(*p_llrRes, p_bnProcBuf[k*cnOffsetInGroup + i]); p_res++; p_llrRes++; } } } // ===================================================================== // Process group with 6 CNs if (lut_numBnInBnGroups[5] > 0) { // If elements in group move to next address idxBnGroup++; // Number of groups of 32 BNs for parallel processing M = (lut_numBnInBnGroups[5]*Z + 31)>>5; // Set the offset to each CN within a group in terms of 32 Byte cnOffsetInGroup = (lut_numBnInBnGroups[5]*NR_LDPC_ZMAX)>>5; // Set pointers to start of group 6 p_bnProcBuf = (__m256i*) &bnProcBuf [lut_startAddrBnGroups[idxBnGroup]]; p_bnProcBufRes = (__m256i*) &bnProcBufRes[lut_startAddrBnGroups[idxBnGroup]]; // Loop over CNs for (k=0; k<6; k++) { p_res = &p_bnProcBufRes[k*cnOffsetInGroup]; p_llrRes = (__m256i*) &llrRes[lut_startAddrBnGroupsLlr[idxBnGroup]]; // Loop over BNs for (i=0; i<M; i++) { *p_res = _mm256_subs_epi8(*p_llrRes, p_bnProcBuf[k*cnOffsetInGroup + i]); p_res++; p_llrRes++; } } } // ===================================================================== // Process group with 7 CNs if (lut_numBnInBnGroups[6] > 0) { // If elements in group move to next address idxBnGroup++; // Number of groups of 32 BNs for parallel processing M = (lut_numBnInBnGroups[6]*Z + 31)>>5; // Set the offset to each CN within a group in terms of 32 Byte cnOffsetInGroup = (lut_numBnInBnGroups[6]*NR_LDPC_ZMAX)>>5; // Set pointers to start of group 7 p_bnProcBuf = (__m256i*) &bnProcBuf [lut_startAddrBnGroups[idxBnGroup]]; p_bnProcBufRes = (__m256i*) &bnProcBufRes[lut_startAddrBnGroups[idxBnGroup]]; // Loop over CNs for (k=0; k<7; k++) { p_res = &p_bnProcBufRes[k*cnOffsetInGroup]; p_llrRes = (__m256i*) &llrRes [lut_startAddrBnGroupsLlr[idxBnGroup]]; // Loop over BNs for (i=0; i<M; i++) { *p_res = _mm256_subs_epi8(*p_llrRes, p_bnProcBuf[k*cnOffsetInGroup + i]); p_res++; p_llrRes++; } } } // ===================================================================== // Process group with 8 CNs if (lut_numBnInBnGroups[7] > 0) { // If elements in group move to next address idxBnGroup++; // Number of groups of 32 BNs for parallel processing M = (lut_numBnInBnGroups[7]*Z + 31)>>5; // Set the offset to each CN within a group in terms of 32 Byte cnOffsetInGroup = (lut_numBnInBnGroups[7]*NR_LDPC_ZMAX)>>5; // Set pointers to start of group 8 p_bnProcBuf = (__m256i*) &bnProcBuf [lut_startAddrBnGroups[idxBnGroup]]; p_bnProcBufRes = (__m256i*) &bnProcBufRes[lut_startAddrBnGroups[idxBnGroup]]; // Loop over CNs for (k=0; k<8; k++) { p_res = &p_bnProcBufRes[k*cnOffsetInGroup]; p_llrRes = (__m256i*) &llrRes [lut_startAddrBnGroupsLlr[idxBnGroup]]; // Loop over BNs for (i=0; i<M; i++) { *p_res = _mm256_subs_epi8(*p_llrRes, p_bnProcBuf[k*cnOffsetInGroup + i]); p_res++; p_llrRes++; } } } // ===================================================================== // Process group with 9 CNs if (lut_numBnInBnGroups[8] > 0) { // If elements in group move to next address idxBnGroup++; // Number of groups of 32 BNs for parallel processing M = (lut_numBnInBnGroups[8]*Z + 31)>>5; // Set the offset to each CN within a group in terms of 32 Byte cnOffsetInGroup = (lut_numBnInBnGroups[8]*NR_LDPC_ZMAX)>>5; // Set pointers to start of group 9 p_bnProcBuf = (__m256i*) &bnProcBuf [lut_startAddrBnGroups[idxBnGroup]]; p_bnProcBufRes = (__m256i*) &bnProcBufRes[lut_startAddrBnGroups[idxBnGroup]]; // Loop over CNs for (k=0; k<9; k++) { p_res = &p_bnProcBufRes[k*cnOffsetInGroup]; p_llrRes = (__m256i*) &llrRes [lut_startAddrBnGroupsLlr[idxBnGroup]]; // Loop over BNs for (i=0; i<M; i++) { *p_res = _mm256_subs_epi8(*p_llrRes, p_bnProcBuf[k*cnOffsetInGroup + i]); p_res++; p_llrRes++; } } } // ===================================================================== // Process group with 10 CNs if (lut_numBnInBnGroups[9] > 0) { // If elements in group move to next address idxBnGroup++; // Number of groups of 32 BNs for parallel processing M = (lut_numBnInBnGroups[9]*Z + 31)>>5; // Set the offset to each CN within a group in terms of 32 Byte cnOffsetInGroup = (lut_numBnInBnGroups[9]*NR_LDPC_ZMAX)>>5; // Set pointers to start of group 10 p_bnProcBuf = (__m256i*) &bnProcBuf [lut_startAddrBnGroups[idxBnGroup]]; p_bnProcBufRes = (__m256i*) &bnProcBufRes[lut_startAddrBnGroups[idxBnGroup]]; // Loop over CNs for (k=0; k<10; k++) { p_res = &p_bnProcBufRes[k*cnOffsetInGroup]; p_llrRes = (__m256i*) &llrRes [lut_startAddrBnGroupsLlr[idxBnGroup]]; // Loop over BNs for (i=0; i<M; i++) { *p_res = _mm256_subs_epi8(*p_llrRes, p_bnProcBuf[k*cnOffsetInGroup + i]); p_res++; p_llrRes++; } } } // ===================================================================== // Process group with 11 CNs if (lut_numBnInBnGroups[10] > 0) { // If elements in group move to next address idxBnGroup++; // Number of groups of 32 BNs for parallel processing M = (lut_numBnInBnGroups[10]*Z + 31)>>5; // Set the offset to each CN within a group in terms of 32 Byte cnOffsetInGroup = (lut_numBnInBnGroups[10]*NR_LDPC_ZMAX)>>5; // Set pointers to start of group 10 p_bnProcBuf = (__m256i*) &bnProcBuf [lut_startAddrBnGroups[idxBnGroup]]; p_bnProcBufRes = (__m256i*) &bnProcBufRes[lut_startAddrBnGroups[idxBnGroup]]; // Loop over CNs for (k=0; k<11; k++) { p_res = &p_bnProcBufRes[k*cnOffsetInGroup]; p_llrRes = (__m256i*) &llrRes [lut_startAddrBnGroupsLlr[idxBnGroup]]; // Loop over BNs for (i=0; i<M; i++) { *p_res = _mm256_subs_epi8(*p_llrRes, p_bnProcBuf[k*cnOffsetInGroup + i]); p_res++; p_llrRes++; } } } // ===================================================================== // Process group with 12 CNs if (lut_numBnInBnGroups[11] > 0) { // If elements in group move to next address idxBnGroup++; // Number of groups of 32 BNs for parallel processing M = (lut_numBnInBnGroups[11]*Z + 31)>>5; // Set the offset to each CN within a group in terms of 32 Byte cnOffsetInGroup = (lut_numBnInBnGroups[11]*NR_LDPC_ZMAX)>>5; // Set pointers to start of group 12 p_bnProcBuf = (__m256i*) &bnProcBuf [lut_startAddrBnGroups[idxBnGroup]]; p_bnProcBufRes = (__m256i*) &bnProcBufRes[lut_startAddrBnGroups[idxBnGroup]]; // Loop over CNs for (k=0; k<12; k++) { p_res = &p_bnProcBufRes[k*cnOffsetInGroup]; p_llrRes = (__m256i*) &llrRes [lut_startAddrBnGroupsLlr[idxBnGroup]]; // Loop over BNs for (i=0; i<M; i++) { *p_res = _mm256_subs_epi8(*p_llrRes, p_bnProcBuf[k*cnOffsetInGroup + i]); p_res++; p_llrRes++; } } } // ===================================================================== // Process group with 13 CNs if (lut_numBnInBnGroups[12] > 0) { // If elements in group move to next address idxBnGroup++; // Number of groups of 32 BNs for parallel processing M = (lut_numBnInBnGroups[12]*Z + 31)>>5; // Set the offset to each CN within a group in terms of 32 Byte cnOffsetInGroup = (lut_numBnInBnGroups[12]*NR_LDPC_ZMAX)>>5; // Set pointers to start of group 13 p_bnProcBuf = (__m256i*) &bnProcBuf [lut_startAddrBnGroups[idxBnGroup]]; p_bnProcBufRes = (__m256i*) &bnProcBufRes[lut_startAddrBnGroups[idxBnGroup]]; // Loop over CNs for (k=0; k<13; k++) { p_res = &p_bnProcBufRes[k*cnOffsetInGroup]; p_llrRes = (__m256i*) &llrRes [lut_startAddrBnGroupsLlr[idxBnGroup]]; // Loop over BNs for (i=0; i<M; i++) { *p_res = _mm256_subs_epi8(*p_llrRes, p_bnProcBuf[k*cnOffsetInGroup + i]); p_res++; p_llrRes++; } } } // ===================================================================== // Process group with 14 CNs if (lut_numBnInBnGroups[13] > 0) { // If elements in group move to next address idxBnGroup++; // Number of groups of 32 BNs for parallel processing M = (lut_numBnInBnGroups[13]*Z + 31)>>5; // Set the offset to each CN within a group in terms of 32 Byte cnOffsetInGroup = (lut_numBnInBnGroups[13]*NR_LDPC_ZMAX)>>5; // Set pointers to start of group 14 p_bnProcBuf = (__m256i*) &bnProcBuf [lut_startAddrBnGroups[idxBnGroup]]; p_bnProcBufRes = (__m256i*) &bnProcBufRes[lut_startAddrBnGroups[idxBnGroup]]; // Loop over CNs for (k=0; k<14; k++) { p_res = &p_bnProcBufRes[k*cnOffsetInGroup]; p_llrRes = (__m256i*) &llrRes [lut_startAddrBnGroupsLlr[idxBnGroup]]; // Loop over BNs for (i=0; i<M; i++) { *p_res = _mm256_subs_epi8(*p_llrRes, p_bnProcBuf[k*cnOffsetInGroup + i]); p_res++; p_llrRes++; } } } // ===================================================================== // Process group with 15 CNs if (lut_numBnInBnGroups[14] > 0) { // If elements in group move to next address idxBnGroup++; // Number of groups of 32 BNs for parallel processing M = (lut_numBnInBnGroups[14]*Z + 31)>>5; // Set the offset to each CN within a group in terms of 32 Byte cnOffsetInGroup = (lut_numBnInBnGroups[14]*NR_LDPC_ZMAX)>>5; // Set pointers to start of group 15 p_bnProcBuf = (__m256i*) &bnProcBuf [lut_startAddrBnGroups[idxBnGroup]]; p_bnProcBufRes = (__m256i*) &bnProcBufRes[lut_startAddrBnGroups[idxBnGroup]]; // Loop over CNs for (k=0; k<15; k++) { p_res = &p_bnProcBufRes[k*cnOffsetInGroup]; p_llrRes = (__m256i*) &llrRes [lut_startAddrBnGroupsLlr[idxBnGroup]]; // Loop over BNs for (i=0; i<M; i++) { *p_res = _mm256_subs_epi8(*p_llrRes, p_bnProcBuf[k*cnOffsetInGroup + i]); p_res++; p_llrRes++; } } } // ===================================================================== // Process group with 16 CNs if (lut_numBnInBnGroups[15] > 0) { // If elements in group move to next address idxBnGroup++; // Number of groups of 32 BNs for parallel processing M = (lut_numBnInBnGroups[15]*Z + 31)>>5; // Set the offset to each CN within a group in terms of 32 Byte cnOffsetInGroup = (lut_numBnInBnGroups[15]*NR_LDPC_ZMAX)>>5; // Set pointers to start of group 16 p_bnProcBuf = (__m256i*) &bnProcBuf [lut_startAddrBnGroups[idxBnGroup]]; p_bnProcBufRes = (__m256i*) &bnProcBufRes[lut_startAddrBnGroups[idxBnGroup]]; // Loop over CNs for (k=0; k<16; k++) { p_res = &p_bnProcBufRes[k*cnOffsetInGroup]; p_llrRes = (__m256i*) &llrRes [lut_startAddrBnGroupsLlr[idxBnGroup]]; // Loop over BNs for (i=0; i<M; i++) { *p_res = _mm256_subs_epi8(*p_llrRes, p_bnProcBuf[k*cnOffsetInGroup + i]); p_res++; p_llrRes++; } } } // ===================================================================== // Process group with 17 CNs if (lut_numBnInBnGroups[16] > 0) { // If elements in group move to next address idxBnGroup++; // Number of groups of 32 BNs for parallel processing M = (lut_numBnInBnGroups[16]*Z + 31)>>5; // Set the offset to each CN within a group in terms of 32 Byte cnOffsetInGroup = (lut_numBnInBnGroups[16]*NR_LDPC_ZMAX)>>5; // Set pointers to start of group 17 p_bnProcBuf = (__m256i*) &bnProcBuf [lut_startAddrBnGroups[idxBnGroup]]; p_bnProcBufRes = (__m256i*) &bnProcBufRes[lut_startAddrBnGroups[idxBnGroup]]; // Loop over CNs for (k=0; k<17; k++) { p_res = &p_bnProcBufRes[k*cnOffsetInGroup]; p_llrRes = (__m256i*) &llrRes [lut_startAddrBnGroupsLlr[idxBnGroup]]; // Loop over BNs for (i=0; i<M; i++) { *p_res = _mm256_subs_epi8(*p_llrRes, p_bnProcBuf[k*cnOffsetInGroup + i]); p_res++; p_llrRes++; } } } // ===================================================================== // Process group with 18 CNs if (lut_numBnInBnGroups[17] > 0) { // If elements in group move to next address idxBnGroup++; // Number of groups of 32 BNs for parallel processing M = (lut_numBnInBnGroups[17]*Z + 31)>>5; // Set the offset to each CN within a group in terms of 32 Byte cnOffsetInGroup = (lut_numBnInBnGroups[17]*NR_LDPC_ZMAX)>>5; // Set pointers to start of group 18 p_bnProcBuf = (__m256i*) &bnProcBuf [lut_startAddrBnGroups[idxBnGroup]]; p_bnProcBufRes = (__m256i*) &bnProcBufRes[lut_startAddrBnGroups[idxBnGroup]]; // Loop over CNs for (k=0; k<18; k++) { p_res = &p_bnProcBufRes[k*cnOffsetInGroup]; p_llrRes = (__m256i*) &llrRes [lut_startAddrBnGroupsLlr[idxBnGroup]]; // Loop over BNs for (i=0; i<M; i++) { *p_res = _mm256_subs_epi8(*p_llrRes, p_bnProcBuf[k*cnOffsetInGroup + i]); p_res++; p_llrRes++; } } } // ===================================================================== // Process group with 19 CNs if (lut_numBnInBnGroups[18] > 0) { // If elements in group move to next address idxBnGroup++; // Number of groups of 32 BNs for parallel processing M = (lut_numBnInBnGroups[18]*Z + 31)>>5; // Set the offset to each CN within a group in terms of 32 Byte cnOffsetInGroup = (lut_numBnInBnGroups[18]*NR_LDPC_ZMAX)>>5; // Set pointers to start of group 19 p_bnProcBuf = (__m256i*) &bnProcBuf [lut_startAddrBnGroups[idxBnGroup]]; p_bnProcBufRes = (__m256i*) &bnProcBufRes[lut_startAddrBnGroups[idxBnGroup]]; // Loop over CNs for (k=0; k<19; k++) { p_res = &p_bnProcBufRes[k*cnOffsetInGroup]; p_llrRes = (__m256i*) &llrRes [lut_startAddrBnGroupsLlr[idxBnGroup]]; // Loop over BNs for (i=0; i<M; i++) { *p_res = _mm256_subs_epi8(*p_llrRes, p_bnProcBuf[k*cnOffsetInGroup + i]); p_res++; p_llrRes++; } } } // ===================================================================== // Process group with 20 CNs if (lut_numBnInBnGroups[19] > 0) { // If elements in group move to next address idxBnGroup++; // Number of groups of 32 BNs for parallel processing M = (lut_numBnInBnGroups[19]*Z + 31)>>5; // Set the offset to each CN within a group in terms of 32 Byte cnOffsetInGroup = (lut_numBnInBnGroups[19]*NR_LDPC_ZMAX)>>5; // Set pointers to start of group 20 p_bnProcBuf = (__m256i*) &bnProcBuf [lut_startAddrBnGroups[idxBnGroup]]; p_bnProcBufRes = (__m256i*) &bnProcBufRes[lut_startAddrBnGroups[idxBnGroup]]; // Loop over CNs for (k=0; k<20; k++) { p_res = &p_bnProcBufRes[k*cnOffsetInGroup]; p_llrRes = (__m256i*) &llrRes [lut_startAddrBnGroupsLlr[idxBnGroup]]; // Loop over BNs for (i=0; i<M; i++) { *p_res = _mm256_subs_epi8(*p_llrRes, p_bnProcBuf[k*cnOffsetInGroup + i]); p_res++; p_llrRes++; } } } // ===================================================================== // Process group with 21 CNs if (lut_numBnInBnGroups[20] > 0) { // If elements in group move to next address idxBnGroup++; // Number of groups of 32 BNs for parallel processing M = (lut_numBnInBnGroups[20]*Z + 31)>>5; // Set the offset to each CN within a group in terms of 32 Byte cnOffsetInGroup = (lut_numBnInBnGroups[20]*NR_LDPC_ZMAX)>>5; // Set pointers to start of group 21 p_bnProcBuf = (__m256i*) &bnProcBuf [lut_startAddrBnGroups[idxBnGroup]]; p_bnProcBufRes = (__m256i*) &bnProcBufRes[lut_startAddrBnGroups[idxBnGroup]]; // Loop over CNs for (k=0; k<21; k++) { p_res = &p_bnProcBufRes[k*cnOffsetInGroup]; p_llrRes = (__m256i*) &llrRes [lut_startAddrBnGroupsLlr[idxBnGroup]]; // Loop over BNs for (i=0; i<M; i++) { *p_res = _mm256_subs_epi8(*p_llrRes, p_bnProcBuf[k*cnOffsetInGroup + i]); p_res++; p_llrRes++; } } } // ===================================================================== // Process group with 22 CNs if (lut_numBnInBnGroups[21] > 0) { // If elements in group move to next address idxBnGroup++; // Number of groups of 32 BNs for parallel processing M = (lut_numBnInBnGroups[21]*Z + 31)>>5; // Set the offset to each CN within a group in terms of 32 Byte cnOffsetInGroup = (lut_numBnInBnGroups[21]*NR_LDPC_ZMAX)>>5; // Set pointers to start of group 22 p_bnProcBuf = (__m256i*) &bnProcBuf [lut_startAddrBnGroups[idxBnGroup]]; p_bnProcBufRes = (__m256i*) &bnProcBufRes[lut_startAddrBnGroups[idxBnGroup]]; // Loop over CNs for (k=0; k<22; k++) { p_res = &p_bnProcBufRes[k*cnOffsetInGroup]; p_llrRes = (__m256i*) &llrRes [lut_startAddrBnGroupsLlr[idxBnGroup]]; // Loop over BNs for (i=0; i<M; i++) { *p_res = _mm256_subs_epi8(*p_llrRes, p_bnProcBuf[k*cnOffsetInGroup + i]); p_res++; p_llrRes++; } } } // ===================================================================== // Process group with 23 CNs if (lut_numBnInBnGroups[22] > 0) { // If elements in group move to next address idxBnGroup++; // Number of groups of 32 BNs for parallel processing M = (lut_numBnInBnGroups[22]*Z + 31)>>5; // Set the offset to each CN within a group in terms of 32 Byte cnOffsetInGroup = (lut_numBnInBnGroups[22]*NR_LDPC_ZMAX)>>5; // Set pointers to start of group 23 p_bnProcBuf = (__m256i*) &bnProcBuf [lut_startAddrBnGroups[idxBnGroup]]; p_bnProcBufRes = (__m256i*) &bnProcBufRes[lut_startAddrBnGroups[idxBnGroup]]; // Loop over CNs for (k=0; k<23; k++) { p_res = &p_bnProcBufRes[k*cnOffsetInGroup]; p_llrRes = (__m256i*) &llrRes [lut_startAddrBnGroupsLlr[idxBnGroup]]; // Loop over BNs for (i=0; i<M; i++) { *p_res = _mm256_subs_epi8(*p_llrRes, p_bnProcBuf[k*cnOffsetInGroup + i]); p_res++; p_llrRes++; } } } // ===================================================================== // Process group with 24 CNs if (lut_numBnInBnGroups[23] > 0) { // If elements in group move to next address idxBnGroup++; // Number of groups of 32 BNs for parallel processing M = (lut_numBnInBnGroups[23]*Z + 31)>>5; // Set the offset to each CN within a group in terms of 32 Byte cnOffsetInGroup = (lut_numBnInBnGroups[23]*NR_LDPC_ZMAX)>>5; // Set pointers to start of group 24 p_bnProcBuf = (__m256i*) &bnProcBuf [lut_startAddrBnGroups[idxBnGroup]]; p_bnProcBufRes = (__m256i*) &bnProcBufRes[lut_startAddrBnGroups[idxBnGroup]]; // Loop over CNs for (k=0; k<24; k++) { p_res = &p_bnProcBufRes[k*cnOffsetInGroup]; p_llrRes = (__m256i*) &llrRes [lut_startAddrBnGroupsLlr[idxBnGroup]]; // Loop over BNs for (i=0; i<M; i++) { *p_res = _mm256_subs_epi8(*p_llrRes, p_bnProcBuf[k*cnOffsetInGroup + i]); p_res++; p_llrRes++; } } } // ===================================================================== // Process group with 25 CNs if (lut_numBnInBnGroups[24] > 0) { // If elements in group move to next address idxBnGroup++; // Number of groups of 32 BNs for parallel processing M = (lut_numBnInBnGroups[24]*Z + 31)>>5; // Set the offset to each CN within a group in terms of 32 Byte cnOffsetInGroup = (lut_numBnInBnGroups[24]*NR_LDPC_ZMAX)>>5; // Set pointers to start of group 25 p_bnProcBuf = (__m256i*) &bnProcBuf [lut_startAddrBnGroups[idxBnGroup]]; p_bnProcBufRes = (__m256i*) &bnProcBufRes[lut_startAddrBnGroups[idxBnGroup]]; // Loop over CNs for (k=0; k<25; k++) { p_res = &p_bnProcBufRes[k*cnOffsetInGroup]; p_llrRes = (__m256i*) &llrRes [lut_startAddrBnGroupsLlr[idxBnGroup]]; // Loop over BNs for (i=0; i<M; i++) { *p_res = _mm256_subs_epi8(*p_llrRes, p_bnProcBuf[k*cnOffsetInGroup + i]); p_res++; p_llrRes++; } } } // ===================================================================== // Process group with 26 CNs if (lut_numBnInBnGroups[25] > 0) { // If elements in group move to next address idxBnGroup++; // Number of groups of 32 BNs for parallel processing M = (lut_numBnInBnGroups[25]*Z + 31)>>5; // Set the offset to each CN within a group in terms of 32 Byte cnOffsetInGroup = (lut_numBnInBnGroups[25]*NR_LDPC_ZMAX)>>5; // Set pointers to start of group 26 p_bnProcBuf = (__m256i*) &bnProcBuf [lut_startAddrBnGroups[idxBnGroup]]; p_bnProcBufRes = (__m256i*) &bnProcBufRes[lut_startAddrBnGroups[idxBnGroup]]; // Loop over CNs for (k=0; k<26; k++) { p_res = &p_bnProcBufRes[k*cnOffsetInGroup]; p_llrRes = (__m256i*) &llrRes [lut_startAddrBnGroupsLlr[idxBnGroup]]; // Loop over BNs for (i=0; i<M; i++) { *p_res = _mm256_subs_epi8(*p_llrRes, p_bnProcBuf[k*cnOffsetInGroup + i]); p_res++; p_llrRes++; } } } // ===================================================================== // Process group with 27 CNs if (lut_numBnInBnGroups[26] > 0) { // If elements in group move to next address idxBnGroup++; // Number of groups of 32 BNs for parallel processing M = (lut_numBnInBnGroups[26]*Z + 31)>>5; // Set the offset to each CN within a group in terms of 32 Byte cnOffsetInGroup = (lut_numBnInBnGroups[26]*NR_LDPC_ZMAX)>>5; // Set pointers to start of group 27 p_bnProcBuf = (__m256i*) &bnProcBuf [lut_startAddrBnGroups[idxBnGroup]]; p_bnProcBufRes = (__m256i*) &bnProcBufRes[lut_startAddrBnGroups[idxBnGroup]]; // Loop over CNs for (k=0; k<27; k++) { p_res = &p_bnProcBufRes[k*cnOffsetInGroup]; p_llrRes = (__m256i*) &llrRes [lut_startAddrBnGroupsLlr[idxBnGroup]]; // Loop over BNs for (i=0; i<M; i++) { *p_res = _mm256_subs_epi8(*p_llrRes, p_bnProcBuf[k*cnOffsetInGroup + i]); p_res++; p_llrRes++; } } } // ===================================================================== // Process group with 28 CNs if (lut_numBnInBnGroups[27] > 0) { // If elements in group move to next address idxBnGroup++; // Number of groups of 32 BNs for parallel processing M = (lut_numBnInBnGroups[27]*Z + 31)>>5; // Set the offset to each CN within a group in terms of 32 Byte cnOffsetInGroup = (lut_numBnInBnGroups[27]*NR_LDPC_ZMAX)>>5; // Set pointers to start of group 28 p_bnProcBuf = (__m256i*) &bnProcBuf [lut_startAddrBnGroups[idxBnGroup]]; p_bnProcBufRes = (__m256i*) &bnProcBufRes[lut_startAddrBnGroups[idxBnGroup]]; // Loop over CNs for (k=0; k<28; k++) { p_res = &p_bnProcBufRes[k*cnOffsetInGroup]; p_llrRes = (__m256i*) &llrRes [lut_startAddrBnGroupsLlr[idxBnGroup]]; // Loop over BNs for (i=0; i<M; i++) { *p_res = _mm256_subs_epi8(*p_llrRes, p_bnProcBuf[k*cnOffsetInGroup + i]); p_res++; p_llrRes++; } } } // ===================================================================== // Process group with 29 CNs if (lut_numBnInBnGroups[28] > 0) { // If elements in group move to next address idxBnGroup++; // Number of groups of 32 BNs for parallel processing M = (lut_numBnInBnGroups[28]*Z + 31)>>5; // Set the offset to each CN within a group in terms of 32 Byte cnOffsetInGroup = (lut_numBnInBnGroups[28]*NR_LDPC_ZMAX)>>5; // Set pointers to start of group 29 p_bnProcBuf = (__m256i*) &bnProcBuf [lut_startAddrBnGroups[idxBnGroup]]; p_bnProcBufRes = (__m256i*) &bnProcBufRes[lut_startAddrBnGroups[idxBnGroup]]; // Loop over CNs for (k=0; k<29; k++) { p_res = &p_bnProcBufRes[k*cnOffsetInGroup]; p_llrRes = (__m256i*) &llrRes [lut_startAddrBnGroupsLlr[idxBnGroup]]; // Loop over BNs for (i=0; i<M; i++) { *p_res = _mm256_subs_epi8(*p_llrRes, p_bnProcBuf[k*cnOffsetInGroup + i]); p_res++; p_llrRes++; } } } // ===================================================================== // Process group with 30 CNs if (lut_numBnInBnGroups[29] > 0) { // If elements in group move to next address idxBnGroup++; // Number of groups of 32 BNs for parallel processing M = (lut_numBnInBnGroups[29]*Z + 31)>>5; // Set the offset to each CN within a group in terms of 32 Byte cnOffsetInGroup = (lut_numBnInBnGroups[29]*NR_LDPC_ZMAX)>>5; // Set pointers to start of group 30 p_bnProcBuf = (__m256i*) &bnProcBuf [lut_startAddrBnGroups[idxBnGroup]]; p_bnProcBufRes = (__m256i*) &bnProcBufRes[lut_startAddrBnGroups[idxBnGroup]]; // Loop over CNs for (k=0; k<30; k++) { p_res = &p_bnProcBufRes[k*cnOffsetInGroup]; p_llrRes = (__m256i*) &llrRes [lut_startAddrBnGroupsLlr[idxBnGroup]]; // Loop over BNs for (i=0; i<M; i++) { *p_res = _mm256_subs_epi8(*p_llrRes, p_bnProcBuf[k*cnOffsetInGroup + i]); p_res++; p_llrRes++; } } } } static inline void nrLDPC_llr2bit(int8_t* out, int8_t* llrOut, uint16_t numLLR) { __m256i* p_llrOut = (__m256i*) llrOut; __m256i* p_out = (__m256i*) out; int8_t* p_llrOut8; int8_t* p_out8; uint32_t i; uint32_t M = numLLR>>5; uint32_t Mr = numLLR&31; const __m256i* p_zeros = (__m256i*) zeros256_epi8; const __m256i* p_ones = (__m256i*) ones256_epi8; for (i=0; i<M; i++) { *p_out++ = _mm256_and_si256(*p_ones, _mm256_cmpgt_epi8(*p_zeros, *p_llrOut)); p_llrOut++; } if (Mr > 0) { // Remaining LLRs that do not fit in multiples of 32 bytes p_llrOut8 = (int8_t*) p_llrOut; p_out8 = (int8_t*) p_out; for (i=0; i<Mr; i++) { if (p_llrOut8[i] < 0) { p_out8[i] = 1; } else { p_out8[i] = 0; } } } } static inline void nrLDPC_llr2bitPacked(int8_t* out, int8_t* llrOut, uint16_t numLLR) { __m256i* p_llrOut = (__m256i*) llrOut; uint32_t* p_bits = (uint32_t*) out; int8_t* p_llrOut8; uint32_t bitsTmp = 0; uint32_t i; uint32_t M = numLLR>>5; uint32_t Mr = numLLR&31; const __m256i* p_zeros = (__m256i*) zeros256_epi8; for (i=0; i<M; i++) { *p_bits++ = _mm256_movemask_epi8(_mm256_cmpgt_epi8(*p_zeros, *p_llrOut)); p_llrOut++; } if (Mr > 0) { // Remaining LLRs that do not fit in multiples of 32 bytes p_llrOut8 = (int8_t*) p_llrOut; for (i=0; i<Mr; i++) { if (p_llrOut8[i] < 0) { bitsTmp |= (1<<i); } else { bitsTmp &= (0<<i); } } } *p_bits = bitsTmp; } /* static inline void nrLDPC_bnProcPc_test(t_nrLDPC_lut* p_lut, int8_t* llrIn, int8_t* llrOut, uint16_t numLLR, uint16_t Z, uint8_t BG) { // Sum all edges and store in llrRes const uint32_t* lut_llr2CnProcBuf = p_lut->llr2CnProcBuf; const uint8_t* lut_numEdgesPerBn = p_lut->numEdgesPerBn; uint32_t idxLut = 0; uint32_t idxCnProcBuf = 0; uint8_t numEdges; uint32_t i; uint32_t j; uint32_t k; uint8_t startColParity = NR_LDPC_START_COL_PARITY_BG1; uint32_t colG1; uint16_t bnSum[16] __attribute__ ((aligned(32))) = {0}; uint16_t llrTmp[16] __attribute__ ((aligned(32))) = {0}; __m256i* p_bnSum256 = (__m256i*) &bnSum[0]; __m256i* p_llrOut256 = (__m256i*) &llrTmp[0]; if (BG == 2) { startColParity = NR_LDPC_START_COL_PARITY_BG2; } colG1 = startColParity*Z; // BNs connected to more than 1 CN for (k=0; k<startColParity; k++) { numEdges = lut_numEdgesPerBn[k]; for (i=0; i<Z; i++) { bnSum[0] = 0; // Sum all edges for (j=0; j<numEdges; j++) { idxCnProcBuf = lut_llr2CnProcBuf[idxLut++]; bnSum[0] += cnProcBufRes[idxCnProcBuf]; } // Add LLR from receiver input bnSum[0] += llrIn[k*Z + i]; // Signed saturation *p_llrOut256 = _mm256_packs_epi16(*p_bnSum256, *p_llrOut256); llrOut[k*Z + i] = llrTmp[0]; } } // BNs connected to 1 CN for (i=colG1; i<numLLR; i++) { idxCnProcBuf = lut_llr2CnProcBuf[idxLut++]; bnSum[0] = cnProcBufRes[idxCnProcBuf]; cnProcBuf[idxCnProcBuf] = llrIn[i]; // Add LLR from receiver input bnSum[0] += llrIn[i]; // Signed saturation *p_llrOut256 = _mm256_packs_epi16(*p_bnSum256, *p_llrOut256); llrOut[i] = llrTmp[0]; } } */ /* static inline void nrLDPC_bnProc_test(t_nrLDPC_lut* p_lut, int8_t* llrOut, uint16_t numLLR, uint16_t Z, uint8_t BG) { // Sum all edges and store in llrRes const uint32_t* lut_llr2CnProcBuf = p_lut->llr2CnProcBuf; const uint8_t* lut_numEdgesPerBn = p_lut->numEdgesPerBn; uint32_t idxLut = 0; uint32_t idxCnProcBuf = 0; uint8_t numEdges; uint32_t i; uint32_t j; uint32_t k; uint8_t startColParity = NR_LDPC_START_COL_PARITY_BG1; uint32_t colG1; if (BG == 2) { startColParity = NR_LDPC_START_COL_PARITY_BG2; } colG1 = startColParity*Z; // BNs connected to more than 1 CN for (k=0; k<startColParity; k++) { numEdges = lut_numEdgesPerBn[k]; for (i=0; i<Z; i++) { for (j=0; j<numEdges; j++) { idxCnProcBuf = lut_llr2CnProcBuf[idxLut++]; cnProcBuf[idxCnProcBuf] = llrOut[k*Z + i] - cnProcBufRes[idxCnProcBuf]; } } } } */ #endif