feat(v4.0.0): the nucleus is a capsule, sent to a node born empty
MESH.md step 2. A capsule of F18 code is the words a neighbour writes to a node's port: for each stretch of memory, "@p a! @p push", the address and count, "@p !+ unext" and the words; then a jump to the start. A node born empty executes that from its port, so it needs nothing in it beforehand. - capsule.h/.c: v4_capsule_write, any node's memory as such a capsule - mkimage writes the nucleus so, to capsules/v4/nucleus-64.f18, and the addresses a host needs as a C file; the memory image is no longer linked into either product - mkcapsule is unchanged: the nucleus capsule is a built file kept under capsules/, as BLOCK_MAP.md is, and is baked, hashed and signed with the rest - boot: the node is born empty (v4_image_born); the nucleus capsule is found, its hash and signature checked, and given to the node a word at a time as it reads its port; PARITY:V4_NUCLEUS carries its name and hash Verified: test_fabric.c (59 checks, both widths, and under ASan and UBSan): a memory with a programme and scattered words arrives word for word in an empty node and runs. The nucleus capsule rebuilds byte for byte. hosted-check passes on three ISAs; clean qemu with STARFORTH_V4=1 on amd64, aarch64 and riscv64 takes the nucleus in, passes POST (550 of 550) and answers lines typed at each prompt (logs/20261006-102421, -102706, -103048). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
9af442f793
commit
42610e844f
@@ -6,6 +6,7 @@
|
||||
* At the level of opcodes: no word of any vocabulary is defined here.
|
||||
*/
|
||||
#include "v4/asm.h"
|
||||
#include "v4/capsule.h"
|
||||
#include "v4/fabric.h"
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
@@ -69,6 +70,13 @@ static int stream_take(void *self, v4_cell value)
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* for v4_capsule_write: each word of the capsule, into the stream's own list */
|
||||
static void collect(void *self, v4_cell word)
|
||||
{
|
||||
stream *s = (stream *)self;
|
||||
((v4_cell *)s->words)[s->count++] = word;
|
||||
}
|
||||
|
||||
/* What a neighbour sends an empty node to put `count` words at `addr` and
|
||||
* start there (MESH.md section 5): for the F18, and for this node, code a
|
||||
* node executes straight from its port. */
|
||||
@@ -187,6 +195,42 @@ int main(void)
|
||||
CHECK(ND(b)->n.last_from == 0, "it was listening to any port, and knows which it heard from: %u", ND(b)->n.last_from);
|
||||
}
|
||||
|
||||
/* ---- a capsule of F18 code: any node's memory, sent to an empty node (capsule.h) ---- */
|
||||
{
|
||||
static v4_node src;
|
||||
static v4_cell sent[400];
|
||||
static stream s;
|
||||
static v4_device dev;
|
||||
unsigned k;
|
||||
|
||||
v4_node_reset(&src);
|
||||
v4_asm_begin(&as, &src, 40); /* a programme, not at the start of memory */
|
||||
LIT(123); LIT(OUT); O(BANG_A); O(STORE_A);
|
||||
wait_for_ever();
|
||||
CHECK(v4_asm_ok(&as), "a programme for the capsule");
|
||||
src.mem[3] = 5; /* and words here and there: the first of memory, */
|
||||
src.mem[200] = -1; src.mem[202] = 7; /* two with one zero between them, */
|
||||
src.mem[300] = 9; src.mem[310] = 11; /* two with many, */
|
||||
src.mem[PB - 1] = 13; /* and the last before the ports */
|
||||
|
||||
memset(&s, 0, sizeof s);
|
||||
s.words = sent;
|
||||
dev.give = stream_give; dev.take = stream_take; dev.self = &s;
|
||||
s.count = 0;
|
||||
s.count = v4_capsule_write(&src, 40, collect, &s);
|
||||
CHECK(s.count > 0 && s.count < 400, "the capsule is %u words for a memory of %u", s.count, (unsigned)V4_NODE_WORDS);
|
||||
s.at = 0;
|
||||
|
||||
v4_fabric_init(&f, places, 4);
|
||||
b = (unsigned)v4_fabric_add(&f, &pool[0], PB);
|
||||
CHECK(v4_fabric_wire_device(&f, b, 5, &dev), "it is sent to a node newly born");
|
||||
steps = settle(5000);
|
||||
CHECK(s.at == s.count, "which takes all of it: %u of %u", s.at, s.count);
|
||||
for (k = 0; k < V4_NODE_WORDS && ND(b)->n.mem[k] == (k == (unsigned)OUT ? 123 : src.mem[k]); k++) { }
|
||||
CHECK(k == V4_NODE_WORDS, "its memory is then the same, word for word (first difference at %u)", k);
|
||||
CHECK(ND(b)->n.mem[OUT] == 123 && ND(b)->n.reading, "and it was started where the capsule says, and ran");
|
||||
}
|
||||
|
||||
/* ---- a word is passed on by a node in between ---- */
|
||||
v4_fabric_init(&f, places, 4);
|
||||
a = loaded(0);
|
||||
|
||||
Reference in New Issue
Block a user