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
+430
View File
@@ -0,0 +1,430 @@
/*
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.
*/
/*
*** StarForth ***
physics_pipelining_metrics.h - Word transition tracking for speculative execution
Phase 1: Instrumentation for pipelining/speculative execution
This module tracks word-to-word transitions (frequency of which words follow
which other words) to support speculative prefetching and pipelining decisions.
Terminology:
- transition_heat[i]: How many times word[i] has been executed immediately
after this word (forms prediction basis)
- total_transitions: Sum of all transition_heat entries
- prefetch_*: Metrics for speculative execution success/failure
*/
#ifndef PHYSICS_PIPELINING_METRICS_H
#define PHYSICS_PIPELINING_METRICS_H
#include <stdint.h>
#include "starforth_config.h"
/* ============================================================================
* Pipelining Feature Switch (disabled by default during Phase 1)
* ============================================================================
* Default lives in starforth_config.h, the single source of truth for VM
* build-time defaults; overridable via -D exactly as before.
*/
/* ============================================================================
* Tuning Knobs (adjustable at compile-time, future: runtime)
* ============================================================================
*/
/**
* SPECULATION_THRESHOLD_Q48: Minimum probability (Q48.16) to speculate on
* a word transition.
* Range: 0.10 (very aggressive) to 0.95 (very conservative)
* Default: see starforth_config.h (STARFORTH_CONFIG_SPECULATION_THRESHOLD_Q48_DEFAULT)
* Q48.16 encoding: 0.50 = 0x8000LL (1LL << 15)
*/
/**
* SPECULATION_DEPTH: How many words ahead to prefetch speculatively.
* Range: 1 (next word only) to 4 (very aggressive)
* Default: see starforth_config.h (STARFORTH_CONFIG_SPECULATION_DEPTH_DEFAULT)
*/
/**
* MIN_SAMPLES_FOR_SPECULATION: Minimum number of transitions observed
* before making speculation decisions.
* Range: 1 (immediate) to 100 (very conservative)
* Default: see starforth_config.h (STARFORTH_CONFIG_MIN_SAMPLES_FOR_SPECULATION_DEFAULT)
*/
/**
* MISPREDICTION_COST_Q48: Estimated cost (in nanoseconds, Q48.16 format)
* of recovering from wrong speculation.
* This is calibrated to the actual recovery time on target hardware.
* Range: 0 to 100 ns
* Default: see starforth_config.h (STARFORTH_CONFIG_MISPREDICTION_COST_Q48_DEFAULT)
* Q48.16 encoding: 25 ns = 25 << 16 = 0x190000LL
*/
/**
* MINIMUM_PREFETCH_ROI: Minimum expected Return-On-Investment ratio
* for speculation to be worthwhile.
* Speculation succeeds only if:
* (prefetch_latency_saved / total_attempts) > MINIMUM_PREFETCH_ROI
* Range: 1.0 (always speculate) to 2.0 (very selective)
* Default: see starforth_config.h (STARFORTH_CONFIG_MINIMUM_PREFETCH_ROI_DEFAULT)
* Q48.16 encoding: 1.10 = 1.10 * (1 << 16) = 0x1199AL
*/
/**
* TRANSITION_WINDOW_SIZE: Knob #6 - Execution context depth for prediction
*
* How many previous words to remember when predicting next word.
* Larger window captures deeper patterns but uses more memory.
*
* Window=1: Only immediate predecessor (A→B predictions)
* Window=2: Previous 2 words (A,B→C predictions) - good balance
* Window=4: Previous 4 words (captures multi-level patterns)
* Window=8: Very deep, expensive -- see starforth_config.h for the actual
* shipped default
*
* Binary Chop Search Space (Phase 2):
* Iteration 1: Try window=2 (baseline)
* Iteration 2: Try window=1 and window=4
* Iteration 3: Narrow to optimal (1, 2, or 4)
* Converge: Pick size with highest prediction accuracy
*
* Range: 1 to 8
* Default: see starforth_config.h (STARFORTH_CONFIG_TRANSITION_WINDOW_SIZE_DEFAULT)
* Trade-off: Pattern depth vs. memory usage & complexity
*
* Tuning: make TRANSITION_WINDOW_SIZE=1 (or 2, 4, 8)
*/
/* ============================================================================
* Word Transition Metrics
* ============================================================================
*
* Allocated per dictionary entry to track which words follow this word.
* This is the basis for speculative prefetching decisions.
*/
typedef struct WordTransitionMetrics {
/**
* transition_heat[i]: Number of times word with index i has been
* executed immediately after this word.
*
* Dynamically allocated array of size DICTIONARY_SIZE.
* Initialized to NULL; allocated on first use to save memory
* for words that are never executed.
*/
uint64_t *transition_heat;
/** Total number of transitions observed from this word */
uint64_t total_transitions;
/** Number of speculative prefetch attempts made for this word */
uint64_t prefetch_attempts;
/** Number of successful prefetch predictions (hits) */
uint64_t prefetch_hits;
/** Number of failed prefetch predictions (misses) */
uint64_t prefetch_misses;
/**
* Total latency saved through successful prefetching (Q48.16 nanoseconds).
* Positive value indicates net benefit from speculation.
*/
int64_t prefetch_latency_saved_q48;
/**
* Total latency cost from failed prefetch predictions (Q48.16 nanoseconds).
* Negative value (cost) to be subtracted from savings.
*/
int64_t misprediction_cost_q48;
/**
* Cached probability of most likely next word (for quick access).
* Updated periodically to avoid recomputation.
* Q48.16 format (0.0 to 1.0 == 0LL to 1LL<<16)
*/
int64_t max_transition_probability_q48;
/**
* Index (word id) of most likely next word.
* Used for fast prefetch without scanning transition_heat array.
*/
uint32_t most_likely_next_word_id;
/* ========== Context-Aware Transitions (Phase 1 Extension) ========== */
/**
* Circular buffer of previous word IDs for context tracking.
* Size = TRANSITION_WINDOW_SIZE (default 2)
* Used to build multi-word context patterns (e.g., A,B→C)
*
* Example with WINDOW=2:
* context_window[0] = older word (2 steps back)
* context_window[1] = recent word (1 step back)
* Next word completes the pattern: (context_window[0], context_window[1]) → next
*/
uint32_t *context_window;
/**
* Current position in context_window circular buffer.
* Points to slot where next word ID will be stored.
*/
uint32_t context_window_pos;
/**
* Sparse hash table for context-based transitions.
* Maps: hash(context_window) → counts_array[DICTIONARY_SIZE]
*
* Phase 1: Collect only (simple reference implementation)
* Phase 2: Analyze prediction accuracy by context depth
* Phase 3: Use for adaptive prefetching decisions
*
* Opaque pointer - implementation is in transition_metrics.c
*/
void *context_transitions;
/**
* Total context-based transitions observed.
* Counter for Phase 2 analysis (accuracy measurement)
*/
uint64_t total_context_transitions;
/**
* Actual window size for this word's metrics.
* May differ from TRANSITION_WINDOW_SIZE if memory allocation failed.
* Phase 2 uses this to validate context data reliability.
*/
uint32_t actual_window_size;
} WordTransitionMetrics;
/* ============================================================================
* Transition Metrics API
* ============================================================================
*/
/*
* Initialize word transition metrics for a dictionary entry.
* Called once per word during dictionary entry creation.
*
* @param metrics Pointer to uninitialized WordTransitionMetrics
* @return 0 on success, -1 on memory allocation failure
*/
int transition_metrics_init(WordTransitionMetrics *metrics);
/*
* Record a word transition (word_from -> word_to).
* Called in the inner interpreter after each word execution.
*
* @param metrics Metrics for the current word
* @param next_word_id Index of word that executed next
* @param dict_size Total number of words in dictionary (for array bounds)
* @return 0 on success, -1 on invalid word_id
*/
int transition_metrics_record(WordTransitionMetrics *metrics, uint32_t next_word_id, uint32_t dict_size);
/*
* Get the probability (Q48.16 format) of a specific word following this word.
*
* Returns: (transition_heat[target] / total_transitions) in Q48.16 format
* or 0 if total_transitions == 0
*
* @param metrics Metrics for the current word
* @param target_word_id Index of potential next word
* @return Probability in Q48.16 format (0.0 to 1.0)
*/
int64_t transition_metrics_get_probability_q48(const WordTransitionMetrics *metrics, uint32_t target_word_id);
/*
* Update cached most-likely-next-word information.
* Should be called periodically (e.g., after every 100 transitions)
* to avoid stale cache.
*
* @param metrics Metrics for the current word
* @param dict_size Total number of words in dictionary
*/
void transition_metrics_update_cache(WordTransitionMetrics *metrics, uint32_t dict_size);
/*
* Record a successful prefetch prediction.
* Called when speculation correctly predicted the next word.
*
* @param metrics Metrics for the current word
* @param latency_saved_ns Nanoseconds saved (will be Q48.16 encoded)
*/
void transition_metrics_record_prefetch_hit(WordTransitionMetrics *metrics, int64_t latency_saved_ns);
/*
* Record a failed prefetch prediction.
* Called when speculation incorrectly predicted the next word.
*
* @param metrics Metrics for the current word
* @param recovery_cost_ns Nanoseconds lost to misprediction recovery
*/
void transition_metrics_record_prefetch_miss(WordTransitionMetrics *metrics, int64_t recovery_cost_ns);
/*
* Check if speculation should be attempted for a given target word.
* Applies threshold logic and ROI analysis.
*
* Returns: 1 if speculation should be attempted, 0 otherwise
*
* @param metrics Metrics for the current word
* @param target_word_id Index of potential next word
* @return 1 if probability > SPECULATION_THRESHOLD and enough samples, 0 otherwise
*/
int transition_metrics_should_speculate(const WordTransitionMetrics *metrics, uint32_t target_word_id);
/*
* Get detailed statistics string for diagnostics.
* Caller must free the returned string.
*
* @param metrics Metrics to report on
* @return Formatted statistics string (must be freed by caller)
*/
char *transition_metrics_stats_string(const WordTransitionMetrics *metrics);
/*
* Reset all transition metrics (clear counts, free transition_heat array).
* Called on VM reset or explicit metrics reset.
*
* @param metrics Metrics to reset
*/
void transition_metrics_reset(WordTransitionMetrics *metrics);
/*
* Free all allocated memory for transition metrics.
* Called during dictionary cleanup.
*
* @param metrics Metrics to clean up
*/
void transition_metrics_cleanup(WordTransitionMetrics *metrics);
/* ============================================================================
* Context-Aware Transition API (Phase 1 Extension)
* ============================================================================
*
* These functions handle multi-word pattern tracking for Phase 2 analysis.
* Phase 1: Collect context window data (this session)
* Phase 2: Analyze accuracy by context depth (next session)
* Phase 3: Use for adaptive prediction (future)
*/
/*
* Record a context-based transition (multi-word pattern).
* Called after each word execution with the execution window.
*
* Example with WINDOW=2:
* context[0] = word_A, context[1] = word_B, next_word = word_C
* Records: (A,B) → C transition in sparse hash table
*
* Phase 1: Just collects data, no analysis
* Phase 2: Will measure: "Do patterns with window=2 predict better than window=1?"
*
* @param metrics Metrics for the current word
* @param context Array of word IDs forming the context (size = window_size)
* @param window_size Length of context array
* @param next_word_id Word that follows the context
* @param dict_size Total number of words in dictionary
* @return 0 on success, -1 on error
*/
int transition_metrics_record_context(WordTransitionMetrics *metrics,
const uint32_t *context,
uint32_t window_size,
uint32_t next_word_id,
uint32_t dict_size);
/*
* Update the execution context window with a new word.
* Called after each word execution to slide the window forward.
*
* Example with WINDOW=2:
* Before: [A, B] (two previous words)
* After calling with C: [B, C] (shift left, add C on right)
*
* @param metrics Metrics to update
* @param word_id New word ID to add to window
* @return 0 on success, -1 if context tracking not initialized
*/
int transition_metrics_update_context_window(WordTransitionMetrics *metrics, uint32_t word_id);
/*
* Get context-based prediction accuracy statistics (Phase 2).
* Compares prediction success rates across different window sizes.
*
* Phase 2 will use this to run binary chop tuning:
* Measure accuracy(window=1), accuracy(window=2), accuracy(window=4)
* Binary search converges to optimal window size
*
* @param metrics Metrics to analyze
* @return Formatted string with accuracy statistics (caller must free)
*/
char *transition_metrics_context_accuracy_string(const WordTransitionMetrics *metrics);
/*
* Get recommended window size based on collected data.
* Phase 2 will call this as part of binary chop tuning algorithm.
*
* Algorithm:
* 1. Collect data with current window size
* 2. Measure prediction accuracy
* 3. If accuracy improves, try larger window
* 4. If accuracy declines, try smaller window
* 5. Converge to optimal size
*
* @param metrics Metrics to analyze
* @param current_window Current window size being tested
* @param accuracy_at_current Measured accuracy with current window
* @return Suggested next window size to try (1, 2, 4, or 8)
*/
uint32_t transition_metrics_binary_chop_suggest_window(const WordTransitionMetrics *metrics,
uint32_t current_window,
double accuracy_at_current);
#endif /* PHYSICS_PIPELINING_METRICS_H */