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:
co-authored by
Claude Opus 5.5
parent
630d03fa4e
commit
f9c034cadd
@@ -155,10 +155,34 @@ static unsigned hand_over_read(v4_fabric *f, unsigned a)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* What node `a` can see of its neighbours before it executes: who is
|
||||
* blocked writing to it, and who would take a word from it. A device is
|
||||
* always ready to be written to; what it has to give, the node finds when
|
||||
* it reads. */
|
||||
static void look_about(v4_fabric *f, unsigned a)
|
||||
{
|
||||
unsigned k, writers = 0, readers = 0;
|
||||
|
||||
for (k = 0; k < V4_PORTS; k++) {
|
||||
const v4_wire *w = &f->place[a].wire[k];
|
||||
if (w->kind == V4_WIRE_DEVICE) {
|
||||
if (w->device->take) readers |= 1u << k;
|
||||
} else if (w->kind == V4_WIRE_NODE && awake(f, w->node)) {
|
||||
const v4_node *o = &f->place[w->node].node->n;
|
||||
if (o->asking && o->ask_port == w->port) writers |= 1u << k;
|
||||
if (o->reading && !o->given && (o->read_port == w->port || o->read_port == V4_PORT_ANY)) readers |= 1u << k;
|
||||
}
|
||||
}
|
||||
v4_node_port_status(&f->place[a].node->n, writers, readers);
|
||||
}
|
||||
|
||||
unsigned v4_fabric_step(v4_fabric *f)
|
||||
{
|
||||
unsigned i, done = 0;
|
||||
|
||||
for (i = 0; i < f->capacity; i++)
|
||||
if (awake(f, i)) look_about(f, i);
|
||||
|
||||
for (i = 0; i < f->capacity; i++)
|
||||
if (awake(f, i)) done += v4_exec_step_word(&f->place[i].node->n, &f->place[i].node->es, &f->place[i].node->h);
|
||||
|
||||
|
||||
+12
-2
@@ -159,6 +159,8 @@ v4_cell v4_node_fetch(v4_node *n, v4_cell addr)
|
||||
{
|
||||
int port = v4_node_port_index(n, addr);
|
||||
if (port == (int)V4_PORTS + 1) return (v4_cell)n->last_from;
|
||||
if (port == (int)V4_PORTS + 2) return (v4_cell)n->writers;
|
||||
if (port == (int)V4_PORTS + 3) return (v4_cell)n->readers;
|
||||
if (port >= 0) {
|
||||
/* the word its neighbour wrote; v4_node_read_ready has said it is there */
|
||||
if (!n->given) return 0;
|
||||
@@ -214,18 +216,26 @@ void v4_node_port_attach(v4_node *n, v4_cell base)
|
||||
n->given_value = 0;
|
||||
n->given_port = 0;
|
||||
n->last_from = 0;
|
||||
n->writers = 0;
|
||||
n->readers = 0;
|
||||
}
|
||||
|
||||
void v4_node_port_status(v4_node *n, unsigned writers, unsigned readers)
|
||||
{
|
||||
n->writers = writers;
|
||||
n->readers = readers;
|
||||
}
|
||||
|
||||
int v4_node_port_index(const v4_node *n, v4_cell addr)
|
||||
{
|
||||
if (n->port < 0 || addr < n->port || addr > n->port + (v4_cell)V4_PORTS + 1) return -1;
|
||||
if (n->port < 0 || addr < n->port || addr > n->port + (v4_cell)V4_PORTS + 3) return -1;
|
||||
return (int)(addr - n->port);
|
||||
}
|
||||
|
||||
int v4_node_read_ready(v4_node *n, v4_cell addr)
|
||||
{
|
||||
int port = v4_node_port_index(n, addr);
|
||||
if (port < 0 || port == (int)V4_PORTS + 1) return 1;
|
||||
if (port < 0 || port > (int)V4_PORT_ANY) return 1;
|
||||
if (n->given && (port == (int)V4_PORT_ANY || (unsigned)port == n->given_port)) return 1;
|
||||
n->reading = 1;
|
||||
n->read_port = (unsigned)port;
|
||||
|
||||
Reference in New Issue
Block a user