- Simulate IPC3 and IPC4 SOF versions with run of set of processing components based on desired topology.
- Supports arbitrary multi-pipeline DAG topologies, including linear chains,
1-to-N fan-out (e.g., crossover), N-to-1 fan-in (e.g., AEC reference + mic,
deepbuffer + main playback mixing), diamond graphs,
module-copier(SND_SOC_TPLG_DAPM_BUFFER), and concurrent multi-PCM playback and capture. - Multi-core and multi-threaded execution on host CPUs (
pthread+pthread_setaffinity_np) honoring topologycore/core_idassignments for both Low Latency (LL) pipelines and Data Processing (DP) modules. - Replaces host and dai components with file I/O with raw binary S16_LE/S24_LE/S32_LE or text format files for audio waveforms.
- Much faster than real-time execution in native build, e.g. x86 on Linux for efficient validation usage.
- With xtensa DSP build offers cycles accurate simulated environment execution. And also with options for simulation speed vs. model accuracy.
- Allows easy use of conventional debugger, profiler, leak and memory check tools usage for DSP firmware code.
sof-testbench4 parses the full topology widget, route, and PCM lists and constructs the active subgraph selected via -p <pipeline1,pipeline2,...>:
- Multi-Source / Multi-Sink Discovery: Automatically discovers all active
AIF_IN(playback host),AIF_OUT(capture host),DAI_IN(playback DAI), andDAI_OUT(capture DAI) endpoints across enabled pipelines and binds them in order to the comma-separated-iinput files and-ooutput files. - Pin Binding & Sink Formats: Parses
SOF_TKN_COMP_INPUT_PIN_BINDING_WNAMEandSOF_TKN_COMP_OUTPUT_PIN_BINDING_WNAMEtuples to assign exact source and destination queue IDs (src_queue_id,dst_queue_id) for multi-pin modules (such ascrossover,mixin/mixout,google-rtc-audio-processing, and multi-sinkcopiers), and sendsSOF_IPC4_COPIER_MODULE_CFG_PARAM_SET_SINK_FORMATIPCs for non-zero output pins. - DAG Traversal: Prepares, sets up, binds, triggers, and tears down branching and merging pipeline graphs without duplicate widget initialization or double unbinding.
sof-testbench4 supports up to CONFIG_CORE_COUNT=8 virtual DSP cores (CONFIG_CROSS_CORE_STREAM=y) mapped onto host CPU cores via sched_getaffinity and pthread_setaffinity_np:
- Topology Core Assignment:
- Pipelines (
SND_SOC_TPLG_DAPM_SCHEDULER) useSOF_TKN_SCHED_CORE(core) andSOF_TKN_SCHED_PRIORITY(priority), propagated viaSOF_IPC4_GLB_CREATE_PIPELINE. - Widgets use
SOF_TKN_COMP_CORE_ID(core_id) andSOF_TKN_COMP_SCHED_DOMAIN(LLvs.DP), propagated viaSOF_IPC4_MOD_INIT_INSTANCE. LL widgets inherit their parent pipeline'score_id, while DP widgets can reside on any DSP core independent of their parent LL pipeline.
- Pipelines (
- Per-Core LL Worker Threads (
ll_schedule_pthread.c):- Each active DSP core
c(0 .. CONFIG_CORE_COUNT - 1) spawns a dedicated persistentpthreadworker pinned to host CPUc % num_allowed_host_cpuswith thread-localcpu_get_id() == c. - On each 1 ms tick (
schedule_ll_run_tasks()), all active LL core worker threads run their core's queued LL pipeline tasks concurrently in parallel across host CPU cores and synchronize at the end of the LL cycle before triggering the DP scheduler.
- Each active DSP core
- Per-Module DP Worker Threads (
dp_schedule_pthread.c):- Each Data Processing (DP) module (
COMP_PROCESSING_DOMAIN_DP) runs in its own dedicatedpthreadpinned to the host CPU core corresponding to the module's topologycore_id. - Cross-core and same-core LL-to-DP and DP-to-LL connections communicate through lock-free single-producer single-consumer (SPSC) shared
ring_bufferinstances.
- Each Data Processing (DP) module (
- Xtensa Simulator & Single-Threaded C Library Partitioning (
ll_schedule.c/dp_schedule.c):- When built for the Xtensa simulator (
xt-runviascripts/rebuild-testbench.sh -p <platform>, or manually with-DTESTBENCH_XTENSA_SIM=ON), CMake automatically selects the pure standard-C cooperative schedulers (ll_schedule.canddp_schedule.c) instead ofll_schedule_pthread.canddp_schedule_pthread.c. - This eliminates dependencies on
<pthread.h>,-lpthread,<sched.h>, andclock_gettimethat are unavailable in the Xtensa newlib (-mlsp=sim) runtime, while executing DP modules synchronously insidescheduler_dp_ll_tick()so their instruction cycles are included inXT_RSR_CCOUNT()profiling.
- When built for the Xtensa simulator (
sof-testbench4 instruments every DSP core's LL and DP schedulers, every pipeline walk (pipeline_copy()), and every LL (comp_copy()) and DP (dp_task_run()) module execution:
-
Per-Core LL & DP Scheduler Telemetry: Tracks LL tick counts, active LL tasks, LL average/peak/total DSP cycles and KCPS, DP thread run counts, active DP threads, DP average/peak/total DSP cycles and KCPS, and combined core utilization (
total_util_x100) on every DSP core (0 .. CONFIG_CORE_COUNT - 1). - Per-Pipeline Telemetry: Tracks copy iterations, priority, period, core assignment, LL and DP module counts, average/peak/total cycles, KCPS, and XRUN counts for each active pipeline.
-
Per-Module Scheduling & Buffer Entry/Exit Telemetry:
- Tracks
iterations,last/avg/peak/total_cycles,avg/peak_kcps,ibs,obs,cpcbudget andcpc_violations, plus LL ring-buffer sync iterations and cycles for DP modules. - On entry (before processing) and exit (after processing) of every module's
copy()/dp_task_run()call, captures for each input (producer) and output (consumer) pin:- Primary LL
comp_bufferfill levels (entry_avail_bytes,entry_free_bytes,exit_avail_bytes,exit_free_bytes) and secondary DPring_bufferfill levels (dp_ring_size,dp_ring_entry_avail,dp_ring_exit_avail). - Exact bytes consumed/produced (
last_bytes_transferred,total_bytes_transferred). - Signal levels in
0.01 dBFS(entry_rms_dbfs_x100,entry_peak_dbfs_x100,exit_rms_dbfs_x100,exit_peak_dbfs_x100) and rolling S16-normalized sample taps (entry_samples[64],exit_samples[64]).
- Primary LL
- Tracks
-
CLI & Remote Exposure: Printed automatically at the end of every testbench run, exposed in SRAM Windows 2 & 3 and
SOF_NET_OP_TELEM_SNAPSHOT, and queryable live viasof-remote shell "sched-telem"andsof-remote shell "mod-buffers [comp_id|name]". -
Accurate CPC, Core Frequency & SRAM/DRAM Workload Execution Time Simulation:
- Enabled via
-w <0|1|2|off|virtual|realtime>,-F <freq_mhz | core:freq_mhz,...>, and-M <sram|dram[:penalty_x100[:cycles_per_word]]>or dynamically over TCP viaSOF_NET_OP_WORKLOAD_SIM_CFG(0x0029) andsof-remote shell "workload-sim ...". - Computes module cycle consumption from each module's topology
SOF_TKN_COMP_CPC(base_cfg.cpc, per-module override, or calibrated module-type CPC), scales cycles by memory residency (SRAM1.00x vsDRAMcache/bus stall multiplier + per-word transfer penalty), and computes execution time ($T_{\text{exec}} = \text{cycles} / f_{\text{core}}$ ), core utilization %, and 1 ms LL tick deadline overruns against each core's target clock frequency. - Supports both fast virtual cycle/time accounting (
-w 1/virtual) and real-time wall-clock pacing (-w 2/realtime).
- Enabled via
sof-testbench4 exposes the sof-remote TCP binary framing protocol (SOF_NET_MAGIC = 0x534F4652 'SOFR', SOF_NET_VERSION = 1, default TCP port 9998) via -S <port> and -W:
- Supported Opcodes:
SOF_NET_OP_PING,SOF_NET_OP_GET_INFO,SOF_NET_OP_PM_CTL(query,release/D3 pause,wake/D0 resume)SOF_NET_OP_IPC_TX(direct IPC4 message dispatch) andSOF_NET_OP_IPC_LARGE_CFG(BaseFW params 9, 12, 14, 15, 17, 18, 30 and live moduleLARGE_CONFIG_GET/SET)SOF_NET_OP_WIN_INFO,SOF_NET_OP_WIN_READ,SOF_NET_OP_WIN_WRITE,SOF_NET_OP_WINSTREAM_IO(emulated SRAM Windows 0–3 and debug slots)SOF_NET_OP_TELEM_SNAPSHOT(single-RPC composite telemetry snapshot consumed bytools/softop/softop.pyandsof-remote telem)SOF_NET_OP_WORKLOAD_SIM_CFG(0x0029, query/configure CPC workload execution simulation mode, SRAM/DRAM residency, DRAM stall multiplier, per-core target clock frequencies, and per-module CPC/memory overrides viasof-remote workload-sim ...)SOF_NET_OP_SHELL_EXEC(info,pipelines,modules,tplg-load <file> [p1,p2,...],ppl-create,ppl-state,ppl-delete,mod-bind,mod-unbind,mod-delete,controls, liveamixer cset ..., livesof-ctl ...,stats,heap,sched-telem,sched-telem-reset,workload-sim [status|enable|disable|freq|mem|mod|reset],mod-buffers [id|name],kernel cycles,kernel threads,pause,resume,step [N],loglevel <0..4>,quit)SOF_NET_OP_LLEXT_LOAD(upload and load dynamic.so/.llextmodule images viadlopen/ LLEXT table registration)SOF_NET_OP_PROBE_CTL(enumerate and read inter-componentstruct comp_bufferaudio streams as probe points)SOF_NET_OP_PCM_CTL(start-tone,stop-tone,status, andcapturefrom output streams)
- Tick-Boundary Synchronization: All network RPCs that inspect or mutate IPC/module/topology state acquire
g_tb_lockbetween 1 ms LL ticks (tb_remote_tick_begin()/tb_remote_tick_end()), guaranteeing thread safety across multi-core LL and DP worker threads.
Usage: sof-testbench4 <options> -i <input_file1,input_file2,...> -o <output_file1,output_file2,...>
Options for processing:
-t <topology file>
-i <input_file1,input_file2,...> (up to 16 comma-separated input files)
-o <output_file1,output_file2,...> (up to 16 comma-separated output files)
Options to control test:
-d <level> Sets the traces print level:
0 all traces are suppressed
1 shows error traces
2 shows warning traces and previous
3 shows info traces and previous
4 shows debug traces and previous, plus other testbench debug messages
-p <pipeline1,pipeline2,...> (up to 16 comma-separated pipeline IDs, default: 1)
-C <number of copy() iterations>
-P <number of dynamic pipeline iterations>
-s <script file to set controls, with amixer and sleep commands>
-S <port> Start sof-remote TCP server on <port> (default port: 9998)
-W Keep testbench running continuously for remote network control
-w <0|1|2|off|virtual|realtime> Enable CPC workload execution time simulation
-F <freq_mhz | core:freq_mhz,...> Set target DSP core clock frequency in MHz
-M <sram|dram[:penalty_x100[:cycles_per_word]]> Set workload memory domain
Options for input and output format override:
-b <input_format>, S16_LE, S24_LE, or S32_LE
-c <input channels>
-n <output channels>
-r <input rate>
-R <output rate>
Help:
-h
Before running the SOF testbench, install the required dependencies:
sudo apt install valgrind octave-signal octave # For Ubuntu/Debian
sudo dnf install valgrind octave-signal octave # For Fedora
The simplest way to build and execute testbench is with supplied scripts. It executes a simple chirp waveform test for a number of processing components. Corrupted audio or failure in execution or a memory violation results to fail of test.
cd $SOF_WORKSPACE/sof
scripts/build-tools.sh
scripts/rebuild-testbench.sh
scripts/host-testbench.sh
As an example, process a wav file and listen it. The example processing component is IIR equalizer. The wav file is first converted with sox to raw 32 bit 48 kHz stereo format, then processed by testbench, converted back to wav.
The example processes the playback direction of topology sof-hda-benchmark-eqiir32.tplg with IIR component. The playback direction in the component test topologies consists of host pipeline 1 and dai pipeline 2. Therefore the command line has option -p 1,2.
cd $SOF_WORKSPACE/sof
sox --encoding signed-integer /usr/share/sounds/alsa/Front_Left.wav -L -r 48000 -c 2 -b 32 in.raw
tools/testbench/build_testbench/install/bin/sof-testbench4 -r 48000 -c 2 -b S32_LE \
-p 1,2 -t tools/build_tools/topology/topology2/development/sof-hda-benchmark-eqiir32.tplg \
-i in.raw -o out.raw
sox --encoding signed-integer -L -r 48000 -c 2 -b 32 out.raw out.wav
aplay out.wav
To test capture use -p 3,4 with same topologies. To run both directions, use -p 1,2,3,4 and provide multiple input and output files separated with comma. Use e.g. -i i1.raw,i2.raw -o o1.raw,o2.raw.
# 1-to-2 Fan-Out (2-way Crossover across pipelines 1, 101, 102)
tools/testbench/build_testbench/install/bin/sof-testbench4 -r 48000 -R 48000 -c 2 -n 2 -b S32_LE \
-t tools/build_tools/topology/topology2/development/sof-tgl-nocodec-crossover-2way.tplg \
-p 1,101,102 -i in.raw -o out_sink1.raw,out_sink2.raw
# 2-to-1 Fan-In (Google RTC AEC capture + playback reference across pipelines 7, 8, 12)
tools/testbench/build_testbench/install/bin/sof-testbench4 -r 16000 -R 16000 -c 2 -n 2 -b S16_LE \
-t tools/build_tools/topology/topology2/development/sof-tgl-nocodec-rtcaec.tplg \
-p 7,8,12 -i mic_in.raw,ref_in.raw -o aec_out.raw
# Multiple DP Modules in Dedicated Threads (Playback + Capture Phase Vocoder)
tools/testbench/build_testbench/install/bin/sof-testbench4 -r 48000 -R 48000 -c 2 -n 2 -b S32_LE \
-t tools/build_tools/topology/topology2/development/sof-hda-benchmark-phase_vocoder32.tplg \
-p 1,2,3,4 -i pb_in.raw,cap_in.raw -o pb_out.raw,cap_out.raw
# Multi-Core LL & Cross-Core DP Execution (Core 0 Capture LL, Core 1 DP SRC threads, Core 2 Playback/Capture LL)
tools/testbench/build_testbench/install/bin/sof-testbench4 -r 48000 -R 48000 -c 2 -n 2 -b S32_LE \
-t tools/build_tools/topology/topology2/development/sof-mtl-nocodec-dp-core-test.tplg \
-p 5,6,7,8,11,12 -i pb_in.raw,cap1_in.raw,cap2_in.raw -o pb_out.raw,cap1_out.raw,cap2_out.raw
# Interactive Remote Server Mode (connect with sof-remote or tools/softop/softop.py)
tools/testbench/build_testbench/sof-testbench4 \
-t tools/build_tools/topology/topology2/target/sof-ipc4-tplg/sof-hda-generic.tplg \
-p 1,2 -S 9998 -W
# In another terminal, query and control testbench over TCP:
tools/sof-remote-server/sof-remote -H 127.0.0.1 -p 9998 info
tools/sof-remote-server/sof-remote -H 127.0.0.1 -p 9998 telem
tools/sof-remote-server/sof-remote -H 127.0.0.1 -p 9998 cards
tools/sof-remote-server/sof-remote -H 127.0.0.1 -p 9998 pcm-caps
tools/sof-remote-server/sof-remote -H 127.0.0.1 -p 9998 dapm /tmp/tb_dapm.dot
tools/sof-remote-server/sof-remote -H 127.0.0.1 -p 9998 compr caps
tools/sof-remote-server/sof-remote -H 127.0.0.1 -p 9998 kctl list
tools/sof-remote-server/sof-remote -H 127.0.0.1 -p 9998 kctl get 1
tools/sof-remote-server/sof-remote -H 127.0.0.1 -p 9998 kctl set 1 28 28
tools/sof-remote-server/sof-remote -H 127.0.0.1 -p 9998 shell "pipelines"
tools/sof-remote-server/sof-remote -H 127.0.0.1 -p 9998 shell "sched-telem"
tools/sof-remote-server/sof-remote -H 127.0.0.1 -p 9998 shell "mod-buffers"
tools/sof-remote-server/sof-remote -H 127.0.0.1 -p 9998 shell "controls"
tools/sof-remote-server/sof-remote -H 127.0.0.1 -p 9998 shell "amixer cset name=\"Pre Mixer Analog Playback Volume\" 20,20"
tools/sof-remote-server/sof-remote -H 127.0.0.1 -p 9998 pcm start-tone hw:0,0 1000
tools/sof-remote-server/sof-remote -H 127.0.0.1 -p 9998 pcm capture hw:0,0 100
python3 tools/softop/softop.py --remote 127.0.0.1:9998
tools/sof-remote-server/sof-remote -H 127.0.0.1 -p 9998 shell "quit"
tools/testbench/run_test_suite.sh executes 67 automated test cases across 5 progressive tiers:
- Tier 1 (46 tests): All 26 built-in SOF audio processing modules (
dcblock,drc,drc_multiband,dolby-dax,eqfir,eqiir,gain,igo_nr,level_multiplier,mfcc,mfccmel,micsel,micsel_multich,rtnr,sound_dose,tdfb,template_comp,aria,src,src_lite,asrc,crossover,google_ctc_audio_processing,google_rtc_audio_processing,phase_vocoder,stft_process,mixin/mixout,host-copier/dai-copier/module-copier) acrossS32_LE,S24_LE,S16_LE, rate conversion (44.1 kHz <-> 48 kHz), and multi-channel (4ch -> 2ch). - Tier 2 (7 tests): Simple to complex multi-pipeline DAG topologies (3x HDMI passthrough, 3-pipeline cascaded
aria->gain->mixin->mixout, 6-module EFX chain, 1-to-2 fan-out crossover, 2-to-1 fan-in Google RTC AEC, 4ch DMICtdfb->drc->eqiir->gain, and 11-pipeline 6-input/5-output concurrentsof-hda-generic.tplg). - Tier 3 (6 tests): Combinations of Low-Latency (
LL) and Data Processing (DP) modules (single-thread DPphase_vocoder, full-duplex dual-thread DPphase_vocoderandstft_process192/48,512/128,1536/240, and 6-pipeline LL + 2 DPsrcthreads). - Tier 4 (6 tests): Multi-Core LL and Cross-Core DP execution across DSP Cores 0, 1, and 2 (
sof-mtl-nocodec.tplg,sof-hda-src-generic-dp.tplg,sof-mtl-nocodec-dp-core-test.tplg,sof-lnl-nocodec-dp-core-test.tplg,sof-ptl-nocodec-dp-core-test.tplg, andsof-mtl-rt1019-rt5682-dax.tplg). - Tier 5 (2 tests): Runtime control scripts (
-swithamixerandsof-ctl) and liveSOFRv1 TCP remote control & 3-core telemetry inspection (-S <port> -Wwithsof-remote).
# Run the complete 67-test suite
tools/testbench/run_test_suite.sh
# Run a single tier (1..5) or filter by regex
tools/testbench/run_test_suite.sh --tier 4
tools/testbench/run_test_suite.sh --filter "mcore|fanout|fanin"
# Or run via CTest from the testbench build directory
ctest --test-dir tools/testbench/build_testbench --output-on-failure
The testbench supports shell script like amixer and sleep commands for the controls. Create e.g. this script file as controls.sh:
#!/bin/sh
# Example test sequence for DRC and volume components
amixer -c0 cset name='Post Mixer Analog Playback DRC switch' off
amixer -c0 cset name='Post Mixer Analog Playback Volume' 40,30
sleep 1
amixer -c0 cset name='Post Mixer Analog Playback Volume' 0
sleep 1
amixer -c0 cset name='Post Mixer Analog Playback Volume' 45
Then generarate sine wave (997 Hz, -3 dB level, 3 seconds) with sox and check the impact to processed signal with next commands:
sox -n --encoding signed-integer -L -r 48000 -c 2 -b 32 in.raw synth 3 sine 997 norm -3
tools/testbench/build_testbench/install/bin/sof-testbench4 -r 48000 -c 2 -b S32_LE -p 1,2 \
-t tools/build_tools/topology/topology2/production/sof-hda-generic.tplg \
-i in.raw -o out.raw -s controls.sh
sox --encoding signed-integer -L -r 48000 -c 2 -b 32 out.raw out.wav
As second example apply in one second intervals bytes control blobs for IIR equalizer. The impact is easiest to hear with pink noise signal. Create the control script below and run the following commands to create the input, run testbench, and convert to wav for examining the output.
#!/bin/sh
# Example test sequence for IIR equalizer, switch other processing off
amixer -c0 cset name='Post Mixer Analog Playback DRC switch' off
amixer -c0 cset name='Post Mixer Analog Playback Volume' 45
sof-ctl -c name='Post Mixer Analog Playback FIR Eq bytes' -s tools/ctl/ipc4/eq_fir/pass.txt
sof-ctl -c name='Post Mixer Analog Playback IIR Eq bytes' -s tools/ctl/ipc4/eq_iir/pass.txt
sleep 1
sof-ctl -c name='Post Mixer Analog Playback IIR Eq bytes' -s tools/ctl/ipc4/eq_iir/loudness.txt
sleep 1
sof-ctl -c name='Post Mixer Analog Playback IIR Eq bytes' -s tools/ctl/ipc4/eq_iir/bandpass.txt
sleep 1
sof-ctl -c name='Post Mixer Analog Playback IIR Eq bytes' -s tools/ctl/ipc4/eq_iir/bassboost.txt
sleep 1
sof-ctl -c name='Post Mixer Analog Playback IIR Eq bytes' -s tools/ctl/ipc4/eq_iir/highpass_50hz_0db_48khz.txt
sox -n --encoding signed-integer -L -r 48000 -c 2 -b 32 in.raw synth 5 pinknoise norm -20
tools/testbench/build_testbench/install/bin/sof-testbench4 -r 48000 -c 2 -b S32_LE -p 1,2 \
-t tools/build_tools/topology/topology2/production/sof-hda-generic.tplg \
-i in.raw -o out.raw -s controls.sh
sox --encoding signed-integer -L -r 48000 -c 2 -b 32 out.raw out.wav
The scripts/sof-testbench-helper.sh simplifies the task. See the help text shown with option -h.
Usage: scripts/sof-testbench-helper.sh <options>
Options
-b <bits>, default 32
-c <channels>, default 2
-h shows this text
-i <input wav>, default /usr/share/sounds/alsa/Front_Center.wav
-k keep temporary files in /tmp
-m <module>, default gain
-n <pipelines>, default 1,2
-o <output wav>, default none
-p <profiling result text>, use with -x, default none
-r <rate>, default 48000
-t <force topology>, default none, e.g. production/sof-hda-generic.tplg
-v runs with valgrind, not available with -x
-x runs testbench with xt-run simulator
Example: run DRC with xt-run with profiling (slow)
scripts/sof-testbench-helper.sh -x -m drc -p profile-drc32.txt
Example: process with native build DRC file Front_Center.wav (fast)
scripts/sof-testbench-helper.sh -m drc -i /usr/share/sounds/alsa/Front_Center.wav \
-o ~/tmp/Front_Center_with_DRC.wav
Example: check component eqiir with valgrind
scripts/sof-testbench-helper.sh -v -m eqiir
The above manual run can be executed with single command. The -i could be omitted as well since the ALSA clip is the default input wav.
scripts/sof-testbench-helper.sh -m eqiir -i /usr/share/sounds/alsa/Front_Center.wav -o out.wav
To run the same example with Xtensa simulator (MTL platform), set up the build environment, build, and execute with additional -x option. An MCPS estimate for pipeline execution is printed in the end of run than can be useful when checking impact of code optimizations. Note that the cycles of testbench file component that replaces host-copier and dai-copier are excluded.
export XTENSA_TOOLS_ROOT=~/xtensa/XtDevTools
export ZEPHYR_TOOLCHAIN_VARIANT=xt-clang
scripts/rebuild-testbench.sh -p mtl
scripts/sof-testbench-helper.sh -x -m eqiir -i /usr/share/sounds/alsa/Front_Center.wav -o out.wav
When profiling add to above run script option -p, e.g. (can omit output wav conversion).
scripts/sof-testbench-helper.sh -x -m eqiir -p profile-eqiir.txt
less profile-eqiir.txt
The output of xt-gprof looks like
Flat profile:
self total
cumulative self cycles cycles
% cycles cycles calls /call /call name
(K) (K) (K) (K)
56.73 10144.51 10144.51 137088 0.07 0.07 iir_df1
12.91 12453.23 2308.72 1428 1.62 8.72 eq_iir_s32_default
3.23 13031.59 578.36 4290 0.13 3.61 module_adapter_copy
2.22 13429.03 397.44 2860 0.14 0.67 file_process
2.14 13811.37 382.34 3178 0.12 0.13 memmove
To profile a set of processing components in SOF there is example script sof-testbench-build-profile.sh. It profiles also two hda-generic topologies with multiple SOF components in it. The help for the script is shown with option -h:
Usage: scripts/sof-testbench-build-profile.sh <options>
-d <directory> directory to place code profiling reports
-h shows this text
-p <platform> sets platform for scripts/rebuild-testbench.sh
It can be run for platform mtl with command
scripts/sof-testbench-build-profile.sh -p mtl
The profiling reports and component run logs (with MCPS) can be found from default directory tools/testbench/profile.
This step needs Matlab or Octave tool with signal processing package. A number of tests is performed for IIR equalizer component as example. The script opens plot windows and outputs a text report in the end. A simple pass/fail criteria is used to report a verdict of the test run.
cd $SOF_WORKSPACE/sof/tools/test/audio
octave -q --eval "pkg load signal io; [n_fail]=process_test('eq-iir', 32, 32, 48000, 1, 1); input('Press ENTER'); exit(n_fail)"
See from interactive Octave shell command "help process_test" the explanation for the test run parameters.
The testbench build is by default IPC4. The IPC version can be changed by applying next patch:
diff --git a/src/arch/host/configs/library_defconfig b/src/arch/host/configs/library_defconfig
index 1b9483ffe..5c944d292 100644
--- a/src/arch/host/configs/library_defconfig
+++ b/src/arch/host/configs/library_defconfig
@@ -22,8 +22,8 @@ CONFIG_COMP_VOLUME=y
CONFIG_COMP_VOLUME_LINEAR_RAMP=y
CONFIG_COMP_VOLUME_WINDOWS_FADE=y
CONFIG_DEBUG_MEMORY_USAGE_SCAN=n
-CONFIG_IPC_MAJOR_3=n
-CONFIG_IPC_MAJOR_4=y
+CONFIG_IPC_MAJOR_3=y
+CONFIG_IPC_MAJOR_4=n
CONFIG_LIBRARY=y
CONFIG_MATH_IIR_DF2T=y
As an example, process a wav file and listen it. The example processing component is DC block. The wav file is first converted with sox to raw 32 bit 48 kHz stereo format, then processed by testbench, converted back to wav.
cd $SOF_WORKSPACE/sof
scripts/rebuild-testbench.sh
scripts/build-tools.sh -t
sox --encoding signed-integer /usr/share/sounds/alsa/Front_Left.wav -L -r 48000 -c 2 -b 32 in.raw
tools/testbench/build_testbench/install/bin/sof-testbench3 -r 48000 -R 48000 -c 2 -n 2 -b S32_LE \
-t tools/build_tools/test/topology/test-playback-ssp5-mclk-0-I2S-dcblock-s32le-s32le-48k-24576k-codec.tplg \
-i in.raw -o out.raw
sox --encoding signed-integer -L -r 48000 -c 2 -b 32 out.raw out.wav
aplay out.wav
The testbench binary can be debugged and profiled with native executable tools like gdb, ddd (GUI for gdb), gprof, and valgrind.
The example is with IPC3 build for Intel MTL platform. The similar commands would work with IPC4 build also, with changed topology for IPC4. This needs access to Cadence Xplorer toolchain with the core confiration for the platform.
cd $SOF_WORKSPACE/sof
export XTENSA_TOOLS_ROOT=~/xtensa/XtDevTools
export ZEPHYR_TOOLCHAIN_VARIANT=xt-clang
scripts/rebuild-testbench.sh -p mtl
source tools/testbench/build_xt_testbench/xtrun_env.sh
Next the testbench is run with xt-run simulator. The example component is dynamic range processing (DRC). For proling data generate use option --profile. Note that this is a lot slower than native run. An 1s extract of a pink noise file is used as example.
sox --encoding signed-integer /usr/share/sounds/alsa/Noise.wav -L -r 48000 -c 2 -b 32 in.raw trim 0.0 1.0
$XTENSA_PATH/xt-run --profile=profile.out tools/testbench/build_xt_testbench/testbench \
-r 48000 -R 48000 -c 2 -n 2 -b S32_LE \
-t tools/build_tools/test/topology/test-playback-ssp5-mclk-0-I2S-drc-s32le-s32le-48k-24576k-codec.tplg \
-i in.raw -o out.raw 2> trace.txt
Then convert the profiler data to readable format and check it.
$XTENSA_PATH/xt-gprof tools/testbench/build_xt_testbench/testbench profile.out > example_profile.txt
less example_profile.txt