test_host_mesh.c, 220 checks: three exchanges on the row of three -- text from the console for node 12 with what it prints and how it ended; node 11 SENDing node 12 text and waiting for its answer; a message node 12 has no way for and its NACK to node 10 -- are each played once for every engine step they take with node 11 removed at that step, and again with node 12: 17,642 removals at 64 bits. Every node left comes to rest asleep, blocked at no port and in no operation, and answers. What is typed is a word defined beforehand, so that the steps are the exchange's and not the dictionary being searched. Removed from the engine, nothing using them: v4_fabric_interrupt_error, a device's pending hook, v4_node_words_since_look, V4_ERROR_INTERRUPTED. MESH.md: 4.1's table has the addresses after the ports; 7a and 7b say what of them still holds; 7b.7's limit is closed; step 6e is written up. v4/README.md likewise. make -C v4 test and sanitize at both widths, hosted-check, lint. Three bare-metal boots with the typed session and a loop printing 400 numbers: logs/20261013-165124 (amd64), -165428 (aarch64), -165818 (riscv64). POST 538 of 538, word_count=317, dict_hash=0x0951d7e02e251554 on all six, and the three sessions are the same character for character. The boots were built with the working tree's uncommitted change to kernel/Makefile that adds the ISA to the kernel's version line; nothing else differs from this commit. The plan's final review is not done yet. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
94 lines
4.0 KiB
C
94 lines
4.0 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 node that has taken the nucleus in is sent text as messages and sends
|
|
* back what it prints (v4/include/v4/message.h); nothing here hands it a
|
|
* line.
|
|
*
|
|
* 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;
|
|
|
|
/* Where the nucleus waits for a message (v4/capsule/quit.v4, (IDLE)):
|
|
* a node that has taken the nucleus in begins there, and with nothing
|
|
* to do it is asleep at a wire inside it (operation 8, MESH.md 7d.3). */
|
|
v4_cell idle;
|
|
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;
|
|
|
|
/* 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;
|
|
|
|
/* the block window: the word address of the slots the kernel copies
|
|
* blocks into (v4/blocks.h) */
|
|
v4_cell block_window;
|
|
} v4_image;
|
|
|
|
/* The nucleus's error for a node blocked at a port with no one on it
|
|
* (v4/capsule/core.v4's list; node.h, v4_node_port_gone): "No one on that
|
|
* port". */
|
|
#define V4_ERROR_NO_ONE 18
|
|
|
|
/* 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);
|
|
|
|
/* The dictionary hash of a node started from `im`: FNV-1a over its memory
|
|
* below HERE, a cell at a time, low byte first, and then LATEST. It does
|
|
* not depend on the machine: every build of one commit, with one cell
|
|
* width, gives the same hash for the same dictionary. */
|
|
uint64_t v4_image_dict_hash(const v4_node *n, const v4_image *im);
|
|
|
|
/* A node newly born (node.h), with the registers the nucleus expects of the
|
|
* node it runs on. 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);
|
|
|
|
/* 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 */
|