diff --git a/cmake_targets/CMakeLists.txt b/cmake_targets/CMakeLists.txt index 9677d65a67..2b4e5bfc47 100644 --- a/cmake_targets/CMakeLists.txt +++ b/cmake_targets/CMakeLists.txt @@ -1132,7 +1132,7 @@ set(PHY_POLARSRC ${OPENAIR1_DIR}/PHY/CODING/nrPolar_tools/nr_crc_byte.c ${OPENAIR1_DIR}/PHY/CODING/nrPolar_tools/nr_polar_bit_insertion.c ${OPENAIR1_DIR}/PHY/CODING/nrPolar_tools/nr_polar_channel_interleaver_pattern.c - ${OPENAIR1_DIR}/PHY/CODING/nrPolar_tools/nr_polar_crc.c + # ${OPENAIR1_DIR}/PHY/CODING/nrPolar_tools/nr_polar_crc.c ${OPENAIR1_DIR}/PHY/CODING/nrPolar_tools/nr_polar_decoding_tools.c ${OPENAIR1_DIR}/PHY/CODING/nrPolar_tools/nr_polar_info_bit_pattern.c ${OPENAIR1_DIR}/PHY/CODING/nrPolar_tools/nr_polar_interleaving_pattern.c @@ -1147,7 +1147,13 @@ set(PHY_POLARSRC ) set(PHY_TURBOIF ${OPENAIR1_DIR}/PHY/CODING/coding_load.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 + ) add_library(coding MODULE ${PHY_TURBOSRC} ) @@ -1300,6 +1306,7 @@ set(PHY_SRC_UE ${OPENAIR1_DIR}/PHY/TOOLS/time_meas.c ${OPENAIR1_DIR}/PHY/TOOLS/lut.c ${PHY_POLARSRC} + ${PHY_LDPCSRC} ) set(PHY_NR_UE_SRC @@ -1337,6 +1344,7 @@ set(PHY_SRC_UE ${OPENAIR1_DIR}/PHY/TOOLS/lut.c ${OPENAIR1_DIR}/PHY/INIT/nr_init_ue.c ${PHY_POLARSRC} + ${PHY_LDPCSRC} ) @@ -2539,7 +2547,10 @@ target_link_libraries (dlsim_tm4 ) add_executable(polartest ${OPENAIR1_DIR}/PHY/CODING/TESTBENCH/polartest.c) -target_link_libraries(polartest m SIMU PHY PHY_NR -lm ${ATLAS_LIBRARIES}) +target_link_libraries(polartest m SIMU PHY PHY_NR PHY_COMMON -lm ${ATLAS_LIBRARIES}) + +add_executable(ldpctest ${OPENAIR1_DIR}/PHY/CODING/TESTBENCH/ldpctest.c) +target_link_libraries(ldpctest m SIMU PHY PHY_NR ${ATLAS_LIBRARIES}) foreach(myExe dlsim dlsim_tm7 ulsim pbchsim scansim mbmssim pdcchsim pucchsim prachsim syncsim) 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 33c51386ba..158be941c7 100644 --- a/openair1/PHY/CODING/TESTBENCH/ldpctest.c +++ b/openair1/PHY/CODING/TESTBENCH/ldpctest.c @@ -25,8 +25,18 @@ #include #include "SIMULATION/TOOLS/sim.h" +#include "PHY/CODING/nrLDPC_encoder/defs.h" +#include "PHY/CODING/nrLDPC_decoder/nrLDPC_decoder.h" +#define MAX_NUM_DLSCH_SEGMENTS 16 +#ifndef malloc16 +# ifdef __AVX2__ +# define malloc16(x) memalign(32,x) +# else +# define malloc16(x) memalign(16,x) +# endif +#endif // 4-bit quantizer char quantize4bit(double D,double x) @@ -62,11 +72,11 @@ char quantize(double D,double x,unsigned char B) #define MAX_BLOCK_LENGTH 8448 int test_ldpc(short No_iteration, - int nom_rate, - int denom_rate, + //int nom_rate, + //int denom_rate, double SNR, unsigned char qbits, - short block_length, + unsigned short block_length, unsigned int ntrials, unsigned int *errors, unsigned int *crc_misses) @@ -85,12 +95,14 @@ int test_ldpc(short No_iteration, 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; + short BG,Zc,Kb; + //short 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; + int N; //length encoded block t_nrLDPC_dec_params decParams; int n_iter; @@ -107,7 +119,9 @@ int test_ldpc(short No_iteration, 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); + estimated_output = (unsigned char*) malloc16(sizeof(unsigned char) * block_length); + + memset(channel_output_fixed,0,sizeof(char) * 68*384); reset_meas(&time); reset_meas(&time_optim); @@ -124,18 +138,18 @@ int test_ldpc(short No_iteration, } //determine number of bits in codeword - //if (block_length>3840) + if ((block_length>3840) && (block_length <= MAX_BLOCK_LENGTH)) { BG=1; Kb = 22; - nrows=46; //parity check bits - ncols=22; //info bits + //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 - ncols=10; // info bits + //nrows=42; //parity check bits + //ncols=10; // info bits if (block_length>640) Kb = 10; @@ -145,11 +159,14 @@ 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) @@ -160,12 +177,17 @@ int test_ldpc(short No_iteration, } } - 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; + if (BG==1) + N=66*Zc; + else if (BG==2) + N=50*Zc; + + 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)); + //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); + ldpc_encoder_orig(test_input[0],channel_input[0], block_length, BG, 1); for (trial=0; trial < ntrials; trial++) { @@ -173,20 +195,20 @@ int test_ldpc(short No_iteration, //// encoder start_meas(&time); for(j=0;j1.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]); } - //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 - + /* + 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; @@ -236,9 +256,9 @@ int test_ldpc(short No_iteration, // 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)); + //estimated_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); + 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]); @@ -248,15 +268,12 @@ int test_ldpc(short No_iteration, { if (estimated_output[i] != test_input[0][i]) { - //printf("error pos %d (%d, %d)\n",i,estimated_output[i],test_input[i]); + printf("error pos %d (%d, %d)\n",i,estimated_output[i],test_input[0][i]); *errors = (*errors) + 1; break; } } - } - /*else if (trial==0) - printf("decoder is not supported\n");*/ } for(j=0;j 1280, 2401 -> 2560 short No_iteration=25; //double rate=0.333; - int nom_rate=1; - int denom_rate=3; + //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 @@ -295,21 +312,13 @@ int main(int argc, char *argv[]) randominit(0); - while ((c = getopt (argc, argv, "q:r:s:l:n:d:")) != -1) + while ((c = getopt (argc, argv, "q:s:l:n: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; @@ -323,21 +332,25 @@ int main(int argc, char *argv[]) break; default: - abort (); + 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("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("rate: %d/%d\n",nom_rate,denom_rate); + 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;SNR eq. (8a) and (11b), 1 --> eq. (9) and (12) - while ((arguments = getopt (argc, argv, "s:d:f:m:i:l:a:")) != -1) + while ((arguments = getopt (argc, argv, "s:d:f:m:i:l:a:h")) != -1) switch (arguments) { case 's': @@ -64,21 +65,33 @@ int main(int argc, char *argv[]) { pathMetricAppr = (uint8_t) atoi(optarg); break; + case 'h': + printf("./polartest -s SNRstart -d SNRinc -f SNRstop -m [0=DCI|1=PBCH|2=UCI] -i iterations -l decoderListSize -a pathMetricAppr\n"); + exit(-1); + default: perror("[polartest.c] Problem at argument parsing with getopt"); - abort (); + exit(-1); } if (polarMessageType == 0) { //DCI - //testLength = ; - //coderLength = ; + //testLength = ; + //coderLength = ; + printf("polartest for DCI not supported yet\n"); + exit(-1); } else if (polarMessageType == 1) { //PBCH - testLength = NR_POLAR_PBCH_PAYLOAD_BITS; - coderLength = NR_POLAR_PBCH_E; + testLength = NR_POLAR_PBCH_PAYLOAD_BITS; + coderLength = NR_POLAR_PBCH_E; + printf("running polartest for PBCH\n"); } else if (polarMessageType == 2) { //UCI - //testLength = ; - //coderLength = ; + testLength = NR_POLAR_PUCCH_PAYLOAD_BITS; + coderLength = NR_POLAR_PUCCH_E; + printf("running polartest for UCI"); + } else { + printf("unsupported polarMessageType %d (0=DCI, 1=PBCH, 2=UCI)\n",polarMessageType); + exit(-1); } + //Logging time_t currentTime; @@ -96,12 +109,12 @@ int main(int argc, char *argv[]) { if (stat(folderName, &folder) == -1) mkdir(folderName, S_IRWXU | S_IRWXG | S_IRWXO); FILE* logFile; - logFile = fopen(fileName, "w"); - if (logFile==NULL) { - fprintf(stderr,"[polartest.c] Problem creating file %s with fopen\n",fileName); - exit(-1); - } - fprintf(logFile,",SNR,nBitError,blockErrorState,t_encoder[us],t_decoder[us]\n"); + logFile = fopen(fileName, "w"); + if (logFile==NULL) { + fprintf(stderr,"[polartest.c] Problem creating file %s with fopen\n",fileName); + exit(-1); + } + fprintf(logFile,",SNR,nBitError,blockErrorState,t_encoder[us],t_decoder[us]\n"); uint8_t *testInput = malloc(sizeof(uint8_t) * testLength); //generate randomly uint8_t *encoderOutput = malloc(sizeof(uint8_t) * coderLength); @@ -121,7 +134,8 @@ int main(int argc, char *argv[]) { SNR_lin = pow(10, SNR/10); for (itr = 1; itr <= iterations; itr++) { - for(int i=0; i D^6+D^5+1 +uint32_t poly11 = 0xc4200000; //11000100001000... -> D^11+D^10+D^9+D^5+1 + /********************************************************* For initialization && verification purposes, @@ -93,6 +96,18 @@ void crcTableInit (void) crc8Table[c] = (unsigned char) (crcbit (&c, 1, poly8) >> 24); } while (++c); } + +//Generic version +void crcTable256Init (uint32_t poly, uint32_t* crc256Table) +{ + unsigned char c = 0; + + do { + crc256Table[c] = crcbit(&c, 1, poly); + } while (++c); + +} + /********************************************************* Byte by byte implementations, @@ -193,6 +208,70 @@ crc8 (unsigned char * inptr, int bitlen) return crc; } +//Generic version +unsigned int crcPayload(unsigned char * inptr, int bitlen, uint32_t* crc256Table) +{ + int octetlen, resbit; + unsigned int crc = 0; + octetlen = bitlen/8; // Change in bytes + resbit = (bitlen % 8); + + while (octetlen-- > 0) + { + crc = (crc << 8) ^ crc256Table[(*inptr++) ^ (crc >> 24)]; + } + + if (resbit > 0) + { + crc = (crc << resbit) ^ crc256Table[((*inptr) >> (8 - resbit)) ^ (crc >> (32 - resbit))]; + } + return crc; +} + +void nr_crc_computation(uint8_t* input, uint8_t* output, uint16_t payloadBits, uint16_t crcParityBits, uint32_t* crc256Table) +{ + //Create payload in bit + uint8_t* input2 = (uint8_t*)malloc(payloadBits); //divided by 8 (in bits) + uint8_t mask = 128; // 10000000 + + for(uint8_t ind=0; ind<(payloadBits/8); ind++) + { + input2[ind]=0; + for(uint8_t ind2=0; ind2<8; ind2++) + { + if(input[8*ind+ind2]) + { + input2[ind] = input2[ind] | mask; + } + mask= mask >> 1; + } + mask=128; + } + + //crcTable256Init(poly); + + unsigned int crcBits; + crcBits = crcPayload(input2, payloadBits, crc256Table); + + //create crc in byte + unsigned int mask2=0x80000000; //100... + + for(uint8_t ind=0; ind> 1; + } + +} + + + + + #ifdef DEBUG_CRC /*******************************************************************/ /** diff --git a/openair1/PHY/CODING/nrLDPC_encoder/defs.h b/openair1/PHY/CODING/nrLDPC_encoder/defs.h index b8652bc593..629d50c79c 100644 --- a/openair1/PHY/CODING/nrLDPC_encoder/defs.h +++ b/openair1/PHY/CODING/nrLDPC_encoder/defs.h @@ -31,6 +31,18 @@ #include "PHY/TOOLS/time_meas.h" +/*ldpc_encoder.c*/ +int encode_parity_check_part_orig(unsigned char *c,unsigned char *d, short BG,short Zc,short Kb,short block_length); + +/*ldpc_encoder2.c*/ +void encode_parity_check_part_optim(uint8_t *c,uint8_t *d, short BG,short Zc,short Kb); +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); +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); + +/*ldpc_generate_coefficient.c*/ +int ldpc_encoder_orig(unsigned char *test_input,unsigned char *channel_input,short block_length,short BG,unsigned char gen_code); + +/* int encode_parity_check_part(unsigned char *c,unsigned char *d, short BG,short Zc,short Kb); int encode_parity_check_part_orig(unsigned char *c,unsigned char *d, short BG,short Zc,short Kb,short block_length); int ldpc_encoder(unsigned char *test_input,unsigned char *channel_input,short block_length, double rate); @@ -38,4 +50,4 @@ int ldpc_encoder_orig(unsigned char *test_input,unsigned char *channel_input,sho int ldpc_encoder_multi_segment(unsigned char **test_input,unsigned char **channel_input,short block_length,double rate,uint8_t n_segments); int ldpc_encoder_optim(unsigned char *test_input,unsigned char *channel_input,short block_length,int nom_rate,int denom_rate,time_stats_t *tinput,time_stats_t *tprep,time_stats_t *tparity,time_stats_t *toutput); int ldpc_encoder_optim_8seg(unsigned char **test_input,unsigned char **channel_input,short block_length,int nom_rate,int denom_rate,int n_segments,time_stats_t *tinput,time_stats_t *tprep,time_stats_t *tparity,time_stats_t *toutput); - +*/ diff --git a/openair1/PHY/CODING/nrLDPC_encoder/ldpc_encoder.c b/openair1/PHY/CODING/nrLDPC_encoder/ldpc_encoder.c index 7e78c3f03f..b97b780333 100644 --- a/openair1/PHY/CODING/nrLDPC_encoder/ldpc_encoder.c +++ b/openair1/PHY/CODING/nrLDPC_encoder/ldpc_encoder.c @@ -50,14 +50,14 @@ int encode_parity_check_part_orig(unsigned char *c,unsigned char *d, short BG,sh int i1,i2,i3,i4,i5,temp_prime; unsigned char channel_temp,temp; - //if (BG==1) + if (BG==1) { no_shift_values=(short *) no_shift_values_BG1; pointer_shift_values=(short *) pointer_shift_values_BG1; nrows=46; //parity check bits ncols=22; //info bits } - /*else if (BG==2) + else if (BG==2) { no_shift_values=(short *) no_shift_values_BG2; pointer_shift_values=(short *) pointer_shift_values_BG2; @@ -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 b691d3020e..037c19f88e 100644 --- a/openair1/PHY/CODING/nrLDPC_encoder/ldpc_encoder2.c +++ b/openair1/PHY/CODING/nrLDPC_encoder/ldpc_encoder2.c @@ -198,10 +198,10 @@ 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,int nom_rate,int denom_rate,time_stats_t *tinput,time_stats_t *tprep,time_stats_t *tparity,time_stats_t *toutput) +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 BG,Zc,Kb,nrows,ncols; + short Kb,Zc,nrows,ncols; int i,i1; int no_punctured_columns,removed_bit; @@ -211,16 +211,14 @@ int ldpc_encoder_optim(unsigned char *test_input,unsigned char *channel_input,sh int simd_size; //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 @@ -232,7 +230,7 @@ int ldpc_encoder_optim(unsigned char *test_input,unsigned char *channel_input,sh Kb = 8; else Kb = 6; - }*/ + } //find minimum value in all sets of lifting size Zc=0; @@ -315,10 +313,10 @@ int ldpc_encoder_optim(unsigned char *test_input,unsigned char *channel_input,sh return 0; } -int ldpc_encoder_optim_8seg(unsigned char **test_input,unsigned char **channel_input,short block_length,int nom_rate,int denom_rate,int n_segments,time_stats_t *tinput,time_stats_t *tprep,time_stats_t *tparity,time_stats_t *toutput) +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 BG,Zc,Kb,nrows,ncols; + short Kb,Zc,nrows,ncols; int i,i1,j; int no_punctured_columns,removed_bit; //Table of possible lifting sizes @@ -345,16 +343,14 @@ 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 (block_length<=3840) + else if (BG==2) { - BG=2; nrows=42; //parity check bits ncols=10; // info bits @@ -366,7 +362,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; diff --git a/openair1/PHY/CODING/nrLDPC_encoder/ldpc_generate_coefficient.c b/openair1/PHY/CODING/nrLDPC_encoder/ldpc_generate_coefficient.c index ed8201c51d..93edc734de 100644 --- a/openair1/PHY/CODING/nrLDPC_encoder/ldpc_generate_coefficient.c +++ b/openair1/PHY/CODING/nrLDPC_encoder/ldpc_generate_coefficient.c @@ -361,13 +361,13 @@ 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,int nom_rate,int denom_rate,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 unsigned char channel_temp,temp; short *Gen_shift_values, *no_shift_values, *pointer_shift_values; - short BG,Zc,Kb,nrows,ncols; + short Zc,Kb,nrows,ncols; int i,i1,i2,i3,i4,i5,temp_prime,var; int no_punctured_columns,removed_bit; //Table of possible lifting sizes @@ -378,16 +378,14 @@ int ldpc_encoder_orig(unsigned char *test_input,unsigned char *channel_input,sho int indlist2[1000]; //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 @@ -399,7 +397,7 @@ int ldpc_encoder_orig(unsigned char *test_input,unsigned char *channel_input,sho Kb = 8; else Kb = 6; - }*/ + } //find minimum value in all sets of lifting size Zc=0; @@ -417,6 +415,8 @@ 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,9 +438,15 @@ 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); @@ -608,8 +614,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)); - memcpy(&channel_input[block_length-2*Zc], &d[0], ((nrows-no_punctured_columns) * Zc-removed_bit)*sizeof(unsigned char)); + 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,c,Kb*Zc*sizeof(unsigned char)); return 0; } diff --git a/openair1/PHY/CODING/nrPolar_init.c b/openair1/PHY/CODING/nrPolar_init.c index 6f5b167c0e..65422ee073 100644 --- a/openair1/PHY/CODING/nrPolar_init.c +++ b/openair1/PHY/CODING/nrPolar_init.c @@ -21,9 +21,17 @@ #include "nrPolar_tools/nr_polar_defs.h" #include "nrPolar_tools/nr_polar_pbch_defs.h" +#include "nrPolar_tools/nr_polar_uci_defs.h" void nr_polar_init(t_nrPolar_params* polarParams, int messageType) { +uint32_t poly6 = 0x84000000; // 1000100000... -> D^6+D^5+1 +uint32_t poly11 = 0x63200000; //11000100001000... -> D^11+D^10+D^9+D^5+1 +uint32_t poly16 = 0x81080000; //100000010000100... - > D^16+D^12+D^5+1 +uint32_t poly24a = 0x864cfb00; //100001100100110011111011 -> D^24+D^23+D^18+D^17+D^14+D^11+D^10+D^7+D^6+D^5+D^4+D^3+D+1 +uint32_t poly24b = 0x80006300; //100000000000000001100011 -> D^24+D^23+D^6+D^5+D+1 +uint32_t poly24c = 0xB2B11700; //101100101011000100010111 -> D^24... + if (messageType == 0) { //DCI } else if (messageType == 1) { //PBCH @@ -36,13 +44,13 @@ void nr_polar_init(t_nrPolar_params* polarParams, int messageType) { polarParams->payloadBits = NR_POLAR_PBCH_PAYLOAD_BITS; polarParams->encoderLength = NR_POLAR_PBCH_E; polarParams->crcParityBits = NR_POLAR_PBCH_CRC_PARITY_BITS; - polarParams->crcCorrectionBits = NR_POLAR_PBCH_CRC_ERROR_CORRECTION_BITS; polarParams->K = polarParams->payloadBits + polarParams->crcParityBits; // Number of bits to encode. polarParams->N = nr_polar_output_length(polarParams->K, polarParams->encoderLength, polarParams->n_max); polarParams->n = log2(polarParams->N); polarParams->crc_generator_matrix=crc24c_generator_matrix(polarParams->payloadBits); + polarParams->crc_polynomial = poly24c; polarParams->G_N = nr_polar_kronecker_power_matrices(polarParams->n); //polar_encoder vectors: @@ -55,9 +63,80 @@ void nr_polar_init(t_nrPolar_params* polarParams, int messageType) { polarParams->nr_polar_cPrime = malloc(sizeof(uint8_t) * polarParams->K); //Decoder: nr_polar_cHat polarParams->nr_polar_b = malloc(sizeof(uint8_t) * polarParams->K); //Decoder: nr_polar_bHat } else if (messageType == 2) { //UCI + polarParams->payloadBits = NR_POLAR_PUCCH_PAYLOAD_BITS; //A depends on what they carry... + polarParams->encoderLength = NR_POLAR_PUCCH_E ; //E depends on other standards 6.3.1.4 + + if (polarParams->payloadBits <= 11) //Ref. 38-212, Section 6.3.1.2.2 + polarParams->crcParityBits = 0; //K=A + else //Ref. 38-212, Section 6.3.1.2.1 + { + if (polarParams->payloadBits < 20) + polarParams->crcParityBits = NR_POLAR_PUCCH_CRC_PARITY_BITS_SHORT; + else + polarParams->crcParityBits = NR_POLAR_PUCCH_CRC_PARITY_BITS_LONG; + if (polarParams->payloadBits >= 360 && polarParams->encoderLength >= 1088) + polarParams->i_seg = NR_POLAR_PUCCH_I_SEG_LONG; // -> C=2 + else + polarParams->i_seg = NR_POLAR_PUCCH_I_SEG_SHORT; // -> C=1 + } + + polarParams->K = polarParams->payloadBits + polarParams->crcParityBits; // Number of bits to encode. + + //K_r = K/C ; C = I_seg+1 + if((polarParams->K)/(polarParams->i_seg+1)>=18 && (polarParams->K)/(polarParams->i_seg+1)<=25) //Ref. 38-212, Section 6.3.1.3.1 + { + polarParams->n_max = NR_POLAR_PUCCH_N_MAX; + polarParams->i_il =NR_POLAR_PUCCH_I_IL; + polarParams->n_pc = NR_POLAR_PUCCH_N_PC_SHORT; + + if( (polarParams->encoderLength - polarParams->K)/(polarParams->i_seg + 1) + 3 > 192 ) + polarParams->n_pc_wm = NR_POLAR_PUCCH_N_PC_WM_LONG; + else + polarParams->n_pc_wm = NR_POLAR_PUCCH_N_PC_WM_SHORT; + } + + if( (polarParams->K)/(polarParams->i_seg + 1) > 30 ) //Ref. 38-212, Section 6.3.1.3.1 + { + polarParams->n_max = NR_POLAR_PUCCH_N_MAX; + polarParams->i_il =NR_POLAR_PUCCH_I_IL; + polarParams->n_pc = NR_POLAR_PUCCH_N_PC_LONG; + polarParams->n_pc_wm = NR_POLAR_PUCCH_N_PC_WM_LONG; + } + + polarParams->i_bil = NR_POLAR_PUCCH_I_BIL; //Ref. 38-212, Section 6.3.1.4.1 + + polarParams->N = nr_polar_output_length(polarParams->K, polarParams->encoderLength, polarParams->n_max); + polarParams->n = log2(polarParams->N); + + if((polarParams->payloadBits) <= 19) + { + polarParams->crc_generator_matrix=crc6_generator_matrix(polarParams->payloadBits); + polarParams->crc_polynomial = poly6; + + } + else + { + polarParams->crc_generator_matrix=crc11_generator_matrix(polarParams->payloadBits); + polarParams->crc_polynomial = poly11; + } + polarParams->G_N = nr_polar_kronecker_power_matrices(polarParams->n); + + //polar_encoder vectors: + polarParams->nr_polar_crc = malloc(sizeof(uint8_t) * polarParams->crcParityBits); + polarParams->nr_polar_cPrime = malloc(sizeof(uint8_t) * polarParams->K); + polarParams->nr_polar_d = malloc(sizeof(uint8_t) * polarParams->N); + + //Polar Coding vectors + polarParams->nr_polar_u = malloc(sizeof(uint8_t) * polarParams->N); //Decoder: nr_polar_uHat + polarParams->nr_polar_cPrime = malloc(sizeof(uint8_t) * polarParams->K); //Decoder: nr_polar_cHat + polarParams->nr_polar_b = malloc(sizeof(uint8_t) * polarParams->K); //Decoder: nr_polar_bHat } + polarParams->crcCorrectionBits = NR_POLAR_CRC_ERROR_CORRECTION_BITS; + + polarParams->crc256Table = malloc(sizeof(uint32_t)*256); + crcTable256Init(polarParams->crc_polynomial, polarParams->crc256Table); polarParams->Q_0_Nminus1 = nr_polar_sequence_pattern(polarParams->n); polarParams->interleaving_pattern = malloc(sizeof(uint16_t) * polarParams->K); diff --git a/openair1/PHY/CODING/nrPolar_tools/nr_crc_byte.c b/openair1/PHY/CODING/nrPolar_tools/nr_crc_byte.c index 18d416b980..7b5a1c922a 100644 --- a/openair1/PHY/CODING/nrPolar_tools/nr_crc_byte.c +++ b/openair1/PHY/CODING/nrPolar_tools/nr_crc_byte.c @@ -21,6 +21,133 @@ #include "PHY/CODING/nrPolar_tools/nr_polar_defs.h" +/* +// ----- New implementation ---- +uint32_t poly6 = 0x84000000; // 10000100000... -> D^6+D^5+1 +uint32_t poly11 = 0xc4200000; //11000100001000... -> D^11+D^10+D^9+D^5+1 +uint32_t poly16 = 0x10210000; //00100000010000100... - > D^16+D^12+D^5+1 +uint32_t poly24a = 0x864cfb00; //100001100100110011111011 -> D^24+D^23+D^18+D^17+D^14+D^11+D^10+D^7+D^6+D^5+D^4+D^3+D+1 +uint32_t poly24b = 0x80006300; //100000000000000001100011 -> D^24+D^23+D^6+D^5+D+1 +uint32_t poly24c = 0xB2B11700; //101100101011000100010111 -> D^24... + +//static unsigned int crc256Table[256]; + +void nr_crc_computation(uint8_t* input, uint8_t* output, uint16_t payloadBits, uint16_t crcParityBits, uint32_t* crc256Table) +{ + //Create payload in bit + uint8_t* input2 = (uint8_t*)malloc(payloadBits); //divided by 8 (in bits) + uint8_t mask = 128; // 10000000 + + for(uint8_t ind=0; ind<(payloadBits/8); ind++) + { + input2[ind]=0; + for(uint8_t ind2=0; ind2<8; ind2++) + { + if(input[8*ind+ind2]) + { + input2[ind] = input2[ind] | mask; + } + mask= mask >> 1; + } + mask=128; + } + + //crcTable256Init(poly); + + unsigned int crcBits; + crcBits = crcPayload(input2, payloadBits, crc256Table); + + //create crc in byte + unsigned int mask2=0x80000000; //100... + output = (uint8_t*)malloc(sizeof(uint8_t)*crcParityBits); + + for(uint8_t ind=0; ind> 1; + } + +} + +unsigned int crcbit (unsigned char* inputptr, int octetlen, unsigned int poly) +{ + unsigned int i, crc = 0, c; + + while (octetlen-- > 0) { + c = (*inputptr++) << 24; + + for (i = 8; i != 0; i--) { + if ((1 << 31) & (c ^ crc)) + crc = (crc << 1) ^ poly; + else + crc <<= 1; + + c <<= 1; + } + } + + return crc; +} + +void crcTableInit (void) +{ + unsigned char c = 0; + + do { + crc6Table[c] = crcbit(&c, 1, poly6); + crc11Table[c]= crcbit(&c, 1, poly11); + crc16Table[c] =crcbit(&c, 1, poly16); + crc24aTable[c]=crcbit(&c, 1, poly24a); + crc24bTable[c]=crcbit(&c, 1, poly24b); + crc24cTable[c]=crcbit(&c, 1, poly24c); + + } while (++c); +} + +void crcTable256Init (uint32_t poly, uint32_t* crc256Table) +{ + unsigned char c = 0; +// crc256Table = malloc(sizeof(uint32_t)*256); + + do { + crc256Table[c] = crcbit(&c, 1, poly); + +// crc6Table[c] = crcbit(&c, 1, poly6); + // crc11Table[c]= crcbit(&c, 1, poly11); +// crc16Table[c] =crcbit(&c, 1, poly16); +// crc24aTable[c]=crcbit(&c, 1, poly24a); +// crc24bTable[c]=crcbit(&c, 1, poly24b); +// crc24cTable[c]=crcbit(&c, 1, poly24c); + + } while (++c); + + //return crc256Table; +} + +unsigned int crcPayload(unsigned char * inptr, int bitlen, uint32_t* crc256Table) +{ + int octetlen, resbit; + unsigned int crc = 0; + octetlen = bitlen/8; // Change in bytes + resbit = (bitlen % 8); + + while (octetlen-- > 0) + { + crc = (crc << 8) ^ crc256Table[(*inptr++) ^ (crc >> 24)]; + } + + if (resbit > 0) + { + crc = (crc << resbit) ^ crc256Table[((*inptr) >> (8 - resbit)) ^ (crc >> (32 - resbit))]; + } + return crc; +} +*/ +// ----- Old implementation ---- uint8_t **crc24c_generator_matrix(uint16_t payloadSizeBits){ uint8_t crcPolynomialPattern[25] = {1,1,0,1,1,0,0,1,0,1,0,1,1,0,0,0,1,0,0,0,1,0,1,1,1}; diff --git a/openair1/PHY/CODING/nrPolar_tools/nr_polar_defs.h b/openair1/PHY/CODING/nrPolar_tools/nr_polar_defs.h index 0db26f6f35..7caf547395 100644 --- a/openair1/PHY/CODING/nrPolar_tools/nr_polar_defs.h +++ b/openair1/PHY/CODING/nrPolar_tools/nr_polar_defs.h @@ -19,6 +19,8 @@ * contact@openairinterface.org */ +#define NR_POLAR_CRC_ERROR_CORRECTION_BITS 3 + #ifndef __NR_POLAR_DEFS__H__ #define __NR_POLAR_DEFS__H__ @@ -53,9 +55,11 @@ struct nrPolar_params { int16_t *Q_PC_N; uint8_t *information_bit_pattern; uint16_t *channel_interleaver_pattern; + uint32_t crc_polynomial; uint8_t **crc_generator_matrix; //G_P uint8_t **G_N; + uint32_t* crc256Table; //polar_encoder vectors: uint8_t *nr_polar_crc; @@ -68,6 +72,8 @@ typedef struct nrPolar_params t_nrPolar_params; void polar_encoder(uint8_t *input, uint8_t *output, t_nrPolar_params* polarParams); +void nr_polar_kernal_operation(uint8_t *u, uint8_t *d, uint16_t N); + int8_t polar_decoder(double *input, uint8_t *output, t_nrPolar_params *polarParams, uint8_t listSize, double *aPrioriPayload, uint8_t pathMetricAppr); @@ -135,6 +141,11 @@ uint8_t **crc24c_generator_matrix(uint16_t payloadSizeBits); uint8_t **crc11_generator_matrix(uint16_t payloadSizeBits); uint8_t **crc6_generator_matrix(uint16_t payloadSizeBits); +void crcTable256Init (uint32_t poly, uint32_t* crc256Table); +void nr_crc_computation(uint8_t* input, uint8_t* output, uint16_t payloadBits, uint16_t crcParityBits, uint32_t* crc256Table); +unsigned int crcbit (unsigned char* inputptr, int octetlen, uint32_t poly); +unsigned int crcPayload(unsigned char * inptr, int bitlen, uint32_t* crc256Table); + static inline void nr_polar_rate_matcher(uint8_t *input, unsigned char *output, uint16_t *pattern, uint16_t size) { for (int i=0; icrc_generator_matrix, - polarParams->nr_polar_crc, polarParams->payloadBits, polarParams->crcParityBits); - for (uint8_t i = 0; i < polarParams->crcParityBits; i++) polarParams->nr_polar_crc[i] = (polarParams->nr_polar_crc[i] % 2); + // --- OLD --- + //nr_matrix_multiplication_uint8_t_1D_uint8_t_2D(input, polarParams->crc_generator_matrix, + // polarParams->nr_polar_crc, polarParams->payloadBits, polarParams->crcParityBits); + //for (uint8_t i = 0; i < polarParams->crcParityBits; i++) polarParams->nr_polar_crc[i] = (polarParams->nr_polar_crc[i] % 2); + + // --- NEW --- + nr_crc_computation(input, polarParams->nr_polar_crc, polarParams->payloadBits, polarParams->crcParityBits, polarParams->crc256Table); + //Attach CRC to the Transport Block. (a to b) for (uint16_t i = 0; i < polarParams->payloadBits; i++) polarParams->nr_polar_b[i] = input[i]; @@ -50,8 +55,19 @@ void polar_encoder( polarParams->Q_I_N, polarParams->Q_PC_N, polarParams->n_pc); //Encoding (u to d) - nr_matrix_multiplication_uint8_t_1D_uint8_t_2D(polarParams->nr_polar_u, polarParams->G_N, polarParams->nr_polar_d, polarParams->N, polarParams->N); - for (uint16_t i = 0; i < polarParams->N; i++) polarParams->nr_polar_d[i] = (polarParams->nr_polar_d[i] % 2); + // --- OLD --- + //nr_matrix_multiplication_uint8_t_1D_uint8_t_2D(polarParams->nr_polar_u, polarParams->G_N, polarParams->nr_polar_d, polarParams->N, polarParams->N); + //for (uint16_t i = 0; i < polarParams->N; i++) polarParams->nr_polar_d[i] = (polarParams->nr_polar_d[i] % 2); + //printf("\nd old: "); + //for (uint16_t i = 0; i < polarParams->N; i++) + //printf("%i ", polarParams->nr_polar_d[i]); + + // --- NEW --- + nr_polar_kernal_operation(polarParams->nr_polar_u, polarParams->nr_polar_d, polarParams->N); + //printf("\nd new: "); + //for (uint16_t i = 0; i < polarParams->N; i++) + // printf("%i ", polarParams->nr_polar_d[i]); + //for (uint16_t i = 0; i < polarParams->N; i++) polarParams->nr_polar_d[i] = (polarParams->nr_polar_d[i] % 2); //Rate matching //Sub-block interleaving (d to y) and Bit selection (y to e) diff --git a/openair1/PHY/CODING/nrPolar_tools/nr_polar_kernal_operation.c b/openair1/PHY/CODING/nrPolar_tools/nr_polar_kernal_operation.c index 0584d98afa..5985130eee 100644 --- a/openair1/PHY/CODING/nrPolar_tools/nr_polar_kernal_operation.c +++ b/openair1/PHY/CODING/nrPolar_tools/nr_polar_kernal_operation.c @@ -3,21 +3,73 @@ #include #include -void nr_polar_kernel_operation(uint8_t *u, uint8_t *d, uint16_t N) +#include + +void nr_polar_kernal_operation(uint8_t *u, uint8_t *d, uint16_t N) { - // Martino's algorithm to avoid multiplication for the generating matrix + // Martino's algorithm to avoid multiplication for the generating matrix of polar codes + + uint32_t i,j; - int i,j; - printf("\nd = "); - for(i=0; i If zero, then XOR with the u(j) + D=_mm256_cmpeq_epi32(C, zerosOnly); // compare with zero and use the result as mask + + E=_mm256_maskload_epi32((int const*)uArray, D); // load only some u(j)s for the XOR + OUT=_mm256_xor_si256(OUT, E); //32 bit x 8 + + } + _mm256_storeu_si256((__m256i*)dTest, OUT); + + for(k=0; k<8; k++) // Conversion from 32 bits to 8 bits + { + d[i+k]=(uint8_t)dTest[k]; // With AVX512 there is an intrinsic to do it + } + + } + + #else + + for(i=0; i