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
@@ -0,0 +1,15 @@
# include/starkernel/freestanding/
Minimal libc-shim headers so shared VM code (`src/vm.c`, `src/word_source/`,
etc.) can be compiled into the freestanding kernel build, which has no real
libc.
- `assert.h`, `ctype.h`, `errno.h`, `inttypes.h`, `math.h`, `sched.h`,
`signal.h`, `stdio.h`, `stdlib.h`, `string.h`, `time.h` — narrow,
kernel-appropriate substitutes for the corresponding standard headers,
implementing only what the shared VM code actually calls.
- `sys/` — `sys/time.h`, `sys/types.h` shims.
These are intentionally minimal, not general-purpose libc replacements —
extend only when a specific shared-code call site needs a symbol that
isn't here yet.
@@ -0,0 +1,6 @@
/* Freestanding assert.h shim — asserts become no-ops in kernel builds. */
#ifndef FREESTANDING_ASSERT_H
#define FREESTANDING_ASSERT_H
#define assert(expr) ((void)(expr))
#define static_assert _Static_assert
#endif /* FREESTANDING_ASSERT_H */
@@ -0,0 +1,16 @@
/* Freestanding ctype.h shim — character classification for kernel builds. */
#ifndef FREESTANDING_CTYPE_H
#define FREESTANDING_CTYPE_H
static inline int isdigit(int c) { return c >= '0' && c <= '9'; }
static inline int isspace(int c) { return c == ' ' || c == '\t' || c == '\n' || c == '\r' || c == '\f' || c == '\v'; }
static inline int isalpha(int c) { return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'); }
static inline int isalnum(int c) { return isalpha(c) || isdigit(c); }
static inline int isupper(int c) { return c >= 'A' && c <= 'Z'; }
static inline int islower(int c) { return c >= 'a' && c <= 'z'; }
static inline int isprint(int c) { return c >= 0x20 && c < 0x7F; }
static inline int isxdigit(int c) { return isdigit(c) || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F'); }
static inline int toupper(int c) { return islower(c) ? c - 32 : c; }
static inline int tolower(int c) { return isupper(c) ? c + 32 : c; }
static inline int ispunct(int c) { return isprint(c) && !isalnum(c) && c != ' '; }
static inline int iscntrl(int c) { return (unsigned)c < 0x20 || c == 0x7F; }
#endif /* FREESTANDING_CTYPE_H */
@@ -0,0 +1,10 @@
/* Freestanding errno.h shim — no OS errno in kernel builds. */
#ifndef FREESTANDING_ERRNO_H
#define FREESTANDING_ERRNO_H
static int _freestanding_errno = 0;
#define errno _freestanding_errno
#define EPERM 1
#define ENOENT 2
#define EINVAL 22
#define ENOMEM 12
#endif /* FREESTANDING_ERRNO_H */
@@ -0,0 +1,25 @@
/* Freestanding inttypes.h shim — PRI* format macros for kernel builds. */
#ifndef FREESTANDING_INTTYPES_H
#define FREESTANDING_INTTYPES_H
#include <stdint.h>
#define PRId8 "d"
#define PRId16 "d"
#define PRId32 "d"
#define PRId64 "lld"
#define PRIu8 "u"
#define PRIu16 "u"
#define PRIu32 "u"
#define PRIu64 "llu"
#define PRIx8 "x"
#define PRIx16 "x"
#define PRIx32 "x"
#define PRIx64 "llx"
#define PRIX8 "X"
#define PRIX16 "X"
#define PRIX32 "X"
#define PRIX64 "llX"
#define PRIi8 "d"
#define PRIi16 "d"
#define PRIi32 "d"
#define PRIi64 "lld"
#endif /* FREESTANDING_INTTYPES_H */
@@ -0,0 +1,19 @@
/* Freestanding math.h shim — floating-point math for kernel builds.
* These functions are declared but should not be called; physics feedback
* loops use Q48.16 integer arithmetic, not float. */
#ifndef FREESTANDING_MATH_H
#define FREESTANDING_MATH_H
double sqrt(double x);
double pow(double base, double exp);
double fabs(double x);
double ceil(double x);
double floor(double x);
double log(double x);
double exp(double x);
double sin(double x);
double cos(double x);
double atan2(double y, double x);
#define HUGE_VAL __builtin_huge_val()
#define NAN __builtin_nanf("")
#define INFINITY __builtin_inff()
#endif /* FREESTANDING_MATH_H */
@@ -0,0 +1,5 @@
/* Freestanding sched.h shim — no POSIX scheduling in kernel builds. */
#ifndef FREESTANDING_SCHED_H
#define FREESTANDING_SCHED_H
static inline int sched_yield(void) { return 0; }
#endif /* FREESTANDING_SCHED_H */
@@ -0,0 +1,16 @@
/* Freestanding signal.h shim — no POSIX signals in kernel builds. */
#ifndef FREESTANDING_SIGNAL_H
#define FREESTANDING_SIGNAL_H
#define SIGINT 2
#define SIGABRT 6
#define SIGSEGV 11
#define SIGTERM 15
typedef void (*sighandler_t)(int);
#define SIG_DFL ((sighandler_t)0)
#define SIG_IGN ((sighandler_t)1)
struct sigaction { sighandler_t sa_handler; int sa_flags; };
#define SA_RESETHAND 0
static inline sighandler_t signal(int sig, sighandler_t handler) { (void)sig; (void)handler; return SIG_DFL; }
static inline int sigaction(int sig, const struct sigaction *act, struct sigaction *old)
{ (void)sig; (void)act; (void)old; return 0; }
#endif /* FREESTANDING_SIGNAL_H */
@@ -0,0 +1,36 @@
/* Freestanding stdio.h shim for aarch64 COFF kernel builds.
* printf/fprintf/snprintf/vfprintf all provided by shim.c (route to console). */
#ifndef FREESTANDING_STDIO_H
#define FREESTANDING_STDIO_H
#include <stddef.h>
#include <stdarg.h>
typedef struct { int _dummy; } FILE;
#define stderr ((FILE *)0)
#define stdout ((FILE *)1)
#define stdin ((FILE *)2)
int printf(const char *fmt, ...);
int fprintf(FILE *stream, const char *fmt, ...);
int vfprintf(FILE *stream, const char *fmt, va_list args);
int snprintf(char *buf, size_t n, const char *fmt, ...);
int vsnprintf(char *buf, size_t n, const char *fmt, va_list args);
int puts(const char *s);
int fputs(const char *s, FILE *stream);
#define SEEK_SET 0
#define SEEK_CUR 1
#define SEEK_END 2
int fflush(FILE *stream);
int putchar(int c);
int fseek(FILE *stream, long offset, int whence);
long ftell(FILE *stream);
int sscanf(const char *str, const char *fmt, ...);
int getchar(void);
int fgetc(FILE *stream);
int fputc(int c, FILE *stream);
char *fgets(char *s, int n, FILE *stream);
FILE *fopen(const char *path, const char *mode);
int fclose(FILE *stream);
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);
int fscanf(FILE *stream, const char *fmt, ...);
void rewind(FILE *stream);
#endif /* FREESTANDING_STDIO_H */
@@ -0,0 +1,18 @@
/* Freestanding stdlib.h shim for aarch64 COFF kernel builds.
* malloc/free/calloc/realloc provided by shim.c; abort by shim.c. */
#ifndef FREESTANDING_STDLIB_H
#define FREESTANDING_STDLIB_H
#include <stddef.h>
void *malloc(size_t size);
void free(void *ptr);
void *calloc(size_t n, size_t size);
void *realloc(void *ptr, size_t size);
void abort(void);
void qsort(void *base, size_t nmemb, size_t size,
int (*compar)(const void *, const void *));
long strtol(const char *str, char **endptr, int base);
unsigned long strtoul(const char *str, char **endptr, int base);
long long strtoll(const char *str, char **endptr, int base);
int atoi(const char *str);
long atol(const char *str);
#endif /* FREESTANDING_STDLIB_H */
@@ -0,0 +1,19 @@
/* Freestanding string.h shim for aarch64 COFF kernel builds.
* Implementations are provided by src/starkernel/vm/host/shim.c. */
#ifndef FREESTANDING_STRING_H
#define FREESTANDING_STRING_H
#include <stddef.h>
void *memcpy(void *dest, const void *src, size_t n);
void *memmove(void *dest, const void *src, size_t n);
void *memset(void *s, int c, size_t n);
int memcmp(const void *s1, const void *s2, size_t n);
void *memchr(const void *s, int c, size_t n);
size_t strlen(const char *s);
char *strcpy(char *dest, const char *src);
char *strncpy(char *dest, const char *src, size_t n);
int strcmp(const char *s1, const char *s2);
int strncmp(const char *s1, const char *s2, size_t n);
char *strchr(const char *s, int c);
char *strrchr(const char *s, int c);
char *strerror(int errnum);
#endif /* FREESTANDING_STRING_H */
@@ -0,0 +1,4 @@
# include/starkernel/freestanding/sys/
- `time.h`, `types.h` — minimal `sys/time.h`/`sys/types.h` shims for the
freestanding kernel build. See `include/starkernel/freestanding/README.md`.
@@ -0,0 +1,15 @@
/* Freestanding sys/time.h shim — no gettimeofday in kernel builds. */
#ifndef FREESTANDING_SYS_TIME_H
#define FREESTANDING_SYS_TIME_H
#include <stddef.h>
typedef long time_t;
typedef long suseconds_t;
struct timeval {
time_t tv_sec;
suseconds_t tv_usec;
};
struct timezone { int tz_minuteswest; int tz_dsttime; };
static inline int gettimeofday(struct timeval *tv, struct timezone *tz) {
(void)tv; (void)tz; return 0;
}
#endif /* FREESTANDING_SYS_TIME_H */
@@ -0,0 +1,12 @@
/* Freestanding sys/types.h shim — POSIX types for kernel builds. */
#ifndef FREESTANDING_SYS_TYPES_H
#define FREESTANDING_SYS_TYPES_H
#include <stddef.h>
#include <stdint.h>
typedef long ssize_t;
typedef long off_t;
typedef unsigned int mode_t;
typedef unsigned int uid_t;
typedef unsigned int gid_t;
typedef int pid_t;
#endif /* FREESTANDING_SYS_TYPES_H */
@@ -0,0 +1,11 @@
/* Freestanding time.h shim — no POSIX time in kernel builds. */
#ifndef FREESTANDING_TIME_H
#define FREESTANDING_TIME_H
#include <stddef.h>
#include "sys/time.h" /* provides time_t, suseconds_t, struct timeval */
struct timespec {
time_t tv_sec;
long tv_nsec;
};
int nanosleep(const struct timespec *req, struct timespec *rem);
#endif /* FREESTANDING_TIME_H */