Commit b61e8007 authored by Florian Kaltenberger's avatar Florian Kaltenberger

adding LDPC encoder and decoder (from mwc18 branch)

parent 4b0a1c06

Too many changes to show.

To preserve performance only 242 of 242+ files are displayed.

......@@ -1064,12 +1064,18 @@ set(PHY_TURBOSRC
${OPENAIR1_DIR}/PHY/CODING/3gpplte_turbo_decoder_sse_16bit.c
${OPENAIR1_DIR}/PHY/CODING/3gpplte_turbo_decoder_avx2_16bit.c
${OPENAIR1_DIR}/PHY/CODING/3gpplte_turbo_decoder.c
)
set(PHY_LDPCSRC
${OPENAIR1_DIR}/PHY/CODING/nrLDPC_decoder/nrLDPC_decoder.c
${OPENAIR1_DIR}/PHY/CODING/nrLDPC_encoder/ldpc_encoder.c
${OPENAIR1_DIR}/PHY/CODING/nrLDPC_encoder/ldpc_encoder2.c
${OPENAIR1_DIR}/PHY/CODING/nrLDPC_encoder/ldpc_generate_coefficient.c
)
set(PHY_TURBOIF
${OPENAIR1_DIR}/PHY/CODING/coding_load.c
)
add_library(coding MODULE ${PHY_TURBOSRC} )
add_library(coding MODULE ${PHY_TURBOSRC} ${PHY_LDPCSRC})
set(PHY_SRC
# depend on code generation from asn1c
${RRC_FULL_DIR}/asn1_constants.h
......
/*
* 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
*/
#include <stdlib.h>
#include <math.h>
#include <stdio.h>
#include <string.h>
#include "SIMULATION/TOOLS/defs.h"
// 4-bit quantizer
char quantize4bit(double D,double x)
{
double qxd;
qxd = floor(x/D);
// printf("x=%f,qxd=%f\n",x,qxd);
if (qxd <= -8)
qxd = -8;
else if (qxd > 7)
qxd = 7;
return((char)qxd);
}
char quantize(double D,double x,unsigned char B)
{
double qxd;
char maxlev;
qxd = floor(x/D);
// printf("x=%f,qxd=%f\n",x,qxd);
maxlev = 1<<(B-1);
if (qxd <= -maxlev)
qxd = -maxlev;
else if (qxd >= maxlev)
qxd = maxlev-1;
return((char)qxd);
}
#define MAX_BLOCK_LENGTH 8448
int test_ldpc(short No_iteration,
int nom_rate,
int denom_rate,
double SNR,
unsigned char qbits,
short block_length,
unsigned int ntrials,
unsigned int *errors,
unsigned int *crc_misses)
{
//clock initiate
time_stats_t time,time_optim,tinput,tprep,tparity,toutput;
opp_enabled=1;
cpu_freq_GHz = get_cpu_freq_GHz();
//short test_input[block_length];
unsigned char *test_input[MAX_NUM_DLSCH_SEGMENTS]={NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL};;
//short *c; //padded codeword
unsigned char *estimated_output;
unsigned char *channel_input[MAX_NUM_DLSCH_SEGMENTS];
unsigned char *channel_input_optim[MAX_NUM_DLSCH_SEGMENTS];
double *channel_output;
double *modulated_input;
char *channel_output_fixed;
unsigned int i,j,trial=0;
short BG,Zc,Kb,nrows,ncols;
int no_punctured_columns,removed_bit;
int i1;
//Table of possible lifting sizes
short lift_size[51]= {2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,20,22,24,26,28,30,32,36,40,44,48,52,56,60,64,72,80,88,96,104,112,120,128,144,160,176,192,208,224,240,256,288,320,352,384};
int n_segments=8;
t_nrLDPC_dec_params decParams;
int n_iter;
*errors=0;
*crc_misses=0;
// generate input block
for(j=0;j<MAX_NUM_DLSCH_SEGMENTS;j++) {
test_input[j]=(unsigned char *)malloc16(sizeof(unsigned char) * block_length/8);
channel_input[j] = (unsigned char *)malloc16(sizeof(unsigned char) * 68*384);
channel_input_optim[j] = (unsigned char *)malloc16(sizeof(unsigned char) * 68*384);
}
modulated_input = (double *)malloc(sizeof(double) * 68*384);
channel_output = (double *)malloc(sizeof(double) * 68*384);
channel_output_fixed = (char *)malloc16(sizeof(char) * 68*384);
estimated_output = (unsigned char*) malloc16(sizeof(unsigned char) * block_length/8);
reset_meas(&time);
reset_meas(&time_optim);
reset_meas(&tinput);
reset_meas(&tprep);
reset_meas(&tparity);
reset_meas(&toutput);
for (j=0;j<MAX_NUM_DLSCH_SEGMENTS;j++) {
for (i=0; i<block_length/8; i++) {
test_input[j][i]=(unsigned char) rand();
//test_input[j][i]=j%256;
}
}
//determine number of bits in codeword
//if (block_length>3840)
{
BG=1;
Kb = 22;
nrows=46; //parity check bits
ncols=22; //info bits
}
/*else if (block_length<=3840)
{
BG=2;
nrows=42; //parity check bits
ncols=10; // info bits
if (block_length>640)
Kb = 10;
else if (block_length>560)
Kb = 9;
else if (block_length>192)
Kb = 8;
else
Kb = 6;
}*/
//find minimum value in all sets of lifting size
Zc=0;
for (i1=0; i1 < 51; i1++)
{
if (lift_size[i1] >= (double) block_length/Kb)
{
Zc = lift_size[i1];
//printf("%d\n",Zc);
break;
}
}
printf("ldpc_test: block_length %d, BG %d, Zc %d, Kb %d\n",block_length,BG, Zc, Kb);
no_punctured_columns=(int)((nrows-2)*Zc+block_length-block_length*(1/((float)nom_rate/(float)denom_rate)))/Zc;
// printf("puncture:%d\n",no_punctured_columns);
removed_bit=(nrows-no_punctured_columns-2) * Zc+block_length-(int)(block_length/((float)nom_rate/(float)denom_rate));
if (ntrials==0)
ldpc_encoder_orig(test_input[0],channel_input[0], block_length, nom_rate, denom_rate, 1);
for (trial=0; trial < ntrials; trial++)
{
//// encoder
start_meas(&time);
for(j=0;j<n_segments;j++) {
ldpc_encoder_orig(test_input[j], channel_input[j],block_length,nom_rate,denom_rate,0);
}
stop_meas(&time);
start_meas(&time_optim);
ldpc_encoder_optim_8seg(test_input,channel_input_optim,block_length,nom_rate,denom_rate,n_segments,&tinput,&tprep,&tparity,&toutput);
/*for(j=0;j<n_segments;j++) {
ldpc_encoder_optim(test_input[j],channel_input_optim[j],block_length,nom_rate,denom_rate,&tinput,&tprep,&tparity,&toutput);
}*/
stop_meas(&time_optim);
if (ntrials==1)
for (j=0;j<n_segments;j++)
for (i = 0; i < block_length+(nrows-no_punctured_columns) * Zc - removed_bit; i++)
if (channel_input[j][i]!=channel_input_optim[j][i]) {
printf("differ in seg %d pos %d (%d,%d)\n",j,i,channel_input[j][i],channel_input_optim[j][i]);
return (-1);
}
//print_meas_now(&time, "", stdout);
// for (i=0;i<6400;i++)
//printf("channel_input[%d]=%d\n",i,channel_input[i]);
//printf("%d ",channel_input[i]);
//if ((BG==2) && (Zc==128||Zc==256))
if (0)
{
for (i = 2*Zc; i < (Kb+nrows-no_punctured_columns) * Zc-removed_bit; i++)
{
#ifdef DEBUG_CODER
if ((i&0xf)==0)
printf("\ne %d..%d: ",i,i+15);
#endif
if (channel_input[0][i-2*Zc]==0)
modulated_input[i]=1/sqrt(2); //QPSK
else
modulated_input[i]=-1/sqrt(2);
channel_output[i] = modulated_input[i] + gaussdouble(0.0,1.0) * 1/sqrt(2*SNR);
channel_output_fixed[i] = (char) ((channel_output[i]*128)<0?(channel_output[i]*128-0.5):(channel_output[i]*128+0.5)); //fixed point 9-7
//printf("llr[%d]=%d\n",i,channel_output_fixed[i]);
}
//for (i=(Kb+nrows) * Zc-5;i<(Kb+nrows) * Zc;i++)
//{
// printf("channel_input[%d]=%d\n",i,channel_input[i]);
//printf("%lf %d\n",channel_output[i], channel_output_fixed[i]);
//printf("v[%d]=%lf\n",i,modulated_input[i]);}
#ifdef DEBUG_CODER
printf("\n");
exit(-1);
#endif
decParams.BG=BG;
decParams.Z=Zc;
decParams.R=13;
decParams.numMaxIter=6;
decParams.outMode = nrLDPC_outMode_BIT;
// decode the sequence
// decoder supports BG2, Z=128 & 256
//esimated_output=ldpc_decoder(channel_output_fixed, block_length, No_iteration, (double)((float)nom_rate/(float)denom_rate));
nrLDPC_decoder(&decParams, channel_output_fixed, estimated_output, NULL);
//for (i=(Kb+nrows) * Zc-5;i<(Kb+nrows) * Zc;i++)
// printf("esimated_output[%d]=%d\n",i,esimated_output[i]);
//count errors
for (i=0; i<block_length>>3; i++)
{
if (estimated_output[i] != test_input[0][i])
{
//printf("error pos %d (%d, %d)\n",i,estimated_output[i],test_input[i]);
*errors = (*errors) + 1;
break;
}
}
}
/*else if (trial==0)
printf("decoder is not supported\n");*/
}
for(j=0;j<MAX_NUM_DLSCH_SEGMENTS;j++) {
free(test_input[j]);
free(channel_input[j]);
free(channel_input_optim[j]);
}
free(modulated_input);
free(channel_output);
free(channel_output_fixed);
free(estimated_output);
print_meas(&time,"ldpc_encoder",NULL,NULL);
print_meas(&time_optim,"ldpc_encoder_optim",NULL,NULL);
print_meas(&tinput,"ldpc_encoder_optim(input)",NULL,NULL);
print_meas(&tprep,"ldpc_encoder_optim(prep)",NULL,NULL);
print_meas(&tparity,"ldpc_encoder_optim(parity)",NULL,NULL);
print_meas(&toutput,"ldpc_encoder_optim(output)",NULL,NULL);
return *errors;
}
int main(int argc, char *argv[])
{
unsigned int errors,crc_misses;
short block_length=576; // decoder supports length: 1201 -> 1280, 2401 -> 2560
short No_iteration=25;
//double rate=0.333;
int nom_rate=1;
int denom_rate=3;
double SNR0=-2.0,SNR,SNR_lin;
unsigned char qbits=4;
unsigned int decoded_errors[100]; // initiate the size of matrix equivalent to size of SNR
int c,i=0;
int n_trials = 1;
randominit(0);
while ((c = getopt (argc, argv, "q:r:s:l:n:d:")) != -1)
switch (c)
{
case 'q':
qbits = atoi(optarg);
break;
case 'r':
nom_rate = atoi(optarg);
break;
case 'd':
denom_rate = atoi(optarg);
break;
case 'l':
block_length = atoi(optarg);
break;
case 'n':
n_trials = atoi(optarg);
break;
case 's':
SNR0 = atoi(optarg);
break;
default:
abort ();
}
printf("the decoder supports BG2, Kb=10, Z=128 & 256\n");
printf(" range of blocklength: 1201 -> 1280, 2401 -> 2560\n");
printf("block length %d: \n", block_length);
printf("rate: %d/%d\n",nom_rate,denom_rate);
//for (block_length=8;block_length<=MAX_BLOCK_LENGTH;block_length+=8)
for (SNR=SNR0;SNR<SNR0+1.0;SNR+=1.0)
{
SNR_lin = pow(10,SNR/10);
decoded_errors[i]=test_ldpc(No_iteration,
nom_rate,
denom_rate,
SNR_lin, // noise standard deviation
qbits,
block_length, // block length bytes
n_trials,
&errors,
&crc_misses);
printf("SNR %f, BLER %f (%d/%d)\n",SNR,(float)decoded_errors[i]/(float)n_trials,decoded_errors[i],n_trials);
i=i+1;
}
return(0);
}
%
% Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
% contributor license agreements. See the NOTICE file distributed with
% this work for additional information regarding copyright ownership.
% The OpenAirInterface Software Alliance licenses this file to You under
% the OAI Public License, Version 1.1 (the "License"); you may not use this file
% except in compliance with the License.
% You may obtain a copy of the License at
%
% http://www.openairinterface.org/?page_id=698
%
% Unless required by applicable law or agreed to in writing, software
% distributed under the License is distributed on an "AS IS" BASIS,
% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
% See the License for the specific language governing permissions and
% limitations under the License.
%-------------------------------------------------------------------------------
% For more information about the OpenAirInterface (OAI) Software Alliance:
% contact@openairinterface.org
%
\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}
}
\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