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:
co-authored by
Claude Opus 5.5
parent
03d8d991ef
commit
2c16183788
@@ -72,6 +72,14 @@ typedef struct {
|
||||
unsigned console_len; /* characters captured */
|
||||
unsigned console_dropped; /* characters that did not fit */
|
||||
unsigned char console[V4_CONSOLE_CAP];
|
||||
|
||||
/* CONSOLE-RX and CONSOLE-STATUS (section 7). See
|
||||
* v4_node_console_input_attach below. */
|
||||
v4_cell console_rx; /* its word address, or -1: no input */
|
||||
v4_cell console_status; /* its word address, or -1 */
|
||||
unsigned input_len; /* characters fed */
|
||||
unsigned input_pos; /* characters taken; input_len - input_pos are pending */
|
||||
unsigned char input[V4_CONSOLE_CAP];
|
||||
} v4_node;
|
||||
|
||||
/* Zero P, A and B, empty the stacks, and clear memory. Installs every
|
||||
@@ -143,4 +151,38 @@ void v4_node_store(v4_node *n, v4_cell addr, v4_cell value);
|
||||
* Passing -1 detaches. The address is the caller's choice. */
|
||||
void v4_node_console_attach(v4_node *n, v4_cell addr);
|
||||
|
||||
/* CONSOLE-RX and CONSOLE-STATUS, the console's receive side, on the
|
||||
* single-node model.
|
||||
*
|
||||
* KEY and ?TERMINAL are device services too (DECOMPOSITION.md 5.10), and for
|
||||
* the same reason as CONSOLE-TX the model stands in for the console with two
|
||||
* memory-mapped registers and a queue of characters the test feeds.
|
||||
*
|
||||
* After v4_node_console_input_attach(n, rx, status), a data fetch (the
|
||||
* opcodes @, @+ and @b, which go through v4_node_fetch) from word address
|
||||
* `status` gives -1 when a character is pending and 0 when none is;
|
||||
* `rx` gives the next pending character, 0 .. 255, and takes it off
|
||||
* the queue; with none pending it gives -1 and takes nothing.
|
||||
* Fetching the status changes nothing. Neither fetch reads or writes
|
||||
* n->mem, a store to either address is an ordinary memory store, and
|
||||
* v4_node_load -- which the executor uses to fetch instruction words and
|
||||
* literals, and the assembler to patch them -- always reads memory, so code
|
||||
* and literals are never mistaken for the registers.
|
||||
*
|
||||
* v4_node_console_feed appends characters to the queue and returns how many
|
||||
* it took; the queue holds V4_CONSOLE_CAP characters that have not been
|
||||
* read. A node has no input until it is attached: v4_node_reset detaches it
|
||||
* (both addresses -1) and empties the queue. Attaching empties it too.
|
||||
* Passing -1 for both detaches. The addresses are the caller's choice and
|
||||
* must differ from each other and from CONSOLE-TX.
|
||||
*
|
||||
* Nothing here blocks. A KEY that must wait polls CONSOLE-STATUS, so on
|
||||
* this model a wait is a loop that runs until the test feeds a character. */
|
||||
void v4_node_console_input_attach(v4_node *n, v4_cell rx, v4_cell status);
|
||||
unsigned v4_node_console_feed(v4_node *n, const void *chars, unsigned len);
|
||||
|
||||
/* A data fetch: what @, @+ and @b read at `addr`. The two receive registers
|
||||
* above when attached, memory otherwise. Same precondition as v4_node_load. */
|
||||
v4_cell v4_node_fetch(v4_node *n, v4_cell addr);
|
||||
|
||||
#endif /* V4_NODE_H */
|
||||
|
||||
Reference in New Issue
Block a user