From 6e29ff08722dd1c3ff914148c6c48eeb244cc02a Mon Sep 17 00:00:00 2001 From: Florian Kaltenberger Date: Wed, 29 Aug 2018 02:57:42 -0700 Subject: [PATCH] patch from Milan Zivkovic (Nokia Bell Labs) --- cmake_targets/build_oai | 2 +- openair1/PHY/CODING/TESTBENCH/ldpctest.c | 773 +++++++++++++----- .../CODING/nrLDPC_decoder/nrLDPC_decoder.c | 3 + .../PHY/CODING/nrLDPC_encoder/ldpc_encoder.c | 2 +- .../PHY/CODING/nrLDPC_encoder/ldpc_encoder2.c | 279 ++++++- .../ldpc_generate_coefficient.c | 56 +- 6 files changed, 850 insertions(+), 265 deletions(-) diff --git a/cmake_targets/build_oai b/cmake_targets/build_oai index 0daba0b235..3d0238e8ae 100755 --- a/cmake_targets/build_oai +++ b/cmake_targets/build_oai @@ -686,7 +686,7 @@ function main() { echo_info "Compiling unitary tests simulators" # TODO: fix: dlsim_tm4 pucchsim prachsim pdcchsim pbchsim mbmssim #simlist="dlsim_tm4 dlsim ulsim pucchsim prachsim pdcchsim pbchsim mbmssim" - simlist="dlsim ulsim" + simlist="dlsim ulsim polartest ldpctest" for f in $simlist ; do compilations \ lte-simulators $f \ diff --git a/openair1/PHY/CODING/TESTBENCH/ldpctest.c b/openair1/PHY/CODING/TESTBENCH/ldpctest.c index 158be941c7..49af918bd9 100644 --- a/openair1/PHY/CODING/TESTBENCH/ldpctest.c +++ b/openair1/PHY/CODING/TESTBENCH/ldpctest.c @@ -24,6 +24,7 @@ #include #include +#include "assertions.h" #include "SIMULATION/TOOLS/sim.h" #include "PHY/CODING/nrLDPC_encoder/defs.h" #include "PHY/CODING/nrLDPC_decoder/nrLDPC_decoder.h" @@ -38,6 +39,10 @@ # endif #endif +#define NR_LDPC_PROFILER_DETAIL +#define NR_LDPC_ENABLE_PARITY_CHECK + + // 4-bit quantizer char quantize4bit(double D,double x) { @@ -53,13 +58,33 @@ char quantize4bit(double D,double x) return((char)qxd); } +char quantize8bit(double D,double x) +{ + double qxd; + //char maxlev; + qxd = floor(x/D); + + //maxlev = 1<<(B-1); + + //printf("x=%f,qxd=%f,maxlev=%d\n",x,qxd, maxlev); + + if (qxd <= -128) + qxd = -128; + else if (qxd >= 128) + qxd = 127; + + return((char)qxd); +} + char quantize(double D,double x,unsigned char B) { double qxd; - char maxlev; + short maxlev; qxd = floor(x/D); - // printf("x=%f,qxd=%f\n",x,qxd); - maxlev = 1<<(B-1); + + maxlev = 1<<(B-1);//(char)(pow(2,B-1)); + + //printf("x=%f,qxd=%f,maxlev=%d\n",x,qxd, maxlev); if (qxd <= -maxlev) qxd = -maxlev; @@ -69,45 +94,78 @@ char quantize(double D,double x,unsigned char B) return((char)qxd); } +typedef struct { +double n_iter_mean; +double n_iter_std; +int n_iter_max; +} n_iter_stats_t; + #define MAX_BLOCK_LENGTH 8448 +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 test_ldpc(short No_iteration, - //int nom_rate, - //int denom_rate, + int nom_rate, + int denom_rate, double SNR, unsigned char qbits, - unsigned short block_length, + short block_length, unsigned int ntrials, + int n_segments, unsigned int *errors, - unsigned int *crc_misses) + unsigned int *errors_bit, + double *errors_bit_uncoded, + unsigned int *crc_misses, + time_stats_t *time_optim, + time_stats_t *time_decoder, + n_iter_stats_t * dec_iter) { //clock initiate - time_stats_t time,time_optim,tinput,tprep,tparity,toutput; + //time_stats_t time,time_optim,tinput,tprep,tparity,toutput, time_decoder; + time_stats_t time, tinput,tprep,tparity,toutput; + double n_iter_mean = 0; + double n_iter_std = 0; + int n_iter_max = 0; + unsigned int segment_bler = 0; + + double sigma; + sigma = 1.0/sqrt(2*SNR); + 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 *estimated_output[MAX_NUM_DLSCH_SEGMENTS]; + unsigned char *estimated_output_bit[MAX_NUM_DLSCH_SEGMENTS]; + unsigned char *test_input_bit; unsigned char *channel_input[MAX_NUM_DLSCH_SEGMENTS]; + unsigned char *channel_output_uncoded[MAX_NUM_DLSCH_SEGMENTS]; unsigned char *channel_input_optim[MAX_NUM_DLSCH_SEGMENTS]; double *channel_output; - double *modulated_input; - char *channel_output_fixed; + double *modulated_input[MAX_NUM_DLSCH_SEGMENTS]; + char *channel_output_fixed[MAX_NUM_DLSCH_SEGMENTS]; unsigned int i,j,trial=0; - short BG,Zc,Kb; - //short nrows,ncols; - //int no_punctured_columns,removed_bit; + short BG,Zc,Kb,nrows;//,ncols; + int no_punctured_columns,removed_bit; int i1; + int R_ind = 0; //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; - int N; //length encoded block +//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=1; + int code_rate_vec[8] = {15, 13, 25, 12, 23, 34, 56, 89}; + //double code_rate_actual_vec[8] = {0.2, 0.33333, 0.4, 0.5, 0.66667, 0.73333, 0.81481, 0.88}; t_nrLDPC_dec_params decParams; - int n_iter; + + t_nrLDPC_time_stats decoder_profiler; + t_nrLDPC_time_stats* p_decoder_profiler =&decoder_profiler ; + + int32_t n_iter = 0;; *errors=0; + *errors_bit=0; + *errors_bit_uncoded=0; *crc_misses=0; // generate input block @@ -115,37 +173,450 @@ int test_ldpc(short No_iteration, 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); + channel_output_uncoded[j] = (unsigned char *)malloc16(sizeof(unsigned char) * 68*384); + estimated_output[j] = (unsigned char*) malloc16(sizeof(unsigned char) * block_length); + estimated_output_bit[j] = (unsigned char*) malloc16(sizeof(unsigned char) * block_length); + modulated_input[j] = (double *)malloc16(sizeof(double) * 68*384); + channel_output_fixed[j] = (char *)malloc16(sizeof( 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); - - memset(channel_output_fixed,0,sizeof(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); + //modulated_input = (double *)calloc(68*384, sizeof(double)); + channel_output = (double *)calloc(68*384, sizeof(double)); + //channel_output_fixed = (double *)calloc(68*384, sizeof(double)); + //channel_output_fixed = (unsigned char*)calloc(68*384, sizeof(unsigned char*)); + //estimated_output = (unsigned char*) malloc16(sizeof(unsigned char) * block_length);///8); + //estimated_output_bit = (unsigned char*) malloc16(sizeof(unsigned char) * block_length); + test_input_bit = (unsigned char*) malloc16(sizeof(unsigned char) * block_length); reset_meas(&time); - reset_meas(&time_optim); + reset_meas(time_optim); + reset_meas(time_decoder); reset_meas(&tinput); reset_meas(&tprep); reset_meas(&tparity); reset_meas(&toutput); + //Reset Decoder profiles + reset_meas(&decoder_profiler.llr2llrProcBuf); + reset_meas(&decoder_profiler.llr2CnProcBuf); + reset_meas(&decoder_profiler.cnProc); + reset_meas(&decoder_profiler.cnProcPc); + reset_meas(&decoder_profiler.bnProc); + reset_meas(&decoder_profiler.bnProcPc); + reset_meas(&decoder_profiler.cn2bnProcBuf); + reset_meas(&decoder_profiler.bn2cnProcBuf); + reset_meas(&decoder_profiler.llrRes2llrOut); + reset_meas(&decoder_profiler.llr2bit); + //reset_meas(&decoder_profiler.total); for (j=0;j3840) && (block_length <= MAX_BLOCK_LENGTH)) + 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; + } + + if (nom_rate == 1) + if (denom_rate == 5) + if (BG == 2) + R_ind = 0; + else + printf("Not supported"); + else if (denom_rate == 3) + R_ind = 1; + else if (denom_rate == 2) + //R_ind = 3; + printf("Not supported"); + else + printf("Not supported"); + + else if (nom_rate == 2) + if (denom_rate == 5) + //R_ind = 2; + printf("Not supported"); + else if (denom_rate == 3) + R_ind = 4; + else + printf("Not supported"); + + else if ((nom_rate == 22) && (denom_rate == 30)) + //R_ind = 5; + printf("Not supported"); + else if ((nom_rate == 22) && (denom_rate == 27)) + //R_ind = 6; + printf("Not supported"); + else if ((nom_rate == 22) && (denom_rate == 25)) + if (BG == 1) + R_ind = 7; + else + printf("Not supported"); + else + printf("Not supported"); + + //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: codeword_length %d, n_segments %d, block_length %d, BG %d, Zc %d, Kb %d\n",n_segments *block_length, n_segments, 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, BG, 1); + + for (trial=0; trial < ntrials; trial++) + { + segment_bler = 0; + //// encoder + start_meas(&time); + for(j=0;j>3; i++) + { + //printf("block_length>>3: %d \n",block_length>>3); + /// printf("i: %d \n",i); + ///printf("estimated_output[%d]: %d \n",i,estimated_output[i]); + ///printf("test_input[0][%d]: %d \n",i,test_input[0][i]); + if (estimated_output[j][i] != test_input[j][i]) + { + + + //////printf("error pos %d (%d, %d)\n\n",i,estimated_output[i],test_input[0][i]); + segment_bler = segment_bler + 1; + break; + } + } + + for (i=0; i>(i&7); + test_input_bit[i] = (test_input[j][i/8]&(1<<(i&7)))>>(i&7); // Further correct for multiple segments + if (estimated_output_bit[j][i] != test_input_bit[i]) + { + *errors_bit = (*errors_bit) + 1; + } + } + + //if (*errors == 1000) + //break; + + n_iter_mean = n_iter_mean + n_iter; + n_iter_std = n_iter_std + pow(n_iter-1,2); + + if ( n_iter > n_iter_max ) + n_iter_max = n_iter; + + } // end segments + + if (segment_bler != 0) + *errors = (*errors) + 1; + + } + /*else if (trial==0) + printf("decoder is not supported\n");*/ + } + + + dec_iter->n_iter_mean = n_iter_mean/(double)ntrials/(double)n_segments - 1; + dec_iter->n_iter_std = sqrt(n_iter_std/(double)ntrials/(double)n_segments - pow(n_iter_mean/(double)ntrials/(double)n_segments - 1,2)); + dec_iter->n_iter_max = n_iter_max -1; + + *errors_bit_uncoded = *errors_bit_uncoded / (double)((Kb+nrows-no_punctured_columns-2) * Zc-removed_bit); + + for(j=0;j 1280, 2401 -> 2560 + + short No_iteration=5; + int n_segments=1; + //double rate=0.333; + int nom_rate=1; + int denom_rate=3; + double SNR0=-2.0,SNR,SNR_lin; + unsigned char qbits=8; + unsigned int decoded_errors[10000]; // initiate the size of matrix equivalent to size of SNR + int c,i=0, i1 = 0; + + int n_trials = 1; + double SNR_step = 0.1; + + randominit(0); + int test_uncoded= 0; + + time_stats_t time_optim[10], time_decoder[10]; + n_iter_stats_t dec_iter[3]; + + + + short BG,Zc,Kb; + + while ((c = getopt (argc, argv, "q:r:s:S:l:n:d:i:t:u:h")) != -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 = atof(optarg); + break; + + case 'S': + n_segments = atof(optarg); + break; + + case 't': + SNR_step = atof(optarg); + break; + + case 'i': + No_iteration = atoi(optarg); + break; + + case 'u': + test_uncoded = atoi(optarg); + break; + + case 'h': + default: + printf("CURRENTLY SUPPORTED CODE RATES: \n"); + printf("BG1 (blocklength > 3840): 1/3, 2/3, 22/25 (8/9) \n"); + printf("BG2 (blocklength <= 3840): 1/5, 1/3, 2/3 \n\n"); + printf("-h This message\n"); + printf("-q Quantization bits, Default: 8\n"); + printf("-r Nominator rate, (1, 2, 22), Default: 1\n"); + printf("-d Denominator rate, (3, 5, 25), Default: 1\n"); + printf("-l Block length (l > 3840 -> BG1, rest BG2 ), Default: 8448\n"); + printf("-n Number of simulation trials, Default: 1\n"); + //printf("-M MCS2 for TB 2\n"); + printf("-s SNR per information bit (EbNo) in dB, Default: -2\n"); + printf("-S Number of segments (Maximum: 8), Default: 1\n"); + printf("-t SNR simulation step, Default: 0.1\n"); + printf("-i Max decoder iterations, Default: 5\n"); + printf("-u Set SNR per coded bit, Default: 0\n"); + exit(1); + break; + } + cpu_freq_GHz = get_cpu_freq_GHz(); + //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("n_trials %d: \n", n_trials); + printf("SNR0 %f: \n", SNR0); + + + + + //for (block_length=8;block_length<=MAX_BLOCK_LENGTH;block_length+=8) + + + //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) + else if (block_length<=3840) { BG=2; //nrows=42; //parity check bits @@ -159,14 +630,11 @@ int test_ldpc(short No_iteration, Kb = 8; else Kb = 6; - } - else { - printf("block_length %d not supported\n",block_length); - exit(-1); - } - + } + //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) @@ -177,192 +645,87 @@ int test_ldpc(short No_iteration, } } - if (BG==1) - N=66*Zc; - else if (BG==2) - N=50*Zc; + char fname[200]; + sprintf(fname,"../../../openair1/PHY/CODING/TESTBENCH/ldpctest_BG_%d_Zc_%d_rate_%d-%d_block_length_%d_maxit_%d.txt",BG,Zc,nom_rate,denom_rate,block_length, No_iteration); + FILE *fd=fopen(fname,"w"); + AssertFatal(fd!=NULL,"cannot open %s\n",fname); - printf("ldpc_test: block_length %d, BG %d, Zc %d, Kb %d, N %d\n",block_length,BG, Zc, Kb, N); - //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, BG, 1); - - for (trial=0; trial < ntrials; trial++) + fprintf(fd,"SNR BLER BER UNCODED_BER ENCODER_MEAN ENCODER_STD ENCODER_MAX DECODER_TIME_MEAN DECODER_TIME_STD DECODER_TIME_MAX DECODER_ITER_MEAN DECODER_ITER_STD DECODER_ITER_MAX\n"); + + for (SNR=SNR0;SNR1.0) - channel_output_fixed[i]=127; - else if (channel_output[i]<-1.0) - channel_output_fixed[i]=-128; - else - 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 (%f)\n",i,channel_output_fixed[i],channel_output[i]); - } - - /* - the LDPC decoder supports several rates and the input has to be adapted accordingly (by padding with zeros to the next lower supported rate). Moreover, the first 2*Z LLRs are zero (since they are punctured and not transmitted) then you have the LLRs corresponding to the systematic bits. After that come the filler bits, the encoder uses 0 for the filler bits hence for the decoder you need to put 127 (max LLR for bit 0) at their place. Then come the LLRs corresponding to the punctured bits followed by zeros to pad for the supported decoder rate. - */ - for (i=0;i<2*Zc;i++) - channel_output_fixed[i] = 0; - - 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 - //estimated_output=ldpc_decoder(channel_output_fixed, block_length, No_iteration, (double)((float)nom_rate/(float)denom_rate)); - - n_iter = nrLDPC_decoder(&decParams, (int8_t*) channel_output_fixed, (int8_t*) 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>3; i++) - { - if (estimated_output[i] != test_input[0][i]) - { - printf("error pos %d (%d, %d)\n",i,estimated_output[i],test_input[0][i]); - *errors = (*errors) + 1; - break; - } - } - - } - - for(j=0;j 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:s:l:n:h")) != -1) - switch (c) - { - case 'q': - qbits = atoi(optarg); - break; - - case 'l': - block_length = atoi(optarg); - break; - - case 'n': - n_trials = atoi(optarg); - break; - - case 's': - SNR0 = atoi(optarg); - break; - - default: - case 'h': - printf("usage ldpctest -h -l blocklength -n n_trials -s SNR\n"); - exit(0); - } - - //printf("the decoder supports BG2, Kb=10, Z=128 & 256\n"); - //printf(" range of blocklength: 1201 -> 1280, 2401 -> 2560\n"); - //printf("rate: %d/%d\n",nom_rate,denom_rate); - printf("block length %d: \n", block_length); - printf("n_trials %d: \n", n_trials); - printf("SNR0 %f: \n", SNR0); - - //for (block_length=8;block_length<=MAX_BLOCK_LENGTH;block_length+=8) - for (SNR=SNR0;SNRn_iter_mean); + printf("SNR %f, Std iterations: %f\n",SNR, dec_iter->n_iter_std); + printf("SNR %f, Max iterations: %d\n",SNR, dec_iter->n_iter_max); + printf("\n"); + printf("Encoding time mean: %15.3f us\n",(double)time_optim->diff/time_optim->trials/1000.0/cpu_freq_GHz); + printf("Encoding time std: %15.3f us\n",sqrt((double)time_optim->diff_square/time_optim->trials/pow(1000,2)/pow(cpu_freq_GHz,2)-pow((double)time_optim->diff/time_optim->trials/1000.0/cpu_freq_GHz,2))); + printf("Encoding time max: %15.3f us\n",(double)time_optim->max/1000.0/cpu_freq_GHz); + printf("\n"); + printf("Decoding time mean: %15.3f us\n",(double)time_decoder->diff/time_decoder->trials/1000.0/cpu_freq_GHz); + printf("Decoding time std: %15.3f us\n",sqrt((double)time_decoder->diff_square/time_decoder->trials/pow(1000,2)/pow(cpu_freq_GHz,2)-pow((double)time_decoder->diff/time_decoder->trials/1000.0/cpu_freq_GHz,2))); + printf("Decoding time max: %15.3f us\n",(double)time_decoder->max/1000.0/cpu_freq_GHz); + + fprintf(fd,"%f %f %f %f %f %f %f %f %f %f %f %f %d \n", + SNR, + (double)decoded_errors[i]/(double)n_trials , + (double)errors_bit/(double)n_trials/(double)block_length/(double)n_segments , + errors_bit_uncoded/(double)n_trials/(double)n_segments , + (double)time_optim->diff/time_optim->trials/1000.0/cpu_freq_GHz, + sqrt((double)time_optim->diff_square/time_optim->trials/pow(1000,2)/pow(cpu_freq_GHz,2)-pow((double)time_optim->diff/time_optim->trials/1000.0/cpu_freq_GHz,2)), + (double)time_optim->max/1000.0/cpu_freq_GHz, + (double)time_decoder->diff/time_decoder->trials/1000.0/cpu_freq_GHz, + sqrt((double)time_decoder->diff_square/time_decoder->trials/pow(1000,2)/pow(cpu_freq_GHz,2)-pow((double)time_decoder->diff/time_decoder->trials/1000.0/cpu_freq_GHz,2)), + (double)time_decoder->max/1000.0/cpu_freq_GHz, + dec_iter->n_iter_mean, + dec_iter->n_iter_std, + dec_iter->n_iter_max + ); + + if (decoded_errors[i] == 0) + break; i=i+1; + + } + fclose(fd); return(0); } + + + + + + + diff --git a/openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_decoder.c b/openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_decoder.c index 53966befff..2758ae35c0 100644 --- a/openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_decoder.c +++ b/openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_decoder.c @@ -38,6 +38,9 @@ #include "nrLDPC_cnProc.h" #include "nrLDPC_bnProc.h" +#define NR_LDPC_ENABLE_PARITY_CHECK +#define NR_LDPC_PROFILER_DETAIL + #ifdef NR_LDPC_DEBUG_MODE #include "nrLDPC_tools/nrLDPC_debug.h" #endif diff --git a/openair1/PHY/CODING/nrLDPC_encoder/ldpc_encoder.c b/openair1/PHY/CODING/nrLDPC_encoder/ldpc_encoder.c index b97b780333..a225730845 100644 --- a/openair1/PHY/CODING/nrLDPC_encoder/ldpc_encoder.c +++ b/openair1/PHY/CODING/nrLDPC_encoder/ldpc_encoder.c @@ -68,7 +68,7 @@ int encode_parity_check_part_orig(unsigned char *c,unsigned char *d, short BG,sh printf("problem with BG\n"); return(-1); } - + no_punctured_columns=(int)((nrows-2)*Zc+block_length-block_length*3)/Zc; diff --git a/openair1/PHY/CODING/nrLDPC_encoder/ldpc_encoder2.c b/openair1/PHY/CODING/nrLDPC_encoder/ldpc_encoder2.c index 037c19f88e..8ba6928966 100644 --- a/openair1/PHY/CODING/nrLDPC_encoder/ldpc_encoder2.c +++ b/openair1/PHY/CODING/nrLDPC_encoder/ldpc_encoder2.c @@ -201,7 +201,7 @@ void encode_parity_check_part_optim(uint8_t *c,uint8_t *d, short BG,short Zc,sho int ldpc_encoder_optim(unsigned char *test_input,unsigned char *channel_input,short block_length,short BG,time_stats_t *tinput,time_stats_t *tprep,time_stats_t *tparity,time_stats_t *toutput) { - short Kb,Zc,nrows,ncols; + short Zc,Kb,nrows,ncols; int i,i1; int no_punctured_columns,removed_bit; @@ -211,26 +211,31 @@ int ldpc_encoder_optim(unsigned char *test_input,unsigned char *channel_input,sh int simd_size; //determine number of bits in codeword - if (BG==1) - { - Kb = 22; - nrows=46; //parity check bits - ncols=22; //info bits - } - else if (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; - } + //determine number of bits in codeword + //if (block_length>3840) + if (BG==1) + { + //BG=1; + Kb = 22; + nrows=46; //parity check bits + ncols=22; //info bits + } + //else if (block_length<=3840) + else if (BG==2) + { + //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; @@ -316,7 +321,7 @@ int ldpc_encoder_optim(unsigned char *test_input,unsigned char *channel_input,sh int ldpc_encoder_optim_8seg(unsigned char **test_input,unsigned char **channel_input,short block_length,short BG,int n_segments,time_stats_t *tinput,time_stats_t *tprep,time_stats_t *tparity,time_stats_t *toutput) { - short Kb,Zc,nrows,ncols; + short Zc,Kb,nrows,ncols; int i,i1,j; int no_punctured_columns,removed_bit; //Table of possible lifting sizes @@ -343,14 +348,18 @@ int ldpc_encoder_optim_8seg(unsigned char **test_input,unsigned char **channel_i AssertFatal(n_segments>0&&n_segments<=8,"0 < n_segments %d <= 8\n",n_segments); //determine number of bits in codeword + //if (block_length>3840) if (BG==1) { + //BG=1; Kb = 22; nrows=46; //parity check bits ncols=22; //info bits } - else if (BG==2) + //else if (block_length<=3840) + else if (BG==2) { + //BG=2; nrows=42; //parity check bits ncols=10; // info bits @@ -362,7 +371,7 @@ int ldpc_encoder_optim_8seg(unsigned char **test_input,unsigned char **channel_i Kb = 8; else Kb = 6; - } + } //find minimum value in all sets of lifting size Zc=0; @@ -481,12 +490,12 @@ int ldpc_encoder_optim_8seg(unsigned char **test_input,unsigned char **channel_i // if (((block_length-(2*Zc))&31)>0) l1++; for (i=0;i0) l2++; for (i1=0;i1>j)&1; for (i=0;i<((nrows-no_punctured_columns) * Zc-removed_bit);i++) - for (j=0; j>j)&1; } @@ -508,3 +517,217 @@ int ldpc_encoder_optim_8seg(unsigned char **test_input,unsigned char **channel_i stop_meas(toutput); return 0; } + +int ldpc_encoder_optim_8seg_multi(unsigned char **test_input,unsigned char **channel_input,short block_length,int nom_rate,int denom_rate,int n_segments,unsigned int macro_num, time_stats_t *tinput,time_stats_t *tprep,time_stats_t *tparity,time_stats_t *toutput) +{ + + short BG,Zc,Kb,nrows,ncols; + int i,i1,j; + int no_punctured_columns,removed_bit; + //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}; + char temp; + int simd_size; + int macro_segment, macro_segment_end; + + + macro_segment = 8*macro_num; + macro_segment_end = (n_segments > 8*(macro_num+1)) ? 8*(macro_num+1) : n_segments; + ///printf("macro_segment: %d\n", macro_segment); + ///printf("macro_segment_end: %d\n", macro_segment_end ); + +#ifdef __AVX2__ + __m256i shufmask = _mm256_set_epi64x(0x0303030303030303, 0x0202020202020202,0x0101010101010101, 0x0000000000000000); + __m256i andmask = _mm256_set1_epi64x(0x8040201008040201); // every 8 bits -> 8 bytes, pattern repeats. + __m256i zero256 = _mm256_setzero_si256(); + __m256i masks[8]; + register __m256i c256; + masks[0] = _mm256_set1_epi8(0x1); + masks[1] = _mm256_set1_epi8(0x2); + masks[2] = _mm256_set1_epi8(0x4); + masks[3] = _mm256_set1_epi8(0x8); + masks[4] = _mm256_set1_epi8(0x10); + masks[5] = _mm256_set1_epi8(0x20); + masks[6] = _mm256_set1_epi8(0x40); + masks[7] = _mm256_set1_epi8(0x80); +#endif + + ///AssertFatal(n_segments>0&&n_segments<=8,"0 < n_segments %d <= 8\n",n_segments); + + //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; + } + } + +#ifdef DEBUG_LDPC + LOG_D(PHY,"ldpc_encoder_optim_8seg: BG %d, Zc %d, Kb %d, block_length %d, segments %d\n",BG,Zc,Kb,block_length,n_segments); + LOG_D(PHY,"ldpc_encoder_optim_8seg: PDU (seg 0) %x %x %x %x\n",test_input[0][0],test_input[0][1],test_input[0][2],test_input[0][3]); +#endif + + AssertFatal(Zc>0,"no valid Zc found for block length %d\n",block_length); + + if ((Zc&31) > 0) simd_size = 16; + else simd_size = 32; + + unsigned char c[22*Zc] __attribute__((aligned(32))); //padded input, unpacked, max size + unsigned char d[46*Zc] __attribute__((aligned(32))); //coded parity part output, unpacked, max size + + unsigned char c_extension[2*22*Zc*simd_size] __attribute__((aligned(32))); //double size matrix of c + + // calculate number of punctured bits + no_punctured_columns=(int)((nrows-2)*Zc+block_length-block_length*3)/Zc; + removed_bit=(nrows-no_punctured_columns-2) * Zc+block_length-(int)(block_length*3); + // printf("%d\n",no_punctured_columns); + // printf("%d\n",removed_bit); + // unpack input + memset(c,0,sizeof(unsigned char) * ncols * Zc); + memset(d,0,sizeof(unsigned char) * nrows * Zc); + + start_meas(tinput); +#if 0 + for (i=0; i>(i&7); + //printf("c(%d,%d)=%d\n",j,i,temp); + c[i] |= (temp << (j-macro_segment)); + } + } +#else +#ifdef __AVX2__ + for (i=0; i>5; i++) { + c256 = _mm256_and_si256(_mm256_cmpeq_epi8(_mm256_andnot_si256(_mm256_shuffle_epi8(_mm256_set1_epi32(((uint32_t*)test_input[macro_segment])[i]), shufmask),andmask),zero256),masks[0]); + //for (j=1; j>5)<<5;i>(i&7); + //printf("c(%d,%d)=%d\n",j,i,temp); + c[i] |= (temp << (j-macro_segment)); + } + } +#else + AssertFatal(1==0,"Need AVX2 for this\n"); +#endif +#endif + + stop_meas(tinput); + + if ((BG==1 && Zc>176) || (BG==2 && Zc>64)) { + // extend matrix + start_meas(tprep); + for (i1=0; i1 < ncols; i1++) + { + memcpy(&c_extension[2*i1*Zc], &c[i1*Zc], Zc*sizeof(unsigned char)); + memcpy(&c_extension[(2*i1+1)*Zc], &c[i1*Zc], Zc*sizeof(unsigned char)); + } + for (i1=1;i1>5; + uint32_t l2 = ((nrows-no_punctured_columns) * Zc-removed_bit)>>5; + __m256i *c256p = (__m256i *)&c[2*Zc]; + __m256i *d256p = (__m256i *)&d[0]; + // if (((block_length-(2*Zc))&31)>0) l1++; + + for (i=0;i0) l2++; + + for (i1=0;i1>(j-macro_segment))&1; + for (i=0;i<((nrows-no_punctured_columns) * Zc-removed_bit);i++) + //for (j=0; j>(j-macro_segment))&1; + } + +#else + AssertFatal(1==0,"Need AVX2 for now\n"); +#endif + + stop_meas(toutput); + return 0; +} + diff --git a/openair1/PHY/CODING/nrLDPC_encoder/ldpc_generate_coefficient.c b/openair1/PHY/CODING/nrLDPC_encoder/ldpc_generate_coefficient.c index 93edc734de..07335b2cfb 100644 --- a/openair1/PHY/CODING/nrLDPC_encoder/ldpc_generate_coefficient.c +++ b/openair1/PHY/CODING/nrLDPC_encoder/ldpc_generate_coefficient.c @@ -361,7 +361,7 @@ short *choose_generator_matrix(short BG,short Zc) return Gen_shift_values; } -int ldpc_encoder_orig(unsigned char *test_input,unsigned char *channel_input,short block_length,short BG,unsigned char gen_code) +int ldpc_encoder_orig(unsigned char *test_input,unsigned char *channel_input,short block_length, short BG,unsigned char gen_code) { unsigned char c[22*384]; //padded input, unpacked, max size unsigned char d[68*384]; //coded output, unpacked, max size @@ -378,26 +378,30 @@ int ldpc_encoder_orig(unsigned char *test_input,unsigned char *channel_input,sho int indlist2[1000]; //determine number of bits in codeword - if (BG==1) - { - Kb = 22; - nrows=46; //parity check bits - ncols=22; //info bits - } - else if (BG==2) - { - nrows=42; //parity check bits - ncols=10; // info bits + //if (block_length>3840) + if (BG==1) + { + //BG=1; + Kb = 22; + nrows=46; //parity check bits + ncols=22; //info bits + } + //else if (block_length<=3840) + else if (BG==2) + { + //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; - } + 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; @@ -415,8 +419,6 @@ int ldpc_encoder_orig(unsigned char *test_input,unsigned char *channel_input,sho return(-1); } - int K = ncols*Zc; - Gen_shift_values=choose_generator_matrix(BG,Zc); if (Gen_shift_values==NULL) { printf("ldpc_encoder_orig: could not find generator matrix\n"); @@ -438,15 +440,9 @@ int ldpc_encoder_orig(unsigned char *test_input,unsigned char *channel_input,sho } no_punctured_columns=(int)((nrows-2)*Zc+block_length-block_length*3)/Zc; - //nrows - no_punctured_columns = 2 +2*block_length/Zc removed_bit=(nrows-no_punctured_columns-2) * Zc+block_length-(block_length*3); - // ((nrows-no_punctured_columns) * Zc-removed_bit) = - // 2Zc + 2*block_length //printf("%d\n",no_punctured_columns); //printf("%d\n",removed_bit); - //printf("%d\n",nrows-no_punctured_columns); - //printf("%d\n",((nrows-no_punctured_columns) * Zc-removed_bit)); - // unpack input memset(c,0,sizeof(unsigned char) * ncols * Zc); memset(d,0,sizeof(unsigned char) * nrows * Zc); @@ -614,8 +610,8 @@ int ldpc_encoder_orig(unsigned char *test_input,unsigned char *channel_input,sho } // information part and puncture columns - memcpy(&channel_input[0], &c[2*Zc], (block_length-2*Zc)*sizeof(unsigned char)); //systematic bits - memcpy(&channel_input[block_length-2*Zc], &d[0], ((nrows-no_punctured_columns) * Zc-removed_bit)*sizeof(unsigned char)); //systematic bits 2Zc + 2*block_length + memcpy(&channel_input[0], &c[2*Zc], (block_length-2*Zc)*sizeof(unsigned char)); + memcpy(&channel_input[block_length-2*Zc], &d[0], ((nrows-no_punctured_columns) * Zc-removed_bit)*sizeof(unsigned char)); //memcpy(channel_input,c,Kb*Zc*sizeof(unsigned char)); return 0; }