math: Introduce a DSP basicmath subsystem with a cmsis backend
Introduce an API mirroring the CMSIS-DSP's basicmath. If CMSIS_DSP is enabled, then it will by default be used as a backend. Developers may opt into a custom backend by setting CONFIG_DSP_BACKEND_CMSIS=n. If done, the application must provide `zdsp_backend/dsp.h` and optionally implement the functions in its own .c files. Signed-off-by: Yuval Peress <peress@google.com>
This commit is contained in:
parent
0433965982
commit
b38445eaa0
20 changed files with 1637 additions and 3 deletions
8
subsys/dsp/CMakeLists.txt
Normal file
8
subsys/dsp/CMakeLists.txt
Normal file
|
@ -0,0 +1,8 @@
|
|||
# Copyright (c) 2022 Google LLC
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
zephyr_library_named(zdsp)
|
||||
|
||||
add_subdirectory_ifdef(CONFIG_DSP_BACKEND_CMSIS cmsis)
|
||||
|
||||
zephyr_link_libraries(zdsp)
|
26
subsys/dsp/Kconfig
Normal file
26
subsys/dsp/Kconfig
Normal file
|
@ -0,0 +1,26 @@
|
|||
# Copyright (c) 2022 Google LLC
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
config DSP_BACKEND_HAS_STATIC
|
||||
bool
|
||||
|
||||
choice DSP_BACKEND
|
||||
prompt "DSP library backend selection"
|
||||
default DSP_BACKEND_CMSIS if CMSIS_DSP
|
||||
default DSP_BACKEND_CUSTOM
|
||||
|
||||
config DSP_BACKEND_CMSIS
|
||||
bool "Use the CMSIS-DSP library as the math backend"
|
||||
depends on CMSIS_DSP
|
||||
select DSP_BACKEND_HAS_STATIC
|
||||
help
|
||||
Implement the various zephyr DSP functions using the CMSIS-DSP library. This feature
|
||||
requires the CMSIS module to be selected.
|
||||
|
||||
config DSP_BACKEND_CUSTOM
|
||||
bool "Do not use any Zephyr backends for DSP"
|
||||
help
|
||||
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.
|
||||
|
||||
endchoice
|
4
subsys/dsp/cmsis/CMakeLists.txt
Normal file
4
subsys/dsp/cmsis/CMakeLists.txt
Normal file
|
@ -0,0 +1,4 @@
|
|||
# Copyright (c) 2022 Google LLC
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
target_include_directories(zdsp PUBLIC public)
|
280
subsys/dsp/cmsis/public/zdsp_backend.h
Normal file
280
subsys/dsp/cmsis/public/zdsp_backend.h
Normal file
|
@ -0,0 +1,280 @@
|
|||
/* Copyright (c) 2022 Google LLC
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef SUBSYS_MATH_CMSIS_BACKEND_PUBLIC_ZDSP_BACKEND_DSP_H_
|
||||
#define SUBSYS_MATH_CMSIS_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 <zephyr/kernel.h>
|
||||
|
||||
#include <arm_math.h>
|
||||
|
||||
static inline void zdsp_mult_q7(const q7_t *src_a, const q7_t *src_b, q7_t *dst,
|
||||
uint32_t block_size)
|
||||
{
|
||||
arm_mult_q7(src_a, src_b, dst, block_size);
|
||||
}
|
||||
static inline void zdsp_mult_q15(const q15_t *src_a, const q15_t *src_b, q15_t *dst,
|
||||
uint32_t block_size)
|
||||
{
|
||||
arm_mult_q15(src_a, src_b, dst, block_size);
|
||||
}
|
||||
static inline void zdsp_mult_q31(const q31_t *src_a, const q31_t *src_b, q31_t *dst,
|
||||
uint32_t block_size)
|
||||
{
|
||||
arm_mult_q31(src_a, src_b, dst, block_size);
|
||||
}
|
||||
static inline void zdsp_mult_f32(const float32_t *src_a, const float32_t *src_b, float32_t *dst,
|
||||
uint32_t block_size)
|
||||
{
|
||||
arm_mult_f32(src_a, src_b, dst, block_size);
|
||||
}
|
||||
|
||||
static inline void zdsp_add_q7(const q7_t *src_a, const q7_t *src_b, q7_t *dst, uint32_t block_size)
|
||||
{
|
||||
arm_add_q7(src_a, src_b, dst, block_size);
|
||||
}
|
||||
static inline void zdsp_add_q15(const q15_t *src_a, const q15_t *src_b, q15_t *dst,
|
||||
uint32_t block_size)
|
||||
{
|
||||
arm_add_q15(src_a, src_b, dst, block_size);
|
||||
}
|
||||
static inline void zdsp_add_q31(const q31_t *src_a, const q31_t *src_b, q31_t *dst,
|
||||
uint32_t block_size)
|
||||
{
|
||||
arm_add_q31(src_a, src_b, dst, block_size);
|
||||
}
|
||||
static inline void zdsp_add_f32(const float32_t *src_a, const float32_t *src_b, float32_t *dst,
|
||||
uint32_t block_size)
|
||||
{
|
||||
arm_add_f32(src_a, src_b, dst, block_size);
|
||||
}
|
||||
|
||||
static inline void zdsp_sub_q7(const q7_t *src_a, const q7_t *src_b, q7_t *dst, uint32_t block_size)
|
||||
{
|
||||
arm_sub_q7(src_a, src_b, dst, block_size);
|
||||
}
|
||||
static inline void zdsp_sub_q15(const q15_t *src_a, const q15_t *src_b, q15_t *dst,
|
||||
uint32_t block_size)
|
||||
{
|
||||
arm_sub_q15(src_a, src_b, dst, block_size);
|
||||
}
|
||||
static inline void zdsp_sub_q31(const q31_t *src_a, const q31_t *src_b, q31_t *dst,
|
||||
uint32_t block_size)
|
||||
{
|
||||
arm_sub_q31(src_a, src_b, dst, block_size);
|
||||
}
|
||||
static inline void zdsp_sub_f32(const float32_t *src_a, const float32_t *src_b, float32_t *dst,
|
||||
uint32_t block_size)
|
||||
{
|
||||
arm_sub_f32(src_a, src_b, dst, block_size);
|
||||
}
|
||||
|
||||
static inline void zdsp_scale_q7(const q7_t *src, q7_t scale_fract, int8_t shift, q7_t *dst,
|
||||
uint32_t block_size)
|
||||
{
|
||||
arm_scale_q7(src, scale_fract, shift, dst, block_size);
|
||||
}
|
||||
static inline void zdsp_scale_q15(const q15_t *src, q15_t scale_fract, int8_t shift, q15_t *dst,
|
||||
uint32_t block_size)
|
||||
{
|
||||
arm_scale_q15(src, scale_fract, shift, dst, block_size);
|
||||
}
|
||||
static inline void zdsp_scale_q31(const q31_t *src, q31_t scale_fract, int8_t shift, q31_t *dst,
|
||||
uint32_t block_size)
|
||||
{
|
||||
arm_scale_q31(src, scale_fract, shift, dst, block_size);
|
||||
}
|
||||
|
||||
static inline void zdsp_scale_f32(const float32_t *src, float32_t scale, float32_t *dst,
|
||||
uint32_t block_size)
|
||||
{
|
||||
arm_scale_f32(src, scale, dst, block_size);
|
||||
}
|
||||
|
||||
static inline void zdsp_abs_q7(const q7_t *src, q7_t *dst, uint32_t block_size)
|
||||
{
|
||||
arm_abs_q7(src, dst, block_size);
|
||||
}
|
||||
static inline void zdsp_abs_q15(const q15_t *src, q15_t *dst, uint32_t block_size)
|
||||
{
|
||||
arm_abs_q15(src, dst, block_size);
|
||||
}
|
||||
static inline void zdsp_abs_q31(const q31_t *src, q31_t *dst, uint32_t block_size)
|
||||
{
|
||||
arm_abs_q31(src, dst, block_size);
|
||||
}
|
||||
static inline void zdsp_abs_f32(const float32_t *src, float32_t *dst, uint32_t block_size)
|
||||
{
|
||||
arm_abs_f32(src, dst, block_size);
|
||||
}
|
||||
|
||||
static inline void zdsp_negate_q7(const q7_t *src, q7_t *dst, uint32_t block_size)
|
||||
{
|
||||
arm_negate_q7(src, dst, block_size);
|
||||
}
|
||||
static inline void zdsp_negate_q15(const q15_t *src, q15_t *dst, uint32_t block_size)
|
||||
{
|
||||
arm_negate_q15(src, dst, block_size);
|
||||
}
|
||||
static inline void zdsp_negate_q31(const q31_t *src, q31_t *dst, uint32_t block_size)
|
||||
{
|
||||
arm_negate_q31(src, dst, block_size);
|
||||
}
|
||||
static inline void zdsp_negate_f32(const float32_t *src, float32_t *dst, uint32_t block_size)
|
||||
{
|
||||
arm_negate_f32(src, dst, block_size);
|
||||
}
|
||||
|
||||
static inline void zdsp_dot_prod_q7(const q7_t *src_a, const q7_t *src_b, uint32_t block_size,
|
||||
q31_t *dst)
|
||||
{
|
||||
arm_dot_prod_q7(src_a, src_b, block_size, dst);
|
||||
}
|
||||
static inline void zdsp_dot_prod_q15(const q15_t *src_a, const q15_t *src_b, uint32_t block_size,
|
||||
q63_t *dst)
|
||||
{
|
||||
arm_dot_prod_q15(src_a, src_b, block_size, dst);
|
||||
}
|
||||
static inline void zdsp_dot_prod_q31(const q31_t *src_a, const q31_t *src_b, uint32_t block_size,
|
||||
q63_t *dst)
|
||||
{
|
||||
arm_dot_prod_q31(src_a, src_b, block_size, dst);
|
||||
}
|
||||
static inline void zdsp_dot_prod_f32(const float32_t *src_a, const float32_t *src_b,
|
||||
uint32_t block_size, float32_t *dst)
|
||||
{
|
||||
arm_dot_prod_f32(src_a, src_b, block_size, dst);
|
||||
}
|
||||
|
||||
static inline void zdsp_shift_q7(const q7_t *src, int8_t shift_bits, q7_t *dst, uint32_t block_size)
|
||||
{
|
||||
arm_shift_q7(src, shift_bits, dst, block_size);
|
||||
}
|
||||
static inline void zdsp_shift_q15(const q15_t *src, int8_t shift_bits, q15_t *dst,
|
||||
uint32_t block_size)
|
||||
{
|
||||
arm_shift_q15(src, shift_bits, dst, block_size);
|
||||
}
|
||||
static inline void zdsp_shift_q31(const q31_t *src, int8_t shift_bits, q31_t *dst,
|
||||
uint32_t block_size)
|
||||
{
|
||||
arm_shift_q31(src, shift_bits, dst, block_size);
|
||||
}
|
||||
|
||||
static inline void zdsp_offset_q7(const q7_t *src, q7_t offset, q7_t *dst, uint32_t block_size)
|
||||
{
|
||||
arm_offset_q7(src, offset, dst, block_size);
|
||||
}
|
||||
static inline void zdsp_offset_q15(const q15_t *src, q15_t offset, q15_t *dst, uint32_t block_size)
|
||||
{
|
||||
arm_offset_q15(src, offset, dst, block_size);
|
||||
}
|
||||
static inline void zdsp_offset_q31(const q31_t *src, q31_t offset, q31_t *dst, uint32_t block_size)
|
||||
{
|
||||
arm_offset_q31(src, offset, dst, block_size);
|
||||
}
|
||||
static inline void zdsp_offset_f32(const float32_t *src, float32_t offset, float32_t *dst,
|
||||
uint32_t block_size)
|
||||
{
|
||||
arm_offset_f32(src, offset, dst, block_size);
|
||||
}
|
||||
|
||||
static inline void zdsp_clip_q7(const q7_t *src, 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 q15_t *src, 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 q31_t *src, 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 float32_t *src, 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 uint8_t *src_a, const uint8_t *src_b, uint8_t *dst,
|
||||
uint32_t block_size)
|
||||
{
|
||||
arm_and_u8(src_a, src_b, dst, block_size);
|
||||
}
|
||||
static inline void zdsp_and_u16(const uint16_t *src_a, const uint16_t *src_b, uint16_t *dst,
|
||||
uint32_t block_size)
|
||||
{
|
||||
arm_and_u16(src_a, src_b, dst, block_size);
|
||||
}
|
||||
static inline void zdsp_and_u32(const uint32_t *src_a, const uint32_t *src_b, uint32_t *dst,
|
||||
uint32_t block_size)
|
||||
{
|
||||
arm_and_u32(src_a, src_b, dst, block_size);
|
||||
}
|
||||
|
||||
static inline void zdsp_or_u8(const uint8_t *src_a, const uint8_t *src_b, uint8_t *dst,
|
||||
uint32_t block_size)
|
||||
{
|
||||
arm_or_u8(src_a, src_b, dst, block_size);
|
||||
}
|
||||
static inline void zdsp_or_u16(const uint16_t *src_a, const uint16_t *src_b, uint16_t *dst,
|
||||
uint32_t block_size)
|
||||
{
|
||||
arm_or_u16(src_a, src_b, dst, block_size);
|
||||
}
|
||||
static inline void zdsp_or_u32(const uint32_t *src_a, const uint32_t *src_b, uint32_t *dst,
|
||||
uint32_t block_size)
|
||||
{
|
||||
arm_or_u32(src_a, src_b, dst, block_size);
|
||||
}
|
||||
|
||||
static inline void zdsp_xor_u8(const uint8_t *src_a, const uint8_t *src_b, uint8_t *dst,
|
||||
uint32_t block_size)
|
||||
{
|
||||
arm_xor_u8(src_a, src_b, dst, block_size);
|
||||
}
|
||||
static inline void zdsp_xor_u16(const uint16_t *src_a, const uint16_t *src_b, uint16_t *dst,
|
||||
uint32_t block_size)
|
||||
{
|
||||
arm_xor_u16(src_a, src_b, dst, block_size);
|
||||
}
|
||||
static inline void zdsp_xor_u32(const uint32_t *src_a, const uint32_t *src_b, uint32_t *dst,
|
||||
uint32_t block_size)
|
||||
{
|
||||
arm_xor_u32(src_a, src_b, dst, block_size);
|
||||
}
|
||||
|
||||
static inline void zdsp_not_u8(const uint8_t *src, uint8_t *dst, uint32_t block_size)
|
||||
{
|
||||
arm_not_u8(src, dst, block_size);
|
||||
}
|
||||
static inline void zdsp_not_u16(const uint16_t *src, uint16_t *dst, uint32_t block_size)
|
||||
{
|
||||
arm_not_u16(src, dst, block_size);
|
||||
}
|
||||
static inline void zdsp_not_u32(const uint32_t *src, uint32_t *dst, uint32_t block_size)
|
||||
{
|
||||
arm_not_u32(src, dst, block_size);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_FP16
|
||||
#include "zdsp_backend_f16.h"
|
||||
#endif /* COIFNG_FP16 */
|
||||
|
||||
#endif /* SUBSYS_MATH_CMSIS_BACKEND_PUBLIC_ZDSP_BACKEND_DSP_H_ */
|
75
subsys/dsp/cmsis/public/zdsp_backend_f16.h
Normal file
75
subsys/dsp/cmsis/public/zdsp_backend_f16.h
Normal file
|
@ -0,0 +1,75 @@
|
|||
/* Copyright (c) 2022 Google LLC
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef SUBSYS_DSP_CMSIS_PUBLIC_ZDSP_BACKEND_F16_H_
|
||||
#define SUBSYS_DSP_CMSIS_PUBLIC_ZDSP_BACKEND_F16_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 <zephyr/kernel.h>
|
||||
|
||||
#include <arm_math_f16.h>
|
||||
|
||||
static inline void zdsp_mult_f16(const float16_t *src_a, const float16_t *src_b, float16_t *dst,
|
||||
uint32_t block_size)
|
||||
{
|
||||
arm_mult_f16(src_a, src_b, dst, block_size);
|
||||
}
|
||||
|
||||
static inline void zdsp_add_f16(const float16_t *src_a, const float16_t *src_b, float16_t *dst,
|
||||
uint32_t block_size)
|
||||
{
|
||||
arm_add_f16(src_a, src_b, dst, block_size);
|
||||
}
|
||||
|
||||
static inline void zdsp_sub_f16(const float16_t *src_a, const float16_t *src_b, float16_t *dst,
|
||||
uint32_t block_size)
|
||||
{
|
||||
arm_sub_f16(src_a, src_b, dst, block_size);
|
||||
}
|
||||
|
||||
static inline void zdsp_scale_f16(const float16_t *src, float16_t scale, float16_t *dst,
|
||||
uint32_t block_size)
|
||||
{
|
||||
arm_scale_f16(src, scale, dst, block_size);
|
||||
}
|
||||
|
||||
static inline void zdsp_abs_f16(const float16_t *src, float16_t *dst, uint32_t block_size)
|
||||
{
|
||||
arm_abs_f16(src, dst, block_size);
|
||||
}
|
||||
|
||||
static inline void zdsp_dot_prod_f16(const float16_t *src_a, const float16_t *src_b,
|
||||
uint32_t block_size, float16_t *result)
|
||||
{
|
||||
arm_dot_prod_f16(src_a, src_b, block_size, result);
|
||||
}
|
||||
|
||||
static inline void zdsp_offset_f16(const float16_t *src, float16_t offset, float16_t *dst,
|
||||
uint32_t block_size)
|
||||
{
|
||||
arm_offset_f16(src, offset, dst, block_size);
|
||||
}
|
||||
|
||||
static inline void zdsp_negate_f16(const float16_t *src, float16_t *dst, uint32_t block_size)
|
||||
{
|
||||
arm_negate_f16(src, dst, block_size);
|
||||
}
|
||||
|
||||
static inline void zdsp_clip_f16(const float16_t *src, float16_t *dst, float16_t low,
|
||||
float16_t high, uint32_t num_samples)
|
||||
{
|
||||
arm_clip_f16(src, dst, low, high, num_samples);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* SUBSYS_DSP_CMSIS_PUBLIC_ZDSP_BACKEND_F16_H_ */
|
Loading…
Add table
Add a link
Reference in a new issue