Files
LithosAnanake/v4/include/v4/image.h
T
rajamesandClaude Opus 5.5 42610e844f feat(v4.0.0): the nucleus is a capsule, sent to a node born empty
MESH.md step 2.  A capsule of F18 code is the words a neighbour writes to a
node's port: for each stretch of memory, "@p a! @p push", the address and
count, "@p !+ unext" and the words; then a jump to the start.  A node born
empty executes that from its port, so it needs nothing in it beforehand.

- capsule.h/.c: v4_capsule_write, any node's memory as such a capsule
- mkimage writes the nucleus so, to capsules/v4/nucleus-64.f18, and the
  addresses a host needs as a C file; the memory image is no longer linked
  into either product
- mkcapsule is unchanged: the nucleus capsule is a built file kept under
  capsules/, as BLOCK_MAP.md is, and is baked, hashed and signed with the
  rest
- boot: the node is born empty (v4_image_born); the nucleus capsule is
  found, its hash and signature checked, and given to the node a word at a
  time as it reads its port; PARITY:V4_NUCLEUS carries its name and hash

Verified: test_fabric.c (59 checks, both widths, and under ASan and UBSan):
a memory with a programme and scattered words arrives word for word in an
empty node and runs.  The nucleus capsule rebuilds byte for byte.
hosted-check passes on three ISAs; clean qemu with STARFORTH_V4=1 on amd64,
aarch64 and riscv64 takes the nucleus in, passes POST (550 of 550) and
answers lines typed at each prompt (logs/20261006-102421, -102706,
-103048).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 10:33:15 -04:00

104 lines
4.9 KiB
C

/* image.h -- the StarForth nucleus, as its host knows it: where things are
* in a node that has taken it in, and how a line is handed to that node.
*
* The nucleus is text (capsule/ *.v4). tools/mkimage.c assembles it on the
* build machine and writes two things:
*
* - the nucleus as a capsule of F18 code (capsule.h), which is put into
* an empty node through its port. It is a capsule like any other: in
* the capsule directory, with a name, a hash and a signature
* (capsules/v4/nucleus-<width>.f18). docs/v4.0.0/MESH.md section 5.
* - this description of it, a C file: the addresses a host needs.
*
* A description is for one cell width, one node size and one pair of stack
* sizes; v4_image_born refuses one the engine was not built for.
*/
#ifndef V4_IMAGE_H
#define V4_IMAGE_H
#include "v4/exec.h"
typedef struct {
/* what the image was built for */
unsigned cell_bits, node_words, data_ring, ret_ring;
/* The node is handed a line (docs/v4.0.0/ENGINE.md 3.1). Its host puts
* text in the input buffer and starts it at `line`; it stops at `idle`,
* with how the line ended in the cell `line_status`. At switch-on it
* is at `idle`. */
v4_cell line; /* (LINE) */
v4_cell idle; /* (IDLE) */
v4_cell line_status; /* word address of the variable (LINE-STATUS) */
v4_cell tib; /* byte address of the input buffer */
unsigned tib_bytes; /* its size: a line may be one less */
v4_cell span; /* word address of the variable SPAN */
v4_cell fault_table; /* (FAULTS): where a fault goes */
v4_cell port; /* word address of the node's port (node.h) */
/* KEY's code: a node whose P is in key_start .. key_end - 1 with no
* character pending is waiting for one */
v4_cell key_start, key_end;
/* the memory-mapped registers (DECOMPOSITION.md section 7; D-4 leaves
* the map to the loader, and this is the map the image was built with) */
v4_cell console_tx, console_rx, console_status;
v4_cell dstack_reg, rstack_reg;
v4_cell node_error;
v4_cell storage_reg;
/* the dictionary's two variables: DP holds HERE, a byte address, and
* LATEST the newest word of FORTH. What lies below HERE, and LATEST,
* is what the dictionary hash covers (v4/include/v4/boot.h). */
v4_cell dp, latest;
/* What COLD returns the system to and FORGET will not go below: two
* cells, DP and LATEST as they were when the system was complete, and
* the variable FENCE. The image has them as the nucleus alone; a system
* that loads capsules when it boots sets them again when it has
* (v4_image_seal). */
v4_cell boot_cells, fence;
} v4_image;
/* The description of the nucleus built from v4/capsule (the generated file
* defines it). */
extern const v4_image v4_capsule_image;
/* The system is complete: what is in the dictionary now is what COLD comes
* back to, and FORGET will not go below it. */
void v4_image_seal(v4_node *n, const v4_image *im);
/* How a line ended. */
#define V4_LINE_QUIT 0 /* QUIT: nothing is to be said */
#define V4_LINE_COMPLETED 1 /* the host says " ok" */
#define V4_LINE_ERROR 2 /* the message is printed; the host says " ERROR" */
/* A node newly born (node.h), with the registers the nucleus expects of the
* node it runs on -- and `disk`, `blocks` blocks of 1024 bytes, as its block
* storage, or none if `disk` is 0. Its memory is empty and it is blocked
* reading its ports: the nucleus is yet to be sent to it. Returns 1, or 0
* if the description is not for this build of the engine (nothing is then
* done). */
int v4_image_born(v4_node *n, v4_exec_state *es, v4_heat *h, const v4_image *im,
unsigned char *disk, unsigned blocks);
/* Hand the node `len` characters of text to interpret. Returns 1, or 0 if
* the text is longer than the node's input buffer holds (nothing is then
* done). After it the host runs the node -- v4_exec_step_word again and
* again, taking what the node prints from n->console and setting
* n->console_len back to 0 -- until v4_line_done; if v4_image_waiting comes
* first, the line is reading the keyboard, and the host gives it characters
* with v4_node_console_feed. */
int v4_line_begin(v4_node *n, const v4_image *im, const char *text, unsigned len);
/* 1 when the node has finished the line it was handed and is idle again. */
int v4_line_done(const v4_node *n, const v4_image *im);
/* How the line just finished ended: V4_LINE_QUIT, _COMPLETED or _ERROR. */
int v4_line_status(const v4_node *n, const v4_image *im);
/* 1 if the node is waiting for a character: it is inside KEY and none is
* pending. */
int v4_image_waiting(const v4_node *n, const v4_image *im);
#endif /* V4_IMAGE_H */