diff --git a/openair1/PHY/CODING/nrLDPC_decoder/doc/nrLDPC/logo.png b/openair1/PHY/CODING/nrLDPC_decoder/doc/nrLDPC/logo.png new file mode 100644 index 0000000000..7b785ca051 Binary files /dev/null and b/openair1/PHY/CODING/nrLDPC_decoder/doc/nrLDPC/logo.png differ diff --git a/openair1/PHY/CODING/nrLDPC_decoder/doc/nrLDPC/nrLDPC.tex b/openair1/PHY/CODING/nrLDPC_decoder/doc/nrLDPC/nrLDPC.tex new file mode 100644 index 0000000000..019b51aa96 --- /dev/null +++ b/openair1/PHY/CODING/nrLDPC_decoder/doc/nrLDPC/nrLDPC.tex @@ -0,0 +1,960 @@ +% +% 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 +% + +\documentclass{article} + +\usepackage[a4paper, total={6in, 8in}]{geometry} + +\usepackage{amsmath} +\usepackage{amsfonts} +\usepackage{amssymb} +\usepackage{booktabs} +\usepackage{url} +\usepackage{tcolorbox} + +\usepackage{tikz} +\usetikzlibrary{arrows,decorations,shapes,backgrounds,patterns} +\usepackage{pgfplots} +\pgfplotsset{compat=newest} +\definecolor{green}{RGB}{32,127,43} +\usetikzlibrary{calc} + +\usepackage{listings} +\lstdefinestyle{customc}{ + belowcaptionskip=1\baselineskip, + breaklines=true, + frame=L, + xleftmargin=\parindent, + language=C, + showstringspaces=false, + basicstyle=\footnotesize\ttfamily, + keywordstyle=\bfseries\color{green!40!black}, + commentstyle=\itshape\color{purple!40!black}, + identifierstyle=\color{blue}, + stringstyle=\color{orange}, +} +\lstset{escapechar=@,style=customc} + +\title{NR LDPC Decoder} +\author{Sebastian Wagner (TCL)} +\date{\today} + +\def\0{\mathbf{0}} +\def\b{\mathbf{b}} +\def\Bbb{\mathbb{B}} +\def\Bcal{\mathcal{B}} +\def\c{\mathbf{c}} +\def\C{\mathbf{C}} +\def\Cbb{\mathbb{C}} +\def\Ccal{\mathcal{C}} +\def\eqdef{\triangleq} +\def\g{\mathbf{g}} +\def\G{\mathbf{G}} +\def\Gcal{\mathcal{G}} +\def\h{\mathbf{h}} +\def\H{\mathbf{H}} +\def\Hbg{\mathbf{H}_\mathrm{BG}} +\def\Hbgo{\mathbf{H}_\mathrm{BG1}} +\def\Hbgt{\mathbf{H}_\mathrm{BG2}} +\def\I{\mathbf{I}} +\def\Kb{{K_b}} +\def\m{\mathbf{m}} +\def\Mb{{M_b}} +\def\Nb{{N_b}} +\def\Nbb{\mathbb{N}} +\def\n{\mathbf{n}} +\def\nr{{n_{\rm r}}} +\def\nt{{n_{\rm t}}} +\def\s{\mathbf{s}} +\def\SNR{\mathsf{SNR}} +\def\y{\mathbf{y}} +\def\z{\mathbf{z}} +\def\Z{\mathbf{Z}} +\def\Zc{{Z_c}} + + +\def\herm{\mathsf{H}} +\def\trans{\mathsf{T}} +\def\EE{\mathsf{E}} +\newcommand{\sgn}{\operatorname{sgn}} + +\begin{document} + +\maketitle + +\begin{tikzpicture}[remember picture,overlay] + \node[anchor=north west,inner sep=0pt] at (current page.north west) + {\includegraphics[scale=0.5]{logo.png}}; +\end{tikzpicture} + + +\begin{center}Currently Supported:\end{center} +\tcbox[center]{ + \begin{tabular}{lll} + \toprule + \textbf{BG} & \textbf{Lifting Size Z} & \textbf{Code Rate R} \\ + \midrule + 1 & all & 1/3, 2/3, 8/9 \\ + 2 & all & 1/5, 1/3, 2/3 \\ + \bottomrule + \end{tabular} +} + +\paragraph{Version 1.0:} +\begin{itemize} +\item Initial version +\end{itemize} + +\paragraph{Version 2.0:} +\begin{itemize} +\item Enhancements in message passing: + \begin{itemize} + \item LUTs replaced by smaller BG-specific parameters + \item Inefficient load/store replaced by circular memcpy + \end{itemize} +\item Bug fixes: + \begin{itemize} + \item Fixed bug in function \texttt{llr2CnProcBuf} + \item Corrected input LLR dynamic range in BLER simulations + \end{itemize} +\item Results: + \begin{itemize} + \item Size of LUTs reduced significantly (60MB to 200KB) + \item Siginifcantly enhances execution time (factor 3.5) + \item Improved BLER performance (all simulation results have been updated) + \end{itemize} +\end{itemize} + + +\newpage +\tableofcontents + +\newpage +\section{Introduction} +\label{sec:introduction} + +Low Density Parity Check (LDPC) codes have been developed by Gallager in 1963 \cite{gallager1962low}. They are linear error correcting codes that are capacity-achieving for large block length and are completely described by their Parity Check Matrix (PCM) $\H^{M\times N}$. The PCM $\H$ defines $M$ constraints on the codeword $\c$ of length $N$ such that +\begin{equation} + \label{eq:29} + \H\c = \0. +\end{equation} +The number of information bits $B$ that can be encoded with $\H$ is given by $B=N-M$. Hence the code rate $R$ of $\H$ reads +\begin{equation} + \label{eq:37} + R = \frac{B}{N} = 1-\frac{M}{N}. +\end{equation} + + +\subsection{LDPC in NR} +\label{sec:ldpc-nr} + +NR uses quasi-cyclic (QC) Protograph LDPC codes, i.e. a smaller graph, called Base Graph (BG), is defined and utilized to construct the larger PCM. This has the advantage that the large PCM does not have to be stored in memory and allows for a more efficient implementation while maintaining good decoding properties. +Two BGs $\Hbg\in\Nbb^{\Mb\times \Nb}$ are defined in NR: +\begin{enumerate} +\item $\Hbgo\in\Nbb^{46\times 68}$ +\item $\Hbgt\in\Nbb^{42\times 52}$ +\end{enumerate} +where $\Nbb$ is the set of integers. For instance the first 3 rows and 13 columns of BG2 are given by + +\setcounter{MaxMatrixCols}{30} +\begin{equation*} + \label{eq:33} + \Hbgt = + \begin{bmatrix} + 9 & 117 & 204 & 26 & \emptyset & \emptyset & 189 & \emptyset & \emptyset & 205 & 0 & 0 & \emptyset & \emptyset \\ + 127 & \emptyset & \emptyset & 166 & 253 & 125 & 226 & 156 & 224 & 252 & \emptyset & 0 & 0 & \emptyset \\ + 81 & 114 & \emptyset & 44 & 52 & \emptyset & \emptyset & \emptyset & 240 & \emptyset & 1 & \emptyset & 0 & 0 + \end{bmatrix}. +\end{equation*} + +To obtain the PCM $\H$ from the BG $\Hbg$, each element $\Hbg(i,j)$ in the BG is replaced by a lifting matrix of size $\Zc\times \Zc$ according to +\begin{equation} + \label{eq:35} + \Hbg(i,j) = + \begin{cases} + \0 & \textrm{if}~ \Hbg(i,j)=\emptyset \\ + \I_{P_{ij}} & \textrm{otherwise} + \end{cases} +\end{equation} +where $\I_{P_{ij}}$ is the identity matrix circularly shifted to the right by $P_{ij} = \Hbg(i,j)\mod \Zc$. Hence, the resulting PCM $\H$ will be of size $\Mb\Zc\times\Nb\Zc$. + +The lifting size $\Zc$ depends on the number of bits to encode. To limit the complexity, a discrete set $\mathcal{Z}$ of possible values of $\Zc$ has been defined in \cite{3gpp2017_38212} and the optimal value $\Zc$ is calculated according to +\begin{equation} + \label{eq:36} + \Zc = \min_{\Z\in\mathcal{Z}}\left[Z\geq\frac{B}{\Nb}\right]. +\end{equation} + +The base rate of the two BGs is $1/3$ and $1/5$ for BG1 and BG2, respectively. That is, BG1 encodes $K=22\Zc$ bits and BG2 encodes $K=10\Zc$ bits. Note that the first 2 columns of BG 1 and 2 are always punctured, that is after encoding, the first $2\Zc$ bits are discarded and not transmitted. +For instance, consider $B=500$ information bits to encode using BG2, \eqref{eq:36} yields $\Zc=64$ hence $K=640$. Since $K>B$, $K-B=140$ filler bits are appended to the information bits. The PCM $\Hbgt$ is of size $2688\times 3328$ and the $640$ bits $\b$ are encoded according to \eqref{eq:29} at a rate $R \approx 0.192$. To achieve the higher base rate of $0.2$, the first $128$ are punctured, i.e. instead of transmitting all $3328$ bits, only $3200$ are transmitted resulting in the desired rate $R=640/3200=0.2$. + +\subsection{LDPC Decoding} +\label{sec:ldpc-decoding} + +The decoding of codeword $\c$ can be achieved via the classical message passing algorithm. This algorithm can be illustrated best using the Tanner graph of the PCM. The rows of the PCM are called check nodes (CN) since they represent the parity check equations. The parity check equation of each of these check nodes involves various bits in the codeword. Similarly, every column of the PCM corresponds to a bit and each bit is involved in several parity check equations. In the Tanner graph representation, the bits are called bit nodes (BN). Let's go back to the previous example of BG2 and assume $\Zc=2$, hence the first 3 rows and 13 columns of BG2 $\Hbgt$ read +\begin{equation*} + \label{eq:36} + \Hbgt = + \begin{bmatrix} + 1 & 1 & 0 & 0 & \emptyset & \emptyset & 1 & \emptyset & \emptyset & 1 & 0 & 0 & \emptyset & \emptyset \\ + 1 & \emptyset & \emptyset & 0 & 1 & 1 & 0 & 0 & 0 & 0 & \emptyset & 0 & 0 & \emptyset \\ + 1 & 0 & \emptyset & 0 & 0 & \emptyset & \emptyset & \emptyset & 0 & \emptyset & 1 & \emptyset & 0 & 0 + \end{bmatrix}. +\end{equation*} +Replacing the elements according to \eqref{eq:35}, we obtain the first 6 rows and 26 columns of the PCM as +\begin{equation*} + \label{eq:39} + \H = + \begin{bmatrix} + 0 & 1 & 0 & 1 & 1 & 0 & 1 & 0 & 0 & 0 & 0 & 0 & 0 & 1 & 0 & 0 & 0 & 0 & 0 & 1 & 1 & 0 & 1 & 0 & 0 & 0 & 0 & 0\\ + 1 & 0 & 1 & 0 & 0 & 1 & 0 & 1 & 0 & 0 & 0 & 0 & 1 & 0 & 0 & 0 & 0 & 0 & 1 & 0 & 0 & 1 & 0 & 1 & 0 & 0 & 0 & 0\\ + 0 & 1 & 0 & 0 & 0 & 0 & 1 & 0 & 0 & 1 & 0 & 1 & 1 & 0 & 1 & 0 & 1 & 0 & 1 & 0 & 0 & 0 & 1 & 0 & 1 & 0 & 0 & 0\\ + 1 & 0 & 0 & 0 & 0 & 0 & 0 & 1 & 1 & 0 & 1 & 0 & 0 & 1 & 0 & 1 & 0 & 1 & 0 & 1 & 0 & 0 & 0 & 1 & 0 & 1 & 0 & 0\\ + 0 & 1 & 1 & 0 & 0 & 0 & 1 & 0 & 1 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 1 & 0 & 0 & 0 & 0 & 1 & 0 & 0 & 1 & 0 & 1 & 0\\ + 1 & 0 & 0 & 1 & 0 & 0 & 0 & 1 & 0 & 1 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 1 & 0 & 0 & 1 & 0 & 0 & 0 & 0 & 1 & 0 & 1 + \end{bmatrix}. +\end{equation*} + +The Tanner graph of the first 8 BNs is shown in Figure \ref{fig:tannergraph}. + +\begin{figure}[ht] + \label{fig:tannergraph} + \centering + \def\ww{0.3cm} + \def\hh{0.3cm} + \tikzstyle{cnode}=[fill=white,rectangle,draw=black,thick,inner sep=2pt, minimum height=\hh,minimum width=\ww, rounded corners=1pt,text width=\ww] + \tikzstyle{vnode}=[fill=white,circle,draw=black,thick,inner sep=2pt, minimum height=\hh,minimum width=\ww, rounded corners=1pt,text width=\ww] + \tikzstyle{connector}=[<->,>=latex',semithick] + + \begin{tikzpicture} + \tikzstyle{every node}=[node distance=1.5cm,text centered] + % Check nodes + \node[cnode, label=above:$v_0$] (v0) {}; + \node[cnode, label=above:$v_1$, right of=v0] (v1) {}; + \node[cnode, label=above:$v_2$, right of=v1] (v2) {}; + % Variable nodes + \node[vnode, label=below:$c_3$, below of=v1, node distance=1.5cm] (c3) {}; + \node[vnode, label=below:$c_2$, left of=c3, node distance=1.5cm] (c2) {}; + \node[vnode, label=below:$c_1$, left of=c2, node distance=1.5cm] (c1) {}; + \node[vnode, label=below:$c_0$, left of=c1, node distance=1.5cm] (c0) {}; + \node[vnode, label=below:$c_4$, right of=c3, node distance=1.5cm] (c4) {}; + \node[vnode, label=below:$c_5$, right of=c4, node distance=1.5cm] (c5) {}; + \node[vnode, label=below:$c_6$, right of=c5, node distance=1.5cm] (c6) {}; + + % Draw edges + \draw (c0) edge[connector] (v1); + \draw (c1) edge[connector] (v0); + \draw (c1) edge[connector] (v2); + \draw (c2) edge[connector] (v1); + \draw (c3) edge[connector] (v0); + \draw (c4) edge[connector] (v0); + \draw (c4) edge[connector] (v2); + \draw (c5) edge[connector] (v1); + \draw (c6) edge[connector] (v0); + \draw (c6) edge[connector] (v2); + + \end{tikzpicture} + + \caption{Tanner graph for first 7 bits nodes and 3 check nodes from \eqref{eq:39}.} +\end{figure} + +The message passing algorithm is an iterative algorithm where probabilities of the bits (being either 0 or 1) are exchanged between the BNs and CNs. After sufficient iterations, the probabilities will have either converged to either 0 or 1 and the parity check equations will be satisfied, at this point, the codeword has been decoded correctly. + +\newpage +\section{LDPC Decoder Implementation} +\label{sec:ldpc-implementation} + +The implementation on a general purpose processor (GPP) has to take advantage of potential instruction extension of the processor architecture. We focus on the Intel x86 instruction set architecture (ISA) and its advanced vector extension (AVX). In particular, we utilize AVX2 with its 256-bit single instruction multiple data (SIMD) format. In order to utilize AVX2 to speed up the processing at the CNs and BNs, the corresponding data has to be ordered/aligned in a specific way. The processing flow of the LDPC decoder is depicted in \ref{fig:ldpc_decoder_flow}. + +\begin{figure}[ht] + \label{fig:ldpc_decoder_flow} + \centering + \def\ww{0.3cm} + \def\hh{0.3cm} + \tikzstyle{func}=[,draw=none] + \tikzstyle{connector}=[->,>=latex',semithick] + + \begin{tikzpicture} + \tikzstyle{every node}=[node distance=2.5cm,text centered] + % Check nodes + % First iteration + \node[func] (llr2llrProcBuf) {\texttt{llr2llrProcBuf}}; + \node[func, above of=llr2llrProcBuf] (llr2CnProcBuf) {\texttt{llr2CnProcBuf}}; + \node[func, above right of=llr2CnProcBuf] (cnProc1) {\texttt{cnProc}}; + \node[func, below right of=cnProc1] (cn2bnProcBuf1) {\texttt{cn2bnProcBuf}}; + \node[func, below of=cn2bnProcBuf1] (bnProcPc1) {\texttt{bnProcPc}}; + + % Iterations + \node[func, right of=cnProc1, node distance=7cm] (cnProc) {\texttt{cnProc}}; + \node[func, below right of=cnProc] (cn2bnProcBuf) {\texttt{cn2bnProcBuf}}; + \node[func, below of=cn2bnProcBuf] (bnProcPc) {\texttt{bnProcPc}}; + \node[func, below left of=cnProc] (bn2cnProcBuf) {\texttt{bn2cnProcBuf}}; + \node[func, below of=bn2cnProcBuf] (bnProc) {\texttt{bnProc}}; + + % Post processing + \node[func, below of=bnProcPc] (llrRes2llrOut) {\texttt{llrRes2llrOut}}; + \node[func, below of=llrRes2llrOut, node distance=1cm] (llr2bit) {\texttt{llr2bit}}; + + % Draw edges + \draw (llr2llrProcBuf) edge[connector] (llr2CnProcBuf); + \draw (llr2CnProcBuf) edge[connector] (cnProc1); + \draw (cnProc1) edge[connector] (cn2bnProcBuf1); + \draw (cn2bnProcBuf1) edge[connector] (bnProcPc1); + + \draw (bnProcPc) edge[connector] (bnProc); + \draw (bnProc) edge[connector] (bn2cnProcBuf); + \draw (bn2cnProcBuf) edge[connector] node[above left] {\texttt{cnProcPc}} (cnProc); + \draw (cnProc) edge[connector] (cn2bnProcBuf); + \draw (cn2bnProcBuf) edge[connector] (bnProcPc); + + \draw (bnProcPc1) edge[connector] (bnProc); + + \draw (bnProcPc) edge[connector] node[left] {iterations done} (llrRes2llrOut); + \draw (llrRes2llrOut) edge[connector] (llr2bit); + + % Boxes + \node[inner sep=0pt,above right of=cn2bnProcBuf1, node distance = 2.5cm] (ref) {}; + + \draw[fill=black,opacity=.2, rounded corners] (llr2llrProcBuf.south west) rectangle ($(ref) + (-.5cm,.5cm)$); + \draw[fill=black,opacity=.2, rounded corners] ($(ref) + (.5cm,.5cm)$) rectangle ($(bnProcPc.south east) + (.4cm,0)$); + + \node[func, above of=cnProc1, node distance=.8cm] (iter1) {\textbf{First Iteration}}; + \node[func, above of=cnProc , node distance=.8cm] (iterX) {\textbf{Subsequent Iterations}}; + + \end{tikzpicture} + + \caption{LDPC Decoder processing flow.} +\end{figure} + +The functions involved are described in more detail in Table \ref{tab:sum_func}. + +\begin{table}[ht] + \centering + \begin{tabular}{ll} + \toprule + \textbf{Function} & \textbf{Description} \\ + \midrule + \texttt{llr2llrProcBuf} & Copies input LLRs to LLR processing buffer \\ + \texttt{llr2CnProcBuf} & Copies input LLRs to CN processing buffer \\ + \texttt{cnProc} & Performs CN signal processing \\ + \texttt{cnProcPc} & Performs parity check \\ + \texttt{cn2bnProcBuf} & Copies the CN results to the BN processing buffer \\ + \texttt{bnProcPc} & Performs BN processing for parity check and/or hard-decision \\ + \texttt{bnProc} & Utilizes the results of \texttt{bnProcPc} to compute LLRs for CN processing \\ + \texttt{bn2cnProcBuf} & Copies the BN results to the CN processing buffer \\ + \texttt{llrRes2llrOut} & Copies the results of \texttt{bnProcPc} to output LLRs \\ + \texttt{llr2bit} & Performs hard-decision on the output LLRs \\ + \bottomrule + \end{tabular} + \caption{Summary of the LDPC decoder functions.} + \label{tab:sum_func} +\end{table} + +The input LLRs are assumed to be 8-bit and aligned on 32 bytes. CN processing is carried out in 8-bit whereas BN processing is done in 16 bit. Subsequently, the processing tasks at the CNs and BNs are explained in more detail. + +\newpage +\subsection{Check Node Processing} +\label{sec:check-node-proc} + +Denote $q_{ij}$ the value from BN $j$ to CN $i$ and let $\Bcal_i$ be the set of connected BNs to the $i$th CN. Then, using the min-sum approximation, CN $i$ has to carry out the following operation for each connected BN. +\begin{equation} + \label{eq:40} + r_{ji} = \prod_{j'\in\Bcal_i\setminus j}\sgn q_{ij'}\min_{j'\in\Bcal_i\setminus j} |q_{ij'}| +\end{equation} +where $r_{ji}$ is the value returned to BN $j$ from CN $i$. There are $\Mb = \{46,42\}$ CNs in BG 1 and BG 2, respectively. Each of these CNs is connected to only a small number of BNs. The number of connected BNs to CN $i$ is $|\Bcal_i|$. In BG1 and BG2, $|\Bcal_i|=\{3,4,5,6,7,8,9,10,19\}$ and $|\Bcal_i|=\{3,4,5,6,8,10\}$, respectively. The following tables show the number of CNs $M_{|\Bcal_i|}$ that are connected to the same number of BNs. + +\begin{table}[ht] + \centering + \begin{tabular}{llllllllll} + \toprule + $|\Bcal_i|$ & 3 & 4 & 5 & 6 & 7 & 8 & 9 & 10 & 19 \\ + \midrule + $M_{|\Bcal_i|}^\mathrm{BG1}$ & 1 & 5 &18 & 8 & 5 & 2 & 2 & 1 & 4 \\ + $M_{|\Bcal_i|}^\mathrm{BG2}$ & 6 & 20 & 9 & 3 & 0 & 2 & 0 & 2 & 0 \\ + \bottomrule + \end{tabular} + \caption{Ceck node groups for BG1 and BG2.} + \label{tab:checkNodeGroups} +\end{table} + +It can be observed that each CN is at least connected to 3 BNs and there are 9 groups and 5 groups in BG1 and BG2, respectively. Denote the set of CN groups as $\Gcal$ and $M_k$ the number of CNs in group $k\in\Gcal$, e.g. for BG2 $M_4=20\Zc$. Each CN group will be processed separately. The CN processing buffer $p_C^k$ of group $k$ is defined as +\begin{equation} + \label{eq:44} + p_C^k = \{\underbrace{q_{11}q_{21}\dots q_{M_k 1}}_{\text 1. BN},\underbrace{q_{12}q_{22}\dots q_{M_k 2}}_{\text 2. BN},\dots,\underbrace{q_{12}q_{22}\dots q_{M_k k}}_{\text last BN}\} +\end{equation} +Hence, $|p_C^k| = kM_k$, e.g, $\Zc=128$, $|p_C^4| = 4\cdot 20\cdot 128 = 10240$. + +\begin{lstlisting}[frame=single,caption={Example of CN processing for group 3 from \texttt{cnProc}.},label=code_cnproc] % Start your code-block + + const uint8_t lut_idxCnProcG3[3][2] = {{72,144}, {0,144}, {0,72}}; + + // ===================================================================== + // Process group with 3 BNs + + // Number of groups of 32 CNs for parallel processing + M = (lut_numCnInCnGroups[0]*Z)>>5; + // Set the offset to each bit within a group in terms of 32 Byte + bitOffsetInGroup = (lut_numCnInCnGroups_BG2_R15[0]*NR_LDPC_ZMAX)>>5; + + // Set pointers to start of group 3 + p_cnProcBuf = (__m256i*) &cnProcBuf [lut_startAddrCnGroups[0]]; + p_cnProcBufRes = (__m256i*) &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>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