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:
@@ -0,0 +1,5 @@
|
||||
# src/starkernel/hash/
|
||||
|
||||
- `xxhash64.c` — XXHash64 implementation used for capsule content
|
||||
addressing (a capsule's ID is the XXHash64 of its content; any mutation
|
||||
is detectable) and for dictionary-hash comparison in parity records.
|
||||
@@ -0,0 +1,285 @@
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* xxhash64.c - Freestanding xxHash64 Implementation
|
||||
*
|
||||
* Based on xxHash by Yann Collet (BSD-2-Clause).
|
||||
* Adapted for freestanding kernel use - no libc dependency.
|
||||
*
|
||||
* xxHash is an extremely fast non-cryptographic hash algorithm.
|
||||
* https://github.com/Cyan4973/xxHash
|
||||
*/
|
||||
|
||||
#include "starkernel/xxhash64.h"
|
||||
|
||||
/*===========================================================================
|
||||
* xxHash64 Constants
|
||||
*===========================================================================*/
|
||||
|
||||
#define XXHASH64_PRIME1 0x9E3779B185EBCA87ULL
|
||||
#define XXHASH64_PRIME2 0xC2B2AE3D27D4EB4FULL
|
||||
#define XXHASH64_PRIME3 0x165667B19E3779F9ULL
|
||||
#define XXHASH64_PRIME4 0x85EBCA77C2B2AE63ULL
|
||||
#define XXHASH64_PRIME5 0x27D4EB2F165667C5ULL
|
||||
|
||||
/*===========================================================================
|
||||
* Helper Functions
|
||||
*===========================================================================*/
|
||||
|
||||
/**
|
||||
* Rotate left 64-bit
|
||||
*/
|
||||
static inline uint64_t xxh64_rotl(uint64_t x, int r) {
|
||||
return (x << r) | (x >> (64 - r));
|
||||
}
|
||||
|
||||
/**
|
||||
* Read 64-bit little-endian (unaligned safe)
|
||||
*/
|
||||
static inline uint64_t xxh64_read64(const uint8_t *p) {
|
||||
return ((uint64_t)p[0]) |
|
||||
((uint64_t)p[1] << 8) |
|
||||
((uint64_t)p[2] << 16) |
|
||||
((uint64_t)p[3] << 24) |
|
||||
((uint64_t)p[4] << 32) |
|
||||
((uint64_t)p[5] << 40) |
|
||||
((uint64_t)p[6] << 48) |
|
||||
((uint64_t)p[7] << 56);
|
||||
}
|
||||
|
||||
/**
|
||||
* Read 32-bit little-endian (unaligned safe)
|
||||
*/
|
||||
static inline uint32_t xxh64_read32(const uint8_t *p) {
|
||||
return ((uint32_t)p[0]) |
|
||||
((uint32_t)p[1] << 8) |
|
||||
((uint32_t)p[2] << 16) |
|
||||
((uint32_t)p[3] << 24);
|
||||
}
|
||||
|
||||
/**
|
||||
* Round function
|
||||
*/
|
||||
static inline uint64_t xxh64_round(uint64_t acc, uint64_t input) {
|
||||
acc += input * XXHASH64_PRIME2;
|
||||
acc = xxh64_rotl(acc, 31);
|
||||
acc *= XXHASH64_PRIME1;
|
||||
return acc;
|
||||
}
|
||||
|
||||
/**
|
||||
* Merge accumulator
|
||||
*/
|
||||
static inline uint64_t xxh64_merge_round(uint64_t acc, uint64_t val) {
|
||||
val = xxh64_round(0, val);
|
||||
acc ^= val;
|
||||
acc = acc * XXHASH64_PRIME1 + XXHASH64_PRIME4;
|
||||
return acc;
|
||||
}
|
||||
|
||||
/**
|
||||
* Avalanche finalization
|
||||
*/
|
||||
static inline uint64_t xxh64_avalanche(uint64_t h) {
|
||||
h ^= h >> 33;
|
||||
h *= XXHASH64_PRIME2;
|
||||
h ^= h >> 29;
|
||||
h *= XXHASH64_PRIME3;
|
||||
h ^= h >> 32;
|
||||
return h;
|
||||
}
|
||||
|
||||
/*===========================================================================
|
||||
* One-Shot Hashing
|
||||
*===========================================================================*/
|
||||
|
||||
uint64_t xxhash64(const void *data, size_t len, uint64_t seed) {
|
||||
const uint8_t *p = (const uint8_t *)data;
|
||||
const uint8_t *end = p + len;
|
||||
uint64_t h64;
|
||||
|
||||
if (len >= 32) {
|
||||
const uint8_t *limit = end - 32;
|
||||
uint64_t v1 = seed + XXHASH64_PRIME1 + XXHASH64_PRIME2;
|
||||
uint64_t v2 = seed + XXHASH64_PRIME2;
|
||||
uint64_t v3 = seed + 0;
|
||||
uint64_t v4 = seed - XXHASH64_PRIME1;
|
||||
|
||||
do {
|
||||
v1 = xxh64_round(v1, xxh64_read64(p));
|
||||
p += 8;
|
||||
v2 = xxh64_round(v2, xxh64_read64(p));
|
||||
p += 8;
|
||||
v3 = xxh64_round(v3, xxh64_read64(p));
|
||||
p += 8;
|
||||
v4 = xxh64_round(v4, xxh64_read64(p));
|
||||
p += 8;
|
||||
} while (p <= limit);
|
||||
|
||||
h64 = xxh64_rotl(v1, 1) + xxh64_rotl(v2, 7) +
|
||||
xxh64_rotl(v3, 12) + xxh64_rotl(v4, 18);
|
||||
|
||||
h64 = xxh64_merge_round(h64, v1);
|
||||
h64 = xxh64_merge_round(h64, v2);
|
||||
h64 = xxh64_merge_round(h64, v3);
|
||||
h64 = xxh64_merge_round(h64, v4);
|
||||
} else {
|
||||
h64 = seed + XXHASH64_PRIME5;
|
||||
}
|
||||
|
||||
h64 += (uint64_t)len;
|
||||
|
||||
/* Process remaining 8-byte chunks */
|
||||
while (p + 8 <= end) {
|
||||
uint64_t k1 = xxh64_round(0, xxh64_read64(p));
|
||||
h64 ^= k1;
|
||||
h64 = xxh64_rotl(h64, 27) * XXHASH64_PRIME1 + XXHASH64_PRIME4;
|
||||
p += 8;
|
||||
}
|
||||
|
||||
/* Process remaining 4-byte chunk */
|
||||
if (p + 4 <= end) {
|
||||
h64 ^= (uint64_t)xxh64_read32(p) * XXHASH64_PRIME1;
|
||||
h64 = xxh64_rotl(h64, 23) * XXHASH64_PRIME2 + XXHASH64_PRIME3;
|
||||
p += 4;
|
||||
}
|
||||
|
||||
/* Process remaining bytes */
|
||||
while (p < end) {
|
||||
h64 ^= (uint64_t)(*p) * XXHASH64_PRIME5;
|
||||
h64 = xxh64_rotl(h64, 11) * XXHASH64_PRIME1;
|
||||
p++;
|
||||
}
|
||||
|
||||
return xxh64_avalanche(h64);
|
||||
}
|
||||
|
||||
/*===========================================================================
|
||||
* Streaming API
|
||||
*===========================================================================*/
|
||||
|
||||
void xxhash64_reset(XXHash64State *state, uint64_t seed) {
|
||||
state->total_len = 0;
|
||||
state->v1 = seed + XXHASH64_PRIME1 + XXHASH64_PRIME2;
|
||||
state->v2 = seed + XXHASH64_PRIME2;
|
||||
state->v3 = seed + 0;
|
||||
state->v4 = seed - XXHASH64_PRIME1;
|
||||
state->buffer_size = 0;
|
||||
state->seed = seed;
|
||||
}
|
||||
|
||||
void xxhash64_update(XXHash64State *state, const void *data, size_t len) {
|
||||
const uint8_t *p = (const uint8_t *)data;
|
||||
const uint8_t *end = p + len;
|
||||
|
||||
state->total_len += len;
|
||||
|
||||
/* Fill buffer if we have leftover data */
|
||||
if (state->buffer_size + len < 32) {
|
||||
/* Not enough to process, just buffer it */
|
||||
while (p < end) {
|
||||
state->buffer[state->buffer_size++] = *p++;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* Process buffered data first */
|
||||
if (state->buffer_size > 0) {
|
||||
uint32_t fill = 32 - state->buffer_size;
|
||||
for (uint32_t i = 0; i < fill; i++) {
|
||||
state->buffer[state->buffer_size + i] = p[i];
|
||||
}
|
||||
p += fill;
|
||||
|
||||
state->v1 = xxh64_round(state->v1, xxh64_read64(state->buffer));
|
||||
state->v2 = xxh64_round(state->v2, xxh64_read64(state->buffer + 8));
|
||||
state->v3 = xxh64_round(state->v3, xxh64_read64(state->buffer + 16));
|
||||
state->v4 = xxh64_round(state->v4, xxh64_read64(state->buffer + 24));
|
||||
|
||||
state->buffer_size = 0;
|
||||
}
|
||||
|
||||
/* Process 32-byte blocks */
|
||||
if (p + 32 <= end) {
|
||||
const uint8_t *limit = end - 32;
|
||||
do {
|
||||
state->v1 = xxh64_round(state->v1, xxh64_read64(p));
|
||||
p += 8;
|
||||
state->v2 = xxh64_round(state->v2, xxh64_read64(p));
|
||||
p += 8;
|
||||
state->v3 = xxh64_round(state->v3, xxh64_read64(p));
|
||||
p += 8;
|
||||
state->v4 = xxh64_round(state->v4, xxh64_read64(p));
|
||||
p += 8;
|
||||
} while (p <= limit);
|
||||
}
|
||||
|
||||
/* Buffer remaining bytes */
|
||||
while (p < end) {
|
||||
state->buffer[state->buffer_size++] = *p++;
|
||||
}
|
||||
}
|
||||
|
||||
uint64_t xxhash64_digest(const XXHash64State *state) {
|
||||
const uint8_t *p = state->buffer;
|
||||
const uint8_t *end = p + state->buffer_size;
|
||||
uint64_t h64;
|
||||
|
||||
if (state->total_len >= 32) {
|
||||
h64 = xxh64_rotl(state->v1, 1) + xxh64_rotl(state->v2, 7) +
|
||||
xxh64_rotl(state->v3, 12) + xxh64_rotl(state->v4, 18);
|
||||
|
||||
h64 = xxh64_merge_round(h64, state->v1);
|
||||
h64 = xxh64_merge_round(h64, state->v2);
|
||||
h64 = xxh64_merge_round(h64, state->v3);
|
||||
h64 = xxh64_merge_round(h64, state->v4);
|
||||
} else {
|
||||
h64 = state->seed + XXHASH64_PRIME5;
|
||||
}
|
||||
|
||||
h64 += state->total_len;
|
||||
|
||||
/* Process remaining 8-byte chunks */
|
||||
while (p + 8 <= end) {
|
||||
uint64_t k1 = xxh64_round(0, xxh64_read64(p));
|
||||
h64 ^= k1;
|
||||
h64 = xxh64_rotl(h64, 27) * XXHASH64_PRIME1 + XXHASH64_PRIME4;
|
||||
p += 8;
|
||||
}
|
||||
|
||||
/* Process remaining 4-byte chunk */
|
||||
if (p + 4 <= end) {
|
||||
h64 ^= (uint64_t)xxh64_read32(p) * XXHASH64_PRIME1;
|
||||
h64 = xxh64_rotl(h64, 23) * XXHASH64_PRIME2 + XXHASH64_PRIME3;
|
||||
p += 4;
|
||||
}
|
||||
|
||||
/* Process remaining bytes */
|
||||
while (p < end) {
|
||||
h64 ^= (uint64_t)(*p) * XXHASH64_PRIME5;
|
||||
h64 = xxh64_rotl(h64, 11) * XXHASH64_PRIME1;
|
||||
p++;
|
||||
}
|
||||
|
||||
return xxh64_avalanche(h64);
|
||||
}
|
||||
Reference in New Issue
Block a user