diff --git a/openair1/PHY/CODING/TESTBENCH/polartest.c b/openair1/PHY/CODING/TESTBENCH/polartest.c index cd280c236e..266f829efa 100644 --- a/openair1/PHY/CODING/TESTBENCH/polartest.c +++ b/openair1/PHY/CODING/TESTBENCH/polartest.c @@ -91,11 +91,12 @@ int main(int argc, char *argv[]) case 'L': aggregation_level=atoi(optarg); - if (aggregation_level != 1 && aggregation_level != 2 && aggregation_level != 4 && aggregation_level != 8 && aggregation_level != 16) { - printf("Illegal aggregation level %d \n",aggregation_level); - exit(-1); - } - break; + if (aggregation_level != 1 && aggregation_level != 2 && aggregation_level != 4 && aggregation_level != 8 + && aggregation_level != 16) { + printf("Illegal aggregation level %d \n", aggregation_level); + exit(-1); + } + break; case 'k': testLength=atoi(optarg); @@ -106,9 +107,10 @@ int main(int argc, char *argv[]) break; case 'h': - printf("./polartest\nOptions\n-h Print this help\n-s SNRstart (dB)\n-d SNRinc (dB)\n-f SNRstop (dB)\n-m [0=PBCH|1=DCI|2=UCI]\n" - "-i Number of iterations\n-l decoderListSize\n-q Flag for optimized coders usage\n-F Flag for test results logging\n" - "-L aggregation level (for DCI)\n-k packet_length (bits) for DCI/UCI\n"); + printf( + "./polartest\nOptions\n-h Print this help\n-s SNRstart (dB)\n-d SNRinc (dB)\n-f SNRstop (dB)\n-m [0=PBCH|1=DCI|2=UCI]\n" + "-i Number of iterations\n-l decoderListSize\n-q Flag for optimized coders usage\n-F Flag for test results logging\n" + "-L aggregation level (for DCI)\n-k packet_length (bits) for DCI/UCI\n"); exit(-1); break; @@ -186,7 +188,7 @@ int main(int argc, char *argv[]) double channelOutput[coderLength]; //add noise int16_t channelOutput_int16[coderLength]; - t_nrPolar_params *currentPtr = nr_polar_params(polarMessageType, testLength, aggregation_level, true); + t_nrPolar_params *currentPtr = nr_polar_params(polarMessageType, testLength, aggregation_level); #ifdef DEBUG_DCI_POLAR_PARAMS uint32_t dci_pdu[4]; @@ -283,30 +285,37 @@ int main(int argc, char *argv[]) channelOutput[i] = modulatedInput[i] + (gaussdouble(0.0,1.0) * (1/sqrt(2*SNR_lin))); if (decoder_int16==1) { - if (channelOutput[i] > 15) channelOutput_int16[i] = 127; - else if (channelOutput[i] < -16) channelOutput_int16[i] = -128; - else channelOutput_int16[i] = (int16_t) (8*channelOutput[i]); - } + if (channelOutput[i] > 15) + channelOutput_int16[i] = 127; + else if (channelOutput[i] < -16) + channelOutput_int16[i] = -128; + else + channelOutput_int16[i] = (int16_t)(8 * channelOutput[i]); + } } start_meas(&timeDecoder); if (decoder_int16==1) { - decoderState = polar_decoder_int16(channelOutput_int16, (uint64_t *)estimatedOutput, 0, - polarMessageType, testLength, aggregation_level); + decoderState = polar_decoder_int16(channelOutput_int16, + (uint64_t *)estimatedOutput, + 0, + polarMessageType, + testLength, + aggregation_level); } else { //0 --> PBCH, 1 --> DCI, -1 --> UCI if (polarMessageType == 0) { - decoderState = polar_decoder(channelOutput, - estimatedOutput, - decoderListSize, - polarMessageType, testLength, aggregation_level); - } else if (polarMessageType == 1) { - decoderState = polar_decoder_dci(channelOutput, - estimatedOutput, - decoderListSize, - rnti, - polarMessageType, testLength, aggregation_level); - } + decoderState = + polar_decoder(channelOutput, estimatedOutput, decoderListSize, polarMessageType, testLength, aggregation_level); + } else if (polarMessageType == 1) { + decoderState = polar_decoder_dci(channelOutput, + estimatedOutput, + decoderListSize, + rnti, + polarMessageType, + testLength, + aggregation_level); + } } stop_meas(&timeDecoder); @@ -332,7 +341,12 @@ int main(int argc, char *argv[]) if (nBitError>0) blockErrorState=1; #ifdef DEBUG_POLARTEST for (int i = 0; i < testArrayLength; i++) - printf("[polartest/decoderState=%u] testInput[%d]=0x%08x, estimatedOutput[%d]=0x%08x\n",decoderState, i, testInput[i], i, estimatedOutput[i]); + printf("[polartest/decoderState=%u] testInput[%d]=0x%08x, estimatedOutput[%d]=0x%08x\n", + decoderState, + i, + testInput[i], + i, + estimatedOutput[i]); #endif //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 5704a9e0d4..1d7e7e8373 100644 --- a/openair1/PHY/CODING/nrPolar_tools/nr_polar_decoder.c +++ b/openair1/PHY/CODING/nrPolar_tools/nr_polar_decoder.c @@ -66,7 +66,7 @@ int8_t polar_decoder(double *input, uint8_t aggregation_level ) { - t_nrPolar_params *polarParams=nr_polar_params(messageType, messageLength, aggregation_level, true); + t_nrPolar_params *polarParams = nr_polar_params(messageType, messageLength, aggregation_level); //Assumes no a priori knowledge. uint8_t bit[polarParams->N][polarParams->n + 1][2 * listSize]; memset(bit, 0, sizeof bit); @@ -329,7 +329,7 @@ int8_t polar_decoder_dci(double *input, int8_t messageType, uint16_t messageLength, uint8_t aggregation_level ) { - t_nrPolar_params *polarParams=nr_polar_params(messageType, messageLength, aggregation_level, true); + t_nrPolar_params *polarParams = nr_polar_params(messageType, messageLength, aggregation_level); uint8_t bit[polarParams->N][polarParams->n+1][2*listSize]; memset(bit,0,sizeof bit); @@ -595,25 +595,17 @@ int8_t polar_decoder_dci(double *input, void init_polar_deinterleaver_table(t_nrPolar_params *polarParams) { AssertFatal(polarParams->K > 17, "K = %d < 18, is not allowed\n",polarParams->K); AssertFatal(polarParams->K < 129, "K = %d > 128, is not supported yet\n",polarParams->K); - int bit_i,ip,ipmod64; - int numbytes = polarParams->K>>3; - int residue = polarParams->K & 7; - - if (residue > 0) - numbytes++; - + int numbytes = (polarParams->K + 7) / 8; for (int byte=0; byteK >> 3) ? 8 : residue; + int numbits = byte < (polarParams->K >> 3) ? 8 : polarParams->K & 7; - for (int i=0; iK - 1 - polarParams->interleaving_pattern[(8 * byte) + i]; - ipmod64 = ip&63; - AssertFatal(ip<128,"ip = %d\n",ip); - + int ip = polarParams->K - 1 - polarParams->interleaving_pattern[(8 * byte) + bit]; + int ipmod64 = ip & 63; + AssertFatal(ip < 128, "ip = %d\n", ip); for (int val=0; val<256; val++) { - bit_i=(val>>i)&1; - + int bit_i = (val >> bit) & 1; if (ip < 64) polarParams->B_tab0[byte][val] |= ((uint64_t)bit_i) << ipmod64; else @@ -623,6 +615,64 @@ void init_polar_deinterleaver_table(t_nrPolar_params *polarParams) { } } +static inline void nr_polar_rate_matching_int16(int16_t *input, + int16_t *output, + const uint16_t *rmp, + const uint16_t K, + const uint16_t N, + const uint16_t E, + const uint8_t i_bil) +{ + if (E >= N) { // repetition + memset(output, 0, N * sizeof(*output)); + for (int i = 0; i <= E - 1; i++) + output[rmp[i]] += input[i]; + } else { + if ((K / (double)E) <= (7.0 / 16)) + memset(output, 0, N * sizeof(*output)); // puncturing + else { // shortening + for (int i = 0; i <= N - 1; i++) + output[i] = 32767; // instead of INFINITY, to prevent [-Woverflow] + } + + for (int i = 0; i <= E - 1; i++) + output[rmp[i]] = input[i]; + } +} + +static inline void nr_polar_info_extraction_from_u(uint64_t *Cprime, + const uint8_t *u, + const uint8_t *information_bit_pattern, + const uint8_t *parity_check_bit_pattern, + uint16_t N, + uint8_t n_pc) +{ + int k = 0; + + if (n_pc > 0) { + for (int n = 0; n < N; n++) { + if (information_bit_pattern[n] == 1) { + if (parity_check_bit_pattern[n] == 0) { + int k1 = k >> 6; + int k2 = k - (k1 << 6); + Cprime[k1] |= (uint64_t)u[n] << k2; + k++; + } + } + } + + } else { + for (int n = 0; n < N; n++) { + if (information_bit_pattern[n] == 1) { + int k1 = k >> 6; + int k2 = k - (k1 << 6); + Cprime[k1] |= (uint64_t)u[n] << k2; + k++; + } + } + } +} + uint32_t polar_decoder_int16(int16_t *input, uint64_t *out, uint8_t ones_flag, @@ -630,12 +680,12 @@ uint32_t polar_decoder_int16(int16_t *input, uint16_t messageLength, uint8_t aggregation_level) { - t_nrPolar_params *polarParams=nr_polar_params(messageType, messageLength, aggregation_level, true); - + t_nrPolar_params *polarParams = nr_polar_params(messageType, messageLength, aggregation_level); + const uint N = polarParams->N; #ifdef POLAR_CODING_DEBUG printf("\nRX\n"); printf("rm:"); - for (int i = 0; i < polarParams->N; i++) { + for (int i = 0; i < N; i++) { if (i % 4 == 0) { printf(" "); } @@ -644,25 +694,28 @@ uint32_t polar_decoder_int16(int16_t *input, printf("\n"); #endif - int16_t d_tilde[polarParams->N]; - nr_polar_rate_matching_int16(input, + int16_t d_tilde[N]; + const uint E = polarParams->encoderLength; + int16_t inbis[E]; + int16_t *input_deinterleaved; + if (polarParams->i_bil) { + for (int i = 0; i < E; i++) + inbis[i] = input[polarParams->i_bil_pattern[i]]; + input_deinterleaved = inbis; + } else { + input_deinterleaved = input; + } + + nr_polar_rate_matching_int16(input_deinterleaved, d_tilde, polarParams->rate_matching_pattern, polarParams->K, - polarParams->N, - polarParams->encoderLength, + N, + E, polarParams->i_bil); - - for (int i=0; iN; i++) { - if (d_tilde[i] < -128) - d_tilde[i] = -128; - else if (d_tilde[i] > 127) - d_tilde[i] = 128; - } - #ifdef POLAR_CODING_DEBUG printf("d: "); - for (int i = 0; i < polarParams->N; i++) { + for (int i = 0; i < N; i++) { if (i % 4 == 0) { printf(" "); } @@ -670,15 +723,23 @@ uint32_t polar_decoder_int16(int16_t *input, } printf("\n"); #endif - - memcpy(polarParams->tree.root->alpha, d_tilde, sizeof(d_tilde)); - uint8_t nr_polar_U[polarParams->N]; + uint8_t nr_polar_U[N]; memset(nr_polar_U, 0, sizeof(nr_polar_U)); - generic_polar_decoder(polarParams, polarParams->tree.root, nr_polar_U); - + static uint64_t cnt = 0, timeTree = 0, timeDecoder = 0; + uint64_t a = rdtsc_oai(); + decoder_tree_t tree; + build_decoder_tree(&tree, polarParams); + uint64_t b = rdtsc_oai(); + memcpy(treeAlpha(tree.root), d_tilde, sizeof(d_tilde)); + generic_polar_decoder(polarParams, tree.root, nr_polar_U); + uint64_t c = rdtsc_oai(); + timeTree += b - a; + timeDecoder += c - b; + if (cnt++ % 1000 == 0) + printf("tree: %ld, dec %ld\n", timeTree / (cnt), timeDecoder / (cnt)); #ifdef POLAR_CODING_DEBUG printf("u: "); - for (int i = 0; i < polarParams->N; i++) { + for (int i = 0; i < N; i++) { if (i % 4 == 0) { printf(" "); } @@ -693,7 +754,7 @@ uint32_t polar_decoder_int16(int16_t *input, nr_polar_U, polarParams->information_bit_pattern, polarParams->parity_check_bit_pattern, - polarParams->N, + N, polarParams->n_pc); #ifdef POLAR_CODING_DEBUG @@ -718,17 +779,30 @@ uint32_t polar_decoder_int16(int16_t *input, | polarParams->B_tab0[3][Cprimebyte[3]] | polarParams->B_tab0[4][Cprimebyte[4]] | polarParams->B_tab0[5][Cprimebyte[5]] | polarParams->B_tab0[6][Cprimebyte[6]] | polarParams->B_tab0[7][Cprimebyte[7]]; } else if (polarParams->K<129) { - int len = polarParams->K/8; - - if ((polarParams->K & 7) > 0) - len++; - - for (int k=0; kB_tab0[k][Cprimebyte[k]]; B[1] |= polarParams->B_tab1[k][Cprimebyte[k]]; } } + uint128_t Cprime128 = *(uint128_t *)Cprime; + uint128_t res = 0; + uint deinterleaving_pattern[polarParams->K]; + + for (int i = 0; i < polarParams->K; i++) + deinterleaving_pattern[polarParams->interleaving_pattern[i]] = i; + for (int i = 0; i < polarParams->K; i++) { + uint128_t bit = (Cprime128 >> i) & 1; + res |= bit << (polarParams->K - 1 - deinterleaving_pattern[i]); + } + uint128_t B128 = *(uint128_t *)B; + printf("old:(k=%d)", polarParams->K); + for (int i = 0; i < polarParams->K; i++) + printf("%lld", (B128 >> i) & 1); + printf("\nnew:(k=%d)", polarParams->K); + for (int i = 0; i < polarParams->K; i++) + printf("%lld", (res >> i) & 1); + printf("\n\n"); #ifdef POLAR_CODING_DEBUG int B_array = (polarParams->K + 63) >> 6; int n_start = (B_array << 6) - polarParams->K; diff --git a/openair1/PHY/CODING/nrPolar_tools/nr_polar_decoding_tools.c b/openair1/PHY/CODING/nrPolar_tools/nr_polar_decoding_tools.c index 8180f5ebeb..aa7f835291 100644 --- a/openair1/PHY/CODING/nrPolar_tools/nr_polar_decoding_tools.c +++ b/openair1/PHY/CODING/nrPolar_tools/nr_polar_decoding_tools.c @@ -149,100 +149,79 @@ void updatePathMetric2(double *pathMetric, pathMetric[i] = tempPM[(i - listSize)] + log(1 + exp(multiplier * llr[row][0][(i - listSize)])); // eq. (11b) } -decoder_node_t *new_decoder_node(int first_leaf_index, int level) { - - decoder_node_t *node=(decoder_node_t *)malloc(sizeof(decoder_node_t)); - - node->first_leaf_index=first_leaf_index; - node->level=level; - node->Nv = 1<leaf = 0; - node->left=(decoder_node_t *)NULL; - node->right=(decoder_node_t *)NULL; - node->all_frozen=0; - node->alpha = (int16_t*)malloc16(node->Nv*sizeof(int16_t)); - node->beta = (int16_t*)malloc16(node->Nv*sizeof(int16_t)); - memset((void*)node->beta,-1,node->Nv*sizeof(int16_t)); - +static inline decoder_node_t *new_decoder_node(simde__m256i **buffer, + const int level, + const int first_leaf_index, + const bool leaf, + const bool frozen) +{ + int leaf_sz = 1 << level; + // we will use SIMD128 minimum + leaf_sz = (leaf_sz + 7) & ~7; + if (leaf_sz > 15) // we will use SIMD256 + leaf_sz = (leaf_sz + 15) & ~15; + const int tree_sz = (sizeof(decoder_node_t) + 31) & ~31; + decoder_node_t *node = (decoder_node_t *)*buffer; + *buffer = *buffer + (tree_sz + leaf_sz * sizeof(int16_t) + leaf_sz + sizeof(**buffer) - 1) / sizeof(**buffer); + *node = (decoder_node_t){.first_leaf_index = first_leaf_index, + .level = level, + .leaf = leaf, + .all_frozen = frozen, + .alpha = tree_sz, + .beta = tree_sz + leaf_sz * sizeof(int16_t), + .betaInit = false}; return(node); } -decoder_node_t *add_nodes(int level, int first_leaf_index, t_nrPolar_params *polarParams) { - - int all_frozen_below = 1; - int Nv = 1<tree.num_nodes,Nv,level); -#endif - polarParams->tree.num_nodes++; +static inline decoder_node_t *add_nodes(decoder_tree_t *tree, + int level, + int first_leaf_index, + const uint8_t *information_bit_pattern, + simde__m256i **buffer) +{ if (level==0) { #ifdef DEBUG_NEW_IMPL - printf("leaf %d (%s)\n", first_leaf_index, polarParams->information_bit_pattern[first_leaf_index]==1 ? "information or crc" : "frozen"); + printf("leaf %d (%s)\n", first_leaf_index, information_bit_pattern[first_leaf_index] == 1 ? "information or crc" : "frozen"); #endif - new_node->leaf=1; - new_node->all_frozen = polarParams->information_bit_pattern[first_leaf_index]==0 ? 1 : 0; - return new_node; // this is a leaf node + return new_decoder_node(buffer, level, first_leaf_index, true, information_bit_pattern[first_leaf_index] == 0); } - for (int i=0;iinformation_bit_pattern[i+first_leaf_index]>0) { - all_frozen_below = 0; - break; - } + int Nv = 1 << level; + const uint8_t *ptr = information_bit_pattern + first_leaf_index; + const uint8_t *end = ptr + Nv; + bool all_frozen_below = true; + while (ptr < end && all_frozen_below) { + all_frozen_below = *ptr++ <= 0; } - if (all_frozen_below==0) - new_node->left = add_nodes(level - 1, first_leaf_index, polarParams); - else { -#ifdef DEBUG_NEW_IMPL - printf("aggregating frozen bits %d ... %d at level %d (%s)\n",first_leaf_index,first_leaf_index+Nv-1,level,((first_leaf_index/Nv)&1)==0?"left":"right"); -#endif - new_node->leaf=1; - new_node->all_frozen=1; + if (all_frozen_below) { + return new_decoder_node(buffer, level, first_leaf_index, true, true); } - if (all_frozen_below==0) - new_node->right = add_nodes(level - 1, first_leaf_index + (Nv / 2), polarParams); - -#ifdef DEBUG_NEW_IMPL - printf("new_node (%d): first_leaf_index %d, left %p, right %p\n",Nv,first_leaf_index,new_node->left,new_node->right); -#endif + decoder_node_t *new_node = new_decoder_node(buffer, level, first_leaf_index, false, false); + new_node->left = add_nodes(tree, level - 1, first_leaf_index, information_bit_pattern, buffer); + new_node->right = add_nodes(tree, level - 1, first_leaf_index + (Nv / 2), information_bit_pattern, buffer); return(new_node); } -void delete_nodes(decoder_node_t * n) { - if (n) { - if(n->left) - delete_nodes(n->left); - if(n->right) - delete_nodes(n->right); - free(n->alpha); - free(n->beta); - free(n); - } -} - -void delete_decoder_tree(t_nrPolar_params *polarParams) { - if (polarParams->tree.root) - delete_nodes(polarParams->tree.root); -} - -void build_decoder_tree(t_nrPolar_params *polarParams) +void build_decoder_tree(decoder_tree_t *tree, const t_nrPolar_params *pp) { - polarParams->tree.num_nodes=0; - polarParams->tree.root = add_nodes(polarParams->n,0,polarParams); + simde__m256i *buffer = tree->buffer; + tree->root = add_nodes(tree, pp->n, 0, pp->information_bit_pattern, &buffer); + AssertFatal(buffer < tree->buffer + sizeofArray(tree->buffer), + "Arbitrary size too small (also check arbitrary max size of the entire polar decoder) %ld instead of max %ld\n", + buffer - tree->buffer, + sizeofArray(tree->buffer)); #ifdef DEBUG_NEW_IMPL - printf("root : left %p, right %p\n",polarParams->tree.root->left,polarParams->tree.root->right); + printf("root : left %p, right %p\n", tree->root->left, tree->root->right); #endif } -static void applyFtoleft(const t_nrPolar_params *pp, decoder_node_t *node, uint8_t *output) +static inline void applyFtoleft(const t_nrPolar_params *pp, decoder_node_t *node, uint8_t *output) { - int16_t *alpha_v=node->alpha; - int16_t *alpha_l=node->left->alpha; - int16_t *betal = node->left->beta; - int16_t a,b,absa,absb,maska,maskb,minabs; + int16_t *alpha_v = treeAlpha(node); + int16_t *alpha_l = treeAlpha(node->left); + int8_t *betal = treeBeta(node->left); #ifdef DEBUG_NEW_IMPL printf("applyFtoleft %d, Nv %d (level %d,node->left (leaf %d, AF %d))\n",node->first_leaf_index,node->Nv,node->level,node->left->leaf,node->left->all_frozen); @@ -250,61 +229,59 @@ static void applyFtoleft(const t_nrPolar_params *pp, decoder_node_t *node, uint8 for (int i = 0; i < node->Nv; i++) printf("i%d (frozen %d): alpha_v[i] = %d\n", i, 1 - pp->information_bit_pattern[node->first_leaf_index + i], alpha_v[i]); #endif - + assert(node->level); + const int sz = 1 << (node->level - 1); if (node->left->all_frozen == 0) { - int avx2mod = (node->Nv/2)&15; + int avx2mod = sz & 15; if (avx2mod == 0) { - simde__m256i a256,b256,absa256,absb256,minabs256; - int avx2len = node->Nv/2/16; + int avx2len = sz / 16; // printf("avx2len %d\n",avx2len); for (int i=0;i> 15; + int16_t maskb = b >> 15; + int16_t absa = (a + maska) ^ maska; + int16_t absb = (b + maskb) ^ maskb; + int16_t minabs = absa < absb ? absa : absb; + alpha_l[i] = (maska ^ maskb) == 0 ? minabs : -minabs; + // printf("alphal[%d] %d (%d,%d)\n",i,alpha_l[i],a,b); + } } - else - { // equivalent scalar code to above, activated only on non x86/ARM architectures - for (int i=0;iNv/2;i++) { - a=alpha_v[i]; - b=alpha_v[i+(node->Nv/2)]; - maska=a>>15; - maskb=b>>15; - absa=(a+maska)^maska; - absb=(b+maskb)^maskb; - minabs = absaNv == 2) { // apply hard decision on left node - betal[0] = (alpha_l[0]>0) ? -1 : 1; + if (sz == 1) { // apply hard decision on left node + const int tmp = alpha_l[0] <= 0; + betal[0] = tmp * 2 - 1; + node->left->betaInit = true; #ifdef DEBUG_NEW_IMPL printf("betal[0] %d (%p)\n",betal[0],&betal[0]); #endif - output[node->first_leaf_index] = (1 + betal[0]) >> 1; + output[node->first_leaf_index] = tmp; #ifdef DEBUG_NEW_IMPL printf("Setting bit %d to %d (LLR %d)\n",node->first_leaf_index,(betal[0]+1)>>1,alpha_l[0]); #endif @@ -312,39 +289,47 @@ static void applyFtoleft(const t_nrPolar_params *pp, decoder_node_t *node, uint8 } } -static void applyGtoright(const t_nrPolar_params *pp, decoder_node_t *node, uint8_t *output) +static inline void applyGtoright(const t_nrPolar_params *pp, decoder_node_t *node, uint8_t *output) { - int16_t *alpha_v=node->alpha; - int16_t *alpha_r=node->right->alpha; - int16_t *betal = node->left->beta; - int16_t *betar = node->right->beta; + int16_t *alpha_v = treeAlpha(node); + int16_t *alpha_r = treeAlpha(node->right); + int8_t *betal = treeBeta(node->left); + int8_t *betar = treeBeta(node->right); #ifdef DEBUG_NEW_IMPL printf("applyGtoright %d, Nv %d (level %d), (leaf %d, AF %d)\n",node->first_leaf_index,node->Nv,node->level,node->right->leaf,node->right->all_frozen); #endif - - if (node->right->all_frozen == 0) { - int avx2mod = (node->Nv/2)&15; - if (avx2mod == 0) { - int avx2len = node->Nv/2/16; - - for (int i=0;ilevel); + const int sz = 1 << (node->level - 1); + if (node->right->all_frozen == 0) { + if (!node->left->betaInit) { + for (int i = 0; i < sz; i++) { + int temp_alpha_r = alpha_v[i + sz] + alpha_v[i]; + if (temp_alpha_r > SHRT_MAX) { + alpha_r[i] = SHRT_MAX; + } else if (temp_alpha_r < -SHRT_MAX) { + alpha_r[i] = -SHRT_MAX; + } else { + alpha_r[i] = temp_alpha_r; + } } - } - else if (avx2mod == 8) { - ((simde__m128i *)alpha_r)[0] = simde_mm_subs_epi16(((simde__m128i *)alpha_v)[1],simde_mm_sign_epi16(((simde__m128i *)alpha_v)[0],((simde__m128i *)betal)[0])); - } - else if (avx2mod == 4) { - ((simde__m64 *)alpha_r)[0] = simde_mm_subs_pi16(((simde__m64 *)alpha_v)[1],simde_mm_sign_pi16(((simde__m64 *)alpha_v)[0],((simde__m64 *)betal)[0])); - } - else - { - int temp_alpha_r; - for (int i = 0; i < node->Nv / 2; i++) { - temp_alpha_r = alpha_v[i + (node->Nv / 2)] - (betal[i] * alpha_v[i]); + } else { + int avx2mod = sz & 15; + if (avx2mod == 0) { + int avx2len = sz / 16; + + for (int i = 0; i < avx2len; i++) { + simde__m256i tmp = simde_mm256_sign_epi16(((simde__m256i *)alpha_v)[i], _mm256_cvtepi8_epi16(((simde__m128i *)betal)[i])); + ((simde__m256i *)alpha_r)[i] = + + simde_mm256_subs_epi16(((simde__m256i *)alpha_v)[i + avx2len], tmp); + } + } else if (avx2mod == 8) { + simde__m128i tmp = simde_mm_sign_epi16(((simde__m128i *)alpha_v)[0], _mm_cvtepi8_epi16(((simde__m128i *)betal)[0])); + ((simde__m128i *)alpha_r)[0] = simde_mm_subs_epi16(((simde__m128i *)alpha_v)[1], tmp); + } else { + for (int i = 0; i < sz; i++) { + int temp_alpha_r = alpha_v[i + sz] - (betal[i] * alpha_v[i]); if (temp_alpha_r > SHRT_MAX) { alpha_r[i] = SHRT_MAX; } else if (temp_alpha_r < -SHRT_MAX) { @@ -352,55 +337,56 @@ static void applyGtoright(const t_nrPolar_params *pp, decoder_node_t *node, uint } else { alpha_r[i] = temp_alpha_r; } - } + } } - if (node->Nv == 2) { // apply hard decision on right node - betar[0] = (alpha_r[0]>0) ? -1 : 1; - output[node->first_leaf_index + 1] = (1 + betar[0]) >> 1; + } + if (sz == 1) { // apply hard decision on right node + int tmp = alpha_r[0] <= 0; + betar[0] = tmp * 2 - 1; + node->right->betaInit = true; + output[node->first_leaf_index + 1] = tmp; + #ifdef DEBUG_NEW_IMPL printf("Setting bit %d to %d (LLR %d)\n",node->first_leaf_index+1,(betar[0]+1)>>1,alpha_r[0]); #endif - } + } } } -static const int16_t all1[16] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}; +static const int64_t all11[4] = {-1, -1, -1, -1}; -void computeBeta(const t_nrPolar_params *pp,decoder_node_t *node) { - - int16_t *betav = node->beta; - int16_t *betal = node->left->beta; - int16_t *betar = node->right->beta; +static inline void computeBeta(decoder_node_t *node) +{ + int8_t *betav = treeBeta(node); + int8_t *betal = treeBeta(node->left); + int8_t *betar = treeBeta(node->right); #ifdef DEBUG_NEW_IMPL printf("Computing beta @ level %d first_leaf_index %d (all_frozen %d)\n",node->level,node->first_leaf_index,node->left->all_frozen); #endif + assert(node->level); + const int sz = 1 << (node->level - 1); if (node->left->all_frozen==0) { // if left node is not aggregation of frozen bits - int avx2mod = (node->Nv/2)&15; - register simde__m256i allones=*((simde__m256i*)all1); + assert(node->left->betaInit && node->right->betaInit); + int avx2mod = sz & 31; if (avx2mod == 0) { - int avx2len = node->Nv/2/16; + int avx2len = sz / 16; for (int i=0;iNv/2;i++) { - betav[i] = (betal[i] != betar[i]) ? 1 : -1; - } - } + } else { + assert(node->right->betaInit); + memcpy(betav, betar, sz * sizeof(*betav)); + node->betaInit = true; } - else memcpy((void*)&betav[0],betar,(node->Nv/2)*sizeof(int16_t)); - memcpy((void*)&betav[node->Nv/2],betar,(node->Nv/2)*sizeof(int16_t)); + assert(node->right->betaInit); + memcpy(&betav[sz], betar, sz * sizeof(*betav)); + node->betaInit = true; } void generic_polar_decoder(const t_nrPolar_params *pp, decoder_node_t *node, uint8_t *nr_polar_U) @@ -415,5 +401,5 @@ void generic_polar_decoder(const t_nrPolar_params *pp, decoder_node_t *node, uin if (node->right->leaf == 0) generic_polar_decoder(pp, node->right, nr_polar_U); - computeBeta(pp, node); + computeBeta(node); } diff --git a/openair1/PHY/CODING/nrPolar_tools/nr_polar_defs.h b/openair1/PHY/CODING/nrPolar_tools/nr_polar_defs.h index 84b3241e68..82292fb8fe 100644 --- a/openair1/PHY/CODING/nrPolar_tools/nr_polar_defs.h +++ b/openair1/PHY/CODING/nrPolar_tools/nr_polar_defs.h @@ -63,18 +63,18 @@ static const uint8_t nr_polar_subblock_interleaver_pattern[32] = {0,1,2,4,3,5,6, typedef struct decoder_node_t_s { struct decoder_node_t_s *left; struct decoder_node_t_s *right; - int level; - int leaf; - int Nv; - int first_leaf_index; - int all_frozen; - int16_t *alpha; - int16_t *beta; + uint64_t level: 16; + uint64_t leaf: 16; + uint64_t first_leaf_index: 16; + uint64_t all_frozen: 1; + uint64_t betaInit: 1; + uint32_t alpha; + uint32_t beta; } decoder_node_t; typedef struct decoder_tree_t_s { decoder_node_t *root; - int num_nodes; + simde__m256i buffer[1024]; // seems enough but to be refined } decoder_tree_t; typedef struct nrPolar_params { @@ -100,6 +100,7 @@ typedef struct nrPolar_params { uint16_t *interleaving_pattern; uint16_t *rate_matching_pattern; + uint16_t *i_bil_pattern; const uint16_t *Q_0_Nminus1; int16_t *Q_I_N; int16_t *Q_F_N; @@ -110,13 +111,10 @@ typedef struct nrPolar_params { const uint8_t **G_N; int groupsize; int *rm_tab; - uint64_t cprime_tab0[32][256]; - uint64_t cprime_tab1[32][256]; - uint64_t B_tab0[32][256]; - uint64_t B_tab1[32][256]; - // lowercase: bits, Uppercase: Bits stored in bytes - // polar_encoder vectors - decoder_tree_t tree; + uint64_t cprime_tab0[16][256]; + uint64_t cprime_tab1[16][256]; + uint64_t B_tab0[16][256]; + uint64_t B_tab1[16][256]; } t_nrPolar_params; void polar_encoder(uint32_t *input, @@ -164,19 +162,23 @@ int8_t polar_decoder_dci(double *input, void generic_polar_decoder(const t_nrPolar_params *pp, decoder_node_t *node, uint8_t *nr_polar_U); -void computeBeta(const t_nrPolar_params *pp, - decoder_node_t *node); +static inline int16_t *treeAlpha(decoder_node_t *node) +{ + return (int16_t *)((uint8_t *)node + node->alpha); +} -void build_decoder_tree(t_nrPolar_params *pp); +static inline int8_t *treeBeta(decoder_node_t *node) +{ + return (int8_t *)node + node->beta; +} + +void build_decoder_tree(decoder_tree_t *tree, const t_nrPolar_params *pp); void build_polar_tables(t_nrPolar_params *polarParams); void init_polar_deinterleaver_table(t_nrPolar_params *polarParams); void nr_polar_print_polarParams(void); -t_nrPolar_params *nr_polar_params (int8_t messageType, - uint16_t messageLength, - uint8_t aggregation_level, - int decoder_flag); +t_nrPolar_params *nr_polar_params(int8_t messageType, uint16_t messageLength, uint8_t aggregation_level); uint16_t nr_polar_aggregation_prime (uint8_t aggregation_level); @@ -207,14 +209,6 @@ void nr_polar_rate_matching(double *input, uint16_t N, uint16_t E); -void nr_polar_rate_matching_int16(int16_t *input, - int16_t *output, - const uint16_t *rmp, - const uint16_t K, - const uint16_t N, - const uint16_t E, - const uint8_t i_bil); - void nr_polar_interleaving_pattern(uint16_t K, uint8_t I_IL, uint16_t *PI_k_); @@ -256,13 +250,6 @@ void nr_polar_generate_u(uint64_t *u, void nr_polar_uxG(uint8_t const* u, size_t N, uint8_t* D); -void nr_polar_info_extraction_from_u(uint64_t *Cprime, - const uint8_t *u, - const uint8_t *information_bit_pattern, - const uint8_t *parity_check_bit_pattern, - uint16_t N, - uint8_t n_pc); - void nr_polar_bit_insertion(uint8_t *input, uint8_t *output, uint16_t N, @@ -328,7 +315,52 @@ static inline void nr_polar_deinterleaver(uint8_t *input, uint8_t *output, uint1 output[pattern[i]] = input[i]; } -void delete_decoder_tree(t_nrPolar_params *); +/* + * De-interleaving of coded bits implementation + * TS 138.212: Section 5.4.1.3 - Interleaving of coded bits + */ +static inline void nr_polar_rm_deinterleaving_lut(uint16_t *out, const uint E) +{ + int16_t in[E]; + for (int i = 0; i < E; i++) + in[i] = i; + int T = ceil((sqrt(8 * E + 1) - 1) / 2); + int v_tab[T][T]; + memset(v_tab, 0, sizeof(v_tab)); + int k = 0; + for (int i = 0; i < T; i++) { + for (int j = 0; j < T - i; j++) { + if (k < E) { + v_tab[i][j] = k + 1; + } + k++; + } + } + + int v[T][T]; + k = 0; + for (int j = 0; j < T; j++) { + for (int i = 0; i < T - j; i++) { + if (k < E && v_tab[i][j] != 0) { + v[i][j] = in[k]; + k++; + } else { + v[i][j] = INT_MAX; + } + } + } + + k = 0; + memset(out, 0, E * sizeof(*out)); + for (int i = 0; i < T; i++) { + for (int j = 0; j < T - i; j++) { + if (v[i][j] != INT_MAX) { + out[k] = v[i][j]; + k++; + } + } + } +} extern pthread_mutex_t PolarListMutex; static inline void polarReturn(t_nrPolar_params *polarParams) diff --git a/openair1/PHY/CODING/nrPolar_tools/nr_polar_encoder.c b/openair1/PHY/CODING/nrPolar_tools/nr_polar_encoder.c index c23513bdf6..285f936085 100644 --- a/openair1/PHY/CODING/nrPolar_tools/nr_polar_encoder.c +++ b/openair1/PHY/CODING/nrPolar_tools/nr_polar_encoder.c @@ -47,7 +47,7 @@ void polar_encoder(uint32_t *in, int8_t messageType, uint16_t messageLength, uint8_t aggregation_level) { - t_nrPolar_params *polarParams=nr_polar_params(messageType, messageLength, aggregation_level, false); + t_nrPolar_params *polarParams = nr_polar_params(messageType, messageLength, aggregation_level); uint8_t nr_polar_A[polarParams->payloadBits]; nr_bit2byte_uint32_8(in, polarParams->payloadBits, nr_polar_A); /* @@ -146,7 +146,7 @@ void polar_encoder_dci(uint32_t *in, int8_t messageType, uint16_t messageLength, uint8_t aggregation_level) { - t_nrPolar_params *polarParams=nr_polar_params(messageType, messageLength, aggregation_level, false); + t_nrPolar_params *polarParams = nr_polar_params(messageType, messageLength, aggregation_level); #ifdef DEBUG_POLAR_ENCODER_DCI printf("[polar_encoder_dci] in: [0]->0x%08x \t [1]->0x%08x \t [2]->0x%08x \t [3]->0x%08x\n", in[0], in[1], in[2], in[3]); @@ -463,7 +463,7 @@ void polar_encoder_fast(uint64_t *A, uint16_t messageLength, uint8_t aggregation_level) { - t_nrPolar_params *polarParams=nr_polar_params(messageType, messageLength, aggregation_level, false); + t_nrPolar_params *polarParams = nr_polar_params(messageType, messageLength, aggregation_level); #ifdef POLAR_CODING_DEBUG printf("polarParams->payloadBits = %i\n", polarParams->payloadBits); diff --git a/openair1/PHY/CODING/nrPolar_tools/nr_polar_interleaving_pattern.c b/openair1/PHY/CODING/nrPolar_tools/nr_polar_interleaving_pattern.c index 264ef9731d..97450d9dbf 100644 --- a/openair1/PHY/CODING/nrPolar_tools/nr_polar_interleaving_pattern.c +++ b/openair1/PHY/CODING/nrPolar_tools/nr_polar_interleaving_pattern.c @@ -33,7 +33,7 @@ #include "PHY/CODING/nrPolar_tools/nr_polar_defs.h" void nr_polar_interleaving_pattern(uint16_t K, uint8_t I_IL, uint16_t *PI_k_){ - uint K_IL_max = 164, k = 0; + uint K_IL_max = 164; uint8_t interleaving_pattern_table[164] = { 0, 2, 4, 7, 9, 14, 19, 20, 24, 25, 26, 28, 31, 34, 42, 45, 49, 50, 51, 53, 54, 56, 58, 59, 61, 62, 65, 66, 67, 69, 70, 71, 72, 76, 77, 81, 82, 83, 87, 88, 89, 91, 93, 95, 98, 101, 104, 106, @@ -44,10 +44,10 @@ void nr_polar_interleaving_pattern(uint16_t K, uint8_t I_IL, uint16_t *PI_k_){ 40, 146, 41, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163}; if (I_IL == 0) { - for (; k <= K - 1; k++) + for (int k = 0; k < K; k++) PI_k_[k] = k; } else { - for (int m = 0; m <= (K_IL_max - 1); m++) { + for (int m = 0, k = 0; m < K_IL_max; m++) { if (interleaving_pattern_table[m] >= (K_IL_max - K)) { PI_k_[k] = interleaving_pattern_table[m] - (K_IL_max - K); k++; diff --git a/openair1/PHY/CODING/nrPolar_tools/nr_polar_procedures.c b/openair1/PHY/CODING/nrPolar_tools/nr_polar_procedures.c index a4d3bb301e..1a1a3fb830 100644 --- a/openair1/PHY/CODING/nrPolar_tools/nr_polar_procedures.c +++ b/openair1/PHY/CODING/nrPolar_tools/nr_polar_procedures.c @@ -89,40 +89,6 @@ void nr_polar_generate_u(uint64_t *u, } } -void nr_polar_info_extraction_from_u(uint64_t *Cprime, - const uint8_t *u, - const uint8_t *information_bit_pattern, - const uint8_t *parity_check_bit_pattern, - uint16_t N, - uint8_t n_pc) -{ - int k = 0; - - if (n_pc > 0) { - for (int n = 0; n < N; n++) { - if (information_bit_pattern[n] == 1) { - if (parity_check_bit_pattern[n] == 0) { - int k1 = k >> 6; - int k2 = k - (k1 << 6); - Cprime[k1] |= (uint64_t)u[n] << k2; - k++; - } - } - } - - } else { - for (int n = 0; n < N; n++) { - if (information_bit_pattern[n] == 1) { - int k1 = k >> 6; - int k2 = k - (k1 << 6); - Cprime[k1] |= (uint64_t)u[n] << k2; - k++; - } - } - } -} - - static void encode_packed_byte(uint8_t* in_out) { @@ -442,76 +408,3 @@ void nr_polar_rate_matching(double *input, } } } - -/* - * De-interleaving of coded bits implementation - * TS 138.212: Section 5.4.1.3 - Interleaving of coded bits - */ -void nr_polar_rm_deinterleaving_cb(const int16_t *in, int16_t *out, const uint16_t E) -{ - int T = ceil((sqrt(8 * E + 1) - 1) / 2); - int v_tab[T][T]; - memset(v_tab, 0, sizeof(v_tab)); - int k = 0; - for (int i = 0; i < T; i++) { - for (int j = 0; j < T - i; j++) { - if (k < E) { - v_tab[i][j] = k + 1; - } - k++; - } - } - - int v[T][T]; - k = 0; - for (int j = 0; j < T; j++) { - for (int i = 0; i < T - j; i++) { - if (k < E && v_tab[i][j] != 0) { - v[i][j] = in[k]; - k++; - } else { - v[i][j] = INT_MAX; - } - } - } - - k = 0; - memset(out, 0, E * sizeof(*out)); - for (int i = 0; i < T; i++) { - for (int j = 0; j < T - i; j++) { - if (v[i][j] != INT_MAX) { - out[k] = v[i][j]; - k++; - } - } - } -} - -void nr_polar_rate_matching_int16(int16_t *input, - int16_t *output, - const uint16_t *rmp, - const uint16_t K, - const uint16_t N, - const uint16_t E, - const uint8_t i_bil) -{ - if (i_bil == 1) { - nr_polar_rm_deinterleaving_cb(input, input, E); - } - - if (E >= N) { // repetition - memset(output, 0, N * sizeof(*output)); - for (int i = 0; i <= E - 1; i++) - output[rmp[i]] += input[i]; - } else { - if ((K / (double)E) <= (7.0 / 16)) - memset(output, 0, N * sizeof(*output)); // puncturing - else { // shortening - for (int i = 0; i <= N - 1; i++) - output[i] = 32767; // instead of INFINITY, to prevent [-Woverflow] - } - - for (int i = 0; i <= E - 1; i++) - output[rmp[i]] = input[i]; - } -} diff --git a/openair1/PHY/CODING/nr_polar_init.c b/openair1/PHY/CODING/nr_polar_init.c index 1d12aae23e..d0c9dc3c60 100644 --- a/openair1/PHY/CODING/nr_polar_init.c +++ b/openair1/PHY/CODING/nr_polar_init.c @@ -47,8 +47,7 @@ static void nr_polar_delete_list(t_nrPolar_params * polarParams) { return; if (polarParams->nextPtr) nr_polar_delete_list(polarParams->nextPtr); - - delete_decoder_tree(polarParams); + // From build_polar_tables() free(polarParams->rm_tab); if (polarParams->crc_generator_matrix) @@ -71,7 +70,7 @@ static void nr_polar_delete(void) { pthread_mutex_unlock(&PolarListMutex); } -t_nrPolar_params *nr_polar_params(int8_t messageType, uint16_t messageLength, uint8_t aggregation_level, int decoder_flag) +t_nrPolar_params *nr_polar_params(int8_t messageType, uint16_t messageLength, uint8_t aggregation_level) { // The lock is weak, because we never delete in the list, only at exit time // therefore, returning t_nrPolar_params * from the list is safe for future usage @@ -87,8 +86,6 @@ t_nrPolar_params *nr_polar_params(int8_t messageType, uint16_t messageLength, ui if (currentPtr->busy == false && currentPtr->idx == PolarKey ) { currentPtr->busy=true; pthread_mutex_unlock(&PolarListMutex); - if (decoder_flag && !currentPtr->tree.root) - build_decoder_tree(currentPtr); return currentPtr ; } else @@ -97,11 +94,10 @@ t_nrPolar_params *nr_polar_params(int8_t messageType, uint16_t messageLength, ui // printf("currentPtr %p (polarParams %p)\n",currentPtr,polarParams); //Else, initialize and add node to the end of the linked list. - t_nrPolar_params *newPolarInitNode = calloc(sizeof(t_nrPolar_params),1); + t_nrPolar_params *newPolarInitNode = malloc(sizeof(t_nrPolar_params)); + AssertFatal(newPolarInitNode, "[nr_polar_init] New t_nrPolar_params * could not be created"); - newPolarInitNode->busy = true; - newPolarInitNode->nextPtr = NULL; - newPolarInitNode->nextPtr = PolarList; + *newPolarInitNode = (t_nrPolar_params){.busy = true, .nextPtr = PolarList}; PolarList = newPolarInitNode; pthread_mutex_unlock(&PolarListMutex); // LOG_D(PHY,"Setting new polarParams index %d, messageType %d, messageLength %d, aggregation_prime %d\n",(messageType * messageLength * aggregation_prime),messageType,messageLength,aggregation_prime); @@ -220,6 +216,10 @@ t_nrPolar_params *nr_polar_params(int8_t messageType, uint16_t messageLength, ui newPolarInitNode->K, newPolarInitNode->N, newPolarInitNode->encoderLength); + if (newPolarInitNode->i_bil) { + newPolarInitNode->i_bil_pattern = malloc(sizeof(uint16_t) * newPolarInitNode->encoderLength); + nr_polar_rm_deinterleaving_lut(newPolarInitNode->i_bil_pattern, newPolarInitNode->encoderLength); + } newPolarInitNode->information_bit_pattern = malloc(sizeof(uint8_t) * newPolarInitNode->N); newPolarInitNode->parity_check_bit_pattern = malloc(sizeof(uint8_t) * newPolarInitNode->N); newPolarInitNode->Q_I_N = malloc(sizeof(int16_t) * (newPolarInitNode->K + newPolarInitNode->n_pc)); @@ -245,8 +245,6 @@ t_nrPolar_params *nr_polar_params(int8_t messageType, uint16_t messageLength, ui // sort the Q_I_N array in ascending order (first K positions) qsort((void *)newPolarInitNode->Q_I_N,newPolarInitNode->K,sizeof(int16_t),intcmp); - if (decoder_flag == 1) - build_decoder_tree(newPolarInitNode); build_polar_tables(newPolarInitNode); init_polar_deinterleaver_table(newPolarInitNode);