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
+196
View File
@@ -0,0 +1,196 @@
/*
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.
*/
/**
* @file block_words.h
* @brief FORTH-79 Block and Buffer System Implementation
*
* This file implements the standard FORTH-79 block and buffer words:
* @li BLOCK ( u -- addr ) Get block buffer address
* @li BUFFER ( u -- addr ) Get empty buffer for block
* @li UPDATE ( -- ) Mark current block as modified
* @li SAVE-BUFFERS ( -- ) Save all modified blocks
* @li EMPTY-BUFFERS ( -- ) Mark all buffers as empty
* @li FLUSH ( -- ) Save buffers and empty them
* @li LIST ( u -- ) List block contents
* @li LOAD ( u -- ) Load and interpret block
* @li SCR ( -- addr ) Variable: screen/block being listed
* @li THRU ( u1 u2 -- ) Load blocks from u1 to u2
* @li --> or → ( -- ) Continue to next block
*/
#ifndef BLOCK_WORDS_H
#define BLOCK_WORDS_H
#include "vm.h"
/** @name Block System Configuration
* @{
*/
/** @brief Size of each block in bytes (1KB) */
#define BLOCK_SIZE 1024
/** @brief Maximum number of blocks (1024 blocks from 1MB memory) */
#define MAX_BLOCKS (VM_MEMORY_SIZE / BLOCK_SIZE)
/** @brief Number of block buffers in memory */
#define BUFFER_COUNT 4
/** @} */
/**
* @brief Block buffer types for different storage mechanisms
*/
typedef enum {
BUFFER_TYPE_MEMORY, /**< Direct memory access (current implementation) */
BUFFER_TYPE_HARDWARE, /**< Future: Hardware register blocks */
BUFFER_TYPE_STORAGE, /**< Future: Persistent storage blocks */
BUFFER_TYPE_NETWORK /**< Future: Network packet buffers */
} buffer_type_t;
/**
* @brief Block buffer structure maintaining buffer state
*/
typedef struct {
unsigned char data[BLOCK_SIZE]; /**< Block content buffer */
int block_number; /**< Currently loaded block number (-1 = empty) */
int dirty; /**< Modified flag for write-back */
int accessed; /**< LRU counter for buffer management */
buffer_type_t type; /**< Buffer type for storage mechanism */
uintptr_t hw_address; /**< Future: Hardware backing address */
} BlockBuffer;
/**
* @brief Registers all block and buffer words with the virtual machine
* @param vm Pointer to the Forth virtual machine instance
*/
void register_block_words(VM * vm);
/**
* @brief Initializes the block system
* @param vm Pointer to the Forth virtual machine instance
*/
void init_block_system(VM * vm);
/*
* @brief Gets a buffer containing the specified block
* @param vm Pointer to the Forth virtual machine instance
* @param block_num Block number to retrieve
* @return Pointer to the block buffer data
*/
unsigned char *get_block_buffer(VM *vm, int block_num);
/*
* @brief Gets an empty buffer for the specified block
* @param vm Pointer to the Forth virtual machine instance
* @param block_num Block number to allocate
* @return Pointer to the empty buffer data
*/
unsigned char *get_empty_buffer(VM *vm, int block_num);
/**
* @brief Marks the current buffer as modified
* @param vm Pointer to the Forth virtual machine instance
*/
void mark_buffer_dirty(VM * vm);
/*
* @brief Saves all modified buffers to storage
* @param vm Pointer to the Forth virtual machine instance
*/
void save_all_buffers(VM * vm);
/**
* @brief Sync every dirty VM block-window slot to the C-layer block cache,
* then flush the whole block subsystem to physical media --
* the complete SAVE-BUFFERS implementation (unlike
* save_all_buffers() above, which only calls blk_flush() and so
* misses any BUFFER-modified-but-not-yet-UPDATE'd content still
* sitting only in vm->memory's window). Cheap to call when nothing
* is dirty -- every check inside is a small fixed-size scan, no
* I/O happens unless something actually needs writing. Safe to
* call from outside word dispatch (e.g. a periodic idle-tick
* auto-flush); vm must be non-NULL.
* @param vm Pointer to the Forth virtual machine instance
*/
void blk_vm_flush_all(VM * vm);
/*
* @brief Marks all buffers as empty
* @param vm Pointer to the Forth virtual machine instance
*/
void empty_all_buffers(VM * vm);
/**
* @brief Discards vm->blk_vm_lbn[]/cbuf[]/dirty[] if the device chain has
* changed since last validated (see this function's own doc comment in
* block_words.c for why). Exposed (Phase 8 v3, 2026-09-23) so callers
* outside this file that read vm->blk_vm_lbn[] directly (MOVE/CMOVE's
* cross-device block-copy check, memory_words.c/string_words.c) go through
* the same invalidation contract blk_vm_find() already uses internally,
* rather than a second, divergent copy of this logic.
* @param vm Pointer to the Forth virtual machine instance
*/
void blk_vm_check_epoch(VM *vm);
/**
* @brief Does `addr` fall inside the block I/O window? Pure address
* arithmetic against the window's fixed compile-time base/size -- no VM
* state needed. Exposed (Phase 8 v3, 2026-09-23) for MOVE/CMOVE/CMOVE>'s
* cross-device block-copy check.
* @param addr VM offset to test
* @return slot index (0..BLK_VM_SLOTS-1) if inside the window, -1 otherwise
*/
int blk_vm_slot_for_addr(vaddr_t addr);
/**
* @brief True if addr1/addr2 are both block-window addresses currently
* loaded from two different physical devices (Phase 8 v3, 2026-09-23) --
* the check MOVE/CMOVE/CMOVE> call before copying to refuse a same-VM,
* cross-device raw block copy. See this function's own doc comment in
* block_words.c for exactly what is and isn't flagged.
* @param vm VM performing the copy
* @param addr1 first VM offset (source or destination, order doesn't matter)
* @param addr2 second VM offset
* @return 1 if this copy should be refused, 0 otherwise
*/
int blk_vm_is_cross_device_copy(VM *vm, vaddr_t addr1, vaddr_t addr2);
#endif /* BLOCK_WORDS_H */