feat(v4.0.0): CONSOLE-RX and CONSOLE-STATUS on the single-node model

The console's receive side, standing in for the console node until the
mesh exists, as CONSOLE-TX does for output.  A data fetch (@, @+, @b)
from CONSOLE-STATUS gives -1 when a character is pending and 0 when
not; from CONSOLE-RX it gives the next character and takes it, or -1
with none pending.  The characters come from a queue the test feeds.

Instruction words and literals are still fetched with v4_node_load, so
code at a register's address is never taken for the register.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
rajames
2026-10-03 20:53:56 -04:00
co-authored by Claude Opus 5.5
parent 03d8d991ef
commit 2c16183788
5 changed files with 208 additions and 7 deletions
+40
View File
@@ -12,6 +12,7 @@ void v4_node_reset(v4_node *n)
v4_dstack_reset(&n->ds);
v4_rstack_reset(&n->rs);
v4_node_console_attach(n, -1);
v4_node_console_input_attach(n, -1, -1);
}
int v4_node_guards_intact(const v4_node *n)
@@ -44,6 +45,45 @@ void v4_node_store(v4_node *n, v4_cell addr, v4_cell value)
n->mem[(unsigned)addr] = value;
}
v4_cell v4_node_fetch(v4_node *n, v4_cell addr)
{
/* console_rx and console_status are -1 when no input is attached, which
* no valid address equals. */
if (addr == n->console_status)
return n->input_pos < n->input_len ? (v4_cell)-1 : (v4_cell)0;
if (addr == n->console_rx) {
v4_cell c;
if (n->input_pos >= n->input_len) return (v4_cell)-1;
c = (v4_cell)n->input[n->input_pos++];
if (n->input_pos == n->input_len) n->input_pos = n->input_len = 0;
return c;
}
return v4_node_load(n, addr);
}
void v4_node_console_input_attach(v4_node *n, v4_cell rx, v4_cell status)
{
n->console_rx = rx;
n->console_status = status;
n->input_len = 0;
n->input_pos = 0;
}
unsigned v4_node_console_feed(v4_node *n, const void *chars, unsigned len)
{
const unsigned char *c = (const unsigned char *)chars;
unsigned i, pending = n->input_len - n->input_pos, took = 0;
/* Slide what is pending to the front so the whole buffer is usable. */
if (n->input_pos > 0) {
for (i = 0; i < pending; i++) n->input[i] = n->input[n->input_pos + i];
n->input_pos = 0;
n->input_len = pending;
}
while (took < len && n->input_len < V4_CONSOLE_CAP) n->input[n->input_len++] = c[took++];
return took;
}
void v4_node_console_attach(v4_node *n, v4_cell addr)
{
n->console_tx = addr;