The host node starts in its ROM (entry 12), and the boot feeds it the system's source through the console: capsules/v4/sys/map-64.f18, the fourteen .f18 blobs and end.f18, each found, hash-checked and signature-checked as any capsule, then EOT. The ROM assembles the system and starts it at (IDLE); the host reads the image record (v4_image_from_node) for what only the assembled system knows. A ROM error is reported with its blob, line and meaning, then PARITY:FAIL. Deleted: v4/tools/mkimage.c, capsules/v4/nucleus-64.f18, v4/capsule/*.v4, v4/tools/v4tof18.py. The .f18 files are the source now. - text.c speaks the rest of the ROM's language (set, here, store, start; v4_text_value, v4_text_start), so the oracle reads the same source: test_host_rom_nucleus compares the ROM against text.c on the .f18 files, word for word, image record included. Host tests load the .f18 files. - mkmap image writes v4_map_image (the map's description of the system); hosted and the kernel link the ROM and the map instead of v4_image_64.c. - Hera (Captain Bob's ruling, option 1): births stream the system the ROM assembled, as assembled code; hera.4th is unchanged. test_host_unit's host builds the system with the ROM. - New parity lines: PARITY:V4_F18 per blob, PARITY:V4_ROM words=2049 rom_hash=0xa6c792b5821010b7 instructions=60725216. Acceptance: amd64, aarch64, riscv64 boot to ok> with PARITY:V4_POST tests=538 pass=538 fail=0, POST: PASSED, and PARITY:V4_SYSTEM word_count=317 dict_hash=0xe5a57f3eb72ff94a on all three -- the same hash as the prebuilt nucleus gave. make -C v4 test test-32 hosted-check: all pass. Logs: logs/20261015-141648, -141938, -142350. Startup cost under QEMU TCG, the ROM's assembly (last V4_F18 line to V4_ROM): amd64 26.7 s of 132 s to ok>; aarch64 41.0 s of 195 s; riscv64 20.5 s of 101 s. Hosted native: +0.85 s. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
109 lines
4.9 KiB
C
109 lines
4.9 KiB
C
/* image.h -- the StarForth system, as its host knows it: where things are
|
|
* in a node that holds it, and how a line is handed to that node.
|
|
*
|
|
* The system is text, the .f18 blobs of capsules/v4/sys, and the machine's
|
|
* ROM assembles it when the machine starts (docs/v4.0.0/MACHINE.md; v4/
|
|
* system/boot.c). Its host knows two things of it:
|
|
*
|
|
* - the memory map, before it is built: v4_map_image, a C file that
|
|
* tools/mkmap.c writes from the map (`mkmap image`);
|
|
* - what only the assembled system knows -- where it waits, its fault
|
|
* table, KEY -- from the image record, a fixed block of RAM whose
|
|
* address is a constant of the map and which the system's source
|
|
* stores (capsules/v4/sys/end.f18): v4_image_from_node.
|
|
*
|
|
* A node that holds the system is sent text as messages and sends back
|
|
* what it prints (v4/include/v4/message.h); nothing here hands it a line.
|
|
*
|
|
* A description is for one cell width, one node size and one pair of stack
|
|
* sizes; v4_image_born refuses one the engine was not built for.
|
|
*/
|
|
#ifndef V4_IMAGE_H
|
|
#define V4_IMAGE_H
|
|
|
|
#include "v4/exec.h"
|
|
|
|
typedef struct {
|
|
/* what the image was built for */
|
|
unsigned cell_bits, node_words, data_ring, ret_ring;
|
|
|
|
/* Where the system waits for a message (capsules/v4/sys/quit.f18,
|
|
* (IDLE)): a node that holds the system begins there, and with nothing
|
|
* to do it is asleep at a wire inside it (operation 8, MESH.md 7d.3).
|
|
* This, fault_table, key_start and key_end are -1 until the system is
|
|
* built (v4_image_from_node). */
|
|
v4_cell idle;
|
|
v4_cell fault_table; /* (FAULTS): where a fault goes */
|
|
v4_cell port; /* word address of the node's port (node.h) */
|
|
|
|
/* KEY's code: a node whose P is in key_start .. key_end - 1 with no
|
|
* character pending is waiting for one */
|
|
v4_cell key_start, key_end;
|
|
|
|
/* the memory-mapped registers (DECOMPOSITION.md section 7; D-4 leaves
|
|
* the map to the loader, and this is the map the system is built with) */
|
|
v4_cell console_tx, console_rx, console_status;
|
|
v4_cell dstack_reg, rstack_reg;
|
|
v4_cell node_error;
|
|
|
|
/* the dictionary's two variables: DP holds HERE, a byte address, and
|
|
* LATEST the newest word of FORTH. What lies below HERE, and LATEST,
|
|
* is what the dictionary hash covers (v4/include/v4/boot.h). */
|
|
v4_cell dp, latest;
|
|
|
|
/* What COLD returns the system to and FORGET will not go below: two
|
|
* cells, DP and LATEST as they were when the system was complete, and
|
|
* the variable FENCE. The system's source sets them; a system that
|
|
* loads capsules when it boots sets them again when it has
|
|
* (v4_image_seal). */
|
|
v4_cell boot_cells, fence;
|
|
|
|
/* the block window: the word address of the slots the kernel copies
|
|
* blocks into (v4/blocks.h) */
|
|
v4_cell block_window;
|
|
|
|
/* the image record (capsules/v4/sys/end.f18): four cells, where the
|
|
* system waits, its fault table, KEY and the word after KEY; and the
|
|
* ROM's two cells that say why it stopped, if it did: the code of its
|
|
* error (0 if none) and the line it was on, counting from 0 */
|
|
v4_cell record, rom_failed, rom_errline;
|
|
} v4_image;
|
|
|
|
/* The system's error for a node blocked at a port with no one on it
|
|
* (capsules/v4/sys/core.f18's list; node.h, v4_node_port_gone): "No one on
|
|
* that port". */
|
|
#define V4_ERROR_NO_ONE 18
|
|
|
|
/* The memory map's description of the system (the generated file defines
|
|
* it): what is known of it before it is built. */
|
|
extern const v4_image v4_map_image;
|
|
|
|
/* What only the assembled system knows, read from the image record of the
|
|
* node `n` that holds it into `im`, which the map's description is in.
|
|
* Returns 1, or 0 if the record does not name addresses of the node's
|
|
* memory (nothing is then changed). */
|
|
int v4_image_from_node(const v4_node *n, v4_image *im);
|
|
|
|
/* The system is complete: what is in the dictionary now is what COLD comes
|
|
* back to, and FORGET will not go below it. */
|
|
void v4_image_seal(v4_node *n, const v4_image *im);
|
|
|
|
/* The dictionary hash of a node started from `im`: FNV-1a over its memory
|
|
* below HERE, a cell at a time, low byte first, and then LATEST. It does
|
|
* not depend on the machine: every build of one commit, with one cell
|
|
* width, gives the same hash for the same dictionary. */
|
|
uint64_t v4_image_dict_hash(const v4_node *n, const v4_image *im);
|
|
|
|
/* A node newly born (node.h), with the registers the system expects of the
|
|
* node it runs on. Its memory is empty and it is blocked
|
|
* reading its ports: its code is yet to be sent to it, or assembled on it. Returns 1, or 0
|
|
* if the description is not for this build of the engine (nothing is then
|
|
* done). */
|
|
int v4_image_born(v4_node *n, v4_exec_state *es, v4_heat *h, const v4_image *im);
|
|
|
|
/* 1 if the node is waiting for a character: it is inside KEY and none is
|
|
* pending. */
|
|
int v4_image_waiting(const v4_node *n, const v4_image *im);
|
|
|
|
#endif /* V4_IMAGE_H */
|