diff --git a/doc/services/dsp/index.rst b/doc/services/dsp/index.rst index f37aefb4f6..38d4ee32d6 100644 --- a/doc/services/dsp/index.rst +++ b/doc/services/dsp/index.rst @@ -14,7 +14,7 @@ optimized. The status of the various architectures can be found below: ============ ============= Architecture Status ============ ============= -ARC Unoptimized +ARC Optimized ARM Optimized ARM64 Optimized MIPS Unoptimized @@ -46,11 +46,13 @@ Optimizing for your architecture If your architecture is showing as ``Unoptimized``, it's possible to add a new zDSP backend to better support it. To do that, a new Kconfig option should be -added to `subsys/dsp/Kconfig`_ along with the required dependencies and the +added to :file:`subsys/dsp/Kconfig` along with the required dependencies and the ``default`` set for ``DSP_BACKEND`` Kconfig choice. Next, the implementation should be added at ``subsys/dsp//`` and -linked in at `subsys/dsp/CMakeLists.txt`_. +linked in at :file:`subsys/dsp/CMakeLists.txt`. To add architecture-specific attributes, +its corresponding Kconfig option should be added to :file:`subsys/dsp/Kconfig` and use +them to update ``DSP_DATA`` and ``DSP_STATIC_DATA`` in :file:`include/zephyr/dsp/dsp.h`. API Reference ************* @@ -59,3 +61,4 @@ API Reference .. _subsys/dsp/Kconfig: https://github.com/zephyrproject-rtos/zephyr/blob/main/subsys/dsp/Kconfig .. _subsys/dsp/CMakeLists.txt: https://github.com/zephyrproject-rtos/zephyr/blob/main/subsys/dsp/CMakeLists.txt +.. _include/zephyr/dsp/dsp.h: https://github.com/zephyrproject-rtos/zephyr/blob/main/include/zephyr/dsp/dsp.h diff --git a/include/zephyr/dsp/dsp.h b/include/zephyr/dsp/dsp.h index 9c720962c0..d475c68a00 100644 --- a/include/zephyr/dsp/dsp.h +++ b/include/zephyr/dsp/dsp.h @@ -17,9 +17,17 @@ #define DSP_FUNC_SCOPE #endif +#ifdef CONFIG_DSP_BACKEND_HAS_AGU +#define DSP_DATA __agu +#else #define DSP_DATA +#endif +#ifdef CONFIG_DSP_BACKEND_HAS_XDATA_SECTION +#define DSP_STATIC_DATA DSP_DATA __attribute__((section(".Xdata"))) +#else #define DSP_STATIC_DATA DSP_DATA +#endif /** * @brief DSP Interface diff --git a/soc/arc/snps_nsim/CMakeLists.txt b/soc/arc/snps_nsim/CMakeLists.txt index 2a103f3dce..103cb7463c 100644 --- a/soc/arc/snps_nsim/CMakeLists.txt +++ b/soc/arc/snps_nsim/CMakeLists.txt @@ -28,6 +28,8 @@ else() -Xshift_assist -Xfpus_div -Xfpu_mac -Xfpuda -Xfpus_mpy_slow -Xfpus_div_slow -Xbitstream -Xtimer0 -Xtimer1) + zephyr_ld_option_ifdef(CONFIG_SOC_NSIM_EM11D -Hlib=em9d_nrg_fpusp -Hdsplib) + if(CONFIG_SOC_NSIM_EM11D) set_property(GLOBAL PROPERTY z_arc_dsp_options -Xxy -Xagu_large -Hfxapi -Xdsp2 -Xdsp_accshift=full -Xdsp_divsqrt=radix2 -Xdsp_complex -Xdsp_itu diff --git a/subsys/dsp/CMakeLists.txt b/subsys/dsp/CMakeLists.txt index 8a07484fec..2908c03a36 100644 --- a/subsys/dsp/CMakeLists.txt +++ b/subsys/dsp/CMakeLists.txt @@ -2,3 +2,4 @@ # SPDX-License-Identifier: Apache-2.0 add_subdirectory_ifdef(CONFIG_DSP_BACKEND_CMSIS cmsis) +add_subdirectory_ifdef(CONFIG_DSP_BACKEND_ARCMWDT arcmwdt) diff --git a/subsys/dsp/Kconfig b/subsys/dsp/Kconfig index d4e203c526..ac101be9fb 100644 --- a/subsys/dsp/Kconfig +++ b/subsys/dsp/Kconfig @@ -13,9 +13,16 @@ if DSP config DSP_BACKEND_HAS_STATIC bool +config DSP_BACKEND_HAS_AGU + bool + +config DSP_BACKEND_HAS_XDATA_SECTION + bool + choice DSP_BACKEND prompt "DSP library backend selection" default DSP_BACKEND_CMSIS if CMSIS_DSP + default DSP_BACKEND_ARCMWDT if ARC && "$(ZEPHYR_TOOLCHAIN_VARIANT)" = "arcmwdt" default DSP_BACKEND_CUSTOM config DSP_BACKEND_CMSIS @@ -32,6 +39,17 @@ config DSP_BACKEND_CUSTOM Rely on the application to provide a custom DSP backend. The implementation should be added to the 'zdsp' build target by the application or one of its modules. +config DSP_BACKEND_ARCMWDT + bool "Use the mwdt library as the math backend" + depends on ARCMWDT_LIBC + depends on CMSIS_DSP + select DSP_BACKEND_HAS_STATIC + select DSP_BACKEND_HAS_AGU + select DSP_BACKEND_HAS_XDATA_SECTION + help + Implement the various zephyr DSP functions using the MWDT-DSP library. This feature + requires the MetaWare toolchain and CMSIS module to be selected. + endchoice endif # DSP diff --git a/subsys/dsp/arcmwdt/CMakeLists.txt b/subsys/dsp/arcmwdt/CMakeLists.txt new file mode 100644 index 0000000000..1996f407ac --- /dev/null +++ b/subsys/dsp/arcmwdt/CMakeLists.txt @@ -0,0 +1,8 @@ +# Copyright (c) 2022 Synopsys +# SPDX-License-Identifier: Apache-2.0 + +zephyr_include_directories(public) + +zephyr_include_directories_ifdef(CONFIG_DSP_BACKEND_ARCMWDT + ${ARCMWDT_TOOLCHAIN_PATH}/MetaWare/arc/lib/src/dsp/include/ +) diff --git a/subsys/dsp/arcmwdt/public/zdsp_backend.h b/subsys/dsp/arcmwdt/public/zdsp_backend.h new file mode 100644 index 0000000000..1a6870819c --- /dev/null +++ b/subsys/dsp/arcmwdt/public/zdsp_backend.h @@ -0,0 +1,293 @@ +/* + * Copyright (c) 2022 Synopsys + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef SUBSYS_MATH_ARC_BACKEND_PUBLIC_ZDSP_BACKEND_DSP_H_ +#define SUBSYS_MATH_ARC_BACKEND_PUBLIC_ZDSP_BACKEND_DSP_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/* This include MUST be done before arm_math.h so we can let the arch specific + * logic set up the right #define values for arm_math.h + */ +#include + +#include +#include "dsplib.h" + +static inline void zdsp_mult_q7(const DSP_DATA q7_t *src_a, const DSP_DATA q7_t *src_b, + DSP_DATA q7_t *dst, uint32_t block_size) +{ + dsp_mult_q7(src_a, src_b, dst, block_size); +} +static inline void zdsp_mult_q15(const DSP_DATA q15_t *src_a, const DSP_DATA q15_t *src_b, + DSP_DATA q15_t *dst, uint32_t block_size) +{ + dsp_mult_q15(src_a, src_b, dst, block_size); +} +static inline void zdsp_mult_q31(const DSP_DATA q31_t *src_a, const DSP_DATA q31_t *src_b, + DSP_DATA q31_t *dst, uint32_t block_size) +{ + dsp_mult_q31(src_a, src_b, dst, block_size); +} +static inline void zdsp_mult_f32(const DSP_DATA float32_t *src_a, const DSP_DATA float32_t *src_b, + DSP_DATA float32_t *dst, uint32_t block_size) +{ + dsp_mult_f32(src_a, src_b, dst, block_size); +} + +static inline void zdsp_add_q7(const DSP_DATA q7_t *src_a, const DSP_DATA q7_t *src_b, + DSP_DATA q7_t *dst, uint32_t block_size) +{ + dsp_add_q7(src_a, src_b, dst, block_size); +} +static inline void zdsp_add_q15(const DSP_DATA q15_t *src_a, const DSP_DATA q15_t *src_b, + DSP_DATA q15_t *dst, uint32_t block_size) +{ + dsp_add_q15(src_a, src_b, dst, block_size); +} +static inline void zdsp_add_q31(const DSP_DATA q31_t *src_a, const DSP_DATA q31_t *src_b, + DSP_DATA q31_t *dst, uint32_t block_size) +{ + dsp_add_q31(src_a, src_b, dst, block_size); +} +static inline void zdsp_add_f32(const DSP_DATA float32_t *src_a, const DSP_DATA float32_t *src_b, + DSP_DATA float32_t *dst, uint32_t block_size) +{ + dsp_add_f32(src_a, src_b, dst, block_size); +} + +static inline void zdsp_sub_q7(const DSP_DATA q7_t *src_a, const DSP_DATA q7_t *src_b, + DSP_DATA q7_t *dst, uint32_t block_size) +{ + dsp_sub_q7(src_a, src_b, dst, block_size); +} +static inline void zdsp_sub_q15(const DSP_DATA q15_t *src_a, const DSP_DATA q15_t *src_b, + DSP_DATA q15_t *dst, uint32_t block_size) +{ + dsp_sub_q15(src_a, src_b, dst, block_size); +} +static inline void zdsp_sub_q31(const DSP_DATA q31_t *src_a, const DSP_DATA q31_t *src_b, + DSP_DATA q31_t *dst, uint32_t block_size) +{ + dsp_sub_q31(src_a, src_b, dst, block_size); +} +static inline void zdsp_sub_f32(const DSP_DATA float32_t *src_a, const DSP_DATA float32_t *src_b, + DSP_DATA float32_t *dst, uint32_t block_size) +{ + dsp_sub_f32(src_a, src_b, dst, block_size); +} + +static inline void zdsp_scale_q7(const DSP_DATA q7_t *src, q7_t scale_fract, int8_t shift, + DSP_DATA q7_t *dst, uint32_t block_size) +{ + dsp_scale_q7(src, scale_fract, shift, dst, block_size); +} +static inline void zdsp_scale_q15(const DSP_DATA q15_t *src, q15_t scale_fract, int8_t shift, + DSP_DATA q15_t *dst, uint32_t block_size) +{ + dsp_scale_q15(src, scale_fract, shift, dst, block_size); +} +static inline void zdsp_scale_q31(const DSP_DATA q31_t *src, q31_t scale_fract, int8_t shift, + DSP_DATA q31_t *dst, uint32_t block_size) +{ + dsp_scale_q31(src, scale_fract, shift, dst, block_size); +} + +static inline void zdsp_scale_f32(const DSP_DATA float32_t *src, float32_t scale, + DSP_DATA float32_t *dst, uint32_t block_size) +{ + dsp_scale_f32(src, scale, dst, block_size); +} + +static inline void zdsp_abs_q7(const DSP_DATA q7_t *src, DSP_DATA q7_t *dst, uint32_t block_size) +{ + dsp_abs_q7(src, dst, block_size); +} +static inline void zdsp_abs_q15(const DSP_DATA q15_t *src, DSP_DATA q15_t *dst, uint32_t block_size) +{ + dsp_abs_q15(src, dst, block_size); +} +static inline void zdsp_abs_q31(const DSP_DATA q31_t *src, DSP_DATA q31_t *dst, uint32_t block_size) +{ + dsp_abs_q31(src, dst, block_size); +} +static inline void zdsp_abs_f32(const DSP_DATA float32_t *src, DSP_DATA float32_t *dst, + uint32_t block_size) +{ + dsp_abs_f32(src, dst, block_size); +} + +static inline void zdsp_negate_q7(const DSP_DATA q7_t *src, DSP_DATA q7_t *dst, uint32_t block_size) +{ + dsp_negate_q7(src, dst, block_size); +} +static inline void zdsp_negate_q15(const DSP_DATA q15_t *src, DSP_DATA q15_t *dst, + uint32_t block_size) +{ + dsp_negate_q15(src, dst, block_size); +} +static inline void zdsp_negate_q31(const DSP_DATA q31_t *src, DSP_DATA q31_t *dst, + uint32_t block_size) +{ + dsp_negate_q31(src, dst, block_size); +} +static inline void zdsp_negate_f32(const DSP_DATA float32_t *src, DSP_DATA float32_t *dst, + uint32_t block_size) +{ + dsp_negate_f32(src, dst, block_size); +} + +static inline void zdsp_dot_prod_q7(const DSP_DATA q7_t *src_a, const DSP_DATA q7_t *src_b, + uint32_t block_size, DSP_DATA q31_t *dst) +{ + dsp_dot_prod_q7(src_a, src_b, block_size, dst); +} +static inline void zdsp_dot_prod_q15(const DSP_DATA q15_t *src_a, const DSP_DATA q15_t *src_b, + uint32_t block_size, DSP_DATA q63_t *dst) +{ + dsp_dot_prod_q15(src_a, src_b, block_size, dst); +} +static inline void zdsp_dot_prod_q31(const DSP_DATA q31_t *src_a, const DSP_DATA q31_t *src_b, + uint32_t block_size, DSP_DATA q63_t *dst) +{ + dsp_dot_prod_q31(src_a, src_b, block_size, dst); +} +static inline void zdsp_dot_prod_f32(const DSP_DATA float32_t *src_a, + const DSP_DATA float32_t *src_b, uint32_t block_size, + DSP_DATA float32_t *dst) +{ + dsp_dot_prod_f32(src_a, src_b, block_size, dst); +} + +static inline void zdsp_shift_q7(const DSP_DATA q7_t *src, int8_t shift_bits, DSP_DATA q7_t *dst, + uint32_t block_size) +{ + dsp_shift_q7(src, shift_bits, dst, block_size); +} +static inline void zdsp_shift_q15(const DSP_DATA q15_t *src, int8_t shift_bits, DSP_DATA q15_t *dst, + uint32_t block_size) +{ + dsp_shift_q15(src, shift_bits, dst, block_size); +} +static inline void zdsp_shift_q31(const DSP_DATA q31_t *src, int8_t shift_bits, DSP_DATA q31_t *dst, + uint32_t block_size) +{ + dsp_shift_q31(src, shift_bits, dst, block_size); +} + +static inline void zdsp_offset_q7(const DSP_DATA q7_t *src, q7_t offset, DSP_DATA q7_t *dst, + uint32_t block_size) +{ + dsp_offset_q7(src, offset, dst, block_size); +} +static inline void zdsp_offset_q15(const DSP_DATA q15_t *src, q15_t offset, DSP_DATA q15_t *dst, + uint32_t block_size) +{ + dsp_offset_q15(src, offset, dst, block_size); +} +static inline void zdsp_offset_q31(const DSP_DATA q31_t *src, q31_t offset, DSP_DATA q31_t *dst, + uint32_t block_size) +{ + dsp_offset_q31(src, offset, dst, block_size); +} +static inline void zdsp_offset_f32(const DSP_DATA float32_t *src, float32_t offset, + DSP_DATA float32_t *dst, uint32_t block_size) +{ + dsp_offset_f32(src, offset, dst, block_size); +} + +static inline void zdsp_clip_q7(const DSP_DATA q7_t *src, DSP_DATA q7_t *dst, q7_t low, q7_t high, + uint32_t num_samples) +{ + arm_clip_q7(src, dst, low, high, num_samples); +} +static inline void zdsp_clip_q15(const DSP_DATA q15_t *src, DSP_DATA q15_t *dst, q15_t low, + q15_t high, uint32_t num_samples) +{ + arm_clip_q15(src, dst, low, high, num_samples); +} +static inline void zdsp_clip_q31(const DSP_DATA q31_t *src, DSP_DATA q31_t *dst, q31_t low, + q31_t high, uint32_t num_samples) +{ + arm_clip_q31(src, dst, low, high, num_samples); +} +static inline void zdsp_clip_f32(const DSP_DATA float32_t *src, DSP_DATA float32_t *dst, + float32_t low, float32_t high, uint32_t num_samples) +{ + arm_clip_f32(src, dst, low, high, num_samples); +} + +static inline void zdsp_and_u8(const DSP_DATA uint8_t *src_a, const DSP_DATA uint8_t *src_b, + DSP_DATA uint8_t *dst, uint32_t block_size) +{ + arm_and_u8(src_a, src_b, dst, block_size); +} +static inline void zdsp_and_u16(const DSP_DATA uint16_t *src_a, const DSP_DATA uint16_t *src_b, + DSP_DATA uint16_t *dst, uint32_t block_size) +{ + arm_and_u16(src_a, src_b, dst, block_size); +} +static inline void zdsp_and_u32(const DSP_DATA uint32_t *src_a, const DSP_DATA uint32_t *src_b, + DSP_DATA uint32_t *dst, uint32_t block_size) +{ + arm_and_u32(src_a, src_b, dst, block_size); +} + +static inline void zdsp_or_u8(const DSP_DATA uint8_t *src_a, const DSP_DATA uint8_t *src_b, + DSP_DATA uint8_t *dst, uint32_t block_size) +{ + arm_or_u8(src_a, src_b, dst, block_size); +} +static inline void zdsp_or_u16(const DSP_DATA uint16_t *src_a, const DSP_DATA uint16_t *src_b, + DSP_DATA uint16_t *dst, uint32_t block_size) +{ + arm_or_u16(src_a, src_b, dst, block_size); +} +static inline void zdsp_or_u32(const DSP_DATA uint32_t *src_a, const DSP_DATA uint32_t *src_b, + DSP_DATA uint32_t *dst, uint32_t block_size) +{ + arm_or_u32(src_a, src_b, dst, block_size); +} + +static inline void zdsp_xor_u8(const DSP_DATA uint8_t *src_a, const DSP_DATA uint8_t *src_b, + DSP_DATA uint8_t *dst, uint32_t block_size) +{ + arm_xor_u8(src_a, src_b, dst, block_size); +} +static inline void zdsp_xor_u16(const DSP_DATA uint16_t *src_a, const DSP_DATA uint16_t *src_b, + DSP_DATA uint16_t *dst, uint32_t block_size) +{ + arm_xor_u16(src_a, src_b, dst, block_size); +} +static inline void zdsp_xor_u32(const DSP_DATA uint32_t *src_a, const DSP_DATA uint32_t *src_b, + DSP_DATA uint32_t *dst, uint32_t block_size) +{ + arm_xor_u32(src_a, src_b, dst, block_size); +} + +static inline void zdsp_not_u8(const DSP_DATA uint8_t *src, DSP_DATA uint8_t *dst, + uint32_t block_size) +{ + arm_not_u8(src, dst, block_size); +} +static inline void zdsp_not_u16(const DSP_DATA uint16_t *src, DSP_DATA uint16_t *dst, + uint32_t block_size) +{ + arm_not_u16(src, dst, block_size); +} +static inline void zdsp_not_u32(const DSP_DATA uint32_t *src, DSP_DATA uint32_t *dst, + uint32_t block_size) +{ + arm_not_u32(src, dst, block_size); +} + +#ifdef __cplusplus +} +#endif + +#endif /* SUBSYS_MATH_ARC_BACKEND_PUBLIC_ZDSP_BACKEND_DSP_H_ */ diff --git a/tests/subsys/dsp/basicmath/CMakeLists.txt b/tests/subsys/dsp/basicmath/CMakeLists.txt index 22ec493cdf..15512830bb 100644 --- a/tests/subsys/dsp/basicmath/CMakeLists.txt +++ b/tests/subsys/dsp/basicmath/CMakeLists.txt @@ -14,3 +14,8 @@ target_sources(app PRIVATE target_sources_ifdef(CONFIG_FP16 app PRIVATE src/f16.c) target_include_directories(app PRIVATE ${ZEPHYR_BASE}/tests/lib/cmsis_dsp) + +if(COMPILER STREQUAL arcmwdt) + get_property(Z_ARC_DSP_OPTIONS GLOBAL PROPERTY z_arc_dsp_options) + target_compile_options(app PRIVATE ${Z_ARC_DSP_OPTIONS}) +endif() diff --git a/tests/subsys/dsp/basicmath/prj_arc.conf b/tests/subsys/dsp/basicmath/prj_arc.conf new file mode 100644 index 0000000000..c84bec1f3d --- /dev/null +++ b/tests/subsys/dsp/basicmath/prj_arc.conf @@ -0,0 +1,8 @@ +CONFIG_ZTEST=y +CONFIG_ZTEST_NEW_API=y +CONFIG_ARCMWDT_LIBC=y +CONFIG_CPLUSPLUS=y +CONFIG_DSP=y +CONFIG_CMSIS_DSP=y +CONFIG_CMSIS_DSP_BASICMATH=y +CONFIG_DSP_BACKEND_ARCMWDT=y diff --git a/tests/subsys/dsp/basicmath/testcase.yaml b/tests/subsys/dsp/basicmath/testcase.yaml index b0cd202d3f..a31b4ffe68 100644 --- a/tests/subsys/dsp/basicmath/testcase.yaml +++ b/tests/subsys/dsp/basicmath/testcase.yaml @@ -19,3 +19,8 @@ tests: - CONFIG_FPU=y min_flash: 128 min_ram: 64 + zdsp.basicmath.arcmwdt: + filter: CONFIG_ISA_ARCV2 + toolchain_allow: arcmwdt + platform_allow: nsim_em11d + extra_args: CONF_FILE=prj_arc.conf