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

Core of the #208 block/frame-size sweep (--sweep-block). More...

#include "sweep_block.h"
#include <string.h>
#include "miniz.h"
#include "ra8_err.h"
#include "ra8_vmem.h"
#include "ra8_vsource.h"
#include "sweep_block_internal.h"
Include dependency graph for sweep_block.c:

Go to the source code of this file.

Data Structures

struct  cbs_cache_t
 One ::ra8_vmem instance sized for a swept block size + its storage. More...

Enumerations

enum  cbs_block_size_t : uint32_t {
  k_cbs_block_512b = 512U ,
  k_cbs_block_1kib = 1024U ,
  k_cbs_block_4kib = 4096U ,
  k_cbs_block_16kib = 16384U ,
  k_cbs_block_64kib = 65536U ,
  k_cbs_block_256kib = 262144U
}
 The swept block / frame / chunk sizes, in bytes. More...
enum  cbs_leg_t : uint8_t {
  k_cbs_leg_seq = 0U ,
  k_cbs_leg_hot = 1U ,
  k_cbs_leg_count = 2U
}
 Leg indices for internal_run_block's per-leg loop. More...

Functions

void ra8_log_emit_error (const char *tag, const char *message)
 Log backend stub so ra8_check's RA8_CHECK_* macros link host-side.
void ra8_log_emit_error_val (const char *tag, const char *message, uint32_t value)
 Valued log backend stub (present for the linker, as reader_vmem).
static uint32_t internal_pow2_ceil (uint32_t v)
 Round v up to a power of two (>= 1).
static void internal_cache_close (cbs_cache_t *c)
 End a cbs_cache_t's borrowed workspace bindings (idempotent).
static size_t internal_align_size (size_t value)
 Round a workspace span to maximum fundamental alignment.
static void * internal_workspace_take (cb_sweep_config_t *config, size_t *used, size_t bytes)
 Take one aligned region from the caller-owned sweep workspace.
static int internal_cache_storage (cbs_cache_t *c, uint32_t block_bytes, cb_sweep_config_t *config, uint32_t *out_buckets)
 Carve and clear exact cache metadata from caller-owned bindings.
static int internal_cache_open (cbs_cache_t *c, const cbs_backend_t *be, uint32_t blob_bytes, uint32_t block_bytes, cb_sweep_config_t *config)
 Stand up a real ::ra8_vmem cache with frame_bytes == block_bytes.
static int internal_drive (cbs_cache_t *c, ra8_vsource_read_fn payload_read, void *payload_ctx, uint64_t n_reads, uint64_t wrap_bytes, cbs_row_t *row)
 Drive one timed leg: n_reads requests of k_cbs_req_bytes each, at offsets (i * req) % wrap_bytes, verifying every byte returned.
static int internal_run_block (cbs_backend_t *be, ra8_vsource_read_fn payload_read, void *payload_ctx, uint32_t block_bytes, cbs_row_t *rows, uint32_t *nrows, cb_sweep_config_t *config)
 Run both legs of one (backend, block size) combination.
static int internal_execute (cb_sweep_config_t *config, cbs_payload_t *payload, cbs_backend_t *backends, uint32_t backend_count, cbs_row_t *rows, uint32_t *row_count)
 Execute every backend and block-size pair and append its result rows.
static int internal_summary (cb_sweep_config_t *config, const cbs_backend_t *backends, uint32_t backend_count, const cbs_row_t *rows, uint32_t row_count)
 Publish all human summary tables and the crossover verdict.
int cb_sweep_block (cb_sweep_config_t *config)
 Run the #208 block/frame-size sweep and print the report.

Variables

static const char *const s_cbs_leg_names [k_cbs_leg_count] = {"seq", "hot"}
 Report names for the two workload legs, indexed by cbs_leg_t.
static const uint32_t s_cbs_blocks []
 The swept block sizes, ascending (drives loops + knee search).

Detailed Description

Core of the #208 block/frame-size sweep (--sweep-block).

Drives the REAL ::ra8_vmem SLRU page cache (not a re-modelled policy) with frame_bytes swept from 512 B to 256 KiB under a constant byte budget, over the backends published by priv_backends() (the cbs_backend_t seam; implementations live in src/sweep_block_backends.c). Leg (a) scans the whole object sequentially; leg (b) re-reads one block. Every byte handed back by the cache is verified against the source blob. Row printing and the summary report live in src/sweep_block_report.c.

[Ring 7 / Tooling] {World: NS}

Since
0.1.0

Definition in file sweep_block.c.

Enumeration Type Documentation

◆ cbs_block_size_t

enum cbs_block_size_t : uint32_t

The swept block / frame / chunk sizes, in bytes.

Powers of two from one SD sector up to a quarter MiB, bracketing the 64 KiB .rabook chunk default (#204) by two octaves on each side so the knee is visible whichever way it falls.

Since
0.1.0
Enumerator
k_cbs_block_512b 

One SD sector.

k_cbs_block_1kib 

1 KiB.

k_cbs_block_4kib 

Classic VM page size.

k_cbs_block_16kib 

16 KiB.

k_cbs_block_64kib 

The current .rabook chunk default.

k_cbs_block_256kib 

256 KiB (frame RAM gets expensive).

Definition at line 39 of file sweep_block.c.

◆ cbs_leg_t

enum cbs_leg_t : uint8_t

Leg indices for internal_run_block's per-leg loop.

Enumerator
k_cbs_leg_seq 

Sequential whole-object scan.

k_cbs_leg_hot 

Same-block re-read loop.

k_cbs_leg_count 

Number of legs.

Definition at line 398 of file sweep_block.c.

Function Documentation

◆ cb_sweep_block()

int cb_sweep_block ( cb_sweep_config_t * config)

Run the #208 block/frame-size sweep and print the report.

For every registered backend and every swept block size (512 B .. 256 KiB), builds the backing, stands up a real ::ra8_vmem cache with frame_bytes equal to the swept size under a constant byte budget, and drives legs (a) sequential whole-object scan and (b) same-block re-read. Prints one machine-parseable sweep-block ... line per row, then a human summary with the measured knee and a chunk-size recommendation versus the current 64 KiB .rabook default (#204). Every returned byte is verified against the source blob, so a lying backend fails the run instead of skewing it.

Parameters
[in,out]configCaller-owned cache, workspace, scratch, and sinks.
Returns
int Process-style status.
Return values
0Sweep completed; every row verified byte-identical.
1Capacity, backend setup, I/O, or data-verification failure.
Precondition
config supplies exactly 1 MiB of aligned cache backing, bounded metadata workspace, a scratch transaction, and output/error sinks.
The scratch callbacks complete exact positional transfers.
Postcondition
On 0, one row per (backend, leg, size) was printed plus the summary.
No storage ownership changes; scratch and workspace remain caller-owned.
Note
Not thread-safe (single-threaded host tool; static backend state).
See also
cbs_backend_t The seam a future SD-over-SPI hardware leg implements.
Since
0.1.0

Definition at line 608 of file sweep_block.c.

References cb_sweep_config_t::cache_capacity, cb_sweep_config_t::cache_required, cb_sink_format(), cb_sweep_config_t::error, internal_align_size(), internal_execute(), internal_summary(), k_cb_io_ok, k_cbs_blob_bytes, k_cbs_cache_bytes, k_cbs_hot_reads, k_cbs_max_rows, k_cbs_req_bytes, k_cbs_seq_passes, cb_sweep_config_t::output, priv_backends(), priv_payload_init(), priv_payload_workspace_required(), cb_sweep_config_t::scratch, cb_sweep_config_t::workspace, cb_sweep_config_t::workspace_capacity, cb_sweep_config_t::workspace_floor, cb_sweep_config_t::workspace_required, and cb_sweep_config_t::workspace_used.

Referenced by internal_run_sweep().

◆ internal_align_size()

size_t internal_align_size ( size_t value)
static

Round a workspace span to maximum fundamental alignment.

Applies the power-of-two alignment mask used by every metadata partition in this bounded sweep composition.

Parameters
[in]valueUnaligned byte count.
Returns
Smallest aligned byte count not less than value.
Return values
otherAligned span used for workspace partitioning.
Precondition
value plus the alignment bias fits in size_t by sweep geometry.
alignof(max_align_t) is a non-zero power of two.
Postcondition
The result is a multiple of alignof(max_align_t).
No storage is read or modified.
Note
Thread-safe: this is a pure arithmetic helper.
Since
0.1.0

Definition at line 160 of file sweep_block.c.

Referenced by cb_sweep_block(), and internal_workspace_take().

◆ internal_cache_close()

void internal_cache_close ( cbs_cache_t * c)
static

End a cbs_cache_t's borrowed workspace bindings (idempotent).

Frees the frame storage, per-frame metadata, key-storage, and bucket arrays, then zeroes the bundle so a repeat call is a safe no-op. Called on every leg exit and on any partial internal_cache_open failure.

Parameters
[in,out]cCache bundle to release (NULL tolerated as a no-op).
Precondition
c is NULL, or its buffers came from internal_cache_open.
Called on the single benchmark thread.
Postcondition
c is all-zero; caller-owned backing remains reusable.
The embedded ::ra8_vmem is no longer usable until reopened.
Note
Safe for distinct cache/workspace bindings.
Since
0.1.0

Definition at line 137 of file sweep_block.c.

Referenced by internal_cache_open(), and internal_run_block().

◆ internal_cache_open()

int internal_cache_open ( cbs_cache_t * c,
const cbs_backend_t * be,
uint32_t blob_bytes,
uint32_t block_bytes,
cb_sweep_config_t * config )
static

Stand up a real ::ra8_vmem cache with frame_bytes == block_bytes.

The byte budget k_cbs_cache_bytes is constant across sizes, so the frame count is budget / block (min 1) and the bucket count is the next power of two above twice the frames (min k_cbs_bucket_min). The backend is wired in through the vsource-seam meter so meter.calls counts storage commands.

Parameters
[out]cCache bundle to populate.
[in]beBackend with a live read (post-setup).
[in]blob_bytesObject length in bytes.
[in]block_bytesSwept frame size in bytes.
[in,out]configCaller cache/workspace bindings and diagnostics.
Returns
int 0 on success, 1 on capacity or init failure.
Return values
0c is cold and ready for ra8_vmem_get.
1A NULL/zero argument, exact capacity, or init step failed.
Precondition
be->setup succeeded for this block size.
c is writable.
Postcondition
On 0, c->vm is cold and ready for ra8_vmem_get.
On 1, no caller-owned storage is retained.
Note
Not thread-safe.
Since
0.1.0

Definition at line 275 of file sweep_block.c.

References cbs_cache_t::buckets, cb_sweep_config_t::cache_backing, cb_sweep_config_t::cache_capacity, cbs_cache_t::frame_mem, cbs_cache_t::frames, internal_cache_close(), internal_cache_storage(), k_cbs_cache_bytes, k_ra8_ok, cbs_cache_t::keys, cbs_cache_t::meta, cbs_cache_t::meter, cbs_cache_t::object_id, cbs_cache_t::objs, priv_meter_read(), ra8_vmem_init(), ra8_vsource_add_paged(), ra8_vsource_init(), ra8_vsource_loader(), cbs_cache_t::vm, and cbs_cache_t::vs.

Referenced by internal_run_block().

◆ internal_cache_storage()

int internal_cache_storage ( cbs_cache_t * c,
uint32_t block_bytes,
cb_sweep_config_t * config,
uint32_t * out_buckets )
static

Carve and clear exact cache metadata from caller-owned bindings.

Derives frame and bucket counts for block_bytes, binds the fixed cache backing, and partitions metadata from the small workspace.

Parameters
[out]cCache bundle receiving all borrowed regions.
[in]block_bytesSwept cache-frame size.
[in,out]configCaller bindings and exact-capacity diagnostics.
[out]out_bucketsReceives the hash-bucket count.
Returns
Zero when all regions fit, otherwise one.
Return values
0Cache storage is bound and cleared.
1Caller workspace is too small.
Precondition
All pointers are non-NULL and cache backing satisfies cache_capacity.
block_bytes is one of the non-zero swept sizes.
Postcondition
config->workspace_required records the attempted high-water mark.
On success, cache bytes and metadata are zero initialized.
Note
No storage ownership changes.
Since
0.1.0

Definition at line 213 of file sweep_block.c.

References cbs_cache_t::buckets, cb_sweep_config_t::cache_backing, cb_sweep_config_t::cache_capacity, cbs_cache_t::frame_mem, cbs_cache_t::frames, internal_pow2_ceil(), internal_workspace_take(), k_cbs_bucket_min, k_cbs_cache_bytes, cbs_cache_t::keys, memset(), cbs_cache_t::meta, cb_sweep_config_t::workspace_required, and cb_sweep_config_t::workspace_used.

Referenced by internal_cache_open().

◆ internal_drive()

int internal_drive ( cbs_cache_t * c,
ra8_vsource_read_fn payload_read,
void * payload_ctx,
uint64_t n_reads,
uint64_t wrap_bytes,
cbs_row_t * row )
static

Drive one timed leg: n_reads requests of k_cbs_req_bytes each, at offsets (i * req) % wrap_bytes, verifying every byte returned.

wrap_bytes == blob_bytes yields sequential whole-object passes (leg a); wrap_bytes == block_bytes pins the loop inside block 0 (leg b, the pure hit path after one cold fill). The wall clock brackets only this loop – backend setup and container packing are never timed.

Parameters
[in,out]cAn open, cold cbs_cache_t.
[in]payload_readGround-truth byte-source callback.
[in]payload_ctxGround-truth callback context.
[in]n_readsRequests to issue.
[in]wrap_bytesOffset wrap span (see details).
[out]rowRow receiving reads / stats / wall time.
Returns
int 0 on success, 1 on any get/put/verify failure.
Return values
0Every request hit correct bytes; row is fully filled.
1A NULL argument, a get/put error, or a byte mismatch occurred.
Precondition
c was opened by internal_cache_open and is unused (cold).
wrap_bytes is a non-zero multiple of k_cbs_req_bytes.
Postcondition
row->wall_ns, row->reads, and the hit/miss/eviction counters are filled from the cache's own accounting.
The cache holds no pins (every get was put back).
Note
Not thread-safe.
Since
0.1.0

Definition at line 349 of file sweep_block.c.

References ra8_vmem_t::cfg, cbs_row_t::evictions, ra8_vmem_cfg_t::frame_bytes, cbs_row_t::hits, k_cbs_req_bytes, k_ra8_ok, memcmp(), cbs_row_t::misses, cbs_cache_t::object_id, priv_now_ns(), ra8_vmem_get(), ra8_vmem_put(), ra8_vmem_stats(), cbs_row_t::reads, cbs_cache_t::vm, and cbs_row_t::wall_ns.

Referenced by internal_run_block().

◆ internal_execute()

int internal_execute ( cb_sweep_config_t * config,
cbs_payload_t * payload,
cbs_backend_t * backends,
uint32_t backend_count,
cbs_row_t * rows,
uint32_t * row_count )
static

Execute every backend and block-size pair and append its result rows.

Traverses the bounded backend-by-size matrix in stable order and stops at the first failed setup, drive, verification, or report.

Parameters
[in,out]configBound sweep composition.
[in,out]payloadDeterministic payload source.
[in,out]backendsBackend table.
[in]backend_countNumber of backend entries.
[out]rowsFixed result-row array.
[in,out]row_countNumber of valid rows appended.
Returns
Zero after the complete matrix, otherwise one.
Return values
0Every matrix point produced both workload rows.
1One matrix point failed.
Precondition
Output arrays have capacity k_cbs_max_rows.
backend_count and the static size count fit that row capacity.
Postcondition
On success, row_count equals the full matrix row count.
On failure, rows before row_count remain complete and ordered.
Note
Backends are executed serially on the benchmark thread.
Since
0.1.0

Definition at line 534 of file sweep_block.c.

References internal_run_block(), priv_payload_read(), and s_cbs_blocks.

Referenced by cb_sweep_block().

◆ internal_pow2_ceil()

uint32_t internal_pow2_ceil ( uint32_t v)
static

Round v up to a power of two (>= 1).

Starts at 1 and left-shifts until the running value reaches or exceeds v, yielding the smallest power of two not less than v. Used to size the ::ra8_vmem hash-bucket table for a swept frame count.

Parameters
[in]vTarget to round up; both 0 and 1 map to 1.
Returns
uint32_t The smallest power of two that is >= v (never 0).
Return values
1v was 0 or 1.
otherThe next power of two at or above v.
Precondition
v <= 2^31 so the next power of two fits in 32 bits.
Called on the single benchmark thread.
Postcondition
The result is an exact power of two.
The result is >= v and >= 1; no shared state is touched.
Note
Thread-safe: a pure function of v with no shared state.
Since
0.1.0

Definition at line 86 of file sweep_block.c.

Referenced by internal_cache_storage().

◆ internal_run_block()

int internal_run_block ( cbs_backend_t * be,
ra8_vsource_read_fn payload_read,
void * payload_ctx,
uint32_t block_bytes,
cbs_row_t * rows,
uint32_t * nrows,
cb_sweep_config_t * config )
static

Run both legs of one (backend, block size) combination.

Sets the backend up once for the size, then runs each leg on a fresh cold cache; per-leg backend counters are taken as deltas so open-time header/table reads never pollute a leg's traffic numbers. Each finished row is appended and printed immediately.

Parameters
[in,out]beBackend to exercise.
[in]payload_readGround-truth byte-source callback.
[in]payload_ctxGround-truth callback context.
[in]block_bytesSwept block size.
[in,out]rowsRow array (capacity k_cbs_max_rows).
[in,out]nrowsRow count; incremented per finished leg.
[in,out]configCaller workspace, scratch, and report sinks.
Returns
int 0 on success, 1 on any setup / leg failure.
Return values
0Both legs ran; k_cbs_leg_count rows were appended and printed.
1A NULL argument, a backend setup, an open, or a drive failed.
Precondition
rows has space for k_cbs_leg_count more rows.
be has setup and teardown bound.
Postcondition
The backend binding is ended on every path; caller storage is retained.
On 0, k_cbs_leg_count rows were appended and printed.
Note
Not thread-safe.
Since
0.1.0

Definition at line 442 of file sweep_block.c.

References cbs_row_t::be_bytes, cbs_row_t::be_calls, cbs_meter_t::bytes, cbs_meter_t::calls, cbs_cache_t::frames, internal_cache_close(), internal_cache_open(), internal_drive(), k_cbs_blob_bytes, k_cbs_hot_reads, k_cbs_leg_count, k_cbs_leg_seq, k_cbs_req_bytes, k_cbs_seq_passes, cbs_cache_t::meter, cb_sweep_config_t::output, priv_print_row(), s_cbs_leg_names, cbs_row_t::src_bytes, cb_sweep_config_t::workspace_floor, and cb_sweep_config_t::workspace_used.

Referenced by internal_execute().

◆ internal_summary()

int internal_summary ( cb_sweep_config_t * config,
const cbs_backend_t * backends,
uint32_t backend_count,
const cbs_row_t * rows,
uint32_t row_count )
static

Publish all human summary tables and the crossover verdict.

Emits the fixed report heading, both workload tables for each backend, and the measured chunk-size crossover conclusion.

Parameters
[in,out]configBound output composition.
[in]backendsCompleted backend table.
[in]backend_countNumber of backend entries.
[in]rowsCompleted result rows.
[in]row_countNumber of valid rows.
Returns
Zero after complete publication, otherwise one.
Return values
0Every summary fragment was accepted by the sink.
1A table or verdict publication failed.
Precondition
config and backends are non-NULL.
rows contains row_count complete matrix rows.
Postcondition
No result row or backend is modified.
On success, the human-readable report is complete.
Note
Timing values are informational and do not select process exit status.
Since
0.1.0

Definition at line 577 of file sweep_block.c.

References cb_sink_format(), k_cb_io_ok, k_cbs_req_bytes, cb_sweep_config_t::output, priv_print_crossover(), priv_print_hot_table(), priv_print_seq_table(), and s_cbs_blocks.

Referenced by cb_sweep_block().

◆ internal_workspace_take()

void * internal_workspace_take ( cb_sweep_config_t * config,
size_t * used,
size_t bytes )
static

Take one aligned region from the caller-owned sweep workspace.

Advances used only when the aligned request fits completely.

Parameters
[in,out]configSweep configuration carrying workspace storage.
[in,out]usedCurrent cursor, advanced on success.
[in]bytesRequested region size before alignment.
Returns
Borrowed region pointer, or NULL when capacity is insufficient.
Return values
NULLThe aligned request does not fit.
otherPointer to the start of the reserved region.
Precondition
config and used are non-NULL.
config->workspace is valid for workspace_capacity bytes.
Postcondition
On success, used advances by the aligned span.
On failure, used and workspace bytes are unchanged.
Note
Returned storage remains owned by the caller.
Since
0.1.0

Definition at line 183 of file sweep_block.c.

References internal_align_size(), cb_sweep_config_t::workspace, and cb_sweep_config_t::workspace_capacity.

Referenced by internal_cache_storage().

◆ ra8_log_emit_error()

void ra8_log_emit_error ( const char * tag,
const char * message )

Log backend stub so ra8_check's RA8_CHECK_* macros link host-side.

Emit an ERROR-level log line with only a tag and a message.

Definition at line 49 of file sweep_block.c.

◆ ra8_log_emit_error_val()

void ra8_log_emit_error_val ( const char * tag,
const char * message,
uint32_t value )

Valued log backend stub (present for the linker, as reader_vmem).

Emit an ERROR log line with a uint32_t companion value.

Definition at line 56 of file sweep_block.c.

Variable Documentation

◆ s_cbs_blocks

const uint32_t s_cbs_blocks[]
static
Initial value:
= {
(uint32_t)k_cbs_block_512b,
(uint32_t)k_cbs_block_1kib,
(uint32_t)k_cbs_block_4kib,
(uint32_t)k_cbs_block_16kib,
(uint32_t)k_cbs_block_64kib,
(uint32_t)k_cbs_block_256kib,
}
@ k_cbs_block_256kib
256 KiB (frame RAM gets expensive).
Definition sweep_block.c:45
@ k_cbs_block_4kib
Classic VM page size.
Definition sweep_block.c:42
@ k_cbs_block_16kib
16 KiB.
Definition sweep_block.c:43
@ k_cbs_block_512b
One SD sector.
Definition sweep_block.c:40
@ k_cbs_block_64kib
The current .rabook chunk default.
Definition sweep_block.c:44
@ k_cbs_block_1kib
1 KiB.
Definition sweep_block.c:41

The swept block sizes, ascending (drives loops + knee search).

Values come from cbs_block_size_t.

Note
Read-only.
Since
0.1.0

Definition at line 504 of file sweep_block.c.

Referenced by internal_execute(), and internal_summary().

◆ s_cbs_leg_names

const char* const s_cbs_leg_names[k_cbs_leg_count] = {"seq", "hot"}
static

Report names for the two workload legs, indexed by cbs_leg_t.

Read-only.

Note
Only the run/report functions read this.
Since
0.1.0

Definition at line 411 of file sweep_block.c.

Referenced by internal_run_block().