MESH.md step 5, in the fabric under test; the products are still one node each until steps 8 and 9. manage.c: what Hera asks of whoever holds the fabric, eleven requests by KERNEL-WORD -- NODE-ME -BORN -WIRE -UNWIRE -SLEEP -WAKE -KILL -PARITY and CAPSULE-OPEN -CELL -LINE. Nucleus: PORT!, SEND-ON, AWAIT, (SEAL). capsules/v4/hera.4th: BIRTH and UNIT, the unit rule in FORTH and nowhere else. The dictionary hash moves to the engine (v4_image_dict_hash). test_host_unit.c, 34 checks, 64-bit: Hera is born empty, takes the nucleus through her port, FORTH-79, POST and her capsule; 10 UNIT; four nodes are born, each takes the nucleus and FORTH-79 through its port from Hera and passes POST 538/538; four parities, one dictionary hash; they talk, and a message between two corners not wired goes by Hera. All v4 tests at both widths and under ASan+UBSan. hosted-check on three ISAs. Bare metal: logs/20261006-143934 (amd64), -144204 (aarch64), -144601 (riscv64). Open, recorded in MESH.md: not run at 32 bits; a node that never answers leaves Hera waiting; the capsules are read from files in the test, not from the baked directory. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
172 lines
8.8 KiB
Markdown
172 lines
8.8 KiB
Markdown
# v4/
|
|
|
|
StarForth v4: the 32-instruction F18-derived core. The design lives in
|
|
`docs/v4.0.0/JUSTIFICATION.md` (why) and `docs/v4.0.0/DECOMPOSITION.md`
|
|
(every v3 word mapped to a v4 fate).
|
|
|
|
The first deliverable is the hosted C99 golden model (`JUSTIFICATION.md` §10,
|
|
step 1). It must pass POST and hold K≡1.0 with 32- and 64-bit cells on all
|
|
three host ISAs.
|
|
|
|
Acceptance (`JUSTIFICATION.md` §16): v4 must be equivalent to v3 at any point
|
|
in time, with the same vocabularies and behaviour, on the F18-derived engine;
|
|
and every ISA, hosted and bare metal, must still reach its `ok` prompt.
|
|
`make -C v4 test` passing is a development check, not acceptance.
|
|
|
|
What exists so far is the single node: registers, circular stacks, memory, all
|
|
32 opcodes, per-opcode and per-call-target heat, and three console
|
|
registers (`CONSOLE-TX`, which captures output, and `CONSOLE-RX` and `CONSOLE-STATUS`, which hand out
|
|
input a test feeds) standing in for the console node until the mesh exists. The tests load definitions
|
|
onto a node either opcode by opcode (`v4/include/v4/asm.h`) or as text in the notation `DECOMPOSITION.md`
|
|
uses (`v4/include/v4/text.h`). `make -C v4 test` builds
|
|
and runs the tests at both cell widths; `make -C v4 sanitize` repeats them
|
|
under ASan and UBSan. There is no POST and no K measurement yet.
|
|
|
|
## The system: nucleus, capsules, prompt
|
|
|
|
`docs/v4.0.0/NUCLEUS.md` is the design. A v4 system is four things:
|
|
|
|
| Part | Where | What it is |
|
|
|---|---|---|
|
|
| Engine | `v4/src` | The golden model of the 32-opcode node |
|
|
| Nucleus | `v4/capsule/*.v4`, built by `v4/tools/mkimage.c` into `capsules/v4/nucleus-64.f18` | The assembled words, as a capsule of F18 code: sent through its port to a node born empty |
|
|
| Capsules | `capsules/v4/*.4th`, baked by `tools/mkcapsule.c` | FORTH source, loaded when the system comes up |
|
|
| Boot | `v4/system/boot.c` | Starts the nucleus, checks and loads each capsule, prints the parity lines, gives the prompt |
|
|
|
|
Two products link the same four and differ only in the console:
|
|
|
|
- **Hosted Linux**, `v4/tools/hosted.c`: `make -C v4 hosted` builds
|
|
`v4/build/starforth4-amd64`, `-aarch64` and `-riscv64`, static, 64-bit cells.
|
|
- **Bare metal**, `kernel/src/v4/sk_v4.c`: `make -f kernel/Makefile ARCH=<arch> STARFORTH_V4=1`.
|
|
|
|
A boot prints:
|
|
|
|
```
|
|
PARITY:V4_NUCLEUS words=292 image_hash=0x...
|
|
PARITY:V4_CAPSULE name=v4:forth79.4th capsule_id=0x... capsule_hash=0x... dict_hash=0x...
|
|
PARITY:OK
|
|
ok>
|
|
```
|
|
|
|
Every build of one commit prints the same hashes. `make -C v4 hosted-check`
|
|
boots the three hosted binaries (the two foreign ones under user-mode QEMU)
|
|
and fails unless their output is identical and ends in `PARITY:OK`.
|
|
|
|
A capsule line the node does not answer ` ok` to ends the boot, naming the
|
|
capsule, block and line, with `PARITY:FAIL` and `POST: FAILED`.
|
|
|
|
State, 2026-10-05, after `ENGINE.md` step 1: all six builds start the nucleus,
|
|
load `v4:forth79.4th`, pass POST and reach `ok>`, with the same lines:
|
|
|
|
```
|
|
PARITY:V4_NUCLEUS name=v4:nucleus-64.f18 capsule_id=... capsule_hash=0x97a655081b2af559 words=298
|
|
PARITY:V4_CAPSULE name=v4:forth79.4th capsule_id=... dict_hash=...
|
|
PARITY:V4_POST tests=538 pass=538 fail=0
|
|
PARITY:V4_CAPSULE name=v4:post79.4th capsule_id=... dict_hash=...
|
|
PARITY:OK
|
|
POST: PASSED
|
|
ok>
|
|
```
|
|
|
|
Bare-metal logs: `logs/20261006-110551/amd64/`, `logs/20261006-111621/aarch64/`,
|
|
`logs/20261006-111341/riscv64/`. On each, seven lines were then typed at the
|
|
prompt through the serial port — a definition, its use with the capsule's
|
|
`U*`, `COLD`, the capsule word again, a `FORGET` of it (refused), a kernel
|
|
word no one serves, and `BYE` — and each was answered as the hosted binary
|
|
answers it. The
|
|
capsules were unsigned (no signing key on this machine).
|
|
|
|
**A node is sent text as a message** (`docs/v4.0.0/MESH.md` section 6). It
|
|
does not read its own command line, prints no prompt and has no console of
|
|
its own. With nothing to do it is blocked reading its ports. A neighbour
|
|
writes it a message; text for it is interpreted; what it prints goes back
|
|
as messages to the sender, and then a message saying how the text ended.
|
|
Its console says ` ok` or ` ERROR` and prompts, as the kernel's REPL does
|
|
for a v3 VM. A message carries 1024 characters, a block. `v4/src/message.c`
|
|
is the format for a host; `v4_boot_line` (`v4/system/boot.c`) is the
|
|
console both products and the capsule loader use.
|
|
|
|
**A node asks its kernel by writing to its port** (`ENGINE.md` 3.3). The
|
|
write blocks the node until it has been served. A kernel word is a
|
|
dictionary entry made by `n KERNEL-WORD name`, whose body writes `n` to the
|
|
port; its arguments and results are on the data stack. `BYE` is the one
|
|
kernel word so far. A node can be stopped between any two instruction
|
|
words and is blocked while it waits at its port, which is what a system of
|
|
many users and tasks, preemptive and cooperative, needs of it
|
|
(`ENGINE.md` 3a).
|
|
|
|
**The two products have parted** (`ENGINE.md` 3c). They share the engine,
|
|
the FORTH-79 capsule and its POST; their nuclei may differ. The hosted
|
|
product is its own and may become a hosted SDK. The bare-metal product is
|
|
to be LithosAnanke with the node in the StarForth VM's place, and
|
|
everything about word records, the fleet and identity is its alone.
|
|
|
|
**Nodes that talk** (`docs/v4.0.0/MESH.md`) are the next step, ahead of
|
|
making v4 equal v3 on bare metal. Its first part is built and tested in
|
|
the engine: a node has `V4_PORTS` ports; a read from one blocks until the
|
|
neighbour writes and a write until the neighbour reads; a node is born
|
|
empty with `P` at its ports and executes what a neighbour sends it, which
|
|
is how each product's node now gets its nucleus, as a capsule; and
|
|
the fabric (`v4/src/fabric.c`) is the nodes there are and the table of how
|
|
their ports are wired, both of which change while they run. The products
|
|
below are still one node each; they become the five nodes at `MESH.md`
|
|
steps 8 and 9.
|
|
|
|
**Finding the way** (`MESH.md` step 4) is built: a node has a table of
|
|
which port leads toward which node (`ROUTE`, `DEFAULT-ROUTE`, `NO-ROUTES`),
|
|
passes on a message that is not for it, and `SEND`s text to another node;
|
|
`v4/tests/test_host_mesh.c` runs three StarForth nodes in a row. A node
|
|
looks before it begins a message (`MESH.md` section 7a): it takes in what
|
|
its neighbours are waiting to write to it, keeps those messages until it
|
|
has nothing else to do, and writes only to a neighbour that is waiting to
|
|
read -- or, of two neighbours, the one with the lower number may wait.
|
|
`NEIGHBOUR ( node port -- )` tells a node who is on each port. A node with
|
|
no room for one more message lets it go and counts it in `(LOST)`.
|
|
|
|
**Five nodes from nothing** (`MESH.md` step 5) is built and proven in the
|
|
fabric under test: Hera asks whoever holds the fabric for a node
|
|
(`v4/src/manage.c`: `NODE-BORN`, `NODE-WIRE` and the rest), sends it the
|
|
nucleus through the port that joins them, then FORTH-79 and POST a line at
|
|
a time, and joins four such nodes in a square round her
|
|
(`capsules/v4/hera.4th`: `BIRTH`, `UNIT`). `v4/tests/test_host_unit.c`.
|
|
The two products are not yet this: they become the five nodes at steps 8
|
|
and 9.
|
|
|
|
**This is still the lone node.** On bare metal `kernel_main.c` starts it
|
|
before the fleet tables, beside the kernel's own system and not in the VM's
|
|
place. `ENGINE.md` sets out the steps from here; step 1 is done and step 2 is
|
|
part done. `V3-PARITY.md` records the rulings it is built from.
|
|
|
|
**What this does not yet show.** `forth79.4th` holds two definitions, `U*`
|
|
and `U/MOD`. Every other word is still in the assembled nucleus, so POST is
|
|
so far a test of the assembled words. Moving them to the capsule, a group at
|
|
a time with POST after each, is the next step (`NUCLEUS.md` section 8).
|
|
|
|
## POST
|
|
|
|
`capsules/v4/post79.4th`: 538 cases in blocks 7000 up, covering 126 of the
|
|
130 words of the FORTH-79 Required Word Set. 443 are v3's cases with what
|
|
the hosted v3 binary did as the expected result. The other 107, and the 27
|
|
v3 cases left out, are listed with reasons in `docs/v4.0.0/POST79.md`.
|
|
|
|
- `make -C v4 post` boots the amd64 system: the quick check after a change.
|
|
- `make -C v4 hosted-check` boots all three hosted ISAs and compares them.
|
|
- `make -C v4 post79` writes the capsule again (`tools/mkpost.py`,
|
|
`tools/post79_rules.py`); it needs the hosted v3 binary.
|
|
|
|
POST is FORTH: a harness of FORTH-79 words and two nucleus hooks, `(CATCH)`
|
|
and `(EMIT-HOOK)`. It forgets itself when it has finished. The boot passes
|
|
only on seeing POST's tally line with `fail=0` (`v4/system/boot.c`). A colon
|
|
definition broken on purpose (`U/MOD` without its last `SWAP`) fails five
|
|
cases and the boot stops with `POST: FAILED`.
|
|
|
|
Not tested: `KEY`, `EXPECT`, `QUERY` (the keyboard) and `QUIT` (it returns
|
|
without ` ok`).
|
|
|
|
Open: `PAD 42 OVER !` faults on v4, because `PAD` is a byte address and `!`
|
|
takes a cell address (D-1). FORTH-79 expects it to work. The v3 case for it
|
|
is left out until that is ruled.
|
|
|
|
The Required Word Set list in `tools/mkpost.py` was written from memory of
|
|
the standard and has not been checked against the document.
|