YACC1 test inventory: every test in the tree, what it proves, how to run it¶
The complete list of tests under tests/, the root make check, the verification tools under tools/, and the emulator
modes they rely on. For each: what it proves, how to run it, what a pass looks like, and whether it needs hardware.
Written 2026-09-23 from the YACC1-D tree.
Sources: Makefile (root), tests/README.md and the READMEs under tests/*/, the docstrings of every run.py and of
tools/verify_firmware.py, verify_embedded.py, verify_processing.py, audit_tree.py, gen_bom.py; software/emulator/README.md,
software/ucemu/README.md, os/README.md and os/Makefile; software/assembler/Makefile and firmware/microcode/ucode-generator2/Makefile
(the two check targets); tests/memory/*.log, tests/sequencer/*.log, tests/video/README.md. The "pass looks like" columns
are from a run of every software-only test on this tree on 2026-09-23 (all passed). The bench procedures behind the hardware
tests are in BRING-UP.md.
Needs hardware? column: no = runs on the Mac alone; tester = the machine on the bench with the Bus Test Card on its FTDI port; card = the sequencer-memory card's FTDI port; burn = a 28C64 to program and the machine to run it.
1. make check - the tree's own proof, in order¶
make check at the root runs, in this order (root Makefile):
| Step | Command | What it enforces |
|---|---|---|
| 1 | python3 tools/audit_tree.py |
every file in the tree is explained (section 4) |
| 2 | python3 tools/verify_firmware.py |
the ROM and microcode images reproduce from source (section 4) |
| 3 | python3 tools/verify_embedded.py |
every Arduino sketch compiles with zero warnings (needs arduino-cli) |
| 4 | python3 tools/verify_processing.py |
the Processing command sender builds with zero warnings (needs Processing 4) |
| 5 | make -C software/assembler check |
monitor.img / basic.img / shipped rom re-assemble identical |
| 6 | make -C firmware/microcode/ucode-generator2 check |
test.hex regenerates identical |
| 7 | python3 tests/compiler/run.py |
15 C programs on the instruction-level emulator |
| 8 | python3 tests/ucemu/run.py |
13 of them + brur on the microcode-level emulator |
| 9 | python3 tests/os/run.py |
the Y1/OS session on both emulators |
| 10 | python3 tests/sequencer/run.py |
the microcode sender against a mock card |
| 11 | python3 tests/assembler/romcount/run.py |
the ROM counter on the microcode emulator |
| 12 | python3 tests/assembler/romdiag/run.py |
the ROM diagnostic on the microcode emulator |
| 13 | python3 tests/monload/run.py |
the monitor's : loader on both emulators (error paths too) and tools/monload.py over a pty (2026-09-23) |
| 14 | python3 tests/bench/run.py |
the 15 bench programs on both emulators against their expected transcripts, the committed images, and the --port path over a pty (2026-09-23) |
| - | python3 tests/disasm/run.py |
/BIN/DISASM round trip (2026-09-29): its output reassembled by RC/asm gives the same bytes, over tests/asm's corpus, the OS build's programs, the ROM and synthetic bytes (section 3.10) |
| 15 | python3 tests/kermit/run.py |
/BIN/KERMIT against tools/y1kermit.py over a pty on both emulators: files both ways, options, damaged/missing packets and timeouts, the server; then --calib, the receive loop's and the timeouts' clocks on the microcode emulator (2026-09-26) |
Shortcuts: make cc-test = steps 7+8, make os-test = step 9. make (all) first builds the C tools the tests need:
software/emulator, software/ucemu, software/assembler, firmware/microcode/ucode-generator2, software/disassembler/disasm2,
software/ubasic-c/ubasic-master, the bus-tester vector generator - after tools/layout_links.py has laid the include symlinks.
Steps 3 and 4 are the only ones that need tools outside the tree (arduino-cli, Processing 4); everything else is Python 3 and cc.
Generated documentation has its own checks that are not in make check: python3 tools/gen_bom.py --check (docs/bom/,
section 4) and make isa (docs/isa/, regenerate rather than check).
2. The emulators and their scripted modes¶
Two emulators, deliberately different (software/ucemu/README.md):
software/emulator/emulator- the instruction-level reference model (main.c): knows what every opcode does, 64K, 16 ports, console on port 2. Quick and forgiving. Options used by the tests:-xscripted mode (no load/dump chatter, no raw tty, stdout flushed,HALTexits withHALT at aaaa after N instructions, R3=xxxxon stderr),-f FILEload an Intel-hex image (the assembler's.img),-mload the monitor+BASIC ROM (firmware/basic/basic.img+firmware/monitor/monitor.img, found relative to the executable),-c disk.imga CompactFlash image on ports P8/P9 (MACHINE.md). Since 2026-09-22BRVRandJSRURdo what the microcode does, so the monitor'sGandTwork on it. It also stops itself at an instruction limit (tests/os/basic.int.outends withinstruction limit reached at f530 after 6000000 instructions).software/ucemu/y1ucemu- the microcode-level model: does not know what any instruction does; it steps the control words offirmware/microcode/ucode-generator2/test.hex(256 x 64 x 64 bits) through a model of the cards (sequencer, register cards, ALU, memory with FORCE-ROM, I/O with the 16550 model), and counts bus fights (two drivers disagreeing on a data lane, per opcode and step). This is what turned the microcode review's findings into runnable tests. Options:-xscripted,-mmonitor ROM,-f FILE,-u test.hexanother control store,-F and|srchow a fight resolves (AND = the usual TTL outcome; src = the ALU's-AC-RDloses),-s NNthe switch byte,-l Nstop after N steps,-tone line per instruction fetch,-Tevery step with signals,-wlist every fight as it first occurs,-i 0|1the input-switch line level (BRINH/BRINL),-I Nflip that line every N steps,-Lreport LED-board / TIL311 / ON-OFF writes on stderr,-R 1|2the number of index-register cards fitted (with 1, R4..R7 read $FF and lose loads and counts),-c disk.img. Its status line gives instructions, steps, clocks (a step is two clock periods), R3 and the fight count - e.g.HALT at 3046 after 90 instructions, 1187 steps, 2285 clocks, R3=0000; bus fights: 0 in 0 (opcode,step) pairs; weak pull-up drives: 162.
Under the microcode BRDEV always branches, so a program's console goes through the monitor's charout/uartin and the UART
model - the path the real machine takes - and the monitor's uartin echoes every character it reads. That is why some
tests have a second expectation file (.ucout, .uc.out) for the microcode emulator.
Every test image is loaded at $3000 (the C compiler's default; BASIC's token buffer is $1000-$1FFF) and starts with a branch to
an address above $8000 (--boot stub) so that the FORCE-ROM remap is released exactly as on the hardware.
3. The tests under tests/¶
3.1 tests/compiler/ - the C cross-compiler (no hardware)¶
- Proves:
software/compiler/y1cc.pycompiles each program correctly for the YACC1: 15 programs (arith,arrays,calls,chars(with stdin),control,fib,globals,hello,io,sieve,structs,switch,switchnb=switchcompiled with--no-brur) plus two that must fail to compile (bigconst.err"does not fit 16 bits",recurse.err"recursion is not supported"). Since 2026-09-24 recursion is supported:rfact,rmutual,rlocals,rcalcrun, and the errors arerecurse.err(the address of a local passed into a recursive cycle) andrmain.err(recursivemain).tests/compiler/diffcheck.pycompiles the whole corpus with an oldery1cc.pyfrom git and the working one and requires identical assembly.adjstr.err(adjacent string literals) joined with the C twin. - The C twin:
python3 tests/compiler/twin.py [--16] [-v]buildssoftware/compiler/c/y1cc(y1cc.c, 2026-09-24) and compiles the whole corpus (tests/compiler/corpus.py, 121 compiles including y1cc.c itself) with it and with y1cc.py: the assembly, the-lsummary and every expected error message must be identical.--16uses the check buildy1cc16(int = unsigned short, unsigned char). Pass looks like:twin: 117 programs identical, 4 identical errors, 0 DIFFERENT. Both run inmake check. (126 programs since the multi-pass compiler's nine passes joined the corpus as Y1/OS programs,software/compiler/c/target/.) - The multi-pass compiler (2026-09-24,
software/compiler/c/cc1_lex.c..cc9_final.c, drivery1ccp):twin.py --chainand--chain16compare y1cc.py with the nine passes chained (the 16-bit check builds),twinfuzz.py N --seed S --chaindoes the same for random programs and the 60 invalid ones. Pass looks like:twin (the pass chain y1ccp: cc1..cc9): 126 programs identical, 4 identical errors, 0 DIFFERENT.python3 tests/compiler/passes.py [-v]compiles each pass with y1cc.py as a Y1/OS program, assembles it, and measures image + tables + stack against the 32K program area; then it compiles the corpus through the passes built with their Y1/OS table sizes and a stack probe. Pass looks like: a table with a positive "free" column for all nine passes,125 identical, 4 identical errors, 1 do not fit, 0 DIFFERENT(the one: y1cc.c,software/compiler/c/target.c), and the count of compiles whose files stay under Y1/OS's 64K. Exit 1 if a pass does not fit or an assembly differs. All inmake check. - Run:
python3 tests/compiler/run.py [name ...] [--oracle] [--keep]. Per test: compile with--boot(stack,JSR main,HALT), assemble withsoftware/assembler/asm NAME -d=yacc1, runemulator -x -f NAME.img < NAME.in, compare stdout withNAME.out. Per-test compiler flags in a// y1cc:comment.--oracleregenerates the.outfiles with the host C compiler throughhost_shim.h(int = unsigned short, char unsigned) for tests not marked// no-oracle.--keepleavesbuild/. - Pass looks like: one line per test and
15/15 passed, e.g.arith PASS 2364 bytes 184720 instructions,bigconst PASS expected compile error 'does not fit 16 bits': seen. A failure writesbuild/NAME/NAME.gotand prints both.
3.2 tests/ucemu/ - the same programs on the microcode (no hardware)¶
- Proves: the control store in
test.hexexecutes the compiler's programs the way the instruction-level emulator says they should, with zero bus fights, through the monitor's real console path. Also runstests/assembler/brur. - Run:
python3 tests/ucemu/run.py [name ...] [--keep] [--ucode PATH] [--fight and|src]. Each program is compiled with--bootand run with-m(monitor ROM); the expectation istests/compiler/NAME.out, orNAME.ucoutwhere the hardware's input echo makes it differ (chars.ucout). - Pass looks like:
arith PASS 196018 instr 2577002 steps 4957987 clocks fights 0 (0 pairs)...brur PASS HALT at 3046 after 90 instructions ... bus fights: 0 ..., then14 passed, 0 failed. A non-zero fight count is a failure even when the output matches: it means the image has a two-driver step (this is how H-1 and H-2 were reproduced on 2026-09-22). tests/ucemu/isa.asm- the differential ISA test: every arithmetic, logic, shift, compare, register, memory and stack instruction, each result written raw to port 2 with the expected value in a comment. Run on both emulators, the byte streams must be identical (they are,BRDEVaside).run.pydoes not run it by default; assemble it besideyacc1.defand compareemulator -x -f isa.imgwithy1ucemu -x -f isa.imgby hand. It is also the byte stream to check on the machine through the UART once a RAM loader exists (BACKLOG;BRING-UP.mdsection 4).
3.3 tests/os/ - Y1/OS on both emulators (no hardware)¶
- Proves:
os/builds (y1os.bin, the/BINprograms,disk.imgas a P8XFS v2 volume viatools/p8xfs.py), the monitor'sOcommand boots it from the CF model on ports P8/P9, and a scripted shell session gives the same transcript on both emulators. - Run:
python3 tests/os/run.py [--keep] [--update](=make os-test,make -C os test). Sessions aretests/os/*.session(one console line per line, sent afterO); expectationsNAME.int.out(instruction-level) andNAME.uc.out(microcode, with the input echo). The comparison starts atBOOT FROM CFand ends after the OS saysbyeand the prompt returns.--updaterewrites the expectations from the run - only after reading them by eye. - Pass looks like:
basic int PASS instruction limit reached at f530 after 6000000 instructions, R3=22a7andbasic uc PASS HALT at F529 after 5023647 instructions, 80000000 steps, ...,2 passed, 0 failed. The session exercisesdir,cat,cd,pwd,hello a b c(implicit/BINlookup with arguments),run /BIN/ECHO hi there,wc 45 1(raw sectors through the BIOS vectors), an unknown command,load,help,exit. - The CF hardware (planned on the memory card,
docs/cards/cf.md) does not exist yet, so this is emulator-only by nature.
3.4 tests/sequencer/ - the microcode sender, without the card (no hardware)¶
- Proves:
tools/ucode_send.pyspeaks the Sequencer4 download protocol correctly: (1) a differential send - a cache that differs fromtest.hexin four records plus one never sent makes exactly those five reach the card with the right bytes, and the cache ends equal totest.hex; (2)--allsends all 256; (3)--boot-check's dump comparison, applied to the recorded 2026-09-21 Sequencer4 transcript, finds exactly the pre-fix$07(PUSHR) lines differing and nothing else. - Run:
python3 tests/sequencer/run.py.mock_card.py OUTFILEis a fake Sequencer4 in download mode on a pseudo-terminal (prints its slave path, then>>prompts, takes%cc ii + 512 hex byte values per instruction,!ends; writes what it received as 256 lines). - Pass looks like:
PASS differential send: 5 records/PASS --all send: 256 records/PASS boot-check: 320 dumped lines compared, only the pre-fix $07 (PUSHR) lines differ (20)/0 failed. - The logs (
boot-run-mode-*.log) are bench captures, not tests: the clobbered copy with-BUS-ENasserted, the clean copy, the Sequencer4 boot, and the boot after the 2026-09-22 reload.BRING-UP.mdsection 8 explains how to read them; a fresh capture istools/ucode_send.py --boot-check --log FILE(card).
3.5 tests/assembler/ - the assembler-level programs¶
| Item | Proves | Run | Pass | Hardware |
|---|---|---|---|---|
romcount/run.py |
romcount.asm assembles to the committed romcount.img, img2bin gives the committed 8K romcount.bin, and on the microcode emulator it mirrors the switches with the input line low (-s 0x25 -i 0 -L), counts from the switch value with it high, and wraps FF -> 00 (-s 0xFD), 0 bus fights |
python3 tests/assembler/romcount/run.py |
PASS romcount.img == assembled / PASS romcount.bin == img2bin of the image (8192 bytes) / PASS input low: mirrors the switches, no ON / PASS input high: counts from the switches / PASS wraps FF -> 00 / 0 failed |
no (emulator); burn for the real thing - it ran overnight 2026-09-22/23 on the machine (MACHINE.md) |
romdiag/run.py |
romdiag.asm/.img/.bin match, and the twelve stages read 25 ON AA 20 11 03 01 02 FF 33 20 55 00 01 02 with two register cards (-R 2, -I 100000 flipping the input line every 100,000 steps) and ... 33 FF 55 ... with one (-R 1) |
python3 tests/assembler/romdiag/run.py |
PASS stages, 2 register cards: 25 ON AA 20 11 03 01 02 FF 33 20 55 00 01 02 / PASS stages, 1 register card: ... 33 FF 55 ... / 0 failed |
no; burn on the bench (its first run found the missing register card 1, 2026-09-22) |
brur/brur.asm |
BRUR Rn ($AD, added 2026-09-22): a plain BRUR R5, a jump through a table-fetched address, a four-way dispatch; prints ABC0123 then HALT (89 instructions) |
assemble beside yacc1.def with a -h rcasm.rc, then emulator -x -f brur.img; also run by tests/ucemu/run.py |
ABC0123; on the microcode emulator HALT at 3046 after 90 instructions ... bus fights: 0 |
no; not yet on the machine (needs a RAM loader) |
ledcount/ |
the 10-byte switch-ROM LED counter for the Mem Switch card; ledcount.prg is the assembled output |
set the DIP switches per its README table, clock the machine | LEDs count 00..FF at one count per four instructions | hardware only (the 2026-09-21 first-run program) |
yacc1test.asm + history-2020/ |
the 2020 CPU test program and its 15 dated snapshots (serial out, ROM, RAM, push/pop, ring shift, "major test"); test_output.txt is a 2026-05-26 assembler run |
assemble; run on the emulator or the machine | a record of how bring-up progressed rather than a pass/fail test | either |
3.6 tests/memory/ - the memory card through the bus tester (tester)¶
| Script | Proves | Time | Result on record |
|---|---|---|---|
memory_status.py [port] |
boot remap after -RESET (ROM at $0000 until an A15-high access), every ROM byte against basic.img+monitor.img (tools/romimage.py), 8 low-RAM spots, every 4K block $8000-$FFFF classified RAM / ROM / VIDEO / undecoded against the jumper table in MACHINE.md |
~1 min | 2026-09-18: the fitted map ($8000-$CFFF RAM, $D000 undecoded/video, $E000-$FFFF ROM) |
rom_verify.py [port] [--save] |
the 28C64 holds exactly the tree's ROM image; --save keeps the read-back as rom-readback-<date>.bin |
~30 s (blocks-1 firmware) | the chip burned 2026-09-23 was the tree's image (ROM 2026-09-23, firmware/rom/README.md); since 2026-09-25 the tree holds ROM 2026-09-25 (the video unit, not burned), so until it is burned the monitor half differs - expected, as for a chip with the 2021 build |
memory_full_test.py [port] [--log F] |
A ROM; B address lines (unique byte at $0000 and at every 1<<n, read after all writes: an open or shorted address line shows in seconds); C RAM $0000-$7FFF and $8000-$CFFF address-derived pattern written in one sweep, verified in a second (retention); D the inverted pattern; E video RAM (both patterns, neighbour isolation, the block-0/9 write-through checks, read stability); F ROM again and nothing answers at $D800-$DFFF | ~20 min with blocks-1 (~10 h per byte) | full-run-2026-09-21.log: 14/14 PASS, 53,248 cells x 2 patterns, 0 bad, in 0.3 h |
The four logs beside them tell the day's story: attempt1-linkdrop (the USB port vanished mid-sweep, which is why busdrv.py
now reopens and resends), attempt2-stopped-for-reflash (stopped by hand after 157 min to flash the blocks-1 firmware),
blocks-13of14 (first blocks-1 run; F2 failed because the test expected the $D800 block to echo the bus and the card, with no
CRTC, gives 00 FF instead - the test was corrected), then the clean 14/14.
3.7 tests/video/ - the video card's display RAM (tester)¶
video_ram_test.py [port] [--quick]: five tests over $D000-$D3FF (address-derived pattern, inverted, one-cell neighbour isolation for address-line shorts, the 2026-09-18 write-through check - writes to $0010 / $9010 / $0011 / $1010 must not reach $D010 - and read stability with memory-card traffic in between, because $D000 is undecoded on the memory card and a floating bus can fake a good read).--quick= first 64 cells (~1 min), full ~14 min. 8/8 PASS on 2026-09-21 after the +5V/VCC join, and again with RN2 back at 10k; before the join the write-through fault reproduced every time.hold_address.py HEXADDR [--rd]: not a test - holds an address on the bus (with-VMA, optionally-MEM-RD) for a meter or scope on the card's decode pins; Enter releases. The port must stay open (the tester resets when it closes).tools/alias_min.py: the minimal reproduction of the write-through fault (write $0010;$D010must keep 11, fault = 22).emu.py(2026-09-25; emulators, inmake check): not the card but the ROM's driver for it and Y1/OS'svideo, on both emulators' card model (-Vscreen dump,-Nno card): the probe (banner,VS), mirroring off by default,VW/VB/VF/VD/VR, errors dropping the rest of the line, mirroring with a scroll compared against a Python model of the driver, the absent card, and the OS command (on, clear, off, init, -h). 10 checks x 2 emulators, ~2 min. On the machine the same steps are done by hand:docs/cards/video.mdsection 8.
3.8 tests/bus-tester-scripts/ - the 2020 CMD:OPERAND# scripts (tester)¶
Not pass/fail tests but the scripts that brought each card up in 2020, sent by embedded/command-sender/command_sender_8
(or line by line with tools/busdrv.py --raw): Memory Card Tests/ (low/high RAM and EPROM fill-and-dump, dump-eprom.txt),
ALU/*.new (add, and, or, sub, branch, zero test, in the 2020 signal names), IO/ (basic-out, serialin, serialout),
Index Register/commands-1 copy.txt (372 lines), Gen Test Vectors/ (a C generator for the 2016 register card - stale signal
names, template only), ramtest.logicsettings (Saleae capture set-up). Format and the script language (LET/FOR/NEXT/labels/
expected values) are in BRING-UP.md section 7.3. Always -BUS-EN:1# and -VMA:1# before driving memory.
3.9 tests/basic/ - test¶
A short program using LET, FOR ... NEXT, :loop, DUMPVARS, DUMPLABELS. Its README (2026-09-20) says the interpreter had
not been identified and that it is not uBASIC. Every one of those keywords is in the bus-driver script language of
docs/procedures/BUS Driver Commands - Google Docs.pdf (LET VARIABLE=VALUE, FOR VARIABLE=Initial,Final,Increment, NEXT,
:Label, DUMPVARS, DUMPLABELS), so it is a test of the command sender's script interpreter, not of any BASIC: send it
with command_sender_8 and the variable dumps should show the loop variables. Nothing to run on an emulator. (tests/basic/README.md
is not among this document's files and is left as it is.)
3.10 tests/disasm/ - the disassembler round trip (no hardware)¶
- Proves:
/BIN/DISASM(os/commands/disasm.c) prints only what the assembler turns back into the same bytes, and its table (os/dis_optab.c) is current withyacc1.def. - Run:
python3 tests/disasm/run.py [-v] [--quick] [--only NAME](=make disasm-test;--quickskips the y1cc corpus). - Pass looks like:
gen_y1_distab: os/dis_optab.c is current,... 382 ok, 0 FAILED; 5901847 instructions and DBs,START/COUNT and errors: 168 runs, 0 FAILED. Under Y1/OS:tests/os/disasm.session(section 3.3).
4. The verification tools under tools/¶
| Tool | Enforces | Needs | Pass |
|---|---|---|---|
verify_firmware.py |
the images in the machine reproduce from source: builds software/assembler, assembles firmware/monitor/monitor.asm and firmware/basic/basic.asm with yacc1.def in a scratch dir, compares monitor.img / basic.img, runs makerom and compares firmware/rom/shipped/rom; builds the microcode generator and compares test.hex. Never writes into the tree |
cc | monitor.img IDENTICAL / basic.img IDENTICAL / rom (shipped = image to burn) IDENTICAL / microcode test.hex IDENTICAL / FIRMWARE VERIFIED |
make -C software/assembler check |
the same for the ROM, plus the listings (basic.lst: differs (listing only) is informational) |
cc | basic.img: IDENTICAL ... / rom: IDENTICAL to firmware/rom/shipped/rom (the image to burn) |
make -C firmware/microcode/ucode-generator2 check |
test.hex regenerates identical (fails on any difference - the guard that the committed image is what the generator says) |
cc | test.hex: IDENTICAL to the committed microcode image |
verify_embedded.py |
every Arduino sketch under embedded/ compiles for arduino:avr:uno against only the vendored embedded/libraries (a private user-libraries dir keeps ~/Documents/Arduino/libraries out), with --warnings all; expected outcomes in EXPECT (the MCP23X17 work-in-progress is expected to fail); sketch folders whose name differs from the .ino are copied under the right name first |
arduino-cli | 12 sketches, 0 unexpected results -> EMBEDDED VERIFIED (2026-09-20) |
verify_processing.py |
embedded/command-sender/command_sender_8 builds with the Processing 4 command-line builder and the generated Java re-compiles with Processing's Eclipse compiler with warnings on, cosmetic categories excluded |
Processing 4 in /Applications | zero warnings (2026-09-20) |
audit_tree.py |
every file in the tree is explained: a migration-plan row (hash re-checked against migration/dryrun-plan.tsv), an extra source from the run logs, a hand-made file (the HAND_MADE prefixes: tools/, migration/, front-page docs, docs/cards/, docs/programming/, docs/procedures/, ...), or a generated file (FABRICATED markers, KiCad conversions, PDFs, docs/isa/, docs/bom/ (tools/gen_bom.py), ...). Prints the buckets, hash mismatches, unexplained files and plan rows missing from disk; git-ignored build products are excluded |
git | unexplained files: 0 [] and plan rows missing from disk: 0 []; exit 0. On 2026-09-23 it reports one hash mismatch, firmware/microcode/ucode-generator2/cache - the loader's record of what the card holds, rewritten by ucode_send.py --all on 2026-09-22 after the plan was made, so the mismatch is expected until the plan row is refreshed |
gen_bom.py --check |
docs/bom/ matches what the active schematics say (regenerates into a temp dir and diffs, ignoring the generation-date line) |
Python | docs/bom: UP TO DATE (13 files, date line ignored) |
gen_fabricated.py, gen_provenance.py, compare_eagle.py, eagle_to_kicad_all.py, brd_to_pdf.py, sch_to_pdf.py, ucode_wavedrom.py |
generators for hardware/FABRICATED.md, PROVENANCE.md, NEWER-DESIGNS-vs-ACTIVE.txt, the KiCad conversions, the board/schematic PDFs and docs/isa/ - regenerate and diff by hand (git diff) rather than a --check |
various | |
ucode_review.py |
the mechanical microcode review (rule R2 "two drivers" count went from 37 to 3 with the H-1/H-2 fixes, software/ucemu/README.md) |
Python | a report, not pass/fail |
5. Hardware tests, summarised (what the machine has proven so far)¶
| Date | Test | Result | Where |
|---|---|---|---|
| 2026-09-18 | memory card map, boot remap, ROM capture | jumper map as designed; chip = the 2021 sources | tests/memory/memory_status.py, firmware/rom/eprom-captured-2026-09-18.* |
| 2026-09-18 | video write-through fault | reproduced | tools/alias_min.py |
| 2026-09-21 | full memory test | 14/14, 53,248 cells x 2, 0 bad | tests/memory/full-run-2026-09-21.log |
| 2026-09-21 | video RAM after the +5V/VCC join | 8/8 quick and full | tests/video/README.md |
| 2026-09-21 | sequencer boot, bus quiet, then Sequencer4 | RAM == EEPROM == test.hex, READY 54 s | tests/sequencer/*.log |
| 2026-09-21 | switch-ROM ledcount on the CPU (ALU + one register card, function-generator clock) |
executes as expected | MACHINE.md |
| 2026-09-22 | microcode reload (BRUR, H-1, H-2), boot-check | all 256 sent, boot dumps == test.hex | tests/sequencer/boot-run-mode-2026-09-22-reload.log |
| 2026-09-22 | romcount first build, then romdiag |
found register card 1 missing (stage 2/9 = FF); card fitted | tests/assembler/romcount/README.md, romdiag/README.md |
| 2026-09-22/23 | romcount (R3/TMP build) overnight from ROM |
counting without a fault | MACHINE.md |
Still owed on the bench (BACKLOG, MACHINE.md): a rom_verify.py read-back of the chip burned 2026-09-23; the H-5
scope check on bus C3; the 6845 register-select fix on the video card. (brur and the ISA sweep
ran on the machine in tests/bench, 14/14 on 2026-09-23.)