FFmpeg
checkasm.h
Go to the documentation of this file.
1 /*
2  * Copyright © 2025, Niklas Haas
3  * Copyright © 2018, VideoLAN and dav1d authors
4  * Copyright © 2018, Two Orioles, LLC
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions are met:
9  *
10  * 1. Redistributions of source code must retain the above copyright notice, this
11  * list of conditions and the following disclaimer.
12  *
13  * 2. Redistributions in binary form must reproduce the above copyright notice,
14  * this list of conditions and the following disclaimer in the documentation
15  * and/or other materials provided with the distribution.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
21  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  */
28 
29 /**
30  * @file checkasm.h
31  * @brief Main checkasm API for test suite configuration and execution
32  *
33  * This header provides the primary checkasm API for setting up and running
34  * assembly test suites, including configuration structures, test registration,
35  * and benchmark execution. It defines the main entry points and configuration
36  * options for checkasm-based test programs.
37  */
38 
39 #ifndef CHECKASM_CHECKASM_H
40 #define CHECKASM_CHECKASM_H
41 
42 #include <stdint.h>
43 
44 #include "checkasm/attributes.h"
45 
46 /**
47  * @defgroup config User-provided Configuration
48  * @{
49  *
50  * User-provided preprocessor definitions for configuring the behavior of
51  * the checkasm header files. These macros should be defined before including
52  * checkasm.h, based on the availability of compiler features in the target
53  * project.
54  */
55 
56 /**
57  * @def CHECKASM_HAVE_GENERIC
58  * @brief Enable C11 _Generic support
59  *
60  * When enabled (defined to a nonzero value), checkasm uses C11's _Generic
61  * keyword to enable extra checks that rely on type information. This enables
62  * register width checking and floating point state checks on supported
63  * platforms. When disabled (defined to 0), these features are silently
64  * disabled.
65  *
66  * By default (when not defined), this is automatically enabled for C11 and
67  * later, and disabled for older C standards. Define this macro before
68  * including checkasm.h to explicitly control the behavior.
69  *
70  * @note This is not needed when compiling with `-std=c11` or later.
71  */
72 #ifndef CHECKASM_HAVE_GENERIC
73  #if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L
74  #define CHECKASM_HAVE_GENERIC 1
75  #else
76  #define CHECKASM_HAVE_GENERIC 0
77  #endif
78 #endif
79 
80 /** @} */ /* end of config group */
81 
82 /**
83  * @brief Opaque type representing a set of CPU feature flags
84  *
85  * Bitfield type used to represent CPU capabilities and SIMD instruction set
86  * support. The specific bit values are defined by the implementation.
87  */
88 typedef uint64_t CheckasmCpu;
89 
90 /**
91  * @brief Opaque type used to identify function implementations
92  *
93  * Used internally by checkasm to track and match different variants of
94  * functions being tested.
95  */
96 typedef uintptr_t CheckasmKey;
97 
98 /**
99  * @brief Describes a CPU feature flag/capability
100  *
101  * Used to define the CPU features that the test suite should test against.
102  * Tests will be run incrementally for each CPU feature set, with each test
103  * inheriting flags from previously tested CPUs.
104  */
105 typedef struct CheckasmCpuInfo {
106  const char *name; /**< Human-readable name (e.g., "SSE2", "AVX2") */
107  const char *suffix; /**< Short suffix for function names (e.g., "sse2", "avx2") */
108  CheckasmCpu flag; /**< Bitmask flag value for this CPU feature */
110 
111 /**
112  * @brief Describes a single test function
113  *
114  * Represents one test function that will be invoked by the test suite.
115  * Each test function typically tests a specific component or subsystem.
116  */
117 typedef struct CheckasmTest {
118  const char *name; /**< Name of the test (used for filtering and reporting) */
119  void (*func)(void); /**< Test function to invoke */
120 } CheckasmTest;
121 
122 /**
123  * @brief Output format for benchmark results
124  *
125  * Specifies how benchmark results should be formatted.
126  *
127  * @note In all cases, output is written to `stdout` by default.
128  */
129 typedef enum CheckasmFormat {
130  CHECKASM_FORMAT_PRETTY, /**< Pretty-printed (colored) text output (default) */
131  CHECKASM_FORMAT_CSV, /**< Comma-separated values with optional header */
132  CHECKASM_FORMAT_TSV, /**< Tab-separated values with optional header */
133  CHECKASM_FORMAT_JSON, /**< JSON structured output with all measurement data */
134  CHECKASM_FORMAT_HTML, /**< Interactive HTML report for web viewing */
136 
137 /**
138  * @brief Configuration structure for the checkasm test suite
139  *
140  * This structure contains all configuration options for running checkasm tests,
141  * including test selection, CPU feature flags, benchmarking options, and output
142  * formatting. Initialize this structure with your project's tests and CPU flags
143  * before calling checkasm_main() or checkasm_run().
144  *
145  * @code
146  * CheckasmConfig config = {
147  * .cpu_flags = my_cpu_flags,
148  * .tests = my_tests,
149  * .cpu = my_get_cpu_flags(),
150  * .set_cpu_flags = my_set_cpu_flags,
151  * };
152  *
153  * return checkasm_main(&config, argc, argv);
154  * @endcode
155  *
156  * @see checkasm_main(), checkasm_run()
157  */
158 typedef struct CheckasmConfig {
159  /**
160  * @brief List of CPU flags understood by the implementation
161  *
162  * Array of CPU features that will be tested in incremental order,
163  * terminated by an entry with `CheckasmCpuInfo.flag == 0` (i.e. `{0}`).
164  *
165  * Each test run inherits any active flags from previously tested CPUs.
166  * This allows testing progressively more advanced instruction sets.
167  */
169 
170  /**
171  * @brief Array of test functions to execute
172  *
173  * Array of test functions to execute, terminated by an entry with
174  * `CheckasmTest.func == NULL` (i.e. `{0}`.
175  */
177 
178  /**
179  * @brief Detected CPU flags for the current system
180  *
181  * Set this to the detected CPU capabilities of the system. Any extra flags
182  * not included in cpu_flags will also be transparently included in
183  * checkasm_get_cpu_flags(), and can be used to signal flags that should
184  * be assumed to always be enabled (e.g., CPU_FLAG_FAST_* modifiers).
185  */
187 
188  /**
189  * @brief Callback invoked when active CPU flags change
190  *
191  * If provided, this function will be called whenever the active set of
192  * CPU flags changes, with the new set of flags as argument. This includes
193  * once at the start of the program with the baseline set of flags.
194  *
195  * Use this to update global function pointers, internal static variables,
196  * or dispatch tables.
197  */
198  void (*set_cpu_flags)(CheckasmCpu new_flags);
199 
200  /**
201  * @brief Pattern for filtering which tests to run
202  *
203  * Shell-style wildcard pattern (e.g., "video_*") to select tests.
204  * NULL means run all tests.
205  */
206  const char *test_pattern;
207 
208  /**
209  * @brief Pattern for filtering which functions within tests to run
210  *
211  * Shell-style wildcard pattern to select specific functions. Matched
212  * against the names passed to checkasm_check_func(). NULL means run all
213  * functions.
214  */
215  const char *function_pattern;
216 
217  /**
218  * @brief Enable benchmarking
219  *
220  * When nonzero, enables performance benchmarking of tested functions.
221  * Set to 1 to enable with default settings.
222  */
223  int bench;
224 
225  /**
226  * @brief Target benchmark duration in microseconds
227  *
228  * Target time (in µs) to spend benchmarking each function.
229  * Defaults to 1000 µs if left unset when bench is enabled.
230  *
231  * @note Very slow functions may execute for a longer duration to ensure
232  * enough samples are collected for accurate measurement.
233  */
234  unsigned bench_usec;
235 
236  /** @brief Output format for benchmark results */
238 
239  /**
240  * @brief Enable verbose output
241  *
242  * When nonzero, prints detailed timing information, failure diagnostics,
243  * and extra terminal output (including table headers and extra information
244  * about the active configuration).
245  */
246  int verbose;
247 
248  /** @brief Enable using the seed value
249  *
250  * If nonzero, the value in the seed field will be used even if it may be
251  * zero.
252  */
253  int seed_set;
254 
255  /**
256  * @brief Random number generator seed
257  *
258  * If nonzero or if seed_set is nonzero, use this seed for deterministic
259  * random number generation. If zero and seed_set is zero, a seed will
260  * be chosen based on the current time.
261  */
262  unsigned seed;
263 
264  /**
265  * @brief Number of times to repeat tests
266  *
267  * Repeat the test (and benchmark, if enabled) this many times using
268  * successive seeds. Setting to -1 effectively tests every possible seed
269  * (useful for exhaustive testing).
270  */
271  unsigned repeat;
272 
273  /** @brief Enable process pinning via cpu_affinity
274  *
275  * If nonzero, the test process will be pinned to the CPU core specified
276  * in cpu_affinity.
277  *
278  * @warning This will override the CPU affinity of the calling process, and
279  * will persist even after checkasm_run() returns.
280  */
282 
283  /**
284  * @brief CPU core ID for process pinning
285  *
286  * If cpu_affinity_set is nonzero, pin the test process to this CPU core.
287  */
288  unsigned cpu_affinity;
290 
291 /**
292  * @brief Get the current active set of CPU flags
293  *
294  * Returns the currently active (masked) set of CPU flags. During test execution,
295  * this reflects which CPU features are currently being tested. May be called
296  * from within test functions to choose an implementation to test.
297  *
298  * @return Current CPU feature flags as a bitmask
299  *
300  * @note The returned value changes as checkasm iterates through different CPU
301  * feature sets during testing.
302  */
304 
305 /**
306  * @brief Get the CPU flag currently being tested
307  *
308  * Returns the CheckasmCpuInfo structure for the CPU flag currently being
309  * tested, or NULL if testing the baseline configuration with no additional
310  * CPU flags.
311  *
312  * @return Currently active CPU flag info, or NULL
313  *
314  * @note Unlike checkasm_get_cpu_flags(), this only reflects the currently
315  * running test, and does not include any information about previously
316  * tested CPU flags.
317  *
318  * @since v1.2.0
319  */
321 
322 /**
323  * @brief Get the suffix for the current CPU flag, or "c" if none
324  * @since v1.2.0
325  */
326 static inline const char *checkasm_get_cpu_suffix(void)
327 {
329  return info ? info->suffix : "c";
330 }
331 
332 /**
333  * @brief Print available CPU flags to stdout.
334  *
335  * Prints a list of all CPU flags/features that are available for testing
336  * based on the configuration, as well as CPU flags which are defined but
337  * unsupported on the system.
338  *
339  * @param[in] config Configuration containing CPU flag definitions
340  */
342 
343 /**
344  * @brief Print available tests
345  *
346  * Prints a list of all test functions registered in the configuration.
347  * Useful for discovering what tests are available and for use with
348  * test pattern filtering.
349  *
350  * @param[in] config Configuration containing test definitions
351  */
353 
354 /**
355  * @brief Print available functions within tests
356  *
357  * Prints a detailed list of all functions being tested across all registered
358  * tests. Useful for discovering what can be filtered with function patterns.
359  *
360  * @param[in] config Configuration containing test definitions
361  *
362  * @note This requires executing all tests to gather information about the
363  * available functions. During this process, checkasm_check_func() always
364  * returns 0 to skip the actual testing. However, any side effects from
365  * test functions will still occur, unless properly guarded.
366  */
368 
369 /**
370  * @brief Run all tests and benchmarks matching the specified patterns
371  *
372  * Executes the checkasm test suite according to the configuration. Tests
373  * and functions are filtered according to test_pattern and function_pattern
374  * if specified. Benchmarks are run if bench is enabled.
375  *
376  * @param[in] config Configuration structure with all test parameters
377  * @return 0 on success (all tests passed), negative error code on failure
378  *
379  * @note This is the lower-level entry point. Most users should use
380  * checkasm_main() instead, which handles argument parsing.
381  *
382  * @warning This function may override the processor state in subtle ways,
383  * including enabling high-precision performance timers, installing
384  * signal handlers and configuring the terminal output.
385  *
386  * @see checkasm_main()
387  */
389 
390 /**
391  * @brief Main entry point for checkasm test programs
392  *
393  * Convenience wrapper around checkasm_run() that parses command-line arguments
394  * and updates the config accordingly. This is the recommended entry point for
395  * most checkasm test programs. Call this from your main() function.
396  *
397  * Before calling this function, initialize config with the minimum set of
398  * project-specific fields:
399  * - config.cpu_flags: Array of CPU features to test
400  * - config.tests: Array of test functions
401  * - config.cpu: Detected CPU capabilities
402  *
403  * Command-line arguments like --bench, --test, --function, --seed, etc. are
404  * automatically parsed and applied to the config.
405  *
406  * @param[in,out] config Configuration structure (will be modified by argument parsing)
407  * @param[in] argc Argument count from main()
408  * @param[in] argv Argument vector from main()
409  * @return 0 on success, non-zero on failure (suitable for return from main())
410  *
411  * @code
412  * int main(int argc, const char *argv[]) {
413  * CheckasmConfig config = {
414  * .cpu_flags = my_cpu_flags,
415  * .tests = my_tests,
416  * .cpu = my_get_cpu_flags(),
417  * .set_cpu_flags = my_set_cpu_flags,
418  * };
419  * return checkasm_main(&config, argc, argv);
420  * }
421  * @endcode
422  *
423  * @see checkasm_run()
424  */
425 CHECKASM_API int checkasm_main(CheckasmConfig *config, int argc, const char *argv[]);
426 
427 #endif /* CHECKASM_CHECKASM_H */
CheckasmConfig::cpu_affinity
unsigned cpu_affinity
CPU core ID for process pinning.
Definition: checkasm.h:288
checkasm_get_cpu_suffix
static const char * checkasm_get_cpu_suffix(void)
Get the suffix for the current CPU flag, or "c" if none.
Definition: checkasm.h:326
CheckasmTest::name
const char * name
Name of the test (used for filtering and reporting)
Definition: checkasm.h:118
checkasm_list_functions
CHECKASM_API void checkasm_list_functions(const CheckasmConfig *config)
Print available functions within tests.
Definition: checkasm.c:700
CheckasmConfig::bench
int bench
Enable benchmarking.
Definition: checkasm.h:223
CheckasmConfig::test_pattern
const char * test_pattern
Pattern for filtering which tests to run.
Definition: checkasm.h:206
tf_sess_config.config
config
Definition: tf_sess_config.py:33
checkasm_list_tests
CHECKASM_API void checkasm_list_tests(const CheckasmConfig *config)
Print available tests.
Definition: checkasm.c:681
CheckasmFormat
CheckasmFormat
Output format for benchmark results.
Definition: checkasm.h:129
CHECKASM_FORMAT_JSON
@ CHECKASM_FORMAT_JSON
JSON structured output with all measurement data.
Definition: checkasm.h:133
attributes.h
Platform and compiler attribute macros.
CheckasmConfig::cpu_flags
const CheckasmCpuInfo * cpu_flags
List of CPU flags understood by the implementation.
Definition: checkasm.h:168
CheckasmConfig::tests
const CheckasmTest * tests
Array of test functions to execute.
Definition: checkasm.h:176
checkasm_run
CHECKASM_API int checkasm_run(const CheckasmConfig *config)
Run all tests and benchmarks matching the specified patterns.
Definition: checkasm.c:783
CheckasmCpuInfo
Describes a CPU feature flag/capability.
Definition: checkasm.h:105
CheckasmConfig::function_pattern
const char * function_pattern
Pattern for filtering which functions within tests to run.
Definition: checkasm.h:215
info
MIPS optimizations info
Definition: mips.txt:2
CheckasmTest::func
void(* func)(void)
Test function to invoke.
Definition: checkasm.h:119
CheckasmConfig::seed
unsigned seed
Random number generator seed.
Definition: checkasm.h:262
CheckasmConfig::bench_usec
unsigned bench_usec
Target benchmark duration in microseconds.
Definition: checkasm.h:234
checkasm_get_cpu_info
const CHECKASM_API CheckasmCpuInfo * checkasm_get_cpu_info(void)
Get the CPU flag currently being tested.
Definition: checkasm.c:126
CheckasmTest
Describes a single test function.
Definition: checkasm.h:117
CHECKASM_FORMAT_PRETTY
@ CHECKASM_FORMAT_PRETTY
Pretty-printed (colored) text output (default)
Definition: checkasm.h:130
CHECKASM_FORMAT_TSV
@ CHECKASM_FORMAT_TSV
Tab-separated values with optional header.
Definition: checkasm.h:132
checkasm_main
CHECKASM_API int checkasm_main(CheckasmConfig *config, int argc, const char *argv[])
Main entry point for checkasm test programs.
Definition: checkasm.c:1142
CheckasmCpuInfo::suffix
const char * suffix
Short suffix for function names (e.g., "sse2", "avx2")
Definition: checkasm.h:107
CheckasmConfig
Configuration structure for the checkasm test suite.
Definition: checkasm.h:158
CHECKASM_FORMAT_CSV
@ CHECKASM_FORMAT_CSV
Comma-separated values with optional header.
Definition: checkasm.h:131
CHECKASM_FORMAT_HTML
@ CHECKASM_FORMAT_HTML
Interactive HTML report for web viewing.
Definition: checkasm.h:134
CheckasmCpuInfo::flag
CheckasmCpu flag
Bitmask flag value for this CPU feature.
Definition: checkasm.h:108
CheckasmConfig::cpu_affinity_set
int cpu_affinity_set
Enable process pinning via cpu_affinity.
Definition: checkasm.h:281
CHECKASM_API
#define CHECKASM_API
Symbol visibility attribute for public API functions.
Definition: attributes.h:90
checkasm_get_cpu_flags
CHECKASM_API CheckasmCpu checkasm_get_cpu_flags(void)
Get the current active set of CPU flags.
Definition: checkasm.c:121
CheckasmKey
uintptr_t CheckasmKey
Opaque type used to identify function implementations.
Definition: checkasm.h:96
CheckasmConfig::seed_set
int seed_set
Enable using the seed value.
Definition: checkasm.h:253
CheckasmConfig::repeat
unsigned repeat
Number of times to repeat tests.
Definition: checkasm.h:271
checkasm_list_cpu_flags
CHECKASM_API void checkasm_list_cpu_flags(const CheckasmConfig *config)
Print available CPU flags to stdout.
Definition: checkasm.c:668
CheckasmConfig::cpu
CheckasmCpu cpu
Detected CPU flags for the current system.
Definition: checkasm.h:186
CheckasmCpuInfo::name
const char * name
Human-readable name (e.g., "SSE2", "AVX2")
Definition: checkasm.h:106
CheckasmConfig::format
CheckasmFormat format
Output format for benchmark results.
Definition: checkasm.h:237
CheckasmCpu
uint64_t CheckasmCpu
Opaque type representing a set of CPU feature flags.
Definition: checkasm.h:88
CheckasmConfig::set_cpu_flags
void(* set_cpu_flags)(CheckasmCpu new_flags)
Callback invoked when active CPU flags change.
Definition: checkasm.h:198
CheckasmConfig::verbose
int verbose
Enable verbose output.
Definition: checkasm.h:246