Tools: Testbench: Fixes for xt-xcc build and cycles counting

This patch avoids the build errors. Most of the issues are
from different types for formatted printing in gcc vs. xt-xcc.

The "__attribute__ ((fallthrough));" is not supported in xt-xcc.

The xtensa C library does not have clock_gettime() so it is
only left out from build. The cycles count and MCPS is printed
instead.

The include of dlfcn.h is not needed since the testbench no
more has dynamic libraries.

Structs within structs need to be initialized to zero in xt-xcc
with multiple brackets.

Signed-off-by: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com>
This commit is contained in:
Seppo Ingalsuo 2023-03-31 14:17:56 +03:00 committed by Kai Vehmanen
parent 11592fed5b
commit a380d21d85
7 changed files with 87 additions and 20 deletions

View File

@ -29,6 +29,10 @@
#include "testbench/trace.h"
#include <tplg_parser/topology.h>
#if defined __XCC__
#include <xtensa/tie/xt_timer.h>
#endif
/* testbench helper functions for pipeline setup and trigger */
int tb_setup(struct sof *sof, struct testbench_prm *tp)
@ -281,3 +285,22 @@ void tb_enable_trace(bool enable)
else
debug_print("trace print disabled\n");
}
void tb_gettime(struct timespec *td)
{
#if !defined __XCC__
clock_gettime(CLOCK_MONOTONIC, td);
#else
td->tv_nsec = 0;
td->tv_sec = 0;
#endif
}
void tb_getcycles(uint64_t *cycles)
{
#if defined __XCC__
*cycles = XT_RSR_CCOUNT();
#else
*cycles = 0;
#endif
}

View File

@ -617,6 +617,7 @@ static struct comp_dev *file_new(const struct comp_driver *drv,
cd->fs.write_failed = false;
cd->fs.n = 0;
cd->fs.copy_count = 0;
cd->fs.cycles_count = 0;
dev->state = COMP_STATE_READY;
return dev;
@ -803,11 +804,13 @@ static int file_copy(struct comp_dev *dev)
struct comp_buffer *buffer;
struct dai_data *dd = comp_get_drvdata(dev);
struct file_comp_data *cd = comp_get_drvdata(dd->dai);
uint64_t cycles0, cycles1;
int snk_frames;
int src_frames;
int bytes = cd->sample_container_bytes;
int ret = 0;
tb_getcycles(&cycles0);
switch (cd->fs.mode) {
case FILE_READ:
/* file component sink buffer */
@ -859,6 +862,9 @@ static int file_copy(struct comp_dev *dev)
cd->fs.reached_eof);
schedule_task_cancel(dev->pipeline->pipe_task);
}
tb_getcycles(&cycles1);
cd->fs.cycles_count += cycles1 - cycles0;
return ret;
}

View File

@ -36,6 +36,7 @@ struct tplg_context;
* into per pipeline data and per topology data structures.
*/
struct testbench_prm {
long long total_cycles;
char *tplg_file; /* topology file to use */
char *input_file[MAX_INPUT_FILE_NUM]; /* input file names */
char *output_file[MAX_OUTPUT_FILE_NUM]; /* output file names */
@ -104,4 +105,8 @@ int tb_pipeline_reset(struct ipc *ipc, struct pipeline *p);
void debug_print(char *message);
void tb_gettime(struct timespec *td);
void tb_getcycles(uint64_t *cycles);
#endif

View File

@ -11,6 +11,8 @@
#ifndef _FILE_H
#define _FILE_H
#include <stdint.h>
/**< Convert with right shift a bytes count to samples count */
#define FILE_BYTES_TO_S16_SAMPLES(s) ((s) >> 1)
#define FILE_BYTES_TO_S32_SAMPLES(s) ((s) >> 2)
@ -29,14 +31,15 @@ enum file_format {
/* file component state */
struct file_state {
char *fn;
uint64_t cycles_count;
FILE *rfh, *wfh; /* read/write file handle */
bool reached_eof;
bool write_failed;
char *fn;
int copy_count;
int n;
enum file_mode mode;
enum file_format f_format;
int copy_count;
bool reached_eof;
bool write_failed;
};
/* file comp data */

View File

@ -254,7 +254,7 @@ static void test_pipeline_get_file_stats(int pipeline_id)
time = cd->pipeline->pipe_task->start;
if (fcd->fs.copy_count == 0)
fcd->fs.copy_count = 1;
printf("file %s: id %d: type %d: samples %d copies %d total time %zu uS avg time %zu uS\n",
printf("file %s: id %d: type %d: samples %d copies %d total time %lu uS avg time %lu uS\n",
fcd->fs.fn, cd->ipc_config.id, cd->drv->type, fcd->fs.n,
fcd->fs.copy_count, time, time / fcd->fs.copy_count);
break;
@ -356,7 +356,7 @@ static int parse_input_args(int argc, char **argv, struct testbench_prm *tp)
default:
fprintf(stderr, "unknown option %c\n", option);
ret = -EINVAL;
__attribute__ ((fallthrough));
/* fallthrough */
case 'h':
print_usage(argv[0]);
exit(EXIT_SUCCESS);
@ -487,10 +487,16 @@ static int test_pipeline_start(struct testbench_prm *tp)
static bool test_pipeline_check_state(struct testbench_prm *tp, int state)
{
struct pipeline *p;
uint64_t cycles0, cycles1;
int i;
tb_getcycles(&cycles0);
schedule_ll_run_tasks();
tb_getcycles(&cycles1);
tp->total_cycles += cycles1 - cycles0;
/* Run pipeline until EOF from fileread */
for (i = 0; i < tp->pipeline_num; i++) {
p = get_pipeline_by_id(tp->pipelines[i]);
@ -522,7 +528,7 @@ static int test_pipeline_load(struct testbench_prm *tp, struct tplg_context *ctx
}
static void test_pipeline_stats(struct testbench_prm *tp,
struct tplg_context *ctx, uint64_t delta)
struct tplg_context *ctx, long long delta_t)
{
int count = 1;
struct ipc_comp_dev *icd;
@ -530,7 +536,9 @@ static void test_pipeline_stats(struct testbench_prm *tp,
struct dai_data *dd;
struct pipeline *p;
struct file_comp_data *frcd, *fwcd;
int n_in, n_out;
long long file_cycles, pipeline_cycles;
float pipeline_mcps;
int n_in, n_out, frames_out;
int i;
/* Get pointer to filewrite */
@ -566,6 +574,7 @@ static void test_pipeline_stats(struct testbench_prm *tp,
n_in = frcd->fs.n;
n_out = fwcd->fs.n;
file_cycles = frcd->fs.cycles_count + fwcd->fs.cycles_count;
/* print test summary */
printf("==========================================================\n");
@ -586,10 +595,25 @@ static void test_pipeline_stats(struct testbench_prm *tp,
printf("Output[%d] written to file: \"%s\"\n",
i, tp->output_file[i]);
}
frames_out = n_out / tp->channels_out;
printf("Input sample (frame) count: %d (%d)\n", n_in, n_in / tp->channels_in);
printf("Output sample (frame) count: %d (%d)\n", n_out, n_out / tp->channels_out);
printf("Total execution time: %zu us, %.2f x realtime\n\n",
delta, (double)((double)n_out / tp->channels_out / tp->fs_out) * 1000000 / delta);
printf("Output sample (frame) count: %d (%d)\n", n_out, frames_out);
if (tp->total_cycles) {
pipeline_cycles = tp->total_cycles - file_cycles;
pipeline_mcps = (float)pipeline_cycles * tp->fs_out / frames_out / 1e6;
printf("Total execution cycles: %lld\n", tp->total_cycles);
printf("File component cycles: %lld\n", file_cycles);
printf("Pipeline cycles: %lld\n", pipeline_cycles);
printf("Pipeline MCPS: %6.2f\n", pipeline_mcps);
if (!tp->quiet)
printf("Warning: Use -q to avoid printing to increase MCPS.\n");
}
if (delta_t)
printf("Total execution time: %lld us, %.2f x realtime\n",
delta_t, (float)frames_out / tp->fs_out * 1000000 / delta_t);
printf("\n");
}
/*
@ -602,10 +626,10 @@ static int pipline_test(struct testbench_prm *tp)
struct tplg_context ctx;
struct timespec ts;
struct timespec td0, td1;
long long delta_t;
int err;
int nsleep_time;
int nsleep_limit;
uint64_t delta;
/* build, run and teardown pipelines */
while (dp_count < tp->dynamic_pipeline_iterations) {
@ -637,7 +661,8 @@ static int pipline_test(struct testbench_prm *tp)
dp_count, err);
break;
}
clock_gettime(CLOCK_MONOTONIC, &td0);
tb_gettime(&td0);
/* sleep to let the pipeline work - we exit at timeout OR
* if copy iterations OR max_samples is reached (whatever first)
@ -652,8 +677,12 @@ static int pipline_test(struct testbench_prm *tp)
tp->pipeline_duration_ms;
while (nsleep_time < nsleep_limit) {
#if defined __XCC__
err = 0;
#else
/* wait for next tick */
err = nanosleep(&ts, &ts);
#endif
if (err == 0) {
nsleep_time += tp->tick_period_us; /* sleep fully completed */
if (test_pipeline_check_state(tp, SOF_TASK_STATE_CANCEL)) {
@ -670,7 +699,8 @@ static int pipline_test(struct testbench_prm *tp)
}
}
clock_gettime(CLOCK_MONOTONIC, &td1);
tb_gettime(&td1);
err = test_pipeline_stop(tp);
if (err < 0) {
fprintf(stderr, "error: pipeline stop %d failed %d\n",
@ -678,9 +708,9 @@ static int pipline_test(struct testbench_prm *tp)
break;
}
delta = (td1.tv_sec - td0.tv_sec) * 1000000;
delta += (td1.tv_nsec - td0.tv_nsec) / 1000;
test_pipeline_stats(tp, &ctx, delta);
delta_t = (td1.tv_sec - td0.tv_sec) * 1000000;
delta_t += (td1.tv_nsec - td0.tv_nsec) / 1000;
test_pipeline_stats(tp, &ctx, delta_t);
err = test_pipeline_reset(tp);
if (err < 0) {
@ -705,6 +735,7 @@ int main(int argc, char **argv)
/* initialize input and output sample rates, files, etc. */
debug = 0;
tp.total_cycles = 0;
tp.fs_in = 0;
tp.fs_out = 0;
tp.bits_in = 0;

View File

@ -7,7 +7,6 @@
/* Topology loader to set up components and pipeline */
#include <dlfcn.h>
#include <errno.h>
#include <math.h>
#include <stdio.h>
@ -161,7 +160,7 @@ static int tb_register_pga(struct testbench_prm *tp, struct tplg_context *ctx)
static int tb_register_pipeline(struct testbench_prm *tp, struct tplg_context *ctx)
{
struct sof *sof = ctx->sof;
struct sof_ipc_pipe_new pipeline = {0};
struct sof_ipc_pipe_new pipeline = {{0}};
int ret;
ret = tplg_new_pipeline(ctx, &pipeline, sizeof(pipeline), NULL);

View File

@ -85,7 +85,7 @@ struct tplg_context {
({struct snd_soc_tplg_hdr *ptr; \
ptr = (struct snd_soc_tplg_hdr *)(ctx->tplg_base + ctx->tplg_offset); \
if (ptr->size != sizeof(*ptr)) { \
printf("%s %d hdr size mismatch 0x%x:0x%lx at offset %ld\n", \
printf("%s %d hdr size mismatch 0x%x:0x%zx at offset %ld\n", \
__func__, __LINE__, ptr->size, sizeof(*ptr), \
ctx->tplg_offset); assert(0); \
} \