feat(v4): the ROM assembles the system's .f18 to the nucleus, word for word
capsules/v4/sys: the nucleus's fourteen sources as .f18 blobs (made once by v4/tools/v4tof18.py: header becomes the ROM's directives, every other token and line kept), the memory map as map-<width>.f18 (mkmap sys, from one table in host_map.h that host_load reads too), and end.f18, the switch-on state mkimage.c set in C, the image record, and start (IDLE). test_host_rom_nucleus.c: the ROM, fed those blobs through the console, builds RAM identical word for word to mkimage.c's, outside its own state and the image record, and starts at (IDLE), at both widths. The cost: 60.7 million instructions, 1.5 s on the C model. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
084c520a54
commit
1bf19d6224
+18
-1
@@ -1,6 +1,7 @@
|
||||
/* mkmap.c -- the memory map, as constants the ROM is assembled with.
|
||||
*
|
||||
* mkmap > rom-map-<width>.f18
|
||||
* mkmap sys > capsules/v4/sys/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
|
||||
@@ -17,10 +18,26 @@ static void constant(const char *name, long value)
|
||||
printf("constant %s %ld\n", name, value);
|
||||
}
|
||||
|
||||
int main(void)
|
||||
/* `mkmap sys`: the system's map, the blob the ROM reads before the system's
|
||||
* source (capsules/v4/sys/map-<width>.f18): every constant host_load gives
|
||||
* the nucleus, and the two its end (capsules/v4/sys/end.f18) needs besides. */
|
||||
static int system_map(void)
|
||||
{
|
||||
printf("\\ map-%d.f18 -- the memory map the system's source is assembled with, %d-bit cells.\n", V4_CELL_BITS, V4_CELL_BITS);
|
||||
printf("\\ Generated by v4/tools/mkmap.c (mkmap sys) from v4/tests/host_map.h -- do not edit.\n");
|
||||
#define SYS_CONSTANT(name, value) constant(name, (long)(v4_cell)(value));
|
||||
HOST_CONSTANTS(SYS_CONSTANT)
|
||||
#undef SYS_CONSTANT
|
||||
constant("DICT-W", (long)DICT_W);
|
||||
constant("(IMG)", (long)ROM_IMG);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
(void)host_load; /* host_map.h's loader is not this tool's */
|
||||
(void)host_branch_slots;
|
||||
if (argc == 2 && argv[1][0] == 's') return system_map();
|
||||
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);
|
||||
|
||||
@@ -0,0 +1,110 @@
|
||||
#!/usr/bin/env python3
|
||||
"""v4tof18.py -- turn the nucleus's .v4 sources into the system's .f18 blobs.
|
||||
|
||||
v4/tools/v4tof18.py
|
||||
|
||||
Run once (MACHINE.md step 2; plan Task 8): reads v4/capsule/*.v4 and writes
|
||||
capsules/v4/sys/*.f18. Everything is kept token for token and line for
|
||||
line except `header NAME flags :`, which text.c lays down itself and the
|
||||
ROM's language says with its directives:
|
||||
|
||||
set HDR-NFA here ", NAME #, F #, HDR-NFA #, HDR-LINK set HDR-LINK here :
|
||||
|
||||
-- the name as a counted string, the flags (immediate 1, data 4, inline 8,
|
||||
compile-only 16), the name's address and the link to the header before;
|
||||
HDR-LINK is then the new entry's code address, as text.c's latest is. The
|
||||
first file begins `set HDR-LINK 0`. The tokens are found as text.c's
|
||||
next_token finds them: `\\` and `(` as whole tokens begin comments; a
|
||||
header's name is the next run of characters, whatever they are.
|
||||
"""
|
||||
import os
|
||||
import sys
|
||||
|
||||
ROOT = os.path.abspath(os.path.join(os.path.dirname(__file__), "..", ".."))
|
||||
SRC = os.path.join(ROOT, "v4", "capsule")
|
||||
OUT = os.path.join(ROOT, "capsules", "v4", "sys")
|
||||
FILES = ["core", "input", "dict", "codegen", "compile", "quit", "forth", "numout",
|
||||
"words", "system", "qmath", "blocks", "log", "acl"]
|
||||
FLAGS = {"immediate": 1, "data": 4, "inline": 8, "compile-only": 16}
|
||||
BLANK = " \t\r\n"
|
||||
|
||||
|
||||
def tokens(text):
|
||||
"""(token, start, end) for each token text.c's next_token would return,
|
||||
and for each header its raw name."""
|
||||
i, n = 0, len(text)
|
||||
raw_next = False
|
||||
while True:
|
||||
while i < n and text[i] in BLANK:
|
||||
i += 1
|
||||
if i >= n:
|
||||
return
|
||||
j = i
|
||||
while j < n and text[j] not in BLANK:
|
||||
j += 1
|
||||
tok = text[i:j]
|
||||
if raw_next:
|
||||
raw_next = False
|
||||
yield tok, i, j
|
||||
i = j
|
||||
continue
|
||||
if tok == "\\":
|
||||
while j < n and text[j] != "\n":
|
||||
j += 1
|
||||
i = j
|
||||
continue
|
||||
if tok == "(":
|
||||
k = text.find(")", j)
|
||||
if k < 0:
|
||||
sys.exit("comment not closed")
|
||||
i = k + 1
|
||||
continue
|
||||
yield tok, i, j
|
||||
if tok == "header":
|
||||
raw_next = True
|
||||
i = j
|
||||
|
||||
|
||||
def convert(text, first):
|
||||
out, last = [], 0
|
||||
toks = list(tokens(text))
|
||||
k = 0
|
||||
while k < len(toks):
|
||||
tok, s, e = toks[k]
|
||||
if tok != "header":
|
||||
k += 1
|
||||
continue
|
||||
name = toks[k + 1][0]
|
||||
flags, m = 0, k + 2
|
||||
while toks[m][0] != ":":
|
||||
if toks[m][0] not in FLAGS:
|
||||
sys.exit("header %s: %s is not a flag" % (name, toks[m][0]))
|
||||
flags |= FLAGS[toks[m][0]]
|
||||
m += 1
|
||||
colon = toks[m][1]
|
||||
span = text[s:colon]
|
||||
directive = ('set HDR-NFA here ", %s #, %d #, HDR-NFA #, HDR-LINK set HDR-LINK here '
|
||||
% (name, flags))
|
||||
out.append(text[last:s])
|
||||
out.append(directive + "\n" * span.count("\n"))
|
||||
last = colon
|
||||
k = m
|
||||
out.append(text[last:])
|
||||
body = "".join(out)
|
||||
if first:
|
||||
body = "set HDR-LINK 0 \\ the newest dictionary entry: none yet\n" + body
|
||||
return body
|
||||
|
||||
|
||||
def main():
|
||||
os.makedirs(OUT, exist_ok=True)
|
||||
for i, f in enumerate(FILES):
|
||||
with open(os.path.join(SRC, f + ".v4")) as h:
|
||||
text = h.read()
|
||||
with open(os.path.join(OUT, f + ".f18"), "w") as h:
|
||||
h.write(convert(text, i == 0))
|
||||
print("v4tof18: %d files -> %s" % (len(FILES), OUT))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user