feat(v4.0.0): a node looks before it writes; two neighbours no longer stop each other

MESH.md step 4, the fault found there, as ruled (section 7a): a node
writes only to a neighbour that is reading, keeps what it takes in
meanwhile, and loses and counts what it has no room for.

Engine: two more addresses after a node's ports -- which ports have a
neighbour waiting to write to it, which to read from it. Nucleus: (GATE)
before every message; the messages waiting, a ring of 400 cells, dealt
with when the node is idle. Of two neighbours the lower number may wait
to write (ruled after it was built); NEIGHBOUR tells a node who is on
each port.

test_host_mesh.c, 44 checks: the case that stopped the nodes passes; six
messages from each node to each at once all arrive; 800 at once, the
nodes come to rest and every message arrived or was counted (287 arrived,
714 of all kinds let go). test_fabric.c: the two looks. Both widths,
ASan+UBSan.

POST: twelve cases handed HERE, a cell address on v4, to words that take
a byte address, and so wrote into or read from the nucleus's code at cell
HERE/4. Ruled: left out, marked OPEN, until HERE and the byte words are
made to agree as its own step. POST is 538 cases.

hosted-check on three ISAs, 538/538. Bare metal: logs/20261006-134817
(amd64), -135044 (aarch64), -135440 (riscv64).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
rajames
2026-10-06 13:56:57 -04:00
co-authored by Claude Opus 5.5
parent 630d03fa4e
commit f9c034cadd
21 changed files with 1015 additions and 308 deletions
+14
View File
@@ -109,6 +109,8 @@ typedef struct {
v4_cell given_value;
unsigned given_port;
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 */
/* DSTACK-DEPTH and RSTACK-DEPTH (D-16). See v4_node_stack_regs_attach. */
v4_cell dstack_reg; /* its word address, or -1 */
@@ -181,6 +183,13 @@ void v4_node_console_attach(v4_node *n, v4_cell addr);
* base + V4_PORTS "any port": a read here takes from whichever port
* has a neighbour writing
* base + V4_PORTS + 1 which port the last read from "any" came from
* base + V4_PORTS + 2 which ports have a neighbour waiting to write to this
* node: bit k for port k
* base + V4_PORTS + 3 which ports have a neighbour waiting to read from it
* The last two are how a node looks before it writes (MESH.md 7a), as the
* F18's io register lets it. They are what whoever connects the ports last
* said, v4_node_port_status; fetching them waits for nothing and changes
* nothing.
* (read only)
* None of them is memory while the ports are attached.
*
@@ -213,6 +222,11 @@ void v4_node_port_served(v4_node *n);
* port or "any", is unblocked and will fetch it. */
void v4_node_port_give(v4_node *n, unsigned port, v4_cell value);
/* What is on the other end of the node's ports now: bit k of `writers` if
* the neighbour on port k is blocked writing to this node, bit k of
* `readers` if it is blocked reading from it and would take a word. */
void v4_node_port_status(v4_node *n, unsigned writers, unsigned readers);
/* Which port `addr` is: 0 .. V4_PORTS - 1, V4_PORT_ANY, V4_PORTS + 1 for the
* "which port" address, or -1 if it is none of them. */
int v4_node_port_index(const v4_node *n, v4_cell addr);