ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
Loading...
Searching...
No Matches
main.c File Reference

RA8P1 Ethos-U55 .npub container loader end-to-end – load a .npub, run it. More...

#include <stdint.h>
#include "ra8_attributes.h"
#include "ra8_board_ek_ra8d2.h"
#include "ra8_boot_entry.h"
#include "ra8_cgc.h"
#include "ra8_device.h"
#include "ra8_err.h"
#include "ra8_npu.h"
#include "ra8_npu_blob.h"
#include "ra8_npu_fake_cmd.h"
#include "ra8_npu_loader.h"
#include "ra8_npu_model_addk_fake.h"
#include "ra8_npu_regs.h"
Include dependency graph for main.c:

Go to the source code of this file.

Enumerations

enum  npu_vela_size_t : uint32_t {
  k_npu_vela_baud = 115200U ,
  k_npu_vela_arena = 128U ,
  k_npu_vela_word_bytes = 4U ,
  k_npu_vela_byte_mask = 0xFFU ,
  k_npu_vela_hex_digits = 8U ,
  k_npu_vela_hex_shift = 4U ,
  k_npu_vela_hex_mask = 0x0FU
}
 Console baud, runtime-arena size, banner width, and word geometry. More...
enum  npu_vela_fnv_t : uint32_t {
  k_npu_vela_fnv_offset = 0x811C9DC5U ,
  k_npu_vela_fnv_prime = 0x01000193U
}
 FNV-1a 32-bit constants for the displayed output checkword. More...

Functions

static void internal_npu_vela_panic_halt (void)
 Park the CPU forever in WFI after a fatal init error (a real panic).
static void internal_npu_vela_park (void)
 Park the CPU forever in WFI after the verdict banner (a clean stop).
static void internal_npu_vela_setup_or_halt (void)
 Bring up CGC + the SCI8 console.
static uint32_t internal_npu_vela_cmd_word (const ra8_npu_job_t *job, ra8_npu_fake_word_idx_t widx)
 Read a little-endian command-stream word from the loaded job.
static bool internal_npu_vela_verify (const ra8_npu_job_t *job, uint32_t *out_check)
 Verify the output arena equals input+K and fold it into a checkword.
static ra8_err_t internal_npu_vela_run_job (ra8_npu_job_t *out_job)
 Load the golden blob, submit + run + wait for the NPU job.
static void internal_npu_vela_write (const uint8_t *data, size_t len)
static void internal_npu_vela_write_hex32 (uint32_t value)
static void internal_npu_vela_write_status (bool ok)
static void internal_npu_vela_write_verdict (bool pass)
static void internal_npu_vela_emit (uint32_t id, bool load_ok, bool run_ok, uint32_t check, bool pass)
 Print the one-line verdict banner over the SCI8 console.
void main (void)
 Application entry: load a .npub model, run it, print the verdict.

Variables

static uint8_t s_npu_vela_arena [k_npu_vela_arena]
 Runtime arena the loader carves the output activation from.
volatile uint32_t g_npu_vela_id = 0U
 NPU_ID captured after init, for external (J-Link) inspection.
volatile uint32_t g_npu_vela_check = 0U
 Output checkword captured after verify, for external inspection.
volatile uint32_t g_npu_vela_pass = 0U
 Final verdict (1 = PASS, 0 = FAIL), for external inspection.

Detailed Description

RA8P1 Ethos-U55 .npub container loader end-to-end – load a .npub, run it.

Tag
[Ring 6 / APP] {World: S}

Companion to examples/ra8p1_foundation/npu_smoke on the way to issue #227: instead of hand-building a command stream in SRAM, this app LOADS a committed, generated .npub model container (tools/vela/generated/ra8_npu_model_addk_fake.h, produced offline by tools/vela/src/vela_gen.py) through the on-target loader ra8_npu_load(), which maps it into an ra8_npu_job_t – command stream plus resolved region bases (baked weights/input inside the blob, the output activation carved from a runtime SRAM arena). It then submits + runs the job, reads the output arena back, and asserts it holds the deterministic input + K result. The verdict is printed over the SCI8 console:

npu-vela: id=0x10060000 load=OK run=OK out=0x........ verdict=PASS

The container's command stream is NOT a real Vela program: it is the tiny, documented ra8_emulator / host-test convention in ra8_npu_fake_cmd.h. Under tools/ra8_emulator --device ra8p1 the NPU model decodes it and applies the op to the tensor arenas, so this app is a DETERMINISTIC, emulator-runnable proof of the FULL offline-build -> on-target-load -> run pipeline. It is still a FOUNDATION app: there is no RA8P1 board yet, and real Vela-compiled inference is the follow-up on the RA8P1 NPU epic. On silicon the NPU reaches the arenas over AXI, so a real driver would add cache maintenance around the tensors; the cache-less emulator needs none, so this foundation omits it.

Architectural ring
See docs/RING_AND_WORLD.md for what [Ring 6 / APP] {World: S} means – application-layer code that runs in the Secure world.
Author
Brighton Sikarskie
Date
2026-07-15
Since
0.1.0

Definition in file main.c.

Enumeration Type Documentation

◆ npu_vela_fnv_t

enum npu_vela_fnv_t : uint32_t

FNV-1a 32-bit constants for the displayed output checkword.

Enumerator
k_npu_vela_fnv_offset 

FNV-1a 32-bit offset basis.

k_npu_vela_fnv_prime 

FNV-1a 32-bit prime.

Definition at line 82 of file main.c.

◆ npu_vela_size_t

enum npu_vela_size_t : uint32_t

Console baud, runtime-arena size, banner width, and word geometry.

Enumerator
k_npu_vela_baud 

SCI8 J-Link OB console baud.

k_npu_vela_arena 

Runtime arena for output activation.

k_npu_vela_word_bytes 

Bytes in one little-endian word.

k_npu_vela_byte_mask 

8-bit element wrap (matches the op).

k_npu_vela_hex_digits 

Fixed-width hexadecimal word digits.

k_npu_vela_hex_shift 

Bits per hexadecimal nibble.

k_npu_vela_hex_mask 

Mask for one hexadecimal nibble.

Definition at line 68 of file main.c.

Function Documentation

◆ internal_npu_vela_cmd_word()

uint32_t internal_npu_vela_cmd_word ( const ra8_npu_job_t * job,
ra8_npu_fake_word_idx_t widx )
static

Read a little-endian command-stream word from the loaded job.

Computes the byte offset for the requested fake-command word and delegates endian-safe decoding to the blob reader.

Parameters
[in]jobLoaded job whose cmd_stream is byte-addressable.
[in]widxWord index within the SE55 command stream.
Returns
The 32-bit word at widx.
Return values
0..UINT32_MAXThe decoded little-endian command word.
Precondition
job->cmd_stream is non-NULL and at least (widx+1) words long.
widx names a defined word within the loaded command header.
Postcondition
No state is modified; the function is pure.
The job's stream position and region mappings remain unchanged.
Note
The helper intentionally performs no bounds check beyond its contract.
Since
0.1.0

Definition at line 207 of file main.c.

References ra8_npu_job_t::cmd_stream, k_npu_vela_word_bytes, RA8_INTERNAL, and ra8_npu_blob_read_word().

Referenced by internal_npu_vela_verify().

◆ internal_npu_vela_emit()

void internal_npu_vela_emit ( uint32_t id,
bool load_ok,
bool run_ok,
uint32_t check,
bool pass )
static

Print the one-line verdict banner over the SCI8 console.

Emits fixed text fragments and fixed-width hexadecimal fields directly, avoiding the libc snprintf implementation unavailable to the freestanding target.

Parameters
[in]idNPU_ID read after init.
[in]load_okWhether ra8_npu_load() succeeded.
[in]run_okWhether the submit/run/wait sequence returned k_ra8_ok.
[in]checkOutput checkword from internal_npu_vela_verify().
[in]passFinal verdict (id valid AND load AND run AND output matched).
Precondition
The SCI8 console is initialised.
All supplied status values are final snapshots for this run.
Postcondition
One banner line has been written and flushed to the console.
The NPU job, arena, and published globals remain unchanged.
Note
Individual diagnostic writes are best-effort; the final flush keeps the complete line observable by the HIL scraper.
Since
0.1.0

Definition at line 341 of file main.c.

References internal_npu_vela_write(), internal_npu_vela_write_hex32(), internal_npu_vela_write_status(), internal_npu_vela_write_verdict(), and ra8_board_uart_console_flush().

Referenced by main().

◆ internal_npu_vela_panic_halt()

void internal_npu_vela_panic_halt ( void )
static

Park the CPU forever in WFI after a fatal init error (a real panic).

Reserved for failures BEFORE a verdict can be emitted (CGC or the SCI8 console did not come up), so a ra8_emulator gate that scans for a *panic_halt terminal PC correctly reads this as a failed run.

Precondition
Called only after a fatal init error, before the verdict banner.
No initialized diagnostic path can publish a normal verdict.
Postcondition
CPU is parked; only a debugger or reset wakes it.
No NPU loader, driver, or console operation follows entry.
Note
Emulator automation uses the panic suffix to classify boot failure.
Since
0.1.0

Definition at line 138 of file main.c.

References RA8_INTERNAL.

Referenced by internal_npu_vela_setup_or_halt().

◆ internal_npu_vela_park()

void internal_npu_vela_park ( void )
static

Park the CPU forever in WFI after the verdict banner (a clean stop).

Distinct from internal_npu_vela_panic_halt on purpose: a run that reached the verdict has done its job and parks here, whose name deliberately does NOT match the *panic_halt patterns a ra8_emulator gate treats as a give-up. The authoritative verdict is the emitted banner.

Precondition
The verdict banner has been emitted over the SCI8 console.
Published ID, checkword, and pass values are final.
Postcondition
CPU is parked; only a debugger or reset wakes it.
Run evidence remains stable for debugger or memory-probe inspection.
Note
The banner, rather than this terminal PC, determines PASS or FAIL.
Since
0.1.0

Definition at line 160 of file main.c.

References RA8_INTERNAL.

Referenced by main().

◆ internal_npu_vela_run_job()

ra8_err_t internal_npu_vela_run_job ( ra8_npu_job_t * out_job)
static

Load the golden blob, submit + run + wait for the NPU job.

Resolves the generated container into the static arena, submits its descriptor, starts the NPU, and waits synchronously for completion.

Parameters
[out]out_jobFilled with the loaded, run job descriptor on success.
Returns
ra8_err_t from the first failing loader / driver call, else k_ra8_ok.
Return values
k_ra8_okThe container loaded and the NPU job completed.
non-k_ra8_okThe loader, submission, run, or wait stage failed.
Precondition
out_job is non-NULL; ra8_npu_init() previously succeeded.
The static Vela arena is not owned by another job.
Postcondition
On k_ra8_ok the output region of *out_job holds the NPU result.
On failure no later loader or driver stage is attempted.
Note
Region storage remains application-owned for the complete synchronous run.
Since
0.1.0

Definition at line 271 of file main.c.

References k_npu_vela_arena, k_ra8_ok, RA8_INTERNAL, ra8_npu_load(), ra8_npu_model_addk_fake_blob(), ra8_npu_model_addk_fake_bytes(), ra8_npu_run(), ra8_npu_submit(), ra8_npu_wait(), and s_npu_vela_arena.

Referenced by main().

◆ internal_npu_vela_setup_or_halt()

void internal_npu_vela_setup_or_halt ( void )
static

Bring up CGC + the SCI8 console.

Panic-halts on any failure.

The NPU needs no clock beyond the CGC default NPUCLK; only the console (PCLKA/SCICLK) is set up here so the verdict can be printed.

Precondition
Reset_Handler has initialised .data / .bss.
The application remains in single-threaded boot context.
Postcondition
On return CGC is up and the SCI8 console is ready for writes.
Any mandatory setup error transfers to the panic halt.
Note
NPU initialization is deferred until diagnostics are known operational.
Since
0.1.0

Definition at line 180 of file main.c.

References internal_npu_vela_panic_halt(), k_npu_vela_baud, k_ra8_ok, ra8_board_uart_console_init(), ra8_cgc_init(), and RA8_INTERNAL.

Referenced by main().

◆ internal_npu_vela_verify()

bool internal_npu_vela_verify ( const ra8_npu_job_t * job,
uint32_t * out_check )
static

Verify the output arena equals input+K and fold it into a checkword.

Reads the resolved input region (baked in the blob) and output region (the runtime arena) straight out of the loaded job, plus the add constant and byte count from the command stream, and checks every output byte against the deterministic input + K result.

Parameters
[in]jobJob returned by ra8_npu_load() (regions resolved).
[out]out_checkFNV-1a digest of the output bytes (for the banner).
Returns
true when every output byte matches the expected add-constant result.
Return values
trueEvery byte matches the command stream's add-constant operation.
falseOne or more bytes differ from the deterministic expectation.
Precondition
out_check is non-NULL; the job has completed.
Input and output region mappings cover the command's declared byte count.
Postcondition
*out_check holds the output digest regardless of the verdict.
The job, command stream, and data regions are not modified.
Note
The FNV digest is diagnostic evidence rather than an integrity primitive.
Since
0.1.0

Definition at line 235 of file main.c.

References internal_npu_vela_cmd_word(), k_npu_vela_byte_mask, k_npu_vela_fnv_offset, k_npu_vela_fnv_prime, k_ra8_npu_fake_word_const, k_ra8_npu_fake_word_count, k_ra8_npu_region_1, k_ra8_npu_region_2, RA8_INTERNAL, and ra8_npu_job_t::region_base.

Referenced by main().

◆ internal_npu_vela_write()

void internal_npu_vela_write ( const uint8_t * data,
size_t len )
static

◆ internal_npu_vela_write_hex32()

void internal_npu_vela_write_hex32 ( uint32_t value)
static

◆ internal_npu_vela_write_status()

void internal_npu_vela_write_status ( bool ok)
static

Definition at line 307 of file main.c.

References internal_npu_vela_write(), and RA8_INTERNAL.

Referenced by internal_npu_vela_emit().

◆ internal_npu_vela_write_verdict()

void internal_npu_vela_write_verdict ( bool pass)
static

Definition at line 314 of file main.c.

References internal_npu_vela_write(), and RA8_INTERNAL.

Referenced by internal_npu_vela_emit().

◆ main()

void main ( void )

Application entry: load a .npub model, run it, print the verdict.

The application entry point Reset_Handler hands control to.

Precondition
Reset_Handler has copied .data and zeroed .bss.
Postcondition
The verdict banner is on the console; the CPU is parked in WFI.
Since
0.1.0

Definition at line 364 of file main.c.

References ra8_npu_job_t::cmd_stream, g_npu_vela_check, g_npu_vela_id, g_npu_vela_pass, internal_npu_vela_emit(), internal_npu_vela_park(), internal_npu_vela_run_job(), internal_npu_vela_setup_or_halt(), internal_npu_vela_verify(), k_ra8_ok, ra8_npu_init(), and ra8_npu_read_id().

Variable Documentation

◆ g_npu_vela_check

volatile uint32_t g_npu_vela_check = 0U

Output checkword captured after verify, for external inspection.

volatile + non-static so a debugger can read the result digest.

Note
Read externally only.
Since
0.1.0

Definition at line 113 of file main.c.

Referenced by main().

◆ g_npu_vela_id

volatile uint32_t g_npu_vela_id = 0U

NPU_ID captured after init, for external (J-Link) inspection.

volatile + non-static so a debugger can read it; firmware writes once.

Note
Read externally only.
Since
0.1.0

Definition at line 104 of file main.c.

Referenced by main().

◆ g_npu_vela_pass

volatile uint32_t g_npu_vela_pass = 0U

Final verdict (1 = PASS, 0 = FAIL), for external inspection.

volatile + non-static so a memprobe can read the verdict.

Note
Read externally only.
Since
0.1.0

Definition at line 122 of file main.c.

Referenced by main().

◆ s_npu_vela_arena

uint8_t s_npu_vela_arena[k_npu_vela_arena]
static

Runtime arena the loader carves the output activation from.

Passed to ra8_npu_load() as the runtime region backing store; the NPU (fake) writes the model output here.

Note
Written by the NPU (fake), read back by the app.
Since
0.1.0

Definition at line 95 of file main.c.

Referenced by internal_npu_vela_run_job().