This commit is contained in:
Steven Dan
2025-12-11 09:43:42 +08:00
commit d8b2974133
1822 changed files with 280037 additions and 0 deletions

View File

@@ -0,0 +1,153 @@
// Copyright 2024-2025 XMOS LIMITED.
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
/// Unit tests for adsp_control.c
#include <unity.h>
#include <stages/adsp_control.h>
#include <stages/dummy.h>
#include <adsp_generated_dummy.h>
#include <adsp_instance_id_dummy.h>
#include <cmds.h>
#include <stdio.h>
#include <swlock.h>
void setUp(){}
void tearDown(){}
/// Test that basic read and write works.
void test_basic_control(void) {
adsp_pipeline_t* p = adsp_dummy_pipeline_init();
module_instance_t* dummy_inst = &p->modules[dummy_stage_index];
adsp_controller_t ctrl;
adsp_controller_init(&ctrl, p);
int test_val = 5;
adsp_stage_control_cmd_t cmd = {
.instance_id = dummy_stage_index,
.cmd_id = CMD_DUMMY_DUMMY_FIELD,
.payload_len = sizeof(int),
.payload = &test_val
};
// First write succeeds as stage isn't busy
adsp_control_status_t status = adsp_write_module_config(&ctrl, &cmd);
TEST_ASSERT_EQUAL(ADSP_CONTROL_SUCCESS, status);
// Now the stage is busy
status = adsp_write_module_config(&ctrl, &cmd);
TEST_ASSERT_EQUAL(ADSP_CONTROL_BUSY, status);
// Now the stage is busy
status = adsp_read_module_config(&ctrl, &cmd);
TEST_ASSERT_EQUAL(ADSP_CONTROL_BUSY, status);
// Stage processes control
dummy_control(dummy_inst->state, &dummy_inst->control);
*(int*)cmd.payload = 0; // clear the payload, ready for read.
// request a read, stage must process it so it is busy
status = adsp_read_module_config(&ctrl, &cmd);
TEST_ASSERT_EQUAL(ADSP_CONTROL_BUSY, status);
// The stage is busy
status = adsp_write_module_config(&ctrl, &cmd);
TEST_ASSERT_EQUAL(ADSP_CONTROL_BUSY, status);
// Stage processes control
dummy_control(dummy_inst->state, &dummy_inst->control);
// re-request the read, stage must process it so it is busy
status = adsp_read_module_config(&ctrl, &cmd);
TEST_ASSERT_EQUAL(ADSP_CONTROL_SUCCESS, status);
TEST_ASSERT_EQUAL(test_val, *(int*)cmd.payload);
}
/// Test that when there are two controllers, only the controller who made
/// the request will get a response.
void test_adsp_control_2_controllers(void) {
adsp_pipeline_t* p = adsp_dummy_pipeline_init();
module_instance_t* dummy_inst = &p->modules[dummy_stage_index];
adsp_controller_t ctrl_a;
adsp_controller_init(&ctrl_a, p);
adsp_controller_t ctrl_b;
adsp_controller_init(&ctrl_b, p);
int test_val = 5;
adsp_stage_control_cmd_t cmd = {
.instance_id = dummy_stage_index,
.cmd_id = CMD_DUMMY_DUMMY_FIELD,
.payload_len = sizeof(int),
.payload = &test_val
};
// First write succeeds as stage isn't busy
adsp_control_status_t status = adsp_write_module_config(&ctrl_a, &cmd);
TEST_ASSERT_EQUAL(ADSP_CONTROL_SUCCESS, status);
// stage is now busy for both controllers.
status = adsp_write_module_config(&ctrl_a, &cmd);
TEST_ASSERT_EQUAL(ADSP_CONTROL_BUSY, status);
status = adsp_write_module_config(&ctrl_b, &cmd);
TEST_ASSERT_EQUAL(ADSP_CONTROL_BUSY, status);
// Stage processes control
dummy_control(dummy_inst->state, &dummy_inst->control);
*(int*)cmd.payload = 0; // clear the payload, ready for read.
// request a read, stage must process it so it is busy
status = adsp_read_module_config(&ctrl_a, &cmd);
TEST_ASSERT_EQUAL(ADSP_CONTROL_BUSY, status);
// Stage processes control
dummy_control(dummy_inst->state, &dummy_inst->control);
// Even though a read was processed, b still gets busy
// because it didn't ask for it.
status = adsp_read_module_config(&ctrl_b, &cmd);
TEST_ASSERT_EQUAL(ADSP_CONTROL_BUSY, status);
// but a gets the result.
status = adsp_read_module_config(&ctrl_a, &cmd);
TEST_ASSERT_EQUAL(ADSP_CONTROL_SUCCESS, status);
TEST_ASSERT_EQUAL(test_val, *(int*)cmd.payload);
}
/// Ensure that busy is returned when the lock is taken for both read
/// and write.
void test_lock_contention(void) {
adsp_pipeline_t* p = adsp_dummy_pipeline_init();
module_instance_t* dummy_inst = &p->modules[dummy_stage_index];
adsp_controller_t ctrl;
adsp_controller_init(&ctrl, p);
int test_val = 5;
adsp_stage_control_cmd_t cmd = {
.instance_id = dummy_stage_index,
.cmd_id = CMD_DUMMY_DUMMY_FIELD,
.payload_len = sizeof(int),
.payload = &test_val
};
// take the lock to emulate contention.
swlock_acquire(&dummy_inst->control.lock);
// Get busy even though the stage isn't doing anything because the lock
// is taken.
adsp_control_status_t status = adsp_write_module_config(&ctrl, &cmd);
TEST_ASSERT_EQUAL(ADSP_CONTROL_BUSY, status);
swlock_release(&dummy_inst->control.lock);
status = adsp_write_module_config(&ctrl, &cmd);
TEST_ASSERT_EQUAL(ADSP_CONTROL_SUCCESS, status);
// Stage processes control
dummy_control(dummy_inst->state, &dummy_inst->control);
}