diff --git a/CMakeLists.txt b/CMakeLists.txt index 9883366ba6..50fd45fc51 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -166,6 +166,8 @@ elseif (CMAKE_SYSTEM_PROCESSOR STREQUAL "aarch64") 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") + elseif (CPUPART MATCHES "0xd03") # Cortex-A53 + set(C_FLAGS_PROCESSOR "${C_FLAGS_PROCESSOR} -gdwarf-2 -mcpu=cortex-a53 -lgcc -lrt") else () set(C_FLAGS_PROCESSOR "${C_FLAGS_PROCESSOR} -gdwarf-2 -mcpu=native -lgcc -lrt") endif() @@ -174,7 +176,12 @@ else() endif() if (NOT CROSS_COMPILE) - set(C_FLAGS_PROCESSOR "${C_FLAGS_PROCESSOR} -march=native") + if (CPUPART MATCHES "0xd03") + # Cortex-A53 does not support ARMv8.2-A extensions + set(C_FLAGS_PROCESSOR "${C_FLAGS_PROCESSOR} -march=armv8-a+simd") + else() + set(C_FLAGS_PROCESSOR "${C_FLAGS_PROCESSOR} -march=native") + endif() else () set(C_FLAGS_PROCESSOR "${C_FLAGS_PROCESSOR} -march=armv8.2-a") endif() diff --git a/cmake_targets/tools/build_helper b/cmake_targets/tools/build_helper index 3443d06c43..1b025e65a1 100755 --- a/cmake_targets/tools/build_helper +++ b/cmake_targets/tools/build_helper @@ -107,6 +107,7 @@ check_supported_distribution() { "ubuntu22.04") return 0 ;; "ubuntu20.04") return 0 ;; "debian11") return 0 ;; + "debian12") return 0 ;; "fedora41") return 0 ;; "fedora40") return 0 ;; "rhel8.2") return 0 ;; @@ -453,7 +454,7 @@ check_install_additional_tools (){ local optional_packages="" if [[ "$OS_BASEDISTRO" == "debian" ]]; then case "$(get_distribution_release)" in - "ubuntu20.04" | "ubuntu22.04" | "debian11" ) + "ubuntu20.04" | "ubuntu22.04" | "debian11" | "debian12" ) optional_packages="python3 python3-pip python3-dev python3-scipy python3-matplotlib python3-pyroute2 universal-ctags" ;; esac @@ -496,7 +497,7 @@ check_install_oai_software() { if [[ "$OS_BASEDISTRO" == "debian" ]]; then $SUDO apt install -y software-properties-common case "$(get_distribution_release)" in - "debian11") + "debian11" | "debian12" ) specific_packages="libz-dev" ;; esac diff --git a/openair1/PHY/MODULATION/nr_modulation.c b/openair1/PHY/MODULATION/nr_modulation.c index eb4dc50bc9..562c43895b 100644 --- a/openair1/PHY/MODULATION/nr_modulation.c +++ b/openair1/PHY/MODULATION/nr_modulation.c @@ -760,6 +760,8 @@ static inline __attribute__((always_inline)) int16x8_t cmac0_prec128(int16x8_t x // int16x8_t xr = vuzp1q_s16(x, x); // even lanes int16x8_t xi = vuzp2q_s16(x, x); // odd lanes +#ifdef __ARM_FEATURE_QRDMX + // ARMv8.1-A: Use RDM instructions // real = ar*br - ai*bi (Q15 scaling via high-half doubling muls) int16x8_t real = vqdmulhq_s16(xr, wr); // ≈ round((2*xr*wr)/2^16) real = vqrdmlshq_s16(real, xi, wi); // real -= round((2*xi*wi)/2^16) @@ -767,7 +769,21 @@ static inline __attribute__((always_inline)) int16x8_t cmac0_prec128(int16x8_t x // imag = ar*bi + ai*br int16x8_t imag = vqdmulhq_s16(xr, wi); imag = vqrdmlahq_s16(imag, xi, wr); // imag += round((2*xi*wr)/2^16) - // +#else + // ARMv8.0-A fallback: Use standard 32-bit multiply + int32x4_t real_lo = vmull_s16(vget_low_s16(xr), vget_low_s16(wr)); + int32x4_t real_hi = vmull_s16(vget_high_s16(xr), vget_high_s16(wr)); + real_lo = vmlsl_s16(real_lo, vget_low_s16(xi), vget_low_s16(wi)); + real_hi = vmlsl_s16(real_hi, vget_high_s16(xi), vget_high_s16(wi)); + + int32x4_t imag_lo = vmull_s16(vget_low_s16(xr), vget_low_s16(wi)); + int32x4_t imag_hi = vmull_s16(vget_high_s16(xr), vget_high_s16(wi)); + imag_lo = vmlal_s16(imag_lo, vget_low_s16(xi), vget_low_s16(wr)); + imag_hi = vmlal_s16(imag_hi, vget_high_s16(xi), vget_high_s16(wr)); + + int16x8_t real = vcombine_s16(vqrshrn_n_s32(real_lo, 15), vqrshrn_n_s32(real_hi, 15)); + int16x8_t imag = vcombine_s16(vqrshrn_n_s32(imag_lo, 15), vqrshrn_n_s32(imag_hi, 15)); +#endif // Re-interleave [real, imag] int16x8x2_t produ = vzipq_s16(real, imag); return produ.val[0]; diff --git a/openair1/PHY/TOOLS/tools_defs.h b/openair1/PHY/TOOLS/tools_defs.h index 36fc496545..40f6ca46f6 100644 --- a/openair1/PHY/TOOLS/tools_defs.h +++ b/openair1/PHY/TOOLS/tools_defs.h @@ -816,7 +816,8 @@ static inline void rotate_cpx_vector(const c16_t *const x, const c16_t *const al // Split interleaved -> separate real/imag int16x8_t br = vuzp1q_s16(x_128[i], x_128[i]); int16x8_t bi = vuzp2q_s16(x_128[i], x_128[i]); - +#ifdef __ARM_FEATURE_QRDMX + // ARMv8.1-A: Use RDM instructions (rounding doubling multiply) // Start with the two “diagonal” products using high-half, doubling, sat: // x = round( (2*ar*br) / 2^16 ), y = round( (2*ar*bi) / 2^16 ) int16x8_t real = vqdmulhq_s16(ar, br); @@ -827,7 +828,21 @@ static inline void rotate_cpx_vector(const c16_t *const x, const c16_t *const al // imag += round( (2*ai*br) / 2^16 ) imag = vqrdmlahq_s16(imag, ai, br); +#else + // ARMv8.0-A fallback: Use standard 32-bit multiply + int32x4_t real_lo = vmull_s16(vget_low_s16(ar), vget_low_s16(br)); + int32x4_t real_hi = vmull_s16(vget_high_s16(ar), vget_high_s16(br)); + real_lo = vmlsl_s16(real_lo, vget_low_s16(ai), vget_low_s16(bi)); + real_hi = vmlsl_s16(real_hi, vget_high_s16(ai), vget_high_s16(bi)); + int32x4_t imag_lo = vmull_s16(vget_low_s16(ar), vget_low_s16(bi)); + int32x4_t imag_hi = vmull_s16(vget_high_s16(ar), vget_high_s16(bi)); + imag_lo = vmlal_s16(imag_lo, vget_low_s16(ai), vget_low_s16(br)); + imag_hi = vmlal_s16(imag_hi, vget_high_s16(ai), vget_high_s16(br)); + + int16x8_t real = vcombine_s16(vqrshrn_n_s32(real_lo, 15), vqrshrn_n_s32(real_hi, 15)); + int16x8_t imag = vcombine_s16(vqrshrn_n_s32(imag_lo, 15), vqrshrn_n_s32(imag_hi, 15)); +#endif // Re-interleave [real, imag] int16x8x2_t z = vzipq_s16(real, imag);