The header scan (Captain Bob, 2026-11-10): 788 source files -- 351 with the
SL-1.0 header, 12 with the old name (docs/working/experiments, kept by
ruling), 31 under someone else's licence (tools/kconfig, Linux's, GPL-2.0:
kept), and 394 with none. Ruled: the SPDX form; capsules (.4th, .f18) and
proofs (.thy) left for a ruling of their own (mkcapsule's 64x16 block format,
content-addressed capsules).
253 files now begin
SPDX-License-Identifier: LicenseRef-Starship-1.0
Copyright (c) 2023-2026 Robert A. James
as a /* */ block (C, headers, assembly, linker scripts) or # lines (scripts,
Makefiles, Kconfig; below a shebang or a coding line); tools/mkcapsule.c,
which had the copyright line, gets the SPDX line only.
Not touched: docs/working/ (archive and old campaign material, as the
ruling kept the experiments); v4/system/post_cases.c (generated by
v4/tools/mkpost.py, "do not edit" -- the generator has the header).
Comments only: the kernel builds on amd64, aarch64, riscv64; make -C v4
test-32: 39 programs, 0 failures; every changed script parses.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GE3SDvQn5EoxdGufk84zz2
83 lines
4.1 KiB
C
83 lines
4.1 KiB
C
/* SPDX-License-Identifier: LicenseRef-Starship-1.0
|
||
* Copyright (c) 2023-2026 Robert A. James
|
||
*/
|
||
/* heat.h -- heat and anti-clock, not instructions themselves (1.4).
|
||
*
|
||
* DECOMPOSITION.md section 1.4 states: "Execution itself drives the physics.
|
||
* Every retired instruction increments that opcode's heat counter and advances
|
||
* the anti-clock; every `call` increments the heat counter of its target. None
|
||
* of this costs an instruction."
|
||
*
|
||
* D-6 is deferred to step 2, but the note immediately adds: "The golden model
|
||
* implements per-opcode and per-call-target heat in the meantime." The
|
||
* counters here are therefore a two-dimensional heat structure (op × target)
|
||
* on a per-call basis, with counts stored in 64-bit (because heat is
|
||
* accumulated and must not roll over at 32-bit). The "per-call-target"
|
||
* counter is indexed by the address of the called target -- on a word-addressed
|
||
* node, that is a cell value equal to the address `a` passed to `call a`.
|
||
*
|
||
* The anti-clock is a virtual tick driven by execution -- one tick per retired
|
||
* instruction -- and the rest of §7 refers to it via `ANTICLOCK`. It is not a
|
||
* wall-clock time, it is a function of the execution stream, as specified.
|
||
*
|
||
* The MM names in §7: `HEAT-OP[0..31]` (R), `HEAT-CALL[...]` (R/W) with a
|
||
* freeze bit (D-6). D-4 (memory map) is deferred, so the model does not
|
||
* materialize those MM addresses yet. This header defines the backing storage
|
||
* that a later MM layer will expose; it keeps the counts separate from the node
|
||
* itself because heat is physics data, not the instruction word stream, and it
|
||
* needs to be accessible to assertions such as K conservation tests later.
|
||
*
|
||
* Counts are 64-bit. Even for a short run a call-heavy word can heat up many
|
||
* times, and the golden model must run POST and remain monotonic and
|
||
* comparable. They are stored as `v4_uheat_t` (which is uint64_t by cell-width
|
||
* parameterisation) rather than cell-sized so that a 32-bit node's heat is not
|
||
* width-truncated in the model. (JUSTIFICATION.md §5 keeps heat arithmetic
|
||
* 64-bit regardless of cell width.)
|
||
*/
|
||
#ifndef V4_HEAT_H
|
||
#define V4_HEAT_H
|
||
|
||
#include "v4/cell.h"
|
||
#include "v4/opcode.h"
|
||
|
||
#define V4_HEAT_MAX_CALL_TARGETS 4096u
|
||
|
||
typedef struct {
|
||
v4_uheat_t op[V4_OPCODE_COUNT]; /* HEAT-OP[0..31] */
|
||
|
||
/* Per-call-target heat. Indexed by target address. The table is fixed-size
|
||
* for the golden model; the actual hardware table size is deferred with D-6,
|
||
* but "in the meantime" the model must have a per-call-target structure.
|
||
* 4096 entries is small (32KB if using 64-bit per entry), enough to cover a
|
||
* typical test program's call targets without needing to allocate on-the-fly
|
||
* -- and since the node has boundaries, over-indexing is caught. */
|
||
v4_uheat_t call[V4_HEAT_MAX_CALL_TARGETS];
|
||
v4_ucell call_freeze_mask[V4_HEAT_MAX_CALL_TARGETS / (sizeof(v4_ucell) * 8u)];
|
||
/* freeze bits: one per call-target entry (D-6). Stored as a bitmask. */
|
||
} v4_heat;
|
||
|
||
void v4_heat_reset(v4_heat *h);
|
||
|
||
/* Every retired instruction: +1 to the opcode's heat and +1 to ANTICLOCK. */
|
||
void v4_heat_on_retire(v4_heat *h, unsigned op, v4_uheat_t *anticlock);
|
||
|
||
/* Every call: +1 to the call-target's heat. The target is the address passed
|
||
* to call (word address). If the target is outside the table range, the model
|
||
* must not silently wrap -- a boundary-style check is the conservative choice
|
||
* here, because the table size is a model parameter. */
|
||
void v4_heat_on_call(v4_heat *h, v4_cell target);
|
||
|
||
/* Read/write helpers for per-call-target heat (R/W). Freeze bits are set per
|
||
* target when D-6's freeze bit is asserted; writes to a frozen target should be
|
||
* ignored in a real implementation, but the MM layer is not defined yet. The
|
||
* golden model stores freeze bits and the accessor can enforce them later. */
|
||
v4_uheat_t v4_heat_call_get(const v4_heat *h, v4_cell target);
|
||
int v4_heat_call_set(v4_heat *h, v4_cell target, v4_uheat_t val);
|
||
|
||
/* Freeze control (D-6). */
|
||
void v4_heat_call_freeze(v4_heat *h, v4_cell target);
|
||
void v4_heat_call_unfreeze(v4_heat *h, v4_cell target);
|
||
int v4_heat_call_is_frozen(const v4_heat *h, v4_cell target);
|
||
|
||
#endif /* V4_HEAT_H */
|