From 5e5e487e4c5bb00258ebead98e61a95ffec3ced3 Mon Sep 17 00:00:00 2001 From: Sy Date: Fri, 29 May 2020 11:58:55 +0200 Subject: [PATCH] Test for avx512 --- cmake_targets/build_oai | 2 +- ...176_rate_1-3_block_length_3848_maxit_5.txt | 0 ...384_rate_1-3_block_length_8000_maxit_5.txt | 0 ...384_rate_1-3_block_length_8448_maxit_5.txt | 0 ...320_rate_1-3_block_length_3200_maxit_5.txt | 0 ...384_rate_1-3_block_length_3840_maxit_5.txt | 0 .../PHY/CODING/nrLDPC_decoder/nrLDPC_bnProc.h | 2 +- .../PHY/CODING/nrLDPC_decoder/nrLDPC_cnProc.h | 1 + .../CODING/nrLDPC_decoder/nrLDPC_decoder.c | 12 +- .../generator_avx512/cnProc_gen_BG1_avx512.c | 96 +- .../cnProc_gen_BG1_avx512.c.save | 742 ++++++++ .../generator_avx512/cnProc_gen_BG1_avx512.o | Bin 0 -> 34248 bytes .../cnProc_gen_BG1_avx512.save11 | 706 +++++++ .../generator_avx512/cnProc_gen_BG2_avx512.o | Bin 0 -> 28832 bytes .../generator_avx512/cnProc_gen_avx512 | Bin 0 -> 199680 bytes .../nrLDPC_tools/generator_avx512/main.o | Bin 0 -> 206816 bytes .../nrLDPC_cnProc_BG1_Z104_13_AVX512.c | 1614 ++++++++--------- .../nrLDPC_cnProc_BG1_Z10_13_AVX512.c | 1614 ++++++++--------- .../nrLDPC_cnProc_BG1_Z112_13_AVX512.c | 1614 ++++++++--------- .../nrLDPC_cnProc_BG1_Z11_13_AVX512.c | 1614 ++++++++--------- .../nrLDPC_cnProc_BG1_Z120_13_AVX512.c | 1614 ++++++++--------- .../nrLDPC_cnProc_BG1_Z128_13_AVX512.c | 1614 ++++++++--------- .../nrLDPC_cnProc_BG1_Z12_13_AVX512.c | 1614 ++++++++--------- .../nrLDPC_cnProc_BG1_Z13_13_AVX512.c | 1614 ++++++++--------- .../nrLDPC_cnProc_BG1_Z144_13_AVX512.c | 1614 ++++++++--------- .../nrLDPC_cnProc_BG1_Z14_13_AVX512.c | 1614 ++++++++--------- .../nrLDPC_cnProc_BG1_Z15_13_AVX512.c | 1614 ++++++++--------- .../nrLDPC_cnProc_BG1_Z160_13_AVX512.c | 1614 ++++++++--------- .../nrLDPC_cnProc_BG1_Z16_13_AVX512.c | 1614 ++++++++--------- .../nrLDPC_cnProc_BG1_Z176_13_AVX512.c | 1614 ++++++++--------- .../nrLDPC_cnProc_BG1_Z18_13_AVX512.c | 1614 ++++++++--------- .../nrLDPC_cnProc_BG1_Z192_13_AVX512.c | 1614 ++++++++--------- .../nrLDPC_cnProc_BG1_Z208_13_AVX512.c | 1614 ++++++++--------- .../nrLDPC_cnProc_BG1_Z20_13_AVX512.c | 1614 ++++++++--------- .../nrLDPC_cnProc_BG1_Z224_13_AVX512.c | 1614 ++++++++--------- .../nrLDPC_cnProc_BG1_Z22_13_AVX512.c | 1614 ++++++++--------- .../nrLDPC_cnProc_BG1_Z240_13_AVX512.c | 1614 ++++++++--------- .../nrLDPC_cnProc_BG1_Z24_13_AVX512.c | 1614 ++++++++--------- .../nrLDPC_cnProc_BG1_Z256_13_AVX512.c | 1614 ++++++++--------- .../nrLDPC_cnProc_BG1_Z26_13_AVX512.c | 1614 ++++++++--------- .../nrLDPC_cnProc_BG1_Z288_13_AVX512.c | 1614 ++++++++--------- .../nrLDPC_cnProc_BG1_Z28_13_AVX512.c | 1614 ++++++++--------- .../nrLDPC_cnProc_BG1_Z2_13_AVX512.c | 1614 ++++++++--------- .../nrLDPC_cnProc_BG1_Z30_13_AVX512.c | 1614 ++++++++--------- .../nrLDPC_cnProc_BG1_Z320_13_AVX512.c | 1614 ++++++++--------- .../nrLDPC_cnProc_BG1_Z32_13_AVX512.c | 1614 ++++++++--------- .../nrLDPC_cnProc_BG1_Z352_13_AVX512.c | 1614 ++++++++--------- .../nrLDPC_cnProc_BG1_Z36_13_AVX512.c | 1614 ++++++++--------- .../nrLDPC_cnProc_BG1_Z384_13_AVX512.c | 1614 ++++++++--------- .../nrLDPC_cnProc_BG1_Z3_13_AVX512.c | 1614 ++++++++--------- .../nrLDPC_cnProc_BG1_Z40_13_AVX512.c | 1614 ++++++++--------- .../nrLDPC_cnProc_BG1_Z44_13_AVX512.c | 1614 ++++++++--------- .../nrLDPC_cnProc_BG1_Z48_13_AVX512.c | 1614 ++++++++--------- .../nrLDPC_cnProc_BG1_Z4_13_AVX512.c | 1614 ++++++++--------- .../nrLDPC_cnProc_BG1_Z52_13_AVX512.c | 1614 ++++++++--------- .../nrLDPC_cnProc_BG1_Z56_13_AVX512.c | 1614 ++++++++--------- .../nrLDPC_cnProc_BG1_Z5_13_AVX512.c | 1614 ++++++++--------- .../nrLDPC_cnProc_BG1_Z60_13_AVX512.c | 1614 ++++++++--------- .../nrLDPC_cnProc_BG1_Z64_13_AVX512.c | 1614 ++++++++--------- .../nrLDPC_cnProc_BG1_Z6_13_AVX512.c | 1614 ++++++++--------- .../nrLDPC_cnProc_BG1_Z72_13_AVX512.c | 1614 ++++++++--------- .../nrLDPC_cnProc_BG1_Z7_13_AVX512.c | 1614 ++++++++--------- .../nrLDPC_cnProc_BG1_Z80_13_AVX512.c | 1614 ++++++++--------- .../nrLDPC_cnProc_BG1_Z88_13_AVX512.c | 1614 ++++++++--------- .../nrLDPC_cnProc_BG1_Z8_13_AVX512.c | 1614 ++++++++--------- .../nrLDPC_cnProc_BG1_Z96_13_AVX512.c | 1614 ++++++++--------- .../nrLDPC_cnProc_BG1_Z9_13_AVX512.c | 1614 ++++++++--------- .../include/avx512bwintrin.h | 2 +- .../include/avx512fintrin.h | 2 +- .../nrLDPC_decoder_full/nrLDPC_bnProc.h | 113 +- .../nrLDPC_decoder_full/nrLDPC_cnProc.h | 156 +- .../nrLDPC_decoder_full/nrLDPC_decoder.c | 6 +- 72 files changed, 42802 insertions(+), 41352 deletions(-) create mode 100644 cmake_targets/ldpctest_BG_1_Zc_176_rate_1-3_block_length_3848_maxit_5.txt create mode 100644 cmake_targets/ldpctest_BG_1_Zc_384_rate_1-3_block_length_8000_maxit_5.txt create mode 100644 cmake_targets/ldpctest_BG_1_Zc_384_rate_1-3_block_length_8448_maxit_5.txt create mode 100644 cmake_targets/ldpctest_BG_2_Zc_320_rate_1-3_block_length_3200_maxit_5.txt create mode 100644 cmake_targets/ldpctest_BG_2_Zc_384_rate_1-3_block_length_3840_maxit_5.txt create mode 100644 openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_tools/generator_avx512/cnProc_gen_BG1_avx512.c.save create mode 100644 openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_tools/generator_avx512/cnProc_gen_BG1_avx512.o create mode 100644 openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_tools/generator_avx512/cnProc_gen_BG1_avx512.save11 create mode 100644 openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_tools/generator_avx512/cnProc_gen_BG2_avx512.o create mode 100755 openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_tools/generator_avx512/cnProc_gen_avx512 create mode 100644 openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_tools/generator_avx512/main.o diff --git a/cmake_targets/build_oai b/cmake_targets/build_oai index 965dfaea3a..8ab9fff880 100755 --- a/cmake_targets/build_oai +++ b/cmake_targets/build_oai @@ -697,7 +697,7 @@ function main() { if [ "$SIMUS_PHY" = "1" ] ; then echo_info "Compiling physical unitary tests simulators" # TODO: fix: dlsim_tm4 pucchsim prachsim pdcchsim pbchsim mbmssim - simlist="dlsim ulsim ldpctest polartest smallblocktest nr_pbchsim nr_dlschsim nr_ulschsim nr_dlsim nr_ulsim nr_pucchsim nr_prachsim" + simlist="ldpctest dlsim ulsim polartest smallblocktest nr_pbchsim nr_dlschsim nr_ulschsim nr_dlsim nr_ulsim nr_pucchsim nr_prachsim" for f in $simlist ; do compilations \ phy_simulators $f \ diff --git a/cmake_targets/ldpctest_BG_1_Zc_176_rate_1-3_block_length_3848_maxit_5.txt b/cmake_targets/ldpctest_BG_1_Zc_176_rate_1-3_block_length_3848_maxit_5.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/cmake_targets/ldpctest_BG_1_Zc_384_rate_1-3_block_length_8000_maxit_5.txt b/cmake_targets/ldpctest_BG_1_Zc_384_rate_1-3_block_length_8000_maxit_5.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/cmake_targets/ldpctest_BG_1_Zc_384_rate_1-3_block_length_8448_maxit_5.txt b/cmake_targets/ldpctest_BG_1_Zc_384_rate_1-3_block_length_8448_maxit_5.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/cmake_targets/ldpctest_BG_2_Zc_320_rate_1-3_block_length_3200_maxit_5.txt b/cmake_targets/ldpctest_BG_2_Zc_320_rate_1-3_block_length_3200_maxit_5.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/cmake_targets/ldpctest_BG_2_Zc_384_rate_1-3_block_length_3840_maxit_5.txt b/cmake_targets/ldpctest_BG_2_Zc_384_rate_1-3_block_length_3840_maxit_5.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_bnProc.h b/openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_bnProc.h index 878150a9a8..9641563e9e 100644 --- a/openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_bnProc.h +++ b/openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_bnProc.h @@ -30,7 +30,7 @@ #ifndef __NR_LDPC_BNPROC__H__ #define __NR_LDPC_BNPROC__H__ - +#include /** \brief Performs first part of BN processing on the BN processing buffer and stores the results in the LLR results buffer. At every BN, the sum of the returned LLRs from the connected CNs and the LLR of the receiver input is computed. diff --git a/openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_cnProc.h b/openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_cnProc.h index 50e425753d..74b66ab0b5 100644 --- a/openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_cnProc.h +++ b/openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_cnProc.h @@ -438,6 +438,7 @@ static inline void nrLDPC_cnProc_BG1(t_nrLDPC_lut* p_lut, t_nrLDPC_procBuf* p_pr ymm0 = p_cnProcBuf[lut_idxCnProcG3[j][1] + i]; min = _mm256_min_epu8(min, _mm256_abs_epi8(ymm0)); sgn = _mm256_sign_epi8(sgn, ymm0); + // Store result min = _mm256_min_epu8(min, *p_maxLLR); // 128 in epi8 is -127 diff --git a/openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_decoder.c b/openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_decoder.c index 493888ebbe..13223a1e40 100644 --- a/openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_decoder.c +++ b/openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_decoder.c @@ -263,8 +263,8 @@ static inline uint32_t nrLDPC_decoder_core(int8_t* p_llr, int8_t* p_out, t_nrLDP uint8_t BG = p_decParams->BG; uint8_t numMaxIter = p_decParams->numMaxIter; e_nrLDPC_outMode outMode = p_decParams->outMode; - int8_t* cnProcBuf= p_procBuf->cnProcBuf; - int8_t* cnProcBufRes=p_procBuf->cnProcBufRes; + // int8_t* cnProcBuf= p_procBuf->cnProcBuf; + // int8_t* cnProcBufRes=p_procBuf->cnProcBufRes; // Minimum number of iterations is 1 // 0 iterations means hard-decision on input LLRs @@ -334,7 +334,7 @@ static inline uint32_t nrLDPC_decoder_core(int8_t* p_llr, int8_t* p_out, t_nrLDP case 384: { // nrLDPC_cnProc_BG1_Z384_13_AVX2(p_procBuf->cnProcBuf,p_procBuf->cnProcBufRes); - nrLDPC_cnProc_BG1_Z384_13_AVX512(p_procBuf->cnProcBuf,p_procBuf->cnProcBufRes); //were test here + nrLDPC_cnProc_BG1_Z384_13_AVX512(p_procBuf->cnProcBuf,p_procBuf->cnProcBufRes); //we test here break; } case 352: @@ -349,7 +349,7 @@ static inline uint32_t nrLDPC_decoder_core(int8_t* p_llr, int8_t* p_out, t_nrLDP nrLDPC_cnProc_BG1_Z320_13_AVX2(p_procBuf->cnProcBuf,p_procBuf->cnProcBufRes); //nrLDPC_cnProc_BG1_Z320_13_AVX512(p_procBuf->cnProcBuf,p_procBuf->cnProcBufRes); break; - } + } case 288: { @@ -1928,8 +1928,8 @@ static inline uint32_t nrLDPC_decoder_core(int8_t* p_llr, int8_t* p_out, t_nrLDP } case 352: { - //nrLDPC_cnProc_BG1_Z352_13_AVX2(p_procBuf->cnProcBuf,p_procBuf->cnProcBufRes); - nrLDPC_cnProc_BG1_Z352_13_AVX512(p_procBuf->cnProcBuf,p_procBuf->cnProcBufRes); + nrLDPC_cnProc_BG1_Z352_13_AVX2(p_procBuf->cnProcBuf,p_procBuf->cnProcBufRes); + //nrLDPC_cnProc_BG1_Z352_13_AVX512(p_procBuf->cnProcBuf,p_procBuf->cnProcBufRes); break; } diff --git a/openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_tools/generator_avx512/cnProc_gen_BG1_avx512.c b/openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_tools/generator_avx512/cnProc_gen_BG1_avx512.c index 1d6f2f14d8..277cea73cf 100644 --- a/openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_tools/generator_avx512/cnProc_gen_BG1_avx512.c +++ b/openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_tools/generator_avx512/cnProc_gen_BG1_avx512.c @@ -80,10 +80,10 @@ void nrLDPC_cnProc_BG1_generator_AVX512(uint16_t Z,int R) { // Number of groups of 64 CNs for parallel processing // Ceil for values not divisible by 64 - M = (lut_numCnInCnGroups[0]*Z + 63)>>5; + M = (lut_numCnInCnGroups[0]*Z + 63)>>31; // Set the offset to each bit within a group in terms of 64 Byte - bitOffsetInGroup = (lut_numCnInCnGroups_BG1_R13[0]*NR_LDPC_ZMAX)>>5; + bitOffsetInGroup = (lut_numCnInCnGroups_BG1_R13[0]*NR_LDPC_ZMAX)>>31; // Set pointers to start of group 3 @@ -104,7 +104,7 @@ void nrLDPC_cnProc_BG1_generator_AVX512(uint16_t Z,int R) fprintf(fd," for (int i=0;i<%d;i+=2) {\n",M); // Abs and sign of 64 CNs (first BN) // zmm0 = p_cnProcBuf[lut_idxCnProcG3[j][0] + i]; - fprintf(fd," zmm0 = ((__m512i*)cnProcBuf)[%d+i];\n",(lut_startAddrCnGroups[0]>>5)+lut_idxCnProcG3[j][0]); + fprintf(fd," zmm0 = ((__m512i*)cnProcBuf)[%d+i];\n",(lut_startAddrCnGroups[0]>>31)+lut_idxCnProcG3[j][0]); // sgn = _mm512_sign_epi16(ones, zmm0); fprintf(fd," sgn = _mm512_sign_epi16(ones, zmm0);\n"); // min = _mm512_abs_epi8(zmm0); @@ -112,7 +112,7 @@ void nrLDPC_cnProc_BG1_generator_AVX512(uint16_t Z,int R) // 32 CNs of second BN // zmm0 = p_cnProcBuf[lut_idxCnProcG3[j][1] + i]; - fprintf(fd," zmm0 = ((__m512i*)cnProcBuf)[%d+i];\n",(lut_startAddrCnGroups[0]>>5)+lut_idxCnProcG3[j][1]); + fprintf(fd," zmm0 = ((__m512i*)cnProcBuf)[%d+i];\n",(lut_startAddrCnGroups[0]>>31)+lut_idxCnProcG3[j][1]); // min = _mm512_min_epu8(min, _mm512_abs_epi8(zmm0)); fprintf(fd," min = _mm512_min_epu8(min, _mm512_abs_epi8(zmm0));\n"); @@ -125,11 +125,11 @@ void nrLDPC_cnProc_BG1_generator_AVX512(uint16_t Z,int R) fprintf(fd," min = _mm512_min_epu8(min, maxLLR);\n"); // *p_cnProcBufResBit = _mm512_sign_epi16(min, sgn); // p_cnProcBufResBit++; - fprintf(fd," ((__m512i*)cnProcBufRes)[%d+i] = _mm512_sign_epi16(min, sgn);\n",(lut_startAddrCnGroups[0]>>5)+(j*bitOffsetInGroup)); + fprintf(fd," ((__m512i*)cnProcBufRes)[%d+i] = _mm512_sign_epi16(min, sgn);\n",(lut_startAddrCnGroups[0]>>31)+(j*bitOffsetInGroup)); // Abs and sign of 64 CNs (first BN) // zmm0 = p_cnProcBuf[lut_idxCnProcG3[j][0] + i]; - fprintf(fd," zmm0 = ((__m512i*)cnProcBuf)[%d+i];\n",(lut_startAddrCnGroups[0]>>5)+lut_idxCnProcG3[j][0]+1); + fprintf(fd," zmm0 = ((__m512i*)cnProcBuf)[%d+i];\n",(lut_startAddrCnGroups[0]>>31)+lut_idxCnProcG3[j][0]+1); // sgn = _mm512_sign_epi16(ones, zmm0); fprintf(fd," sgn = _mm512_sign_epi16(ones, zmm0);\n"); // min = _mm512_abs_epi8(zmm0); @@ -137,7 +137,7 @@ void nrLDPC_cnProc_BG1_generator_AVX512(uint16_t Z,int R) // 32 CNs of second BN // zmm0 = p_cnProcBuf[lut_idxCnProcG3[j][1] + i]; - fprintf(fd," zmm0 = ((__m512i*)cnProcBuf)[%d+i];\n",(lut_startAddrCnGroups[0]>>5)+lut_idxCnProcG3[j][1]+1); + fprintf(fd," zmm0 = ((__m512i*)cnProcBuf)[%d+i];\n",(lut_startAddrCnGroups[0]>>31)+lut_idxCnProcG3[j][1]+1); // min = _mm512_min_epu8(min, _mm512_abs_epi8(zmm0)); fprintf(fd," min = _mm512_min_epu8(min, _mm512_abs_epi8(zmm0));\n"); @@ -150,7 +150,7 @@ void nrLDPC_cnProc_BG1_generator_AVX512(uint16_t Z,int R) fprintf(fd," min = _mm512_min_epu8(min, maxLLR);\n"); // *p_cnProcBufResBit = _mm512_sign_epi16(min, sgn); // p_cnProcBufResBit++; - fprintf(fd," ((__m512i*)cnProcBufRes)[%d+i] = _mm512_sign_epi16(min, sgn);\n",(lut_startAddrCnGroups[0]>>5)+(j*bitOffsetInGroup)+1); + fprintf(fd," ((__m512i*)cnProcBufRes)[%d+i] = _mm512_sign_epi16(min, sgn);\n",(lut_startAddrCnGroups[0]>>31)+(j*bitOffsetInGroup)+1); fprintf(fd," }\n"); } @@ -166,10 +166,10 @@ void nrLDPC_cnProc_BG1_generator_AVX512(uint16_t Z,int R) { // Number of groups of 64 CNs for parallel processing // Ceil for values not divisible by 64 - M = (lut_numCnInCnGroups[1]*Z + 63)>>5; + M = (lut_numCnInCnGroups[1]*Z + 63)>>31; // Set the offset to each bit within a group in terms of 64 Byte - bitOffsetInGroup = (lut_numCnInCnGroups_BG1_R13[1]*NR_LDPC_ZMAX)>>5; + bitOffsetInGroup = (lut_numCnInCnGroups_BG1_R13[1]*NR_LDPC_ZMAX)>>31; // Set pointers to start of group 4 @@ -188,7 +188,7 @@ void nrLDPC_cnProc_BG1_generator_AVX512(uint16_t Z,int R) fprintf(fd," for (int i=0;i<%d;i++) {\n",M); // Abs and sign of 64 CNs (first BN) // zmm0 = p_cnProcBuf[lut_idxCnProcG3[j][0] + i]; - fprintf(fd," zmm0 = ((__m512i*)cnProcBuf)[%d+i];\n",(lut_startAddrCnGroups[1]>>5)+lut_idxCnProcG4[j][0]); + fprintf(fd," zmm0 = ((__m512i*)cnProcBuf)[%d+i];\n",(lut_startAddrCnGroups[1]>>31)+lut_idxCnProcG4[j][0]); // sgn = _mm512_sign_epi16(ones, zmm0); fprintf(fd," sgn = _mm512_sign_epi16(ones, zmm0);\n"); // min = _mm512_abs_epi8(zmm0); @@ -198,7 +198,7 @@ void nrLDPC_cnProc_BG1_generator_AVX512(uint16_t Z,int R) // Loop over BNs for (k=1; k<3; k++) { - fprintf(fd," zmm0 = ((__m512i*)cnProcBuf)[%d+i];\n",(lut_startAddrCnGroups[1]>>5)+lut_idxCnProcG4[j][k]); + fprintf(fd," zmm0 = ((__m512i*)cnProcBuf)[%d+i];\n",(lut_startAddrCnGroups[1]>>31)+lut_idxCnProcG4[j][k]); // min = _mm512_min_epu8(min, _mm512_abs_epi8(zmm0)); fprintf(fd," min = _mm512_min_epu8(min, _mm512_abs_epi8(zmm0));\n"); @@ -212,7 +212,7 @@ void nrLDPC_cnProc_BG1_generator_AVX512(uint16_t Z,int R) fprintf(fd," min = _mm512_min_epu8(min, maxLLR);\n"); // *p_cnProcBufResBit = _mm512_sign_epi16(min, sgn); // p_cnProcBufResBit++; - fprintf(fd," ((__m512i*)cnProcBufRes)[%d+i] = _mm512_sign_epi16(min, sgn);\n",(lut_startAddrCnGroups[1]>>5)+(j*bitOffsetInGroup)); + fprintf(fd," ((__m512i*)cnProcBufRes)[%d+i] = _mm512_sign_epi16(min, sgn);\n",(lut_startAddrCnGroups[1]>>31)+(j*bitOffsetInGroup)); fprintf(fd," }\n"); } } @@ -230,10 +230,10 @@ void nrLDPC_cnProc_BG1_generator_AVX512(uint16_t Z,int R) { // Number of groups of 64 CNs for parallel processing // Ceil for values not divisible by 64 - M = (lut_numCnInCnGroups[2]*Z + 63)>>5; + M = (lut_numCnInCnGroups[2]*Z + 63)>>31; // Set the offset to each bit within a group in terms of 64 Byte - bitOffsetInGroup = (lut_numCnInCnGroups_BG1_R13[2]*NR_LDPC_ZMAX)>>5; + bitOffsetInGroup = (lut_numCnInCnGroups_BG1_R13[2]*NR_LDPC_ZMAX)>>31; // Set pointers to start of group 4 @@ -253,7 +253,7 @@ void nrLDPC_cnProc_BG1_generator_AVX512(uint16_t Z,int R) fprintf(fd," for (int i=0;i<%d;i++) {\n",M); // Abs and sign of 64 CNs (first BN) // zmm0 = p_cnProcBuf[lut_idxCnProcG3[j][0] + i]; - fprintf(fd," zmm0 = ((__m512i*)cnProcBuf)[%d+i];\n",(lut_startAddrCnGroups[2]>>5)+lut_idxCnProcG5[j][0]); + fprintf(fd," zmm0 = ((__m512i*)cnProcBuf)[%d+i];\n",(lut_startAddrCnGroups[2]>>31)+lut_idxCnProcG5[j][0]); // sgn = _mm512_sign_epi16(ones, zmm0); fprintf(fd," sgn = _mm512_sign_epi16(ones, zmm0);\n"); // min = _mm512_abs_epi8(zmm0); @@ -263,7 +263,7 @@ void nrLDPC_cnProc_BG1_generator_AVX512(uint16_t Z,int R) // Loop over BNs for (k=1; k<4; k++) { - fprintf(fd," zmm0 = ((__m512i*)cnProcBuf)[%d+i];\n",(lut_startAddrCnGroups[2]>>5)+lut_idxCnProcG5[j][k]); + fprintf(fd," zmm0 = ((__m512i*)cnProcBuf)[%d+i];\n",(lut_startAddrCnGroups[2]>>31)+lut_idxCnProcG5[j][k]); // min = _mm512_min_epu8(min, _mm512_abs_epi8(zmm0)); fprintf(fd," min = _mm512_min_epu8(min, _mm512_abs_epi8(zmm0));\n"); @@ -277,7 +277,7 @@ void nrLDPC_cnProc_BG1_generator_AVX512(uint16_t Z,int R) fprintf(fd," min = _mm512_min_epu8(min, maxLLR);\n"); // *p_cnProcBufResBit = _mm512_sign_epi16(min, sgn); // p_cnProcBufResBit++; - fprintf(fd," ((__m512i*)cnProcBufRes)[%d+i] = _mm512_sign_epi16(min, sgn);\n",(lut_startAddrCnGroups[2]>>5)+(j*bitOffsetInGroup)); + fprintf(fd," ((__m512i*)cnProcBufRes)[%d+i] = _mm512_sign_epi16(min, sgn);\n",(lut_startAddrCnGroups[2]>>31)+(j*bitOffsetInGroup)); fprintf(fd," }\n"); } } @@ -295,10 +295,10 @@ void nrLDPC_cnProc_BG1_generator_AVX512(uint16_t Z,int R) { // Number of groups of 64 CNs for parallel processing // Ceil for values not divisible by 64 - M = (lut_numCnInCnGroups[3]*Z + 63)>>5; + M = (lut_numCnInCnGroups[3]*Z + 63)>>31; // Set the offset to each bit within a group in terms of 64 Byte - bitOffsetInGroup = (lut_numCnInCnGroups_BG1_R13[3]*NR_LDPC_ZMAX)>>5; + bitOffsetInGroup = (lut_numCnInCnGroups_BG1_R13[3]*NR_LDPC_ZMAX)>>31; // Set pointers to start of group 4 @@ -318,7 +318,7 @@ void nrLDPC_cnProc_BG1_generator_AVX512(uint16_t Z,int R) fprintf(fd," for (int i=0;i<%d;i++) {\n",M); // Abs and sign of 64 CNs (first BN) // zmm0 = p_cnProcBuf[lut_idxCnProcG3[j][0] + i]; - fprintf(fd," zmm0 = ((__m512i*)cnProcBuf)[%d+i];\n",(lut_startAddrCnGroups[3]>>5)+lut_idxCnProcG6[j][0]); + fprintf(fd," zmm0 = ((__m512i*)cnProcBuf)[%d+i];\n",(lut_startAddrCnGroups[3]>>31)+lut_idxCnProcG6[j][0]); // sgn = _mm512_sign_epi16(ones, zmm0); fprintf(fd," sgn = _mm512_sign_epi16(ones, zmm0);\n"); // min = _mm512_abs_epi8(zmm0); @@ -328,7 +328,7 @@ void nrLDPC_cnProc_BG1_generator_AVX512(uint16_t Z,int R) // Loop over BNs for (k=1; k<5; k++) { - fprintf(fd," zmm0 = ((__m512i*)cnProcBuf)[%d+i];\n",(lut_startAddrCnGroups[3]>>5)+lut_idxCnProcG6[j][k]); + fprintf(fd," zmm0 = ((__m512i*)cnProcBuf)[%d+i];\n",(lut_startAddrCnGroups[3]>>31)+lut_idxCnProcG6[j][k]); // min = _mm512_min_epu8(min, _mm512_abs_epi8(zmm0)); fprintf(fd," min = _mm512_min_epu8(min, _mm512_abs_epi8(zmm0));\n"); @@ -342,7 +342,7 @@ void nrLDPC_cnProc_BG1_generator_AVX512(uint16_t Z,int R) fprintf(fd," min = _mm512_min_epu8(min, maxLLR);\n"); // *p_cnProcBufResBit = _mm512_sign_epi16(min, sgn); // p_cnProcBufResBit++; - fprintf(fd," ((__m512i*)cnProcBufRes)[%d+i] = _mm512_sign_epi16(min, sgn);\n",(lut_startAddrCnGroups[3]>>5)+(j*bitOffsetInGroup)); + fprintf(fd," ((__m512i*)cnProcBufRes)[%d+i] = _mm512_sign_epi16(min, sgn);\n",(lut_startAddrCnGroups[3]>>31)+(j*bitOffsetInGroup)); fprintf(fd," }\n"); } } @@ -362,10 +362,10 @@ void nrLDPC_cnProc_BG1_generator_AVX512(uint16_t Z,int R) { // Number of groups of 64 CNs for parallel processing // Ceil for values not divisible by 64 - M = (lut_numCnInCnGroups[4]*Z + 63)>>5; + M = (lut_numCnInCnGroups[4]*Z + 63)>>31; // Set the offset to each bit within a group in terms of 64 Byte - bitOffsetInGroup = (lut_numCnInCnGroups_BG1_R13[4]*NR_LDPC_ZMAX)>>5; + bitOffsetInGroup = (lut_numCnInCnGroups_BG1_R13[4]*NR_LDPC_ZMAX)>>31; // Set pointers to start of group 4 @@ -385,7 +385,7 @@ void nrLDPC_cnProc_BG1_generator_AVX512(uint16_t Z,int R) fprintf(fd," for (int i=0;i<%d;i++) {\n",M); // Abs and sign of 64 CNs (first BN) // zmm0 = p_cnProcBuf[lut_idxCnProcG3[j][0] + i]; - fprintf(fd," zmm0 = ((__m512i*)cnProcBuf)[%d+i];\n",(lut_startAddrCnGroups[4]>>5)+lut_idxCnProcG7[j][0]); + fprintf(fd," zmm0 = ((__m512i*)cnProcBuf)[%d+i];\n",(lut_startAddrCnGroups[4]>>31)+lut_idxCnProcG7[j][0]); // sgn = _mm512_sign_epi16(ones, zmm0); fprintf(fd," sgn = _mm512_sign_epi16(ones, zmm0);\n"); // min = _mm512_abs_epi8(zmm0); @@ -395,7 +395,7 @@ void nrLDPC_cnProc_BG1_generator_AVX512(uint16_t Z,int R) // Loop over BNs for (k=1; k<6; k++) { - fprintf(fd," zmm0 = ((__m512i*)cnProcBuf)[%d+i];\n",(lut_startAddrCnGroups[4]>>5)+lut_idxCnProcG7[j][k]); + fprintf(fd," zmm0 = ((__m512i*)cnProcBuf)[%d+i];\n",(lut_startAddrCnGroups[4]>>31)+lut_idxCnProcG7[j][k]); // min = _mm512_min_epu8(min, _mm512_abs_epi8(zmm0)); fprintf(fd," min = _mm512_min_epu8(min, _mm512_abs_epi8(zmm0));\n"); @@ -409,7 +409,7 @@ void nrLDPC_cnProc_BG1_generator_AVX512(uint16_t Z,int R) fprintf(fd," min = _mm512_min_epu8(min, maxLLR);\n"); // *p_cnProcBufResBit = _mm512_sign_epi16(min, sgn); // p_cnProcBufResBit++; - fprintf(fd," ((__m512i*)cnProcBufRes)[%d+i] = _mm512_sign_epi16(min, sgn);\n",(lut_startAddrCnGroups[4]>>5)+(j*bitOffsetInGroup)); + fprintf(fd," ((__m512i*)cnProcBufRes)[%d+i] = _mm512_sign_epi16(min, sgn);\n",(lut_startAddrCnGroups[4]>>31)+(j*bitOffsetInGroup)); fprintf(fd," }\n"); } } @@ -430,10 +430,10 @@ void nrLDPC_cnProc_BG1_generator_AVX512(uint16_t Z,int R) { // Number of groups of 64 CNs for parallel processing // Ceil for values not divisible by 64 - M = (lut_numCnInCnGroups[5]*Z + 63)>>5; + M = (lut_numCnInCnGroups[5]*Z + 63)>>31; // Set the offset to each bit within a group in terms of 64 Byte - bitOffsetInGroup = (lut_numCnInCnGroups_BG1_R13[5]*NR_LDPC_ZMAX)>>5; + bitOffsetInGroup = (lut_numCnInCnGroups_BG1_R13[5]*NR_LDPC_ZMAX)>>31; // Set pointers to start of group 4 @@ -453,7 +453,7 @@ void nrLDPC_cnProc_BG1_generator_AVX512(uint16_t Z,int R) fprintf(fd," for (int i=0;i<%d;i++) {\n",M); // Abs and sign of 64 CNs (first BN) // zmm0 = p_cnProcBuf[lut_idxCnProcG3[j][0] + i]; - fprintf(fd," zmm0 = ((__m512i*)cnProcBuf)[%d+i];\n",(lut_startAddrCnGroups[5]>>5)+lut_idxCnProcG8[j][0]); + fprintf(fd," zmm0 = ((__m512i*)cnProcBuf)[%d+i];\n",(lut_startAddrCnGroups[5]>>31)+lut_idxCnProcG8[j][0]); // sgn = _mm512_sign_epi16(ones, zmm0); fprintf(fd," sgn = _mm512_sign_epi16(ones, zmm0);\n"); // min = _mm512_abs_epi8(zmm0); @@ -463,7 +463,7 @@ void nrLDPC_cnProc_BG1_generator_AVX512(uint16_t Z,int R) // Loop over BNs for (k=1; k<7; k++) { - fprintf(fd," zmm0 = ((__m512i*)cnProcBuf)[%d+i];\n",(lut_startAddrCnGroups[5]>>5)+lut_idxCnProcG8[j][k]); + fprintf(fd," zmm0 = ((__m512i*)cnProcBuf)[%d+i];\n",(lut_startAddrCnGroups[5]>>31)+lut_idxCnProcG8[j][k]); // min = _mm512_min_epu8(min, _mm512_abs_epi8(zmm0)); fprintf(fd," min = _mm512_min_epu8(min, _mm512_abs_epi8(zmm0));\n"); @@ -477,7 +477,7 @@ void nrLDPC_cnProc_BG1_generator_AVX512(uint16_t Z,int R) fprintf(fd," min = _mm512_min_epu8(min, maxLLR);\n"); // *p_cnProcBufResBit = _mm512_sign_epi16(min, sgn); // p_cnProcBufResBit++; - fprintf(fd," ((__m512i*)cnProcBufRes)[%d+i] = _mm512_sign_epi16(min, sgn);\n",(lut_startAddrCnGroups[5]>>5)+(j*bitOffsetInGroup)); + fprintf(fd," ((__m512i*)cnProcBufRes)[%d+i] = _mm512_sign_epi16(min, sgn);\n",(lut_startAddrCnGroups[5]>>31)+(j*bitOffsetInGroup)); fprintf(fd," }\n"); } } @@ -499,10 +499,10 @@ void nrLDPC_cnProc_BG1_generator_AVX512(uint16_t Z,int R) { // Number of groups of 64 CNs for parallel processing // Ceil for values not divisible by 64 - M = (lut_numCnInCnGroups[6]*Z + 63)>>5; + M = (lut_numCnInCnGroups[6]*Z + 63)>>31; // Set the offset to each bit within a group in terms of 64 Byte - bitOffsetInGroup = (lut_numCnInCnGroups_BG1_R13[6]*NR_LDPC_ZMAX)>>5; + bitOffsetInGroup = (lut_numCnInCnGroups_BG1_R13[6]*NR_LDPC_ZMAX)>>31; // Set pointers to start of group 9 @@ -522,7 +522,7 @@ void nrLDPC_cnProc_BG1_generator_AVX512(uint16_t Z,int R) fprintf(fd," for (int i=0;i<%d;i++) {\n",M); // Abs and sign of 64 CNs (first BN) // zmm0 = p_cnProcBuf[lut_idxCnProcG3[j][0] + i]; - fprintf(fd," zmm0 = ((__m512i*)cnProcBuf)[%d+i];\n",(lut_startAddrCnGroups[6]>>5)+lut_idxCnProcG9[j][0]); + fprintf(fd," zmm0 = ((__m512i*)cnProcBuf)[%d+i];\n",(lut_startAddrCnGroups[6]>>31)+lut_idxCnProcG9[j][0]); // sgn = _mm512_sign_epi16(ones, zmm0); fprintf(fd," sgn = _mm512_sign_epi16(ones, zmm0);\n"); // min = _mm512_abs_epi8(zmm0); @@ -532,7 +532,7 @@ void nrLDPC_cnProc_BG1_generator_AVX512(uint16_t Z,int R) // Loop over BNs for (k=1; k<8; k++) { - fprintf(fd," zmm0 = ((__m512i*)cnProcBuf)[%d+i];\n",(lut_startAddrCnGroups[6]>>5)+lut_idxCnProcG9[j][k]); + fprintf(fd," zmm0 = ((__m512i*)cnProcBuf)[%d+i];\n",(lut_startAddrCnGroups[6]>>31)+lut_idxCnProcG9[j][k]); // min = _mm512_min_epu8(min, _mm512_abs_epi8(zmm0)); fprintf(fd," min = _mm512_min_epu8(min, _mm512_abs_epi8(zmm0));\n"); @@ -546,7 +546,7 @@ void nrLDPC_cnProc_BG1_generator_AVX512(uint16_t Z,int R) fprintf(fd," min = _mm512_min_epu8(min, maxLLR);\n"); // *p_cnProcBufResBit = _mm512_sign_epi16(min, sgn); // p_cnProcBufResBit++; - fprintf(fd," ((__m512i*)cnProcBufRes)[%d+i] = _mm512_sign_epi16(min, sgn);\n",(lut_startAddrCnGroups[6]>>5)+(j*bitOffsetInGroup)); + fprintf(fd," ((__m512i*)cnProcBufRes)[%d+i] = _mm512_sign_epi16(min, sgn);\n",(lut_startAddrCnGroups[6]>>31)+(j*bitOffsetInGroup)); fprintf(fd," }\n"); } } @@ -569,10 +569,10 @@ void nrLDPC_cnProc_BG1_generator_AVX512(uint16_t Z,int R) { // Number of groups of 64 CNs for parallel processing // Ceil for values not divisible by 64 - M = (lut_numCnInCnGroups[7]*Z + 63)>>5; + M = (lut_numCnInCnGroups[7]*Z + 63)>>31; // Set the offset to each bit within a group in terms of 64 Byte - bitOffsetInGroup = (lut_numCnInCnGroups_BG1_R13[7]*NR_LDPC_ZMAX)>>5; + bitOffsetInGroup = (lut_numCnInCnGroups_BG1_R13[7]*NR_LDPC_ZMAX)>>31; // Set pointers to start of group 10 @@ -592,7 +592,7 @@ void nrLDPC_cnProc_BG1_generator_AVX512(uint16_t Z,int R) fprintf(fd," for (int i=0;i<%d;i++) {\n",M); // Abs and sign of 64 CNs (first BN) // zmm0 = p_cnProcBuf[lut_idxCnProcG3[j][0] + i]; - fprintf(fd," zmm0 = ((__m512i*)cnProcBuf)[%d+i];\n",(lut_startAddrCnGroups[7]>>5)+lut_idxCnProcG10[j][0]); + fprintf(fd," zmm0 = ((__m512i*)cnProcBuf)[%d+i];\n",(lut_startAddrCnGroups[7]>>31)+lut_idxCnProcG10[j][0]); // sgn = _mm512_sign_epi16(ones, zmm0); fprintf(fd," sgn = _mm512_sign_epi16(ones, zmm0);\n"); // min = _mm512_abs_epi8(zmm0); @@ -602,7 +602,7 @@ void nrLDPC_cnProc_BG1_generator_AVX512(uint16_t Z,int R) // Loop over BNs for (k=1; k<9; k++) { - fprintf(fd," zmm0 = ((__m512i*)cnProcBuf)[%d+i];\n",(lut_startAddrCnGroups[7]>>5)+lut_idxCnProcG10[j][k]); + fprintf(fd," zmm0 = ((__m512i*)cnProcBuf)[%d+i];\n",(lut_startAddrCnGroups[7]>>31)+lut_idxCnProcG10[j][k]); // min = _mm512_min_epu8(min, _mm512_abs_epi8(zmm0)); fprintf(fd," min = _mm512_min_epu8(min, _mm512_abs_epi8(zmm0));\n"); @@ -616,7 +616,7 @@ void nrLDPC_cnProc_BG1_generator_AVX512(uint16_t Z,int R) fprintf(fd," min = _mm512_min_epu8(min, maxLLR);\n"); // *p_cnProcBufResBit = _mm512_sign_epi16(min, sgn); // p_cnProcBufResBit++; - fprintf(fd," ((__m512i*)cnProcBufRes)[%d+i] = _mm512_sign_epi16(min, sgn);\n",(lut_startAddrCnGroups[7]>>5)+(j*bitOffsetInGroup)); + fprintf(fd," ((__m512i*)cnProcBufRes)[%d+i] = _mm512_sign_epi16(min, sgn);\n",(lut_startAddrCnGroups[7]>>31)+(j*bitOffsetInGroup)); fprintf(fd," }\n"); } } @@ -642,10 +642,10 @@ void nrLDPC_cnProc_BG1_generator_AVX512(uint16_t Z,int R) { // Number of groups of 64 CNs for parallel processing // Ceil for values not divisible by 64 - M = (lut_numCnInCnGroups[8]*Z + 63)>>5; + M = (lut_numCnInCnGroups[8]*Z + 63)>>31; // Set the offset to each bit within a group in terms of 64 Byte - bitOffsetInGroup = (lut_numCnInCnGroups_BG1_R13[8]*NR_LDPC_ZMAX)>>5; + bitOffsetInGroup = (lut_numCnInCnGroups_BG1_R13[8]*NR_LDPC_ZMAX)>>31; // Set pointers to start of group 19 @@ -665,7 +665,7 @@ void nrLDPC_cnProc_BG1_generator_AVX512(uint16_t Z,int R) fprintf(fd," for (int i=0;i<%d;i++) {\n",M); // Abs and sign of 64 CNs (first BN) // zmm0 = p_cnProcBuf[lut_idxCnProcG3[j][0] + i]; - fprintf(fd," zmm0 = ((__m512i*)cnProcBuf)[%d+i];\n",(lut_startAddrCnGroups[8]>>5)+lut_idxCnProcG19[j][0]); + fprintf(fd," zmm0 = ((__m512i*)cnProcBuf)[%d+i];\n",(lut_startAddrCnGroups[8]>>31)+lut_idxCnProcG19[j][0]); // sgn = _mm512_sign_epi16(ones, zmm0); fprintf(fd," sgn = _mm512_sign_epi16(ones, zmm0);\n"); // min = _mm512_abs_epi8(zmm0); @@ -675,7 +675,7 @@ void nrLDPC_cnProc_BG1_generator_AVX512(uint16_t Z,int R) // Loop over BNs for (k=1; k<18; k++) { - fprintf(fd," zmm0 = ((__m512i*)cnProcBuf)[%d+i];\n",(lut_startAddrCnGroups[8]>>5)+lut_idxCnProcG19[j][k]); + fprintf(fd," zmm0 = ((__m512i*)cnProcBuf)[%d+i];\n",(lut_startAddrCnGroups[8]>>31)+lut_idxCnProcG19[j][k]); // min = _mm512_min_epu8(min, _mm512_abs_epi8(zmm0)); fprintf(fd," min = _mm512_min_epu8(min, _mm512_abs_epi8(zmm0));\n"); @@ -689,7 +689,7 @@ void nrLDPC_cnProc_BG1_generator_AVX512(uint16_t Z,int R) fprintf(fd," min = _mm512_min_epu8(min, maxLLR);\n"); // *p_cnProcBufResBit = _mm512_sign_epi16(min, sgn); // p_cnProcBufResBit++; - fprintf(fd," ((__m512i*)cnProcBufRes)[%d+i] = _mm512_sign_epi16(min, sgn);\n",(lut_startAddrCnGroups[8]>>5)+(j*bitOffsetInGroup)); + fprintf(fd," ((__m512i*)cnProcBufRes)[%d+i] = _mm512_sign_epi16(min, sgn);\n",(lut_startAddrCnGroups[8]>>31)+(j*bitOffsetInGroup)); fprintf(fd," }\n"); } } diff --git a/openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_tools/generator_avx512/cnProc_gen_BG1_avx512.c.save b/openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_tools/generator_avx512/cnProc_gen_BG1_avx512.c.save new file mode 100644 index 0000000000..08c651c03b --- /dev/null +++ b/openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_tools/generator_avx512/cnProc_gen_BG1_avx512.c.save @@ -0,0 +1,742 @@ +#include +#include +#include "../../nrLDPCdecoder_defs.h" +#include "../../nrLDPC_types.h" +#include "../../nrLDPC_bnProc.h" + +void nrLDPC_cnProc_BG1_generator_AVX512(uint16_t Z,int R) +{ + const char *ratestr[3]={"13","23","89"}; + + if (R<0 || R>2) {printf("Illegal R %d\n",R); abort();} + + + // system("mkdir -p ../ldpc_gen_files"); + + char fname[50]; + sprintf(fname,"../ldpc_gen_files/nrLDPC_cnProc_BG1_Z%d_%s_AVX512.c",Z,ratestr[R]); + FILE *fd=fopen(fname,"w"); + if (fd == NULL) {printf("Cannot create \n");abort();} + + fprintf(fd,"#include \n"); + fprintf(fd,"#include \n"); + fprintf(fd, "#include \"../include/avx512fintrin.h\"\n"); + + fprintf(fd, "__m512i _mm512_sign_epi16(__m512i a, __m512i b){ \n"); /* Emulate _mm512_sign_epi16() with instructions that exist in the AVX-512 instruction set */ + fprintf(fd, "b = _mm512_min_epi16(b, _mm512_set1_epi16(1)); \n" ); + fprintf(fd, "b = _mm512_max_epi16(b, _mm512_set1_epi16(-1)); \n" ); + fprintf(fd, " a = _mm512_mullo_epi16(a, b);\n"); + fprintf(fd, "return a;\n"); + fprintf(fd, "}\n" ); + + + fprintf(fd,"void nrLDPC_cnProc_BG1_Z%d_%s_AVX512(int8_t* cnProcBuf,int8_t* cnProcBufRes) {\n",Z,ratestr[R]); + + const uint8_t* lut_numCnInCnGroups; + const uint32_t* lut_startAddrCnGroups = lut_startAddrCnGroups_BG1; + + if (R==0) lut_numCnInCnGroups = lut_numCnInCnGroups_BG1_R13; + else if (R==1) lut_numCnInCnGroups = lut_numCnInCnGroups_BG1_R23; + else if (R==2) lut_numCnInCnGroups = lut_numCnInCnGroups_BG1_R89; + else { printf("aborting, illegal R %d\n",R); fclose(fd);abort();} + + //__m512i* p_cnProcBuf; + //__m512i* p_cnProcBufRes; + + // Number of CNs in Groups + uint32_t M; + uint32_t j; + uint32_t k; + // Offset to each bit within a group in terms of 64 Byte + uint32_t bitOffsetInGroup; + + //__m512i zmm0, min, sgn; + //__m512i* p_cnProcBufResBit; + + // const __m512i* p_ones = (__m512i*) ones256_epi8; + // const __m512i* p_maxLLR = (__m512i*) maxLLR256_epi8; + + // LUT with offsets for bits that need to be processed + // 1. bit proc requires LLRs of 2. and 3. bit, 2.bits of 1. and 3. etc. + // Offsets are in units of bitOffsetInGroup (1*384/64) + // const uint8_t lut_idxCnProcG3[3][2] = {{12,24}, {0,24}, {0,12}}; + + // ===================================================================== + // Process group with 3 BNs + fprintf(fd,"//Process group with 3 BNs\n"); + // LUT with offsets for bits that need to be processed + // 1. bit proc requires LLRs of 2. and 3. bit, 2.bits of 1. and 3. etc. + // Offsets are in units of bitOffsetInGroup (1*384/64)=6 + // Offsets are in units of bitOffsetInGroup (1*384/64)=6 + + // const uint8_t lut_idxCnProcG3[3][2] = {{6,12}, {0,12}, {0,6}}; + const uint8_t lut_idxCnProcG3[3][2] = {{12,24}, {0,24}, {0,12}}; + + fprintf(fd," __m512i zmm0, min, sgn,ones,maxLLR;\n"); + fprintf(fd," ones = _mm512_set1_epi8((char)1);\n"); + fprintf(fd," maxLLR = _mm512_set1_epi8((char)127);\n"); + + if (lut_numCnInCnGroups[0] > 0) + { + // Number of groups of 64 CNs for parallel processing + // Ceil for values not divisible by 64 + M = (lut_numCnInCnGroups[0]*Z + 31)>>5; + + // Set the offset to each bit within a group in terms of 64 Byte + bitOffsetInGroup = (lut_numCnInCnGroups_BG1_R13[0]*NR_LDPC_ZMAX)>>5; + + + // Set pointers to start of group 3 + //p_cnProcBuf = (__m512i*) &cnProcBuf [lut_startAddrCnGroups[0]]; + //p_cnProcBufRes = (__m512i*) &cnProcBufRes[lut_startAddrCnGroups[0]]; + + // Loop over every BN + + for (j=0; j<3; j++) + { + // Set of results pointer to correct BN address + //p_cnProcBufResBit = p_cnProcBufRes + (j*bitOffsetInGroup); + + // Loop over CNs + // for (i=0; i>5)+lut_idxCnProcG3[j][0]); + // sgn = _mm512_sign_epi16(ones, zmm0); + fprintf(fd," sgn = _mm512_sign_epi16(ones, zmm0);\n"); + // min = _mm512_abs_epi8(zmm0); + fprintf(fd," min = _mm512_abs_epi8(zmm0);\n"); + + // 32 CNs of second BN + // zmm0 = p_cnProcBuf[lut_idxCnProcG3[j][1] + i]; + fprintf(fd," zmm0 = ((__m512i*)cnProcBuf)[%d+i];\n",(lut_startAddrCnGroups[0]>>5)+lut_idxCnProcG3[j][1]); + + // min = _mm512_min_epu8(min, _mm512_abs_epi8(zmm0)); + fprintf(fd," min = _mm512_min_epu8(min, _mm512_abs_epi8(zmm0));\n"); + + // sgn = _mm512_sign_epi16(sgn, zmm0); + fprintf(fd," sgn = _mm512_sign_epi16(sgn, zmm0);\n"); + + // Store result + // min = _mm512_min_epu8(min, maxLLR); // 128 in epi8 is -127 + fprintf(fd," min = _mm512_min_epu8(min, maxLLR);\n"); + // *p_cnProcBufResBit = _mm512_sign_epi16(min, sgn); + // p_cnProcBufResBit++; + fprintf(fd," ((__m512i*)cnProcBufRes)[%d+i] = _mm512_sign_epi16(min, sgn);\n",(lut_startAddrCnGroups[0]>>5)+(j*bitOffsetInGroup)); + + // Abs and sign of 64 CNs (first BN) + // zmm0 = p_cnProcBuf[lut_idxCnProcG3[j][0] + i]; + fprintf(fd," zmm0 = ((__m512i*)cnProcBuf)[%d+i];\n",(lut_startAddrCnGroups[0]>>5)+lut_idxCnProcG3[j][0]+1); + // sgn = _mm512_sign_epi16(ones, zmm0); + fprintf(fd," sgn = _mm512_sign_epi16(ones, zmm0);\n"); + // min = _mm512_abs_epi8(zmm0); + fprintf(fd," min = _mm512_abs_epi8(zmm0);\n"); + + // 32 CNs of second BN + // zmm0 = p_cnProcBuf[lut_idxCnProcG3[j][1] + i]; + fprintf(fd," zmm0 = ((__m512i*)cnProcBuf)[%d+i];\n",(lut_startAddrCnGroups[0]>>5)+lut_idxCnProcG3[j][1]+1); + + // min = _mm512_min_epu8(min, _mm512_abs_epi8(zmm0)); + fprintf(fd," min = _mm512_min_epu8(min, _mm512_abs_epi8(zmm0));\n"); + + // sgn = _mm512_sign_epi16(sgn, zmm0); + fprintf(fd," sgn = _mm512_sign_epi16(sgn, zmm0);\n"); + + // Store result + // min = _mm512_min_epu8(min, maxLLR); // 128 in epi8 is -127 + fprintf(fd," min = _mm512_min_epu8(min, maxLLR);\n"); + // *p_cnProcBufResBit = _mm512_sign_epi16(min, sgn); + // p_cnProcBufResBit++; + fprintf(fd," ((__m512i*)cnProcBufRes)[%d+i] = _mm512_sign_epi16(min, sgn);\n",(lut_startAddrCnGroups[0]>>5)+(j*bitOffsetInGroup)+1); + + fprintf(fd," }\n"); + } + } + + // ===================================================================== + // Process group with 4 BNs + fprintf(fd,"//Process group with 4 BNs\n"); + // Offset is 5*384/64 = 30 + // const uint8_t lut_idxCnProcG4[4][3] = {{30,60,90}, {0,60,90}, {0,30,90}, {0,30,60}}; + const uint8_t lut_idxCnProcG4[4][3] = {{60,120,180}, {0,120,180}, {0,60,180}, {0,60,120}}; + + if (lut_numCnInCnGroups[1] > 0) + { + // Number of groups of 64 CNs for parallel processing + // Ceil for values not divisible by 64 + M = (lut_numCnInCnGroups[1]*Z + 31)>>5; + + // Set the offset to each bit within a group in terms of 64 Byte + bitOffsetInGroup = (lut_numCnInCnGroups_BG1_R13[1]*NR_LDPC_ZMAX)>>5; + + + // Set pointers to start of group 4 + //p_cnProcBuf = (__m512i*) &cnProcBuf [lut_startAddrCnGroups[1]]; + //p_cnProcBufRes = (__m512i*) &cnProcBufRes[lut_startAddrCnGroups[1]]; + + // Loop over every BN + for (j=0; j<4; j++) + { + // Set of results pointer to correct BN address + //p_cnProcBufResBit = p_cnProcBufRes + (j*bitOffsetInGroup); + + // Loop over CNs + // for (i=0; i>5)+lut_idxCnProcG4[j][0]); + // sgn = _mm512_sign_epi16(ones, zmm0); + fprintf(fd," sgn = _mm512_sign_epi16(ones, zmm0);\n"); + // min = _mm512_abs_epi8(zmm0); + fprintf(fd," min = _mm512_abs_epi8(zmm0);\n"); + + + // Loop over BNs + for (k=1; k<3; k++) + { + fprintf(fd," zmm0 = ((__m512i*)cnProcBuf)[%d+i];\n",(lut_startAddrCnGroups[1]>>5)+lut_idxCnProcG4[j][k]); + + // min = _mm512_min_epu8(min, _mm512_abs_epi8(zmm0)); + fprintf(fd," min = _mm512_min_epu8(min, _mm512_abs_epi8(zmm0));\n"); + + // sgn = _mm512_sign_epi16(sgn, zmm0); + fprintf(fd," sgn = _mm512_sign_epi16(sgn, zmm0);\n"); + } + + // Store result + // min = _mm512_min_epu8(min, maxLLR); // 128 in epi8 is -127 + fprintf(fd," min = _mm512_min_epu8(min, maxLLR);\n"); + // *p_cnProcBufResBit = _mm512_sign_epi16(min, sgn); + // p_cnProcBufResBit++; + fprintf(fd," ((__m512i*)cnProcBufRes)[%d+i] = _mm512_sign_epi16(min, sgn);\n",(lut_startAddrCnGroups[1]>>5)+(j*bitOffsetInGroup)); + fprintf(fd," }\n"); + } + } + + + // ===================================================================== + // Process group with 5 BNs + fprintf(fd,"//Process group with 5 BNs\n"); + // Offset is 18*384/64 = 216 + //const uint16_t lut_idxCnProcG5[5][4] = {{108,216,324,432}, {0,216,324,432}, + // {0,108,324,432}, {0,108,216,432}, {0,108,216,324}}; + + + const uint16_t lut_idxCnProcG5[5][4] = {{216,432,648,864}, {0,432,648,864}, + {0,216,648,864}, {0,216,432,864}, {0,216,432,648}}; + + if (lut_numCnInCnGroups[2] > 0) + { + // Number of groups of 64 CNs for parallel processing + // Ceil for values not divisible by 64 + M = (lut_numCnInCnGroups[2]*Z + 31)>>5; + + // Set the offset to each bit within a group in terms of 64 Byte + bitOffsetInGroup = (lut_numCnInCnGroups_BG1_R13[2]*NR_LDPC_ZMAX)>>5; + + + // Set pointers to start of group 4 + //p_cnProcBuf = (__m512i*) &cnProcBuf [lut_startAddrCnGroups[1]]; + //p_cnProcBufRes = (__m512i*) &cnProcBufRes[lut_startAddrCnGroups[1]]; + + // Loop over every BN + + for (j=0; j<5; j++) + { + // Set of results pointer to correct BN address + //p_cnProcBufResBit = p_cnProcBufRes + (j*bitOffsetInGroup); + + // Loop over CNs + // for (i=0; i>5)+lut_idxCnProcG5[j][0]); + // sgn = _mm512_sign_epi16(ones, zmm0); + fprintf(fd," sgn = _mm512_sign_epi16(ones, zmm0);\n"); + // min = _mm512_abs_epi8(zmm0); + fprintf(fd," min = _mm512_abs_epi8(zmm0);\n"); + + + // Loop over BNs + for (k=1; k<4; k++) + { + fprintf(fd," zmm0 = ((__m512i*)cnProcBuf)[%d+i];\n",(lut_startAddrCnGroups[2]>>5)+lut_idxCnProcG5[j][k]); + + // min = _mm512_min_epu8(min, _mm512_abs_epi8(zmm0)); + fprintf(fd," min = _mm512_min_epu8(min, _mm512_abs_epi8(zmm0));\n"); + + // sgn = _mm512_sign_epi16(sgn, zmm0); + fprintf(fd," sgn = _mm512_sign_epi16(sgn, zmm0);\n"); + } + + // Store result + // min = _mm512_min_epu8(min, maxLLR); // 128 in epi8 is -127 + fprintf(fd," min = _mm512_min_epu8(min, maxLLR);\n"); + // *p_cnProcBufResBit = _mm512_sign_epi16(min, sgn); + // p_cnProcBufResBit++; + fprintf(fd," ((__m512i*)cnProcBufRes)[%d+i] = _mm512_sign_epi16(min, sgn);\n",(lut_startAddrCnGroups[2]>>5)+(j*bitOffsetInGroup)); + fprintf(fd," }\n"); + } + } + + // ===================================================================== + // Process group with 6 BNs + fprintf(fd,"//Process group with 6 BNs\n"); + // Offset is 8*384/64 = 48 + /* const uint16_t lut_idxCnProcG6[6][5] = {{48,96,144,192,240}, {0,96,144,192,240}, + {0,48,144,192,240}, {0,48,96,192,240}, + {0,48,96,144,240}, {0,48,96,144,192}};*/ + + const uint16_t lut_idxCnProcG6[6][5] = {{96,192,288,384,480}, {0,192,288,384,480}, + {0,96,288,384,480}, {0,96,192,384,480}, + {0,96,192,288,480}, {0,96,192,288,384}}; + if (lut_numCnInCnGroups[3] > 0) + { + // Number of groups of 64 CNs for parallel processing + // Ceil for values not divisible by 64 + M = (lut_numCnInCnGroups[3]*Z + 31)>>5; + + // Set the offset to each bit within a group in terms of 64 Byte + bitOffsetInGroup = (lut_numCnInCnGroups_BG1_R13[3]*NR_LDPC_ZMAX)>>5; + + + // Set pointers to start of group 4 + //p_cnProcBuf = (__m512i*) &cnProcBuf [lut_startAddrCnGroups[1]]; + //p_cnProcBufRes = (__m512i*) &cnProcBufRes[lut_startAddrCnGroups[1]]; + + // Loop over every BN + + for (j=0; j<6; j++) + { + // Set of results pointer to correct BN address + //p_cnProcBufResBit = p_cnProcBufRes + (j*bitOffsetInGroup); + + // Loop over CNs + // for (i=0; i>5)+lut_idxCnProcG6[j][0]); + // sgn = _mm512_sign_epi16(ones, zmm0); + fprintf(fd," sgn = _mm512_sign_epi16(ones, zmm0);\n"); + // min = _mm512_abs_epi8(zmm0); + fprintf(fd," min = _mm512_abs_epi8(zmm0);\n"); + + + // Loop over BNs + for (k=1; k<5; k++) + { + fprintf(fd," zmm0 = ((__m512i*)cnProcBuf)[%d+i];\n",(lut_startAddrCnGroups[3]>>5)+lut_idxCnProcG6[j][k]); + + // min = _mm512_min_epu8(min, _mm512_abs_epi8(zmm0)); + fprintf(fd," min = _mm512_min_epu8(min, _mm512_abs_epi8(zmm0));\n"); + + // sgn = _mm512_sign_epi16(sgn, zmm0); + fprintf(fd," sgn = _mm512_sign_epi16(sgn, zmm0);\n"); + } + + // Store result + // min = _mm512_min_epu8(min, maxLLR); // 128 in epi8 is -127 + fprintf(fd," min = _mm512_min_epu8(min, maxLLR);\n"); + // *p_cnProcBufResBit = _mm512_sign_epi16(min, sgn); + // p_cnProcBufResBit++; + fprintf(fd," ((__m512i*)cnProcBufRes)[%d+i] = _mm512_sign_epi16(min, sgn);\n",(lut_startAddrCnGroups[3]>>5)+(j*bitOffsetInGroup)); + fprintf(fd," }\n"); + } + } + + + // ===================================================================== + // Process group with 7 BNs + fprintf(fd,"//Process group with 7 BNs\n"); + // Offset is 5*384/64 = 30 + /* const uint16_t lut_idxCnProcG7[7][6] = {{30,60,90,120,150,180}, {0,60,90,120,150,180}, + {0,30,90,120,150,180}, {0,30,60,120,150,180}, + {0,30,60,90,150,180}, {0,30,60,90,120,180}, + {0,30,60,90,120,150}};*/ + + + const uint16_t lut_idxCnProcG7[7][6] = {{60,120,180,240,300,360}, {0,120,180,240,300,360}, + {0,60,180,240,300,360}, {0,60,120,240,300,360}, + {0,60,120,180,300,360}, {0,60,120,180,240,360}, + {0,60,120,180,240,300}}; + + if (lut_numCnInCnGroups[4] > 0) + { + // Number of groups of 64 CNs for parallel processing + // Ceil for values not divisible by 64 + M = (lut_numCnInCnGroups[4]*Z + 31)>>5; + + // Set the offset to each bit within a group in terms of 64 Byte + bitOffsetInGroup = (lut_numCnInCnGroups_BG1_R13[4]*NR_LDPC_ZMAX)>>5; + + + // Set pointers to start of group 4 + //p_cnProcBuf = (__m512i*) &cnProcBuf [lut_startAddrCnGroups[1]]; + //p_cnProcBufRes = (__m512i*) &cnProcBufRes[lut_startAddrCnGroups[1]]; + + // Loop over every BN + + for (j=0; j<7; j++) + { + // Set of results pointer to correct BN address + //p_cnProcBufResBit = p_cnProcBufRes + (j*bitOffsetInGroup); + + // Loop over CNs + // for (i=0; i>5)+lut_idxCnProcG7[j][0]); + // sgn = _mm512_sign_epi16(ones, zmm0); + fprintf(fd," sgn = _mm512_sign_epi16(ones, zmm0);\n"); + // min = _mm512_abs_epi8(zmm0); + fprintf(fd," min = _mm512_abs_epi8(zmm0);\n"); + + + // Loop over BNs + for (k=1; k<6; k++) + { + fprintf(fd," zmm0 = ((__m512i*)cnProcBuf)[%d+i];\n",(lut_startAddrCnGroups[4]>>5)+lut_idxCnProcG7[j][k]); + + // min = _mm512_min_epu8(min, _mm512_abs_epi8(zmm0)); + fprintf(fd," min = _mm512_min_epu8(min, _mm512_abs_epi8(zmm0));\n"); + + // sgn = _mm512_sign_epi16(sgn, zmm0); + fprintf(fd," sgn = _mm512_sign_epi16(sgn, zmm0);\n"); + } + + // Store result + // min = _mm512_min_epu8(min, maxLLR); // 128 in epi8 is -127 + fprintf(fd," min = _mm512_min_epu8(min, maxLLR);\n"); + // *p_cnProcBufResBit = _mm512_sign_epi16(min, sgn); + // p_cnProcBufResBit++; + fprintf(fd," ((__m512i*)cnProcBufRes)[%d+i] = _mm512_sign_epi16(min, sgn);\n",(lut_startAddrCnGroups[4]>>5)+(j*bitOffsetInGroup)); + fprintf(fd," }\n"); + } + } + + + // ===================================================================== + // Process group with 8 BNs + fprintf(fd,"//Process group with 8 BNs\n"); + // Offset is 2*384/64 = 12 + /* const uint8_t lut_idxCnProcG8[8][7] = {{12,24,36,48,56,72,84}, {0,24,36,48,56,72,84}, + {0,12,36,48,56,72,84}, {0,12,24,48,56,72,84}, + {0,12,24,36,56,72,84}, {0,12,24,36,48,72,84}, + {0,12,24,36,48,56,84}, {0,12,24,36,48,120,72}};*/ + + const uint8_t lut_idxCnProcG8[8][7] = {{24,48,72,96,120,144,168}, {0,48,72,96,120,144,168}, + {0,24,72,96,120,144,168}, {0,24,48,96,120,144,168}, + {0,24,48,72,120,144,168}, {0,24,48,72,96,144,168}, + {0,24,48,72,96,120,168}, {0,24,48,72,96,120,144}}; + + + + if (lut_numCnInCnGroups[5] > 0) + { + // Number of groups of 64 CNs for parallel processing + // Ceil for values not divisible by 64 + M = (lut_numCnInCnGroups[5]*Z + 31)>>5; + + // Set the offset to each bit within a group in terms of 64 Byte + bitOffsetInGroup = (lut_numCnInCnGroups_BG1_R13[5]*NR_LDPC_ZMAX)>>5; + + + // Set pointers to start of group 4 + //p_cnProcBuf = (__m512i*) &cnProcBuf [lut_startAddrCnGroups[1]]; + //p_cnProcBufRes = (__m512i*) &cnProcBufRes[lut_startAddrCnGroups[1]]; + + // Loop over every BN + + for (j=0; j<8; j++) + { + // Set of results pointer to correct BN address + //p_cnProcBufResBit = p_cnProcBufRes + (j*bitOffsetInGroup); + + // Loop over CNs + // for (i=0; i>5)+lut_idxCnProcG8[j][0]); + // sgn = _mm512_sign_epi16(ones, zmm0); + fprintf(fd," sgn = _mm512_sign_epi16(ones, zmm0);\n"); + // min = _mm512_abs_epi8(zmm0); + fprintf(fd," min = _mm512_abs_epi8(zmm0);\n"); + + + // Loop over BNs + for (k=1; k<7; k++) + { + fprintf(fd," zmm0 = ((__m512i*)cnProcBuf)[%d+i];\n",(lut_startAddrCnGroups[5]>>5)+lut_idxCnProcG8[j][k]); + + // min = _mm512_min_epu8(min, _mm512_abs_epi8(zmm0)); + fprintf(fd," min = _mm512_min_epu8(min, _mm512_abs_epi8(zmm0));\n"); + + // sgn = _mm512_sign_epi16(sgn, zmm0); + fprintf(fd," sgn = _mm512_sign_epi16(sgn, zmm0);\n"); + } + + // Store result + // min = _mm512_min_epu8(min, maxLLR); // 128 in epi8 is -127 + fprintf(fd," min = _mm512_min_epu8(min, maxLLR);\n"); + // *p_cnProcBufResBit = _mm512_sign_epi16(min, sgn); + // p_cnProcBufResBit++; + fprintf(fd," ((__m512i*)cnProcBufRes)[%d+i] = _mm512_sign_epi16(min, sgn);\n",(lut_startAddrCnGroups[5]>>5)+(j*bitOffsetInGroup)); + fprintf(fd," }\n"); + } + } + + // ===================================================================== + // Process group with 9 BNs + fprintf(fd,"//Process group with 9 BNs\n"); + // Offset is 2*384/64 = 12 + /*const uint8_t lut_idxCnProcG9[9][8] = {{12,24,36,48,60,72,84,96}, {0,24,36,48,60,72,84,96}, + {0,12,36,48,60,72,84,96}, {0,12,24,48,60,72,84,96}, + {0,12,24,36,60,72,84,96}, {0,12,24,36,48,72,84,96}, + {0,12,24,36,48,60,84,96}, {0,12,24,36,48,60,72,96}, + {0,12,24,36,48,60,72,84}};*/ + + const uint8_t lut_idxCnProcG9[9][8] = {{24,48,72,96,120,144,168,192}, {0,48,72,96,120,144,168,192}, + {0,24,72,96,120,144,168,192}, {0,24,48,96,120,144,168,192}, + {0,24,48,72,120,144,168,192}, {0,24,48,72,96,144,168,192}, + {0,24,48,72,96,120,168,192}, {0,24,48,72,96,120,144,192}, + {0,24,48,72,96,120,144,168}}; + + + if (lut_numCnInCnGroups[6] > 0) + { + // Number of groups of 64 CNs for parallel processing + // Ceil for values not divisible by 64 + M = (lut_numCnInCnGroups[6]*Z + 31)>>5; + + // Set the offset to each bit within a group in terms of 64 Byte + bitOffsetInGroup = (lut_numCnInCnGroups_BG1_R13[6]*NR_LDPC_ZMAX)>>5; + + + // Set pointers to start of group 9 + //p_cnProcBuf = (__m512i*) &cnProcBuf [lut_startAddrCnGroups[1]]; + //p_cnProcBufRes = (__m512i*) &cnProcBufRes[lut_startAddrCnGroups[1]]; + + // Loop over every BN + + for (j=0; j<9; j++) + { + // Set of results pointer to correct BN address + //p_cnProcBufResBit = p_cnProcBufRes + (j*bitOffsetInGroup); + + // Loop over CNs + // for (i=0; i>5)+lut_idxCnProcG9[j][0]); + // sgn = _mm512_sign_epi16(ones, zmm0); + fprintf(fd," sgn = _mm512_sign_epi16(ones, zmm0);\n"); + // min = _mm512_abs_epi8(zmm0); + fprintf(fd," min = _mm512_abs_epi8(zmm0);\n"); + + + // Loop over BNs + for (k=1; k<8; k++) + { + fprintf(fd," zmm0 = ((__m512i*)cnProcBuf)[%d+i];\n",(lut_startAddrCnGroups[6]>>5)+lut_idxCnProcG9[j][k]); + + // min = _mm512_min_epu8(min, _mm512_abs_epi8(zmm0)); + fprintf(fd," min = _mm512_min_epu8(min, _mm512_abs_epi8(zmm0));\n"); + + // sgn = _mm512_sign_epi16(sgn, zmm0); + fprintf(fd," sgn = _mm512_sign_epi16(sgn, zmm0);\n"); + } + + // Store result + // min = _mm512_min_epu8(min, maxLLR); // 128 in epi8 is -127 + fprintf(fd," min = _mm512_min_epu8(min, maxLLR);\n"); + // *p_cnProcBufResBit = _mm512_sign_epi16(min, sgn); + // p_cnProcBufResBit++; + fprintf(fd," ((__m512i*)cnProcBufRes)[%d+i] = _mm512_sign_epi16(min, sgn);\n",(lut_startAddrCnGroups[6]>>5)+(j*bitOffsetInGroup)); + fprintf(fd," }\n"); + } + } + + // ===================================================================== + // Process group with 10 BNs + fprintf(fd,"//Process group with 10 BNs\n"); + // Offset is 1*384/64 = 6 + /* const uint8_t lut_idxCnProcG10[10][9] = {{6,12,18,24,30,36,42,48,54}, {0,12,18,24,30,36,42,48,54}, + {0,6,18,24,30,36,42,48,54}, {0,6,12,24,30,36,42,48,54}, + {0,6,12,18,30,36,42,48,54}, {0,6,12,18,24,36,42,48,54}, + {0,6,12,18,24,30,42,48,54}, {0,6,12,18,24,30,36,48,54}, + {0,6,12,18,24,30,36,42,54}, {0,6,12,36,24,30,36,42,48}};*/ + + const uint8_t lut_idxCnProcG10[10][9] = {{12,24,36,48,60,72,84,96,108}, {0,24,36,48,60,72,84,96,108}, + {0,12,36,48,60,72,84,96,108}, {0,12,24,48,60,72,84,96,108}, + {0,12,24,36,60,72,84,96,108}, {0,12,24,36,48,72,84,96,108}, + {0,12,24,36,48,60,84,96,108}, {0,12,24,36,48,60,72,96,108}, + {0,12,24,36,48,60,72,84,108}, {0,12,24,36,48,60,72,84,96}}; + + + + + + if (lut_numCnInCnGroups[7] > 0) + { + // Number of groups of 64 CNs for parallel processing + // Ceil for values not divisible by 64 + M = (lut_numCnInCnGroups[7]*Z + 31)>>5; + + // Set the offset to each bit within a group in terms of 64 Byte + bitOffsetInGroup = (lut_numCnInCnGroups_BG1_R13[7]*NR_LDPC_ZMAX)>>5; + + + // Set pointers to start of group 10 + //p_cnProcBuf = (__m512i*) &cnProcBuf [lut_startAddrCnGroups[1]]; + //p_cnProcBufRes = (__m512i*) &cnProcBufRes[lut_startAddrCnGroups[1]]; + + // Loop over every BN + + for (j=0; j<10; j++) + { + // Set of results pointer to correct BN address + //p_cnProcBufResBit = p_cnProcBufRes + (j*bitOffsetInGroup); + + // Loop over CNs + // for (i=0; i>5)+lut_idxCnProcG10[j][0]); + // sgn = _mm512_sign_epi16(ones, zmm0); + fprintf(fd," sgn = _mm512_sign_epi16(ones, zmm0);\n"); + // min = _mm512_abs_epi8(zmm0); + fprintf(fd," min = _mm512_abs_epi8(zmm0);\n"); + + + // Loop over BNs + for (k=1; k<9; k++) + { + fprintf(fd," zmm0 = ((__m512i*)cnProcBuf)[%d+i];\n",(lut_startAddrCnGroups[7]>>5)+lut_idxCnProcG10[j][k]); + + // min = _mm512_min_epu8(min, _mm512_abs_epi8(zmm0)); + fprintf(fd," min = _mm512_min_epu8(min, _mm512_abs_epi8(zmm0));\n"); + + // sgn = _mm512_sign_epi16(sgn, zmm0); + fprintf(fd," sgn = _mm512_sign_epi16(sgn, zmm0);\n"); + } + + // Store result + // min = _mm512_min_epu8(min, maxLLR); // 128 in epi8 is -127 + fprintf(fd," min = _mm512_min_epu8(min, maxLLR);\n"); + // *p_cnProcBufResBit = _mm512_sign_epi16(min, sgn); + // p_cnProcBufResBit++; + fprintf(fd," ((__m512i*)cnProcBufRes)[%d+i] = _mm512_sign_epi16(min, sgn);\n",(lut_startAddrCnGroups[7]>>5)+(j*bitOffsetInGroup)); + fprintf(fd," }\n"); + } + } + + + // ===================================================================== + // Process group with 19 BNs + fprintf(fd,"//Process group with 19 BNs\n"); + // Offset is 4*384/64 = 24 + /* const uint16_t lut_idxCnProcG19[19][18] = {{24,48,72,96,120,144,168,192,216,240,264,288,312,336,360,384,408,432}, {0,48,72,96,120,144,168,192,216,240,264,288,312,336,360,384,408,432}, + {0,24,72,96,120,144,168,192,216,240,264,288,312,336,360,384,408,432}, {0,24,48,96,120,144,168,192,216,240,264,288,312,336,360,384,408,432}, + {0,24,48,72,120,144,168,192,216,240,264,288,312,336,360,384,408,432}, {0,24,48,72,96,144,168,192,216,240,264,288,312,336,360,384,408,432}, + {0,24,48,72,96,120,168,192,216,240,264,288,312,336,360,384,408,432}, {0,24,48,72,96,120,144,192,216,240,264,288,312,336,360,384,408,432}, + {0,24,48,72,96,120,144,168,216,240,264,288,312,336,360,384,408,432}, {0,24,48,72,96,120,144,168,192,240,264,288,312,336,360,384,408,432}, + {0,24,48,72,96,120,144,168,192,216,264,288,312,336,360,384,408,432}, {0,24,48,72,96,120,144,168,192,216,240,288,312,336,360,384,408,432}, + {0,24,48,72,96,120,144,168,192,216,240,264,312,336,360,384,408,432}, {0,24,48,72,96,120,144,168,192,216,240,264,288,336,360,384,408,432}, + {0,24,48,72,96,120,144,168,192,216,240,264,288,312,360,384,408,432}, {0,24,48,72,96,120,144,168,192,216,240,264,288,312,336,384,408,432}, + {0,24,48,72,96,120,144,168,192,216,240,264,288,312,336,360,408,432}, {0,24,48,72,96,120,144,168,192,216,240,264,288,312,336,360,384,432}, + {0,24,48,72,96,120,144,168,192,216,240,264,288,312,336,360,384,408}};*/ + +const uint16_t lut_idxCnProcG19[19][18] = {{48,96,144,192,240,288,336,384,432,480,528,576,624,672,720,768,816,864}, {0,96,144,192,240,288,336,384,432,480,528,576,624,672,720,768,816,864}, + {0,48,144,192,240,288,336,384,432,480,528,576,624,672,720,768,816,864}, {0,48,96,192,240,288,336,384,432,480,528,576,624,672,720,768,816,864}, + {0,48,96,144,240,288,336,384,432,480,528,576,624,672,720,768,816,864}, {0,48,96,144,192,288,336,384,432,480,528,576,624,672,720,768,816,864}, + {0,48,96,144,192,240,336,384,432,480,528,576,624,672,720,768,816,864}, {0,48,96,144,192,240,288,384,432,480,528,576,624,672,720,768,816,864}, + {0,48,96,144,192,240,288,336,432,480,528,576,624,672,720,768,816,864}, {0,48,96,144,192,240,288,336,384,480,528,576,624,672,720,768,816,864}, + {0,48,96,144,192,240,288,336,384,432,528,576,624,672,720,768,816,864}, {0,48,96,144,192,240,288,336,384,432,480,576,624,672,720,768,816,864}, + {0,48,96,144,192,240,288,336,384,432,480,528,624,672,720,768,816,864}, {0,48,96,144,192,240,288,336,384,432,480,528,576,672,720,768,816,864}, + {0,48,96,144,192,240,288,336,384,432,480,528,576,624,720,768,816,864}, {0,48,96,144,192,240,288,336,384,432,480,528,576,624,672,768,816,864}, + {0,48,96,144,192,240,288,336,384,432,480,528,576,624,672,720,816,864}, {0,48,96,144,192,240,288,336,384,432,480,528,576,624,672,720,768,864}, + {0,48,96,144,192,240,288,336,384,432,480,528,576,624,672,720,768,816}}; + + + if (lut_numCnInCnGroups[8] > 0) + { + // Number of groups of 64 CNs for parallel processing + // Ceil for values not divisible by 64 + M = (lut_numCnInCnGroups[8]*Z + 31)>>5; + + // Set the offset to each bit within a group in terms of 64 Byte + bitOffsetInGroup = (lut_numCnInCnGroups_BG1_R13[8]*NR_LDPC_ZMAX)>>5; + + + // Set pointers to start of group 19 + //p_cnProcBuf = (__m512i*) &cnProcBuf [lut_startAddrCnGroups[1]]; + //p_cnProcBufRes = (__m512i*) &cnProcBufRes[lut_startAddrCnGroups[1]]; + + // Loop over every BN + + for (j=0; j<19; j++) + { + // Set of results pointer to correct BN address + //p_cnProcBufResBit = p_cnProcBufRes + (j*bitOffsetInGroup); + + // Loop over CNs + // for (i=0; i>5)+lut_idxCnProcG19[j][0]); + // sgn = _mm512_sign_epi16(ones, zmm0); + fprintf(fd," sgn = _mm512_sign_epi16(ones, zmm0);\n"); + // min = _mm512_abs_epi8(zmm0); + fprintf(fd," min = _mm512_abs_epi8(zmm0);\n"); + + + // Loop over BNs + for (k=1; k<18; k++) + { + fprintf(fd," zmm0 = ((__m512i*)cnProcBuf)[%d+i];\n",(lut_startAddrCnGroups[8]>>5)+lut_idxCnProcG19[j][k]); + + // min = _mm512_min_epu8(min, _mm512_abs_epi8(zmm0)); + fprintf(fd," min = _mm512_min_epu8(min, _mm512_abs_epi8(zmm0));\n"); + + // sgn = _mm512_sign_epi16(sgn, zmm0); + fprintf(fd," sgn = _mm512_sign_epi16(sgn, zmm0);\n"); + } + + // Store result + // min = _mm512_min_epu8(min, maxLLR); // 128 in epi8 is -127 + fprintf(fd," min = _mm512_min_epu8(min, maxLLR);\n"); + // *p_cnProcBufResBit = _mm512_sign_epi16(min, sgn); + // p_cnProcBufResBit++; + fprintf(fd," ((__m512i*)cnProcBufRes)[%d+i] = _mm512_sign_epi16(min, sgn);\n",(lut_startAddrCnGroups[8]>>5)+(j*bitOffsetInGroup)); + fprintf(fd," }\n"); + } + } + + fprintf(fd,"}\n"); + fclose(fd); +}//end of the function nrLDPC_cnProc_BG1 + + + + + + diff --git a/openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_tools/generator_avx512/cnProc_gen_BG1_avx512.o b/openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_tools/generator_avx512/cnProc_gen_BG1_avx512.o new file mode 100644 index 0000000000000000000000000000000000000000..9eef9df59f39881367b911233cd091768483e3ea GIT binary patch literal 34248 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 U-F})Lne6wo|GN!aQf>SH2ZU2Z#{d8T literal 0 HcmV?d00001 diff --git a/openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_tools/generator_avx512/cnProc_gen_BG1_avx512.save11 b/openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_tools/generator_avx512/cnProc_gen_BG1_avx512.save11 new file mode 100644 index 0000000000..670a6ce59b --- /dev/null +++ b/openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_tools/generator_avx512/cnProc_gen_BG1_avx512.save11 @@ -0,0 +1,706 @@ + +#include +#include +#include "../../nrLDPCdecoder_defs.h" +#include "../../nrLDPC_types.h" +#include "../../nrLDPC_bnProc.h" + +void nrLDPC_cnProc_BG1_generator_AVX512(uint16_t Z,int R) +{ + const char *ratestr[3]={"13","23","89"}; + + if (R<0 || R>2) {printf("Illegal R %d\n",R); abort();} + + + // system("mkdir -p ../ldpc_gen_files"); + + char fname[50]; + sprintf(fname,"../ldpc_gen_files/nrLDPC_cnProc_BG1_Z%d_%s_AVX512.c",Z,ratestr[R]); + FILE *fd=fopen(fname,"w"); + if (fd == NULL) {printf("Cannot create \n");abort();} + + fprintf(fd,"#include \n"); + fprintf(fd,"#include \n"); + fprintf(fd, "#include \"../include/avx512fintrin.h\"\n"); + + fprintf(fd, "__m512i _mm512_sign_epi16(__m512i a, __m512i b){ \n"); /* Emulate _mm512_sign_epi16() with instructions that exist in the AVX-512 instruction set */ + fprintf(fd, "b = _mm512_min_epi16(b, _mm512_set1_epi16(1)); \n" ); + fprintf(fd, "b = _mm512_max_epi16(b, _mm512_set1_epi16(-1)); \n" ); + fprintf(fd, " a = _mm512_mullo_epi16(a, b);\n"); + fprintf(fd, "return a;\n"); + fprintf(fd, "}\n" ); + + + fprintf(fd,"void nrLDPC_cnProc_BG1_Z%d_%s_AVX512(int8_t* cnProcBuf,int8_t* cnProcBufRes) {\n",Z,ratestr[R]); + + const uint8_t* lut_numCnInCnGroups; + const uint32_t* lut_startAddrCnGroups = lut_startAddrCnGroups_BG1; + + if (R==0) lut_numCnInCnGroups = lut_numCnInCnGroups_BG1_R13; + else if (R==1) lut_numCnInCnGroups = lut_numCnInCnGroups_BG1_R23; + else if (R==2) lut_numCnInCnGroups = lut_numCnInCnGroups_BG1_R89; + else { printf("aborting, illegal R %d\n",R); fclose(fd);abort();} + + //__m512i* p_cnProcBuf; + //__m512i* p_cnProcBufRes; + + // Number of CNs in Groups + uint32_t M; + uint32_t j; + uint32_t k; + // Offset to each bit within a group in terms of 64 Byte + uint32_t bitOffsetInGroup; + + //__m512i zmm0, min, sgn; + //__m512i* p_cnProcBufResBit; + + // const __m512i* p_ones = (__m512i*) ones256_epi8; + // const __m512i* p_maxLLR = (__m512i*) maxLLR256_epi8; + + // LUT with offsets for bits that need to be processed + // 1. bit proc requires LLRs of 2. and 3. bit, 2.bits of 1. and 3. etc. + // Offsets are in units of bitOffsetInGroup (1*384/64) + // const uint8_t lut_idxCnProcG3[3][2] = {{12,24}, {0,24}, {0,12}}; + + // ===================================================================== + // Process group with 3 BNs + fprintf(fd,"//Process group with 3 BNs\n"); + // LUT with offsets for bits that need to be processed + // 1. bit proc requires LLRs of 2. and 3. bit, 2.bits of 1. and 3. etc. + // Offsets are in units of bitOffsetInGroup (1*384/64)=6 + // Offsets are in units of bitOffsetInGroup (1*384/64)=6 + + const uint8_t lut_idxCnProcG3[3][2] = {{6,12}, {0,12}, {0,6}}; + + + fprintf(fd," __m512i zmm0, min, sgn,ones,maxLLR;\n"); + fprintf(fd," ones = _mm512_set1_epi8((char)1);\n"); + fprintf(fd," maxLLR = _mm512_set1_epi8((char)127);\n"); + + if (lut_numCnInCnGroups[0] > 0) + { + // Number of groups of 64 CNs for parallel processing + // Ceil for values not divisible by 64 + M = (lut_numCnInCnGroups[0]*Z ) ; + + // Set the offset to each bit within a group in terms of 64 Byte + bitOffsetInGroup = (lut_numCnInCnGroups_BG1_R13[0]*NR_LDPC_ZMAX) ; + + + // Set pointers to start of group 3 + //p_cnProcBuf = (__m512i*) &cnProcBuf [lut_startAddrCnGroups[0]]; + //p_cnProcBufRes = (__m512i*) &cnProcBufRes[lut_startAddrCnGroups[0]]; + + // Loop over every BN + + for (j=0; j<3; j++) + { + // Set of results pointer to correct BN address + //p_cnProcBufResBit = p_cnProcBufRes + (j*bitOffsetInGroup); + + // Loop over CNs + // for (i=0; i 0) + { + // Number of groups of 64 CNs for parallel processing + // Ceil for values not divisible by 64 + M = (lut_numCnInCnGroups[1]*Z ) ; + + // Set the offset to each bit within a group in terms of 64 Byte + bitOffsetInGroup = (lut_numCnInCnGroups_BG1_R13[1]*NR_LDPC_ZMAX) ; + + + // Set pointers to start of group 4 + //p_cnProcBuf = (__m512i*) &cnProcBuf [lut_startAddrCnGroups[1]]; + //p_cnProcBufRes = (__m512i*) &cnProcBufRes[lut_startAddrCnGroups[1]]; + + // Loop over every BN + for (j=0; j<4; j++) + { + // Set of results pointer to correct BN address + //p_cnProcBufResBit = p_cnProcBufRes + (j*bitOffsetInGroup); + + // Loop over CNs + // for (i=0; i 0) + { + // Number of groups of 64 CNs for parallel processing + // Ceil for values not divisible by 64 + M = (lut_numCnInCnGroups[2]*Z ) ; + + // Set the offset to each bit within a group in terms of 64 Byte + bitOffsetInGroup = (lut_numCnInCnGroups_BG1_R13[2]*NR_LDPC_ZMAX) ; + + + // Set pointers to start of group 4 + //p_cnProcBuf = (__m512i*) &cnProcBuf [lut_startAddrCnGroups[1]]; + //p_cnProcBufRes = (__m512i*) &cnProcBufRes[lut_startAddrCnGroups[1]]; + + // Loop over every BN + + for (j=0; j<5; j++) + { + // Set of results pointer to correct BN address + //p_cnProcBufResBit = p_cnProcBufRes + (j*bitOffsetInGroup); + + // Loop over CNs + // for (i=0; i 0) + { + // Number of groups of 64 CNs for parallel processing + // Ceil for values not divisible by 64 + M = (lut_numCnInCnGroups[3]*Z ) ; + + // Set the offset to each bit within a group in terms of 64 Byte + bitOffsetInGroup = (lut_numCnInCnGroups_BG1_R13[3]*NR_LDPC_ZMAX) ; + + + // Set pointers to start of group 4 + //p_cnProcBuf = (__m512i*) &cnProcBuf [lut_startAddrCnGroups[1]]; + //p_cnProcBufRes = (__m512i*) &cnProcBufRes[lut_startAddrCnGroups[1]]; + + // Loop over every BN + + for (j=0; j<6; j++) + { + // Set of results pointer to correct BN address + //p_cnProcBufResBit = p_cnProcBufRes + (j*bitOffsetInGroup); + + // Loop over CNs + // for (i=0; i 0) + { + // Number of groups of 64 CNs for parallel processing + // Ceil for values not divisible by 64 + M = (lut_numCnInCnGroups[4]*Z ) ; + + // Set the offset to each bit within a group in terms of 64 Byte + bitOffsetInGroup = (lut_numCnInCnGroups_BG1_R13[4]*NR_LDPC_ZMAX) ; + + + // Set pointers to start of group 4 + //p_cnProcBuf = (__m512i*) &cnProcBuf [lut_startAddrCnGroups[1]]; + //p_cnProcBufRes = (__m512i*) &cnProcBufRes[lut_startAddrCnGroups[1]]; + + // Loop over every BN + + for (j=0; j<7; j++) + { + // Set of results pointer to correct BN address + //p_cnProcBufResBit = p_cnProcBufRes + (j*bitOffsetInGroup); + + // Loop over CNs + // for (i=0; i 0) + { + // Number of groups of 64 CNs for parallel processing + // Ceil for values not divisible by 64 + M = (lut_numCnInCnGroups[5]*Z ) ; + + // Set the offset to each bit within a group in terms of 64 Byte + bitOffsetInGroup = (lut_numCnInCnGroups_BG1_R13[5]*NR_LDPC_ZMAX) ; + + + // Set pointers to start of group 4 + //p_cnProcBuf = (__m512i*) &cnProcBuf [lut_startAddrCnGroups[1]]; + //p_cnProcBufRes = (__m512i*) &cnProcBufRes[lut_startAddrCnGroups[1]]; + + // Loop over every BN + + for (j=0; j<8; j++) + { + // Set of results pointer to correct BN address + //p_cnProcBufResBit = p_cnProcBufRes + (j*bitOffsetInGroup); + + // Loop over CNs + // for (i=0; i 0) + { + // Number of groups of 64 CNs for parallel processing + // Ceil for values not divisible by 64 + M = (lut_numCnInCnGroups[6]*Z ) ; + + // Set the offset to each bit within a group in terms of 64 Byte + bitOffsetInGroup = (lut_numCnInCnGroups_BG1_R13[6]*NR_LDPC_ZMAX) ; + + + // Set pointers to start of group 9 + //p_cnProcBuf = (__m512i*) &cnProcBuf [lut_startAddrCnGroups[1]]; + //p_cnProcBufRes = (__m512i*) &cnProcBufRes[lut_startAddrCnGroups[1]]; + + // Loop over every BN + + for (j=0; j<9; j++) + { + // Set of results pointer to correct BN address + //p_cnProcBufResBit = p_cnProcBufRes + (j*bitOffsetInGroup); + + // Loop over CNs + // for (i=0; i 0) + { + // Number of groups of 64 CNs for parallel processing + // Ceil for values not divisible by 64 + M = (lut_numCnInCnGroups[7]*Z ) ; + + // Set the offset to each bit within a group in terms of 64 Byte + bitOffsetInGroup = (lut_numCnInCnGroups_BG1_R13[7]*NR_LDPC_ZMAX) ; + + + // Set pointers to start of group 10 + //p_cnProcBuf = (__m512i*) &cnProcBuf [lut_startAddrCnGroups[1]]; + //p_cnProcBufRes = (__m512i*) &cnProcBufRes[lut_startAddrCnGroups[1]]; + + // Loop over every BN + + for (j=0; j<10; j++) + { + // Set of results pointer to correct BN address + //p_cnProcBufResBit = p_cnProcBufRes + (j*bitOffsetInGroup); + + // Loop over CNs + // for (i=0; i 0) + { + // Number of groups of 64 CNs for parallel processing + // Ceil for values not divisible by 64 + M = (lut_numCnInCnGroups[8]*Z ) ; + + // Set the offset to each bit within a group in terms of 64 Byte + bitOffsetInGroup = (lut_numCnInCnGroups_BG1_R13[8]*NR_LDPC_ZMAX) ; + + + // Set pointers to start of group 19 + //p_cnProcBuf = (__m512i*) &cnProcBuf [lut_startAddrCnGroups[1]]; + //p_cnProcBufRes = (__m512i*) &cnProcBufRes[lut_startAddrCnGroups[1]]; + + // Loop over every BN + + for (j=0; j<19; j++) + { + // Set of results pointer to correct BN address + //p_cnProcBufResBit = p_cnProcBufRes + (j*bitOffsetInGroup); + + // Loop over CNs + // for (i=0; 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 G{rBJU{b%C< literal 0 HcmV?d00001 diff --git a/openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_tools/generator_avx512/cnProc_gen_avx512 b/openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_tools/generator_avx512/cnProc_gen_avx512 new file mode 100755 index 0000000000000000000000000000000000000000..92574a4fb21783f63806c058467fd54ed2f8c26e GIT binary patch literal 199680 zcmeFad7NEEmB4>*cRK0pd(zoEWZy$JlCUI!1R4ks!oDVKVG+WvfQn%W5)njEQAQL+ z1sxs06;UC81k_OxH&jMZL4%-!$~cZ2zwfusyZv6j^zxdSKYpLj?^oULR^6&PRj1B5 zb#B$Ex^>^OX6^oUd7c%nF54&buDR#R6cyJjTUlS9?!BzcmS(-VPRe%6dUD^8;!H7Z zWgGu5rJ@VJF{NgirS;&qv@Rl+)~!r|!XF#aS>YEL>RVsgttI&!)8TAa=PKQ=S0D4&smk?Tm5uLddV-~4hK#=YjuN48P}KU>xeEpOYJNC(rq^H z+_O(zvS{A9r_VX}?9G>6Hs`XXOXe(DH2323=PpR?wtVv*aOhE~rh<;m+==rre#(I9 zeJ}5E?27SUIqh%j-te0r{Ak6{Q|lj}A#Cv@ShE{X&LQpO9@Rno+A6VS}I>F23ZHi!Rx4-YI8q&Ngf~^Stvnmtr<#2dq7C z-~Bc$n7d%^VzIBQ_$%(@k$+iM$kU~x&+cvN34-AMa{ejFS2la4P+XcWhv9cn*vcI%c#20Hc`{ zCHo5(r2F;W+vFEEru$!>Ju%yKGxy2u{<{OWefQ*+ZNF@}=DC;G9eLp6+qdttGHZGK z;dRM-{J(py%yzy3z*ja6oUl5}j=KLWDATfcx^8>^l9BgYjHKv)(nChR`fSQ~(xZ|8 zLF0~Ux$5^NfR=~Lkl<(7wcu4u`3w0!rUmke($p>Mf_tbpIL_m{voyL9AHE!&>o zc_oPKXt;}*{G>-yJ%7SmnQfXoaKg2zJ!U)U#cg`9>Vi#=uR-H;eOJBLclYr6-UhGl z>*@8jUS2=Y==FoWz24Es>qq)}{b)b0AMfw=?g3suIne8;26_FrAztqt=Jhipyne39 z>la3Qy??CN2gZB-O0(AoCwtvK-RmQ>y?$-J*By(zKC#s6H}>-S?=S9<;9Mz61I$sb?ycM198k{j0iz2$uazqoqM%>%!<{XyflJ-&0rh%9S2VKC{} ztoeI>&71$e;L5KhmVW)w#D%L~+K#ku`^&b^xBTtcT{-rKt;THI@zB>vPUY@=`tPs4y7Nvhk=F9QmK)YSwte6i-;+wd zam|(opSH+tk4N?w$k}3SzhhGD&L@o6wq|F`HE-UTT{`fg0mSb-%|Z_~&Vec$Ez#^`MTinRz6+Y zhlsz-U%x7Q@zCH{9#Kn-+Ox#Oh}z4j>8QgC5RE4KHG z?Huy%*m?zOVDgTwZ^UcavGq-O*^aGmj=L-4?k#wei$WH)7V@-(?5rrioHXb-lD<`u zw4@cP#iY+f(q9ICA-i__z-#Y=j+F21z%M*G@QX>T2j26@HQQG_{FjDpYo57ZolMfU zC-d$3lMg@JD@8v|CnG+4;Y{FfIO-Wud~gfpw~~2u)bs2O*~2>9uRl3X(i|(<=JH3N4 zTDw!F?0oajsoBp`c#r5(58rUqD=pieY{|E`5O~_aQUXc-mKS;UD)Q`8{Wy&sqYh(nE_p>xw+&f()v@o1VtJ)RPC(Za}G9rL4lf&Wu);|((9KZDy0!hmLEU+4+Y%mWCd%!3G|%tHvIDuxkA znMV*vnVSft%%cgU%wq|p%;O29Dw+wT%)1dtnI{uSnWqv+nWqy-nP(DcDa60NB>ulF zi@#AFh`$rsj>Z4o9f^PcKTu;R&VFsR_ruRBib;v1z6Vi2C+d60%c+?5)b~#-lBzny zc9KdR;)N~X-xiSy4PM}qRJfATkqY0ZqOz)0q_7G0AI!f;463ld=(FX2k`)S z2#<=k;{ot69srNv0q`gu0AIrc;4wS^cHjZw^RP;0+06)e9;3s$h{1gv> zXYc^{4?F;Vh6ljU@u=uoJOF-y2f#1!0QeOi0MFq8@H`#>zs3XLH+U_u$RSiisbBu8 z+%JvlpkF#0?6_aPr=xy(>F=m8`sJ|dep%l#gMLY;TxX}W=Jv-_yGI%Ab;|uKlBzo8 zERu>&d2P8FQxV*T&gW9vFHAUcQR zAv){v5S=6N5S=6O5S^p&kkO;@5V>RUHtyJZEZ(_0wjPIv03MGA_z8G`pNI$eNqB&t zj0gAzJis^N0WMyEt2Y2Y4G$zv#{>KfJis^M0iH&OJGP$19pGo<0e%i1;IG32{9HW1 z&%*RfWH|J@GJ2Ee+wSqTkrtC3J)Z%#smBsJixET1AHqU;Md^+{#HD|ug3#?8y?_q z!vp*VJdk)h9^g0P0e%x6;P1c#{AN7B--!qKyYK+N1rP9d;{pC2Jdk)V9^kj)0scNb zz~7Gt_-%NA{|g@AAHW0rc09m8hzIzG@Ic}YJitGU2lz+u0KXFt@Q>mF{xLkjKaL0Z zU3fR|*m^e};Ge+TSW-j1c2z@0b)be2-q)gre!mm!Lk*4HRSh{jKn>m7xf=Rpl+m6V zdZ;3)N)3IKq;}L$35zN<6o{yXDsgE?4UMm;uu2UrtVpU-Lro-=)KFumYUn?IQ%$bU z)X+O4cOp#H_~7FtmBt6X+o~a-C!vOtb@9!uWjwxfFyWh9jlzRi!q6!E7tCE4h5wG1 zjKZg2_t7XE{*ycKulcH(l2O<|G71~eC`@u#5g+|EmcyI4+_2TOvQapdoQ%R2Sr~=C zPtGt3pPFKKe%6ReqcHJ154F%`rj)d-Mu=$MIMY8^kyK$6HtCv*qza?3NoQ3gRTza$ zI;7pCdrewUkyK$6Hfdx<(u7tFn@=O@@6VT!uP_Rm^oxq53bvWFgQRxp2pJw+M~+rH zo@*f(g;(;>De)=Hz3(GJqp-{<8HMjQ3ZrmhV&uBtD2&1-cHTkJ!OmBnEAW1N=hK9D zezrB@;Rnit(EG)<2^_*G+%t^AD6I;kFn3q-XhxyE1uylww&stgE#!L@<(DU&gH9*u z{)(jXbh^c)+asw%qp-qP7=lB%kyG748#b6!PR6$;C;uC7R`P*^6NS&>wx^%Ewo-4%n1 z$^E7ZlKkG+5f$TuUAm3y-EF5S zmEGnR%4jwIR?^|y&xVXJ?oP(v3EQfSzYGuFm5QeH@+_rNWNwHe+7p>ODw3*1W-Cd> z@ZcIMC=F6dNK_0DN=E3NEshQZ_8e;T1_$GWFM=w~h`l0L!f6VOAw! z-z8&PJgY|sm888ma#xQIl$`5RjfDZ&;eSzMS#f{dj2p;^xoqXDj5@WO?Mon;dsh=! z?YhJM1nxD^LLix^G~A{~Ux&n5z^T_13!-Khb17ZD!PsR*|*09Vqv@6TGfk}RGj?T-OivQ-#>D<$QJ z|52uSmG*zJBB@GfpCqXyv@fHsE3o(sR7vM z!|Z@>H2{~$(ZMs~+s~BgP+?MEPG)^M9L45Y^LPR&b2EXI zc{c(Zg_=wtWu8hPWu8tTW!7+;GS4QEGS4M&vrzL1q|6Hlq|A#5q|8eQq|8eRq|D0+ zY%kPxrv~6%#NQoA9c%D52H;BZ@AuPI@lPhrvIZ}VuB_sr#WN>)ZP)KACGxSKlm(%x zL;R#7sj5RfL{g!}x0JPb36TmdUf_}pz)DJ`0k{&6y(=oK>KW@RlB#;f9wc>X0Je7w zh%#CYz@7Jwdw*OeO4TUgF_OA80NXo0Kt`lU!+|@UlFh&^Ovzl378bM=TxN_$g7+Hu zB!SNv_!NO8a{opkLETFrL4Afmg8CeR1oZ_13F>|V3F-j?snV|yNKg+FNKo4eB&bIS zB&e?uNKiWnB&a6{q)NX*AVFyZPEeYE6V#Ig64X-!64dtzB&Z(}NR>WKAVK|vK!SRP zK!W-ifdus|fdutS0txCl0;$qp6G%`y2_&fB5=c-l5lB$KCy=0CCXk^1NZ`FiPwY{$ zwLDiIOBwZ=#!~O?Xe@R0k6L@;AZ;z>o)}}8)CcH^8$0ibdqy$sji=UCBvtjq#UvFy z@#=CT#Ig$IB(SOCt!13()r0O#TXpbZv)&3FK4gQcPi@Bq*T3&2Hq z0BC~+KpQLo+F$|D1`B{TSSr#63xGCQ0JOmZpbZuPZLk1ngLU?f2Y@zMD%yevfHqhF zuEqmE8!Q0V;sKxy7J%#U0MG_YMc3m2pbZv)x8VVx4Hkg6;{l)z7J!@Z0MG_YMK|LC zpbZv)ci{n`4Hf`xumEU-1wb3@WnqJ@X)$J(XQWn`j-Qcj7Go-(kvqRf%PJOQ%02Vp zXNxtEId|AC+b+gbKA1ilWwh5Vzf_S_)h$0rQqe81EqBYb#xY@AMYk*?;ykAkmv-hk zO%)YZb<8;xNmU(l2uY=m+3{kG56KsvswP)w9rK3Bod{E2jG1hIyMv_CL$Ycyrra?X zoAC`~+_7~K;(_Q4#zS<5;2}Cg@erM1cub{-;~}FX@DRC?cpGBxG8wRO~nIl8Xj=d@qn9w2i#0N zs-1-g+-yAH=HLN07Z133c)-oa18#Rb;1=Kkw-AqN7vTZ77!SB5c);y}2i#IT;FjS5 zw;T_+J@J6s3y*5|#sh92Jm6N~0k;wlxK((-?TZK8et5vG#sh8*9@XxT2iyU8z_s83 zcOV{c2jKyCFdlGg@qjx754c0|sP-^C;MU;*cQ_t!>+yg)0uQ(&@qjxD54fZ8fI9~7 z$kJS~XXz3B&GIAKs16>{ohyPjcl3z<`FE%{6hTuwqLXBQ;o8TPy^4LEl|BEH0n}d4 zf2bmnDcVy%4b?dJyjikuZpCq4nL8kQirGeX<`D8 z)QqYp@n62(E?GL5Gu{@tQ$bZv;(JIcb$Aw9d~y{vjz#%BNF%d{4!6T!M@F_q`~!0{ z+amA~n9tx1VOsU8yWmvM)J`x?d_7ksm|U!`@=w&RY{>gzgmStsL;*-=J& z+GkZoQkC|ZN>V%HjuIAC*siDtTBvq-Q+ej*@p^jHy9d}$9 zWjG-yA==rvV`xQ&pc}Vle|z=S2ks!^OGi0I+xB?N zwjchfet9cMN|jRsveyR&-*B&UDNzR zaf@eFbKB{pV?}sY%qM*vxD(6Hi%*o9R%O}AqKYJ2RRZ)pP=x?h*yl@_v?D-RnZmdO zEjyY}ZmdA1N`5Y_NUD;b<4G#X&)`n&^SehG%1;T;&gAENkC*9EB|ke!Dm})A47~1S z)CP=5RC3%AkFkSY6Md+)jK_B#L73J1RmZH__Ufvm58U?WRYx7T?FXxlTzlh`d*@B$ z6~7zj=pV6m#`C-XwB_M{)cdC7&Ts9Y@U6eQWPI^{-r8-yUAyhit108vVb8Q&^Jw0( z?8Qre>kE`8oV4o1RVS@FdDVtTZ!W*j_oqjZLEpJ7zhViFwY!{mRsXkc3nIQ{H-4Ys z_XkRwics&v?>K(xRnDp!9RA-z-XBK(Exq%szDGmPUX8u`_+GFsZy3_pP*<1RdvuhP z)mPmcU!)t>jUU^qZ|@$B{Th4q>(j4qpI&|X^zYT!w_iig(#x*>`u1pOpt6Sgo;a=z zJ*l~8eSL`x4L$1Hb9HrfV%XTH=dj+Oku~=63h}rmH)3R;hK2#X`uA+?J*aoTEE_PW zu1AlaJsYW{e*dv7_J-}U@H zMcf1Y{!DmUo^3gwLayQW>8=XvysGw6x3F}v#kr^ZNR|;kkKgAB?}*%6sB(*&JI>~J ze#BK=S8Q3C?F;?~Z#gVGJUeE~30qFdPTO*NMUGB`)IM;_h-}Q3DO+~W*my#1J-19r zxD;^Ul(q0XoYWKeoyqTNe(&UWC-Gn8_wW3kCPwBV?Y2`H}R+jZz!d;->WpYT1swmEr z@a%#56gH-J3iriVQyLTczR2&kfx67D(J!SA%X}0zWh1yo{)Tk=M`KFupH3c${Npn< z^~@wfP1*dEe*)M3DgQA1ESuO){&mDRWp=KW>5PPNDgW$j3NZ&}bGR-~_-sn4GqcEV z=UAD2kL$QhjW#=Tq!#%{1*V|Lf+T577E@;xK7y&oN zVv11P{MC1!3Q?x1p@@;LwYmCKLJqyd)u)i91}2@C(m?JWr8;{iZr4H42L5V;FG}xO z1WG=SxT=`;ZmXnT zgGUc^Lp`B^HIy)n-12`^EB}Y0eS-h)812dpq_@leF+epzfni*`$N%UpYC`!Z<)x-P zWZ2fFDsOFJ$Q9t_tV_-IR6tFTH~Q1EF56{2!J0KZp{>02TZnO_?Kz>DmSV z$3V5Vu8z~KYH{*^I?z)~{GXPMgpM<6=Kovd z>{|pDv$6#YXnIrsc<`FoC3Hx>T0^?`1G0bOe;@99cZ2`Ry8Q3Y^V70?HrCZ7|MI^% z8_lq2T*^O+6Th0E{gfK{Kb@Xq{~rYW7-%;Myn9mKbf`G4hW7i!&46r5Px3NA?fl;( z@qaz%rtOvOogInUf3*G*6bBlFj9>Yqya}#eUS?0_I1+{}X7#KGeN2JG4gr^TKKs|DCGT%KsCx zcVt_j{rc>^t^7X`{=cObNF}o|H;Jv z57Ym<%m3*W{9g_~dbgRvb%aVCl6zQ*|LYU~7pMMTJOAI7_d}|EBGIGo#Svqwj!UOH|OiK{qvWy z-=+TFFAx4ZBJawL%J!$__P?{T6HEPX-|UKR(f^+8LgcLu8MObsCp!cBT~=fNdn%im zH)p>Drl9|G+5G(C?6Df@KMEtm?bP`m@P8)TM)=n35%7Nx;k&wOJn4^Q{qw;8kv8}* z&3{sp{;-PjNIya`o-JR~q^Oju{Tz7-(?~6sSuUfqlydn+Ii=!i_KLZZ@Q%K`_gBoP zA|}S_krrVq2w2CzF={U$#W>0c+=~{J{Q@%Zx2*2t@2Ed&2@C?GVlL2waZq^{RL`A% zk>8Y_3SxW-x*2S_c)48K_0I_p6^zi`ePt<_S^-+kw3yAm>HKEccO z#_&P2#&*YdArt0^Tw-I}bhg+TRwKB|?Qlg6<|=ZQl4|grZ}dnMaNHJi2q{|6NJ#q2 z8|hp}K4&Mk)0v4-j z3~XyZ(xpRBAZ%fGomB3}xLx`-;P+Vb0eWCSd<-fvtC2Sb=S$as81;fT;zQ3bQe9tGHp#gy!U6Wo=I|) z9rG%C_Hz4Q*wMt;R@<{|tyVF6jFPXsOC{x9I@mTPHEQR!8%~+EUxnpOiM7{-+$!Vh z3vsdsD%m{L&~doar$N{iJ0Bf&TH z{~)ljlt#)^2M;8Dcxsux@FPea$X`!d-jCk^tRGq$M-bD*efQ}<3c8Jf4t12_s)e-a zo9fRgTU`56ey52_0dt6h{H)8i>r=zmj{6k{Vr?im|nAIpf6 zL-$5+w-!s)UK#q=8Z6toEvLIqtd(JXwVBUZB_MR2TE?+}IE0qWx$8}wPigg5XkT-i z68c|g@mH&;hhv1HZWGTKdpK%|busgVu8AX>HWQ!OQ+EWqX6+aHL!O>IfF_#lN5H31EK$C0lx^_vGgBG`3s>^p6!t>2G_pS9s1u~ z>i-4cwTyL!F|;G}{{%2vM$X;AX*u$-2Qsz@*im3V8tf*K(u)-J|5Rex7D4O;TE@x# z{0&R17q3nKI}ft=IeJu!_=F7o?}$pRG=TJC9;H51->T`=sE!8e`KiMS{qJ1MQE3lK zGOeMMOKs*z#OJRoCCdCja$2_f-?F;vLjS9O9M6RQx1J&B4RzmO!ajl3vqQn8Kk^d# ze`A&Qq5p>g*;fDCSJhME=_sQo_k&VN&S-{{5<23w>VH?8eEyH1>^_9l z{}Z^|4SC%S?yCRCgQ3zsmiS@RK9xK}>6^Wfs4=9g|EH4E-Z~oSVYF8L--OilAk99j zCKyAB+A7um6G>5qT)pU(%Iz-w7gKtUyzfTcyHQ4=|Ci7j_5W1x&5++E)G&j%AxQEJ ze(L`@Kn$mMl=c5?QWhig>i^w=5BS!|t^X&3?PPGCTuLvr`V3k-joS91g=PJ3?HP4U zgGO%j>YfYzzju0O9)S!T!?%U@f^ze+wfO4)!`PnHldIn)a{M3qe<>-U{|`Z`SCd!$ zzW`mbA6y)m9RwdL_5WfpR{zV_!;&n`#a7>+d&d|1!`(*W|2O*oM0j4Q|4-m9^#5|G zeh{2i{~rsN3;n+_TZwcX4DVdARR13fhN1sg5O)&k2WBVJvZ>i={Kl|vXe_ZOkv1$l zp5KW`?%`#fr-qN@!*cYXP;L2^D6rNl^WNank<>w9)^ELC4Kd z>{2Lq3^=TYJH1$S>q(6Ie_i%^+ET6mH;}R)`u{Mb=Tuh5&SZPuxj?OgZ>RJ3ztR8d z6!n@jhzVd<$F;2gM}pM=_}$1)OP90EL9{sZzp3i~anRLS$VepI9Ta8#@AJ;tn7PK2 z;;OPwyBJTX<1HHm20!(GGqul1y3Q6%A#dpadC2ob z`rT;y>3DMVhfiaHsHX)(z$i>Dvb^xUwgnS$XJ`0eD@krBZuwPC5Fnal+GehaC@g&n>3U<=N|Kx%z(v^6NU< zI%GWb|H<^M3`t!A9)$}rZ_5Xo{_99Q{ z|HIRhYc-`0f+FhwgOMg@YOhWIx0Lk%H5JWP|F?9Y|BokM=>O}$AlzwqEv2yI|8v21 zGSoh|6j$i~3!(G0Y-_vv|58$}d=2{lEI527tA(4gQ?h?$74n{>|4(N<^P^Dhjqv0! z))dwM?}blif%E0raoHADYD51Y3kM4Qe?HQq{@*}}A7MTC0%WEb|1U;AT?pI~H0fRN zdouJng8G)AL)HHq`MZl>cU^h>-8}~%S-zIA$rzZpyoB{De*YG+6=D0W0n0o$p2Teuaf#bc(4Bd1Z`6P z-@_{Kr@;7~Y5ae8_9Obhm$T1M_UFO!ThyZd{~rD1b4mZdJ&ph0oV~ld{~w1IT!h|VNA1VqA5Lv${l5sV zj3Vx&r2h{E+r5$dwLmOH@9ax|IWTDz_5X4>H-vss=>PTT+2fJD4N3nW)T;km(0tu> zgTbv|(w1Y;l4bpW8WON6yA51I|G$+yTjB3We(LG#vk%gqO8vi;-uFRz@TJJczKlTL zUZMZrMBg|q`v570{&&Aa=>Io^a_Ij}$WnJ*q5t27e%TGV-Om1*^<003?s5G8?WF&| znSDIFmp>ahs8au52d&@DzKFx= zEfYV59Sp$B~nprN^tHz)AN=x0x752pP?j{m=!V!eD0 zjBif+$Qdu?h5r8&DTV(37s7w1wUzq+V}j!H{A0YTF+6wt|7m#l5z5X|?RxIn|6hViPnGoltL(1{{XZk`&5oOu`BU`HuVsz7`u~;e zB{a+V>|>dp{Rz1qnXk{)|Buo$znexBi?b>Dh3sr8^#AwaaOnSj`B!*JXHY&Uzl&>X zXg4lu@R8|>dNjIy1O2fM4!5U&+|zV!8Vy{K^v@ckxvl=Wgc0>(2G=cgi@LwK&Je=h7m|Gb-hZm$Jxs0A))<0*1d+49D>HT-V2K{qi_CGvn2ISfwPJpLR@f7Y|Buu7b6kE0viBr)Zpx}(Ve49uR-)BLBBxujqv^97vj0f( z^I>G=F8bJAXwe&Zj@|;*{={Ctmyn&KSzTk?Hb?RN`Wady(bAw@cKobNG(!|bW7RQY4J0ss~AOCJ4CS-Ur$=>VTc+n!FqJAn+j_lW6W3W zdZdU*F`v0yjp|9rHL^C`I$bq$zgJ*btn9g(W_zs76xY19F1xa|tFs*U z;rPCSHsheG_FQdB!4=o}tw)P-tfI#*vuJ6*lwwUmjmkP)v-8h&VgF)%(=y!e;QCis zw6zJC7H3xA+L6Iu7JuFVT;vJ_ge&CLt5p6uz{WBL`l+6 zSSe>rd-5OaVXhyzerj&_hRE$|`F9o7T>eQ3_Z0Ny7xFI-t}9eK_sDCL^36eIMBmj3 zW0hHbol@pXYT#qKDaI6T*RoAfa=Z>t^$!B3kbh_OzBMDIUFp!e8Y|n%zpIn3;JPL; zAjP{X<#?~!xvpE5f30gmh5TEqa;^Mp%Xfuz2-uh>>d;~{Dy3-aYES;nuZ7Mv5TV?u z&;W$;uf5B)KWQ;CrH$ok*!7c;f7kv7kVpC7b$@{rwj|enLMp^Kq}E++#uoA~oeKF6 zF56?}S)mzs#ovbqJaG@zxLE975oAw`KDgWarA>`k6>{y-fJ)w|)Ww2Ot4*3tM z>_?7Wo$~Lx*DP8%o{_B<;znXdq_$|2cOQ%Is<_tU+qkY!X>o6YPECx%MpJ_J;qe{F z|70uxW%-}Q+{iUr<=@pIrAh0k@;{q#dLjSTVa~afzc8hY2ghCcJDpZ3|9e75ZNUxv z7E#W8XjI26b2o6DOS83fOiD2gDLe%GKm)TlZH$HdPbPo0Q!ZkkrZTB4h_N!Md85U{A0O&!2Y=>bJ+FFE_&iCo9l_+gBBm2M5Vi%2!(_)G&H!j+`j}6O&w)<$p9aO~h)^NX^s9 z6Y@WqTp|Cvk?u~Ckbh;dt((T`iSoaa`O{&@r*9$dhm3^$Pls~uv{=afbod_fzmUA+ zk)~Nm{`X3po{{8#M%%)IhMaO!Sh_OI2$gl zfI3Gr8(skPq1beKAbE{Q**WdV|1nsOL;f!Z`b28%k5x?le>gqJb&S&zPOoRicLkx4 z|5H+2Z(_>we`Kj2q@>o%TjBlYB>%@TV^{t!Ewx}3Sbq}h27*G>)9@_!5V`ukhu|IP6I4j}KsqNe;mgsfbF+^i-~A^%^X#&?r4 zo;mxj^8XAJ{33r^Djq}jzr-B=0_M=?VgtAWi~4QM_s_wu_o3{Y#MTkhko^?Q-$tFQ zXxn?S&s{|ezJ}%U>2~B_jn)eu?}el!GCYS}Om|{LP{b)lT_ejr{M9mQel=M=Ay)p`rixK{A#RcP#a`w95bfV6Xs7*l_Av zPx>)Q{`aKb_T~Q+>{csTp*W0|-h|!wmh8Hc{9gto=3ra71}U75ooX}aT}-Jr61p1e zqWb^s;P+Nq+y@!Hyc&IQyA9kPPx8M#$^S=zRsNr%)Z3H%Kf$Vpu+M`x`myORiBOQ(TC#iL9{@>U?mH*@O|3Ur_&M(1= zRF}U(E1GlV|3T#c-;?}5LTzoGPpv|JE=MviOY(Cz5X+&+(MVOuPYd;*htwAG^Oht( zm$b^y#w0%{w=JBz%ais{D+?@aQuiS>d)e%=Qsu15kd#@_gGIK2R? z*Kk_(8EX7uNq$c0Kz{PP2ehA)AC^tb=VJG}g#)}k4^{8Un(}$M@-rzfGNag^Ai2r{`D`| zkmn&^(&sj~drS5#dgNcRZ&tfyIW_=rkv`wzUC#Tm_27JG_5)Tfq)(sR{?(Kpn>Xey z`HNsbG2ev6?T^_}`46%q@{34+L*4`3vL}@LZFTW&?rmKBVg?=8uojfVf_S$JDcY1( zzHts@?z$9J+!eER%QD6INHbf+B!Dh1g#|}Dg02U@!e*5sh!0G?I+F=pirC20@zwd2 z*l7K+Z1FWLyeVNL^FFLs<}&0cyB6n+Q0Mqq41Gcbb)AVi|BM`#X^GZpOPxp7;+$ay z<%QN-q4lI8#TFP!Lu~@#Y>VUhpl4TgIKFqcyt~fbRTGx9m}gjyKV5wq8`v^;yF31m zc6VLAd*_|8I6nvrn{yH^N?~)8CeCWK&WM5Uf@tq4TGw?Ag)AzGw%Yla;erOd9%_ zCdF!T@~x16?N(Zslz%0pkbh^6a^E?<7E3Xg&$YN-j4onc8g@?QU)x1Upmr;Bgl)_g zIirlXeL}9fszb|ISVgsq_+F5^u9ScG`FggH-1iNog5HBE-`3P7{{tCANzuW;jAEQV zj5|5u_@|zyqq}f*W%+LcgHhD!T(E05nDJN0|L8<ce#AS%(--J@+tj&&&3^?qbOPVm&Z+% z>>Ded1T`|r|7hwn&Kuap+e>!+-GnvF(!nx$sHuCSxr)wA5 z%^mr!(!>gYG;aX^917{Qg(?4P9BpOh>Yn_2R+aidJ5eG3?*AW7$(|~v#CtA}^6y(W z?)fkDQ9_}^i}LT8fm%JKM5X*|m-C&M;rPC>r)|S?kUV{=JMurCI^5;I80?h)`QYnW zR706BhWyU}19vztM8f7WvK>HbZSqr=e?Q?hB#q#;){IRu>H9D0|H*JV^CI& zznHpPXw48>xQ<$ClmD?`;!{=mS5ACdx#!vES58PbA;tKFQ+GDPY2`m`Vktu>7xn)* z+8Xjd6KGd;+@b9L=Q+s#bVB2aoyV_`f6sRt*GZ}6B;|h%+*(7)8P=aY(FpU9n%;1D zFTw}I?Y;5K^1l{)kh`W9mJ8`5G#Cqo@_#%OUChjX1@)W-?VI56P&lCcAI8jTD*2TE zQ)ug%@Mjj>uf-|<<{S+zD&_xlW{cCH%^Q>apG%#`Gk4FBRptLQ>Ree%@nClkWvJKB zL_TLQyZ%&?|C_Lw3}lA72NLvwD)~QwwjRpPpjzBJvG1w>KV6dlZ*X@3C4Q5AqKC6X zZ4ke!*_HAkIC>WOLjJ!4uWOh82e7M51M^$4fZdGc>$}kRO_ccz^8agWV;iXbW{mH%e$<+}R8J@uXjxE!8LsZoBE|3hf2mfMB!aA}f% zcSx1x|F|Uo8<5gHsecIl{UE4yNG;?iUm^d;((4aqC(zaH$p6(z{?A5Qo8axO$p5J| z;;;PQRFeOXAxrmQ0XmDl!Pm35$oR{8$~7Mx$u(obSn z%dyEkK=?LFdL{b@cAfjPzWJ?CUHSiQ_IuJ+V_o?=d!@Q7|M!B`Kd|2Io1d6Ji~hff zeU1a!RrH&Z{JVqsUMPProbH>~F8?P&$!54&mYIXrClELaaYp7yPA6vZeu`rN zTNbz$e$jqQw=CnWJ;KF&Fxu}7GUj<eV24$;|7ylYw*Or`o!`JnXgyDW*Olb|OK9xVc{VpO3bg&- z;ra7n#+EImwW>PW`md?|*RdXyqch*fi0Whf%I%*GHl7UQ8^E@IPpGr7wf*yn3I6X7 z6?aeXtj=Z39sECnI_!i~A zMEQ?U{%;ufjD^c@WUq8l{-gB1%JTn^%0DzO$}gT1YS1EV!R5PzMu(Ts$Yn_H6JiOX z9O|fmc&ez+v^S|={DqEJ7kA~tept4Zt6hXvN2)iwa?aX(0u|3RwZ0ZWS1F2TkU2VX z&L>0DdR6PX)6e}KYT`)g2-bM((z4@jE48<)8J@G_?%vwkZ++%=4_N5&Slw{1Zr3*I zc&Y~1q<=hLrDts`3_=$B7K4AmNi|b>ltHErTu>^WXYs6-|31xpN)%7&4uFYv^+9@z ztxt9>1CB?eMeKU)7}k{FzxK5l(+KVE(%^sBHrh)5#||=|pFZ8)k=7ml4@5`0H_bUx z@V|d)4A5B%+|lOvVkG(~_^*C<%pw1~wjoI|WzeycYeg}>h#l&+SlHcV8vKu)d#(h@ z3r8vJALtDAlveQHv60_4iIeNJLTdHwn*WYzg8!a_;?B0CjKv`RIT%!ySDt_hq1*RO4uv$ ze=;MMuH1Mm0tb?5-xB|iq}F{hcUsDSQ#yAA|MyJ%Ukv|GDe-?Vb~LT&9GF!1z5!kE zet~y7d z;QyWMuyIe?e8!#8|33=(quzJ$Dj78`Z75u-C8N;oK|KIHrerg{4KPaD) zSMq;s&d#*_@Vu)6_Fz^J^gl1{TD+u!{zo8JUAd#N#0CAYq7_?9^gkb|u8sZ^^RGg; zSJ<^D{m17!Y5Cl|Z!Y~`#G2Zb`(nc1c}L*?3fxnF+>R7{kKKh`xe@thz5=%s{jrMK zQ{exPY+f$@zvw`I%Cn7K$?NDboU@4XT^SEYHBo|3`05#kPe9|`zhenu1u8>FD0a1! z_bipu9gA41<0yXxHboBYL9qu(dyUqjw$2v$9$lOl*Zvc@u!Px)>hiT!751_A+8?R$ zrjKg_yS6{hAa*{{dHdblFrY2++&LbL_WRAAUEA-QS+?J`XUAH*wqJW#f1UuY7Pr@a z=R1xs3u|9n6k_j%qfc#+&Z^ov$0&}IeP7G=SGT}@@Se9A?f2Bjw$7)8Gag6VwmNp|c^h_lLQmv*(1Yi$ZynWv<;1G$mvHa??a@4WZNK-G?nt!u2%ci|X}@cst1A-; zuP(KJBTvgSus2one{Y`Q!_g_WpZ&7Cw0{uTdHSFHcYYLBxN;?)$m2+UTGq_p&|T6! z2WkOh4Br~D{RfpnQ)nWqc|E}4L`qmr`@;%W&SZPF=bW0_fAlWx|5R%K^`-W|ZI||c ziuPZ_x=GRgOUgy3(C4Z9#_Z=y?5+W%wrV@LbHUX^b9|K8gEU+>cX6La~$lr=8-znop(ZQTV4 z|0A$?O{V?}8FRID7qjm2u@e6Gg8wJmCbJV-{C~sw3Y%F$`LA8@kMh4q`5&eHKkQQe z!n`Q|+3bRR*Yc~XE8VJT)XO1FwJZBQjJtcnCqmJqPfj({q#wB*8ReT$ukmSs8d zi+bbv=rc3QFJow19J~9ZDX65)OY37ead3^oU+n&icA3ZLuR9!#F-Kvk6z8^18 zQCdR0acsFonOf&;oApQ~|6KdC4rv#=I)!l5ARU6!h2>9csO{29<+DzTX)y{)i;cga z0D*L;U+G+#lgjS3l^5C;g)qjF+{+qI(bzfYnxFaH183`E2X$Bq!yf2cs$v_XL$M3G z*p7G$T3M2!A$`8R*s%-hY5fgeTUM-c*5$qPeFsw9wYiAB6m={kzOe&4_-To@ z%N)|$7PzB0Mq{q**dyVf^q(ZrjZWC z&)Codk+0l)qK`%`udsJuo&oN%-`p^CQ_TkWf_M-T< zu6m+U|M@;`S^s(NwdZ%o&i+dM*N+;dysa$sP{G+<>1XdO^q=&wrw#;8ec{;!h5n1) zDjnhtWjW;zT;E?0{pTs%@y@%_Vh@&v#<@CS&f(m7D!A{W#JaXC;lYuP_^V~Qt^RZW zcIZF9{L8hn{)<_Z_^G>m8^AU=*O77q5|#wp zadFmpBaoxvoadBFwX**6%!kpm+TF=xNcD>$o}w_2ST&AcXKms>^xp{LeXhDY-jvwu z;0_H>jVyHtUY)SLnakv7+u$gV-zL=QW<>N_6zd&@-WXlx0l5I*{DS^vo)Wz#fEGlx=DJbi=jmgo~g zy`vPnX5$#cS+M5j3uUJKJu2|N8p)+ESi@Q$a^ajt> z_ACb1`V0MM4+>nQk*gAMB8YD)sDXU0$q(xhUnS3;B}RVx!v5iYoR0WAh7|RmyWs6* zq5pi-!oBiw4vZSX?}oT9-ZyKs9u)dd$#Uhxoj(J}GZYE6f5lrNey`YXc!;C&Y6()? zlf{Q3k$#~=e5HUct|?f$_|AdSMH(1auro~Jx9@z>Hj z!cT4HDL#&urckH7eK`4bW&O8%y4Uie^Zf#;X0i;_SVpU?(_F49PefN#S7oz zvwZc9JK=m^(>#R~reNvf8&z6M^|i?POi%|Xx5FsG5s2qbae^srwH<|3(YFa)^;GM4 z_Ki|(KMwt8e;7mw?wX4ynQyFkGMD>`?2oQj`_&=$XbGi@YYLVw6XBfa4i)-uBz#b2 z{IW&{cZ8Wr*l)%7m5R`R+TL`&0i?Y9<&9zKIp{j6d0eYj|G8hz^|OiGHBpl|_e?#; zGibDeX|MBbF5Ry9?Lps~2J|2#!f)VAp2W6Dv`x&}j@!OBGW|Dsi zu@cDM9^r1aVVXVVn*o>c7K?I~dCOy`KNA{##2~F%IZT{~bX-*P{#l zcMSJs{dW}BQk^I5XW2^dvj>*--@f45k@M7&HPGyJtkxC!@9d=i&Y%RpJJCqWEa-3| zE3EsL^xsCTq)Um(v0ys>+eof8*jh(Wx2OE5|Bk}GJdf3M^`Cn%k0Dnx_CWRD#lUZb z7oq<)V~g%c{(Nft_FCva-vATrO}@3iBI;L_>zt?HX!A5?`(`W zL;tx0RsH8^LH(ySKEBUYPfmAH35uk*dOO8w^(*w)zs^`GBOs?>j4>n8&ryjA~ABfWF|cObpcucvqp zRWEvdq5pQLrs)Yg_21r1Mb{+o%EtN+~3vIl+X0Lth=8O{TIe`gQw{0h`8?#8oX zyf-avtN#w6oqN-h4uj+BzttV`_k410z{;=wJAwXqGMK3UPCzHEgboLR^=i`8e+N;U z+}J?wlaMF%-&sJc0+Zpy?2p9xeUn2<`fn35xj%eA1X&x$TISJ|a5SZRg49_^>iLv+ zI3*t6h5oyU^2_?~Fesq@y8ui6xv8(6M%g`xUCz3-`p<9Ecw)Bt?-H!wYOoe)Th9pM zVnPQ&k>lX=)Xrxs}27G@7vdZpC#MZx zSM1_d|6R$-%rBtbb?oK1l{d_eB<&^mANubB=<+Gb-$_?`d*-*QUo4^&6^9f+)k{=1Hv=F=m_ z@HBF?a0XH`g>a$&wpQuCb+p6xBd^V~ZeKYC5TcP>KlK#6l>AyG7PtzLE6bH`w*_ z7<+mu_1{Opv#tJnfjwH!qyKJ3-(;Ltv;mx-rrl4opUXG1)PGMv)ds@9?L_}g%@5(L z0P4SAARnRsegJn5;vImw`AFVn>z5b$uQ%@o{E6K)>c77tQNM$S>c6S^pLuueALzg1 z*x!F>TG?C-PUG`0@y1x5znPPr=F{41pl(_J&E*XA%b`c-`tJ(*?>XdKgBCs?4SXte zS%wr(;2i|}@99X_rK$g(jC6Sp=vheS#r&fGZbpA^K%!Q#qB@OM_U3sq0Q~nu22Vle z9KW1`Znytlifm4z6}~fmKC<{mq{{w#X(#>n;&%G)^}yVR%)FiQKM#kZ|K7lEy7!~I zZb#V;4ccbCKm6QvZD$ zagJYH|LzY|$NhI+z8Z-e2$y?g8O z`HxcnotJ-#G{{yvoW`{%^po9I=K zLfc=kgKH#x{ui|JLHhWACH}t3J14JX{|T;tgEw9AcVWJk{KInf^IuE)xrN4Dm^X7W z+)&=AxtX5qIdli-@^|n2V0NEj+sF(4PRm!YlWuT!bbb}<{%7PrhOS3JSNZ#W_W#=YCy+iL3C1y|{Cz za;lI46}IDg?zD@%7Uw7@Z2g96bJ`pYx!8(cx ztc&%huxD$psnyxySku*N7jNJMRckGw$QSzn#HV)pX}^yZFW1B@L3@}qsLg4&a}`!D zxC$Qhuf6@kYAMq;74O+f0WD{>IoGbWqQ@FtSo>YWsolvz;e2yI8E~woU7bKb2C(Fprs1D>x%n?LnUS?h4CP zxapqQ+WUW*|GOo7Q_kpeF7v!v-FW6;@_!~+tauIlU&36jKeitE?~GLb@0aFxwPH}t z*Mk{iGjkMAyROw~S((X-&^X3?p7k?`nZsVMk^hV6MGNTv2X%x0r!uNrnfQMQ{r`AI z_+yy!R_|KvxHY>ojvB+bIQV}u{MT+)JO2;Hy0H?PA5OoS%}CO(7S3fXR;xRi8HoHp zhdIS-UL+0FaK{z{r_ZUczg2}dF}jvw8a0fGn114 zpYJCBf0jL0;{Q+K-UqOGssFXR)#jFD|KH}nBlYskCFUd<>;?MG3UotNC+{JoRv@OE! z7%{hbi}pB|GOjx=W{uWojn?MuDfScv20@i_$-&>KJN8)`6EjF>pAlyn?v}E&xQeHx zn739Zw3s;~bDruxCjF?fke|XAdv`NLy;3H2WD4u-Qk=y_Eah_0*n9V0`)7T|*Xo=x zy93KPY|LccrB<}lSmy%HvCS8G#J0esXjwow`!r|F;k}BraYYTW2hP~qoVD62=U28^ z-Z;YzoNT{!*a~Ykx2=zTZSFoYMr?(NyoQ|Nm^*s7v$rV4-AYoUI~=aH9b)cY+;}g{ z9Y)q4^KVmP_q;SV&NkZ)+a3MGwm8Rk4{z=B`#9e~O4w#4$~|^cOW88UxwF)C&a4H% zI&HtU0I4K4!NZVUEhK@HxCOtR^?GO9DRtMdbsHCDI1?@RU+HHlwa;#)NS}m>yVu1|%IhqUQXx2h5i#`cLap4 zF`xUp#7hpvelhi5^h{|K`cFHA@~IujQ|080RB*SJGHCuTYZIm4*IuUtCz9+^=mreQ(rnr@6Dv?;xrZ3`x78`0mlG)p;I>GVbYjv47Ux*zWyw z7p*iMp72oaq)zBR=O4pJQ{sjaD(gS-D^92r7r(>k?p(3<i5h%i#YV3q0oPR(NAl~5OT%-Uf;1*_t*}5a;5&WjNV`qd*S^?p=VxuE|0Ob&#wkk zf~_1y&G9Wfd!d=4kw^IN4uDU(5Qvdk|^e9>x)GGAf1Zps66Q$MadScg^2o|CL{0`T6 zVw&NElq&1LCUOlRW;a?gp^g3%kKqZX(0@{UH#njG8%Am`tWWB{;o#>UaZiu@zjmIy z=}tg*xQ?YYlc-nAy}Hix9euZDGFVIjo6vu|5i^n8y}(EPH#N~toij4=q&5s^(ni}l zgA&}$?KeyPBBc7yQ}g|xo3H9imhG$&B8)m=)dV;=lCM@-wb5M-za!C z33>EuZat`P7e&?OWr^zF$wIZP?x99`yJ2S={KSO+|SocUiIHZ_9uAySAX));cq(kOGtA+X`%m? z5Z9l*Kx3$DCKz`||M^~l5-|x7kC^m%Bhk>2a?>VmXsB1TPSLnYv zw8x#$_EYy&_aonUII8|z2u}uKZ=FlIdvKite|)2$R<{stuAr2%{+mnP3&43O_^SWr zQB>$ZccA&*ni*g{i@H5ULrI-Z`#h_{m|lcEhj#(c>OXg}8#jxbE08~TO)u@n`ov7E z;S*U=DD>ZITCV={tfRf4nft_h!to|{*eu{$=s&;H8{@xGY2TUWs+xBp)Y=ma_NNu< zzolR~i#<5*vJ3sUKQ;W{>%XO7F_E>2A?!h4O=}JY-?`9IUFR1y3;lNp)N*frPgWt+ ze}{5E9^Cp9it*oaa_>`Am-{pXiZkEVY0pZoKVg&un#U!nh&;`?pIy~wd2 z7V(v|uh4%7u|v$*y=p}d**F89?GGkB*@@K$+Jyew6Kocz-yy8_9D`;!5G;GJniKkO zU+P&;Eo(^g`vGgnEllV?Pv2NXY3jdY!F5mM;W*lRFuB)oT~RZB$D$L|f2;9(vI?XA zJB#&%1K`LBN&m4!2Rf<$&Ze%i{yUbHANAjHV77wQn>Cbh27lAp)3up$j;4ge;m!)K zo>j628XrMj>OXgP*5=01!wUU(DXSX|z=r-?iTs5AI}{8;|D6KPNAfO0fB00^e`m8- zO#LS}_o5Xo^!?*$i~8^Ur2j5q{Yw3J4ykL%v$;0p$W`dS6QTTQByc1xJeBpcvi>`t zTshP@nY!lD6NXX8OmOTAt<-<^f~myMhHqy;_f6=(qe}X3J(z_4dmT9o{dXC3sMUr3 zy8#JyPyPw;c|5IbW)G_R&wbZ#fDWPmuE;i$HkLhd2eTeE6L~t0v{CFaz6uF$Mnctp z$Fd7;3%kl@(8~{pJ7<*i-$h8L-Jk4|2bm9pIt=)|2~f?8fb${<{JSe3}xru)eh!ELO5V@@)8b zCHP!`WV??s^q>3X-%8K)3!~>I{kIJ|y$@W}e;?p?1p5s`|Gkqkr?cyEZ@z1A6Mf|) z?B>1-{LZG|cSrxdKIy*)lK#6L{(T|ozmHLRq5sZgb+E1ey9fHbA9-wKckX?h@O>+P z*CLaS|K3;9e;*)6=)b$6_nYYHLpaUnLG;p{-PV8qM$0zyjbZiQg~<12%6JT3`TIPp zoe!b^+=YBDdzjyZ9=U>=KAgVg@oCcT;_uVs6vn--yCY$5r=*Ko_1~Se<6%nrEV)0; z^{!gG2YV53p~t$zI`p5detH-EcUjVZ?pz#%{0u|lmmqoHPx|lc>^{8*{rCBj{(E22 ze;I( z)!-x9#~S+YW++{UJpQ6p|NV&lv%f(9-Of4fh5oymHmUz^q!sGFuaf82HPi32$gbl* z-%lv(zds^Pw;(BRr$78BWnINya`oRmtZ;|^dy##->c5Y+>OW83dLI4vYq0(S`tM7~ z;#0J^krsTMHy+e~x25sl|F8dI{P+LszYJOaf4BZ~9ijMh91wqYuRQfJuMw*B%~hLo z4Mj_v`So?iL^%8+oDx&s0*`>RjEtPq>UJH%y1kDTK*Pn4V2v)Y zw=~xnGAZ)@cc}>v}L6Dps|{ zP$w-sgGY$ZYVr|E+ zx5*FX!S)E>z6<$u6*J^B_G-IA<%(J%pMJeD%8b%IbwS#=qGAah<1Zg$y-duVLA$yV z>j|-%t-PDV6}?!sh*eRoC$2hZZ|t~#Y5TLio=o8h6|qm-RnIt=Nb9=ThWy()IV$aZ zcRTLoMn_J0G2L|wR|b9mC(f&IB_P($gC-*D$vF7Y~w#vU>wQ>!_)ksg2buCVcxK^UP_;m|c zid=KB#*X`MA^$_ca{y(zdh8dBJt3wyI4b|XRb0CZ`ELfZX_TV1t1n}F&jcCF zY+)Q_EB{LDXsGDwY3K6qNe6zrV>cisGozM+vy%LKD#%pk-+h@S`EEg_{JT;*4H(zP z`UBsQvz5(I!>?B<|5_OunYVaOlV`)spgzChJDzrUvP$Ux-DpoAVnhC?0MU^fpP-t7 zEaYE2$5EqaRLp_9gPHGoBFij_@Ju6DKgKcRYNSr-G^tDZpM|YwGPumAy$gWyTgy2$ zYCrBtTa^DL)TUK-Ds#z@|5-^cW>9Bm`rmU*mQ(TwN>=`-a5sf|mN7pcNmxL5p1L$p3~``EP-Xn@jS4GM1VHvC=ICO1U^C$^XiZ zibn=Q{?{XEYm@xH9vD{%E=V-qH_898)IAU0_)Qc~8Cgy0LTZ=^rA~!A9n1g0aIY`; zTnyxu(B%L)wha4J$p4#=*9(&TuP@2}MM?hOfURgLSe%88Y$bM~BRj<3?@f;d^LK#Z zW!Q3#X;=Qwz(Tao|HIyUz{gQtegCsNl6JK!D_gQ<*#_3&j*E(m3>X$SY;0WV5G2`_ zZGkL1l59+0dIy^%gpTMffFTe{C<;B4Uu(Ee-z%@ ziZeI#+WznHwg1cE`>*4Ax(;Pw{D0WA|4UKx=U_I7U!pv={a=Jyx9xvxF85&caU@Dx zjdpw|#&<8nmG(!BLcWQzd^J$wKtzf=( z?2AvneJ^(Oiz77r9^Lxi&bQ5Piu+zTuEFsJem`l)ulQ8RXGD^|7q)Wt5SSb5j+*S2 z<2!vX968`vfUSRiPtNZnS^xZgxbMZ*Kfmp!-R#?PRD`1(e2&}Mg|@Q(`B$J>{~Qmo z&#rxG;K-8wp4k3nAb#)3`sX*jJCnbyfBwBsjy&+2R;_>btovSU{Z~r;^XplTQE*=6 zovVNPi+|;2h)Kzj8~c|)`MvDU)jwz6w)M}yB+74O`7AL6bZ6=>1W8-}{C<}8&tLJg z{&(%=sVU_b)<1uB&shlg4IRJB!0HbBQwRa9PeT3 zpHHs*iZFt7QFxH`&pu(_O9W5x{E}}R`r`clx(rA5`X7z{ZQn}_o(iE)wmbYi96Cn9 z?ti!bCnD`sQ~$d`Q=NIrslt=h&e#7K)7om#>$LUHZ9Q!2dl_Zwe~cL);NSAr`X7b* zpVW79^cnfxSeg)6sY~wDrFjb-*uT4&Uke-`mvxLX?`bPY!kBXn*^{8=PCN zuVo%u>1wI}y>QL6;46$awEQLLdC%@EG0q1NX%9tPnF|lF{ttuQd1kwF_0RdR_#N&_ z_~{MxGt@A(hITY7$ZwFjPvIIr6Q==bk@{hx`R{CM=|SK!;8i?P=T zAAa-Ss{gC-{A92H)%cF&->Lu8rT!nq*H9~Q{j>g8q5dDnvqj&_dARy-O4k2#NOKmR zb&lKV`hNtotgXiL7_WcM8_RS0^~cU{!hmCRb2m^ z8?CS919KdwpI~32v#C-;Hx+PdJsHeRBIeWq)^T->9X|v)9f0E&E}#kH1Jvx1Ty~ zAB*om)mN$X>}~NkNbJFK1}FPYE@c7V*0G1ncZeLv=6g`~PgMhTvi#Iye?i9giF%fn zv-})|=ZG7hZL*c0@8|e#EPMI+=92FY*el`txpe)u{Ct1J-~5!K@50{>rSj+ZzWh7% zoM(!*@{6wY^!&BqU`Q|>|H?{c`KypZ%g?@LCCbBJ4`~j3ug08Ne!eH-FRRk^yGSt@ zJ&Arew}+I!JeeAbOfNCL{QNbHYUkf*;IqtdDL>~zemm5|@V(*kYz?O&W2fKg@sLWKPq)xh#k#)w)m`T&D* zW;!B&x_&J`$D{YaeVKE(Pfez#g%wzHmwy(@I~Dg7TmMUqwdv(wDCM7nT9^T;1K^7V zY5HyX_s0EwB5YfPeu}sJbD^d9S2=3 z|0THNrPAMn@;4#>TVVxfj6MMS-$^@vDMr1^afjWC^55b-gfYgmJoPgd->bIai)4Ox z{UE;n%q;&Fl>bam`LD*Ry6t{L?3BXP*nv$bTR)>wE zJEzCqRX8SP$EEaN-fMPdvEwt8w7J`HHSTBL$FghV)4jEtQJQ;pfuwP*@HIHb4dNq~8yT^M4?@Jt$vR`E|caH4Xd#P92e?)sZs$}h@HT=H8-ivo; zjEZ+&dsk-Zc?aW`R`Jf%_Xrcevaw?vyn9gI-e2vvYJI1-{%3x?4>D(t4e*;MmZk6X z{5Fc?3$&K^CXNwWFYsQ?y6t`8eLMAS51*_#^8&wLvZG~v*B^iD&-&*m8$HJHKF&eF zks2<&UkCOJAKtV1^%1?#88TUJ_8IzKD9xS;N7K}Delf+F5cn6h`dawK4re~F*AMHT zx$=D>b@c6j{(gJ_?os^uh0luoB{@gPI8w)d`&!s%;a6JBlXp7SAjg^bi+C5d^|i3S z!(abVma|myF2wl?SSy2|qpyWu!05*lo?%p)gS-b9Dk$6`X7Q4u>LDi z0@go0(N}s~|AV20U*E9)`CBmdp!ii!-wWpo;BS3n_?L5KvgPvcVDN7`?Ogqjl=^3$ zga3>5KNck(i=0Q9`X6ETcCP-};~I|pC+mM4Jh>aZxF^ao2BmkQv#*7JduIsxRILA6 z)c-EHkK6j+W2fq$U!#mO^*Te*vUzmb1H5a{?A+Ugd7v0wX zp0K3v`X2?4^9}!W)ZTRXf<57((8%wXcIH=r{Q8BzSYiFoNY;N1#&+tBKl<|DG~_i-nH`CpC_u>KoSvXj-wUbf};DM+U6y_rr)z

b7-zlpzYghMlKOuVzccFUGyP;HOO|IeHHzilV#|2AB4x8nN$0^?z< z|KDI-?i$p84@&kq>aefn|C###Zoo;Ln^qSu!!zm41AmApu{Mjhu0y(8u>J&Te~Rs0 z*j^90J+QqUX&%Ntw>M$S%XK^UkHXrLmKU&h3E-r8Qm7m@eB>DKxs0P1AbK_Oy$0Kt zuzeZp_1OOr)*G<@D%KmZ{~FetvHv=@Z(zL*`?q6zC$?{4Jq+tc*o8sY1OvlESl`9| z*W?_xXUH+j!g5f4SLk3_dCW2m7WpOEVgT6aItBZXqb~e06Dx~65-Y%{lUuH2r(0(7 zJ_+*gfJr`yL$J^FaJ!m(q0gi}73q*a^*IS_`}8s7{zn$mD@O%#%X&nQ8~@_D$ps4r z`S2RRk=+Zrcs$^_{^bJ(4yqbFWauut?iSm9j}fCri*ZjP@wZT(r?Fm+{b#X#4(pXz ze~7ghtRL35P;B_zxdLne)|p7px|j_H9~ys>&&SFE1lGd?SkYEZ+oa5ikY(FNy|c|y zCNU2y(=aXTf%VFKq@E$QlS{xj2L3?#@hs0$(?@R54PY%SE-8(c^J}f94N*8bo!jazJ;wHAih96*k6G`AVZCOm2wqT!S%eG~AJ$(rV^YRJ`LLt|$-}xSFdla^^UN6SJ*16Ov z?RLUgwT?R>vq9w14zex0UQvavDHsP$dRtyazCXr_dULv^JlAH~YJIZ2JTJ$7)yUlB zo{y!VAlO&_k3jw+tSF;t>uAU3+K}V4wu~CWMVFV6Bjuj}V_TzLT-gS7KUEjOykJ2n zFEjn!$oC%PzZKj2ussvol}LXU_RqooG1&hn)?<;!4y>PH|2x>;gYCW8?uTt0+Zou> zH|Jp;g|ruATPNws#$%u7agO@+ytzkrgH!)=a-OnWk)HWchBh#NV-M4JV}-mg{W_$9 zyq-_We;xYTvChAzr^lKfZKD1x>C^3_JuHvO z1Nu~#mM57$%^uokY-Ik(&#Wb2QLMc!ran+FLHx&S$%J{<3GU%}E-E7rOE8aDZZK%B zUPLYY@8;qE9E#T=|MfW6j%^3FEm+55pY6F7+lU;`!#-CWd)Q8#&n9p35Pix0wBsbp zkze}xAX@ zKL9@x>ul^ZUUp%BXBU*I|A5M>A;Wr4koXYi{{Y?nk>D@beu`tp&>^tnZ`l6__SpxI zVMTm1aS<`Y^o`LUNesuzd*EiA8;Siw?3ZF?yhVF6_aXG<%rWB=%7RZ}9DLGYb6Q;4VbY}kb204Zec&!^zm4sc z*s|O#+cj8Ou3NEXoT7gZ!xla@aTNO)Ug4B>)}Lo!%NRh8I!LU>cITHo)3K&JV~yC( zYl!#Q)L@?$7z|4yiZ<~_>}<#WCs@(XcPhaKVdcH8~P&nP;;moI~6;eaD}J{Q@i7!+luM52T+=U+vr2(pOB!GSgS9u>N-~QcT_z^9v9I zic1C#&Zhfzz;D2YZ(@5nR<>W1$=Ev=`*&cUu^DC8`ZMLnISeP-`#kIQbgXCL_-t%X z#TMl)6sCeJ=sr1$$jg%-9T(TcGnMY}IFR93yVvb-aD$PR=;P_;3=o zP1yFjn2h_(pJOhj{m#I)1`2ttrEhs{;GAdS9UiM;@8aJNu;#;e1z69(KGRIYx)0VR z(8v4UQCN?~ifh)~yI;n33(ngG&c|Z^wM70+USqg_m}l=H*bc|KE7oDqL0gem`quQ{ zHh>+2b9RBXxbNvv`j+t=zQvHA)dQi#P^=|59+29aJoUKH$|q6^p&p$Z^$AYvl6Vh$ ze7>SD&caH+&_54B_rqA1V*g-lS@&oI#un5GCOor!@mH`#J20^h*C7{gPd1CwteE{5 z_o+k|cIhjW%lK_L_Qh|;cX99*FxC%vg2(hJwq{I&$78WJV#UJzxtd4Xln?C5jDOkJ zH)V(KFeq#MYV4p5qrvD?+9k*IyYWBIjmJtmSRc%Xe#c_-<`XD-{CPTVV$Ws%i+k$| z+_MiuY}(J6k5-6@HSzBftcRg(&c?a~*AgdHJS=e(N<72Y+KozfZO!8ae)fZM!wAW# zE>V-<=lDaMXmUFuVg54=fA9@QkRU@3I%-;$$4uUr&;?-=W#>3(dc-O*3aR)qf2aOS z1o)pOl`Zum6ow1Y$uomUrbic)v-1-R@GLS7|IJNIM{VJcv?bz+dGG|U46~?0vmK8} zJtQ#{butY9jWz!cOYE80&D5sI!&lm&$IDsN9sbM)o+6SfnW<5c=i`F8dIFjEpa3!r z6qJPX3c{8B21RQ2-ZwteB+`G30BVE(p=IEGe6S#xR~iWw2SWv=g|1r`Dv5;h%KMiL zEG>!_M!|NHX2jTy!DrRGf6A9)QI^0M>ATNvyDL+)4 zkAEWheEtYUic0be^NS-TMIkiRqSF2YtJtv|w)@DjdyX4Fp}MBFE;Bb{4~iEI2SR~@ z!u(Kvq@XZdR8&+PDhieGiKe6wrKlVeC2cxoB>9EGjO- zr-BUZ#%ZB2o|cN>s>~E@$%);u-huTKoW*m5voF>ou&$wn84K@W>{GpI<@wB^muR_& z2J-ud@sJ!~*yBPiCfu1Ld(2%uFWA|2XsD<#FI*fBp;C(?p-7}86fP=8rCW*OA`}Lh zVVDyO{zXmVBtoe@pO5GCEDN6;As3DmR20GtCmiCxs7(B8mVuR#{QS~T3H(-8Sd2%g zGBYL_MkXcsA++Lrde!`gV%aqO7q=DEUY;AkxeQO4E3YtsYc5PlUg-WM;10-sLPSSm zYdR~?20^PMEd?GMgMoYtlIPR1adFL?Ve2&J+vWWn(b9}#q0eFZEPNJVAM!ICbIgn5 zW@lo(J8Lm~D*qi|?wMssF$yd1m+UV*i2diRmISgiV;s20oBpK5`Y+x*DS$V_5;}mJOk?%tnBxoFJ#7_ z-^CXF$bWm`^~5-c#$@_0?Dw&(8*qFcR`wm!mISX?Ud6+)vfr1y)1?Web}?;5V!F92 z&P3l~4(^ll;Hw2Gfs8%g9d~nv;eI$4JyG5-&4OHc|Kr3xX$u-Rd9AI@tD9P5OJgHeMjU6tgo&*y*RN<;-Q3o& zs-?BLV`5wTf?11aHmqn{+`eu_!;AxJ8;%^YvSCC=!~TaJKDnlL!V1ikJhQ2-ZCz(< zMSF8oXLHQiqor*{>xPxhv3)u^SGKfuPFS-qzHU##mbGgE+gsWUx5ZDMjqMH-M08@) z#!bj#l}hg(aT*%dg0#dM)^gj>(XzU&p?Q5v&6Lr4rfFPEcbAVjDTXp}Sst6NX^^=j zSq@Rr)7)7jux8Ady<>&h(lu@BE!}ue!dO#Uh8tR2*GW=Xw|var5vRSmb3=PutO>iP z(8P`FT2{vTaP?^Tp}wJWY|Pfhj18;C`N-1djxn*5B2Lrtb?u!kZL7z{T09jzaU!d+ zxuYYtx_#Y-^|9kyI@iSNVlx(YSVzS&7Io!`Yu8qfi@|l{VjZj7#;t2>?ijbWY14uQ zOHl$W8OdT4082W(LmXT`di07lP3>c9=!7iktj=E2)lM}j)AL)ku02NI#9F3T@7=P` zh?RS{>^Z&GxWQ)^%K`19wYiKPlXT{oqeiUUv*l~q?Lwi`OOtAL#uG8B_1Q%m;jy%I zP0Ksj4(dnmq`Yma8|p_J$4guFD#_u;oc6NzQs(;nLwl2z=FQ$#O^*DsIh1YD`ZT37 z?SeIBf;rSkSLuT5A!{q0lxn5k_Li;w_cYa?RnKIrN3+8=SB_JxWL7QpJ}tc{s;N%5 zo$a2Bxu5Qi?N|NZulm1V^?$$W|9;i~wSjRb{_V4a+lRn^z5iSDRsT0@zxjWl|C{0J zulm2}H-FXt{i^?q_?Xsvjs36mf2aO;^^K?XqDcGAS$p6$k}~VvVh~=6&vhE{8N_D1 zj_$^11KaUBF&3x~EDo%}yPhio_^@!NWCrbo9_H3pUe==C?NO_Hvsq;}^-`{s%;ubB zPnWqphkv{>-C2E@Df3nqKl^32JDGKnO(vXCU)g11o;uAXQ=eAvxn&k7+eU9PYoz`3 zE|V~AtS^}>0)Zj!-gD84Ib1*d>MwWj6NzWAeGJ<-uw9AmUDtfM;|*+UuKRMwr`XPU z;L9ESWG3&8FLzABwiDZvv8}*4E`bx5I)P1Pfg#1A@a90MjGV8F*FfJ`3doXO-VX6n z{=BQc+|fnZ(y}?FgAR-q9Uo3O`wiZEY~64?x!U|@aR+*7zb;IBG}c$a&w*Xe{-tH- z1ZS2MxTgnTlCkAv;K|p1xnsb<^z&r{_53x!W54_5jwkr;E}8z3-FTjPK8E#$*T3A+ zjIA@HwCvL0?9xG(xU)-R7w63`9eq*$+|ufE3g(v9pBXx+G~QZTzkg}<{-vX5l*VS1 z4ubrQQqI^9AHu%v&=aJdua>Vo@E>?!dqLc!?v^c^J{R5M6`xra=f}-fUy44nuRS&| zi*aU9Ta!7@S2SGo+S2#@F*!ffo=%?s>z6zD<&$$oFwPBr-EEg{H*R(cYB;bQ)=sCqn9?XjLmK8w0wNsv@z+zQzz6-sG)FubzOCu zu;Jq;kHHUz@p9K#Zr%Sk$;Ol7f!MExm?}kH1;vJ+L2%m*^=LSRPB4>OQ z-(X#<>Lhb66AjaABhED!)4)K#8;icEqKl7Ud-M6a6$MIY7G=zjFchn zhyRIpuy5skHU#b}j3QOu-YY{t|RYD?hh)QQj7f^ z+>b@NaA9NqDjtlET#Bn6pY8CVIub)k@`C1|K5_{@<-|*Uo{2{u#JkzNd~+~2G9T{9 zD=-I(Beyd5kU2O!@`HVGP#9PS6B{E@dl z;XE9a2iD`vrpQ@vS6*cR8Q^vIRfphUPyjx2&WPaCP$#b{&;V^`M#hD3uuEVa4$g}# zrGk-xlOVP^^4fG9ObncZgDWDB#Bfk;4!R<5@l1_5xIOYK9@LtHt&#V6P!|}FG!I8U ztHHr!V_SFR1)#jCfepy#8KqdPZ*8; znP$Hr{4FR6-2;)bYP8n;+nIgYi?AgB4zqhcg!At-yRROE{01*ag5n1twH+&_`G1cI z=Jv;_AtY#)m!Nj=olyl!8~g+fJoFT6AXJJ9Kr26l4LY3HFAl3(aixTJ3)bUIL6{At z?2rB6h`r42CkJA8?sC!_;nTu{%PoX5G#}XI1@%`dR4ULq%RwXeP(Z!Vf1tnXF3*Gf9`79)#S4rr6h?3VJc9pIt zE_BZm$;vzMxkPEZg;yxN6wR@;)56;oJ^<@WH(K~`dPddxVtkboiebNUKlBYsParOI zw`uZCsE^W(xBv9K&I#ia3PsZJELlRB3oe3YI}T5^ZnB&JFJBPAal0m<8m3*GK?$h@7B%dZjVa-#C4pdDhY?opkyKj$-9XQU1x?hzL=6Ht0Z!7rR4l! zki3@|cBV_-s*=e4a!P)TFjsmXaiP0dC3(qgQ^|o&sGE|1K~yMxkhsuoOqcwpO5%?~ zeN4%pQ1T&SlwBk%6LG*t>=n0NlhgQVVQ~mD8iW1Hy1gLz7;&K+n~7vtOfgreBr;k? z$r?8ACx~Huy5z+wi3{NrO0LFzptPH~&|RaFRmlAzmE6q<-G==^n`cAvY2p}~orn(l zIqu!1&kF5Q`T%907uub!wzN?;5OEu^LhM|{*#+44kU8wX& zLK8xb2aZ#*yQ{I~D$`1n>Y0PgMBFV!*i;CKT3Da-N0fC~U(O9X-&(ixi%R zJ7aXdg_kM3Z8yLL7G9w+hENeb$inLs-oV;iXyMHY*_(?lvhYrYlW}v2F1B#1!tc_g zB^G{9;lMorms8ty zS@^cXRp>oO54W&K;dg2QkFfB4g~wI`9%p?0XVI=t)Pa;aq zkxOhVBgruq#ufH3k~CPDP&k;8q|w4|g@0fqX%d|Wh|V#*z?X|og}XA6tPq_FA7La} zDLNG{*&DD~bj}r>XEKtk5}gWnFr(F?Q{h33Bx^*c!n!elEuwRt=sfx$z+*+H!dZ+Y z$B9mbm5d~TIa_ot7M(BBq;o{4!U>Ed z=Za2+e_vKa)Ibn_#umVq3Be&gpuST(W&rMMv{v~=Tg!6 zOfBFgqEq1+j3k$ePJt$p>_Aa%3^D)Warh&U%2!!^m+>U}B&y`OYQS$;m{=y+eKrp8 zn-<0o7FfL$@LLu-hX`~J0=!&wDva|2|F-BnR3s-el3XD=4->ep5b#RTdAPuj7M-hA zCxga4qEq2I_DSv)ooht$Wk!;%qO(Qdo@|QuiOypM4lMz^Uvw&LBK)rCJWeF9DF=K& zbhZk7n3vdtqI0dlpE8nsPjo6oDV^v;qO(mTUt?`PEIQW-JfD%|5z)C`;0jzp(MLt6 z!e7&*?~Bf_i{u zKS`2*z)12V3%eBF$4K(3h0e($c`qZ$HVYdSuB7B^7IrHBP_X(BmtKHysxHY)sLPr#p9*sbud zj3jSc7)wa!tzz*209s%EJKPwXjFwyNo37Sr|V{lFwvQ zeBZ(@g}0ysQH7Qww_(4q_zvtA+6kB>Cx#B%fK>rSKj`lD}E#Tqu&CGLrn= z!bXMnGm`wn!ft^kl6(WP%*2oa+cUu^5J=^}Sbd-KBu17l63u^RgZ#q6gu>k!NxrnO zN8!1%);${jw0$722)z`3azTLSvVT zhG!X0@`Wap4rDwp5Za^kG6s~8(D-K2usdBI7TTrs29}~wsIx_6&u2`D2yIk)G=oZ! z&~BwSF;)}{ja?=hrq2g05t>k1F%Gm;Xphq3y+NZwoAtDKvh$Xn2ry zJV=#*m6pv09V#?-g=pxa4Z8?UD6Q!ax~tG0 zr4KXE>?SmRrDzDnKx0C?lqMX|VM3j&L^iM(ba$bRN*`gc*+Xcz(k=Z!hYO8eEgGT> z4I_jmlx}3a87Z_!>D~-DqlCt<5e@G!;*1vBrSwkf9V67aR%ELgbH)m7RC*<^fIWqF zD}8Pf=s2OV>qJ9w9q4$W38gPqf=&?HBh&<*;@u?hgiPQGIHAwb`l|Xxk)S5Pvlx)S zUX+JxKx>6IDy<(6S|>E2w4JeMlF%-t;r&1-3++~VHiOR;p*>31vtdpZ>U4<>10taH zLSssQ$>1|hXk6*fmx1mjv{7l-4A8xWCY0VW6?7k=T}n5N0i7+ZlWg7TTqBw;1RlLc5h-0YjpP3hhx^#o%+8Q0L}2gkbM$LD0j6#+2U9 z;B$n~xYCgf5=RPcRC>uCphpQ!C|$P{zQf?tBs8vcID^k}p^Zv^!{D<*XhNt7KIfw(ChUYY_;i3&jbiXw72sLC zKvy-pGWe_(+M{$KgU=eFv0KIH^B8s#obX3_i!HUZv-8e-h zZ&}A@s9vQ99R_-)>Qy?f5cDk7d$;JluoU!c)vI*h*`VjBUZoE(_?)YHl^)EV&v~l% z9??5`F6jBHSLxIk=mn}*=~f5yLe;CZhQa3|)qAh#{fNQmV%4kkNd})wRIk$M3=)^B zUZuC#Et z>c2+ldZkB<1HD%0W~HN+fnFzctI`v81HE48Hl@GhW!oimyV4tY+1?1G5LN_aYbqVOLLbodY$Nr$V3Eigj$zsskg>F~s z?ge^>(6R@_-j_;1?-W|CbV3>ET|yTtJ&K{@J3`khol^vQx6sW>=g$PaN9b0iox?!y z6}nC7hydtTq1%=If=%Ty=V0Yy_< z9uvA=>G*ok$AxZIT8X9~eM0C~rFR?x`lQfpN{?Lt+AVau(nhwv9|$dbNbLO@+s;!$ ztCfDj+@2P?Sm`yap=X4ySNba3&a*-{D_sr!(dUG2Rl05$(C3A2Q~GQT=nF!(D?Ns7 z{f9!!9u|9N@tS{8XtmN~L!d7SU99xr-9cX#x?X9~SkPC5ZWd~S&zXoEChYV#|Ke}= ztp%x?eIOES3-BynLaCaW5zyC!Ha;Tet%p$bb)n9qLic6x`LWP0rJEUi-Vhr9zR30; z4EhtHJxU*8@Oe{c;xTmw@2fu*8hc#mKdIp@q1{SPVDgF9g!U-?lui46p^4{2_8JDC z4}`{^7y1!{&xb<0m0o->=tn{uUl7@9UPvDcb$%#x9P90OLc5fam_><7s%R(gP}p$&^c|0T3b>3Ix3p9_t@A+nz{_N9pGMLBAB5_=(6aih=GB z8hcad4+erdL5UAa@82CXAhhwPBD?2U(4bJ~ElW-CabSlDJNBbId~*14HG=HtG%PgsGs$u#FVI4vjY>mot`XI%^pT~YMXFcnJi4=3^}a27 zk7NKWQN2nVMuC>9UZro10FA0%r5ExJTBdq`E_x503))ZhDm`irXn)nKbVMa+x$0Hg z%nGScy}uB>&rSgypn8=)RS!B)^(y@u?=qFDS7~7Z=pfbmOVN8XOI)RTm2P9%2CH7B zf13}A-x-+N>`^*{0eh(GeMj`JWdqtp^(wuD0dQB5ZV z&|#`q>5r**ch#%(4Yr*5!SLtkCwxd+9(tFt^ zN2}gni{9NCX2z&qrPtwXbgb%C`fCRFJyoyL_bEG0_5Mcmo<0k7yy{iDmaT7s>Q(w6 z=|t75bU`g>wd(z?=nd=!TBCZEzBvrER`n{KKN7S~^(y@a=_J+ruIQb)C+K9=t8`XA z=oHnf^nG5NQ&q3h^Y#I)SH169y(ajaGFgI;{f-ZRLw+?#)iMU3y@EVj=r&4%sskB( z_7>{Uxmc>EGWhHxv`gvrd7#sU#y=3*U0Bik3hhz)Dud5{LK7c~Y@Du-3ypmw^sR$H z_ZQl&bR#dt8A2OB7TG^B_{YXh#{(F&ap94BaXpho;7<>*8 zn)rjrp3LAgS7_{yLVv;FGf!x@(w{N-94NH$Pa@k{2s&S=vt4Mc0Ca)SE~VdRi4PJQ z|3qXzVA&Q5?NM6FJM$u;i9d_%5eyQGg~t9O^sL=Mmk8}vdJBWZQlX8XitHa4e3l7y z{wnl3>OEL!m(sj_K@Slc|4d{*rrtw^_9*=wgU?|?6MqxghZ%eh7aIG!&`JiBBZPJ< z{ZkC|NTH4Y5ZR+Cdz4V;pF*Ewn><=*m(sls0sWfL_`gKtF48qZV?m)0@;Yu2+O70x2A^YvHo7AFC4HX$$f!-gf1Snnnhnbwaz89>n0YUZ_(bvX`*| zeO+jy(mGajyU=c>?=kpv2#tkA!=}Zcok9~z*Ry~dg!U-Cn3v*4q4BV2D4;u!7uuzC z6EFNtLY+d99l{Ig1fh*e&z}Q&qR?)o%NTr45*mw$hHo(VoGdh<^e+rPrwHv)x}7$h zDl}ds8sd~aO=y?WsRf`3p-!>LzRnV#F0@hUmkd5<2<=ung2CrZp|KLtP(KOuETIXd zS2OsWEwo4JV+<1K2#uGDhP*|f=L+po`XGbPc|vicuuX6UTgmxC8}m6H1>R4SKQA9;F4tKray*?POv8U|t;{ie`_()$>Ez9qCr>9q_qmkW(oh=%t_zb&*& z>B$T}R|s_mh-?jm&y_+Ol@_ozuM*m=^dw#vR|}2NPApYVlU^ep3?Gx*#hG*%_%&0|I1s(O|Fi^1nM)vNRp2A|tiuhM)5i91y9 zVA1>cp`drFUZuOxop-5TrJLDYzoUAU&ZXYFRqqhd+cgLD9@VQfk74Fs)vNSQ(ygjj zX=EzseX4h;=y=ZC6ychMVV*>)vNSE2A|hd?{Lw35wH2z zRj<+s3_d?ry-K$+_`IQdm41s6=FOn}m?t(u^)kZzRA^l3iM(;WCA3lL6O1rF6Pi%k zz}kFUXqVD{%RqlFv|H)Tj4;0t+M~3Vk>Hm?osnYMDAv$BLSsrN(PzIB8drK3yB0k{ z8l)ldh^BbXEN*6Mg{8nhU((jG|eOG9Y(ragfz9-ZfCH9VHgn3_ROlcb< z%m+f_N}CyBJ`~!h)Zvx&knn2=iy5T}rDNVg4etTj>|9<4=Y5 zC|xlV^shplF=FqeVW6K0jVZl>5$10~<4TJdOa3mjQRx|^{}7r``d3Dne+unVx<4b# zzl3%xoda8Q(wvHo>UsRr)h_S;|!Jc+vY1LtQ`BtMvYHp#4>^(pTBw%T=$^Lm28R zR4;Er>{$lbtOlrFrLA?K168lmvq&pduhOBs3lo^W zs9vQsqRaz1Njj7%m(fi#&pu<$J(t}yz z-BqvBqZ#V{KUVz3;cdX>Hg*GEUHUZu4m&{3*a>B9`6qg8L6=)Hn zYSlYg^!|z7sZqU3kH^_)t?E_!8n3K6)vNT0JwPX^-YKGYEW06-Rj<;2u*6eTuhMts zgHBbwN{?fS>s9Ym(Yuh|nWlP`K0XX|FV(B`P=?UGRj<+>+OUu6t+#s3#3w(79ciz$ z@G;NhAXTgPMuHhG&lb9)B|+6j_6}wVtyjuxH#$e?+;rvDXf8&1@~7v6L8{KB@_8=L z7P^g^;91vkntTc7GeHGnVDvzjXA9k}n&3SoxJ(n+aVh*H^<*ZvjX5lIc@|TxXaeT& zv@gNkOi;}n7P&kNllDq;(5IRp`BSxbnBaNlu*~IId~l!%n8S#JJWs3mZCeziY5{XN z*yUM-^S#q@I8+lPf5H-Hf)AL(;V#c22Ti~n&h;huIuop64oA2=i!$t!mIFV#HuYe0 zzytJ+OmI1?^C*{R@!nDsFo%zP34Y83SFjIuw9B*jf!_4A90o&`$szeQd>%+uh%L9# z<=H|vrU{tCd|!geOmH%DXmWWLWsn3_8+o5yA!-szAE4|?k?mIH??L(Psyz95>}6Db zU>o^l;El zk)12lSo4f3Pkumi50ww#1KTE-XW@8FKx_W$OYkcu_~{-S!4OBcoH&xOul_z15$Mv`zU9+JX`3- zXGsEDey=aVl}vC*013`=dA88qtO?#jf*wtfe8u)66Wq@n&UJYfSE43h4*k%DG$thz z{EG>`&K%Bjc^20Rd%##s8D@ABAUKQzsVX0V1Q)nG3-4WlT5I601{l{@@%17rU{rs!BQ!7@?F4o zCb(-R5^QmK7T3BaU>TWx|m+N%;i~>K@%{CHQodTPG~6;)X_`dba@sz%uOr9 zmA(XLGQk(n75$dWv#2;tz#LxG1j!-A2bf?RFZiomo`sj@rRBikKU34m1biD&bqC9E zwac^k=v5L_Eu*2=ikgJdDn_yEM0T4hr!|K!^C-s?zzmS8TUlpaF3-Z61JkTI-10}dyU6w^eU9ecDYDLd zYhKldwBat1jSDqxe_xDxq{Ts$ax_TQ_<2ZhkIS=Y`J@69(EhB3Uyo3%EEE&w$3dTS?Nod*r8Sg&L1e3yPNeJ)MRu`L{yabWlE^kH z-3I;9mqj)qw3t;l_E0e_Iel3LNYzU-k>GWgXA9j+RLy&&Z%Fs9OX&{MH>FF~t+Z+u z=v&f_iY<}?){(xgT_2?fk^VxO;%23*N#Bthb(hlFW;jf4m=7x*SPt3W=*>v!IWs`t zlN(6&VzFWIWYG5|=r<~Th_W9@kn2|Z8tI1;3brc^vcw;Wy=6;8@6&uz_*j}{Oz7Yp z2)TjCa@&ssyr7x8H{Z_P znmhMbqi&WFtTRyUo-J&uqHvgp4d(XY~~*g)_t4!Tw*&paGsqw82MaWfit)8 zjGcoOf9l!H!OBU7-M6m82{T!6-bJ|l>}0`t7jw4&e+SwoGn2FC*~wYMm+=%zRLGQJ z$NdbO2xl41Kh|J3E}l1%)he0qxH0TUILl~$tHJJim0SrON2(-r9!N>fGMc~MVD~(c zjBu9G{B{ekP{>(E^E)lPUEu@!18%hN;q;82){Lqg_q)u9vyA4SV6eMQlXI5Q{F5x) zu8^~g=AU9=*-~VHB~0V-b)9txiis~7od{cdST8ILm1MnHE+n>FRWi?U@1i7U z8O^`bV7EslPlD&!)6m>G9cLsFgXG-?yUxK<@05(@i6nC0LCN{UAbGFBZaiIbno1(~ zG1!lMJO+~Y8SE}rNnTu>w%6o7&~cYhlCzBFKWMPqm@dg_dyQnFAN69&7B(+hBK%O5%ET4phnA9Ct757j2#m$)|~9c1uC4dSk$T22FA~Rbqd(M^s))0U=D#d7u9UNk=Kn}<E9kqb}Gj z_$gF`!oPv(C7g~rw3pfCbkw1_xbrwAoQ^tlklE#Q)S)G2w-qfS{4MU5=I3z}9u_!; zkHBU+>M}DOb(xuty39;RT{gQGaoOqj3UUpP3UJ!rVopaL9%qt;!ry@ocO$T|Weavp zc>_){XPPb?95|gx?m$5chXj~mF=v`C92!{4eaH=03`dH8R03@s(1f z`dz5$ZzhK?`m8yO`Lj7Wd=WqT#r{aN-lEUxfp9q|hcEhq`(@>v9KPsF?hh*G z6}K|?kU2QKf|J7+6$Y+_iH#MU9KNV1a1##JROAP6P-4orzJim(7xgm-ofVuMzNkF# zBFx!T!O7u^Dgy}|Bq}&Le9@o)Z`5a01aL_gRR!*Vwlgcng>bM-;1L|0SHa2Qi$(^1 z0XUz>`Sxa0Mra zFPdy@>#leKsAy{7N#yg4Gk}xB7hT=IcoIBXbOQ@nzHoP-8@cP0b8`5in^@d%IVXoN zx{dWyhK9-?V1&Y~L~|FX*`}S4vN{cYRcX01FdyYB=H&22`v=I2IXQgM47<#9KATqTO5as;|#!UhfCm^6C;i@7(KWUdqnP* z$4n#g7zjc7DSi-#QK1gg)4&ft~>LymO?ER zJ(JVNr$*lAVb^QsaNDVo&v^K=-C?aOHte5zXv5W#~X29}?Kz9Cw{E^jV63 zJ22fGcc1KpdG)gtrb2_ZDp?M5T!RY!8LNFIET#ok%KRH}+%AwX!#}Mt(6s`N`+Yq{ z%M8r30*?Epo}!Tk=34>B{e-8O7wt7LWd1F{J4X<6il!S_X#PbPZxo2rjeqi-kAjf0 zUFiPk?>3?Im+czIX~)q&r|~pG&;LtZ=%aB#VA+W-v`Vr9OlS8xrpwla7D;axTA`;4 zt?&U@k?caJXJmT7%qVLYT9bRa&%3iPfjiNK zPM7Sx3!N_6dlyqVS6%3@y3k*Bq5qe= z&`+>e8OrQg1+KXh{kOC(^zS#Mb)i4pAYEt*rFEenHHX@Tei28>F7zIrF7)uUF7(8- zF0^!~O&40a)6#{m^K_x-^2dMf7VSdc6hM#B-SUofp?^Kp9B!2^^svBGbG-eOp?_v! zR|J-tIEz(;}e%yHsm+r^#`yvZDQoiy~ zYSVv}E;q|`$?%1}1yshv_Mn+MEho0mp6EQ*?lV$&UKPJVguX3v;T!`M00r z-VWjf`UOUmmKV9DLrVJv`iIIY(H1bERJvEu-bM59H0}<^1Npuj^T3W{MB zZYUKR>2MP+54fd8MNAvOVIjI`qNpCy5jo7CSI)yC%?6K@fxx_SrYIQ(Jri-Vv>ZwI z!Kg!YlGTAk`&AK?2|&IU^c#j^^v?_ITSQxscRn?hk48Gqh+ScJpb}4=#u{kC-{4Bu za$cY)I0#+X6yxEb)S(De34sO*44x3!uSyF@=fwwIKBJ164}oCVdXR!ci{Rz{A#^WU z&Yf|(b*DNUzRyqj-Z&jDSKo)#d4=k{NXl|%Uz9qOf?zm8U15D#k`l3?G}E6^^=Fy- zvtPPD`+IA?+*|V%-kR5%K&9Ztldb1U)?%8=_p4H;r@TC>%H!q1c+^Pqa;DQ$Wuz1O zZs=e6{J-7jR|XJGoF@Dm2>h$G1pfxG@9=oyy7iqC+t*B7*}SoH-MZF}=Fag`C$_I! z*Ew-RNBhLqmgN&yuUIj0Q~i{NDU-&xH?LgN)H%MjrESBeiBl)Gw5@2}u(H`PqH-{C zc}r)9hj_(-e7*v!M-irA@NBxf7+e`)ivz*Q6A+3GHlI z+iWTK8rC*9F=LFHw6!mowRq;r<`wH!Hn%sxG;)j%S>DjPfeLVpU>npIq;4c|X7K*t z04JE|UdDgIXPSRc!@q%o0}EP@2nJCVyTi($Gbd~1unv-5{vW9+QxREe#97g{xP9G< zhSkk&4Kog?ZD`uKX>v_%vU2b@Qc+;ooUAC+j=CMSlht48)q$kR>cGBK2lk{2tZGxk z*wuO`^;9;p%BU&UfDUk0g|~z^!rQ@u&Gh`{g7E#pvE||UrUE((-Va}o|86k;OBXEzsIpSg7h21f_NH$lY6c6}Ir+${{RqGq@7QEtL#^WR`ig*oUl|K4bkX$9dM zQpoNH#||{-C;5|1%9Uiik#%Q~*Np^V~t{>StxBKkz?N z-{nSvpXCMqhcbYBuK#|}MU>#29{;yTiJJd^MG1X|+o>qgwbN0eic#X`|7)Yf!4f5& z!j(2N<5HOSZ(a&Vr!M3@)1m|~WUBv9<3yTzT*#g{LG}M>oJdn|tp8^)87H!-pZgy= z=RCJcqXgCer(r0~dOF7~4E`N|-dw_HHt)~+uiI}j@Wi?Q<`U5VZgFs&rvP*R`&#Gd zWE}12Y-;b^f91;d8K!?TW5X(RZ)zHr)=z7gx$uBGXGKf7fx~;+ zQZMNy_i}DZFXy}tgFk9&tNj(2;@%2Oac>2txVHjR+?y|aRy!$6zA5g_H^sgArnooX z6!$e8$v2lhXgD2f*0pyo->@pPmTT($jzUHj`|_!oW*UqCg0b9JK9Tp8Pq?pq!gJ;8 zE1$^cXp40$T8{Q+&gE!t=3I{UX3o_+t*z~~SoyGoV8Y0v0mW%(Xl~os(!Q<@Pf6LM zPOT`}faj^2DGi;TIzj6)*O1qjptbd;swO!N3+ByeICS>XW%Cv-Y&iIc#j`Whi=@|E z&`@Wuih4wX)~3}Ro@A_Z({}y7H+Y&yI;G6p6jI!0zGUug3MqMSQvf&7$450*H8iYS zwJO7Nygsatyhf$CFY{WHi&q?ZTkI=>#W|GtO*Ojf{b39Dof>HYzA%Y%wslO+noe6z z?sVRIVy)UrM|^LXx2R#xyalrx*0*l(SH6fLRJ5*Jaa?9?Pce-EN^-SnTOwcXQtSS^ z3)+3wJFmfB&$AE)dp)1TUe717zabkX-m4-h?X!H6x!U}OPt_)val5ovPfmHCev!|@ zv$RQ?S#7xAHJ1B*W4YfsmixV9x!*mO`|Y$LKcm3Bc(U9glGtayxezjxu(Z;T$aHd+ z(3q6=yTC~MJz%ik0S5caZ?LcU)^0CGDYNt^l}^rn?V!_Suj)yCoS)Lid9UTjwQh3u znh@@-ij=(9jVbQ)V=}O$S5iveYY%EE8DTQyv-O#v#$un97W<5}Jz!rXx7eq|;v7o6 z1%)M6+E*SM^1RY4rnNAmO+!t+#?bWgBY||ly=^H?k^e-t5QGe-GNfkYo7C@hO%i)u zlf+)v0NZfrQ)01CiN!gTOfh$&ABS;bMkrHs`UAyE|*g+_sM5{GC;1v zeI*g@D~fPm?F;uu7u))M#S(d+omnnjSZS!wMnioT8tSvpP@i>%`fM}QYZ+RZq27j| z)N7eiuVqTTmMKNww4w9Fwx+esna#r95&W$?d9}%-?+iTp&PYA_n$A|HE_)?<%L@za zt=(G)I6YfO0MgmInn~vy8~1C%h?OjSXFJW=^MJ zydXo_lRy0~p*4|c%Pr^Itj+WJJ z%`0PYetV{mB(={p;Xd1h`-~IrwGNHnc#k!YXFxvR;n8_j>$;{+j~$S+eUTjF8&dPx zhCXb?=Nc73dr1!_$j3%)Z*h}2%QG|dYcJXN?3+B7eaJ?inKLY~_Y`9>JKkdGPVooW*|ojkMQ( z8d{(It|8p3CMBOskKYkizyJEM+*>Ir{azn{*VJSmjxg9~rIq#>X|c~ni+v_q?6c5f zuYstII<44j&EM9E{~lw<7`#=;!kWIZzf=bMN@bgrPl?4oB^KvU;&Y9ao|^VRu)fn5 z8?BJnBPfM^Ai%vU{lZRGC7j{&RPu#S&O|LJ5VRdBh1zYTMin#_dss~DJ3A~<7 zVy}`U_E}<;cs-kx_O&i+iMN=Lw&BF5M4wqCn9N?ey18RME5&_Y7JFeBkan`IJvvrJ-dmPzc*GKqc7 z$7Y$s5)8znuh!ADvAJP+Q-}X?SnmhsF@aAR<}o2N7FsEve`~9=TrhB%aBp!_+*{rh z_ZB$CeMK|FqyBbavDZqtt;W8B_SK1Suazlzuazn8wKBzh^&vdkP_j#84JRtfp zfY8>wsWY>D*&p<2uek<&m1424QY`jX3Ts@35&YgT+Os_Qn0A$AKsafUzj@~ffpUBB zn##+^%KL21dOJzU`!BZ~aZvR5iY$+4XffG(crvt=^WKZ+pR8A7t}abh$Fnr%fd|)M zHY4mar@u|>V{b2Myv0REHjU3~7W*pE;%T}27y7i9vx8v-a=(nS{>}X|OW%t0u0Qkn z8oi)({8GtALyQ6AL;MrhwKexvS6QCKvpmJ2z1v4BZ~IMRZ}UxJ-_@V(aShU0zxYXU zU#24O%T+FLUziZ?*JImdE_1xb4YE=z7b_YS&12ClOY+L-aJ%p~?*g|EOCdutzt+CFba!H}^&m^O6q z(=Zy_-rTgZA@&kk`~7Z|q;+^R-wM)2rY7s@z;zosGrb`n zY@&c!W4j%=Hjn?Fl(19=qL31A4e)=i^S-cbpN+kZ9QrKw`N?9RpR)B0Xp||ePf3ox zfyF*&TkN}USnR66S+C7x4f)(p_PPtYZJ)qf_$0*;?^;u>=4$2ZR*;Dm34x__sn`-u2 z0h+Dzn#5jTB(X0;tHhV1c2IrYHgns|(#b~6WE*P%mf>*o{UV~Ww*lyRuU$&LW-0Ym zlF7mA9+mY~l5NHr%?j=jE7Pwir9M|0S+B*AwRb=t&SD&dWxNb_ByT~!F%O947(K}L znG;HEvDe%r_8OMNJ{MahK5ts=btja_mpnP{LbiL0=MNSV_uFhAznIRq@2Zh5d3tp) zH~%%G)K?B8>uV~8`U+>Lw`_2}ptdx|%aqph?#qsm_YGoNFEit{6$@%B z!QXh3p9D3m#qV}K5jHJZjz^@_W3#O%`w`gxd-bQdSAUA<((h{<$p?mvRwvxoKJ0_1zcy;jC7*?x;GV%@r+vK+-mvV@ zd9&DK?(HM`j5`U^XKfWJZfkXIQ~Pnv?b&sk?sk@#&bDg$>0Z|+vCp$IP~~kIutd18 z=7f9Ir{r_#_tl)}@n6^3IxR5Yz6^oK`*3x&!`BM%L1(rvM~rLmW$QCy$AZU)#B%t$8}8HE3>cS%Jf*_7!WUV}6VAQzpg6uTI{PeZ3A?YzNhGdF1?D z%GckQB)%AFA4xEllJ!@5sO2nUDW*+%J-{}VeTcnLc<`gK%_d)r5fd+RpEeYI$N$i7BtvG2mS*qbRDrN!Pnli1gutaJ`beC^3r2x4x! ztD#&tE^EFQt+5;YvYAKddvN2m6Hc%lLT_P{*jHF{Q_jdZDeWz668lP(ebfy0TkYQB zLXCXNZ$AYa?WH zyo6y+Kg4=v(Mt(ukmd6GV4Ha@@)nNk(amno(*kNnVRD%RP=g2 zf7K^c|1AN-AJt+kZAuYOXa zIq6p~6WDPye>>C^yslR^ozU8{dQE5UP7>eX=BfmGbNz;fRqf4RZ#ZD?iJmJ3HDbHF zSqv~k$Qcilu-JOgTXLw8*D1bh#NG(J4u`nKle2XoO^x~z*s;Uk$@tXS8&VQrhkXI>5@`Mz1Bk@AwqK9VM-vW>lG{mcR?QZMx~ zB2X$KXKiN5uA;v^%Zm#;LcP3c#c>eV*t3^VQX?G$I?nssZN zF?k~9X*5$1PLzoU&76%B&C_gC=el;8fXfr?lBW2o&z2EI%)mVA|Z8+PcMAUD&UytRv^mv_=($kldaA`EGYhB6tH!y8zW}CC0&ShLatN}ZV zK*kB?n&l3d#NIMNjS==M$T4`^)T9l#a<65 zvDd>%?Da|#`&^s)FeN?2(~I`%L^F`VK>JI~emAVtO6ZcFarFniuxdgP{k#$18LCi7m#$z}V zS?qNHT86n1`kFwN+oQ^Q^Hb{04pas{e42%O3zL%fX&3oi`n@hr>G73Q^!R+6z5LqC z%r5RV5;b9zcuiF5GsK2ApICu|6dh`;=ImLy6byq;8*MtrA~xEcW^d zO6+);R|#AqWAi>Ow!56sEr1%~)65Lxo>+>LX0jBY4-ECWz)+tD4D~s{P_OBlo6m3~ zn>m`1noQ0=G-MKZjfP(g^%||zYqV0Y(Mq$M=Xa~gE~Ebf9ro_-7dK;`UYp?%L%lXD z_1dh|YqL_Hqm5o)NeuNiGgzF(GNoS2lzJ^w>a|R%&xTxGW8wOBU}l#H`s|AbuM3md zXQ`F;nQF1mR*SvHLbvqSeR*b`g)AlS%T?rk*$T%imyMn5D`tC~Kpp2Cxz-cjIzHdCo->p~gtNPOjr-}}}=RK`n&wKhS-k$gNqbqs% z0sgNGHWzn5>G@wT4JVvr|J6j#|EcNdw14<%>#|pIYuEhdd99-t*k^4x8h&u&)Hw%F zoHc3M%qjdoa{h1sUq|kLxZc0N6j=41W3zvy;Vqv1w0a+_e+&2Gc@`Uc*&EZFaeZP{ z(%0Uqes<9Nn(m-)Vpa!zQ?oYc{Y=(3HuBZiY-WaT67v2g4*KRM3HlahSC#6cQ$FzcTsaJps(4r#CI$4!6m+XiSMDj#>yt<{jcPP ztt|90+n7f2IogLrIZuTTfoH_r>cz`(KTH^mQkEkW*uxgI@x-&vbUL;&IbO{c7P`+5;*47UBEB z*9xBqUk~Rq;57IK;pf0>#u|lgZFb=jrj$GV#bNE2`F>o^>c4D7|?p|H+ctY&n+eCA(@537>#O}R)lAn9s1y3f#?)|Cm zS7V-qXK?#CNcY+R-vHzpjc}fSBYYvexXz2$S@0AdIW^`2 zct!Z7@J#r%a5E`(9q3nMZh^15ncz6ginI+EBqArfx^4sBZRMnj}u;jA1?e}_$1-KgC8aQO?ad5zr#-u zzWrvjKBo#F2A?au0lrZ9N$_^z9q?}97sJmLemy)Deh>U2;ZMOY75*pqRl@%cUoCu~ zee7m&p8Qz&f$*DzPlDej{8acF;Y;B62>&kpLE$&ReU_~XK#h5t_YJMia)_p!gx z7svau@Lk}!@DcDo3qK0}uJE~VGnua6p}2mR!DHcjx z_?O&Y_zw0rtYUr4RKNcL@K|^QJQaQtJQLmlH`Dz77r|rU*TGZacfm8^PjLUE{Qj?V zf8n2Uf8pD1N$Zda-xqF<_WK_OkA=^Mr^3(V{=&b_{ipl=ui^f}*KmK~k8ywDuX6tx ze*cfSzwoW>4-CcmkP6=$o(UfhH#7bI$H8OaXTVe8--2htuYsFce*fFyvG8^9RQT)g zO!#NqztQhsyEUytEPOwBD*Om|Cj3OWImYkb!Tp6_%>9L5&;5np%l(h_`#;V7g}=r9 zg@48U;ddE&?XV5bhvTR}`vLHHw(kvabG+{-!ZYEEx&H}%{R-}XqVLyo|C4;bgZm4A zocqu5>tE&mC;R>p_dmt=t+quz2;U2yp6b_s10J8|`!R5Hy6+3QzwisVf0JMTL++pW z{&Vi%?EAlSf8j54|G9qs``mw?@BM3O9ZZYwd%!c{W8i74Uq1sL&-cBB`!DeQJnk?2 zD(=6~ufLW1xB31s_dmn;m$<+14cz}szkag;$cII~?+!PMeIEnQgwKSh?SB1y?%(12 z1>C>W_kZU8!hga2&+_XZ;r?B|zry{O`2Hb06Ta1U$cJvfes6fZ)c5glbGGlZ;hFG7 z-2WWEeg*em=KH^J|K;R~q1PSoMEK+IO!%wt=v=?ghwxPR7TeQ0TAT{XPji6@Csp7k)WB{+8e8W_U&TgK+b0zy3LRBK#eACcI_`T8HR6exE_`RQSR0 zT)2IDu={x|Ug7sS9bOTBHr)J^Uw;`q5q=Xq6aD}^y2$VI96S~NS9mVG?~a)N#eSb% z;T7Q{;pP&*{wR1NycwPeUk;B}`hBj1r^0WA=fWR`$KUn)yacZZe;;nX=htt(6Rkrc zdhjtNr>n z;EC`r;F<94?O%u#e-4dS`+bJNQ{fHpT=+@w_!_@YC%hv361e%1UtfVI!q>tx;p^ei zwSJ$s;HmI0;kob~ccpcR|Hbc92d@a93^&*L^{2xV;b+4$;g`dsANzg&6`l%z2%Zc7 zPk4Mi^@$9<-i0T^`|O5%5IzWA5ncz+ginI!!cT#lia(z&cqDu!JQjXEJQ033JQe;V zydwM!cqaUFcrJXvVC2J3{P_=sN5YSQ$HI??C&CxOQ{mr%SA_ovo(aDlo(q2*Zf@}B z{~A0J{xLijzV+_34vFx+;i>RL;T7S>!ZYD*@LYHbH#f$nct!44V^+f>;cMWr@WgX;al%P>yQcG2c8Q*3~p|U-OPFZ$HODxi{Y{G74Ss(weVEouZKtf8oNTSzZ;$i ze*#_+{yIDt{wX~AX>5uY_uqC1t_$J&!YjhZ!*k)s!lPUK{%zb}c*^~SU(Nl6|C0OP z>i2(?`wM@C`wRbo`wQQEPn-|8`TZk!B77{oB77!17v9SKf9Cf;pZg2{KKB=X8}}Ff zF!%qt-~UDKFZ@03FTCGgv<|uO!SLu8e*e+%MEDGNMR*JM7k(c1|E1smD()}*HtsL{ zH{4(N%iRCp{Qe(sf8kr$3#7=0itr)uT=+P6w8rn>2v3AB;f=x*c&G4X@KwTB!Pf}C1-@Q* z2Hzn3MR@H!{`}vE*9+fbD9(T3d%`<~e*?Zs__6Rc!q0@S7rp|%LHKp>+I#)^-vh4~ z{xrN%_*?K!;a|a52_LjS&VS*<;p>GT1>Yci9=vv~KmYUL^}>G$ZxsGZc&G5k;H!k^ z@C?4%(CZU;av#lyeVbu)yykx2_kmZ0kB7$(`1QxZbKz&g(+B*2ZZx8dn;{d#jC9dGoQ?}Ol(@OpUixL-dNZr1spz$?O+!Q=n%>sP^Z z;kUrkC;a+{;n9=6zYNcWe*jOO^6R%a2Bj z@7G@qH!u3W23~>NAKTpPxA0u}EAZ$g>cjOPz!Ty952kgf2;Uu^3m*lKUiSMR1y6)0 z++X-P++X_#k*i_`&d8_+)tWUw;47 zxWDjj?l1g%++X+&-2YX-|9#wF_!N!;=sF`W0~Vk?+^SE5h%9#~=Ik>)^TY9G-sS*M9tt9-9VJyejTjV8o#~^9`*74yYNi-4e+F|Uw=Q`Y~uT~ z@QUzv;PIwZe=_E8#^HE{?+7>j{Q3joiSP;VO!!IgXfwZ0J3JM>0-g*15j^hi_qiQj z5&k&bZ0^^;22X^449|pbeF&{jw1wYiZ+I&FP$T!lUi|KC|Gd@CEQ(_=WIzpx@_e zct!ZX!OaeS{bTS%_-pV?_$TmaN59Xu<7pjI;rqdJ;YYyZo%}v0!Yjf%;AW6te=$6P z^Pdy1<37Uggy+K7!K0n2Klgc!`wRbw`wQRlFj|LP_z-xsi{F1NJP|$5P{e_>; z{de{If1mpczm59~f0+9Vf06s|=J$V(`wQ=PIITlP_+WT0d=xwy?Dsz!o(P}I{e>^* z{=!#r|K0umKjr?yAL9PPU*P`2-{t;$`2G7HfqW3Y3%nwHI6N0V6&^)?|0eD){A}(o z{4(w@{3h-{#P9zg_ZR*=_ZR*y_ZPlNOzRNs>G$6ao(LZWuLz$G&xN;e|GoVF=W~DI zKj8ktf6o1dKf?X@_WQrW{e^$X{e>659T$H;n+q@Ax_{TP5A}}>y}kjDg*UsqlJuMfenWCj4}G zE_^B6?B~z_Qg|f%MtCgzet07M8F(uEZFoiaSMW^ujuUa72tNpJhWhiL1doKD0*{4v z!4u&t;i>QnydwNwcqaUJ@Lc$taI?QZ|G&c{;oDE5b%=!zgD1ip;HmIA@QU!W;F<81 z@Lc#$;AWUV|NG#P@Mqw$@V~$l;WbCn@utFehF63ShiAg4!E@owaC3k^|K;#V_?7Tj z_^t3n_`~oNZvR@=ytGJ{`wxM~!ViI`!jFMx!rQoiz2E;^++X-L z++X<{u%cdK42=XLneHGxEbO1Z-B?b=fG3pXK{bwE4lwjzyD9T zzwrCGzwl?czwp0s|51MbnrS%yh3^7Sg^z@1!l%Q{Xup3e_ZNNv_ZNOO_ZPl~`;YPa zujBs0|H%D?f5H8Q4?GIz|5(5OLGW1kWOypP37!dG#{I|n{jY=%g>Qu%yB$7G_%raS z!rzA{@J93*a5Np)8u&o?LGT>Du!c6wfG5Qdg!XkZv1x;6@C?2Zo*qi|_OHX->t?Qp zUkZPe`;Vvkz2L9IEAZLyn(6pl4x{=V;Dg~2Jcb_zPvEuiIq+1}FNbHM{)g}!ZZ9AA zx*J}9IL&7}_%rYX&h_uZ*NFP9XV7uw@S*5a2k(Cb_1^-1G(3WH{UZ2OQNI$N!0T(M z(QWWbO#SWj-0Ly8X&~qNx8d;wzkbu1H2(^m>-UA{6aD&$@OTnAug^UADmbs_h42g> z*U&t#hnvaNhtKl|;0ZjXa`Ojx4v*lUaGxpEhtHFpX3=rg!Z$(vNO%Ol3w|6thaUv* z;QFc5|5ErB@C?r9|IgrN8rAdqJOOWn^ZL96PeuJ^c0r0i->nz*d%?|7)W06{nFz0k zZv}6H$M6__Av}fG!mou_MEwKsT-5&_ZjPq;aQ{!>F}xQ2w?BrCD}mcG_ZkIX1Lu4@ z2A+%hE_nTP+Ar5%!TsUfe+~B+^-pns_$bWhZFn?;`tJhYFhR=J^YF zz3_GLF~Z-3j~8COpC_EJm+JjIg;($ADZF|=Px$VbXZ3!b!mIc56kffbr||0iJdbN| zowis<7e7;rh=Q*49YyWz}y{h-~g!6e@y`LwXudnL; zJmIIJPxXGDaQ-=`dOuG%pSRWfc^*&msY9RY{XF43|LXlb;r#pES@t*j;<`xT5&Bf` z=PA5;KTqM+`+1%~^NG=?dOuI$)%$r0U;A~}^{LcfUDt44pXzlDSJ$=h>UAx=dR+^z zUe|EGPOI0o@N;Ttooi2{`E&i1@L_OuT??;X*TSpUweae74OiE-@alCfyn0>3`MRrK z*TSpUweae7ExdYNpHAz;{j1lt@alC9SJyS1&*$oO4d?5kdR;fse${miSJyRMUDt4R zUBlIN4d?T=dR-?pA9Y>BdH&Vw8m_KuIIlzXx)xr&u7y{x>t>pdx~_#+uWR8oHV;C- zU$3{z+^dV7MoInQ&h>rr zZ!f7|QQ|jRFZL_%OTVV1{!#0ZH$!^!y!8QnYEAzmVsGo~h1)&wef#;(l^a}td*67h zXDdd%V?VE2dms2)#5&xH`lz4Z-<&|7%QyRz@312^+RJ*;N3Q3=sQ(0gE~=sWQPv08 z`U>{jpV&0Gdc5iNWp;_TmH0P{{`RId3&nA*boJYqt9FlF_lNeNoqX<&H}IT=d0pL0 zx|hzMUpLRRw05;FXj@_*tkKlHxM`k!@@%Vp9(q$tN7I5u9dnx(HMQ7hp)P4^Ub@W8 z>sZ{msI|MbrEbh2qeh2|n&!8)w>33)bu}-y4=n8NT5jfdH7{;$YFWB?@p3z)*SjWL z+3l6$0er<%HL8ze|>%z zw-wLIrk+Q(ENETQ*xEIrU3QdPdiu#NJ>A6Y-6K?aPh$38x2mvJ+FFo?Ku-lwr+eZW~;_dU)1F- zLwP}2|7wS_UD*CTOQQN?D}8h&TQ|PzjWnmZ^(?yTUoEh^@SaS4ZfjRZ&vUB91F4Hj z`{*BfhPA7#zN5edc!@CSU*wxM?{B%ZoPMvODA6)9tqlInjk>QE( zBRa(=K05r7haL=FEMT}dJtt1hyX1+G^khXEi4n760nBj=MV|dAl zH~f(BxiqrmBNCCEG{1Nt?El3 zWL&ah6i%uQg_B~0lX8TU_L3z=IH`JslXeOx}j)T26GI4N~mq11(w zQWs82DV#Ki_ebHRs$H-sbxEO=!bx+u2ZfWWrf||6-X(>Ts&=`el)_0dU2mGhO(>jH zHC;c7DV!8jI4P!ZQcU5bm@YNN6i$ly5v<}zJGydIHNr`I$zoABsd5S@#S~785l-4m z78l{9>Jd)bOID1+NtIJLDMmOcM>uIOSz?5fsz*3!r*Kk^a8izNQjTy^?!rkuJlBPV zQWs82T{tOq;iQzpNppCA6i%wz1&dOb6iO+aG>3aoIH_t1C(YqqQaGt zaME6~xCkdzk8sjnvSJiYs+__}F~UhX!by9{5+j^cJ;F&lg_ClGlX8TUa)gs|7f$M- zB>=zaME6~SQJjGoWe;l zg_B~0llGFuML4N?gp>A?6{B!ccUB>3n!%%PMX8}qi|ByE?AVhq)=lEO(< zyIfI9;iQA?#YH%&dW4hqk`<$HQsop*iV;rA5l-4mmKfor>Jd)bDV&reoRlM+ zlp~y!yKp)r7*0xEI4O1Eq|}9zQVJ){E}S%ncj$se6}zNRO5vnA+=IeNRZ}==4)2n} zNmaXCQA**Yn65X?;U*MLs+z7J#S~78DV!8jI4P!ZQcRbcVhSh46i$li%2AAP(q6Jy z6i%v~!bvfOlVXIE_L9X#IH`JsllGDoqi|B?6i$i}PRbEZ+Dn!g;iT#jPTDD)lp~y! zBb<~YoRqt88eShvC(SM`G`oD#>;g(NB~-v&LnW)M zUb0`xDqZh#Ml+?AcDe!sUebpGOV`syrJW*6J7t!33N7uFTH5I%)K0mjoq|g{T~^u= zU4ac{D@Wm_2T*!xr})y2{0eL+TWchk9)So8Y$#hk3Nbx^QcOEyOm9Gr1vZqeIFd|{ zK$HbGP?qTp2s6C_X{I+I&h!S#GZk|bEs7~w6jPolraV)OJkwsXQ~Cqpa8*x1q?mF= zG4f1%NgL#usz;t_FWE2hOx05kDMp?t$5pAlq!02;)#DmdjyzM2JX4N5Q;s}Sjtf#b z@=Q7MOgXMD<(y}FL)pq9&(r|qnR4Wra?Ufop=_-=&(sLcGrgf~`H*L70P;*Z=b75T zd8Rj%tvKhI8o_y{Hz3c{2F^3Jf%8ml;5_p;j0pZyPpd9j{C`nq)m`~YUB)SOSGQ6Z zd`jIVsnn&RQi>(bfqz44XH4m!tHZ}PJbZwZr@Be_5Ge;$HC zglRANlyQaYdP+R)B};%H)b$h;%8`%S>31FNC7(88Mb}f-DMvnOFF6sAPO9FWss6vQ zDo)_ypFt~iC!|srPDXCx!bx-B-;h?rNmqxDkHSe;hmVkc+|bqG zqoLDQRnw1dn!`&?;iRj>yQFYZ)f7&e!=D(PuBw`@D$U`U&^f89=?5*vbY*G|uL*^d zs-|$#9G)QkY@(_WPTJ`=J?$l*GQvsMmn?*$w^hyX{$LrK{|PKb$FNblas2ZaMB#!CH>^2s_Asq99}B=$w^hy zIjK2(I22B*ntpOpOyQ)M!bx+x-wNYg_B|mC&d&_noG{L@JtX+stdwNd&#GaaMJY@PTEVB0O6$T zDV&reoV1snUnQS5!b$g`a8izN(q3{RAe>aaJ5&9C#=zmE)SZw@T{tOqpSDsLPDZ8W=#(o7*0aF>PrrmvP##}X&ms9dD7_=s4v+s1(vR- z#0q%HekrqbJ)On@FIhK=EnQEiYrsp6i!NJTPtm2FvP(OKSHR0o!;<+RzjPx6SYSih zM~?^#jGzn)Y$#g|q*!1C#hBiJ91CnHJ@d*=0Yq7#6=j*;fG`VeC_6n6XLdxdo5wVE zblGf$+sf9Ge;6!Zt8rhm-*Le?(|*gx(tZyKj^%A-bEe+mvAnHp zZ1p#l@&n$;nM>VmL1=V!q1FmbaCS zt^TN3KIyU)sLm{u0=+ku?VILSGP=5P(W0&q_CNgI)zH$?>#lR&rU}Jwa{T+MDH~SY z5Uy;P+SaqT;tq9X!_+nmE7o9i$*|D2Uc<^J>6TTr>=~x!&r4#5*=?Q0&j8cfCwe~z z*uS?g-!iIn%;?fBV@kJ-E!{G%bju;7TkLsLc0e}V1Do6*9)ic}wgivWZ3!N$+Y&rh zw-s!ce;e?ayV%s5emn^~Vi`kiZo%X=H zTF+{lGWA?DzoWBNOn6CXj`PpyYU@@9K6}PQd{lBG!}UZ=-IC>tyPN0Quiahrbs>Le z7p1kU)6}(hbhp+uOqh01ck=?gThP9=Ztl{yMJ)%lwV1l%-NNQ23r$_i@^;&gzIJ!f zma|*Cmb7)WdvBWTwyxGi&BXwG*SVg)$#>g+vt7u);jT5FxVbb%ex z+-~nU%WvD-=Xdb;&2#5=wVuuI7PYmv^7nSRdfjyR|MBgvc5HF0W4>?oxIVFcXUsUj zZth*rFSspo6^iGKY-a!C@w5BH_MI`a0g-#x^9$eSnPs^BruX>nKC#=>jq!WCcRjzz z@ssSPkH7k=gZIC>Pwa|U19<+MIyHvx-;B3rru}A1`yY>A+b6c~j9Cllj{`35zh8XI z-j~l-|2SKSH0#xbd%T>5531Ti*ylkPujvQ)XI$*G=a<{VPdjKJ*E_Vo@O%FHj1l9O1lw{<@j{ zhQIG!`YY^zRd2N4%i0}F#?Ls5Dqn8*8_4l{mWpV9cA b7r(*vdhvdl2H0;x<3Fq+ogxN^x8{EViNw1S literal 0 HcmV?d00001 diff --git a/openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_tools/generator_avx512/main.o b/openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_tools/generator_avx512/main.o new file mode 100644 index 0000000000000000000000000000000000000000..61391b08e4b8641ac7b33f8c44d933aa387a130f GIT binary patch literal 206816 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

^IpT;zL(i@blh$oCHy`GLWaNx;5S0n+COK>Co; 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 #ifndef __NR_LDPC_BNPROC__H__ #define __NR_LDPC_BNPROC__H__ @@ -59,7 +59,7 @@ static inline void nrLDPC_bnProcPc(t_nrLDPC_lut* p_lut, t_nrLDPC_procBuf* p_proc uint32_t cnOffsetInGroup; uint8_t idxBnGroup = 0; - __m512i zmm0, zmm1, zmmRes0, zmmRes1; + __m512i zmm0, zmm1, zmmRes0, zmmRes1,tmp; // ===================================================================== // Process group with 1 CN @@ -96,8 +96,8 @@ static inline void nrLDPC_bnProcPc(t_nrLDPC_lut* p_lut, t_nrLDPC_procBuf* p_proc // Pack results back to epi8 zmm0 = _mm512_packs_epi16(zmmRes0, zmmRes1); - //-*p_llrRes = _mm512_permute4x64_epi64(zmm0, 0xD8); // revenir ? - *p_llrRes = _mm512_permutex2var_epi16(zmm0, 0xD8,zmm1); + //-*p_llrRes = _mm512_permutevar_epi32 (tmp, zmm0); // revenir ? + *p_llrRes = _mm512_permutex2var_epi16(zmm0,tmp,zmm1); // Next result p_llrRes++; } @@ -148,7 +148,7 @@ static inline void nrLDPC_bnProcPc(t_nrLDPC_lut* p_lut, t_nrLDPC_procBuf* p_proc // Pack results back to epi8 zmm0 = _mm512_packs_epi16(zmmRes0, zmmRes1); - *p_llrRes = _mm512_permutex2var_epi16(zmm0, 0xD8,zmm1); + *p_llrRes = _mm512_permutex2var_epi16(zmm0,tmp,zmm1); // Next result p_llrRes++; @@ -201,7 +201,7 @@ static inline void nrLDPC_bnProcPc(t_nrLDPC_lut* p_lut, t_nrLDPC_procBuf* p_proc // Pack results back to epi8 zmm0 = _mm512_packs_epi16(zmmRes0, zmmRes1); - *p_llrRes = _mm512_permutex2var_epi16(zmm0, 0xD8,zmm1); + *p_llrRes = _mm512_permutex2var_epi16(zmm0,tmp,zmm1); // Next result p_llrRes++; @@ -254,7 +254,7 @@ static inline void nrLDPC_bnProcPc(t_nrLDPC_lut* p_lut, t_nrLDPC_procBuf* p_proc // Pack results back to epi8 zmm0 = _mm512_packs_epi16(zmmRes0, zmmRes1); - *p_llrRes = _mm512_permutex2var_epi16(zmm0, 0xD8,zmm1); + *p_llrRes = _mm512_permutex2var_epi16(zmm0,tmp,zmm1); // Next result p_llrRes++; @@ -307,7 +307,7 @@ static inline void nrLDPC_bnProcPc(t_nrLDPC_lut* p_lut, t_nrLDPC_procBuf* p_proc // Pack results back to epi8 zmm0 = _mm512_packs_epi16(zmmRes0, zmmRes1); - *p_llrRes = _mm512_permutex2var_epi16(zmm0, 0xD8,zmm1); + *p_llrRes = _mm512_permutex2var_epi16(zmm0,tmp,zmm1); // Next result p_llrRes++; @@ -360,7 +360,7 @@ static inline void nrLDPC_bnProcPc(t_nrLDPC_lut* p_lut, t_nrLDPC_procBuf* p_proc // Pack results back to epi8 zmm0 = _mm512_packs_epi16(zmmRes0, zmmRes1); - *p_llrRes = _mm512_permutex2var_epi16(zmm0, 0xD8,zmm1); + *p_llrRes = _mm512_permutex2var_epi16(zmm0,tmp,zmm1); // Next result p_llrRes++; @@ -413,7 +413,7 @@ static inline void nrLDPC_bnProcPc(t_nrLDPC_lut* p_lut, t_nrLDPC_procBuf* p_proc // Pack results back to epi8 zmm0 = _mm512_packs_epi16(zmmRes0, zmmRes1); - *p_llrRes = _mm512_permutex2var_epi16(zmm0, 0xD8,zmm1); + *p_llrRes = _mm512_permutex2var_epi16(zmm0,tmp,zmm1); // Next result p_llrRes++; @@ -466,7 +466,7 @@ static inline void nrLDPC_bnProcPc(t_nrLDPC_lut* p_lut, t_nrLDPC_procBuf* p_proc // Pack results back to epi8 zmm0 = _mm512_packs_epi16(zmmRes0, zmmRes1); - *p_llrRes = _mm512_permutex2var_epi16(zmm0, 0xD8,zmm1); + *p_llrRes = _mm512_permutex2var_epi16(zmm0,tmp,zmm1); // Next result p_llrRes++; @@ -519,7 +519,7 @@ static inline void nrLDPC_bnProcPc(t_nrLDPC_lut* p_lut, t_nrLDPC_procBuf* p_proc // Pack results back to epi8 zmm0 = _mm512_packs_epi16(zmmRes0, zmmRes1); - *p_llrRes = _mm512_permutex2var_epi16(zmm0, 0xD8,zmm1); + *p_llrRes = _mm512_permutex2var_epi16(zmm0,tmp,zmm1); // Next result p_llrRes++; @@ -572,7 +572,7 @@ static inline void nrLDPC_bnProcPc(t_nrLDPC_lut* p_lut, t_nrLDPC_procBuf* p_proc // Pack results back to epi8 zmm0 = _mm512_packs_epi16(zmmRes0, zmmRes1); - *p_llrRes = _mm512_permutex2var_epi16(zmm0, 0xD8,zmm1); + *p_llrRes = _mm512_permutex2var_epi16(zmm0,tmp,zmm1); // Next result p_llrRes++; @@ -625,7 +625,7 @@ static inline void nrLDPC_bnProcPc(t_nrLDPC_lut* p_lut, t_nrLDPC_procBuf* p_proc // Pack results back to epi8 zmm0 = _mm512_packs_epi16(zmmRes0, zmmRes1); - *p_llrRes = _mm512_permutex2var_epi16(zmm0, 0xD8,zmm1); + *p_llrRes = _mm512_permutex2var_epi16(zmm0,tmp,zmm1); // Next result p_llrRes++; @@ -678,7 +678,7 @@ static inline void nrLDPC_bnProcPc(t_nrLDPC_lut* p_lut, t_nrLDPC_procBuf* p_proc // Pack results back to epi8 zmm0 = _mm512_packs_epi16(zmmRes0, zmmRes1); - *p_llrRes = _mm512_permutex2var_epi16(zmm0, 0xD8,zmm1); + *p_llrRes = _mm512_permutex2var_epi16(zmm0,tmp,zmm1); // Next result p_llrRes++; @@ -731,7 +731,7 @@ static inline void nrLDPC_bnProcPc(t_nrLDPC_lut* p_lut, t_nrLDPC_procBuf* p_proc // Pack results back to epi8 zmm0 = _mm512_packs_epi16(zmmRes0, zmmRes1); - *p_llrRes = _mm512_permutex2var_epi16(zmm0, 0xD8,zmm1); + *p_llrRes = _mm512_permutex2var_epi16(zmm0,tmp,zmm1); // Next result p_llrRes++; @@ -784,7 +784,7 @@ static inline void nrLDPC_bnProcPc(t_nrLDPC_lut* p_lut, t_nrLDPC_procBuf* p_proc // Pack results back to epi8 zmm0 = _mm512_packs_epi16(zmmRes0, zmmRes1); - *p_llrRes = _mm512_permutex2var_epi16(zmm0, 0xD8,zmm1); + *p_llrRes = _mm512_permutex2var_epi16(zmm0,tmp,zmm1); // Next result p_llrRes++; @@ -837,7 +837,7 @@ static inline void nrLDPC_bnProcPc(t_nrLDPC_lut* p_lut, t_nrLDPC_procBuf* p_proc // Pack results back to epi8 zmm0 = _mm512_packs_epi16(zmmRes0, zmmRes1); - *p_llrRes = _mm512_permutex2var_epi16(zmm0, 0xD8,zmm1); + *p_llrRes = _mm512_permutex2var_epi16(zmm0,tmp,zmm1); // Next result p_llrRes++; @@ -890,7 +890,7 @@ static inline void nrLDPC_bnProcPc(t_nrLDPC_lut* p_lut, t_nrLDPC_procBuf* p_proc // Pack results back to epi8 zmm0 = _mm512_packs_epi16(zmmRes0, zmmRes1); - *p_llrRes = _mm512_permutex2var_epi16(zmm0, 0xD8,zmm1); + *p_llrRes = _mm512_permutex2var_epi16(zmm0,tmp,zmm1); // Next result p_llrRes++; @@ -943,7 +943,7 @@ static inline void nrLDPC_bnProcPc(t_nrLDPC_lut* p_lut, t_nrLDPC_procBuf* p_proc // Pack results back to epi8 zmm0 = _mm512_packs_epi16(zmmRes0, zmmRes1); - *p_llrRes = _mm512_permutex2var_epi16(zmm0, 0xD8,zmm1); + *p_llrRes = _mm512_permutex2var_epi16(zmm0,tmp,zmm1); // Next result p_llrRes++; @@ -996,7 +996,7 @@ static inline void nrLDPC_bnProcPc(t_nrLDPC_lut* p_lut, t_nrLDPC_procBuf* p_proc // Pack results back to epi8 zmm0 = _mm512_packs_epi16(zmmRes0, zmmRes1); - *p_llrRes = _mm512_permutex2var_epi16(zmm0, 0xD8,zmm1); + *p_llrRes = _mm512_permutex2var_epi16(zmm0,tmp,zmm1); // Next result p_llrRes++; @@ -1049,7 +1049,7 @@ static inline void nrLDPC_bnProcPc(t_nrLDPC_lut* p_lut, t_nrLDPC_procBuf* p_proc // Pack results back to epi8 zmm0 = _mm512_packs_epi16(zmmRes0, zmmRes1); - *p_llrRes = _mm512_permutex2var_epi16(zmm0, 0xD8,zmm1); + *p_llrRes = _mm512_permutex2var_epi16(zmm0,tmp,zmm1); // Next result p_llrRes++; @@ -1102,7 +1102,7 @@ static inline void nrLDPC_bnProcPc(t_nrLDPC_lut* p_lut, t_nrLDPC_procBuf* p_proc // Pack results back to epi8 zmm0 = _mm512_packs_epi16(zmmRes0, zmmRes1); - *p_llrRes = _mm512_permutex2var_epi16(zmm0, 0xD8,zmm1); + *p_llrRes = _mm512_permutex2var_epi16(zmm0,tmp,zmm1); // Next result p_llrRes++; @@ -1155,7 +1155,7 @@ static inline void nrLDPC_bnProcPc(t_nrLDPC_lut* p_lut, t_nrLDPC_procBuf* p_proc // Pack results back to epi8 zmm0 = _mm512_packs_epi16(zmmRes0, zmmRes1); - *p_llrRes = _mm512_permutex2var_epi16(zmm0, 0xD8,zmm1); + *p_llrRes = _mm512_permutex2var_epi16(zmm0,tmp,zmm1); // Next result p_llrRes++; @@ -1208,7 +1208,7 @@ static inline void nrLDPC_bnProcPc(t_nrLDPC_lut* p_lut, t_nrLDPC_procBuf* p_proc // Pack results back to epi8 zmm0 = _mm512_packs_epi16(zmmRes0, zmmRes1); - *p_llrRes = _mm512_permutex2var_epi16(zmm0, 0xD8,zmm1); + *p_llrRes = _mm512_permutex2var_epi16(zmm0,tmp,zmm1); // Next result p_llrRes++; @@ -1261,7 +1261,7 @@ static inline void nrLDPC_bnProcPc(t_nrLDPC_lut* p_lut, t_nrLDPC_procBuf* p_proc // Pack results back to epi8 zmm0 = _mm512_packs_epi16(zmmRes0, zmmRes1); - *p_llrRes = _mm512_permutex2var_epi16(zmm0, 0xD8,zmm1); + *p_llrRes = _mm512_permutex2var_epi16(zmm0,tmp,zmm1); // Next result p_llrRes++; @@ -1314,7 +1314,7 @@ static inline void nrLDPC_bnProcPc(t_nrLDPC_lut* p_lut, t_nrLDPC_procBuf* p_proc // Pack results back to epi8 zmm0 = _mm512_packs_epi16(zmmRes0, zmmRes1); - *p_llrRes = _mm512_permutex2var_epi16(zmm0, 0xD8,zmm1); + *p_llrRes = _mm512_permutex2var_epi16(zmm0,tmp,zmm1); // Next result p_llrRes++; @@ -1367,7 +1367,7 @@ static inline void nrLDPC_bnProcPc(t_nrLDPC_lut* p_lut, t_nrLDPC_procBuf* p_proc // Pack results back to epi8 zmm0 = _mm512_packs_epi16(zmmRes0, zmmRes1); - *p_llrRes = _mm512_permutex2var_epi16(zmm0, 0xD8,zmm1); + *p_llrRes = _mm512_permutex2var_epi16(zmm0,tmp,zmm1); // Next result p_llrRes++; @@ -1420,7 +1420,7 @@ static inline void nrLDPC_bnProcPc(t_nrLDPC_lut* p_lut, t_nrLDPC_procBuf* p_proc // Pack results back to epi8 zmm0 = _mm512_packs_epi16(zmmRes0, zmmRes1); - *p_llrRes = _mm512_permutex2var_epi16(zmm0, 0xD8,zmm1); + *p_llrRes = _mm512_permutex2var_epi16(zmm0,tmp,zmm1); // Next result p_llrRes++; @@ -1473,7 +1473,7 @@ static inline void nrLDPC_bnProcPc(t_nrLDPC_lut* p_lut, t_nrLDPC_procBuf* p_proc // Pack results back to epi8 zmm0 = _mm512_packs_epi16(zmmRes0, zmmRes1); - *p_llrRes = _mm512_permutex2var_epi16(zmm0, 0xD8,zmm1); + *p_llrRes = _mm512_permutex2var_epi16(zmm0,tmp,zmm1); // Next result p_llrRes++; @@ -1526,7 +1526,7 @@ static inline void nrLDPC_bnProcPc(t_nrLDPC_lut* p_lut, t_nrLDPC_procBuf* p_proc // Pack results back to epi8 zmm0 = _mm512_packs_epi16(zmmRes0, zmmRes1); - *p_llrRes = _mm512_permutex2var_epi16(zmm0, 0xD8,zmm1); + *p_llrRes = _mm512_permutex2var_epi16(zmm0,tmp,zmm1); // Next result p_llrRes++; @@ -1571,16 +1571,16 @@ static inline void nrLDPC_bnProcPc(t_nrLDPC_lut* p_lut, t_nrLDPC_procBuf* p_proc // Add LLR from receiver input zmm0 = _mm512_cvtepi8_epi16(p_llrProcBuf[j]); - zmmRes0 = _mm512_adds_epi16(ymmRes0, ymm0); + zmmRes0 = _mm512_adds_epi16(zmmRes0, zmm0); - ymm1 = _mm512_cvtepi8_epi16(p_llrProcBuf[j+1]); - ymmRes1 = _mm512_adds_epi16(ymmRes1, ymm1); + zmm1 = _mm512_cvtepi8_epi16(p_llrProcBuf[j+1]); + zmmRes1 = _mm512_adds_epi16(zmmRes1, zmm1); // Pack results back to epi8 - ymm0 = _mm512_packs_epi16(ymmRes0, ymmRes1); - // ymm0 = [ymmRes1[255:128] ymmRes0[255:128] ymmRes1[127:0] ymmRes0[127:0]] - // p_llrRes = [ymmRes1[255:128] ymmRes1[127:0] ymmRes0[255:128] ymmRes0[127:0]] - *p_llrRes = _mm512_permute4x64_epi64(ymm0, 0xD8); + zmm0 = _mm512_packs_epi16(zmmRes0, zmmRes1); + // zmm0 = [zmmRes1[255:128] zmmRes0[255:128] zmmRes1[127:0] zmmRes0[127:0]] + // p_llrRes = [zmmRes1[255:128] zmmRes1[127:0] zmmRes0[255:128] zmmRes0[127:0]] + *p_llrRes= _mm512_permutex2var_epi16(zmm0,tmp,zmm1); // Next result p_llrRes++; @@ -1610,31 +1610,31 @@ static inline void nrLDPC_bnProcPc(t_nrLDPC_lut* p_lut, t_nrLDPC_procBuf* p_proc for (i=0,j=0; i>5; uint64_t Mr = numLLR&63; - const __m512i* p_zeros = (__m512i*) zeros256_epi8; - const __m512i* p_ones = (__m512i*) ones256_epi8; + const __m512i* p_zeros = (__m512i*) zeros512_epi8; + const __m512i* p_ones = (__m512i*) ones512_epi8; for (i=0; i>5; uint64_t Mr = numLLR&63; - const __m512i* p_shuffle = (__m512i*) constShuffle_256_epi8; + const __m512i* p_shuffle = (__m512i*) constShuffle_512_epi8; for (i=0; i -#include "include/avx512fintrin.h" +#include +//#include "include/immintrin.h" + /** \brief Performs CN processing for BG2 on the CN processing buffer and stores the results in the CN processing results buffer. @@ -110,12 +112,12 @@ static inline void nrLDPC_cnProc_BG2(t_nrLDPC_lut* p_lut, t_nrLDPC_procBuf* p_pr // Abs and sign of 64 CNS (first BN) zmm0 = p_cnProcBuf[lut_idxCnProcG3[j][0] + i]; sgn = mm512_sign_epi16(*p_ones, zmm0); - min = _m512_abs_epi8(zmm0); + min = _mm512_abs_epi8(zmm0); // 64 CNS of second BN zmm0 = p_cnProcBuf[lut_idxCnProcG3[j][1] + i]; - min = _mm512_min_epu8(min, _m512_abs_epi8(zmm0)); + min = _mm512_min_epu8(min, _mm512_abs_epi8(zmm0)); sgn = mm512_sign_epi16(sgn, zmm0); // Store result @@ -157,13 +159,13 @@ static inline void nrLDPC_cnProc_BG2(t_nrLDPC_lut* p_lut, t_nrLDPC_procBuf* p_pr // Abs and sign of 64 CNS (first BN) zmm0 = p_cnProcBuf[lut_idxCnProcG4[j][0] + i]; sgn = mm512_sign_epi16(*p_ones, zmm0); - min = _m512_abs_epi8(zmm0); + min = _mm512_abs_epi8(zmm0); // Loop over BNs for (k=1; k<3; k++) { zmm0 = p_cnProcBuf[lut_idxCnProcG4[j][k] + i]; - min = _mm512_min_epu8(min, _m512_abs_epi8(zmm0)); + min = _mm512_min_epu8(min, _mm512_abs_epi8(zmm0)); sgn = mm512_sign_epi16(sgn, zmm0); } @@ -206,13 +208,13 @@ static inline void nrLDPC_cnProc_BG2(t_nrLDPC_lut* p_lut, t_nrLDPC_procBuf* p_pr // Abs and sign of 64 CNS (first BN) zmm0 = p_cnProcBuf[lut_idxCnProcG5[j][0] + i]; sgn = mm512_sign_epi16(*p_ones, zmm0); - min = _m512_abs_epi8(zmm0); + min = _mm512_abs_epi8(zmm0); // Loop over BNs for (k=1; k<4; k++) { zmm0 = p_cnProcBuf[lut_idxCnProcG5[j][k] + i]; - min = _mm512_min_epu8(min, _m512_abs_epi8(zmm0)); + min = _mm512_min_epu8(min, _mm512_abs_epi8(zmm0)); sgn = mm512_sign_epi16(sgn, zmm0); } @@ -256,13 +258,13 @@ static inline void nrLDPC_cnProc_BG2(t_nrLDPC_lut* p_lut, t_nrLDPC_procBuf* p_pr // Abs and sign of 64 CNS (first BN) zmm0 = p_cnProcBuf[lut_idxCnProcG6[j][0] + i]; sgn = mm512_sign_epi16(*p_ones, zmm0); - min = _m512_abs_epi8(zmm0); + min = _mm512_abs_epi8(zmm0); // Loop over BNs for (k=1; k<5; k++) { zmm0 = p_cnProcBuf[lut_idxCnProcG6[j][k] + i]; - min = _mm512_min_epu8(min, _m512_abs_epi8(zmm0)); + min = _mm512_min_epu8(min, _mm512_abs_epi8(zmm0)); sgn = mm512_sign_epi16(sgn, zmm0); } @@ -307,13 +309,13 @@ static inline void nrLDPC_cnProc_BG2(t_nrLDPC_lut* p_lut, t_nrLDPC_procBuf* p_pr // Abs and sign of 64 CNS (first BN) zmm0 = p_cnProcBuf[lut_idxCnProcG8[j][0] + i]; sgn = mm512_sign_epi16(*p_ones, zmm0); - min = _m512_abs_epi8(zmm0); + min = _mm512_abs_epi8(zmm0); // Loop over BNs for (k=1; k<7; k++) { zmm0 = p_cnProcBuf[lut_idxCnProcG8[j][k] + i]; - min = _mm512_min_epu8(min, _m512_abs_epi8(zmm0)); + min = _mm512_min_epu8(min, _mm512_abs_epi8(zmm0)); sgn = mm512_sign_epi16(sgn, zmm0); } @@ -359,13 +361,13 @@ static inline void nrLDPC_cnProc_BG2(t_nrLDPC_lut* p_lut, t_nrLDPC_procBuf* p_pr // Abs and sign of 64 CNS (first BN) zmm0 = p_cnProcBuf[lut_idxCnProcG10[j][0] + i]; sgn = mm512_sign_epi16(*p_ones, zmm0); - min = _m512_abs_epi8(zmm0); + min = _mm512_abs_epi8(zmm0); // Loop over BNs for (k=1; k<9; k++) { zmm0 = p_cnProcBuf[lut_idxCnProcG10[j][k] + i]; - min = _mm512_min_epu8(min, _m512_abs_epi8(zmm0)); + min = _mm512_min_epu8(min, _mm512_abs_epi8(zmm0)); sgn = mm512_sign_epi16(sgn, zmm0); } @@ -442,12 +444,12 @@ static inline void nrLDPC_cnProc_BG1(t_nrLDPC_lut* p_lut, t_nrLDPC_procBuf* p_pr { // Abs and sign of 64 CNS (first BN) zmm0 = p_cnProcBuf[lut_idxCnProcG3[j][0] + i]; - sgn = mm512_sign_epi16(*p_ones, zmm0); revenir - min = _m512_abs_epi8(zmm0); + sgn = mm512_sign_epi16(*p_ones, zmm0); + min = _mm512_abs_epi8(zmm0); // 64 CNS of second BN zmm0 = p_cnProcBuf[lut_idxCnProcG3[j][1] + i]; - min = _mm512_min_epu8(min, _m512_abs_epi8(zmm0)); + min = _mm512_min_epu8(min, _mm512_abs_epi8(zmm0)); sgn = mm512_sign_epi16(sgn, zmm0); // Store result @@ -489,13 +491,13 @@ static inline void nrLDPC_cnProc_BG1(t_nrLDPC_lut* p_lut, t_nrLDPC_procBuf* p_pr // Abs and sign of 64 CNS (first BN) zmm0 = p_cnProcBuf[lut_idxCnProcG4[j][0] + i]; sgn = mm512_sign_epi16(*p_ones, zmm0); - min = _m512_abs_epi8(zmm0); + min = _mm512_abs_epi8(zmm0); // Loop over BNs for (k=1; k<3; k++) { zmm0 = p_cnProcBuf[lut_idxCnProcG4[j][k] + i]; - min = _mm512_min_epu8(min, _m512_abs_epi8(zmm0)); + min = _mm512_min_epu8(min, _mm512_abs_epi8(zmm0)); sgn = mm512_sign_epi16(sgn, zmm0); } @@ -539,13 +541,13 @@ static inline void nrLDPC_cnProc_BG1(t_nrLDPC_lut* p_lut, t_nrLDPC_procBuf* p_pr // Abs and sign of 64 CNS (first BN) zmm0 = p_cnProcBuf[lut_idxCnProcG5[j][0] + i]; sgn = mm512_sign_epi16(*p_ones, zmm0); - min = _m512_abs_epi8(zmm0); + min = _mm512_abs_epi8(zmm0); // Loop over BNs for (k=1; k<4; k++) { zmm0 = p_cnProcBuf[lut_idxCnProcG5[j][k] + i]; - min = _mm512_min_epu8(min, _m512_abs_epi8(zmm0)); + min = _mm512_min_epu8(min, _mm512_abs_epi8(zmm0)); sgn = mm512_sign_epi16(sgn, zmm0); } @@ -590,13 +592,13 @@ static inline void nrLDPC_cnProc_BG1(t_nrLDPC_lut* p_lut, t_nrLDPC_procBuf* p_pr // Abs and sign of 64 CNS (first BN) zmm0 = p_cnProcBuf[lut_idxCnProcG6[j][0] + i]; sgn = mm512_sign_epi16(*p_ones, zmm0); - min = _m512_abs_epi8(zmm0); + min = _mm512_abs_epi8(zmm0); // Loop over BNs for (k=1; k<5; k++) { zmm0 = p_cnProcBuf[lut_idxCnProcG6[j][k] + i]; - min = _mm512_min_epu8(min, _m512_abs_epi8(zmm0)); + min = _mm512_min_epu8(min, _mm512_abs_epi8(zmm0)); sgn = mm512_sign_epi16(sgn, zmm0); } @@ -642,13 +644,13 @@ static inline void nrLDPC_cnProc_BG1(t_nrLDPC_lut* p_lut, t_nrLDPC_procBuf* p_pr // Abs and sign of 64 CNS (first BN) zmm0 = p_cnProcBuf[lut_idxCnProcG7[j][0] + i]; sgn = mm512_sign_epi16(*p_ones, zmm0); - min = _m512_abs_epi8(zmm0); + min = _mm512_abs_epi8(zmm0); // Loop over BNs for (k=1; k<6; k++) { zmm0 = p_cnProcBuf[lut_idxCnProcG7[j][k] + i]; - min = _mm512_min_epu8(min, _m512_abs_epi8(zmm0)); + min = _mm512_min_epu8(min, _mm512_abs_epi8(zmm0)); sgn = mm512_sign_epi16(sgn, zmm0); } @@ -694,13 +696,13 @@ static inline void nrLDPC_cnProc_BG1(t_nrLDPC_lut* p_lut, t_nrLDPC_procBuf* p_pr // Abs and sign of 64 CNS (first BN) zmm0 = p_cnProcBuf[lut_idxCnProcG8[j][0] + i]; sgn = mm512_sign_epi16(*p_ones, zmm0); - min = _m512_abs_epi8(zmm0); + min = _mm512_abs_epi8(zmm0); // Loop over BNs for (k=1; k<7; k++) { zmm0 = p_cnProcBuf[lut_idxCnProcG8[j][k] + i]; - min = _mm512_min_epu8(min, _m512_abs_epi8(zmm0)); + min = _mm512_min_epu8(min, _mm512_abs_epi8(zmm0)); sgn = mm512_sign_epi16(sgn, zmm0); } @@ -747,13 +749,13 @@ static inline void nrLDPC_cnProc_BG1(t_nrLDPC_lut* p_lut, t_nrLDPC_procBuf* p_pr // Abs and sign of 64 CNS (first BN) zmm0 = p_cnProcBuf[lut_idxCnProcG9[j][0] + i]; sgn = mm512_sign_epi16(*p_ones, zmm0); - min = _m512_abs_epi8(zmm0); + min = _mm512_abs_epi8(zmm0); // Loop over BNs for (k=1; k<8; k++) { zmm0 = p_cnProcBuf[lut_idxCnProcG9[j][k] + i]; - min = _mm512_min_epu8(min, _m512_abs_epi8(zmm0)); + min = _mm512_min_epu8(min, _mm512_abs_epi8(zmm0)); sgn = mm512_sign_epi16(sgn, zmm0); } @@ -800,13 +802,13 @@ static inline void nrLDPC_cnProc_BG1(t_nrLDPC_lut* p_lut, t_nrLDPC_procBuf* p_pr // Abs and sign of 64 CNS (first BN) zmm0 = p_cnProcBuf[lut_idxCnProcG10[j][0] + i]; sgn = mm512_sign_epi16(*p_ones, zmm0); - min = _m512_abs_epi8(zmm0); + min = _mm512_abs_epi8(zmm0); // Loop over BNs for (k=1; k<9; k++) { zmm0 = p_cnProcBuf[lut_idxCnProcG10[j][k] + i]; - min = _mm512_min_epu8(min, _m512_abs_epi8(zmm0)); + min = _mm512_min_epu8(min, _mm512_abs_epi8(zmm0)); sgn = mm512_sign_epi16(sgn, zmm0); } @@ -857,13 +859,13 @@ static inline void nrLDPC_cnProc_BG1(t_nrLDPC_lut* p_lut, t_nrLDPC_procBuf* p_pr // Abs and sign of 64 CNS (first BN) zmm0 = p_cnProcBuf[lut_idxCnProcG19[j][0] + i]; sgn = mm512_sign_epi16(*p_ones, zmm0); - min = _m512_abs_epi8(zmm0); + min = _mm512_abs_epi8(zmm0); // Loop over BNs for (k=1; k<18; k++) { zmm0 = p_cnProcBuf[lut_idxCnProcG19[j][k] + i]; - min = _mm512_min_epu8(min, _m512_abs_epi8(zmm0)); + min = _mm512_min_epu8(min, _mm512_abs_epi8(zmm0)); sgn = mm512_sign_epi16(sgn, zmm0); } @@ -938,7 +940,7 @@ static inline uint64_t nrLDPC_cnProcPc_BG1(t_nrLDPC_lut* p_lut, t_nrLDPC_procBuf // Add BN and input LLR, extract the sign bit // and add in GF(2) (xor) - pcRes ^= _mm512_movemask_epi8(_mm512_adds_epi8(ymm0,ymm1)); + pcRes ^= _mm512_movemask_epi8(_mm512_adds_epi8(zmm0,zmm1)); } // If no error pcRes should be 0 @@ -1072,7 +1074,7 @@ static inline uint64_t nrLDPC_cnProcPc_BG1(t_nrLDPC_lut* p_lut, t_nrLDPC_procBuf // Add BN and input LLR, extract the sign bit // and add in GF(2) (xor) - pcRes ^= _mm512_movemask_epi8(_mm512_adds_epi8(ymm0,ymm1)); + pcRes ^= _mm512_movemask_epi8(_mm512_adds_epi8(zmm0,zmm1)); } // If no error pcRes should be 0 @@ -1226,7 +1228,7 @@ static inline uint64_t nrLDPC_cnProcPc_BG1(t_nrLDPC_lut* p_lut, t_nrLDPC_procBuf // Add BN and input LLR, extract the sign bit // and add in GF(2) (xor) - pcRes ^= _mm512_movemask_epi8(_mm512_adds_epi8(ymm0,ymm1)); + pcRes ^= _mm512_movemask_epi8(_mm512_adds_epi8(zmm0,zmm1)); } // If no error pcRes should be 0 @@ -1341,7 +1343,7 @@ static inline uint64_t nrLDPC_cnProcPc_BG1(t_nrLDPC_lut* p_lut, t_nrLDPC_procBuf // Add BN and input LLR, extract the sign bit // and add in GF(2) (xor) - pcRes ^= _mm512_movemask_epi8(_mm512_adds_epi8(ymm0,ymm1)); + pcRes ^= _mm512_movemask_epi8(_mm512_adds_epi8(zmm0,zmm1)); } // If no error pcRes should be 0 @@ -1408,7 +1410,7 @@ static inline uint64_t nrLDPC_cnProcPc_BG1(t_nrLDPC_lut* p_lut, t_nrLDPC_procBuf // Add BN and input LLR, extract the sign bit // and add in GF(2) (xor) - pcRes ^= _mm512_movemask_epi8(_mm512_adds_epi8(ymm0,ymm1)); + pcRes ^= _mm512_movemask_epi8(_mm512_adds_epi8(zmm0,zmm1)); } // If no error pcRes should be 0 @@ -1422,12 +1424,12 @@ static inline uint64_t nrLDPC_cnProcPc_BG1(t_nrLDPC_lut* p_lut, t_nrLDPC_procBuf for (j=0; j<10; j++) { // BN offset is units of 1*384/64 = 6 - ymm0 = p_cnProcBuf [j*6 + i]; - ymm1 = p_cnProcBufRes[j*6 + i]; + zmm0 = p_cnProcBuf [j*6 + i]; + zmm1 = p_cnProcBufRes[j*6 + i]; // Add BN and input LLR, extract the sign bit // and add in GF(2) (xor) - pcRes ^= _mm512_movemask_epi8(_mm512_adds_epi8(ymm0,ymm1)); + pcRes ^= _mm512_movemask_epi8(_mm512_adds_epi8(zmm0,zmm1)); } // If no error pcRes should be 0 @@ -1543,7 +1545,7 @@ static inline uint64_t nrLDPC_cnProcPc_BG2(t_nrLDPC_lut* p_lut, t_nrLDPC_procBuf uint64_t Mrem; uint64_ ; - __m512i ymm0, ymm1; + __m512i zmm0, zmm1; // ===================================================================== // Process group with 3 BNs @@ -1574,12 +1576,12 @@ static inline uint64_t nrLDPC_cnProcPc_BG2(t_nrLDPC_lut* p_lut, t_nrLDPC_procBuf for (j=0; j<3; j++) { // BN offset is units of (6*384/32) = 72 - ymm0 = p_cnProcBuf [j*72 + i]; - ymm1 = p_cnProcBufRes[j*72 + i]; + zmm0 = p_cnProcBuf [j*72 + i]; + zmm1 = p_cnProcBufRes[j*72 + i]; // Add BN and input LLR, extract the sign bit // and add in GF(2) (xor) - pcRes ^= _mm512_movemask_epi8(_mm512_adds_epi8(ymm0,ymm1)); + pcRes ^= _mm512_movemask_epi8(_mm512_adds_epi8(zmm0,zmm1)); } // If no error pcRes should be 0 @@ -1593,12 +1595,12 @@ static inline uint64_t nrLDPC_cnProcPc_BG2(t_nrLDPC_lut* p_lut, t_nrLDPC_procBuf for (j=0; j<3; j++) { // BN offset is units of (6*384/32) = 72 - ymm0 = p_cnProcBuf [j*72 + i]; - ymm1 = p_cnProcBufRes[j*72 + i]; + zmm0 = p_cnProcBuf [j*72 + i]; + zmm1 = p_cnProcBufRes[j*72 + i]; // Add BN and input LLR, extract the sign bit // and add in GF(2) (xor) - pcRes ^= _mm512_movemask_epi8(_mm512_adds_epi8(ymm0,ymm1)); + pcRes ^= _mm512_movemask_epi8(_mm512_adds_epi8(zmm0,zmm1)); } // If no error pcRes should be 0 @@ -1641,12 +1643,12 @@ static inline uint64_t nrLDPC_cnProcPc_BG2(t_nrLDPC_lut* p_lut, t_nrLDPC_procBuf for (j=0; j<4; j++) { // BN offset is units of 20*384/32 = 240 - ymm0 = p_cnProcBuf [j*240 + i]; - ymm1 = p_cnProcBufRes[j*240 + i]; + zmm0 = p_cnProcBuf [j*240 + i]; + zmm1 = p_cnProcBufRes[j*240 + i]; // Add BN and input LLR, extract the sign bit // and add in GF(2) (xor) - pcRes ^= _mm512_movemask_epi8(_mm512_adds_epi8(ymm0,ymm1)); + pcRes ^= _mm512_movemask_epi8(_mm512_adds_epi8(zmm0,zmm1)); } // If no error pcRes should be 0 @@ -1660,12 +1662,12 @@ static inline uint64_t nrLDPC_cnProcPc_BG2(t_nrLDPC_lut* p_lut, t_nrLDPC_procBuf for (j=0; j<4; j++) { // BN offset is units of 20*384/32 = 240 - ymm0 = p_cnProcBuf [j*240 + i]; - ymm1 = p_cnProcBufRes[j*240 + i]; + zmm0 = p_cnProcBuf [j*240 + i]; + zmm1 = p_cnProcBufRes[j*240 + i]; // Add BN and input LLR, extract the sign bit // and add in GF(2) (xor) - pcRes ^= _mm512_movemask_epi8(_mm512_adds_epi8(ymm0,ymm1)); + pcRes ^= _mm512_movemask_epi8(_mm512_adds_epi8(zmm0,zmm1)); } // If no error pcRes should be 0 @@ -1708,12 +1710,12 @@ static inline uint64_t nrLDPC_cnProcPc_BG2(t_nrLDPC_lut* p_lut, t_nrLDPC_procBuf for (j=0; j<5; j++) { // BN offset is units of 9*384/32 = 108 - ymm0 = p_cnProcBuf [j*108 + i]; - ymm1 = p_cnProcBufRes[j*108 + i]; + zmm0 = p_cnProcBuf [j*108 + i]; + zmm1 = p_cnProcBufRes[j*108 + i]; // Add BN and input LLR, extract the sign bit // and add in GF(2) (xor) - pcRes ^= _mm512_movemask_epi8(_mm512_adds_epi8(ymm0,ymm1)); + pcRes ^= _mm512_movemask_epi8(_mm512_adds_epi8(zmm0,zmm1)); } // If no error pcRes should be 0 @@ -1727,12 +1729,12 @@ static inline uint64_t nrLDPC_cnProcPc_BG2(t_nrLDPC_lut* p_lut, t_nrLDPC_procBuf for (j=0; j<5; j++) { // BN offset is units of 9*384/32 = 108 - ymm0 = p_cnProcBuf [j*108 + i]; - ymm1 = p_cnProcBufRes[j*108 + i]; + zmm0 = p_cnProcBuf [j*108 + i]; + zmm1 = p_cnProcBufRes[j*108 + i]; // Add BN and input LLR, extract the sign bit // and add in GF(2) (xor) - pcRes ^= _mm512_movemask_epi8(_mm512_adds_epi8(ymm0,ymm1)); + pcRes ^= _mm512_movemask_epi8(_mm512_adds_epi8(zmm0,zmm1)); } // If no error pcRes should be 0 @@ -1775,12 +1777,12 @@ static inline uint64_t nrLDPC_cnProcPc_BG2(t_nrLDPC_lut* p_lut, t_nrLDPC_procBuf for (j=0; j<6; j++) { // BN offset is units of 3*384/32 = 36 - ymm0 = p_cnProcBuf [j*36 + i]; - ymm1 = p_cnProcBufRes[j*36 + i]; + zmm0 = p_cnProcBuf [j*36 + i]; + zmm1 = p_cnProcBufRes[j*36 + i]; // Add BN and input LLR, extract the sign bit // and add in GF(2) (xor) - pcRes ^= _mm512_movemask_epi8(_mm512_adds_epi8(ymm0,ymm1)); + pcRes ^= _mm512_movemask_epi8(_mm512_adds_epi8(zmm0,zmm1)); } // If no error pcRes should be 0 @@ -1794,12 +1796,12 @@ static inline uint64_t nrLDPC_cnProcPc_BG2(t_nrLDPC_lut* p_lut, t_nrLDPC_procBuf for (j=0; j<6; j++) { // BN offset is units of 3*384/32 = 36 - ymm0 = p_cnProcBuf [j*36 + i]; - ymm1 = p_cnProcBufRes[j*36 + i]; + zmm0 = p_cnProcBuf [j*36 + i]; + zmm1 = p_cnProcBufRes[j*36 + i]; // Add BN and input LLR, extract the sign bit // and add in GF(2) (xor) - pcRes ^= _mm512_movemask_epi8(_mm512_adds_epi8(ymm0,ymm1)); + pcRes ^= _mm512_movemask_epi8(_mm512_adds_epi8(zmm0,zmm1)); } // If no error pcRes should be 0 @@ -1842,12 +1844,12 @@ static inline uint64_t nrLDPC_cnProcPc_BG2(t_nrLDPC_lut* p_lut, t_nrLDPC_procBuf for (j=0; j<8; j++) { // BN offset is units of 2*384/32 = 24 - ymm0 = p_cnProcBuf [j*24 + i]; - ymm1 = p_cnProcBufRes[j*24 + i]; + zmm0 = p_cnProcBuf [j*24 + i]; + zmm1 = p_cnProcBufRes[j*24 + i]; // Add BN and input LLR, extract the sign bit // and add in GF(2) (xor) - pcRes ^= _mm512_movemask_epi8(_mm512_adds_epi8(ymm0,ymm1)); + pcRes ^= _mm512_movemask_epi8(_mm512_adds_epi8(zmm0,zmm1)); } // If no error pcRes should be 0 @@ -1861,12 +1863,12 @@ static inline uint64_t nrLDPC_cnProcPc_BG2(t_nrLDPC_lut* p_lut, t_nrLDPC_procBuf for (j=0; j<8; j++) { // BN offset is units of 2*384/32 = 24 - ymm0 = p_cnProcBuf [j*24 + i]; - ymm1 = p_cnProcBufRes[j*24 + i]; + zmm0 = p_cnProcBuf [j*24 + i]; + zmm1 = p_cnProcBufRes[j*24 + i]; // Add BN and input LLR, extract the sign bit // and add in GF(2) (xor) - pcRes ^= _mm512_movemask_epi8(_mm512_adds_epi8(ymm0,ymm1)); + pcRes ^= _mm512_movemask_epi8(_mm512_adds_epi8(zmm0,zmm1)); } // If no error pcRes should be 0 @@ -1909,12 +1911,12 @@ static inline uint64_t nrLDPC_cnProcPc_BG2(t_nrLDPC_lut* p_lut, t_nrLDPC_procBuf for (j=0; j<10; j++) { // BN offset is units of 2*384/32 = 24 - ymm0 = p_cnProcBuf [j*24 + i]; - ymm1 = p_cnProcBufRes[j*24 + i]; + zmm0 = p_cnProcBuf [j*24 + i]; + zmm1 = p_cnProcBufRes[j*24 + i]; // Add BN and input LLR, extract the sign bit // and add in GF(2) (xor) - pcRes ^= _mm512_movemask_epi8(_mm512_adds_epi8(ymm0,ymm1)); + pcRes ^= _mm512_movemask_epi8(_mm512_adds_epi8(zmm0,zmm1)); } // If no error pcRes should be 0 @@ -1928,12 +1930,12 @@ static inline uint64_t nrLDPC_cnProcPc_BG2(t_nrLDPC_lut* p_lut, t_nrLDPC_procBuf for (j=0; j<10; j++) { // BN offset is units of 2*384/32 = 24 - ymm0 = p_cnProcBuf [j*24 + i]; - ymm1 = p_cnProcBufRes[j*24 + i]; + zmm0 = p_cnProcBuf [j*24 + i]; + zmm1 = p_cnProcBufRes[j*24 + i]; // Add BN and input LLR, extract the sign bit // and add in GF(2) (xor) - pcRes ^= _mm512_movemask_epi8(_mm512_adds_epi8(ymm0,ymm1)); + pcRes ^= _mm512_movemask_epi8(_mm512_adds_epi8(zmm0,zmm1)); } // If no error pcRes should be 0 diff --git a/openair1/PHY/CODING/nrLDPC_decoder_full/nrLDPC_decoder.c b/openair1/PHY/CODING/nrLDPC_decoder_full/nrLDPC_decoder.c index 9ff57acf22..b8075ee528 100644 --- a/openair1/PHY/CODING/nrLDPC_decoder_full/nrLDPC_decoder.c +++ b/openair1/PHY/CODING/nrLDPC_decoder_full/nrLDPC_decoder.c @@ -29,17 +29,15 @@ */ #include -//#include +#include #include "nrLDPCdecoder_defs.h" #include "nrLDPC_types.h" #include "nrLDPC_init.h" #include "nrLDPC_mPass.h" #include "nrLDPC_cnProc.h" #include "nrLDPC_bnProc.h" - +#include //#include "include/immintrin.h" -#include "include/avx512fintrin.h" -#include "include/avx2intrin.h" #define NR_LDPC_ENABLE_PARITY_CHECK #define NR_LDPC_PROFILER_DETAIL