Skip to content

Commit 13e8226

Browse files
committed
Tools: Testbench: Cleanup and move common and IPC3 specific functions
The helper functions are moved from testbench.c to common_test.c and common_test_ipc3.c as preparation to add IPC4 support. The file components are looked up in test setup to arrays to ease finding them in test run and control ending the test. The parse string for command getopt() is fixed to match the supported options. The testbench parameter struct is changed to dynamically allocated and zeroed by calloc(). It also avoids issues found with valgrind about uninitialized. Signed-off-by: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com>
1 parent c7b090a commit 13e8226

7 files changed

Lines changed: 617 additions & 548 deletions

File tree

tools/testbench/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ set(default_asoc_h "/usr/include/alsa/sound/uapi/asoc.h")
1111

1212
add_executable(testbench
1313
testbench.c
14+
common_test.c
1415
common_test_ipc3.c
1516
file.c
1617
topology_ipc3.c

tools/testbench/common_test.c

Lines changed: 252 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,252 @@
1+
// SPDX-License-Identifier: BSD-3-Clause
2+
//
3+
// Copyright(c) 2018-2024 Intel Corporation. All rights reserved.
4+
5+
#include <sof/audio/module_adapter/module/generic.h>
6+
#include <platform/lib/ll_schedule.h>
7+
#include <sof/audio/component.h>
8+
#include <sof/ipc/topology.h>
9+
#include <sof/lib/notifier.h>
10+
11+
#include <stdint.h>
12+
#include <stdio.h>
13+
#include <stdlib.h>
14+
#include <time.h>
15+
16+
#include "testbench/common_test.h"
17+
#include "testbench/trace.h"
18+
#include "testbench/file.h"
19+
20+
#if defined __XCC__
21+
#include <xtensa/tie/xt_timer.h>
22+
#endif
23+
24+
int tb_load_topology(struct testbench_prm *tp)
25+
{
26+
struct tplg_context *ctx = &tp->tplg;
27+
int ret;
28+
29+
/* setup the thread virtual core config */
30+
memset(ctx, 0, sizeof(*ctx));
31+
ctx->comp_id = 1;
32+
ctx->core_id = 0;
33+
ctx->sof = sof_get();
34+
ctx->tplg_file = tp->tplg_file;
35+
36+
/* parse topology file and create pipeline */
37+
ret = tb_parse_topology(tp);
38+
if (ret < 0)
39+
fprintf(stderr, "error: parsing topology\n");
40+
41+
tb_debug_print("topology parsing complete\n");
42+
return ret;
43+
}
44+
45+
static int tb_find_file_helper(struct testbench_prm *tp, struct file_comp_lookup fcl[],
46+
int num_files)
47+
{
48+
struct ipc_comp_dev *icd;
49+
struct processing_module *mod;
50+
struct file_comp_data *fcd;
51+
int i;
52+
53+
for (i = 0; i < num_files; i++) {
54+
if (!tb_is_pipeline_enabled(tp, fcl[i].pipeline_id)) {
55+
fcl[i].id = -1;
56+
continue;
57+
}
58+
59+
icd = ipc_get_comp_by_id(sof_get()->ipc, fcl[i].id);
60+
if (!icd) {
61+
fcl[i].state = NULL;
62+
continue;
63+
}
64+
65+
if (!icd->cd) {
66+
fprintf(stderr, "error: null cd.\n");
67+
return -EINVAL;
68+
}
69+
70+
mod = comp_mod(icd->cd);
71+
if (!mod) {
72+
fprintf(stderr, "error: null module.\n");
73+
return -EINVAL;
74+
}
75+
fcd = module_get_private_data(mod);
76+
fcl[i].state = &fcd->fs;
77+
}
78+
79+
return 0;
80+
}
81+
82+
int tb_find_file_components(struct testbench_prm *tp)
83+
{
84+
int ret;
85+
86+
/* file read */
87+
ret = tb_find_file_helper(tp, tp->fr, tp->input_file_num);
88+
if (ret < 0)
89+
return ret;
90+
91+
/* file write */
92+
ret = tb_find_file_helper(tp, tp->fw, tp->output_file_num);
93+
return ret;
94+
}
95+
96+
static bool tb_is_file_component_at_eof(struct testbench_prm *tp)
97+
{
98+
int i;
99+
100+
for (i = 0; i < tp->input_file_num; i++) {
101+
if (!tp->fr[i].state)
102+
continue;
103+
104+
if (tp->fr[i].state->reached_eof)
105+
return true;
106+
}
107+
108+
for (i = 0; i < tp->output_file_num; i++) {
109+
if (!tp->fw[i].state)
110+
continue;
111+
112+
if (tp->fw[i].state->reached_eof || tp->fw[i].state->write_failed)
113+
return true;
114+
}
115+
116+
return false;
117+
}
118+
119+
void tb_show_file_stats(struct testbench_prm *tp, int pipeline_id)
120+
{
121+
struct ipc_comp_dev *icd;
122+
struct comp_dev *dev;
123+
struct processing_module *mod;
124+
struct file_comp_data *fcd;
125+
int i;
126+
127+
for (i = 0; i < tp->input_file_num; i++) {
128+
if (tp->fr[i].id < 0 || tp->fr[i].pipeline_id != pipeline_id)
129+
continue;
130+
131+
icd = ipc_get_comp_by_id(sof_get()->ipc, tp->fr[i].id);
132+
if (!icd)
133+
continue;
134+
135+
dev = icd->cd;
136+
mod = comp_mod(dev);
137+
fcd = module_get_private_data(mod);
138+
printf("file %s: id %d: type %d: samples %d copies %d\n",
139+
fcd->fs.fn, dev->ipc_config.id, dev->drv->type, fcd->fs.n,
140+
fcd->fs.copy_count);
141+
}
142+
143+
for (i = 0; i < tp->output_file_num; i++) {
144+
if (tp->fw[i].id < 0 || tp->fw[i].pipeline_id != pipeline_id)
145+
continue;
146+
147+
icd = ipc_get_comp_by_id(sof_get()->ipc, tp->fw[i].id);
148+
if (!icd)
149+
continue;
150+
151+
dev = icd->cd;
152+
mod = comp_mod(dev);
153+
fcd = module_get_private_data(mod);
154+
printf("file %s: id %d: type %d: samples %d copies %d\n",
155+
fcd->fs.fn, dev->ipc_config.id, dev->drv->type, fcd->fs.n,
156+
fcd->fs.copy_count);
157+
}
158+
}
159+
160+
bool tb_is_pipeline_enabled(struct testbench_prm *tp, int pipeline_id)
161+
{
162+
int i;
163+
164+
for (i = 0; i < tp->pipeline_num; i++) {
165+
if (tp->pipelines[i] == pipeline_id)
166+
return true;
167+
}
168+
169+
return false;
170+
}
171+
172+
bool tb_schedule_pipeline_check_state(struct testbench_prm *tp)
173+
{
174+
uint64_t cycles0, cycles1;
175+
176+
tb_getcycles(&cycles0);
177+
178+
schedule_ll_run_tasks();
179+
180+
tb_getcycles(&cycles1);
181+
tp->total_cycles += cycles1 - cycles0;
182+
183+
/* Check if all file components are running */
184+
return tb_is_file_component_at_eof(tp);
185+
}
186+
187+
struct ipc_data {
188+
struct ipc_data_host_buffer dh_buffer;
189+
};
190+
191+
void tb_free(struct sof *sof)
192+
{
193+
struct schedule_data *sch;
194+
struct schedulers **schedulers;
195+
struct list_item *slist, *_slist;
196+
struct notify **notify = arch_notify_get();
197+
struct ipc_data *iipc;
198+
199+
free(*notify);
200+
201+
/* free all scheduler data */
202+
schedule_free(0);
203+
schedulers = arch_schedulers_get();
204+
list_for_item_safe(slist, _slist, &(*schedulers)->list) {
205+
sch = container_of(slist, struct schedule_data, list);
206+
free(sch);
207+
}
208+
free(*arch_schedulers_get());
209+
210+
/* free IPC data */
211+
iipc = sof->ipc->private;
212+
free(sof->ipc->comp_data);
213+
free(iipc->dh_buffer.page_table);
214+
free(iipc);
215+
free(sof->ipc);
216+
}
217+
218+
/* print debug messages */
219+
void tb_debug_print(char *message)
220+
{
221+
if (host_trace_level >= LOG_LEVEL_DEBUG)
222+
printf("debug: %s", message);
223+
}
224+
225+
/* enable trace in testbench */
226+
void tb_enable_trace(unsigned int log_level)
227+
{
228+
host_trace_level = log_level;
229+
if (host_trace_level)
230+
tb_debug_print("trace print enabled\n");
231+
else
232+
tb_debug_print("trace print disabled\n");
233+
}
234+
235+
void tb_gettime(struct timespec *td)
236+
{
237+
#if !defined __XCC__
238+
clock_gettime(CLOCK_MONOTONIC, td);
239+
#else
240+
td->tv_nsec = 0;
241+
td->tv_sec = 0;
242+
#endif
243+
}
244+
245+
void tb_getcycles(uint64_t *cycles)
246+
{
247+
#if defined __XCC__
248+
*cycles = XT_RSR_CCOUNT();
249+
#else
250+
*cycles = 0;
251+
#endif
252+
}

0 commit comments

Comments
 (0)