From a4c950774b3e11fd1b3d129c209a0d9e053e1a11 Mon Sep 17 00:00:00 2001 From: Raymond Knopp Date: Sun, 29 Dec 2024 09:49:00 +0000 Subject: [PATCH] feat(ldpc_encoder_optim8segmulti): Improvements for Arm Neoverse Use 128 bit SIMD in packing and unpacking segment bits in bytes Adapt compiler options for Neoverse. --- CMakeLists.txt | 16 +++++- .../ldpc_encoder_optim8segmulti.c | 56 ++++++++++++++++++- 2 files changed, 68 insertions(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index feb7e41a4f..491dcd7e0b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -108,6 +108,7 @@ add_list_string_option(CMAKE_BUILD_TYPE "RelWithDebInfo" "Choose the type of bui # -so to avoid AVX512 instructions generation by gcc if(EXISTS "/proc/cpuinfo" AND NOT CROSS_COMPILE) file(STRINGS "/proc/cpuinfo" CPUFLAGS REGEX flags LIMIT_COUNT 1) + file(STRINGS "/proc/cpuinfo" CPUPART REGEX "CPU part" LIMIT_COUNT 1) else() message(WARNING "did not find /proc/cpuinfo -- not setting any x86-specific compilation variables") endif() @@ -146,9 +147,20 @@ elseif(CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64") set(C_FLAGS_PROCESSOR "${C_FLAGS_PROCESSOR} -DSIMDE_X86_SSSE3_NATIVE") endif() elseif (CMAKE_SYSTEM_PROCESSOR STREQUAL "armv7l") - set(C_FLAGS_PROCESSOR "${C_FLAGS_PROCESSOR} -gdwarf-2 -mfloat-abi=hard -mfpu=neon -lgcc -lrt") + set(C_FLAGS_PROCESSOR "${C_FLAGS_PROCESSOR} -gdwarf-2 -mfloat-abi=hard -mfpu=neon -lgcc -lrt") elseif (CMAKE_SYSTEM_PROCESSOR STREQUAL "aarch64") - set(C_FLAGS_PROCESSOR "${C_FLAGS_PROCESSOR} -gdwarf-2 -lgcc -lrt") +# Neoverse CPU part codes available at https://github.com/util-linux/util-linux/blob/master/sys-utils/lscpu-arm.c + if (CPUPART MATCHES "0xd40") # Neoverse-V1 + set(C_FLAGS_PROCESSOR "${C_FLAGS_PROCESSOR} -gdwarf-2 -mcpu=neoverse-v1 -lgcc -lrt") + elseif (CPUPART MATCHES "0xd4f") # Neoverse-V2 + set(C_FLAGS_PROCESSOR "${C_FLAGS_PROCESSOR} -gdwarf-2 -mcpu=neoverse-v2 -ftree-vectorize -lgcc -lrt") + elseif (CPUPART MATCHES "0xd0c") # Neoverse-N1 + set(C_FLAGS_PROCESSOR "${C_FLAGS_PROCESSOR} -gdwarf-2 -mcpu=neoverse-n1 -lgcc -lrt") + elseif (CPUPART MATCHES "0xd49") # Neoverse-N2 + set(C_FLAGS_PROCESSOR "${C_FLAGS_PROCESSOR} -gdwarf-2 -mcpu=neoverse-n2 -ftree-vectorize -lgcc -lrt") + else () + set(C_FLAGS_PROCESSOR "${C_FLAGS_PROCESSOR} -gdwarf-2 -mcpu=native -lgcc -lrt") + endif() else() message(FATAL_ERROR "compile for CPU architecture ${CPUARCH}, CMAKE_SYSTEM_PROCESSOR ${CMAKE_SYSTEM_PROCESSOR}") endif() diff --git a/openair1/PHY/CODING/nrLDPC_encoder/ldpc_encoder_optim8segmulti.c b/openair1/PHY/CODING/nrLDPC_encoder/ldpc_encoder_optim8segmulti.c index 5e327df957..bd25ecf646 100644 --- a/openair1/PHY/CODING/nrLDPC_encoder/ldpc_encoder_optim8segmulti.c +++ b/openair1/PHY/CODING/nrLDPC_encoder/ldpc_encoder_optim8segmulti.c @@ -65,7 +65,22 @@ int LDPCencoder(uint8_t **input, uint8_t **output, encoder_implemparams_t *impp) macro_segment_end = (impp->n_segments > 8*(impp->macro_num+1)) ? 8*(impp->macro_num+1) : impp->n_segments; ///printf("macro_segment: %d\n", macro_segment); ///printf("macro_segment_end: %d\n", macro_segment_end ); +#ifdef __aarch64__ + simde__m128i shufmask = simde_mm_set_epi64x(0x0101010101010101, 0x0000000000000000); + simde__m128i andmask = simde_mm_set1_epi64x(0x0102040810204080); // every 8 bits -> 8 bytes, pattern repeats. + simde__m128i zero128 = simde_mm_setzero_si128(); + simde__m128i masks[8]; + register simde__m128i c128; + masks[0] = simde_mm_set1_epi8(0x1); + masks[1] = simde_mm_set1_epi8(0x2); + masks[2] = simde_mm_set1_epi8(0x4); + masks[3] = simde_mm_set1_epi8(0x8); + masks[4] = simde_mm_set1_epi8(0x10); + masks[5] = simde_mm_set1_epi8(0x20); + masks[6] = simde_mm_set1_epi8(0x40); + masks[7] = simde_mm_set1_epi8(0x80); +#else simde__m256i shufmask = simde_mm256_set_epi64x(0x0303030303030303, 0x0202020202020202,0x0101010101010101, 0x0000000000000000); simde__m256i andmask = simde_mm256_set1_epi64x(0x0102040810204080); // every 8 bits -> 8 bytes, pattern repeats. simde__m256i zero256 = simde_mm256_setzero_si256(); @@ -79,7 +94,7 @@ int LDPCencoder(uint8_t **input, uint8_t **output, encoder_implemparams_t *impp) masks[5] = simde_mm256_set1_epi8(0x20); masks[6] = simde_mm256_set1_epi8(0x40); masks[7] = simde_mm256_set1_epi8(0x80); - +#endif //determine number of bits in codeword @@ -120,6 +135,7 @@ int LDPCencoder(uint8_t **input, uint8_t **output, encoder_implemparams_t *impp) memset(dd,0,sizeof(dd)); if(impp->tinput != NULL) start_meas(impp->tinput); + //interleave up to 8 transport-block segements at a time #if 0 for (i=0; i>4; i++) { + c128 = simde_mm_and_si128(simde_mm_cmpeq_epi8(simde_mm_andnot_si128(simde_mm_shuffle_epi8(simde_mm_set1_epi16(((uint16_t*)input[macro_segment])[i]), shufmask),andmask),zero128),masks[0]); + //for (j=1; j>4)<<4;i>(i&7)))>>(7-(i&7)); + //printf("c(%d,%d)=%d\n",j,i,temp); + cc[i] |= (temp << (j-macro_segment)); + } + } #else for (int i=0; i>5; i++) { c256 = simde_mm256_and_si256(simde_mm256_cmpeq_epi8(simde_mm256_andnot_si256(simde_mm256_shuffle_epi8(simde_mm256_set1_epi32(((uint32_t*)input[macro_segment])[i]), shufmask),andmask),zero256),masks[0]); @@ -208,7 +243,24 @@ int LDPCencoder(uint8_t **input, uint8_t **output, encoder_implemparams_t *impp) //for (j=0;j>4; + uint32_t l2 = ((nrows-no_punctured_columns) * Zc-removed_bit)>>4; + simde__m128i *c128p = (simde__m128i *)&cc[2*Zc]; + simde__m128i *d128p = (simde__m128i *)&dd[0]; + // if (((block_length-(2*Zc))&31)>0) l1++; + + for (int i=0;i