docs(v4.0.0): MACHINE.md -- the machine, its ROM, and the capsule: one prebuilt F18 binary, the rest source
For review; nothing built. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
c7bf68fe13
commit
58f3837498
@@ -0,0 +1,128 @@
|
||||
# StarForth v4.0.0 — The Machine, its ROM, and the Capsule
|
||||
|
||||
Design, 2026-10-15. Captain Bob's rulings in conversation the same day, recorded here.
|
||||
Where this file and `NUCLEUS.md` disagree, this file wins: it replaces `NUCLEUS.md`
|
||||
sections 2, 4, 5.3 (what is loaded and by whom), 7 (the nucleus line) and 10. `NUCLEUS.md`
|
||||
section 6 (POST) stands.
|
||||
|
||||
**Status: for review. Nothing here is built.**
|
||||
|
||||
## 1. The idea
|
||||
|
||||
A capsule is a semi-truck. The VM is the tractor. Behind it is the trailer, and the trailer
|
||||
is source.
|
||||
|
||||
The Altair 8800 had the machine and no ROM; a loader was toggled in by hand. v4 has the
|
||||
machine and a ROM.
|
||||
|
||||
| Part | What it is | Where it is |
|
||||
|---|---|---|
|
||||
| **Engine** | Executes the 32 F18 opcodes: registers, stacks, memory, ports. Nothing else. | The C golden model (`v4/src`) now; the FPGA later. The two are the same. |
|
||||
| **ROM** | **The VM.** A prebuilt binary of F18 opcodes. It assembles `.f18` source. It knows no FORTH. | At the head of every capsule; read-only to the node |
|
||||
| **Trailer** | Source, as named blobs. `.f18` is F18 assembler. `.4th` is FORTH. The blob's name gives its type. | The capsule directory (`capsules/`) |
|
||||
|
||||
The ROM is the only binary. It runs the same on the C engine and on the FPGA: one binary, the
|
||||
same behaviour. Assemble FORTH from the trailer and the node is a FORTH machine. Assemble Lisp
|
||||
and it would be a Lisp machine. The engine and the ROM do not change.
|
||||
|
||||
## 2. The ROM
|
||||
|
||||
**What it does.** It reads a named blob and acts on its type:
|
||||
|
||||
- `.f18`: assembles it into the node's memory. Mnemonics to slots, literals, labels and
|
||||
branches, names for addresses.
|
||||
- `.4th`: hands it, a line at a time, to whatever the `.f18` source has built. The ROM itself
|
||||
does not interpret FORTH. Until a `.f18` has built an interpreter, a `.4th` cannot be
|
||||
loaded.
|
||||
|
||||
**What it does not do.** No FORTH: no dictionary layout, no `:`, no `INTERPRET`, no
|
||||
vocabularies. These are `.f18` source.
|
||||
|
||||
**How it is made.** The ROM is written in F18 assembler and assembled once, off the node, as a
|
||||
bitstream is. That build is the only thing done off the node. It produces one ROM per cell
|
||||
width (32 and 64 bits).
|
||||
|
||||
**Read-only.** A store into the ROM is an address fault. Seal and `COLD` never go below it.
|
||||
|
||||
## 3. The boot
|
||||
|
||||
1. **The machine.** The engine is reset and runs the ROM.
|
||||
2. **The primitives.** The loader feeds the system's `.f18` blobs to the ROM, which assembles
|
||||
them. They hold everything written in opcodes: the stack and arithmetic words, the
|
||||
registers and ports, and the FORTH machinery itself (the text interpreter, `:` and `;`,
|
||||
the dictionary).
|
||||
3. **FORTH.** The interpreter just built compiles `forth79.4th`, then the StarForth system
|
||||
`.4th` words. Ruled: the kernel loads `forth79.4th` as the system's own vocabulary, before
|
||||
POST and before `init.4th`, the way v3 registers its words.
|
||||
4. **POST**, with the existing test DSL: the case table `v4/system/post_cases.c` (name, lines,
|
||||
expected error, stack and output) and its runner `v4/system/post.c`. Seal before it,
|
||||
`COLD` after, as now.
|
||||
5. **`init.4th`.** From here the boot is `init.4th` only. It `EXEC`s `starshipos.4th` and sets
|
||||
`STARSHIPOS` as the search vocabulary. No boot policy is written in C.
|
||||
6. `ok>`.
|
||||
|
||||
The **loader** in steps 2 and 3 is whoever owns the machine: the kernel on bare metal, the
|
||||
hosted program on Linux, the ARM side on the Zynq. It finds each blob by name, checks its hash
|
||||
and signature as now (`NUCLEUS.md` 5.3, items 1–3), and gives the source to the node.
|
||||
|
||||
## 4. Other nodes
|
||||
|
||||
A newborn node blocks on its ports and executes what arrives (`v4_node_born`). Hera births a
|
||||
node by streaming it the ROM through the port that joins them, then the `.f18` and `.4th`
|
||||
blobs it is to carry. Today `hera.4th`'s `(NUCLEUS)` streams the prebuilt 311-word nucleus; it
|
||||
streams the ROM instead.
|
||||
|
||||
## 5. What changes
|
||||
|
||||
| Today | Becomes |
|
||||
|---|---|
|
||||
| `v4/capsule/*.v4`, 14 files, 311 words, assembled on the build machine | `.f18` blobs under `capsules/v4/`, assembled by the ROM at boot |
|
||||
| `v4/tools/mkimage.c` → `nucleus-64.f18`, a prebuilt dictionary | Builds the ROM only. The nucleus binary is gone. |
|
||||
| `v4/src/text.c`, the assembler in C | The ROM's assembler is F18 code. `text.c` builds the ROM, as the first assembler builds the next. |
|
||||
| `forth79.4th`: `U*`, `U/MOD` only | Every FORTH-79 word that is not an opcode, a register or the FORTH machinery (`NUCLEUS.md` 4, rule 1). It moves group by group, with POST after each (`NUCLEUS.md` 8, step 3). |
|
||||
| `boot_capsules[]` in `v4/system/boot.c` | The system list (step 2, then step 3) is the loader's. Everything after POST is `init.4th`'s. |
|
||||
| `capsules/v4/starshipos.4th` (uncommitted) | `EXEC`ed by `init.4th` |
|
||||
|
||||
### 5.1 v3 leaves the build
|
||||
|
||||
v3 goes from every build as though it never existed:
|
||||
- the `system=` switch and `STARFORTH_V4=0`;
|
||||
- `v3/src` in the kernel and the hosted `make`;
|
||||
- the v3 VM (`kernel/src/vm/`, `capsule/`);
|
||||
- the v3 capsules;
|
||||
- v3's POST and `PARITY:M7.1a`.
|
||||
|
||||
The Tripod, kernel-Hermes, the C ACL and the v3 PKI words go with it. v4 has rebuilt only the
|
||||
start of the Tripod (`hera.4th`).
|
||||
|
||||
POST needs nothing from v3 at run time. `post_cases.c` is committed. `mkpost.py` needs a v3
|
||||
binary only to write the cases again.
|
||||
|
||||
## 6. Order of work
|
||||
|
||||
1. **The ROM.** Write the F18 assembler in F18 assembler. Build it with `text.c`. On the C
|
||||
engine it must assemble today's `.v4` files to the same memory `mkimage.c` produces.
|
||||
Proof: the same `dict_hash`, `PARITY:V4_POST tests=538 pass=538`.
|
||||
2. **The trailer.** The `.v4` files become `.f18` blobs. The boot runs ROM, then `.f18`, then
|
||||
`forth79.4th`, then POST. `mkimage.c` keeps only the ROM.
|
||||
3. **`init.4th`.** It takes over after POST. `starshipos.4th` is loaded from it.
|
||||
4. **Hera** streams the ROM, not the nucleus.
|
||||
5. **FORTH-79 out of the `.f18`**, group by group, into `forth79.4th`, with POST after each.
|
||||
6. **v3 out of the build.**
|
||||
|
||||
Each step is accepted as `.claude/CLAUDE.md` says:
|
||||
- three ISAs, `clean qemu`, booting v4 to `ok>` with POST passing and `dict_hash` equal across
|
||||
all three;
|
||||
- `make -C v4 test-32`.
|
||||
|
||||
## 7. For Captain Bob to rule
|
||||
|
||||
1. **What the ROM's assembler knows of names.** `text.c` today has `header`, which lays down a
|
||||
FORTH dictionary entry. That is FORTH, so it belongs in `.f18` source. The ROM would know
|
||||
only its own symbols: labels and named addresses. Is that the line?
|
||||
2. **Format of an `.f18` blob.** `.4th` keeps the `Block N` format, 64 × 16. Today's `.v4` has
|
||||
1080 lines over 64 characters. Proposed: `.f18` is plain text with no block format.
|
||||
3. **The `v3/` tree.** Deleted, or kept out of every build but left in the repository? Kept,
|
||||
it lets `mkpost.py` write POST's cases again.
|
||||
4. **ROM size.** It is whatever the assembler and blob reader take. It is set when step 1 is
|
||||
built.
|
||||
Reference in New Issue
Block a user