blob: a259a0ef63300e182a715be213231ed0b83ea3fd [file] [log] [blame]
// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
/**
* This example serves as a starting point for writing software top-level
* concurrency tests that use the OpenTitan Test Framework (OTTF), and run at
* the flash boot stage. This example is intended to be copied and modified
* according to the instructions below.
*
* This example demonstrates a concurrency test that spawns three FreeRTOS
* tasks, in addition to the `test_main` task. Each task is defined using a
* separate function that never returns, and deletes itself after executing its
* code. Since the priorities of each task are the same, yet higher than the
* priority of the "test_main" task, calling `ottf_task_yield()` will switch
* control flow between these tasks, until each task deletes itself. Then, the
* `test_main` task will continue executing, returning `true` when the overall
* test passes, triggering the OTTF to signal test execution has completed.
*
* Additionally, an example assertion failure is commented out below in `task_3`
* to demonstrate how the test will terminate execution immediately upon
* encountering said behavior in any task. The test runner (opentitantool) on
* Verilator and FPGA platforms is monitoring the UART for a failure message
* that gets printed immediately upon an assertion failure. It terminates the
* test immediately upon seeing said message. Similarly, in DV, the testbench is
* monitoring a specific memory location that gets written to on an assertion
* failure.
*/
#include "sw/device/lib/runtime/log.h"
#include "sw/device/lib/testing/test_framework/check.h"
#include "sw/device/lib/testing/test_framework/ottf_macros.h"
#include "sw/device/lib/testing/test_framework/ottf_main.h"
OTTF_DEFINE_TEST_CONFIG(.enable_concurrency = true,
.can_clobber_uart = false, );
static void task_1(void *task_parameters) {
// ***************************************************************************
// Place test code below.
// ***************************************************************************
LOG_INFO("Executing %s ...", ottf_task_get_self_name());
ottf_task_yield();
LOG_INFO("Continuing to execute %s ...", ottf_task_get_self_name());
// ***************************************************************************
// Delete the current task and never return.
// ***************************************************************************
OTTF_TASK_DELETE_SELF_OR_DIE;
}
static void task_2(void *task_parameters) {
// ***************************************************************************
// Place test code below.
// ***************************************************************************
LOG_INFO("Executing %s ...", ottf_task_get_self_name());
// ***************************************************************************
// Delete the current task and never return.
// ***************************************************************************
OTTF_TASK_DELETE_SELF_OR_DIE;
}
static void task_3(void *task_parameters) {
// ***************************************************************************
// Place test code below.
// ***************************************************************************
LOG_INFO("Executing %s ...", ottf_task_get_self_name());
// ***************************************************************************
// Uncomment to see the effects of a failed assertion. Delete this when
// implementing a test.
// ***************************************************************************
// CHECK(false, "A failed assertion causes immediate test termination.");
// ***************************************************************************
// Delete the current task and never return.
// ***************************************************************************
OTTF_TASK_DELETE_SELF_OR_DIE;
}
bool test_main(void) {
// ***************************************************************************
// Create the FreeRTOS tasks that will comprise this test. Ensure the priority
// levels of each task are higher than the priority of the current "test_main"
// task, which is 0.
// ***************************************************************************
LOG_INFO("Starting to execute %s ...", ottf_task_get_self_name());
CHECK(ottf_task_create(task_1, "task_1", kOttfFreeRtosMinStackSize, 1));
CHECK(ottf_task_create(task_2, "task_2", kOttfFreeRtosMinStackSize, 1));
CHECK(ottf_task_create(task_3, "task_3", kOttfFreeRtosMinStackSize, 1));
// ***************************************************************************
// Yield control flow to the highest priority task in the run queue. Since the
// tasks created above all have a higher priority level than the current
// "test_main" task, execution will not be returned to the current task until
// the above tasks have been deleted.
// ***************************************************************************
LOG_INFO("Yielding execution to another task.");
ottf_task_yield();
// ***************************************************************************
// Return true if the test succeeds. Return false if it should fail.
// ***************************************************************************
return true;
}