diff --git a/openair1/PHY/CODING/TESTBENCH/polartest.c b/openair1/PHY/CODING/TESTBENCH/polartest.c index f412be1271..8c15ef59bc 100644 --- a/openair1/PHY/CODING/TESTBENCH/polartest.c +++ b/openair1/PHY/CODING/TESTBENCH/polartest.c @@ -92,12 +92,12 @@ int main(int argc, char *argv[]) { } if (polarMessageType == 0) { //PBCH - testLength = NR_POLAR_PBCH_PAYLOAD_BITS; + testLength = 64;//NR_POLAR_PBCH_PAYLOAD_BITS; coderLength = NR_POLAR_PBCH_E; aggregation_level = NR_POLAR_PBCH_AGGREGATION_LEVEL; } else if (polarMessageType == 1) { //DCI //testLength = nr_get_dci_size(params_rel15->dci_format, params_rel15->rnti_type, &fp->initial_bwp_dl, cfg); - testLength = 20; + testLength = 64; //20; coderLength = 108; //to be changed by aggregate level function. } else if (polarMessageType == -1) { //UCI //testLength = ; @@ -318,10 +318,16 @@ int main(int argc, char *argv[]) { for (int i=0; i<32; i++) printf("%d\n",(testInput[0]>>i)&1);*/ - start_meas(&timeEncoder); - polar_encoder(testInput, encoderOutput, currentPtr); - stop_meas(&timeEncoder); + + + + start_meas(&timeEncoder); + if (decoder_int16==0) + polar_encoder(testInput, encoderOutput, currentPtr); + else + polar_encoder_fast((uint64_t*)testInput, (uint64_t*)encoderOutput,0, currentPtr); + stop_meas(&timeEncoder); /*printf("encoderOutput: [0]->0x%08x\n", encoderOutput[0]); printf("encoderOutput: [1]->0x%08x\n", encoderOutput[1]);*/ @@ -377,13 +383,16 @@ int main(int argc, char *argv[]) { blockErrorState=-1; nBitError=-1; } else { - for (int i = 0; i < testArrayLength; i++) { - for (int j = 0; j < (sizeof(testInput[0])*8); j++) { - if (((estimatedOutput[i]>>j) & 1) != ((testInput[i]>>j) & 1)) nBitError++; - } - } + for (int j = 0; j < currentPtr->payloadBits; j++) { + if (((estimatedOutput[0]>>j) & 1) != ((testInput[0]>>j) & 1)) nBitError++; + + } + - if (nBitError>0) blockErrorState=1; + if (nBitError>0) { + blockErrorState=1; + printf("Error: Input %x, Output %x\n",testInput[0],estimatedOutput[0]); + } } //Iteration times are in microseconds. diff --git a/openair1/PHY/CODING/nrPolar_tools/nr_polar_decoder.c b/openair1/PHY/CODING/nrPolar_tools/nr_polar_decoder.c index 776cfbbae2..cbd676e9b2 100644 --- a/openair1/PHY/CODING/nrPolar_tools/nr_polar_decoder.c +++ b/openair1/PHY/CODING/nrPolar_tools/nr_polar_decoder.c @@ -37,7 +37,7 @@ */ #include "PHY/CODING/nrPolar_tools/nr_polar_defs.h" - +#include "assertions.h" int8_t polar_decoder( double *input, @@ -1037,6 +1037,31 @@ int8_t polar_decoder_dci(double *input, return(0); } +void init_polar_deinterleaver_table(t_nrPolar_params *polarParams) { + + AssertFatal(polarParams->K > 32, "K = %d < 33, is not supported yet\n",polarParams->K); + AssertFatal(polarParams->K < 65, "K = %d > 64, is not supported yet\n",polarParams->K); + + int bit_i,ip; + + int numbytes = polarParams->K>>3; + int residue = polarParams->K&7; + int numbits; + if (residue>0) numbytes++; + for (int byte=0;byteK>>3)) numbits=8; + else numbits=residue; + for (int i=0;iinterleaving_pattern[(8*byte)+i]; + AssertFatal(ip<64,"ip = %d\n",ip); + for (int val=0;val<256;val++) { + bit_i=(val>>i)&1; + polarParams->B_tab[byte][val] |= (((uint64_t)bit_i)<tree.root->alpha[0],(void*)&d_tilde[0],sizeof(int16_t)*polarParams->N); - /* - * SCL polar decoder. - */ - - generic_polar_decoder(polarParams,polarParams->tree.root); //Extract the information bits (û to ĉ) - nr_polar_info_bit_extraction(polarParams->nr_polar_U, polarParams->nr_polar_CPrime, polarParams->information_bit_pattern, polarParams->N); + uint64_t Cprime=0; + uint64_t B; + for (int i=0;iK;i++) Cprime = Cprime | ((uint64_t)polarParams->nr_polar_U[polarParams->Q_I_N[i]])<B_tab[0][Cprimebyte[0]] | + polarParams->B_tab[1][Cprimebyte[1]] | + polarParams->B_tab[2][Cprimebyte[2]] | + polarParams->B_tab[3][Cprimebyte[3]] | + polarParams->B_tab[4][Cprimebyte[4]] | + polarParams->B_tab[5][Cprimebyte[5]] | + polarParams->B_tab[6][Cprimebyte[6]] | + polarParams->B_tab[7][Cprimebyte[7]]; - nr_polar_deinterleaver(polarParams->nr_polar_CPrime, polarParams->nr_polar_B, polarParams->interleaving_pattern, polarParams->K); - - //Remove the CRC (â) - //for (int j = 0; j < polarParams->payloadBits; j++) polarParams->nr_polar_A[j]=polarParams->nr_polar_B[j]; - - // Check the CRC - for (int j=0;jcrcParityBits;j++) { - int crcbit=0; - for (int i=0;ipayloadBits;i++) - crcbit = crcbit ^ (polarParams->crc_generator_matrix[i][j] & polarParams->nr_polar_B[i]); - if (crcbit != polarParams->nr_polar_B[polarParams->payloadBits+j]) return(-1); +#if 0 + printf("Decoded B %llx (crc %x,B>>payloadBits %x)\n",B,crc24c((uint8_t*)&B,polarParams->payloadBits)>>8, + (uint32_t)(B>>polarParams->payloadBits)); +#endif + + if ((uint64_t)(crc24c((uint8_t*)&B,polarParams->payloadBits)>>8) == (B>>polarParams->payloadBits)) { + *((uint64_t *)out) = B & (((uint64_t)1<payloadBits)-1); + return(0); } - // pack into ceil(payloadBits/32) 32 bit words, lowest index in MSB - // nr_byte2bit_uint8_32_t(polarParams->nr_polar_A, polarParams->payloadBits, out); - nr_byte2bit_uint8_32_t(polarParams->nr_polar_B, polarParams->payloadBits, out); - return(0); + else return(-1); + } diff --git a/openair1/PHY/CODING/nrPolar_tools/nr_polar_defs.h b/openair1/PHY/CODING/nrPolar_tools/nr_polar_defs.h index 611fcf56c2..027ad07607 100644 --- a/openair1/PHY/CODING/nrPolar_tools/nr_polar_defs.h +++ b/openair1/PHY/CODING/nrPolar_tools/nr_polar_defs.h @@ -98,6 +98,7 @@ struct nrPolar_params { uint32_t crcBit; uint16_t *interleaving_pattern; + uint16_t *deinterleaving_pattern; uint16_t *rate_matching_pattern; const uint16_t *Q_0_Nminus1; int16_t *Q_I_N; @@ -110,7 +111,10 @@ struct nrPolar_params { uint8_t **crc_generator_matrix; //G_P uint8_t **G_N; uint64_t **G_N_tab; + int groupsize; + int *rm_tab; uint64_t cprime_tab[8][256]; + uint64_t B_tab[8][256]; uint32_t* crc256Table; uint8_t **extended_crc_generator_matrix; //lowercase: bits, Uppercase: Bits stored in bytes @@ -355,11 +359,11 @@ uint8_t **crc6_generator_matrix(uint16_t payloadSizeBits); //Also nr_polar_rate_matcher static inline void nr_polar_interleaver(uint8_t *input, - uint8_t *output, - uint16_t *pattern, - uint16_t size) + uint8_t *output, + uint16_t *pattern, + uint16_t size) { - for (int i=0; iidx == 0){//PBCH - nr_bit2byte_uint32_8_t(in, polarParams->payloadBits, polarParams->nr_polar_A); + uint64_t B = (((uint64_t)*in)&((((uint64_t)1)<<32)-1)) | (((uint64_t)crc24c((uint8_t*)in,polarParams->payloadBits)>>8)<payloadBits); +#ifdef DEBUG_POLAR_ENCODER + printf("polar_B %llx (crc %x)\n",B,crc24c((uint8_t*)in,polarParams->payloadBits)>>8); +#endif + nr_bit2byte_uint32_8_t((uint32_t*)&B, polarParams->K, polarParams->nr_polar_B); /* * Bytewise operations */ //Calculate CRC. + /* nr_matrix_multiplication_uint8_t_1D_uint8_t_2D(polarParams->nr_polar_A, polarParams->crc_generator_matrix, polarParams->nr_polar_crc, @@ -58,11 +63,23 @@ void polar_encoder(uint32_t *in, for (uint8_t i = 0; i < polarParams->crcParityBits; i++) polarParams->nr_polar_crc[i] = (polarParams->nr_polar_crc[i] % 2); + //Attach CRC to the Transport Block. (a to b) for (uint16_t i = 0; i < polarParams->payloadBits; i++) polarParams->nr_polar_B[i] = polarParams->nr_polar_A[i]; for (uint16_t i = polarParams->payloadBits; i < polarParams->K; i++) - polarParams->nr_polar_B[i]= polarParams->nr_polar_crc[i-(polarParams->payloadBits)]; + polarParams->nr_polar_B[i]= 0;//polarParams->nr_polar_crc[i-(polarParams->payloadBits)]; + */ + + uint64_t B2=0; + for (int i = 0;iK;i++) B2 = B2 | ((uint64_t)polarParams->nr_polar_B[i] << i); + printf("polar_B %llx\n",B2); + /* for (int j=0;jcrcParityBits;j++) { + for (int i=0;ipayloadBits;i++) + printf("%1d.%1d+",polarParams->crc_generator_matrix[i][j],polarParams->nr_polar_A[i]); + printf(" => %d\n",polarParams->nr_polar_crc[j]); + }*/ + } else { //UCI } @@ -73,6 +90,15 @@ void polar_encoder(uint32_t *in, polarParams->interleaving_pattern, polarParams->K); + + uint64_t Cprime=0; + for (int i = 0;iK;i++) { + Cprime = Cprime | ((uint64_t)polarParams->nr_polar_CPrime[i] << i); + if (polarParams->nr_polar_CPrime[i] == 1) printf("pos %d : %llx\n",i,Cprime); + } +#ifdef DEBUG_POLAR_ENCODER + printf("polar_Cprime %llx\n",Cprime); +#endif //Bit insertion (c' to u) nr_polar_bit_insertion(polarParams->nr_polar_CPrime, polarParams->nr_polar_U, @@ -83,6 +109,9 @@ void polar_encoder(uint32_t *in, polarParams->n_pc); //Encoding (u to d) + /* memset(polarParams->nr_polar_U,0,polarParams->N); + polarParams->nr_polar_U[247]=1; + polarParams->nr_polar_U[253]=1;*/ nr_matrix_multiplication_uint8_t_1D_uint8_t_2D(polarParams->nr_polar_U, polarParams->G_N, polarParams->nr_polar_D, @@ -91,6 +120,14 @@ void polar_encoder(uint32_t *in, for (uint16_t i = 0; i < polarParams->N; i++) polarParams->nr_polar_D[i] = (polarParams->nr_polar_D[i] % 2); + uint64_t D[8]; + memset((void*)D,0,8*sizeof(int64_t)); +#ifdef DEBUG_POLAR_ENCODER + for (int i=0;iN;i++) D[i/64] |= ((uint64_t)polarParams->nr_polar_D[i])<<(i&63); + printf("D %llx,%llx,%llx,%llx,%llx,%llx,%llx,%llx\n", + D[0],D[1],D[2],D[3],D[4],D[5],D[6],D[7]); +#endif + //Rate matching //Sub-block interleaving (d to y) and Bit selection (y to e) nr_polar_interleaver(polarParams->nr_polar_D, @@ -316,6 +353,15 @@ void polar_encoder_timing(uint32_t *in, (timeEncoderByte2Bit.diff_now/(cpuFreqGHz*1000.0))); } +static inline void polar_rate_matching(t_nrPolar_paramsPtr polarParams,void *in,void *out) __attribute__((always_inline)); + +static inline void polar_rate_matching(t_nrPolar_paramsPtr polarParams,void *in,void *out) { + + if (polarParams->groupsize == 8) + for (int i=0;iencoderLength>>3;i++) ((uint8_t*)out)[i] = ((uint8_t *)in)[polarParams->rm_tab[i]]; + else + for (int i=0;iencoderLength>>4;i++) ((uint16_t*)out)[i] = ((uint16_t *)in)[polarParams->rm_tab[i]]; +} void build_polar_tables(t_nrPolar_paramsPtr polarParams) { @@ -326,6 +372,7 @@ void build_polar_tables(t_nrPolar_paramsPtr polarParams) { AssertFatal(polarParams->K < 65, "K = %d > 64, is not supported yet\n",polarParams->K); int bit_i,ip; + int numbytes = polarParams->K>>3; int residue = polarParams->K&7; int numbits; @@ -333,46 +380,89 @@ void build_polar_tables(t_nrPolar_paramsPtr polarParams) { for (int byte=0;byteK>>3)) numbits=8; else numbits=residue; - for (int i=0;iinterleaving_pattern[(8*byte)+i]; - printf("input (%d,%d) %d ip %d\n",byte,i,(8*byte)+i,ip); - AssertFatal(ip<64,"ip = %d\n",ip); - for (int val=0;val<256;val++) { + for (int val=0;val<256;val++) { + polarParams->cprime_tab[byte][val] = 0; + for (int i=0;ideinterleaving_pattern[(8*byte)+i]; + AssertFatal(ip<64,"ip = %d\n",ip); bit_i=(val>>i)&1; - polarParams->cprime_tab[byte][val] |= (bit_i<interleaving_pattern[(8*byte)+i]); + polarParams->cprime_tab[byte][val] |= (((uint64_t)bit_i)<cprime_tab[byte][val]); - } - + AssertFatal(polarParams->N==512,"N = %d, not done yet\n",polarParams->N); // build G bit vectors for information bit positions and convert the bit as bytes tables in nr_polar_kronecker_power_matrices.c to 64 bit packed vectors. // keep only rows of G which correspond to information/crc bits polarParams->G_N_tab = (uint64_t**)malloc(polarParams->K * sizeof(int64_t*)); - for (int i=0;iK;i++) { - polarParams->G_N_tab[i] = (uint64_t*)memalign(32,(polarParams->N/64)*sizeof(uint64_t)); - memset((void*)polarParams->G_N_tab[i],0,(polarParams->N/64)*sizeof(uint64_t)); - for (int j=0;jN;j++) - polarParams->G_N_tab[i][j/64] |= polarParams->G_N[polarParams->Q_I_N[i]][j]<<(j&63); + int k=0; + for (int i=0;iN;i++) { + if (polarParams->information_bit_pattern[i] > 0) { + polarParams->G_N_tab[k] = (uint64_t*)memalign(32,(polarParams->N/64)*sizeof(uint64_t)); + memset((void*)polarParams->G_N_tab[k],0,(polarParams->N/64)*sizeof(uint64_t)); + for (int j=0;jN;j++) + polarParams->G_N_tab[k][j/64] |= ((uint64_t)polarParams->G_N[i][j])<<(j&63); +#ifdef DEBUG_POLAR_ENCODER + printf("Bit %d Selecting row %d of G : ",k,i); + for (int j=0;jN;j+=4) printf("%1x",polarParams->G_N[i][j]+(polarParams->G_N[i][j+1]*2)+(polarParams->G_N[i][j+2]*4)+(polarParams->G_N[i][j+3]*8)); + printf("\n"); +#endif + k++; + } } + + // rate matching table + int iplast=polarParams->rate_matching_pattern[0]; + int ccnt=0; + int groupcnt=0; + int firstingroup_out=0; + int firstingroup_in=iplast; + int mingroupsize = 1024; + // compute minimum group size of rate-matching pattern + for (int outpos=1; outposencoderLength; outpos++) { + + ip=polarParams->rate_matching_pattern[outpos]; + if ((ip - iplast) == 1) ccnt++; + else { + groupcnt++; + printf("group %d (size %d): (%d:%d) => (%d:%d)\n",groupcnt,ccnt+1, + firstingroup_in,firstingroup_in+ccnt, + firstingroup_out,firstingroup_out+ccnt); + if ((ccnt+1)groupsize=mingroupsize; + int shift=3; + if (mingroupsize == 16) shift=4; + polarParams->rm_tab=(int*)malloc(sizeof(int)*polarParams->encoderLength/mingroupsize); + // rerun again to create groups + int tcnt; + for (int outpos=0;outposencoderLength; outpos+=mingroupsize,tcnt++) + polarParams->rm_tab[tcnt] = polarParams->rate_matching_pattern[outpos]>>shift; + } void polar_encoder_fast(int64_t *A, - int64_t *D, - int bitlen, + uint32_t *out, int32_t crcmask, t_nrPolar_paramsPtr polarParams) { AssertFatal(polarParams->K > 32, "K = %d < 33, is not supported yet\n",polarParams->K); AssertFatal(polarParams->K < 65, "K = %d > 64, is not supported yet\n",polarParams->K); - uint64_t B,Cprime; - + uint64_t B=0,Cprime=0; + int bitlen = polarParams->payloadBits; // append crc - B = *A | ((crcmask^crc24c(A,bitlen))<crcParityBits == 24,"support for 24-bit crc only for now\n"); + B = ((*A)&((((uint64_t)1)<>8)))<cprime_tab[0][Bbyte[0]] | @@ -384,11 +474,38 @@ void polar_encoder_fast(int64_t *A, polarParams->cprime_tab[6][Bbyte[6]] | polarParams->cprime_tab[7][Bbyte[7]]; + +#ifdef DEBUG_POLAR_ENCODER + printf("A %llx B %llx Cprime %llx (payload bits %d,crc %x)\n", + (unsigned long long)((*A)&((((uint64_t)1)<payloadBits, + crc24c((uint8_t*)A,bitlen)); +#endif + /* printf("Bbytes : %x.%x.%x.%x.%x.%x.%x.%x\n",Bbyte[0],Bbyte[1],Bbyte[2],Bbyte[3],Bbyte[4],Bbyte[5],Bbyte[6],Bbyte[7]); + printf("%llx,%llx,%llx,%llx,%llx,%llx,%llx,%llx\n",polarParams->cprime_tab[0][Bbyte[0]] , + polarParams->cprime_tab[1][Bbyte[1]] , + polarParams->cprime_tab[2][Bbyte[2]] , + polarParams->cprime_tab[3][Bbyte[3]] , + polarParams->cprime_tab[4][Bbyte[4]] , + polarParams->cprime_tab[5][Bbyte[5]] , + polarParams->cprime_tab[6][Bbyte[6]] , + polarParams->cprime_tab[7][Bbyte[7]]);*/ // now do Gu product (here using 64-bit XORs, we can also do with SIMD after) // here we're reading out the bits LSB -> MSB, is this correct w.r.t. 3GPP ? uint64_t Cprime_i = -(Cprime & 1); // this converts bit 0 as, 0 => 0000x00, 1 => 1111x11 + /* printf("%llx Cprime_0 (%llx) G %llx,%llx,%llx,%llx,%llx,%llx,%llx,%llx\n",Cprime_i,Cprime &1, + polarParams->G_N_tab[0][0], + polarParams->G_N_tab[0][1], + polarParams->G_N_tab[0][2], + polarParams->G_N_tab[0][3], + polarParams->G_N_tab[0][4], + polarParams->G_N_tab[0][5], + polarParams->G_N_tab[0][6], + polarParams->G_N_tab[0][7]);*/ + uint64_t D[8]; + D[0] = Cprime_i & polarParams->G_N_tab[0][0]; D[1] = Cprime_i & polarParams->G_N_tab[0][1]; D[2] = Cprime_i & polarParams->G_N_tab[0][2]; @@ -397,9 +514,22 @@ void polar_encoder_fast(int64_t *A, D[5] = Cprime_i & polarParams->G_N_tab[0][5]; D[6] = Cprime_i & polarParams->G_N_tab[0][6]; D[7] = Cprime_i & polarParams->G_N_tab[0][7]; - for (int i=1;iK;i++) { Cprime_i = -((Cprime>>i)&1); +#ifdef DEBUG_POLAR_ENCODER + printf("%llx Cprime_%d (%llx) G %llx,%llx,%llx,%llx,%llx,%llx,%llx,%llx\n", + Cprime_i,i,(Cprime>>i) &1, + polarParams->G_N_tab[i][0], + polarParams->G_N_tab[i][1], + polarParams->G_N_tab[i][2], + polarParams->G_N_tab[i][3], + polarParams->G_N_tab[i][4], + polarParams->G_N_tab[i][5], + polarParams->G_N_tab[i][6], + polarParams->G_N_tab[i][7]); +#endif + D[0] ^= (Cprime_i & polarParams->G_N_tab[i][0]); D[1] ^= (Cprime_i & polarParams->G_N_tab[i][1]); D[2] ^= (Cprime_i & polarParams->G_N_tab[i][2]); @@ -409,8 +539,17 @@ void polar_encoder_fast(int64_t *A, D[6] ^= (Cprime_i & polarParams->G_N_tab[i][6]); D[7] ^= (Cprime_i & polarParams->G_N_tab[i][7]); } +#ifdef DEBUG_POLAR_ENCODER + printf("D %llx,%llx,%llx,%llx,%llx,%llx,%llx,%llx\n", + D[0], + D[1], + D[2], + D[3], + D[4], + D[5], + D[6], + D[7]); +#endif - // Rate matching on the 8 64-bit D bit-strings should be performed more or less like - // The interleaving on the single 64-bit input in the first step. We just need 64 lookup tables I guess, and they will have large entries - + polar_rate_matching(polarParams,(void*)D,(void*)out); } diff --git a/openair1/PHY/CODING/nr_polar_init.c b/openair1/PHY/CODING/nr_polar_init.c index 8e3dea83ed..0e564ed22a 100644 --- a/openair1/PHY/CODING/nr_polar_init.c +++ b/openair1/PHY/CODING/nr_polar_init.c @@ -36,6 +36,11 @@ #include "PHY/CODING/nrPolar_tools/nr_polar_pbch_defs.h" #include "PHY/NR_TRANSPORT/nr_dci.h" +static int intcmp(const void *p1,const void *p2) { + + return(*(int16_t*)p1 > *(int16_t*)p2); +} + void nr_polar_init(t_nrPolar_paramsPtr *polarParams, int8_t messageType, uint16_t messageLength, @@ -115,6 +120,10 @@ void nr_polar_init(t_nrPolar_paramsPtr *polarParams, newPolarInitNode->i_il, newPolarInitNode->interleaving_pattern); + newPolarInitNode->deinterleaving_pattern = malloc(sizeof(uint16_t) * newPolarInitNode->K); + for (int i=0;iK;i++) + newPolarInitNode->deinterleaving_pattern[newPolarInitNode->interleaving_pattern[i]] = i; + newPolarInitNode->rate_matching_pattern = malloc(sizeof(uint16_t) * newPolarInitNode->encoderLength); uint16_t *J = malloc(sizeof(uint16_t) * newPolarInitNode->N); nr_polar_rate_matching_pattern(newPolarInitNode->rate_matching_pattern, @@ -139,7 +148,9 @@ void nr_polar_init(t_nrPolar_paramsPtr *polarParams, newPolarInitNode->N, newPolarInitNode->encoderLength, newPolarInitNode->n_pc); - + // sort the Q_I_N array in ascending order (first K positions) + qsort((void*)newPolarInitNode->Q_I_N,newPolarInitNode->K,sizeof(int16_t),intcmp); + newPolarInitNode->channel_interleaver_pattern = malloc(sizeof(uint16_t) * newPolarInitNode->encoderLength); nr_polar_channel_interleaver_pattern(newPolarInitNode->channel_interleaver_pattern, newPolarInitNode->i_bil, @@ -149,6 +160,8 @@ void nr_polar_init(t_nrPolar_paramsPtr *polarParams, build_decoder_tree(newPolarInitNode); build_polar_tables(newPolarInitNode); + init_polar_deinterleaver_table(newPolarInitNode); + printf("decoder tree nodes %d\n",newPolarInitNode->tree.num_nodes); } else {