The header scan (Captain Bob, 2026-11-10): 788 source files -- 351 with the
SL-1.0 header, 12 with the old name (docs/working/experiments, kept by
ruling), 31 under someone else's licence (tools/kconfig, Linux's, GPL-2.0:
kept), and 394 with none. Ruled: the SPDX form; capsules (.4th, .f18) and
proofs (.thy) left for a ruling of their own (mkcapsule's 64x16 block format,
content-addressed capsules).
253 files now begin
SPDX-License-Identifier: LicenseRef-Starship-1.0
Copyright (c) 2023-2026 Robert A. James
as a /* */ block (C, headers, assembly, linker scripts) or # lines (scripts,
Makefiles, Kconfig; below a shebang or a coding line); tools/mkcapsule.c,
which had the copyright line, gets the SPDX line only.
Not touched: docs/working/ (archive and old campaign material, as the
ruling kept the experiments); v4/system/post_cases.c (generated by
v4/tools/mkpost.py, "do not edit" -- the generator has the header).
Comments only: the kernel builds on amd64, aarch64, riscv64; make -C v4
test-32: 39 programs, 0 failures; every changed script parses.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GE3SDvQn5EoxdGufk84zz2
107 lines
4.2 KiB
C
107 lines
4.2 KiB
C
/* SPDX-License-Identifier: LicenseRef-Starship-1.0
|
|
* Copyright (c) 2023-2026 Robert A. James
|
|
*/
|
|
/* test_host_rom_range.c -- the ROM is the machine's: read and run, never written.
|
|
*
|
|
* docs/v4.0.0/MACHINE.md section 2, DATASHEET-F18.md section 5. The ROM is a
|
|
* read-only range at V4_ROM_BASE, above RAM. An instruction fetch, an @p
|
|
* literal and a data fetch there read the ROM; a running programme's store
|
|
* there is an address fault. Like every device in the model it is attached
|
|
* by the node's owner, and a reset detaches it.
|
|
*/
|
|
#include "v4/asm.h"
|
|
#include "v4/testcode.h"
|
|
#include <stdio.h>
|
|
|
|
static int failures = 0, checks = 0;
|
|
#define CHECK(c,...) do{checks++; if(!(c)){failures++; printf("FAIL %s:%d: ",__FILE__,__LINE__); printf(__VA_ARGS__); printf("\n");}}while(0)
|
|
|
|
static v4_node n, scratch;
|
|
static v4_exec_state es;
|
|
static v4_heat h;
|
|
static v4_cell rom[16];
|
|
|
|
/* ROM words 0..: "7 ;" at ROM+0, then a cell holding 42 at ROM+8 */
|
|
static void build_rom(void)
|
|
{
|
|
v4_asm ra;
|
|
unsigned i;
|
|
v4_node_reset(&scratch);
|
|
v4_asm_begin(&ra, &scratch, 0);
|
|
v4_asm_lit(&ra, 7);
|
|
v4_asm_op(&ra, V4_OP_SEMI);
|
|
CHECK(v4_asm_ok(&ra), "the ROM's code assembles");
|
|
for (i = 0; i < 16; i++) rom[i] = scratch.mem[i];
|
|
rom[8] = 42;
|
|
}
|
|
|
|
int main(void)
|
|
{
|
|
v4_asm as;
|
|
long r;
|
|
|
|
build_rom();
|
|
v4_node_reset(&n);
|
|
v4_exec_reset(&es);
|
|
v4_heat_reset(&h);
|
|
CHECK(V4_ROM_BASE == (v4_cell)V4_NODE_WORDS, "the ROM starts where RAM ends");
|
|
CHECK(v4_node_load(&n, V4_ROM_BASE) == 0, "no ROM attached: nothing there");
|
|
v4_node_rom_attach(&n, rom, 16);
|
|
CHECK(v4_node_load(&n, V4_ROM_BASE) == rom[0], "the ROM reads");
|
|
CHECK(v4_node_load(&n, V4_ROM_BASE + 16) == 0, "past the ROM's words: nothing");
|
|
v4_node_store(&n, V4_ROM_BASE, 12345);
|
|
CHECK(v4_node_load(&n, V4_ROM_BASE) == rom[0] && n.faults == 0, "C code's store into the ROM does nothing and counts no fault (node.h)");
|
|
|
|
/* RAM 16: call the ROM's word, then return */
|
|
v4_asm_begin(&as, &n, 16);
|
|
v4_asm_branch(&as, V4_OP_CALL, V4_ROM_BASE);
|
|
v4_asm_op(&as, V4_OP_SEMI);
|
|
CHECK(v4_asm_ok(&as), "a call into the ROM assembles");
|
|
r = v4_test_call(&n, &es, &h, 16, 100);
|
|
CHECK(r > 0, "the call returns");
|
|
CHECK(n.ds.depth == 1 && n.ds.t == 7, "code in the ROM runs: depth %u T %ld", n.ds.depth, (long)n.ds.t);
|
|
|
|
/* RAM 32: fetch the ROM's cell 8 through A */
|
|
v4_dstack_reset(&n.ds);
|
|
v4_asm_begin(&as, &n, 32);
|
|
v4_asm_lit(&as, V4_ROM_BASE + 8);
|
|
v4_asm_op(&as, V4_OP_BANG_A);
|
|
v4_asm_op(&as, V4_OP_FETCH_A);
|
|
v4_asm_op(&as, V4_OP_SEMI);
|
|
CHECK(v4_asm_ok(&as), "a fetch from the ROM assembles");
|
|
r = v4_test_call(&n, &es, &h, 32, 100);
|
|
CHECK(r > 0 && n.ds.depth == 1 && n.ds.t == 42, "a data fetch reads the ROM: T %ld", (long)n.ds.t);
|
|
|
|
/* RAM 48: store 99 into the ROM's cell 8 through B */
|
|
v4_dstack_reset(&n.ds);
|
|
v4_asm_begin(&as, &n, 48);
|
|
v4_asm_lit(&as, V4_ROM_BASE + 8);
|
|
v4_asm_op(&as, V4_OP_BANG_B);
|
|
v4_asm_lit(&as, 99);
|
|
v4_asm_op(&as, V4_OP_STORE_B);
|
|
v4_asm_op(&as, V4_OP_SEMI);
|
|
CHECK(v4_asm_ok(&as), "a store into the ROM assembles");
|
|
r = v4_test_call(&n, &es, &h, 48, 100);
|
|
CHECK(r < 0, "a store into the ROM does not return");
|
|
CHECK(n.fault_kind == V4_FAULT_ADDRESS && n.fault_addr == V4_ROM_BASE + 8,
|
|
"it is an address fault at the ROM's address: kind %u addr %ld", n.fault_kind, (long)n.fault_addr);
|
|
CHECK(v4_node_load(&n, V4_ROM_BASE + 8) == 42, "and the ROM is unchanged");
|
|
|
|
/* C code's store does nothing there either */
|
|
v4_node_store(&n, V4_ROM_BASE + 8, 99);
|
|
CHECK(v4_node_load(&n, V4_ROM_BASE + 8) == 42, "v4_node_store leaves the ROM alone");
|
|
|
|
/* a reset detaches it, as it does every device */
|
|
v4_node_reset(&n);
|
|
CHECK(v4_node_load(&n, V4_ROM_BASE) == 0, "a reset detaches the ROM");
|
|
v4_node_rom_attach(&n, rom, 16);
|
|
CHECK(v4_node_load(&n, V4_ROM_BASE) == rom[0], "and the owner attaches it again");
|
|
|
|
/* more words than the range holds are refused: nothing attached */
|
|
v4_node_rom_attach(&n, rom, V4_ROM_WORDS + 1u);
|
|
CHECK(v4_node_load(&n, V4_ROM_BASE) == 0, "a ROM larger than the range is not attached");
|
|
|
|
printf("test_host_rom_range: %d checks, %d failures\n", checks, failures);
|
|
return failures != 0;
|
|
}
|