ENGINE.md step 2, the carrier. Ruled 2026-10-05 (V3-PARITY.md 1i), on DECOMPOSITION.md section 6: a write to a port blocks until the neighbour reads. - node: v4_node_port_attach, v4_node_port_served; a store to the port keeps the value as the request and blocks the node - exec: a blocked node executes nothing; served, it goes on from the opcode after the store, in the same instruction word; a fault meanwhile abandons the rest of the word - compile.v4: n KERNEL-WORD name makes a word whose body writes n to the port; its arguments and results are on the data stack - boot: the kernel's words are made by handing the node text, and requests are served between the node's opcodes; one no one serves is error 12 - BYE, the first kernel word: hosted it leaves the program, as hosted v3; on the lone node it is v3's cold restart - ENGINE.md 3a: multiuser, multitasking, preemptive and cooperative, and what that asks of the engine Verified: make -C v4 test passes at both widths, with tests/test_port.c; hosted-check passes on three ISAs; clean qemu with STARFORTH_V4=1 on amd64, aarch64 and riscv64 passes POST with the same hashes as hosted, and a kernel word no one serves and BYE typed at each prompt are answered (logs/20261005-185506, -185734, -190101; -185234 is an amd64 run in which those two lines were not typed). Not done: v3's own C functions serving a node. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
134 lines
6.5 KiB
Markdown
134 lines
6.5 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` | The assembled words, as a memory image linked into the binary |
|
|
| 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 words=296 image_hash=0x736921433a2e0e97
|
|
PARITY:V4_CAPSULE name=v4:forth79.4th capsule_id=... dict_hash=0x01a3a48159f28a3e
|
|
PARITY:V4_POST tests=550 pass=550 fail=0
|
|
PARITY:V4_CAPSULE name=v4:post79.4th capsule_id=... dict_hash=0x212b7b70848080e7
|
|
PARITY:OK
|
|
POST: PASSED
|
|
ok>
|
|
```
|
|
|
|
Bare-metal logs: `logs/20261005-185506/amd64/`, `logs/20261005-185734/aarch64/`,
|
|
`logs/20261005-190101/riscv64/`. On each, six lines were then typed at the
|
|
prompt through the serial port — a definition, its use with the capsule's
|
|
`U*`, an unknown word, 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 handed a line** (`docs/v4.0.0/ENGINE.md` 3.1). It does not read
|
|
its own command line and prints no prompt. Its host puts the text in the
|
|
node's input buffer and starts it at `(LINE)`; the node interprets the text
|
|
and stops at `(IDLE)`, leaving in `(LINE-STATUS)` how it ended. The host says
|
|
` ok` or ` ERROR` and prompts, as the kernel's REPL does for a v3 VM. A line
|
|
may be 1024 characters, a block. `v4_line_begin`, `v4_line_done` and
|
|
`v4_line_status` (`v4/include/v4/image.h`) are that interface;
|
|
`v4_boot_line` (`v4/system/boot.c`) is the one loop the hosted binary, the
|
|
kernel and the capsule loader all run it with.
|
|
|
|
**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).
|
|
|
|
**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`: 550 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.
|