feat(v4.0.0): POST for FORTH-79, from v3's cases; not passing yet

capsules/v4/post79.4th: 537 of v3's POST cases for the FORTH-79 Required
Word Set, each carrying what the hosted v3 binary did with the same line
(error or not, the stack, the length and checksum of what it printed).
Written by v4/tools/mkpost.py.  The harness is FORTH-79 plus the two
nucleus hooks.  docs/v4.0.0/NUCLEUS.md section 6.

- NODE-ERROR has a FORTH name: how a definition in FORTH raises an error
- the boot passes POST only on seeing its tally line with fail=0
- POST is not in the boot yet (V4_POST_AT_BOOT=0); make -C v4 post runs it

Result: tests=537 pass=439 fail=98.  The 98 are not yet sorted into v4
defects and differences needing a ruling; v4/README.md has a first reading.

Verified: make -C v4 test passes; hosted-check passes on three ISAs; clean
qemu with STARFORTH_V4=1 on amd64, aarch64 and riscv64 reaches ok> with the
same hashes as hosted (logs/20261005-1601xx..1604xx).  Nothing was typed at
a bare-metal prompt.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
rajames
2026-10-05 16:04:48 -04:00
co-authored by Claude Opus 5.5
parent ed6b11ad88
commit 5d6043e37e
11 changed files with 2779 additions and 14 deletions
+67 -2
View File
@@ -1,5 +1,5 @@
# Capsule Block Manifest — Auto-generated # Capsule Block Manifest — Auto-generated
<!-- Generated by mkcapsule --manifest 2026-10-05T19:24:40Z --> <!-- Generated by mkcapsule --manifest 2026-10-05T20:03:22Z -->
<!-- DO NOT EDIT — re-run mkcapsule --manifest to refresh. --> <!-- DO NOT EDIT — re-run mkcapsule --manifest to refresh. -->
<!-- Hand-written justifications and immutability notes live --> <!-- Hand-written justifications and immutability notes live -->
<!-- in MANIFEST.md alongside this auto-generated index. --> <!-- in MANIFEST.md alongside this auto-generated index. -->
@@ -30,6 +30,7 @@
| `turtle.4th` | 5100, 5101, 5102, 5103, 5104, 5105, 5106, 5107, 5108 | `0x4d470418ca543365` | n/a | | `turtle.4th` | 5100, 5101, 5102, 5103, 5104, 5105, 5106, 5107, 5108 | `0x4d470418ca543365` | n/a |
| `user-font-demo.4th` | 4200, 4201, 4202 | `0xce1fd7d1b581a56d` | n/a | | `user-font-demo.4th` | 4200, 4201, 4202 | `0xce1fd7d1b581a56d` | n/a |
| `v4:forth79.4th` | 6000 | `0xa4b74bdc7deaf204` | n/a | | `v4:forth79.4th` | 6000 | `0xa4b74bdc7deaf204` | n/a |
| `v4:post79.4th` | 7000, 7001, 7002, 7003, 7004, 7005, 7006, 7007, 7008, 7009, 7010, 7011, 7012, 7013, 7014, 7015, 7016, 7017, 7018, 7019, 7020, 7021, 7022, 7023, 7024, 7025, 7026, 7027, 7028, 7029, 7030, 7031, 7032, 7033, 7034, 7035, 7036, 7037, 7038, 7039, 7040, 7041, 7042, 7043, 7044, 7045, 7046, 7047, 7048, 7049, 7050, 7051, 7052, 7053, 7054, 7055, 7056, 7057, 7058, 7059, 7060, 7061, 7062, 7063 | `0x24df7b11992128ed` | n/a |
| `workload-0.4th` | 2200, 2201 | `0x93f86f60aeba8feb` | n/a | | `workload-0.4th` | 2200, 2201 | `0x93f86f60aeba8feb` | n/a |
| `workload-1-lite.4th` | 5058, 5059 | `0x44a7a7e3176dcc8d` | n/a | | `workload-1-lite.4th` | 5058, 5059 | `0x44a7a7e3176dcc8d` | n/a |
| `workload-1.4th` | 4406, 4415, 4425, 4435 | `0x63e251adb0a03613` | n/a | | `workload-1.4th` | 4406, 4415, 4425, 4435 | `0x63e251adb0a03613` | n/a |
@@ -368,10 +369,74 @@
| 5114 | `sdk.4th` | `0x008fdbbb62c94a3a` | ok | | 5114 | `sdk.4th` | `0x008fdbbb62c94a3a` | ok |
| 5115 | `sdk.4th` | `0x008fdbbb62c94a3a` | ok | | 5115 | `sdk.4th` | `0x008fdbbb62c94a3a` | ok |
| 6000 | `v4:forth79.4th` | `0xa4b74bdc7deaf204` | ok | | 6000 | `v4:forth79.4th` | `0xa4b74bdc7deaf204` | ok |
| 7000 | `v4:post79.4th` | `0x24df7b11992128ed` | ok |
| 7001 | `v4:post79.4th` | `0x24df7b11992128ed` | ok |
| 7002 | `v4:post79.4th` | `0x24df7b11992128ed` | ok |
| 7003 | `v4:post79.4th` | `0x24df7b11992128ed` | ok |
| 7004 | `v4:post79.4th` | `0x24df7b11992128ed` | ok |
| 7005 | `v4:post79.4th` | `0x24df7b11992128ed` | ok |
| 7006 | `v4:post79.4th` | `0x24df7b11992128ed` | ok |
| 7007 | `v4:post79.4th` | `0x24df7b11992128ed` | ok |
| 7008 | `v4:post79.4th` | `0x24df7b11992128ed` | ok |
| 7009 | `v4:post79.4th` | `0x24df7b11992128ed` | ok |
| 7010 | `v4:post79.4th` | `0x24df7b11992128ed` | ok |
| 7011 | `v4:post79.4th` | `0x24df7b11992128ed` | ok |
| 7012 | `v4:post79.4th` | `0x24df7b11992128ed` | ok |
| 7013 | `v4:post79.4th` | `0x24df7b11992128ed` | ok |
| 7014 | `v4:post79.4th` | `0x24df7b11992128ed` | ok |
| 7015 | `v4:post79.4th` | `0x24df7b11992128ed` | ok |
| 7016 | `v4:post79.4th` | `0x24df7b11992128ed` | ok |
| 7017 | `v4:post79.4th` | `0x24df7b11992128ed` | ok |
| 7018 | `v4:post79.4th` | `0x24df7b11992128ed` | ok |
| 7019 | `v4:post79.4th` | `0x24df7b11992128ed` | ok |
| 7020 | `v4:post79.4th` | `0x24df7b11992128ed` | ok |
| 7021 | `v4:post79.4th` | `0x24df7b11992128ed` | ok |
| 7022 | `v4:post79.4th` | `0x24df7b11992128ed` | ok |
| 7023 | `v4:post79.4th` | `0x24df7b11992128ed` | ok |
| 7024 | `v4:post79.4th` | `0x24df7b11992128ed` | ok |
| 7025 | `v4:post79.4th` | `0x24df7b11992128ed` | ok |
| 7026 | `v4:post79.4th` | `0x24df7b11992128ed` | ok |
| 7027 | `v4:post79.4th` | `0x24df7b11992128ed` | ok |
| 7028 | `v4:post79.4th` | `0x24df7b11992128ed` | ok |
| 7029 | `v4:post79.4th` | `0x24df7b11992128ed` | ok |
| 7030 | `v4:post79.4th` | `0x24df7b11992128ed` | ok |
| 7031 | `v4:post79.4th` | `0x24df7b11992128ed` | ok |
| 7032 | `v4:post79.4th` | `0x24df7b11992128ed` | ok |
| 7033 | `v4:post79.4th` | `0x24df7b11992128ed` | ok |
| 7034 | `v4:post79.4th` | `0x24df7b11992128ed` | ok |
| 7035 | `v4:post79.4th` | `0x24df7b11992128ed` | ok |
| 7036 | `v4:post79.4th` | `0x24df7b11992128ed` | ok |
| 7037 | `v4:post79.4th` | `0x24df7b11992128ed` | ok |
| 7038 | `v4:post79.4th` | `0x24df7b11992128ed` | ok |
| 7039 | `v4:post79.4th` | `0x24df7b11992128ed` | ok |
| 7040 | `v4:post79.4th` | `0x24df7b11992128ed` | ok |
| 7041 | `v4:post79.4th` | `0x24df7b11992128ed` | ok |
| 7042 | `v4:post79.4th` | `0x24df7b11992128ed` | ok |
| 7043 | `v4:post79.4th` | `0x24df7b11992128ed` | ok |
| 7044 | `v4:post79.4th` | `0x24df7b11992128ed` | ok |
| 7045 | `v4:post79.4th` | `0x24df7b11992128ed` | ok |
| 7046 | `v4:post79.4th` | `0x24df7b11992128ed` | ok |
| 7047 | `v4:post79.4th` | `0x24df7b11992128ed` | ok |
| 7048 | `v4:post79.4th` | `0x24df7b11992128ed` | ok |
| 7049 | `v4:post79.4th` | `0x24df7b11992128ed` | ok |
| 7050 | `v4:post79.4th` | `0x24df7b11992128ed` | ok |
| 7051 | `v4:post79.4th` | `0x24df7b11992128ed` | ok |
| 7052 | `v4:post79.4th` | `0x24df7b11992128ed` | ok |
| 7053 | `v4:post79.4th` | `0x24df7b11992128ed` | ok |
| 7054 | `v4:post79.4th` | `0x24df7b11992128ed` | ok |
| 7055 | `v4:post79.4th` | `0x24df7b11992128ed` | ok |
| 7056 | `v4:post79.4th` | `0x24df7b11992128ed` | ok |
| 7057 | `v4:post79.4th` | `0x24df7b11992128ed` | ok |
| 7058 | `v4:post79.4th` | `0x24df7b11992128ed` | ok |
| 7059 | `v4:post79.4th` | `0x24df7b11992128ed` | ok |
| 7060 | `v4:post79.4th` | `0x24df7b11992128ed` | ok |
| 7061 | `v4:post79.4th` | `0x24df7b11992128ed` | ok |
| 7062 | `v4:post79.4th` | `0x24df7b11992128ed` | ok |
| 7063 | `v4:post79.4th` | `0x24df7b11992128ed` | ok |
## Conflicts ## Conflicts
None. None.
--- ---
*37 capsule(s) scanned. Re-run `mkcapsule --manifest <dir>` to refresh.* *38 capsule(s) scanned. Re-run `mkcapsule --manifest <dir>` to refresh.*
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,108 @@
[=3hBdsDxe: loading Boot0002 "UEFI QEMU DVD-ROM QM00005 " from PciRoot(0x0)/Pci(0x1F,0x2)/Sata(0x2,0xFFFF,0x0)
BdsDxe: starting Boot0002 "UEFI QEMU DVD-ROM QM00005 " from PciRoot(0x0)/Pci(0x1F,0x2)/Sata(0x2,0xFFFF,0x0)
[=3hStarKernel UEFI Loader
Loading kernel from ESP...
[CKPT 001] Entered efi_main - ConOut live
RAW SERIAL UP
[CKPT 002] Serial (COM1) initialized
Monolithic build - kernel linked directly
Collecting boot information...
CmdLine: parsed OK
[CKPT 004] Command line parsed
[CKPT 005] Kernel stack allocation decided
[CKPT 006] Boot info collected (ACPI table located)
GOP: linear framebuffer found
[CKPT 007] GOP: linear framebuffer found
[CKPT 008] About to enter ExitBootServices retry loop
EBS...
EBS OK
Calling kernel_main (monolithic)...
_____ _ _ __ _
/ ____| | | |/ / | |
| (___ | |_ __ _ _ __| ' / ___ _ __ _ __ ___| |
\___ \| __/ _` | '__| < / _ \ '__| '_ \ / _ \ |
____) | || (_| | | | . \ __/ | | | | | __/ |
|_____/ \__\__,_|_| |_|\_\___|_| |_| |_|\___|_|
LithosAnanke v2.1.0
Architecture: amd64
Build: Oct 5 2026 16:01:18
UEFI BootServices: EXITED
=== StarKernel Boot Information ===
Memory map entries: 131
Total memory: 1023 MB
Usable memory: 968 MB
===================================
PMM initialized.
PMM statistics:
Total pages: 249248
Free pages : 247725
Used pages : 1523
Total MB : 973
Free MB : 967
Used MB : 5
VMM initialized (mapped RAM, CR3 switched)
VMM initialized (mapped RAM, CR3 switched)
VMM self-test: mapped OK at 0xffff800000000000
VMM self-test complete.
IDT installed.
APIC: init...
APIC: IA32_APIC_BASE MSR=0x00000000fee00900
APIC: stale-ISR drain: 0 EOI(s) issued
APIC: initialized (xAPIC MMIO, TPR=0, SIVR=0x1FF, EOI-clear)
APIC: init done
I/O APIC: init...
I/O APIC: base=0xfec00000, gsi_base=0, overrides=5
override: source=00 gsi=2 flags=0x0000
override: source=05 gsi=5 flags=0x000d
override: source=09 gsi=9 flags=0x000d
override: source=0a gsi=10 flags=0x000d
override: source=0b gsi=11 flags=0x000d
i8042: keyboard ACKed enable-scanning
i8042: IRQ1 enabled in controller config byte
I/O APIC: keyboard IRQ1 routed (masked)
Timer: init...
Timer: init start
Timer: PM_TMR_BLK discovered from FADT at port 1544
Timer: VM mode detected (hypervisor present).
Timer: HPET calibration disabled (VM-exit MMIO would poison timing).
Timer: WARNING: invariant TSC not present under hypervisor.
Timer: continuing in RELATIVE mode (no determinism guarantees).
Timer: RDTSCP not present; using RDTSC (less serialized).
Timer: CPUID frequency unavailable; trying PM Timer...
Timer: trust=1 (0=NONE,1=REL,2=ABS), TSC=2102894063 Hz
Timer: init done
Kernel heap initialized.
Heap statistics:
Total bytes: 536870872
Free bytes: 536870872
Used bytes: 0
Peak bytes: 0
Heap base addr: 24641536
Heap end addr: 561512448
Heartbeat: init...
APIC Timer: calibrating...
APIC Timer: apic_hz=1010732930, tick_hz=100, initial_count=10107329
APIC Timer: configured (masked, ready to start)
Heartbeat: init done
Kernel initialization complete.
Boot successful!
StarForth v4: one host node, the F18-derived engine
PARITY:V4_NUCLEUS words=295 image_hash=0x3ed5d5fc83f0b026
V4: capsule v4:forth79.4th signature: missing (unsigned)
PARITY:V4_CAPSULE name=v4:forth79.4th capsule_id=0xa4b74bdc7deaf204 capsule_hash=0xa4b74bdc7deaf204 dict_hash=0x118de9d37e682ea4
PARITY:OK
ok>
@@ -0,0 +1,82 @@
UEFI firmware (version 2025.11-3ubuntu7.3 built at 15:40:26 on Sep 23 2026)
[=3hBdsDxe: failed to load Boot0002 "UEFI Misc Device" from PciRoot(0x0)/Pci(0x2,0x0): Not Found
BdsDxe: failed to load Boot0003 "UEFI QEMU QEMU USB HARDDRIVE 1-0000:00:04.0-1" from PciRoot(0x0)/Pci(0x4,0x0)/USB(0x0,0x0): Not Found
BdsDxe: loading Boot0004 "UEFI Misc Device 2" from PciRoot(0x0)/Pci(0x6,0x0)
BdsDxe: starting Boot0004 "UEFI Misc Device 2" from PciRoot(0x0)/Pci(0x6,0x0)
[=3hStarKernel UEFI Loader
Loading kernel from ESP...
[CKPT 001] Entered efi_main - ConOut live
Collecting boot information...
[CKPT 004] Command line parsed
[CKPT 005] Kernel stack allocation decided
[CKPT 006] Boot info collected (ACPI table located)
[CKPT 007] GOP: linear framebuffer found
[CKPT 008] About to enter ExitBootServices retry loop
_____ _ _ __ _
/ ____| | | |/ / | |
| (___ | |_ __ _ _ __| ' / ___ _ __ _ __ ___| |
\___ \| __/ _` | '__| < / _ \ '__| '_ \ / _ \ |
____) | || (_| | | | . \ __/ | | | | | __/ |
|_____/ \__\__,_|_| |_|\_\___|_| |_| |_|\___|_|
LithosAnanke v2.1.0
Architecture: aarch64
Build: Oct 5 2026 16:02:10
UEFI BootServices: EXITED
=== StarKernel Boot Information ===
Memory map entries: 108
Total memory: 4093 MB
Usable memory: 4056 MB
===================================
PMM initialized.
PMM statistics:
Total pages: 1039860
Free pages : 1038449
Used pages : 1411
Total MB : 4061
Free MB : 4056
Used MB : 5
VMM initialized (mapped RAM, CR3 switched)
VMM initialized (mapped RAM, CR3 switched)
VMM self-test: mapped OK at 0xffff800000000000
VMM self-test complete.
AArch64: running at EL1
IDT installed.
APIC: init...
PSCI: no DTB -- using HVC (QEMU virt-machine default)
GICv2: no DTB GIC node -- using QEMU virt-machine defaults
GICv2: distributor+CPU interface enabled, PPI 30
APIC: init done
Timer: init...
Timer: AArch64 generic timer initialised.
Timer: init done
Kernel heap initialized.
Heap statistics:
Total bytes: 2147483608
Free bytes: 2147483608
Used bytes: 0
Peak bytes: 0
Heap base addr: 1207959552
Heap end addr: 3355443200
Heartbeat: init...
Heartbeat: init done
Kernel initialization complete.
Boot successful!
StarForth v4: one host node, the F18-derived engine
PARITY:V4_NUCLEUS words=295 image_hash=0x3ed5d5fc83f0b026
V4: capsule v4:forth79.4th signature: missing (unsigned)
PARITY:V4_CAPSULE name=v4:forth79.4th capsule_id=0xa4b74bdc7deaf204 capsule_hash=0xa4b74bdc7deaf204 dict_hash=0x118de9d37e682ea4
PARITY:OK
ok>
@@ -0,0 +1,152 @@
OpenSBI v1.8
____ _____ ____ _____
/ __ \ / ____| _ \_ _|
| | | |_ __ ___ _ __ | (___ | |_) || |
| | | | '_ \ / _ \ '_ \ \___ \| _ < | |
| |__| | |_) | __/ | | |____) | |_) || |_
\____/| .__/ \___|_| |_|_____/|____/_____|
| |
|_|
Platform Name : riscv-virtio,qemu
Platform Features : medeleg
Platform HART Count : 1
Platform HART Protection : pmp
Platform IPI Device : aclint-mswi
Platform Timer Device : aclint-mtimer @ 10000000Hz
Platform Console Device : uart8250
Platform HSM Device : ---
Platform PMU Device : ---
Platform Reboot Device : syscon-reboot
Platform Shutdown Device : syscon-poweroff
Platform Suspend Device : ---
Platform CPPC Device : ---
Firmware Base : 0x80000000
Firmware Size : 321 KB
Firmware RW Offset : 0x40000
Firmware RW Size : 65 KB
Firmware Heap Offset : 0x47000
Firmware Heap Size : 37 KB (total), 0 KB (reserved), 12 KB (used), 23 KB (free)
Firmware Scratch Size : 4096 B (total), 1464 B (used), 2632 B (free)
Runtime SBI Version : 3.0
Standard SBI Extensions : ipi,pmu,srst,sse,hsm,rfnc,fwft,time,base,legacy,dbcn,dbtr
Experimental SBI Extensions : none
Domain0 Name : root
Domain0 Boot HART : 0
Domain0 HARTs : 0*
Domain0 Region00 : 0x0000000080040000-0x000000008005ffff M: (F,R,W) S/U: ()
Domain0 Region01 : 0x0000000080000000-0x000000008003ffff M: (F,R,X) S/U: ()
Domain0 Region02 : 0x0000000000100000-0x0000000000100fff M: (I,R,W) S/U: (R,W)
Domain0 Region03 : 0x0000000010000000-0x0000000010000fff M: (I,R,W) S/U: (R,W)
Domain0 Region04 : 0x0000000002000000-0x000000000200ffff M: (I,R,W) S/U: ()
Domain0 Region05 : 0x000000000c400000-0x000000000c5fffff M: (I,R,W) S/U: (R,W)
Domain0 Region06 : 0x000000000c000000-0x000000000c3fffff M: (I,R,W) S/U: (R,W)
Domain0 Region07 : 0x0000000000000000-0xffffffffffffffff M: () S/U: (R,W,X)
Domain0 Next Address : 0x0000000020000000
Domain0 Next Arg1 : 0x00000000bfe00000
Domain0 Next Mode : S-mode
Domain0 SysReset : yes
Domain0 SysSuspend : yes
Boot HART ID : 0
Boot HART Domain : root
Boot HART Priv Version : v1.12
Boot HART Base ISA : rv64imafdch
Boot HART ISA Extensions : sstc,zicntr,zihpm,zicboz,zicbom,sdtrig,svadu
Boot HART PMP Count : 16
Boot HART PMP Granularity : 2 bits
Boot HART PMP Address Bits : 54
Boot HART MHPM Info : 16 (0x0007fff8)
Boot HART Debug Triggers : 2 triggers
Boot HART MIDELEG : 0x0000000000001666
Boot HART MEDELEG : 0x0000000000f4b509
[=3hRISC-V EDK2 firmware version 2025.11-3ubuntu7.3
Press ESCAPE within 5 seconds for boot options ERROR: C40000002:V03051002 I0 6D33944A-EC75-4855-A54D-809C75241F6C 83FFF850
BdsDxe: failed to load Boot0001 "UEFI Misc Device" fr
om PciRoot(0x0)/Pci(0x1,0x0): Not Found
[=3hStarKernel UEFI Loader
Loading kernel from ESP...
[CKPT 001] Entered efi_main - ConOut live
Monolithic build - kernel linked directly
Collecting boot information...
CmdLine: parsed OK
[CKPT 004] Command line parsed
[CKPT 005] Kernel stack allocation decided
[CKPT 006] Boot info collected (ACPI table located)
GOP: linear framebuffer found
[CKPT 007] GOP: linear framebuffer found
[CKPT 008] About to enter ExitBootServices retry loop
Calling kernel_main (monolithic)...
riscv64 item 4.3.5a: satp state at kernel entry (before switch)
satp.MODE = 0x000000000000000a
satp.PPN = 0x00000000000bf868
__kernel_start = 0x00000000bde99936
riscv64: satp cleared -- Bare mode, explicit (item 4.3.5a)
_____ _ _ __ _
/ ____| | | |/ / | |
| (___ | |_ __ _ _ __| ' / ___ _ __ _ __ ___| |
\___ \| __/ _` | '__| < / _ \ '__| '_ \ / _ \ |
____) | || (_| | | | . \ __/ | | | | | __/ |
|_____/ \__\__,_|_| |_|\_\___|_| |_| |_|\___|_|
LithosAnanke v2.1.0
Architecture: riscv64
Build: Oct 5 2026 16:03:23
UEFI BootServices: EXITED
=== StarKernel Boot Information ===
Memory map entries: 100
Total memory: 1020 MB
Usable memory: 977 MB
===================================
PMM initialized.
PMM statistics:
Total pages: 250775
Free pages : 250123
Used pages : 652
Total MB : 979
Free MB : 977
Used MB : 2
VMM initialized (mapped RAM, CR3 switched)
VMM initialized (mapped RAM, CR3 switched)
VMM self-test: mapped OK at 0xffff800000000000
VMM self-test complete.
IDT installed.
APIC: init...
PLIC: no DTB PLIC node -- using QEMU virt-machine default (base=0x0c000000)
PLIC: init (S-mode context 1, threshold=0)
APIC: init done
Timer: init...
Timer: RISC-V time CSR @ 10000000 Hz (FALLBACK, no devicetree)
Timer: init done
Kernel heap initialized.
Heap statistics:
Total bytes: 536870872
Free bytes: 536870872
Used bytes: 0
Peak bytes: 0
Heap base addr: 2214588416
Heap end addr: 2751459328
Heartbeat: init...
Heartbeat: init done
Kernel initialization complete.
Boot successful!
StarForth v4: one host node, the F18-derived engine
PARITY:V4_NUCLEUS words=295 image_hash=0x3ed5d5fc83f0b026
V4: capsule v4:forth79.4th signature: missing (unsigned)
PARITY:V4_CAPSULE name=v4:forth79.4th capsule_id=0xa4b74bdc7deaf204 capsule_hash=0xa4b74bdc7deaf204 dict_hash=0x118de9d37e682ea4
PARITY:OK
ok>
+14
View File
@@ -129,6 +129,20 @@ $(BINDIR)/boot-$(1).txt: $(BINDIR)/starforth4-$(1)
endef endef
$(foreach i,$(HOSTED_ISAS),$(eval $(call HOSTED_RULE,$(i)))) $(foreach i,$(HOSTED_ISAS),$(eval $(call HOSTED_RULE,$(i))))
# `make post` builds the amd64 system with POST in its boot
# (V4_POST_AT_BOOT=1, system/boot.c) and boots it: the POST capsule,
# ../capsules/v4/post79.4th, is loaded after forth79.4th and must end with a
# clean tally. `make post79` writes that capsule again from v3's cases
# (tools/mkpost.py); it needs the hosted v3 binary.
.PHONY: post post79
$(BINDIR)/starforth4-post: $(HERE)/tools/hosted.c $(BINDIR)/v4_image_64.c $(CAPSULE_DIR_C) $(ENGINE_SRCS) $(SYSTEM_SRCS) $(wildcard $(HERE)/include/v4/*.h) $(HERE)/Makefile
$(CC_amd64) $(CFLAGS) -D_POSIX_C_SOURCE=200809L -I$(HERE)/include -DV4_CELL_BITS=64 $(HOST_DEFS) -c $(HERE)/tools/hosted.c -o $(BINDIR)/hosted-post.o
$(CC_amd64) $(SYSTEM_CFLAGS) -DV4_POST_AT_BOOT=1 -static $(BINDIR)/hosted-post.o $(BINDIR)/v4_image_64.c $(CAPSULE_DIR_C) $(ENGINE_SRCS) $(SYSTEM_SRCS) -o $@
post: $(BINDIR)/starforth4-post
@$(BINDIR)/starforth4-post < /dev/null
post79:
python3 $(HERE)/tools/mkpost.py
# `make hosted` builds the three. `make hosted-check` boots each with no # `make hosted` builds the three. `make hosted-check` boots each with no
# input and requires that all three print the same lines, ending in # input and requires that all three print the same lines, ending in
# PARITY:OK and the prompt: the same hashes on every ISA. # PARITY:OK and the prompt: the same hashes on every ISA.
+46 -9
View File
@@ -55,21 +55,58 @@ 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 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`. capsule, block and line, with `PARITY:FAIL` and `POST: FAILED`.
State, 2026-10-05: capsule loading works on all six builds. The three hosted State, 2026-10-05, after the POST work began: all six builds load
binaries and the three bare-metal kernels (`clean qemu` with `STARFORTH_V4=1`) `v4:forth79.4th` and reach `ok>` with the same lines:
print the same four lines and reach `ok>`:
``` ```
PARITY:V4_NUCLEUS words=292 image_hash=0x60b74e4f87adb0ac PARITY:V4_NUCLEUS words=295 image_hash=0x3ed5d5fc83f0b026
PARITY:V4_CAPSULE name=v4:forth79.4th capsule_id=0xa4b74bdc7deaf204 capsule_hash=0xa4b74bdc7deaf204 dict_hash=0x0baed67626b4fac4 PARITY:V4_CAPSULE name=v4:forth79.4th capsule_id=0xa4b74bdc7deaf204 capsule_hash=0xa4b74bdc7deaf204 dict_hash=0x118de9d37e682ea4
PARITY:OK PARITY:OK
ok> ok>
``` ```
Bare-metal logs: `logs/20261005-152955/amd64/`, `logs/20261005-154021/aarch64/`, Bare-metal logs: `logs/20261005-160144/amd64/`, `logs/20261005-160234/aarch64/`,
`logs/20261005-154150/riscv64/`. Each run was ended once the prompt was in the `logs/20261005-160400/riscv64/`. Each run was ended once the prompt was in the
log; nothing was typed at a bare-metal prompt, so keyboard input there is not log; nothing was typed at a bare-metal prompt, so keyboard input there is not
yet verified. The capsules were unsigned (no signing key on this machine). yet verified. The capsules were unsigned (no signing key on this machine).
`forth79.4th` holds no definitions yet: all 292 words are still in the `forth79.4th` holds no definitions yet: every word is still in the nucleus.
nucleus. There is no POST yet.
## POST
`capsules/v4/post79.4th` is v3's POST cases for the FORTH-79 Required Word
Set, written by `v4/tools/mkpost.py` (`make -C v4 post79`): 537 cases in
blocks 7000–7112, covering 111 of the 130 required words. Each case carries
what the hosted v3 binary did with the same line — error or not, the stack,
the length and checksum of what was printed — and v4 must do the same.
**POST does not pass yet, so it is not in the boot.** `make -C v4 post` builds
the amd64 system with it (`-DV4_POST_AT_BOOT=1`) and boots it:
```
PARITY:V4_POST tests=537 pass=439 fail=98
PARITY:FAIL
POST: FAILED
```
The 98 are not yet sorted into v4 defects and differences that need a
ruling. A first reading finds four kinds:
| Kind | About | Examples |
|---|---|---|
| The case prints or leaves a memory address, which differs between the two machines | 40 | `HERE`, `PAD`, `1 BLOCK`, `BL WORD`, `CONTEXT @ .`, `FIND` |
| v3 departs from FORTH-79 and v4 follows the standard | 35 | `PICK` and `ROLL` count from 1; `<# # #S #>` take a double number; `LEAVE` ends the loop at the next `LOOP`; `>R` `R>` only inside a definition |
| The case assumes v3's byte address units, where a v4 address unit is a cell (D-1) | 8 | `42 , HERE 8 - @`, `PAD 42 OVER !` |
| Not yet understood | 15 | vocabulary cases, `LIST`'s layout, `16 BASE ! 255 .`, `321 EMIT`, cases v3 ends in an error and v4 does not |
Required words with no v3 case, and so no POST case: `U*` `U/MOD` `?`
`EXECUTE` `KEY` `EXPECT` `QUERY` `U.` `CONVERT` `'` `."` `LITERAL` `STATE`
`COMPILE` `[COMPILE]` `(` `QUIT` `BLK` `79-STANDARD`. `U*` and `U/MOD` are
in neither v3 nor v4.
Twelve v3 cases are left out: three read the keyboard, two forget a word of
the system, two store to the search order, and five leave v3 unable to
continue in one session (`mkpost.py` prints the list).
The boot passes POST only on seeing the tally line with `fail=0`
(`v4/system/boot.c`); that no line was refused is not enough.
+5
View File
@@ -68,6 +68,11 @@ macro R-CLEAR RSTACK-DEPTH b! a !b endmacro
\ FORTH-79: clear the return stack, set execution mode, return control to \ FORTH-79: clear the return stack, set execution mode, return control to
\ the terminal; no message is given. The data stack is left as it is. \ the terminal; no message is given. The data stack is left as it is.
\ NODE-ERROR, by name: how a definition written in FORTH raises an error.
\ A store of a code that is not zero is the trap of D-18 -- the word goes no
\ further, the message for the code is printed (-1: the word has printed
\ its own) and the line ends with ERROR. The codes are listed in core.v4.
header NODE-ERROR inline : NODE-ERROR' NODE-ERROR ;
header (CATCH) inline : (CATCH)' (CATCH) ; header (CATCH) inline : (CATCH)' (CATCH) ;
header (EMIT-HOOK) inline : (EMIT-HOOK)' (EMIT-HOOK) ; header (EMIT-HOOK) inline : (EMIT-HOOK)' (EMIT-HOOK) ;
+4 -1
View File
@@ -6,8 +6,11 @@
* the text goes. So the two start the same way and print the same lines: * the text goes. So the two start the same way and print the same lines:
* *
* PARITY:V4_NUCLEUS words=N image_hash=0x... * PARITY:V4_NUCLEUS words=N image_hash=0x...
* PARITY:V4_CAPSULE name=... capsule_id=0x... capsule_hash=0x... dict_hash=0x... * PARITY:V4_CAPSULE name=v4:forth79.4th capsule_id=0x... capsule_hash=0x... dict_hash=0x...
* PARITY:V4_POST tests=N pass=N fail=N (printed by the POST capsule)
* PARITY:V4_CAPSULE name=v4:post79.4th capsule_id=0x... capsule_hash=0x... dict_hash=0x...
* PARITY:OK * PARITY:OK
* POST: PASSED
* ok> * ok>
* *
* or, if anything is wrong, what was wrong and then * or, if anything is wrong, what was wrong and then
+59 -2
View File
@@ -11,7 +11,18 @@
#include "starkernel/capsule_blocks.h" #include "starkernel/capsule_blocks.h"
/* The capsules, in the order they are loaded. */ /* The capsules, in the order they are loaded. */
static const char *const boot_capsules[] = { "v4:forth79.4th" }; /* POST is not yet part of the boot: v4:post79.4th does not pass yet
* (v4/README.md). Build with -DV4_POST_AT_BOOT=1 to load it and to require
* its clean tally; `make -C v4 post` does. */
#ifndef V4_POST_AT_BOOT
#define V4_POST_AT_BOOT 0
#endif
static const char *const boot_capsules[] = {
"v4:forth79.4th",
#if V4_POST_AT_BOOT
"v4:post79.4th",
#endif
};
#define LINE_MAX 80u /* QUERY takes 80 characters, the new-line among them */ #define LINE_MAX 80u /* QUERY takes 80 characters, the new-line among them */
#define STEP_LIMIT 4000000000ULL /* instruction words one line may take */ #define STEP_LIMIT 4000000000ULL /* instruction words one line may take */
@@ -105,6 +116,37 @@ typedef struct {
unsigned len; unsigned len;
} tail; } tail;
/* POST's verdict. The POST capsule ends by printing one line,
* PARITY:V4_POST tests=N pass=N fail=N
* and the boot passes only if it has seen that line with fail=0. That no
* line was refused is not enough: a POST that was broken half way would
* refuse nothing. */
static char post_line[96];
static unsigned post_len;
static int post_seen, post_clean;
static int text_at(const char *line, unsigned len, unsigned at, const char *want)
{
unsigned i;
for (i = 0; want[i]; i++)
if (at + i >= len || line[at + i] != want[i]) return 0;
return 1;
}
static void post_watch(char c)
{
static const char clean[] = " fail=0";
if (c != '\n') {
if (post_len < sizeof post_line) post_line[post_len++] = c;
return;
}
if (text_at(post_line, post_len, 0, "PARITY:V4_POST ")) {
post_seen = 1;
post_clean = post_len >= sizeof clean - 1 && text_at(post_line, post_len, post_len - (unsigned)(sizeof clean - 1), clean);
}
post_len = 0;
}
static void tail_put(const v4_boot *b, tail *t, int show, char c) static void tail_put(const v4_boot *b, tail *t, int show, char c)
{ {
unsigned i; unsigned i;
@@ -130,7 +172,10 @@ static int run_to_prompt(const v4_boot *b, int show)
for (;;) { for (;;) {
(void)v4_exec_step_word(n, b->es, b->h); (void)v4_exec_step_word(n, b->es, b->h);
if (n->console_len) { if (n->console_len) {
for (i = 0; i < n->console_len; i++) tail_put(b, &t, show, (char)n->console[i]); for (i = 0; i < n->console_len; i++) {
post_watch((char)n->console[i]);
tail_put(b, &t, show, (char)n->console[i]);
}
n->console_len = 0; n->console_len = 0;
} }
if (n->stopped) { say(b, "\nV4: the node stopped on a fault\n"); return 0; } if (n->stopped) { say(b, "\nV4: the node stopped on a fault\n"); return 0; }
@@ -233,6 +278,7 @@ int v4_boot_run(const v4_boot *b, unsigned char *disk, unsigned blocks)
{ {
unsigned i; unsigned i;
post_len = 0; post_seen = 0; post_clean = 0;
if (!v4_image_boot(b->n, b->es, b->h, b->im, disk, blocks)) { if (!v4_image_boot(b->n, b->es, b->h, b->im, disk, blocks)) {
say(b, "V4: the nucleus image is not for this build of the engine\nPARITY:FAIL\nPOST: FAILED\n"); say(b, "V4: the nucleus image is not for this build of the engine\nPARITY:FAIL\nPOST: FAILED\n");
return 0; return 0;
@@ -247,7 +293,18 @@ int v4_boot_run(const v4_boot *b, unsigned char *disk, unsigned blocks)
for (i = 0; i < sizeof boot_capsules / sizeof boot_capsules[0]; i++) for (i = 0; i < sizeof boot_capsules / sizeof boot_capsules[0]; i++)
if (!load_capsule(b, boot_capsules[i])) { say(b, "PARITY:FAIL\nPOST: FAILED\n"); return 0; } if (!load_capsule(b, boot_capsules[i])) { say(b, "PARITY:FAIL\nPOST: FAILED\n"); return 0; }
#if V4_POST_AT_BOOT
if (!post_seen || !post_clean) {
say(b, post_seen ? "V4: POST reported failures\n" : "V4: POST did not report\n");
say(b, "PARITY:FAIL\nPOST: FAILED\n");
return 0;
}
#endif
#if V4_POST_AT_BOOT
say(b, "PARITY:OK\nPOST: PASSED\nok> ");
#else
say(b, "PARITY:OK\nok> "); say(b, "PARITY:OK\nok> ");
#endif
return 1; return 1;
} }
+455
View File
File diff suppressed because it is too large Load Diff