Sound Open Firmware
Loading...
Searching...
No Matches
common.h
Go to the documentation of this file.
1
/* SPDX-License-Identifier: BSD-3-Clause
2
*
3
* Copyright(c) 2019 Intel Corporation. All rights reserved.
4
*
5
* Author: Tomasz Lauda <tomasz.lauda@linux.intel.com>
6
* Janusz Jankowski <janusz.jankowski@linux.intel.com>
7
*/
8
9
#ifndef __SOF_COMMON_H__
10
#define __SOF_COMMON_H__
11
12
#if !defined(LINKER)
13
14
/* callers must check/use the return value */
15
#define __must_check __attribute__((warn_unused_result))
16
17
#include <zephyr/sys/util.h>
18
19
/* Align the number to the nearest alignment value */
20
#ifndef IS_ALIGNED
21
#define IS_ALIGNED(size, alignment) ((size) % (alignment) == 0)
22
#endif
23
24
/* Treat zero as a special case because it wraps around */
25
#define is_power_of_2(x) ((x) && !((x) & ((x) - 1)))
26
27
#define compile_check(x) (sizeof(struct { int _f[2 * (x) - 1]; }) != 0)
28
29
#define ALIGN_UP_INTERNAL(val, align) (((val) + (align) - 1) & ~((align) - 1))
30
31
#if !defined(__ASSEMBLER__) && defined(__XTENSA__)
32
33
#include <
ipc/trace.h
>
34
#include <
rtos/panic.h
>
35
#define VERIFY_ALIGN
36
37
#endif
38
39
#ifdef VERIFY_ALIGN
40
41
/* Using this when 'alignment' is a constant and when compiling with gcc
42
* -O0 saves about 30 bytes of .text and a few CPU cycles compared to
43
* the ALIGN_UP() combined check. There's no .text difference when
44
* optimizing.
45
*/
46
#define ALIGN_UP_COMPILE(size, alignment) \
47
(compile_check(is_power_of_2(alignment)) ? \
48
ALIGN_UP_INTERNAL(size, alignment) : 0xBADCAFE)
49
50
#if defined(__XCC__) || defined(__clang__)
51
52
/*
53
* xcc doesn't support __builtin_constant_p() so we can only do run-time
54
* verification
55
*/
56
57
#define ALIGN_UP(size, alignment) ({ \
58
if (!is_power_of_2(alignment)) \
59
sof_panic(SOF_IPC_PANIC_ASSERT); \
60
ALIGN_UP_INTERNAL(size, alignment); \
61
})
62
63
#define ALIGN_DOWN(size, alignment) ({ \
64
if (!is_power_of_2(alignment)) \
65
sof_panic(SOF_IPC_PANIC_ASSERT); \
66
(size) & ~((alignment) - 1); \
67
})
68
69
#else
/* not __XCC__ or __clang__ */
70
71
/* If we can't tell at compile time, assume it's OK and defer to run-time */
72
#define COMPILE_TIME_ALIGNED(align) (!__builtin_constant_p(align) || \
73
is_power_of_2(align))
74
75
#define ALIGN_UP(size, alignment) ({ \
76
if (!compile_check(COMPILE_TIME_ALIGNED(alignment)) || \
77
!is_power_of_2(alignment)) \
78
sof_panic(SOF_IPC_PANIC_ASSERT); \
79
ALIGN_UP_INTERNAL(size, alignment); \
80
})
81
82
#define ALIGN_DOWN(size, alignment) ({ \
83
if (!compile_check(COMPILE_TIME_ALIGNED(alignment)) || \
84
!is_power_of_2(alignment)) \
85
sof_panic(SOF_IPC_PANIC_ASSERT); \
86
(size) & ~((alignment) - 1); \
87
})
88
89
#endif
/* not __XCC__ or __clang__ */
90
91
#else
/* not VERIFY_ALIGN */
92
93
#define ALIGN_UP(size, alignment) ALIGN_UP_INTERNAL(size, alignment)
94
#define ALIGN_UP_COMPILE ALIGN_UP
95
#define ALIGN_DOWN(size, alignment) ((size) & ~((alignment) - 1))
96
97
#endif
98
99
/* This most basic ALIGN() must be used in header files that are
100
* included in both C and assembly code. memory.h files require this
101
* exact spelling matching the linker function because memory.h values
102
* are _also_ copied unprocessed to the .x[.in] linker script
103
*/
104
#define ALIGN(val, align) ALIGN_UP_INTERNAL(val, align)
105
#define SOF_DIV_ROUND_UP(val, div) (((val) + (div) - 1) / (div))
106
107
#if !defined(__ASSEMBLER__)
108
109
#include <
rtos/string_macro.h
>
110
#include <
sof/compiler_attributes.h
>
111
#include <stddef.h>
112
113
/* use same syntax as Linux for simplicity */
114
#ifndef __ZEPHYR__
/* Already present and compatible via Zephyr headers */
115
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
116
#endif
117
#define container_of(ptr, type, member) \
118
({const __typeof__(((type *)0)->member)*__memberptr = (ptr); \
119
(type *)((char *)__memberptr - offsetof(type, member)); })
120
/*
121
* typeof() doesn't preserve __attribute__((address_space(x))) sparse
122
* annotations, so if an object belongs to such an address space, using the
123
* original form of container_of() will lose that annotation, which then will
124
* lead to sparse "different address spaces" warnings. We need to explicitly
125
* re-inforce the address space onto the new pointer.
126
*/
127
#define attr_container_of(ptr, type, member, attr) \
128
({const __typeof__(((type *)0)->member) attr *__memberptr = (ptr); \
129
(type *)((char attr *)__memberptr - offsetof(type, member)); })
130
131
#define ffs(i) __builtin_ffs(i)
132
#define ffsl(i) __builtin_ffsl(i)
133
#define ffsll(i) __builtin_ffsll(i)
134
135
#define clz(i) __builtin_clz(i)
136
#define clzl(i) __builtin_clzl(i)
137
#define clzll(i) __builtin_clzll(i)
138
139
#define popcount(x) __builtin_popcount(x)
140
141
/* count number of var args */
142
#define PP_NARG(...) (sizeof((unsigned int[]){0, ##__VA_ARGS__}) \
143
/ sizeof(unsigned int) - 1)
144
145
/* Compile-time assertion.
146
*
147
* The first, typedef-based solution silently succeeds with variables,
148
* for instance STATIC_ASSERT(n == 42, always_succeeds) when 'n' is a
149
* variable in a function. The second, array-based solution is not
150
* fooled by variables but it increases the .bss size at the -O0
151
* optimization level (no difference with any real -O). As we're often
152
* short on space, use the typedef-based version by default. If you're
153
* afraid that some assertions are being fooled by variables then
154
* temporarily and locally switch to the second one.
155
*/
156
#define STATIC_ASSERT(COND, MESSAGE) \
157
__attribute__((unused)) \
158
typedef char _CONCAT(assertion_failed_, MESSAGE)[(COND) ? 1 : -1]
159
160
/* Allows checking preprocessor symbols in compile-time.
161
* Returns true for config with value 1, false for undefined or any other value.
162
*
163
* Expression like (CONFIG_MY ? a : b) rises compilation error when CONFIG_MY
164
* is undefined, (IS_ENABLED(CONFIG_MY) ? a : b) can be used instead of it.
165
*
166
* It is intended to be used with Kconfig's bool configs - it should rise
167
* error for other types, except positive integers, but it shouldn't be
168
* used with them.
169
*/
170
#ifndef __ZEPHYR__
/* Already present and compatible via Zephyr headers */
171
#define IS_ENABLED(config) IS_ENABLED_STEP_1(config)
172
#define IS_ENABLED_DUMMY_1 0,
173
#define IS_ENABLED_STEP_1(config) IS_ENABLED_STEP_2(IS_ENABLED_DUMMY_ ## config)
174
#define IS_ENABLED_STEP_2(values) IS_ENABLED_STEP_3(values 1, 0)
175
#define IS_ENABLED_STEP_3(ignore, value, ...) (!!(value))
176
#endif
177
178
#define SOF_CONFIG_HIFI(level, component) (CONFIG_ ## component ## _HIFI_ ## level)
179
180
/* True if:
181
* (1) EITHER this particular level was manually forced in Kconfig,
182
* (2) OR: - this component defaulted to "MAX"
183
* - AND this level is the max available in the XC HAL.
184
*/
185
#define SOF_USE_HIFI(level, component) (SOF_CONFIG_HIFI(level, component) || \
186
(SOF_CONFIG_HIFI(MAX, component) && level == SOF_MAX_XCHAL_HIFI))
187
188
/* True if:
189
* (1) EITHER this particular level was manually forced in Kconfig,
190
* (2) OR: - this component defaulted to "MAX"
191
* - AND this level is less or equal to max available in the XC HAL.
192
*
193
* Use e.g. for highest optimization level source file, e.g. SOF_USE_MIN_HIFI(4, component)
194
* for HiFi4 code version that can be built with HiFi4 or HiFi5 tool chain.
195
*/
196
#define SOF_USE_MIN_HIFI(minlevel, component) (SOF_CONFIG_HIFI(minlevel, component) || \
197
(SOF_CONFIG_HIFI(MAX, component) && minlevel <= SOF_MAX_XCHAL_HIFI))
198
199
#define SOF_CONFIG_ARM_SIMD(component) (CONFIG_ ## component ## _ARM_SIMD)
200
#define SOF_USE_ARM_SIMD(component) (IS_ENABLED(CONFIG_ ## component ## _ARM_SIMD))
201
#define SOF_CONFIG_ARM_FPU(component) (CONFIG_ ## component ## _ARM_FPU)
202
#define SOF_USE_ARM_FPU(component) (IS_ENABLED(CONFIG_ ## component ## _ARM_FPU))
203
204
#define SOF_CONFIG_RISCV_SIMD(component) (CONFIG_ ## component ## _RISCV_SIMD)
205
#define SOF_USE_RISCV_SIMD(component) (IS_ENABLED(CONFIG_ ## component ## _RISCV_SIMD))
206
207
#ifndef __XCC__
// Cadence toolchains: either xt-xcc or xt-clang.
208
# define SOF_MAX_XCHAL_HIFI NONE
209
#else
210
# include <xtensa/config/core-isa.h>
211
// Maybe we could make this fully generic (and less readable!) using
212
// IS_ENABLED() above.
213
# if XCHAL_HAVE_HIFI5
214
# define SOF_MAX_XCHAL_HIFI 5
215
# define SOF_FRAME_BYTE_ALIGN 16
216
# elif XCHAL_HAVE_HIFI4
217
# define SOF_MAX_XCHAL_HIFI 4
218
# define SOF_FRAME_BYTE_ALIGN 8
219
# elif XCHAL_HAVE_HIFI3
220
# define SOF_MAX_XCHAL_HIFI 3
221
# define SOF_FRAME_BYTE_ALIGN 8
222
# else
223
# define SOF_MAX_XCHAL_HIFI NONE
224
# endif
225
#endif
226
227
/* Keep this last after all platform specific align defaults */
228
#ifndef SOF_FRAME_BYTE_ALIGN
229
# define SOF_FRAME_BYTE_ALIGN 4
230
#endif
231
232
/* Default frame-count alignment is 1 */
233
#define SOF_FRAME_COUNT_ALIGN 1
234
235
#ifndef __GLIBC_USE
236
#define __GLIBC_USE(x) 0
237
#endif
238
239
#if defined(__XCC__) || defined(__CHECKER__)
240
/* XCC does not currently check alignment for packed data so no need for any
241
* compiler hints.
242
*/
243
#define ASSUME_ALIGNED(x, a) x
244
#else
245
/* GCC 9.x has checks for pointer alignment within packed structures when
246
* cast from one type to another. This macro should only be used after checking
247
* alignment. This compiler builtin may not be available on all compilers so
248
* this macro can be defined as NULL if needed.
249
*/
250
#define ASSUME_ALIGNED(x, a) ((__typeof__(x))__builtin_assume_aligned((x), a))
251
#endif
/* __XCC__ */
252
253
#endif
/* __ASSEMBLER__ */
254
#else
/* LINKER */
255
256
#define ALIGN_UP_INTERNAL(val, align) (((val) + (align) - 1) & ~((align) - 1))
257
258
#endif
/* LINKER */
259
#endif
/* __SOF_COMMON_H__ */
compiler_attributes.h
panic.h
trace.h
Host-DSP IPC trace DMA configuration, filtering, and panic descriptors.
string_macro.h
src
include
sof
common.h
Generated by
1.9.8