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:
+238
@@ -0,0 +1,238 @@
|
||||
/*
|
||||
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.
|
||||
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "cli.h"
|
||||
#include "version.h"
|
||||
|
||||
/* Parse helper for --ram-disk */
|
||||
static int parse_u32(const char* s, uint32_t* out)
|
||||
{
|
||||
if (!s || !*s) return -1;
|
||||
uint64_t v = 0;
|
||||
for (const char* p = s; *p; ++p)
|
||||
{
|
||||
if (*p < '0' || *p > '9') return -1;
|
||||
v = v * 10u + (uint32_t)(*p - '0');
|
||||
if (v > 0xffffffffULL) return -1;
|
||||
}
|
||||
*out = (uint32_t)v;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Print usage/help information
|
||||
*/
|
||||
void cli_print_usage(const char* program_name)
|
||||
{
|
||||
printf("Usage: %s [OPTIONS]\n", program_name);
|
||||
printf("StarForth - A lightweight Forth virtual machine\n\n");
|
||||
printf("Options:\n");
|
||||
printf(" -s Script/silent mode - suppress prompts and 'ok' output (for piped input)\n");
|
||||
printf(" --break-me 🔥 ULTRA-COMPREHENSIVE diagnostic mode - tests EVERYTHING\n");
|
||||
printf(" --benchmark [N] Run performance benchmarks (default: 1000 iterations)\n");
|
||||
printf(" --log-error Set logging level to ERROR (only errors)\n");
|
||||
printf(" --log-warn Set logging level to WARN (warnings and errors)\n");
|
||||
printf(" --log-info Set logging level to INFO (default)\n");
|
||||
printf(" --log-test Set logging level to TEST (test results_run_01_2025_12_08 only)\n");
|
||||
printf(" --log-debug Set logging level to DEBUG (all messages)\n");
|
||||
printf(" --log-none Disable all logging (maximum performance)\n");
|
||||
printf(" --fail-fast Stop test suite immediately on first failure\n");
|
||||
printf(" --doe Run DoE experiment: output CSV metrics to stdout and exit\n");
|
||||
printf(" --heartbeat-log=<mode> Heartbeat logging mode (off|summary|full)\n");
|
||||
printf(" off: No heartbeat output (default)\n");
|
||||
printf(" summary: Bucket aggregates in main CSV\n");
|
||||
printf(" full: Per-tick CSV to hb/run-<id>.csv\n");
|
||||
printf(" --disk-img=<path> Use raw disk image file at <path>\n");
|
||||
printf(" --ram-disk=<MB> RAM fallback size if no --disk-img (default: 1 MB)\n");
|
||||
printf(" --version, -v Show version information and exit\n");
|
||||
printf(" --help, -h Show this help message\n\n");
|
||||
printf("Examples:\n");
|
||||
printf(" %s # Start REPL with INFO logging\n", program_name);
|
||||
printf(" %s -s < script.forth # Run script from stdin (no prompts)\n", program_name);
|
||||
printf(" %s --benchmark # Run benchmarks with 1000 iterations\n", program_name);
|
||||
printf(" %s --disk-img=./disks/starship.img # Use disk image\n", program_name);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Parse command-line arguments into CLIConfig
|
||||
*/
|
||||
CLIConfig cli_parse(int argc, char* argv[])
|
||||
{
|
||||
CLIConfig config = {
|
||||
/* Test modes - all default to 0 */
|
||||
.run_tests = 0,
|
||||
.break_me = 0,
|
||||
.fail_fast = 0,
|
||||
.run_tests_flag_observed = 0,
|
||||
|
||||
/* Benchmark */
|
||||
.benchmark = 0,
|
||||
.benchmark_iterations = 1000,
|
||||
|
||||
/* Design of Experiments */
|
||||
.doe_experiment = 0,
|
||||
.heartbeat_log_mode = HEARTBEAT_LOG_OFF,
|
||||
|
||||
/* REPL mode */
|
||||
.script_mode = 0,
|
||||
|
||||
/* Logging */
|
||||
.log_level = LOG_INFO,
|
||||
.log_level_explicitly_set = 0,
|
||||
|
||||
/* Block I/O */
|
||||
.disk_img_path = NULL,
|
||||
.ram_disk_mb = 1,
|
||||
};
|
||||
|
||||
for (int i = 1; i < argc; i++)
|
||||
{
|
||||
if (strcmp(argv[i], "--run-tests") == 0)
|
||||
{
|
||||
config.run_tests_flag_observed = 1;
|
||||
}
|
||||
else if (strcmp(argv[i], "--break-me") == 0)
|
||||
{
|
||||
config.break_me = 1;
|
||||
}
|
||||
else if (strcmp(argv[i], "--benchmark") == 0)
|
||||
{
|
||||
config.benchmark = 1;
|
||||
if (i + 1 < argc && atoi(argv[i + 1]) > 0)
|
||||
{
|
||||
config.benchmark_iterations = atoi(argv[i + 1]);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
else if (strcmp(argv[i], "--log-error") == 0)
|
||||
{
|
||||
config.log_level = LOG_ERROR;
|
||||
config.log_level_explicitly_set = 1;
|
||||
}
|
||||
else if (strcmp(argv[i], "--log-warn") == 0)
|
||||
{
|
||||
config.log_level = LOG_WARN;
|
||||
config.log_level_explicitly_set = 1;
|
||||
}
|
||||
else if (strcmp(argv[i], "--log-info") == 0)
|
||||
{
|
||||
config.log_level = LOG_INFO;
|
||||
config.log_level_explicitly_set = 1;
|
||||
}
|
||||
else if (strcmp(argv[i], "--log-test") == 0)
|
||||
{
|
||||
config.log_level = LOG_TEST;
|
||||
config.log_level_explicitly_set = 1;
|
||||
}
|
||||
else if (strcmp(argv[i], "--log-debug") == 0)
|
||||
{
|
||||
config.log_level = LOG_DEBUG;
|
||||
config.log_level_explicitly_set = 1;
|
||||
}
|
||||
else if (strcmp(argv[i], "--log-none") == 0)
|
||||
{
|
||||
config.log_level = LOG_NONE;
|
||||
config.log_level_explicitly_set = 1;
|
||||
}
|
||||
else if (strcmp(argv[i], "--fail-fast") == 0)
|
||||
{
|
||||
config.fail_fast = 1;
|
||||
}
|
||||
else if (strcmp(argv[i], "--doe-experiment") == 0 || strcmp(argv[i], "--doe") == 0)
|
||||
{
|
||||
config.doe_experiment = 1;
|
||||
}
|
||||
else if (strncmp(argv[i], "--heartbeat-log=", 16) == 0)
|
||||
{
|
||||
const char* mode_str = argv[i] + 16;
|
||||
if (strcmp(mode_str, "off") == 0) {
|
||||
config.heartbeat_log_mode = HEARTBEAT_LOG_OFF;
|
||||
} else if (strcmp(mode_str, "summary") == 0) {
|
||||
config.heartbeat_log_mode = HEARTBEAT_LOG_SUMMARY;
|
||||
} else if (strcmp(mode_str, "full") == 0) {
|
||||
config.heartbeat_log_mode = HEARTBEAT_LOG_FULL;
|
||||
} else {
|
||||
fprintf(stderr, "Invalid --heartbeat-log value: %s (expected off|summary|full)\n", mode_str);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
else if (strcmp(argv[i], "-s") == 0)
|
||||
{
|
||||
config.script_mode = 1;
|
||||
}
|
||||
else if (strncmp(argv[i], "--disk-img=", 11) == 0)
|
||||
{
|
||||
config.disk_img_path = argv[i] + 11;
|
||||
}
|
||||
else if (strncmp(argv[i], "--ram-disk=", 11) == 0)
|
||||
{
|
||||
uint32_t tmp = 0;
|
||||
if (parse_u32(argv[i] + 11, &tmp) != 0 || tmp == 0)
|
||||
{
|
||||
fprintf(stderr, "Invalid --ram-disk value: %s (positive MB expected)\n", argv[i] + 11);
|
||||
exit(1);
|
||||
}
|
||||
config.ram_disk_mb = tmp;
|
||||
}
|
||||
else if (strcmp(argv[i], "--version") == 0 || strcmp(argv[i], "-v") == 0)
|
||||
{
|
||||
printf("%s\n", STARFORTH_VERSION_FULL);
|
||||
exit(0);
|
||||
}
|
||||
else if (strcmp(argv[i], "--help") == 0 || strcmp(argv[i], "-h") == 0)
|
||||
{
|
||||
cli_print_usage(argv[0]);
|
||||
exit(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("Unknown option: %s\n", argv[i]);
|
||||
cli_print_usage(argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
return config;
|
||||
}
|
||||
Reference in New Issue
Block a user