feat(v4): mkrom -- the ROM built off the node; it reads tokens
The ROM's source is F18 code in capsules/v4/rom, assembled off the node by v4/tools/mkrom.c with the memory map's constants from v4/tools/mkmap.c (MACHINE.md 2). main.f18 is the entry table payloads call through (2.1); in.f18 reads the console and splits it into tokens exactly as text.c does, the token held packed as a counted string. The ROM's state is a reserved area of the map (host_map.h ROM_*). text.c gains the constant directive, so the off-node assembler and the ROM speak one language. The map also names (NUMBER)'s state, for the next task. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
32753f5479
commit
0f82d8c22a
@@ -0,0 +1,47 @@
|
||||
/* mkmap.c -- the memory map, as constants the ROM is assembled with.
|
||||
*
|
||||
* mkmap > rom-map-<width>.f18
|
||||
*
|
||||
* Runs on the build machine, built for the host node (HOST_WORDS and the
|
||||
* host stack sizes) at one cell width. It writes, as `constant` lines in
|
||||
* the text assembler's notation, the addresses and codes of
|
||||
* v4/tests/host_map.h that the ROM's source (capsules/v4/rom) uses: the
|
||||
* console's receive registers and the ROM's state area (MACHINE.md 2.1).
|
||||
* The map has one source, host_map.h; this is how the ROM reads it.
|
||||
*/
|
||||
#include "../tests/host_map.h"
|
||||
#include <stdio.h>
|
||||
|
||||
static void constant(const char *name, long value)
|
||||
{
|
||||
printf("constant %s %ld\n", name, value);
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
(void)host_load; /* host_map.h's loader is not this tool's */
|
||||
(void)host_branch_slots;
|
||||
printf("\\ Generated by v4/tools/mkmap.c from v4/tests/host_map.h -- do not edit.\n");
|
||||
constant("CONSOLE-RX", (long)CONSOLE_RX);
|
||||
constant("CONSOLE-STATUS", (long)CONSOLE_ST);
|
||||
constant("(TOK)", (long)ROM_TOK);
|
||||
constant("(TOKN)", (long)ROM_TOKN);
|
||||
constant("(PEEK)", (long)ROM_PEEK);
|
||||
constant("(LINE)", (long)ROM_LINE);
|
||||
constant("(EOF)", (long)ROM_EOF);
|
||||
constant("(FAILED)", (long)ROM_FAILED);
|
||||
constant("(ERRLINE)", (long)ROM_ERRLINE);
|
||||
constant("(NBASE)", (long)ROM_NBASE);
|
||||
constant("(NNEG)", (long)ROM_NNEG);
|
||||
constant("(NI)", (long)ROM_NI);
|
||||
constant("(NU)", (long)ROM_NU);
|
||||
constant("(NBIG)", (long)ROM_NBIG);
|
||||
/* the cell width's constants (NUMBER) needs, written as signed cells */
|
||||
constant("MSB", (long)(v4_cell)V4_MSB);
|
||||
constant("DEC-LIMIT", (long)(v4_cell)(~(v4_ucell)0 / 10u));
|
||||
constant("DEC-NLAST", -(long)(~(v4_ucell)0 % 10u) - 1);
|
||||
constant("HEX-HIGH", (long)(v4_cell)~(~(v4_ucell)0 >> 4));
|
||||
constant("ERR-TOO-LONG", (long)ROM_ERR_TOO_LONG);
|
||||
constant("ERR-COMMENT", (long)ROM_ERR_COMMENT);
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
/* mkrom.c -- build the ROM, off the node, as a bitstream is built.
|
||||
*
|
||||
* mkrom OUT.c OUT.sym MAP.f18 SOURCE.f18...
|
||||
*
|
||||
* docs/v4.0.0/MACHINE.md section 2. The ROM is F18 code, written in the
|
||||
* text assembler's notation (include/v4/text.h) in capsules/v4/rom, and this
|
||||
* is the only thing built off the node. It assembles MAP.f18 (the memory
|
||||
* map's constants, from tools/mkmap.c) and then each SOURCE in the order
|
||||
* given, at the ROM's base address, and writes:
|
||||
* OUT.c the ROM: const v4_cell v4_rom_<width>[] and its length
|
||||
* OUT.sym every word of it, "NAME ADDRESS" a line, for the tests
|
||||
*
|
||||
* This tool is built with a node whose RAM reaches over the ROM's range
|
||||
* (V4_NODE_WORDS = the host's RAM plus its ROM range, V4_ROM_WORDS = 0), so
|
||||
* the assembler can lay the ROM down where it will run; ROM_ORIGIN is the
|
||||
* host's RAM size, which is where the ROM starts on the machine. The
|
||||
* assembler's branch placement depends only on the top of the address space,
|
||||
* which is the same either way.
|
||||
*/
|
||||
#include "v4/text.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifndef ROM_ORIGIN
|
||||
#error "ROM_ORIGIN must be the host node's RAM size"
|
||||
#endif
|
||||
#ifndef ROM_RANGE
|
||||
#error "ROM_RANGE must be the host node's ROM range, in words"
|
||||
#endif
|
||||
|
||||
static v4_node n;
|
||||
static v4_text tx;
|
||||
|
||||
static void die(const char *what, const char *detail)
|
||||
{
|
||||
fprintf(stderr, "mkrom: %s%s%s\n", what, detail ? ": " : "", detail ? detail : "");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* a cell as a C constant of the cell's type, with no implementation-defined conversion */
|
||||
static void put_cell(FILE *f, v4_cell v)
|
||||
{
|
||||
#if V4_CELL_BITS == 64
|
||||
if (v == (v4_cell)((v4_ucell)1 << 63)) fprintf(f, "(-9223372036854775807LL - 1)");
|
||||
else fprintf(f, "%lldLL", (long long)v);
|
||||
#else
|
||||
if (v == (v4_cell)((v4_ucell)1 << 31)) fprintf(f, "(-2147483647L - 1)");
|
||||
else fprintf(f, "%ldL", (long)v);
|
||||
#endif
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
FILE *out;
|
||||
v4_cell here, a;
|
||||
int i;
|
||||
unsigned s;
|
||||
|
||||
if (argc < 5) die("usage: mkrom OUT.c OUT.sym MAP.f18 SOURCE.f18...", NULL);
|
||||
if ((v4_ucell)V4_NODE_WORDS != (v4_ucell)ROM_ORIGIN + (v4_ucell)ROM_RANGE)
|
||||
die("built with the wrong node size: RAM must reach over the ROM's range", NULL);
|
||||
|
||||
v4_node_reset(&n);
|
||||
v4_text_begin(&tx, &n, ROM_ORIGIN);
|
||||
for (i = 3; i < argc; i++)
|
||||
if (!v4_text_assemble_file(&tx, argv[i])) die("does not assemble", v4_text_error(&tx));
|
||||
if (!v4_text_finish(&tx)) die("not everything is defined", v4_text_error(&tx));
|
||||
here = v4_text_here(&tx);
|
||||
if (here - (v4_cell)ROM_ORIGIN > (v4_cell)ROM_RANGE) die("the ROM is larger than its range", NULL);
|
||||
|
||||
out = fopen(argv[1], "w");
|
||||
if (!out) die("cannot write", argv[1]);
|
||||
fprintf(out, "/* Generated by v4/tools/mkrom.c from capsules/v4/rom -- do not edit. */\n#include \"v4/cell.h\"\n\n");
|
||||
fprintf(out, "const v4_cell v4_rom_%d[] = {\n", V4_CELL_BITS);
|
||||
for (a = ROM_ORIGIN; a < here; a++) {
|
||||
fprintf(out, " ");
|
||||
put_cell(out, n.mem[a]);
|
||||
fprintf(out, ",\n");
|
||||
}
|
||||
if (here == ROM_ORIGIN) fprintf(out, " 0\n");
|
||||
fprintf(out, "};\nconst unsigned v4_rom_%d_words = %ldu;\n", V4_CELL_BITS, (long)(here - (v4_cell)ROM_ORIGIN));
|
||||
if (fclose(out) != 0) die("cannot write", argv[1]);
|
||||
|
||||
out = fopen(argv[2], "w");
|
||||
if (!out) die("cannot write", argv[2]);
|
||||
for (s = 0; s < tx.nsym; s++)
|
||||
if (tx.sym[s].kind == 1) fprintf(out, "%s %ld\n", tx.pool + tx.sym[s].name, (long)tx.sym[s].value);
|
||||
if (fclose(out) != 0) die("cannot write", argv[2]);
|
||||
|
||||
fprintf(stderr, "mkrom: a ROM of %ld words, %d-bit cells -> %s\n", (long)(here - (v4_cell)ROM_ORIGIN), V4_CELL_BITS, argv[1]);
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user