Files
LithosAnanke/v4/include/v4/mesh.h
T
Claude e8e7ec8b9f feat(v4): word accounts at call -- the word ID in the header, the kernel's records, the Stadium charged per tick (#189)
ENGINE step 4 Phase 2 (plan docs/v4.0.0/plans/2026-11-13-engine-step4-phase2-word-accounts.md). Rulings,
Captain Bob 2026-11-13: "ID field in the header"; "Per heartbeat tick"; the ACL "All of it in Phase 4".

- The word ID, at xt-4 before the flags (ENGINE.md 3b). The system's words are numbered as they are
  assembled, by a new directive, #id, (and #ids, the count), in the C assembler (text.c) and in the
  machine ROM's (capsules/v4/rom), which counts in the system's own (NEXT-ID). (HEADER) numbers later
  words; FORGET gives back the IDs it frees, always the newest; COLD resets to (BOOT-ID); (SEAL) records
  it. All 313 system headers carry the cell.
- The kernel's records (v4/mesh.h): (TELL-DEFINED) and (TELL-FORGOTTEN), requests -19/-20 on port 0,
  which the kernel puts in (WORD-DEFINED)/(WORD-FORGOTTEN) when it seals a node, and reads the system's
  own words once. A bit per address marks a word's xt (calls into the ROM or headerless code are not
  words); at call, the bit test and a count. v4_mesh_charge hands the owner the calls since.
- The Stadium: stadium_words_charge -- N calls as N of stadium_word_dispatch's dispatches, shared by calls
  when the reservoir is short; sk_v4.c charges every node's words at the tick beside its opcodes, and
  stadium_word_forget before an ID is used again.
- Tests first: test_text.c, test_host_dict.c, test_host_quit.c (numbering, FORGET, COLD),
  test_mesh_boot.c (44 checks), kernel/tests/test_stadium_words.c; qemu_session.py: Hera's words
  admitted after POST.
- amd64: Stadium words: promotions=141 after POST, CONSERVED; POST 539/539; word_count=377;
  dict_hash 0xa854ba15b437d288 (the new cell); the boot 142 s against Phase 1's 153 s.
- v4 test, test-32: all pass; v4-checks: 80 programs under the sanitizers, 0 failures; the hosted
  builds alike. docs/reference/v4-dictionary.tsv: the two new words; FABRIC-3 XLVIII.24.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017RzZgrf7V7Zk2iczBXDRbm
2026-11-13 19:12:44 +00:00

141 lines
8.1 KiB
C

/* SPDX-License-Identifier: LicenseRef-Starship-1.0
* Copyright (c) 2023-2026 Robert A. James
*/
/* mesh.h -- the kernel's boot of the fabric: Hera born empty, given the
* system, and every node stepped together. docs/v4.0.0/MESH.md 9,
* MACHINE.md 3; #189, ENGINE step 4 Phase 1, Task 5b (Captain Bob,
* 2026-11-13: "Build it to proper spec").
*
* There is no scheduler (JUSTIFICATION.md 4: "There is no scheduler to
* write"): every awake node executes an instruction word at each step of
* the fabric (fabric.h), and a node with nothing to do waits at a port.
*
* THE BOOT, as v4/tests/test_host_unit.c does it on the host:
* 1. the nucleus: the machine's ROM assembles the system's source on a
* node of its own (v4/boot.h, v4_boot_assemble), and the system, as
* assembled, is a capsule of F18 cells -- a node that is born is given
* assembled code, never the source (Captain Bob, 2026-10-15);
* 2. Hera is born empty at place 0, with the machine's ROM: the kernel is
* on her port 0 -- it gives her the nucleus a cell at a time, and takes
* her requests: blocks, the kernel's words, the registry (manage.h) --
* and the console on her port 1, which speaks whole messages;
* 3. she is told she is node 10 and where the console is, entered in the
* registry, made the kernel's words, given FORTH-79, sealed, POSTed,
* given the kernel's capsules, and sealed;
* printing the same parity lines as v4_boot_run (boot.h).
*
* A NODE IS BORN (NODE-BORN): in storage the owner gives, with a mesh
* node's ROM, the kernel on its port 0 for its blocks; it is given the
* nucleus by whoever birthed it (centre.4th). NODE-KILL gives the storage
* back.
*
* Nothing here uses the C library. The owner supplies all the memory.
*/
#ifndef V4_MESH_H
#define V4_MESH_H
#include "v4/boot.h"
#include "v4/blocks.h"
#include "v4/fabric.h"
#include "v4/manage.h"
#define V4_MESH_HERA 10 /* Hera's number, as the host mesh numbers her */
#define V4_MESH_CONSOLE 1 /* the console's number as a sender, and her port to it */
#define V4_MESH_NUCLEUS_CELLS (2u * V4_NODE_WORDS + 64u)
/* A WORD'S ACCOUNTS (#189, Phase 2; ENGINE.md 3b): the kernel's record of a word on a node, joined to
* it by the word ID in its header. The node tells the kernel of each entry made and of entries gone
* (dict.f18, (TELL-DEFINED) and (TELL-FORGOTTEN): requests V4_REQ_WORD_DEFINED and _FORGOTTEN on port
* 0); the kernel reads the system's own once, when the node is sealed. At every `call` to a word
* its record counts one: `calls` (v3's execution_heat) and `since`, which the owner takes and clears
* when it charges the Stadium (v4_mesh_charge; Captain Bob, 2026-11-13: "Per heartbeat tick"). */
#define V4_MESH_WORD_IDS 1024u /* word IDs a record is kept for: v3's DICTIONARY_SIZE, the Stadium's bound */
#define V4_REQ_WORD_DEFINED (-19)
#define V4_REQ_WORD_FORGOTTEN (-20)
typedef struct {
v4_uheat_t calls; /* every call since the word was defined */
v4_uheat_t since; /* calls since the owner last charged them */
v4_cell xt; /* the word's xt; 0: no word has this ID */
} v4_mesh_account;
typedef struct v4_mesh v4_mesh;
struct v4_mesh {
/* ---- the owner's: set before v4_mesh_boot ---- */
v4_place *places; /* the fabric's room: `capacity` places */
unsigned capacity;
v4_wire_queue *queues; /* the wires' memory (fabric.h): two for every wire at once */
unsigned queue_count;
v4_manage_entry *reg; /* the registry: `capacity` entries */
v4_blocks *blocks; /* each place's block window, kept by the kernel: `capacity` of them */
v4_fabric_node *nucleus; /* where the ROM assembles the system: a node of its own */
v4_fabric_node *hera; /* Hera's storage */
v4_device *kernel; /* the kernel on each place's port 0: `capacity` of them */
/* storage for a node to be born, or 0: none; and given back */
v4_fabric_node *(*room)(void *self);
void (*unroom)(void *self, v4_fabric_node *x);
/* a node has been born at `place`, numbered `number` once it is told; is gone (may be 0) */
void (*born)(void *self, unsigned place);
void (*gone)(void *self, unsigned place);
/* a node the asker birthed has its system: its parity (may be 0) */
void (*parity)(void *self, unsigned place, v4_cell number, const v4_node *n);
/* the console, the keyboard, the kernel's words and capsules: as v4_boot's (boot.h) */
void (*out)(const char *text, unsigned len);
int (*key)(void);
const char *const *words;
unsigned word_count;
void (*serve)(v4_node *n, unsigned request);
const char *const *capsules;
unsigned capsule_count;
v4_image *im; /* the map's description (v4_map_image), which the boot completes */
/* the words' accounts: `capacity` x V4_MESH_WORD_IDS records, and `capacity` x V4_NODE_WORDS / 8
* bytes, a bit for each address of a node: set for a word's xt (0: none kept) */
v4_mesh_account *accounts;
unsigned char *is_word;
/* a word has gone, its ID free for the next: the owner forgets what it keeps by it (may be 0) */
void (*forgot)(void *self, unsigned place, v4_cell id);
void *self;
/* ---- the mesh's own ---- */
v4_fabric f;
v4_manage m;
unsigned hera_place;
v4_cell cells[V4_MESH_NUCLEUS_CELLS]; /* the nucleus as a capsule of F18 cells */
unsigned cell_count, given; /* how many; how many given to Hera */
unsigned reading_nucleus[64]; /* by place: the next nucleus cell a CAPSULE-CELL gives; 0: not open */
unsigned dones; /* how many texts have said how they ended, ever */
v4_cell done_from, done_how; /* the last of them: from which node, and how */
v4_cell owed_from; /* a node told texts that were left "waiting" ... */
unsigned owed; /* ... and how many of their ends are still to come */
};
/* The boot: the nucleus, Hera, her system, POST. 1, Hera asleep at her
* wires waiting for a line; or 0, the failure printed. */
int v4_mesh_boot(v4_mesh *ms);
/* Text for node `node`, from the console, and the fabric stepped until that node says how the text
* ended: what any node prints goes to `out`; returns how it ended (V4_TEXT_*), or
* V4_BOOT_LINE_STOPPED / _TOO_LONG / _REFUSED / _NO_INPUT (boot.h). Other nodes may run on after it
* returns (v4_mesh_step). V4_BOOT_LINE_WAITING: Hera is asleep awaiting an answer that has not come
* -- nothing else can run, or other nodes have run a long while and not given it; the next text from
* the console breaks the wait (MESH.md 7b.6), and if the answer comes first, `dones` says so. */
int v4_mesh_tell(v4_mesh *ms, v4_cell node, const char *text, unsigned len);
/* One step of the fabric, as the host's idle: every awake node executes an instruction word, and what
* comes back to the console is printed (or counted, for how a text ended: `dones`). Returns how many
* instructions were retired. The host calls it while it waits, whenever v4_mesh_busy says a node can
* run: every node steps together, between lines as during them. */
unsigned v4_mesh_step(v4_mesh *ms);
int v4_mesh_busy(const v4_mesh *ms);
/* A word's record on the node in `place`, by its xt: 0 if that is not a word's xt. */
const v4_mesh_account *v4_mesh_account_at(const v4_mesh *ms, unsigned place, v4_cell xt);
/* For each word on the node in `place` called since the last charge: `each(ctx, id, calls)`, and its
* count since is cleared. */
void v4_mesh_charge(v4_mesh *ms, unsigned place, void (*each)(void *ctx, v4_cell id, v4_uheat_t calls), void *ctx);
/* The node numbered `number`, or 0. */
v4_fabric_node *v4_mesh_node(const v4_mesh *ms, v4_cell number);
#endif