feat(v4.0.0): step 6e -- a node removed at any step leaves the rest at rest; written up

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>
This commit is contained in:
rajames
2026-10-13 17:47:05 -04:00
co-authored by Claude Opus 5.5
parent ab96a9f2be
commit 06da5700bc
17 changed files with 893 additions and 142 deletions
-15
View File
@@ -27,7 +27,6 @@ typedef struct {
int (*take)(void *self, v4_cell value); /* the node wrote `value`: 1 if it is taken, 0 if not yet */
int (*give)(void *self, v4_cell *value); /* the node is reading: 1 with a word in *value, 0 if not yet */
void *self;
int (*pending)(void *self); /* 1 if it has a word to give that has not been asked for; may be 0: it never says */
} v4_device;
/* One end of a wire. */
@@ -61,7 +60,6 @@ typedef struct {
unsigned queue_count, queue_free; /* how many, and how many are not on a wire */
unsigned queue_first; /* the first that is not, and the index plus one; 0: none. Each links to the next by its `head`. */
v4_cell gone_error; /* see v4_fabric_gone_error; 0: none */
v4_cell interrupt_error; /* see v4_fabric_interrupt_error; 0: none */
} v4_fabric;
/* An empty fabric with room for `capacity` nodes, in `places`. */
@@ -99,19 +97,6 @@ int v4_fabric_device_take(v4_fabric *f, unsigned node, unsigned port, v4_cell *h
* is how a fabric begins, nothing is raised. */
void v4_fabric_gone_error(v4_fabric *f, v4_cell code);
/* A NODE BLOCKED WRITING TO A NODE THAT DOES NOT READ. Of two neighbours
* one may write to the other without looking (docs/v4.0.0/MESH.md 7a), and
* is then blocked until the other reads; if the other never does, it is
* blocked for ever, and if it is the node the console is on, nothing can be
* typed to it again. So: when a node that can take an error is blocked
* writing to another node, on the first word of a message (node.h,
* v4_node_words_since_look: nothing of the message has gone), and a device
* on one of its own ports says it has something pending for it, the error
* `code` is raised on the node: it gives up that message and goes on, to
* read what the device has. Only a device with a `pending` function can
* do this. With `code` 0, which is how a fabric begins, it never happens. */
void v4_fabric_interrupt_error(v4_fabric *f, v4_cell code);
/* More room: `places`, of `capacity` no less than before, takes over; every
* node keeps its number and its wiring. */
void v4_fabric_grow(v4_fabric *f, v4_place *places, unsigned capacity);
-5
View File
@@ -65,11 +65,6 @@ typedef struct {
* port". */
#define V4_ERROR_NO_ONE 18
/* The nucleus's error for a node let go of a message it was blocked on the
* first word of, because its console has a line for it (fabric.h,
* v4_fabric_interrupt_error): "Interrupted". */
#define V4_ERROR_INTERRUPTED 21
/* The description of the nucleus built from v4/capsule (the generated file
* defines it). */
extern const v4_image v4_capsule_image;
-8
View File
@@ -120,7 +120,6 @@ typedef struct {
unsigned last_from; /* the port the last read from "any" took its word from */
unsigned writers; /* bit k: the neighbour on port k is blocked writing to this node */
unsigned readers; /* bit k: the neighbour on port k is blocked reading from this node */
unsigned since_look; /* words taken from this node since it last fetched either of those */
/* Whole messages on the wires (MESH.md 7d.3). See v4_node_port_attach. */
unsigned wire; /* the port that A, B and Do are about; V4_PORTS if what was stored is not a port */
@@ -262,13 +261,6 @@ int v4_node_doing(const v4_node *n);
void v4_node_done(v4_node *n, v4_cell how);
void v4_node_have(v4_node *n, unsigned mask);
/* How many words the node has had taken since it last looked at its
* neighbours (a fetch of either of the two status addresses). A node that
* looks before it begins a message (MESH.md 7a) and is blocked writing with
* this at 0 is blocked on the first word of the message: nothing of it has
* gone. */
unsigned v4_node_words_since_look(const v4_node *n);
/* THERE IS NO ONE ON THE PORT the node is blocked at -- writing to it, or
* reading from that one port -- and there will not be. A node that can
* take an error (it has an error register and a fault table: node.h,