Reorganize source tree: kernel/, v3/, v4/ split and board infrastructure

Source tree reorganization:
- Move StarForth v3 engine to v3/ (src/, include/, Makefile)
- Move kernel to kernel/ (src/, include/, linker/, Makefile)
- Create v4/ skeleton for F18-ISA golden model (DECOMPOSITION.md, JUSTIFICATION.md)
- Move FABRIC-0..4.md to docs/fabric/
- Move ONTOLOGY.md and ROADMAP.md to docs/

Board infrastructure:
- Add boards/ser5/, boards/raspi/, boards/milkv/, boards/zynq7020/
- Each board has board.mk (ISA, CPU flags, boot recipe) and README.md
- Root Makefile becomes thin dispatcher: boot_image, all, clean, docs take TARGET
- make boot_image TARGET=SER5|RASPI|MILKV builds one GPT/MBR image per board
- ZYNQ7020 target exists but stops with clear error (ARMv7 port not built yet)
- scripts/mkdiskimage.sh builds disk images for all boards

Docs pipeline:
- docs/book/ with LaTeX master (main.tex) and Makefile
- pandoc converts Markdown to LaTeX at build time
- Two Lua filters: table-widths.lua (wide tables wrap), code-breaks.lua (inline code breaks)
- make docs builds single PDF (754 pages, 0 missing characters)
- make docs TARGET=<board> adds board appendix
- build/docs/<book|board>/meta.tex stamps git commit into PDF

Bug fixes:
- 42 include paths that only worked by accident now use correct relative paths
- clang-18 hardcode replaced with configurable CC variable (fixed aarch64 build)
- Pi 5: kernel_2712.img linked at 0x80000, .bss zeroed, memory reserved
- Doxyfile, .clang-tidy, README.md, Kconfig paths updated

Verified:
- Hosted v3 build passes 1012 tests, 0 failures
- SER5 image boots in QEMU (OVMF), POST passes, K exact (65536 = Q48_ONE)
- Milk-V image boots in QEMU (OpenSBI + U-Boot + bootefi), POST passes
- make clean TARGET=<board> removes only that board and its ISA objects
- make all builds all boards, hosted v3, and docs in one run

Co-authored-by: Junie <junie@jetbrains.com>
This commit is contained in:
rajames
2026-10-01 15:40:09 -04:00
co-authored by Junie
parent 3c709c115b
commit a8b70e88d3
630 changed files with 2646 additions and 2036 deletions
+556
View File
@@ -0,0 +1,556 @@
/*
StarForth — Steady-State Virtual Machine Runtime
Copyright (c) 2023–2025 Robert A. James
All rights reserved.
This file is part of the StarForth project.
Licensed under the StarForth License, Version 1.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at:
https://github.com/star.4th@proton.me/StarForth/LICENSE.txt
This software is provided "AS IS", WITHOUT WARRANTY OF ANY KIND,
express or implied, including but not limited to the warranties of
merchantability, fitness for a particular purpose, and noninfringement.
See the License for the specific language governing permissions and
limitations under the License.
StarForth — Steady-State Virtual Machine Runtime
Copyright (c) 2023–2025 Robert A. James
All rights reserved.
This file is part of the StarForth project.
Licensed under the StarForth License, Version 1.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at:
https://github.com/star.4th@proton.me/StarForth/LICENSE.txt
This software is provided "AS IS", WITHOUT WARRANTY OF ANY KIND,
express or implied, including but not limited to the warranties of
merchantability, fitness for a particular purpose, and noninfringement.
See the License for the specific language governing permissions and
limitations under the License.
*/
#ifndef VM_INNER_INTERP_ARM64_H
#define VM_INNER_INTERP_ARM64_H
#include "vm.h"
/*
* ARM64 DIRECT-THREADED INNER INTERPRETER
* ========================================
*
* ARM64 advantages over x86_64:
* - More registers (31 vs 16)
* - Better branch prediction
* - Conditional execution
* - Load/store with auto-increment
* - Lower power consumption
*
* Register Allocation (using callee-saved registers):
* - x19: VM pointer (callee-saved)
* - x20: Instruction Pointer (IP)
* - x21: Data Stack Pointer (DSP) - actual pointer
* - x22: Return Stack Pointer (RSP) - actual pointer
* - x23: Top of Stack cache (TOS) - keep in register
* - x24-x28: Available for future use
*
* Why more registers help:
* - Can keep TOS in register (x23)
* - More scratch registers for complex operations
* - Less memory traffic
*
* Performance on Raspberry Pi 4:
* - Expected 3-5x speedup for threaded code
* - Better than x86_64 due to more registers
* - Lower power = less thermal throttling
*/
#ifndef USE_DIRECT_THREADING
#define USE_DIRECT_THREADING 0
#endif
#if USE_DIRECT_THREADING
/*
* NEXT macro - ARM64 version
*
* On ARM64, we can use:
* - Load with post-increment (ldr x0, [x20], #8)
* - Indirect branch (br x0)
*/
#define NEXT_ARM64() \
__asm__ __volatile__ ( \
"ldr x0, [x20], #8\n\t" /* Load word ptr from [IP], IP += 8 */ \
"br x0\n\t" /* Branch to word */ \
::: "x0", "memory" \
)
/*
* DOCOL - Enter a colon definition (ARM64)
*/
static inline void vm_docol_arm64(VM *vm) {
__asm__ __volatile__(
/* Save current IP on return stack */
"str x20, [x22], #8\n\t" /* [RSP] = IP, RSP += 8 */
/* IP = address of colon definition body */
"ldr x0, %[entry]\n\t"
"ldr x20, [x0]\n\t" /* IP = entry->code_field */
/* Continue with NEXT */
"ldr x0, [x20], #8\n\t"
"br x0\n\t"
:
: [entry]"m"(vm->current_executing_entry)
: "x0", "x20", "x22", "memory"
);
}
/*
* EXIT - Return from a colon definition (ARM64)
*/
static inline void vm_exit_arm64(void) {
__asm__ __volatile__(
/* Restore IP from return stack */
"ldr x20, [x22, #-8]!\n\t" /* RSP -= 8, IP = [RSP] (pre-decrement) */
/* Continue with NEXT */
"ldr x0, [x20], #8\n\t"
"br x0\n\t"
::: "x0", "x20", "x22", "memory"
);
}
/*
* Setup registers before entering inner loop
*/
static inline void vm_setup_registers_arm64(VM *vm) {
__asm__ __volatile__(
/* Save callee-saved registers (required by ARM64 ABI) */
"stp x19, x20, [sp, #-80]!\n\t"
"stp x21, x22, [sp, #16]\n\t"
"stp x23, x24, [sp, #32]\n\t"
"stp x25, x26, [sp, #48]\n\t"
"stp x27, x28, [sp, #64]\n\t"
/* Load VM pointer */
"mov x19, %[vm]\n\t" /* x19 = VM pointer */
/* Load IP */
"ldr x20, %[ip]\n\t" /* x20 = IP */
/* Calculate data stack pointer */
"ldr w0, %[dsp]\n\t"
"ldr x1, %[dstack]\n\t"
"add x21, x1, x0, sxtw #3\n\t" /* x21 = &data_stack[dsp] */
/* Calculate return stack pointer */
"ldr w0, %[rsp]\n\t"
"ldr x1, %[rstack]\n\t"
"add x22, x1, x0, sxtw #3\n\t" /* x22 = &return_stack[rsp] */
/* Load TOS into x23 if stack not empty */
"ldr w0, %[dsp]\n\t"
"cmp w0, #0\n\t"
"b.lt 1f\n\t"
"ldr x23, [x21]\n\t" /* x23 = TOS (cached) */
"1:\n\t"
:
: [vm]"r"(vm),
[ip]"m"(vm->ip),
[dsp]"m"(vm->dsp),
[rsp]"m"(vm->rsp),
[dstack]"m"(vm->data_stack),
[rstack]"m"(vm->return_stack)
: "x0", "x1", "x19", "x20", "x21", "x22", "x23", "x24",
"x25", "x26", "x27", "x28", "memory"
);
}
/*
* Save registers back to VM structure
*/
static inline void vm_save_registers_arm64(VM *vm) {
__asm__ __volatile__(
/* Save TOS back to stack */
"str x23, [x21]\n\t"
/* Save IP */
"str x20, %[ip]\n\t"
/* Calculate and save dsp */
"ldr x0, %[dstack]\n\t"
"sub x1, x21, x0\n\t"
"lsr x1, x1, #3\n\t" /* / 8 */
"str w1, %[dsp]\n\t"
/* Calculate and save rsp */
"ldr x0, %[rstack]\n\t"
"sub x1, x22, x0\n\t"
"lsr x1, x1, #3\n\t"
"str w1, %[rsp]\n\t"
/* Restore callee-saved registers */
"ldp x27, x28, [sp, #64]\n\t"
"ldp x25, x26, [sp, #48]\n\t"
"ldp x23, x24, [sp, #32]\n\t"
"ldp x21, x22, [sp, #16]\n\t"
"ldp x19, x20, [sp], #80\n\t"
: [ip]"=m"(vm->ip),
[dsp]"=m"(vm->dsp),
[rsp]"=m"(vm->rsp)
: [dstack]"m"(vm->data_stack),
[rstack]"m"(vm->return_stack)
: "x0", "x1", "memory"
);
}
/**
* @defgroup primitives Fast Primitive Word Implementations
* @brief Register-based stack primitives optimized for ARM64
*
* Key optimization: TOS stays in x23, avoiding memory traffic
* @{
*/
/** @brief DUP primitive - duplicates top of stack item */
#define PRIM_DUP_ARM64() \
__asm__ __volatile__ ( \
"str x23, [x21, #8]!\n\t" /* Store TOS, advance DSP */ \
::: "x21", "memory" \
)
/* DROP - remove top of stack */
#define PRIM_DROP_ARM64() \
__asm__ __volatile__ ( \
"ldr x23, [x21], #-8\n\t" /* Load new TOS, decrement DSP */ \
::: "x21", "x23", "memory" \
)
/* SWAP - swap top two stack items */
#define PRIM_SWAP_ARM64() \
__asm__ __volatile__ ( \
"ldr x0, [x21]\n\t" /* Load NOS */ \
"str x23, [x21]\n\t" /* Store TOS to NOS position */ \
"mov x23, x0\n\t" /* TOS = old NOS */ \
::: "x0", "x23", "memory" \
)
/* OVER - copy second item to top */
#define PRIM_OVER_ARM64() \
__asm__ __volatile__ ( \
"ldr x0, [x21]\n\t" /* Load NOS */ \
"str x23, [x21, #8]!\n\t" /* Store TOS, advance DSP */ \
"mov x23, x0\n\t" /* TOS = NOS */ \
::: "x0", "x21", "x23", "memory" \
)
/* ROT - rotate top three items */
#define PRIM_ROT_ARM64() \
__asm__ __volatile__ ( \
"ldr x0, [x21]\n\t" /* Load item2 */ \
"ldr x1, [x21, #-8]\n\t" /* Load item3 */ \
"str x1, [x21]\n\t" /* item3 -> NOS */ \
"str x23, [x21, #-8]\n\t" /* TOS -> item3 */ \
"mov x23, x0\n\t" /* item2 -> TOS */ \
::: "x0", "x1", "x23", "memory" \
)
/* + - add top two stack items */
#define PRIM_PLUS_ARM64() \
__asm__ __volatile__ ( \
"ldr x0, [x21], #-8\n\t" /* Load NOS, decrement DSP */ \
"add x23, x23, x0\n\t" /* TOS = TOS + NOS */ \
::: "x0", "x21", "x23" \
)
/* - - subtract top from second */
#define PRIM_MINUS_ARM64() \
__asm__ __volatile__ ( \
"ldr x0, [x21], #-8\n\t" /* Load NOS, decrement DSP */ \
"sub x23, x0, x23\n\t" /* TOS = NOS - TOS */ \
::: "x0", "x21", "x23" \
)
/* * - multiply top two stack items */
#define PRIM_STAR_ARM64() \
__asm__ __volatile__ ( \
"ldr x0, [x21], #-8\n\t" /* Load NOS, decrement DSP */ \
"mul x23, x23, x0\n\t" /* TOS = TOS * NOS */ \
::: "x0", "x21", "x23" \
)
/* / - divide second by top */
#define PRIM_SLASH_ARM64() \
__asm__ __volatile__ ( \
"ldr x0, [x21], #-8\n\t" /* Load NOS (dividend), decrement DSP */ \
"sdiv x23, x0, x23\n\t" /* TOS = NOS / TOS */ \
::: "x0", "x21", "x23" \
)
/* MOD - modulo */
#define PRIM_MOD_ARM64() \
__asm__ __volatile__ ( \
"ldr x0, [x21], #-8\n\t" /* Load NOS, decrement DSP */ \
"sdiv x1, x0, x23\n\t" /* quotient = NOS / TOS */ \
"msub x23, x1, x23, x0\n\t" /* TOS = NOS - quotient * TOS */ \
::: "x0", "x1", "x21", "x23" \
)
/* AND - bitwise and */
#define PRIM_AND_ARM64() \
__asm__ __volatile__ ( \
"ldr x0, [x21], #-8\n\t" \
"and x23, x23, x0\n\t" \
::: "x0", "x21", "x23" \
)
/* OR - bitwise or */
#define PRIM_OR_ARM64() \
__asm__ __volatile__ ( \
"ldr x0, [x21], #-8\n\t" \
"orr x23, x23, x0\n\t" \
::: "x0", "x21", "x23" \
)
/* XOR - bitwise xor */
#define PRIM_XOR_ARM64() \
__asm__ __volatile__ ( \
"ldr x0, [x21], #-8\n\t" \
"eor x23, x23, x0\n\t" \
::: "x0", "x21", "x23" \
)
/* INVERT - bitwise not */
#define PRIM_INVERT_ARM64() \
__asm__ __volatile__ ( \
"mvn x23, x23\n\t" \
::: "x23" \
)
/* NEGATE - two's complement */
#define PRIM_NEGATE_ARM64() \
__asm__ __volatile__ ( \
"neg x23, x23\n\t" \
::: "x23" \
)
/* @ - fetch cell from memory */
#define PRIM_FETCH_ARM64() \
__asm__ __volatile__ ( \
"ldr x0, [x19]\n\t" /* Load VM->memory */ \
"ldr x23, [x0, x23]\n\t" /* TOS = memory[TOS] */ \
::: "x0", "x23", "memory" \
)
/* ! - store cell to memory */
#define PRIM_STORE_ARM64() \
__asm__ __volatile__ ( \
"ldr x0, [x21], #-8\n\t" /* Load address, decrement DSP */ \
"ldr x1, [x19]\n\t" /* Load VM->memory */ \
"str x23, [x1, x0]\n\t" /* memory[addr] = value */ \
"ldr x23, [x21]\n\t" /* Load new TOS */ \
::: "x0", "x1", "x21", "x23", "memory" \
)
/* C@ - fetch byte from memory */
#define PRIM_C_FETCH_ARM64() \
__asm__ __volatile__ ( \
"ldr x0, [x19]\n\t" \
"ldrb w23, [x0, x23]\n\t" /* Load byte, zero-extend */ \
::: "x0", "x23", "memory" \
)
/* C! - store byte to memory */
#define PRIM_C_STORE_ARM64() \
__asm__ __volatile__ ( \
"ldr x0, [x21], #-8\n\t" \
"ldr x1, [x19]\n\t" \
"strb w23, [x1, x0]\n\t" /* Store byte */ \
"ldr x23, [x21]\n\t" \
::: "x0", "x1", "x21", "x23", "memory" \
)
/* >R - push to return stack */
#define PRIM_TO_R_ARM64() \
__asm__ __volatile__ ( \
"str x23, [x22], #8\n\t" /* Store to RS, advance RSP */ \
"ldr x23, [x21], #-8\n\t" /* Load new TOS, decrement DSP */ \
::: "x21", "x22", "x23", "memory" \
)
/* R> - pop from return stack */
#define PRIM_R_FROM_ARM64() \
__asm__ __volatile__ ( \
"str x23, [x21, #8]!\n\t" /* Store TOS, advance DSP */ \
"ldr x23, [x22, #-8]!\n\t" /* Load from RS, decrement RSP */ \
::: "x21", "x22", "x23", "memory" \
)
/* R@ - copy top of return stack to data stack */
#define PRIM_R_FETCH_ARM64() \
__asm__ __volatile__ ( \
"str x23, [x21, #8]!\n\t" /* Store TOS, advance DSP */ \
"ldr x23, [x22, #-8]\n\t" /* Load from RS (don't pop) */ \
::: "x21", "x23", "memory" \
)
/* 2DUP - duplicate top two items */
#define PRIM_2DUP_ARM64() \
__asm__ __volatile__ ( \
"ldr x0, [x21]\n\t" /* Load NOS */ \
"stp x0, x23, [x21, #8]\n\t" /* Store pair */ \
"add x21, x21, #16\n\t" /* DSP += 2 */ \
::: "x0", "x21", "memory" \
)
/* 2DROP - drop top two items */
#define PRIM_2DROP_ARM64() \
__asm__ __volatile__ ( \
"ldr x23, [x21, #-8]\n\t" /* Load new TOS */ \
"sub x21, x21, #16\n\t" /* DSP -= 2 */ \
::: "x21", "x23", "memory" \
)
/* 0= - test if zero */
#define PRIM_ZERO_EQUALS_ARM64() \
__asm__ __volatile__ ( \
"cmp x23, #0\n\t" \
"cset x23, eq\n\t" /* Set to 1 if zero, else 0 */ \
"neg x23, x23\n\t" /* Convert to -1 (true flag) */ \
::: "x23", "cc" \
)
/* 0< - test if negative */
#define PRIM_ZERO_LESS_ARM64() \
__asm__ __volatile__ ( \
"cmp x23, #0\n\t" \
"cset x23, lt\n\t" \
"neg x23, x23\n\t" \
::: "x23", "cc" \
)
/* = - test equality */
#define PRIM_EQUALS_ARM64() \
__asm__ __volatile__ ( \
"ldr x0, [x21], #-8\n\t" \
"cmp x0, x23\n\t" \
"cset x23, eq\n\t" \
"neg x23, x23\n\t" \
::: "x0", "x21", "x23", "cc" \
)
/* < - test less than (signed) */
#define PRIM_LESS_ARM64() \
__asm__ __volatile__ ( \
"ldr x0, [x21], #-8\n\t" \
"cmp x0, x23\n\t" \
"cset x23, lt\n\t" \
"neg x23, x23\n\t" \
::: "x0", "x21", "x23", "cc" \
)
/* > - test greater than (signed) */
#define PRIM_GREATER_ARM64() \
__asm__ __volatile__ ( \
"ldr x0, [x21], #-8\n\t" \
"cmp x0, x23\n\t" \
"cset x23, gt\n\t" \
"neg x23, x23\n\t" \
::: "x0", "x21", "x23", "cc" \
)
/*
* Control flow primitives
*/
/* BRANCH - unconditional branch */
#define PRIM_BRANCH_ARM64() \
__asm__ __volatile__ ( \
"ldr x0, [x20]\n\t" /* Load offset */ \
"add x20, x20, x0\n\t" /* IP += offset */ \
::: "x0", "x20", "memory" \
)
/* 0BRANCH - branch if TOS is zero */
#define PRIM_ZBRANCH_ARM64() \
__asm__ __volatile__ ( \
"ldr x0, [x20]\n\t" /* Load offset */ \
"cmp x23, #0\n\t" \
"add x1, x20, x0\n\t" /* Calculate target */ \
"add x2, x20, #8\n\t" /* Calculate skip */ \
"csel x20, x1, x2, eq\n\t" /* Select target if zero */ \
"ldr x23, [x21], #-8\n\t" /* Load new TOS */ \
::: "x0", "x1", "x2", "x20", "x21", "x23", "cc", "memory" \
)
/* EXECUTE - execute word whose xt is on stack */
#define PRIM_EXECUTE_ARM64() \
__asm__ __volatile__ ( \
"ldr x23, [x21], #-8\n\t" /* Load new TOS */ \
"br x0\n\t" /* Branch to xt */ \
::: "x0", "x21", "x23", "memory" \
)
#else /* !USE_DIRECT_THREADING */
/* Fallback definitions */
#define NEXT_ARM64() do {} while(0)
#define vm_setup_registers_arm64(vm) do {} while(0)
#define vm_save_registers_arm64(vm) do {} while(0)
#endif /* USE_DIRECT_THREADING */
/*
* ============================================================================
* RASPBERRY PI 4 PERFORMANCE TUNING
* ============================================================================
*
* Cache Optimization:
* -------------------
* 1. Align VM structure to cache line (64 bytes):
* typedef struct VM { ... } __attribute__((aligned(64))) VM;
*
* 2. Separate hot/cold data:
* - Keep stacks, IP, SP together (hot)
* - Move error handling, I/O to separate structure (cold)
*
* 3. Prefetch dictionary entries:
* vm_prefetch(vm->latest);
* vm_prefetch(vm->latest->link);
*
* Thermal Management:
* -------------------
* 1. Monitor temperature:
* vcgencmd measure_temp
*
* 2. Add heatsink or fan for sustained load
*
* 3. Reduce CPU frequency if needed:
* echo 1200000 > /sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq
*
* Power Optimization:
* -------------------
* 1. Use WFE (Wait For Event) in idle loops
* 2. Disable unused cores if single-threaded
* 3. Use NEON for parallel operations (lower power than scalar)
*
* Build Configuration:
* --------------------
* Native: -march=armv8-a+crc+simd -mtune=cortex-a72
* Cross: CC=aarch64-linux-gnu-gcc
*
* ============================================================================
*/
#endif /* VM_INNER_INTERP_ARM64_H */