From 42f8a13914eb7a8e58c992ace30c1ebcf3c0248d Mon Sep 17 00:00:00 2001 From: rajames Date: Thu, 15 Oct 2026 11:10:08 -0400 Subject: [PATCH] docs(v4.0.0): the ROM is shared code, GA144-style -- an entry table, a permanent state area Co-Authored-By: Claude Opus 5.5 --- docs/v4.0.0/DATASHEET-F18.md | 3 +++ docs/v4.0.0/MACHINE.md | 23 ++++++++++++++++++ .../plans/2026-10-15-machine-step1-rom.md | 24 ++++++++++++++----- 3 files changed, 44 insertions(+), 6 deletions(-) diff --git a/docs/v4.0.0/DATASHEET-F18.md b/docs/v4.0.0/DATASHEET-F18.md index 04189a2f..06c22657 100644 --- a/docs/v4.0.0/DATASHEET-F18.md +++ b/docs/v4.0.0/DATASHEET-F18.md @@ -99,6 +99,9 @@ registers (§10.3). - **ROM.** Designed, not built: `MACHINE.md` §2, and plan Task 1. It is a read-only range at `V4_NODE_WORDS` and above. It can be fetched and executed. A store there is an address fault. A reset keeps it. + - Its routines are shared code, GA144-style (`MACHINE.md` 2.1). Payloads call them through + the entry table at the ROM's base. Their state lives in a reserved RAM area. This sheet will + list each entry's stack effect and the registers it uses once the ROM is built. ## 6. Instruction word diff --git a/docs/v4.0.0/MACHINE.md b/docs/v4.0.0/MACHINE.md index 9e826d14..831a38ca 100644 --- a/docs/v4.0.0/MACHINE.md +++ b/docs/v4.0.0/MACHINE.md @@ -60,6 +60,29 @@ width (32 and 64 bits). **Read-only.** A store into the ROM is an address fault. Seal and `COLD` never go below it. +### 2.1 The ROM is shared code, GA144-style (ruled 2026-10-15) + +The ROM is both the tractor's engine and part of the payload's engine. Payload code calls ROM +routines at run time, as GA144 applications call their node ROMs. The routines are: +- the tokenizer; +- number conversion; +- the slot packer, branch placement and resolution, which is the code generator for any + language built on top; +- a generic table from names to values. + +What this asks of the ROM: +- **An entry table at the ROM's base**, one jump per routine. Payloads call through it, never + to an address inside the ROM, so a rebuilt ROM breaks no payload. Each entry's stack effect + and the registers it uses (A, B) are listed in `DATASHEET-F18.md`. +- **A reserved, permanent RAM area** for the routines' state (token buffer, packer state), + fixed in the memory map. Tables needed only while the system assembles may still use + dictionary space and be cleared afterwards. +- **Nothing language-specific.** This is the rule of 7.1, which matters more now that every + payload depends on the ROM. + +Direction (Captain Bob, 2026-10-15): much more GA144-ish. Take what serves from colorForth's +wiring, drop its odd concepts, add our own. That is what v4 becomes, on the way to v5 and later. + ## 3. The boot 1. **The machine.** The engine is reset and runs the ROM. diff --git a/docs/v4.0.0/plans/2026-10-15-machine-step1-rom.md b/docs/v4.0.0/plans/2026-10-15-machine-step1-rom.md index 2d4e19c9..123f594b 100644 --- a/docs/v4.0.0/plans/2026-10-15-machine-step1-rom.md +++ b/docs/v4.0.0/plans/2026-10-15-machine-step1-rom.md @@ -48,9 +48,11 @@ notation, Python 3 (the one-time `.v4` → `.f18` converter), GNU make. branch that goes somewhere else. Test in Task 5. 3. **A symbol defined twice, or an opcode or reserved word used as a name.** Expected: the same errors as `text.c`'s `define`. Test in Task 4. -4. **The ROM's scratch (symbol table, token buffer) left in RAM after assembly.** Expected: it is - zeroed before `start` jumps, so nothing of the building is left behind (as `mkimage.c` today). - Test in Task 8, in the whole-memory comparison. +4. **The ROM's assembly-only tables (symbol table, references) left in RAM after assembly.** + Expected: they are zeroed before `start` jumps, so nothing of the building is left behind (as + `mkimage.c` today). The routines' permanent state area (MACHINE.md 2.1) is not cleared: it + belongs to the ROM. Test in Task 8, in the whole-memory comparison, which leaves out exactly + that area. 5. **The console input running dry between blobs.** Expected: the ROM waits on CONSOLE-STATUS and does not take the absence of a character as the end. Test in Task 3. @@ -207,6 +209,15 @@ through the fault table rather than a field, check it the way `v4/tests/test_gua `void rom_boot(v4_node *n);` (attach the ROM and the console input), `int rom_call(v4_node *n, const char *name, unsigned max_steps);` (push a return to an idle word, set P, run until it returns; 1 if it returned). +- **The entry table (MACHINE.md 2.1).** `main.f18` starts at `V4_ROM_BASE` with one `jump` per + public routine, in a fixed order: `(KEY) (TOKEN) (NUMBER) (FIND) (DEFINE) (OP) (LIT) + (BRANCH) (BRANCH>) (RESOLVE) (LABEL)`, then the ROM's entry. Each task adds its routines' + entries. Tests call routines only through the entry table, as a payload would. `rom-.sym` + still names every internal routine, for debugging. +- **State area.** The routines' state (`(TOK)`, `(LINE)`, the packer's `(HERE) (CUR) (SLOT) + (LITS) (NLIT)`) lives in a reserved RAM area, a constant of the memory map next to + `host_map.h`'s others, outside dictionary space. The assembly-only tables (Task 4's symbol + table and pool, Task 6's references) live in dictionary space. - ROM routines from `in.f18` (the console input is `CONSOLE-RX`/`CONSOLE-STATUS`, as `host_map.h`): - `(KEY) ( -- c )`: wait while CONSOLE-STATUS is 0, then fetch CONSOLE-RX. @@ -320,7 +331,7 @@ labels local to a word and settled at `end_word`, a bare name as a call (now or `main.f18` holds the ROM's entry at `V4_ROM_BASE`: clear its scratch, then loop `(TOKEN)` / directive or `(ONE)`, stopping at an error or at `start`. On error it writes `(ERR)` to CONSOLE-TX and halts at a known address `(ROM-FAILED)`. `start NAME` does `text.c` -`v4_text_finish` (resolve every reference, "never defined"), zeroes the scratch (Review +`v4_text_finish` (resolve every reference, "never defined"), zeroes the assembly-only tables (Review Focus 4), and jumps to NAME. - [ ] **Step 1: Write the failing test.** Five cases: - `#, 5 ", DUP store 9000 7 set L here #, L` with `start` to a word that does `;`: @@ -328,7 +339,8 @@ Focus 4), and jumps to NAME. - A blob split over two feeds, with an EOT only after the second, and a forward call resolved by a word in the second (Review Focus 1). - A reference never defined: error, and P at `(ROM-FAILED)`. - - After `start`, every scratch cell is zero. + - After `start`, every assembly-only table cell is zero, and the state area is as the last + routine left it. - A header written in the directive form gives the same memory as `text.c`'s `header` for the same name and flags. - [ ] **Step 2: Run it and see it fail.** @@ -355,7 +367,7 @@ token for token. `map-.f18` holds: `mkimage.c` does (`host_load`, `v4_text_finish`, `main`'s stores) and node B by feeding the ROM `map-.f18` (constants), the 14 `sys/*.f18` files in order, then the rest of `map-.f18`, then EOT. Run B until P reaches `(IDLE)`. Require every RAM word equal, A to - B. On a difference, print the first address and the symbol at or below it. + B, outside the ROM's state area. On a difference, print the first address and the symbol at or below it. - [ ] **Step 2: Run it and see it fail.** - [ ] **Step 3: Write `v4tof18.py`, generate the files, and fix the ROM** until the memory is equal at both widths. Fix the ROM, not the test. The test is `text.c` and `mkimage.c` as they