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:
co-authored by
Claude Opus 5.5
parent
ab96a9f2be
commit
06da5700bc
+2
-62
@@ -51,10 +51,6 @@ static unsigned loaded(unsigned k)
|
||||
/* the programme ends by waiting at a port nothing is wired to */
|
||||
static void wait_for_ever(void) { LIT(PB + 7); O(BANG_B); O(FETCH_B); (void)v4_asm_label(&as); } /* and the last word is written out */
|
||||
|
||||
/* a device that says whether it has something pending */
|
||||
static int *dev_has;
|
||||
static int device_has(void *self) { (void)self; return *dev_has; }
|
||||
|
||||
/* Let time pass until nothing more can happen, or `max` steps. */
|
||||
static unsigned settle(unsigned max)
|
||||
{
|
||||
@@ -435,62 +431,6 @@ int main(void)
|
||||
CHECK(ND(a)->n.asking && ND(a)->n.request == 5 && ND(c)->n.reading && ND(c)->n.mem[OUT] == 0, "looking takes nothing and gives nothing: both wait as they did");
|
||||
CHECK(!ND(b)->n.stopped && ND(b)->n.reading, "and the one that looked did not wait to look");
|
||||
|
||||
/* ---- a node blocked on the first word of a message, while a device of its own has something for it ---- */
|
||||
{
|
||||
static int has; /* what the device says it has pending */
|
||||
static stream none;
|
||||
static v4_device dev;
|
||||
v4_fabric_init(&f, places, 4);
|
||||
for (i = 0; i < 3; i++) v4_node_reset(&pool[i].n);
|
||||
a = loaded(0); /* looks about, then writes two words to its port 0 */
|
||||
LIT(PB + (v4_cell)V4_PORTS + 3); O(BANG_B); O(FETCH_B); O(DROP);
|
||||
LIT(PB + 0); O(BANG_B); LIT(1); O(STORE_B); LIT(2); O(STORE_B); wait_for_ever();
|
||||
b = loaded(1); /* never reads */
|
||||
LIT(OUT); O(BANG_A);
|
||||
{
|
||||
v4_cell again = v4_asm_label(&as);
|
||||
O(FETCH_A); LIT(1); O(ADD); O(STORE_A);
|
||||
v4_asm_branch(&as, V4_OP_JUMP, again);
|
||||
}
|
||||
CHECK(v4_asm_ok(&as) && v4_fabric_wire(&f, a, 0, b, 3), "a writer that looks first, wired to a node that never reads");
|
||||
dev.take = stream_take; dev.give = 0; dev.self = &none; dev.pending = device_has; has = 1; dev_has = &has;
|
||||
CHECK(v4_fabric_wire_device(&f, a, 5, &dev), "and to a device, which has something for it");
|
||||
for (i = 0; i < 40; i++) (void)v4_fabric_step(&f);
|
||||
CHECK(ND(a)->n.asking && ND(a)->n.request == 1 && v4_node_words_since_look(&ND(a)->n) == 0, "the writer is blocked on its first word, and waits: the fabric has no error for it");
|
||||
v4_fabric_interrupt_error(&f, 21);
|
||||
for (i = 0; i < 40; i++) (void)v4_fabric_step(&f);
|
||||
CHECK(ND(a)->n.asking && ND(a)->n.faults == 0, "nor is a bare node let go when it has: it cannot take an error");
|
||||
v4_node_error_attach(&ND(a)->n, OUT + 20);
|
||||
v4_node_fault_attach(&ND(a)->n, 900);
|
||||
has = 0;
|
||||
for (i = 0; i < 40; i++) (void)v4_fabric_step(&f);
|
||||
CHECK(ND(a)->n.asking && ND(a)->n.faults == 0, "a node that can take one waits all the same while the device has nothing for it");
|
||||
has = 1;
|
||||
(void)v4_fabric_step(&f);
|
||||
CHECK(!ND(a)->n.asking && ND(a)->n.fault_kind == V4_FAULT_RAISED && ND(a)->n.fault_addr == 21 && ND(a)->n.mem[OUT + 20] == 21,
|
||||
"when it has, the writer is let go and the error raised on it");
|
||||
|
||||
/* once the first word has gone, it is not let go: the message must be finished */
|
||||
v4_fabric_init(&f, places, 4);
|
||||
for (i = 0; i < 3; i++) v4_node_reset(&pool[i].n);
|
||||
a = loaded(0);
|
||||
LIT(PB + (v4_cell)V4_PORTS + 3); O(BANG_B); O(FETCH_B); O(DROP);
|
||||
LIT(PB + 0); O(BANG_B); LIT(1); O(STORE_B); LIT(2); O(STORE_B); wait_for_ever();
|
||||
b = loaded(1); /* reads one word, and no more */
|
||||
LIT(PB + 3); O(BANG_B); O(FETCH_B); LIT(OUT); O(BANG_A);
|
||||
{
|
||||
v4_cell again = v4_asm_label(&as);
|
||||
O(FETCH_A); LIT(1); O(ADD); O(STORE_A);
|
||||
v4_asm_branch(&as, V4_OP_JUMP, again);
|
||||
}
|
||||
CHECK(v4_asm_ok(&as) && v4_fabric_wire(&f, a, 0, b, 3) && v4_fabric_wire_device(&f, a, 5, &dev), "the same, to a node that reads one word and no more");
|
||||
v4_node_error_attach(&ND(a)->n, OUT + 20);
|
||||
v4_node_fault_attach(&ND(a)->n, 900);
|
||||
v4_fabric_interrupt_error(&f, 21);
|
||||
for (i = 0; i < 60; i++) (void)v4_fabric_step(&f);
|
||||
CHECK(ND(a)->n.asking && ND(a)->n.request == 2 && ND(a)->n.faults == 0, "blocked on its second word with the device still pending, the writer waits");
|
||||
}
|
||||
|
||||
/* ---- messages on the wire (MESH.md 7d): the engine only ---- */
|
||||
{
|
||||
static v4_wire_queue qpool[8];
|
||||
@@ -800,7 +740,7 @@ int main(void)
|
||||
CHECK(!ND(c)->n.doing && !ND(a)->n.doing && ND(a)->n.how == 1, "room that comes in the step the node goes to sleep wakes it: no wake-up is lost");
|
||||
/* a device's take is a take */
|
||||
{
|
||||
static const v4_device dev = { 0, 0, 0, 0 };
|
||||
static const v4_device dev = { 0, 0, 0 };
|
||||
v4_cell hh[7], tt[V4_WIRE_CELLS / 4];
|
||||
CHECK(v4_fabric_wire_device(&f, a, 4, &dev), "a device on a third wire");
|
||||
fill(f.place[a].wire[4].tx, 0);
|
||||
@@ -855,7 +795,7 @@ int main(void)
|
||||
static stream ks;
|
||||
static v4_device kern;
|
||||
unsigned free_before = f.queue_free;
|
||||
ks.took_n = 0; kern.take = stream_take; kern.give = 0; kern.self = &ks; kern.pending = 0;
|
||||
ks.took_n = 0; kern.take = stream_take; kern.give = 0; kern.self = &ks;
|
||||
CHECK(v4_fabric_wire_kernel(&f, a, 5, &kern) && f.queue_free == free_before && !f.place[a].wire[5].rx && !f.place[a].wire[5].tx, "a kernel is wired to a port, and is given no queues");
|
||||
put_msg(&ND(a)->n, 100, 110, 4, 7);
|
||||
CHECK(ask(a, 5, 100, 110, 5) == 2 && ask(a, 5, 8, 0, 10) == 2 && ask(a, 5, 8, 0, 9) == 2 && ask(a, 5, 200, 220, 1) == 2 && ask(a, 5, 0, 0, 6) == 2 && !ND(a)->n.doing,
|
||||
|
||||
Reference in New Issue
Block a user