/* test_host_rom_nucleus.c -- the proof: the ROM assembles the system as text.c does, word for word. * * Plan Task 8 and 9; MACHINE.md section 6, step 1. The system's source is * capsules/v4/sys: map-.f18, the fourteen .f18 files and end.f18. * Node A is that source assembled off the node by text.c, the oracle (it * speaks the ROM's language: constant, set, here, #, ", store, start). * Node B is the machine with its ROM, fed the same source through the * console. When the ROM starts the system, every word of B's RAM must be * A's, except the ROM's own state area (which A does not have), and B must * start where A's start says. It also reports what the assembly cost: * instructions retired and seconds (Captain Bob: watch the startup cost). */ #include "rom_harness.h" #include "v4/text.h" #include #include static int failures = 0, checks = 0; #define CHECK(c,...) do{checks++; if(!(c)){failures++; printf("FAIL %s:%d: ",__FILE__,__LINE__); printf(__VA_ARGS__); printf("\n");}}while(0) static v4_node a, b; static v4_text tx; /* node A: text.c assembles the system's source, map first and end last */ static int build_a(void) { char path[512]; unsigned i; v4_node_reset(&a); v4_text_begin(&tx, &a, ROM_ORIGIN); for (i = 0; i < ROM_SYS_FILES + 2u; i++) { if (i == 0) snprintf(path, sizeof path, "%s/map-%d.f18", V4_SYS_DIR, V4_CELL_BITS); else if (i <= ROM_SYS_FILES) snprintf(path, sizeof path, "%s/%s.f18", V4_SYS_DIR, rom_system_files[i - 1]); else snprintf(path, sizeof path, "%s/end.f18", V4_SYS_DIR); if (!v4_text_assemble_file(&tx, path)) return 0; } return v4_text_start(&tx) >= 0; } /* the ROM's own cells: not compared */ static int excluded(v4_cell w) { return (w >= OUT_W - 144 && w < OUT_W - 64) || (w >= BUF0_W - 32 && w < BUF0_W - 22) || (w >= BUF0_W - 122 && w < BUF0_W - 119); } int main(void) { long words = 0; clock_t t0, t1; v4_cell w, idle_a; CHECK(build_a(), "text.c assembles the system's source to its start: %s", v4_text_error(&tx)); idle_a = v4_text_start(&tx); CHECK(idle_a == v4_text_word(&tx, "(IDLE)"), "the system starts at (IDLE)"); t0 = clock(); CHECK(rom_build_system(&b, &words), "the ROM started the system: P %ld, failed %ld at line %ld", (long)b.p, (long)b.mem[ROM_FAILED], (long)b.mem[ROM_ERRLINE] + 1); t1 = clock(); printf(" the ROM assembled the system: %lu instructions, %lu instruction words, %.2f s (%d-bit cells)\n", (unsigned long)rom_es.anticlock, (unsigned long)words, (double)(t1 - t0) / CLOCKS_PER_SEC, V4_CELL_BITS); CHECK(b.p == idle_a, "it starts where text.c's start says: %ld, text.c's %ld", (long)b.p, (long)idle_a); CHECK(b.mem[ROM_IMG] == idle_a && b.mem[ROM_IMG + 1] == v4_text_word(&tx, "(FAULTS)") && b.mem[ROM_IMG + 2] == v4_text_word(&tx, "KEY") && b.mem[ROM_IMG + 3] == v4_text_word(&tx, "CR"), "the image record holds text.c's addresses"); for (w = 0; w < (v4_cell)V4_NODE_WORDS; w++) { if (excluded(w) || a.mem[w] == b.mem[w]) continue; CHECK(0, "RAM word %ld: text.c %lx, ROM %lx", (long)w, (unsigned long)a.mem[w], (unsigned long)b.mem[w]); break; } CHECK(w == (v4_cell)V4_NODE_WORDS, "every word of RAM is the same"); printf("test_host_rom_nucleus: %d checks, %d failures\n", checks, failures); return failures != 0; }