Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

debug: tester: add simple DRAM execution test #9866

Merged
merged 1 commit into from
Mar 2, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/debug/tester/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
add_local_sources(tester.c)
add_local_sources(tester_dummy_test.c)
add_local_sources(tester_simple_dram_test.c)
1 change: 1 addition & 0 deletions src/debug/tester/llext/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,5 @@
sof_llext_build("tester"
SOURCES ../tester.c
../tester_dummy_test.c
../tester_simple_dram_test.c
)
4 changes: 4 additions & 0 deletions src/debug/tester/tester.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#include <sof/audio/sink_source_utils.h>
#include "tester.h"
#include "tester_dummy_test.h"
#include "tester_simple_dram_test.h"

/**
* Tester module is a framework for a runtime testing that need a special test code
Expand Down Expand Up @@ -76,6 +77,9 @@ static int tester_init(struct processing_module *mod)
case TESTER_MODULE_CASE_DUMMY_TEST:
cd->tester_case_interface = &tester_interface_dummy_test;
break;
case TESTER_MODULE_CASE_SIMPLE_DRAM_TEST:
cd->tester_case_interface = &tester_interface_simple_dram_test;
break;

default:
comp_err(dev, "Invalid config, unknown test type");
Expand Down
1 change: 1 addition & 0 deletions src/debug/tester/tester.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@

#define TESTER_MODULE_CASE_NO_TEST 0
#define TESTER_MODULE_CASE_DUMMY_TEST 1
#define TESTER_MODULE_CASE_SIMPLE_DRAM_TEST 2

/**
* API of a test case
Expand Down
83 changes: 83 additions & 0 deletions src/debug/tester/tester_simple_dram_test.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
// SPDX-License-Identifier: BSD-3-Clause
//
// Copyright(c) 2025 Intel Corporation. All rights reserved.
//
// Author: Adrian Bonislawski <adrian.bonislawski@intel.com>

#include "tester_simple_dram_test.h"
#include <sof/audio/component.h>
#include <sof/audio/module_adapter/module/generic.h>
#include <sof/lib/memory.h>

/*
* This is a simple test case for DRAM execution
* The test case will copy every 2nd frame of data
* by setting do_copy flag to true/false
*/

struct tester_module_simple_dram_test_data {
bool do_copy_data;
};

static int validate_l3_memory(void *ptr)
{
if (!((POINTER_TO_UINT(ptr) >= L3_MEM_BASE_ADDR) &&
(POINTER_TO_UINT(ptr) < L3_MEM_BASE_ADDR + L3_MEM_SIZE)))
return -EINVAL;

return 0;
}

__cold static int simple_dram_test_case_init(struct processing_module *mod, void **ctx)
{
#if !CONFIG_L3_HEAP
return -EINVAL;
#endif
struct tester_module_simple_dram_test_data *data =
rzalloc(0, 0, SOF_MEM_CAPS_L3, sizeof(*data));

if (!data)
return -ENOMEM;

if (validate_l3_memory(data) != 0) {
rfree(data);
return -EINVAL;
}

if (validate_l3_memory(tester_interface_simple_dram_test.init) != 0 ||
validate_l3_memory(tester_interface_simple_dram_test.process) != 0 ||
validate_l3_memory(tester_interface_simple_dram_test.free) != 0) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was wondering whether this makes sense if the build does not support mapping cold section to DRAM, but I guess these checks will apply in that case as well and would signal an invalid build of the FW.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@abonislawski the way relocations are resolved during dynamic linking, sometimes addresses of functions when examined and when jumped to might be different. E.g. in

    printf("about to call x() at %p\n", x);
    x();

doesn't guarantee that the address you print will be the same address that you jump to. In your above code I actually think it will be necessarily the same, but I'm not 100% sure and it's a bit at the compiler's discretion. To make absolutely sure when debugging I use __builtin_return_address(), e.g.

void *caller_addr(void)
{
    return __builtin_return_address(0);
}

__cold void x(void)
{
    printf("running at %p\n", caller_addr());
}

Would be good to use this here too (1) to make sure we run in DRAM, (2) to document this method for everybody to use for debugging. Maybe even actually make that caller_address() function available in SOF globally.

rfree(data);
return -EINVAL;
}

data->do_copy_data = false;
*ctx = data;
return 0;
}

__cold static int simple_dram_test_case_process(void *ctx, struct processing_module *mod,
struct sof_source **sources, int num_of_sources,
struct sof_sink **sinks, int num_of_sinks,
bool *do_copy)
{
struct tester_module_simple_dram_test_data *data = ctx;

/* copy every second cycle */
*do_copy = data->do_copy_data;
data->do_copy_data = !data->do_copy_data;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just curious, why every second buffer instead of every buffer ?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My plan was to do the same thing as existing TESTER_MODULE_CASE_DUMMY_TEST (switching do_copy) and make difference only in DRAM execution


return 0;
}

__cold static int simple_dram_test_free(void *ctx, struct processing_module *mod)
{
rfree(ctx);
return 0;
}

const struct tester_test_case_interface tester_interface_simple_dram_test = {
.init = simple_dram_test_case_init,
.process = simple_dram_test_case_process,
.free = simple_dram_test_free
};
18 changes: 18 additions & 0 deletions src/debug/tester/tester_simple_dram_test.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
/* SPDX-License-Identifier: BSD-3-Clause
*
* Copyright(c) 2025 Intel Corporation.
*
* Author: Adrian Bonislawski <adrian.bonislawski@intel.com>
*/

#ifndef TESTER_SIMPLE_DRAM_TEST
#define TESTER_SIMPLE_DRAM_TEST

#include <stddef.h>
#include <stdint.h>

#include "tester.h"

extern const struct tester_test_case_interface tester_interface_simple_dram_test;

#endif /* TESTER_DUMMY_TEST */
1 change: 1 addition & 0 deletions zephyr/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,7 @@ elseif(CONFIG_COMP_TESTER)
zephyr_library_sources_ifdef(CONFIG_COMP_TESTER
${SOF_DEBUG_PATH}/tester/tester.c
${SOF_DEBUG_PATH}/tester/tester_dummy_test.c
${SOF_DEBUG_PATH}/tester/tester_simple_dram_test.c
)
endif()

Expand Down
Loading