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
@@ -38,11 +38,11 @@ static v4_wire_queue queues[QUEUES];
|
||||
|
||||
/* ---- the console: a device on a port ---- */
|
||||
#define CONSOLE_ID 1
|
||||
static const v4_device console = { 0, 0, 0, 0 }; /* it takes and gives no words: only whole messages */
|
||||
static const v4_device console = { 0, 0, 0 }; /* it takes and gives no words: only whole messages */
|
||||
/* a kernel on a node's port 0: it takes the words written to it, and no messages (MESH.md 7d.5) */
|
||||
static unsigned kernel_words;
|
||||
static int kernel_take(void *self, v4_cell value) { (void)self; (void)value; kernel_words++; return 1; }
|
||||
static const v4_device kernel_dev = { kernel_take, 0, 0, 0 };
|
||||
static const v4_device kernel_dev = { kernel_take, 0, 0 };
|
||||
static unsigned hera, mid, far; /* where the three nodes are: 10, 11, 12 */
|
||||
static char printed[32768]; /* what has come back since the console last sent */
|
||||
static unsigned printed_len;
|
||||
@@ -246,6 +246,56 @@ static void watch_far_waits(void)
|
||||
if (waits_for_room(far)) { saw_room_wait++; if (going_from(far, 3) && going_from(far, 3)->used == V4_WIRE_CELLS - 8u) saw_full++; }
|
||||
}
|
||||
|
||||
/* ---- a node removed at every step of an exchange (MESH.md 7d.7, acceptance 6) ---- */
|
||||
/* 1 if the node is doing nothing and waits for nothing but a message: asleep, and blocked at no port. */
|
||||
static int at_rest(unsigned id)
|
||||
{
|
||||
const v4_fabric_node *x = v4_fabric_node_at(&f, id);
|
||||
return x && asleep(id) && !x->n.asking && !x->n.reading && !x->n.stopped;
|
||||
}
|
||||
/* 1 if what came back ends with the answer to `1 2 + .`, asked by the word Q that each node was given; a wait
|
||||
* the removal left is first ended by the line, and says so. */
|
||||
#define ASK ": Q 1 2 + . ;"
|
||||
static int answers(v4_cell node, unsigned id)
|
||||
{
|
||||
const char *got = tell(node, "Q");
|
||||
size_t len = strlen(got);
|
||||
return len >= 2 && strcmp(got + len - 2, "3 ") == 0 && ended >= 1 && ended_from == node && at_rest(id);
|
||||
}
|
||||
/* The exchange that `text`, sent to `node`, begins is played from the mesh as kept, once for every step it
|
||||
* takes, with the node at place `gone` removed at that step. Every node left must come to rest, blocked in
|
||||
* nothing, and answer. With the middle node gone the far one is wired to the first, as whoever removed it
|
||||
* would, so that it can be asked. How many steps the exchange takes; how many removals went wrong, and
|
||||
* the first of them. */
|
||||
static v4_fabric_node now_pool[3];
|
||||
static v4_place now_places[3];
|
||||
static v4_wire_queue now_queues[QUEUES];
|
||||
static v4_fabric now_f;
|
||||
static unsigned removed_at_every_step(v4_cell node, const char *text, unsigned gone, unsigned *wrong, unsigned *first_wrong)
|
||||
{
|
||||
unsigned long before;
|
||||
unsigned whole, s;
|
||||
*wrong = 0; *first_wrong = 0;
|
||||
put_back();
|
||||
before = steps_run;
|
||||
if (!put_text(node, text) || !run()) { *wrong = 1; return 0; }
|
||||
whole = (unsigned)(steps_run - before);
|
||||
put_back();
|
||||
if (!put_text(node, text)) { *wrong = 1; return 0; }
|
||||
for (s = 0; s <= whole; s++) {
|
||||
int ok;
|
||||
memcpy(now_pool, pool, sizeof pool); memcpy(now_places, places, sizeof places); memcpy(now_queues, queues, sizeof queues); now_f = f; /* the exchange, s steps on */
|
||||
ok = v4_fabric_remove(&f, gone) == &pool[gone] && run();
|
||||
ok = ok && at_rest(hera) && (gone == mid ? at_rest(far) : at_rest(mid));
|
||||
if (ok && gone == mid) ok = v4_fabric_wire(&f, hera, 2, far, 2) && answers(12, far) && answers(10, hera);
|
||||
else if (ok) ok = answers(11, mid) && answers(10, hera);
|
||||
if (!ok) { if (!*wrong) *first_wrong = s; (*wrong)++; }
|
||||
memcpy(pool, now_pool, sizeof pool); memcpy(places, now_places, sizeof places); memcpy(queues, now_queues, sizeof queues); f = now_f;
|
||||
(void)v4_fabric_step(&f); (void)console_takes();
|
||||
}
|
||||
return whole;
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
unsigned i;
|
||||
@@ -944,6 +994,36 @@ int main(void)
|
||||
printf(" between texts the nucleus used at most %u cells of the data stack and %u entries of the return stack\n", between_data, between_ret);
|
||||
CHECK(between_data <= 4 && between_ret <= 7, "between texts: four cells of the data stack, and seven return entries");
|
||||
|
||||
|
||||
/* ---- A NODE REMOVED AT EVERY STEP (MESH.md 7d.7, acceptance 6) ----
|
||||
* Three exchanges, each played once whole and then once for every step it takes, with node 11 removed
|
||||
* at that step, and again with node 12: the nodes left come to rest, blocked in nothing, and answer.
|
||||
* What is typed is a word defined beforehand, and so is what a node left is asked (Q, which is
|
||||
* `1 2 + .`): a line of several words is mostly the dictionary searched, thousands of steps in which the
|
||||
* mesh does nothing, and every one of them would be a removal played to the end. */
|
||||
{
|
||||
static const struct { const char *what, *set10, *set11, *set12; v4_cell node; const char *text; } ex[3] = {
|
||||
{ "text from the console for node 12, what it prints and how it ended", "1 DROP", "1 DROP", ": A 7 8 * . ;", 12, "A" },
|
||||
{ "node 11 SENDs node 12 text and waits for its answer", "1 DROP", ": T S\" Q\" 12 SEND 12 AWAIT . ;", "1 DROP", 11, "T" },
|
||||
{ "a message node 12 has no way for, and its NACK to node 10", "55 2 ROUTE : N S\" 1 DROP\" 55 SEND ;", "55 3 ROUTE", "NO-ROUTES 1 2 ROUTE 10 2 ROUTE 11 2 ROUTE", 10, "N" }
|
||||
};
|
||||
unsigned e, g, whole, wrong, first;
|
||||
step_cap = 2000000;
|
||||
for (e = 0; e < 3; e++) {
|
||||
CHECK(row() && told(10, ex[e].set10) && told(11, ex[e].set11) && told(12, ex[e].set12) && told(10, ASK) && told(11, ASK) && told(12, ASK), "a row made afresh for: %s", ex[e].what);
|
||||
step_cap = 2000000;
|
||||
keep();
|
||||
for (g = 1; g <= 2; g++) {
|
||||
whole = removed_at_every_step(ex[e].node, ex[e].text, g == 1 ? mid : far, &wrong, &first);
|
||||
CHECK(whole > 0 && wrong == 0, "%s, in %u steps: with node %u removed at each of them the rest come to rest and answer: %u did not, the first at step %u",
|
||||
ex[e].what, whole, 10u + g, wrong, first);
|
||||
}
|
||||
}
|
||||
put_back();
|
||||
CHECK(is_empty(tell(10, "N")) && pool[hera].n.mem[REFUSED] == 1 && pool[far].n.mem[LOST] == 1, "the last of them, whole: node 12 let the message go and node 10 was told it was refused");
|
||||
step_cap = 20000000;
|
||||
}
|
||||
|
||||
printf(" %d checks, %d failures\n", checks, failures);
|
||||
return failures != 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user