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
+37
-27
@@ -65,7 +65,7 @@ macro R-CLEAR RSTACK-DEPTH b! a !b endmacro
|
||||
: (FINISH) ( s -- )
|
||||
(LINE-STATUS) b! dup !b
|
||||
(FLUSH-OUT)
|
||||
(DONE-PORT) a! @ b! (MSG)+1 a! @ !b \ to whoever sent the text
|
||||
(DONE-PORT) a! @ (GATE) (MSG)+1 a! @ !b \ to whoever sent the text
|
||||
3 (HDR) 4 !b !b \ a message of type 3, four characters long: how it ended
|
||||
jump (IDLE)
|
||||
|
||||
@@ -78,29 +78,30 @@ macro R-CLEAR RSTACK-DEPTH b! a !b endmacro
|
||||
OK: drop 1 jump (FINISH)
|
||||
GO: drop 0 jump (FINISH)
|
||||
|
||||
\ ( -- ) WAITING. A node with nothing to do is blocked reading its ports
|
||||
\ (docs/v4.0.0/MESH.md 4.1): it executes nothing until a neighbour writes.
|
||||
\ What arrives is a message (core.v4). Its first word is taken from any
|
||||
\ port and the rest from the port that came on. Its text goes into TIB,
|
||||
\ which holds 1024 characters, the most a message carries; a longer one is
|
||||
\ read to its end, so that what follows it is not taken for a message, and
|
||||
\ is error 12. A message of type 1 for this node is text to interpret: it
|
||||
\ is done as a line was, and (FINISH) reports how it ended. A message for
|
||||
\ another node is passed on, (PASS-ON).
|
||||
\ ( -- ) WAITING. A node with nothing to do deals with the oldest of the
|
||||
\ messages waiting (core.v4). With none waiting it is blocked reading its
|
||||
\ ports (docs/v4.0.0/MESH.md 4.1): it executes nothing until a neighbour
|
||||
\ writes, and what arrives is taken in as any message is, its first word
|
||||
\ from any port and the rest from the port that came on. The message's
|
||||
\ text goes into TIB, which holds 1024 characters, the most a message
|
||||
\ carries; one that came with a length no message has is error 12. A
|
||||
\ message of type 1 for this node is text to interpret: it is done as a
|
||||
\ line was, and (FINISH) reports how it ended. A message for another node
|
||||
\ is passed on, (PASS-ON).
|
||||
: (IDLE)
|
||||
(PORT)+8 b! @b (MSG) a! !+ \ to, from any port
|
||||
(PORT)+9 b! @b (PORT) + dup b! \ B: the port it came on
|
||||
5 FOR @b !+ UNEXT \ from, type, heat and TTL, ACL tag, sequence, length
|
||||
(REPLY) a! !
|
||||
(MSG)+6 a! @ -if SIZED jump BAD \ a length below zero: no telling what follows
|
||||
SIZED: dup -1025 + -if LONG drop jump FITS
|
||||
LONG: drop 3 + 2/ 2/ -1 + FOR @b drop UNEXT 0 \ too long: read it and let it go
|
||||
BAD: drop 0 (MSG)+6 a! ! 0 SPAN a! ! NODE-ERROR b! 12 !b
|
||||
FITS:
|
||||
3 + 2/ 2/ if EMPTY
|
||||
-1 + TIB 2/ 2/ a! FOR @b !+ UNEXT
|
||||
jump READ
|
||||
EMPTY: drop
|
||||
L: (MQ#) a! @ if WAIT drop jump HAVE
|
||||
WAIT: drop (PORT)+8 b! @b (PORT)+9 b! @b (PORT) + dup b! \ ( to port ) B: the port it came on
|
||||
SWAP (TAKE) jump L
|
||||
HAVE:
|
||||
(MQ@) (MSG) a! ! (MQ@) (MSG)+1 a! ! (MQ@) (MSG)+2 a! ! (MQ@) (MSG)+3 a! !
|
||||
(MQ@) (MSG)+4 a! ! (MQ@) (MSG)+5 a! ! (MQ@) (MSG)+6 a! ! (MQ@) (REPLY) a! !
|
||||
(MSG)+6 a! @ -if SIZED
|
||||
drop 0 (MSG)+6 a! ! 0 SPAN a! ! NODE-ERROR b! 12 !b \ no telling what it was
|
||||
SIZED: drop
|
||||
TIB 2/ 2/ (MSG)+6 a! @ 3 + 2/ 2/ if EMPTY
|
||||
-1 + FOR (MQ@) over a! ! 1 + NEXT
|
||||
drop jump READ
|
||||
EMPTY: drop drop
|
||||
READ:
|
||||
0 (MSG)+6 a! @ TIB + C! \ a zero after the text
|
||||
(MSG)+6 a! @ SPAN a! !
|
||||
@@ -124,7 +125,7 @@ macro R-CLEAR RSTACK-DEPTH b! a !b endmacro
|
||||
\ known it is let go, and (LOST) counts it.
|
||||
: (PASS-ON)
|
||||
(MSG) a! @ (PORT-FOR) if NOWAY
|
||||
b! (MSG) a! 6 FOR @+ !b UNEXT \ its seven words
|
||||
(GATE) (MSG) a! 6 FOR @+ !b UNEXT \ its seven words
|
||||
(MSG)+6 a! @ 3 + 2/ 2/ if SENT
|
||||
-1 + TIB 2/ 2/ a! FOR @+ !b UNEXT \ and its text
|
||||
jump (IDLE)
|
||||
@@ -156,6 +157,16 @@ header ROUTE
|
||||
(ROUTE#) a! @ 1 + ! ;
|
||||
FULL: drop drop drop NODE-ERROR b! 12 !b ;
|
||||
|
||||
\ ( node port -- ) the node on the other end of the port, by its number;
|
||||
\ 0: none, or a device. Whoever wires the node tells it, and tells it again
|
||||
\ when the wiring changes. It is what lets one of two neighbours, and one
|
||||
\ only, wait to write to the other (core.v4, (GATE)).
|
||||
header NEIGHBOUR
|
||||
: NEIGHBOUR
|
||||
dup -if POS jump BAD
|
||||
POS: -PORTS + -if BAD drop (NEAR) + a! ! ;
|
||||
BAD: drop drop drop NODE-ERROR b! 12 !b ;
|
||||
|
||||
\ ( port -- ) the port, by its number, leads toward every node not told of
|
||||
header DEFAULT-ROUTE
|
||||
: DEFAULT-ROUTE (PORT) + (ROUTE-DEFAULT) a! ! ;
|
||||
@@ -167,12 +178,11 @@ header NO-ROUTES
|
||||
\ ( baddr u node -- ) send the node u characters of text to interpret. It
|
||||
\ is on its way when SEND returns; what it prints there goes to that node's
|
||||
\ console. With no way to the node it is error 12. The write waits for the
|
||||
\ neighbour to read: a neighbour that is itself waiting to write to this
|
||||
\ node will wait for ever, and so will this one.
|
||||
\ neighbour to read, and is not begun until it may be (core.v4, (GATE)).
|
||||
header SEND
|
||||
: SEND
|
||||
dup (PORT-FOR) if NOWAY
|
||||
b! !b \ to
|
||||
(GATE) !b \ to
|
||||
1 (HDR)
|
||||
dup !b \ length
|
||||
3 + 2/ 2/ if NONE -1 +
|
||||
|
||||
Reference in New Issue
Block a user