mirror of
https://github.com/AmbiML/sparrow-kata-full.git
synced 2025-06-30 16:12:11 +00:00
LogFibonacci component
This CAmkES component demonstrates concurrent control threads when one of them never calls seL4_Yield (preemption by timer interrupts). It can be removed when we are sure this is working well. Until then, the log messages will be visible after issuing "loglevel trace" at the prompt. Change-Id: Ice1a3ac2e11dc50f5d9d5f790e2de80b58fe269e GitOrigin-RevId: d20266a6add4f3d4d673a492a3b0ab70663e0308
This commit is contained in:
parent
d97a78316e
commit
b0e442a623
@ -55,6 +55,11 @@ DeclareCAmkESComponent(MlCoordinator
|
||||
INCLUDES interfaces
|
||||
)
|
||||
|
||||
DeclareCAmkESComponent(LogFibonacci
|
||||
SOURCES
|
||||
components/LogFibonacci/src/main.c
|
||||
)
|
||||
|
||||
DeclareCAmkESComponent(OpenTitanUARTDriver
|
||||
SOURCES
|
||||
components/OpenTitanUARTDriver/src/driver.c
|
||||
|
7
apps/system/components/LogFibonacci/LogFibonacci.camkes
Normal file
7
apps/system/components/LogFibonacci/LogFibonacci.camkes
Normal file
@ -0,0 +1,7 @@
|
||||
import <LoggerInterface.camkes>;
|
||||
|
||||
component LogFibonacci {
|
||||
control;
|
||||
|
||||
uses LoggerInterface logger;
|
||||
}
|
11
apps/system/components/LogFibonacci/assembly.camkes
Normal file
11
apps/system/components/LogFibonacci/assembly.camkes
Normal file
@ -0,0 +1,11 @@
|
||||
import "LogFibonacci.camkes";
|
||||
|
||||
assembly {
|
||||
composition {
|
||||
component LogFibonacci log_fibonacci;
|
||||
|
||||
connection seL4RPCOverMultiSharedData log_fibonacci_logger(
|
||||
from log_fibonacci.logger,
|
||||
to debug_console.logger);
|
||||
}
|
||||
}
|
98
apps/system/components/LogFibonacci/src/main.c
Normal file
98
apps/system/components/LogFibonacci/src/main.c
Normal file
@ -0,0 +1,98 @@
|
||||
/*
|
||||
* Copyright 2021, Google LLC
|
||||
*
|
||||
* Demo component to show that concurrent control threads can be running.
|
||||
*
|
||||
* This component logs the first LOG_FIBONACCI_LIMIT Fibonacci numbers using the
|
||||
* LoggerInterface, waiting for INTERRUPTS_PER_WAIT interrupts between each
|
||||
* number. The messages are logged at level TRACE, which can be enabled by
|
||||
* issuing "loglevel trace" at the Kata prompt.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
// TODO(b/198360356): Remove this component when it is no longer needed for
|
||||
// concurrency testing.
|
||||
|
||||
#include <camkes.h>
|
||||
#include <sel4/config.h>
|
||||
#include <stdint.h>
|
||||
|
||||
// How many Fibonacci numbers to write to the log.
|
||||
#define LOG_FIBONACCI_LIMIT 80
|
||||
|
||||
#define INTERRUPTS_PER_VIRT_SEC (1000 / CONFIG_TIMER_TICK_MS)
|
||||
#define INTERRUPTS_PER_WAIT (2 * INTERRUPTS_PER_VIRT_SEC)
|
||||
#define LOGGER_INTERFACE_LOG_LEVEL 5
|
||||
|
||||
typedef uint64_t interrupt_count_t;
|
||||
|
||||
typedef struct {
|
||||
uint64_t f1;
|
||||
uint64_t f2;
|
||||
uint64_t n;
|
||||
} fibonacci_state_t;
|
||||
|
||||
static void fibonacci_init(fibonacci_state_t *state) {
|
||||
state->f1 = 0;
|
||||
state->f2 = 1;
|
||||
state->n = 0;
|
||||
}
|
||||
|
||||
static void fibonacci_increment(fibonacci_state_t *state) {
|
||||
uint64_t swap = state->f2;
|
||||
state->f2 = state->f1 + state->f2;
|
||||
state->f1 = swap;
|
||||
++state->n;
|
||||
}
|
||||
|
||||
static void wait(interrupt_count_t interrupt_count_to_wait,
|
||||
interrupt_count_t *counter) {
|
||||
for (interrupt_count_t i = 0; i < interrupt_count_to_wait; ++i) {
|
||||
asm volatile("wfi");
|
||||
++*counter;
|
||||
}
|
||||
}
|
||||
|
||||
static float virtual_seconds(interrupt_count_t interrupt_count) {
|
||||
return interrupt_count / INTERRUPTS_PER_VIRT_SEC;
|
||||
}
|
||||
|
||||
static uint64_t rdtime(void) {
|
||||
uint32_t upper, lower, upper_reread;
|
||||
while (1) {
|
||||
asm volatile(
|
||||
"rdtimeh %0\n"
|
||||
"rdtime %1\n"
|
||||
"rdtimeh %2\n"
|
||||
: "=r"(upper), "=r"(lower), "=r"(upper_reread));
|
||||
if (upper_reread == upper) {
|
||||
return ((uint64_t)upper << 32) | lower;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void fibonacci_log(const fibonacci_state_t *fibonacci_state,
|
||||
interrupt_count_t interrupt_count) {
|
||||
char log_buf[128];
|
||||
snprintf(log_buf, sizeof(log_buf) / sizeof(char),
|
||||
"log_fibonacci:control: n == %llu; f == %llu; interrupt_count == "
|
||||
"%llu; rdtime == %llu; virt_sec ~= %.2f",
|
||||
fibonacci_state->n, fibonacci_state->f1, interrupt_count, rdtime(),
|
||||
virtual_seconds(interrupt_count));
|
||||
logger_log(LOGGER_INTERFACE_LOG_LEVEL, log_buf);
|
||||
}
|
||||
|
||||
int run(void) {
|
||||
interrupt_count_t interrupt_count = 0;
|
||||
fibonacci_state_t fibonacci_state;
|
||||
fibonacci_init(&fibonacci_state);
|
||||
while (1) {
|
||||
wait(INTERRUPTS_PER_WAIT, &interrupt_count);
|
||||
if (fibonacci_state.n >= LOG_FIBONACCI_LIMIT) {
|
||||
fibonacci_init(&fibonacci_state);
|
||||
}
|
||||
fibonacci_log(&fibonacci_state, interrupt_count);
|
||||
fibonacci_increment(&fibonacci_state);
|
||||
}
|
||||
}
|
@ -62,14 +62,16 @@ assembly {
|
||||
|
||||
// VectorCoreDriver
|
||||
connection seL4HardwareMMIO vc_csr(from vc_drv.csr, to vctop.csr);
|
||||
connection seL4RPCCall VectorCoreInterface(from ml_coordinator.vctop,
|
||||
to vc_drv.vctop);
|
||||
connection seL4RPCCall ml_coord_to_driver(from ml_coordinator.vctop,
|
||||
to vc_drv.vctop);
|
||||
|
||||
// Hookup ProcessManager to DebugConsole for shell commands.
|
||||
connection seL4RPCCall ProcessControlInterface(from debug_console.proc_ctrl,
|
||||
to process_manager.proc_ctrl);
|
||||
connection seL4RPCCall PackageManagerInterface(from debug_console.pkg_mgmt,
|
||||
to process_manager.pkg_mgmt);
|
||||
connection seL4RPCCall shell_process(from debug_console.proc_ctrl,
|
||||
to process_manager.proc_ctrl);
|
||||
connection seL4RPCCall shell_package(from debug_console.pkg_mgmt,
|
||||
to process_manager.pkg_mgmt);
|
||||
connection seL4RPCCall shell_ml(from debug_console.mlcoord,
|
||||
to ml_coordinator.mlcoord);
|
||||
|
||||
// Connect the DebugConsole to the OpenTitanUARTDriver.
|
||||
connection seL4SharedData tx_channel(
|
||||
@ -84,19 +86,20 @@ assembly {
|
||||
// Connect the LoggerInterface to each component that needs to log
|
||||
// to the console. Note this allocates a 4KB shared memory region to
|
||||
// each component and copies data between components.
|
||||
connection seL4RPCOverMultiSharedData LoggerInterface(
|
||||
connection seL4RPCOverMultiSharedData multi_logger(
|
||||
from process_manager.logger,
|
||||
from ml_coordinator.logger,
|
||||
to debug_console.logger);
|
||||
|
||||
// Connect the SeL4Debug interface of each component that needs access.
|
||||
connection seL4RPCCall SeL4DebugInterface(from debug_console.sel4debug,
|
||||
from process_manager.sel4debug,
|
||||
to sel4debug.sel4debug);
|
||||
|
||||
connection seL4RPCCall MlCoordinatorInterface(from debug_console.mlcoord,
|
||||
to ml_coordinator.mlcoord);
|
||||
|
||||
//
|
||||
// (Note that if the LogFibonacci import at the bottom of this file is
|
||||
// uncommented then there will be another connection to the sel4debug
|
||||
// procedure. This is fine, but it is important that connection names
|
||||
// not clash.)
|
||||
connection seL4RPCCall multi_sel4debug(from debug_console.sel4debug,
|
||||
from process_manager.sel4debug,
|
||||
to sel4debug.sel4debug);
|
||||
}
|
||||
|
||||
configuration {
|
||||
@ -114,3 +117,10 @@ assembly {
|
||||
uart.integrity_label = "opentitan_uart_driver";
|
||||
}
|
||||
}
|
||||
|
||||
// Uncomment to run a concurrency test component that is runnable every time
|
||||
// the scheduler checks and which periodically calls logger.log.
|
||||
//
|
||||
// (Needs to be at the bottom of file because CAmkES ADL does not have forward
|
||||
// declaration.)
|
||||
// import "components/LogFibonacci/assembly.camkes";
|
||||
|
Loading…
Reference in New Issue
Block a user