One-Hour 20 MHz Z80 Arithmetic and SRAM Soak Test¶
This diagnostic makes the physical Z80 execute and check its own workload from SRAM, while the Pico supplies a scope-measured 20 MHz clock, receives result reports and supervises a one-hour run. It is not a Pico simulation of the Z80, an empty clock loop, or a test of only one SRAM address.
The workload combines 16-bit arithmetic and flags, signed and unsigned comparisons, software multiplication, nested loops, subroutine calls, stack traffic and repeated write/read/compare sweeps of a 56 KiB work area.
There are two separately built durations. The original one-hour target remains
unchanged in behavior; z80_stage06_math_soak_14h_20mhz runs the same resident
workload for at least 14 hours, then finishes on a complete four-pattern
cycle. Unless specified otherwise, the examples below describe the one-hour
target.
| Property | Configuration |
|---|---|
| Firmware target | z80_stage06_math_soak_20mhz |
| Z80 program | Resident assembly starting at 0000h |
| Z80 clock | 20,000,000 Hz scope-measured on the project prototype; 50% duty configured |
| Pico system clock | 120 MHz |
| Minimum run | 3600 seconds of execution-phase elapsed time |
| Completion boundary | A complete four-pattern cycle |
| Arithmetic corpus | 128 operand pairs, repeated 16 times per phase |
| SRAM work area | 2000h-FFFFh, 57,344 bytes |
| Result channel | Z80 OUT (06h),A |
| Stop policy | First detected mismatch, control fault or progress timeout |
| Operator start | USB serial with DTR, then f + Enter |
A passing soak is functional evidence under the tested conditions, not an analogue timing qualification or a guaranteed system rating. The earlier full-64-KiB frequency screen is a separate test and remains useful.
Sources and related documentation¶
The maintained implementation, rather than the explanatory examples here, is authoritative:
- Z80 assembly entry: math_soak.asm
- Shared checked workload: math_workload.asm
- Pico controller: math_soak_test.c
- Reference answers and memory layout: math_soak_program.h
- Assembly and embedding rules: CMakeLists.txt
- Hardware I/O trap: io_trap.c
- Buffered data-bus access: bus.c
See also the Phase 6 SRAM bring-up specification and frequency-qualification plan. The full text of this README is also included in the MkDocs soak-test page.
For uninterrupted clock/SRAM captures, use the separate no-I/O 20 MHz scope diagnostic. It selects the same checked assembly workload but stores results in SRAM instead of using OUT; retrieval occurs only after stopping, with no live or timed PASS. It does not replace or alter this one-hour soak.
Hardware, power and clock prerequisites¶
This is for the current breadboard circuit with all eight active packages:
- Raspberry Pi Pico 2 W.
- Z84C0020PEC Z80.
- AS6C1008-55PCN SRAM; grounded A16 selects the accessible lower 64 KiB.
- SN74HCT32N fixed logic.
- SN74AHCT244N control/clock buffer.
- SN74AHCT245N Pico-to-Z80 data buffer.
- SN74LVC245AN Z80-to-Pico data buffer.
- SN74LVC244AN control/port monitor.
Complete the earlier wiring, isolation, assisted-loading and clock-speed checks before using this soak. The historical PCB is not equivalent to this circuit.
Every installed 5 V IC must be powered. Apply external 5 V before USB; disconnect USB before removing external 5 V. Do not flash a populated board on USB power alone. Do not change wiring or insert/remove ICs while powered.
Only this isolated diagnostic chain opts into the 20 MHz limit. Before USB
initialization, with Z80 reset asserted, it configures PLL_SYS with a 1200 MHz
VCO and post-dividers 5 and 2, giving 120 MHz clk_sys. PWM uses integer
divider 1 and period count 6, with three counts HIGH and three LOW. USB keeps
its separate 48 MHz PLL. No supervisor-clock retuning occurs during execution.
The controller refuses to start if the system clock is not 120 MHz or the selected PWM clock is not 20 MHz. Displayed frequencies are nominal configured values, not oscilloscope measurements.
Loading and memory layout¶
The Pico first builds an 8192-byte resident image containing assembled Z80 instructions, reference records and initialized stack space. The Z80 itself writes and reads this image using the existing slow, instruction-injected loader. Every image byte is verified before free-running execution starts. The Pico never drives the SRAM address bus or masters SRAM writes.
The Z80 is then reset to start at 0000h. Its program disables maskable
interrupts with DI and sets SP to 2000h. There is no CP/M, BDOS, UART
driver or DCC-generated startup code involved in this diagnostic.
| Address range | Purpose during the soak |
|---|---|
0000h-0FFFh |
Reserved code region, including the pattern and repeats state bytes |
1000h-19FFh |
128 reference records, 20 bytes each |
1A00h-1FFFh |
Stack reserve, initially filled with A5h |
2000h-FFFFh |
56 KiB destructive SRAM work area |
The stack grows downward from 2000h. The byte at 1A00h is checked as a
lower guard. The code uses only part of its reserved region and only part of
the stack reserve.
The work-area sweeps do not overwrite the code, reference table or stack. Those regions receive instruction fetches, table reads and stack accesses, but are not exhaustively swept at 20 MHz. The physical SRAM's inaccessible upper 64 KiB is not tested.
Overall execution loop¶
The Z80 stays resident and repeats this sequence without reloading:
repeat:
for pattern = 0, 1, 2, 3:
check nested calls, saved registers, stack pointer and stack guard
repeat 16 times:
check all 128 arithmetic/reference records
check that the reference pointer reached the table end
check that the outer repetition count was exactly 16
fill every work-area byte with this pattern
read every work-area byte and compare with the expected pattern
report successful completion of this phase through OUT port 06h
One phase includes all of the above checks for one SRAM pattern. Four phases form one cycle. The Pico, not the Z80 program, measures the hour and stops execution at a completed-cycle boundary.
Arithmetic and comparison workload¶
Operand corpus and independent expected answers¶
The first 64 operand pairs are the Cartesian product of these eight values:
0000h 0001h 0FFFh 7FFFh 8000h 8001h 5555h FFFFh
These exercise zero, carries, the bit-11/bit-12 half-carry boundary, signed
limits and alternating data bits. The remaining 64 pairs come from a
deterministic 32-bit xorshift generator seeded with 5A801337h.
The Pico calculates expected results with wider C arithmetic before loading the image. The Z80 performs the actual calculations independently and compares against the stored answers. It does not generate its expected answer by repeating the same Z80 operation.
The corpus is fixed and repeatable: the test does not generate fresh random operands on every cycle. Each phase executes 128 pairs 16 times, giving 2048 complete vector checks per phase.
Eleven assertions for each operand pair¶
For each 16-bit pair a, b, the Z80 checks:
| Check | Z80 operation | Assertions |
|---|---|---|
| Addition | ADD HL,DE |
Result and applicable flags |
| Addition with carry-in 1 | SCF; ADC HL,DE |
Result and flags |
| Subtraction with borrow-in 0 | OR A; SBC HL,DE |
Result and flags |
| Subtraction with borrow-in 1 | SCF; SBC HL,DE |
Result and flags |
| Multiplication | 16-step shift/add subroutine | Low 16-bit result |
| Unsigned ordering | Subtract, then branch on zero/carry | Less/equal/greater code |
| Signed ordering | Subtract, then branch on zero/sign/overflow | Less/equal/greater code |
Four result checks plus four flag checks plus multiplication and two ordering checks make 11 logical assertions. A checked 16-bit value counts as one assertion even though its low and high bytes are compared separately.
All arithmetic results wrap modulo 65536. The comparison codes are FFh for
less than, 00h for equal and 01h for greater than.
Flag checks¶
For ADD HL,DE, mask 13h checks half-carry, subtract and carry. It does not
check preservation of sign, zero or parity/overflow for this instruction.
For ADC HL,DE and SBC HL,DE, mask D7h checks:
- S: sign, from bit 15.
- Z: zero across the entire 16-bit result.
- H: carry/borrow across the bit-11/bit-12 boundary.
- P/V: signed overflow, not the parity of the result.
- N: whether the operation is subtraction.
- C: unsigned carry or borrow.
Undocumented flag bits 3 and 5 are deliberately excluded. The assembly saves
AF with PUSH AF, then uses POP HL to recover the saved flag byte in L
after checking the arithmetic result.
Examples of cases covered by the corpus:
FFFFh + 0001h -> 0000h, carry set
7FFFh + 0000h + 1 -> 8000h, signed overflow set
0000h - 0000h - 1 -> FFFFh, borrow set
8000h compared with 7FFFh:
unsigned: greater
signed: less (-32768 versus +32767)
Signed ordering uses sign XOR overflow, not sign alone. The branch paths explicitly handle overflow and equality, so a result with its sign bit set does not automatically mean the original signed operand was smaller.
Multiplication and loop invariants¶
There is no native Z80 multiply instruction in this workload. A subroutine
shifts the 16-bit multiplier right using SRL B and RR C. If the shifted-out
bit is one, it adds the multiplicand to the accumulator. It doubles the
multiplicand with ADD HL,HL, exchanging DE/HL as needed, and repeats 16 times.
Only the low 16 product bits are checked; this is not a full 32-bit product or a multiply-overflow test.
After each 128-record pass, the Z80 checks that IX reached 1A00h, immediately
after the reference table. After the 16 repetitions, it checks that IY equals
16. These add 17 loop-bound assertions per phase.
Subroutine and stack checks¶
Each phase loads HL=1357h, DE=2468h, BC=5FAAh, then makes 16 recursive
CALL levels. Each level pushes BC, DE and HL and restores them before RET.
The recursion stops when the low nibble of B becomes zero.
The subsequent assertions check:
- HL was restored to
1357h. - DE was restored to
2468h. - BC was restored to
5FAAh. - SP equals
1FFChinside the stack-test subroutine: two return addresses are active at that point, one for the phase and one for the stack test. - The lower guard byte at
1A00hremainsA5h.
This exercises return-address storage, descending SRAM stack writes, ascending reads, PUSH/POP order and register preservation. It does not scan every byte of the stack reserve or exhaustively prove every possible stack fault.
In addition, pattern_byte is called for every work-byte write and every
work-byte verification. Stack traffic therefore continues throughout the
SRAM sweeps, not just during the explicit recursive check.
SRAM write/read/compare patterns¶
Every phase fills all 57,344 bytes from 2000h through FFFFh before
starting verification. Verification recomputes the expected byte and reads
the entire area in ascending address order. Address-pointer wrap to zero
ends the sweep, including the last address FFFFh.
| Phase | Expected byte at address ABCDh |
Success marker |
|---|---|---|
| 0: low address byte | CDh |
40h |
| 1: high address byte | ABh |
41h |
| 2: complemented low byte | 32h |
42h |
| 3: complemented high byte | 54h |
43h |
The complementary patterns exercise both states of each data bit. Combining low- and high-address patterns helps expose address aliasing. Filling the whole area first avoids relying only on an immediate write/read to one location. This is not a complete March algorithm, an exhaustive coupling-fault test or a separate long-retention test.
Z80 instructions exercised¶
The table describes the actual resident assembly, including supporting instructions. Being exercised is not the same as having every flag, operand combination or possible failure mode exhaustively checked.
| Instruction/forms | Role in this program |
|---|---|
LD r,r, LD r,n |
Operand movement, expected values, counters and report fields |
LD BC,nn, LD DE,nn, LD HL,nn, LD SP,nn |
Register-pair and stack initialization |
LD IX,nn, LD IY,nn |
Reference-table pointer and repetition counter |
LD r,(IX+d) |
Indexed reads of operands, reference results and flags; displacements 0-19 |
LD (HL),A, LD A,(HL) |
Work-area writes and verification reads |
LD (nn),A, LD A,(nn) |
SRAM-backed loop state and stack-guard access |
ADD HL,DE, ADC HL,DE, SBC HL,DE |
Checked 16-bit arithmetic |
ADD HL,HL, ADD HL,SP, ADD IX,DE |
Multiplicand shifting, SP observation and record-pointer advancement |
ADD A,n, SUB B |
Progress-marker formation and failure-vector index encoding |
INC HL, INC IY, INC A, INC C |
Address progression, repetitions, ordering codes and check stages |
DEC A, DEC B |
Multiplication/repetition/vector/recursion loops and ordering codes |
AND n, OR A, OR L, OR n, XOR A |
Flag masks, carry clearing, zero tests and marker/phase setup |
CP D, CP E |
Byte comparisons for work data and 16-bit expected values |
SCF, CPL |
Carry/borrow input setup and complemented SRAM patterns |
BIT 0,C, BIT 1,C |
Select low/high address bytes and complement behavior |
SRL B, RR C |
Shift the 16-bit multiplier, propagating bits through carry |
EX DE,HL |
Swap multiplicand and accumulator during multiplication |
PUSH AF/BC/DE/HL/IX/IY |
Save flags, registers, pointers and comparison values |
POP BC/DE/HL/IX |
Restore saved values or transfer them through the stack |
CALL, RET, RET Z |
Recursion, arithmetic/check helpers and pattern selection |
JR, JR Z/NZ/C/NC |
Relative loops and conditional decision paths |
JP, JP NZ/PE/M |
Cycle/vector loops, sign/overflow decisions and mismatch exits |
OUT (n),A |
Success markers and multi-byte failure packets |
DI |
Disable maskable interrupts at program startup |
HALT |
Failure path only; Pico reset may stop execution before it reaches HALT |
The workload includes ordinary, CB-prefixed, ED-prefixed and DD/FD-prefixed instructions. For example, CB provides bit/shift operations, ED provides 16-bit ADC/SBC, and DD/FD provide IX/IY operations.
It does not exercise IN, DJNZ, LDIR/other block instructions,
EXX, alternate-register-bank checking, BCD/DAA, division, every
indexed addressing mode, or interrupt-service/acknowledge behavior. DI is
executed, but interrupt masking is not verified by injecting interrupts.
Failure-packet instructions and HALT are not part of the normal passing loop.
How results reach the Pico through OUT port 06h¶
The Z80 performs the checks. The Pico receives compact completion reports; it does not reread every SRAM byte or redo every calculation during the soak.
Success reports and the hardware handshake¶
After a successful phase, the Z80 executes the equivalent of:
ld a,040h ; Phase 0 complete
out (06h),a
This is an I/O transaction, not a write to SRAM address 0006h.
- The Z80 drives the port address and D0-D7 data, asserting IORQ#
(I/O request) and WR# (write).
#means active LOW. - With Pico IO_RELEASE LOW, HCT32 logic asserts WAIT# using
WAIT# = IORQ# OR IO_RELEASE. The I/O transaction is held for the Pico. - Buffered IORQ# interrupts the Pico. Its handler stops PWM, allows settling, samples the port through the LVC244 monitor and validates the controls.
- The Pico keeps the upward data driver disabled, enables the downward LVC245 path and reads the byte safely at 3.3 V logic levels.
- The receive callback validates the port and marker order. Expected markers
are
40h,41h,42h,43h, repeating; each credits one complete phase. - The trap raises IO_RELEASE and completes the transaction using controlled single clock cycles until IORQ# and WR# release. It isolates both data paths, lowers IO_RELEASE and resumes PWM.
Only A0/A1/A2/A4 are decoded (address & 17h). OUT (n),A also presents A on
the high address byte, but this circuit ignores those bits. Thus sending
40h to port 06h is still decoded as 06h, not a distinct 4006h service.
The brief I/O reporting pauses are included in execution-phase elapsed time. Memory accesses have no added wait states. During memory cycles IORQ# is HIGH, keeping the HCT32 WAIT# output HIGH.
No IN is needed. An unexpected I/O read or out-of-order/invalid report is a
protocol fault, not a valid success.
Failure packet and check-stage identifiers¶
A detected mismatch sends nine bytes, each with a separate OUT (06h),A:
| Byte position | Meaning |
|---|---|
| 0 | E1h, start of failure packet |
| 1 | Check-stage identifier |
| 2 | Vector index or diagnostic context |
| 3, 4 | Relevant address, low byte then high byte |
| 5, 6 | Actual 16-bit value, low byte then high byte |
| 7, 8 | Expected 16-bit value, low byte then high byte |
| Stage, hexadecimal | Failed check |
|---|---|
01, 02 |
ADD result, flags |
03, 04 |
ADC with carry-in 1 result, flags |
05, 06 |
SBC with borrow-in 0 result, flags |
07, 08 |
SBC with borrow-in 1 result, flags |
09 |
Low-16-bit multiplication result |
0A, 0B |
Unsigned, signed ordering code |
0C, 0D, 0E |
Restored HL, DE, BC |
0F |
Stack-pointer recovery |
10 |
Lower stack guard |
11 |
Reference-table end pointer |
12 |
Outer repetition count |
80, 81, 82, 83 |
SRAM pattern 0, 1, 2, 3 |
Arithmetic records use vector indices 0-127; their address identifies the
20-byte reference record, not a work-area byte. RAM errors use index FFh
and report the failing work address; their actual/expected byte occupies
the low byte of each value. Structural/stack indices are context only:
their address field reflects IX and does not necessarily identify a failing
stack location. For example, stack-guard stage 10 identifies the fixed
guard at 1A00h even though the reported IX points at the reference table.
The assembly contains HALT after the packet. Once the Pico receives the complete packet, it prints the details, asserts RESET and stops PWM; reset may preempt HALT. A partial packet also fails on the progress timeout.
Statistics and what the displayed numbers mean¶
The Pico generates PROGRESS and STATS over USB serial every ten seconds.
The host logger adds the UTC timestamp and SERIAL prefix. The Z80 does not
format or transmit those text lines, nor does it send one OUT per assertion.
For p completed phases:
| Field | Formula |
|---|---|
completed_math_vectors |
p * 2048 |
sram_byte_checks |
p * 57344 |
math_assertions |
p * 2048 * 11 = p * 22528 |
stack_checks |
p * 5 |
loop_checks |
p * 17 |
successes |
Sum of the four check categories: p * 79894 |
completed_cycles |
Integer division p / 4 |
failures |
0 until a detected failure; first-failure stop reports 1 |
Counters credit only completed phases. Successful operations in a partially completed phase are not counted. Counts are logical checks, not CPU instructions, clock edges or unique memory addresses.
For example, this is a progress sample, not a final one-hour PASS:
PROGRESS: actual=20000000Hz pwm_ms=340010 phases=365 completed_math_vectors=747520
STATS: successes=29161310 failures=0 sram_byte_checks=20930560 math_assertions=8222720 stack_checks=1825 loop_checks=6205 completed_cycles=91
It represents 5 minutes 40.010 seconds, 365 phases, 91 full cycles plus one phase, and 29,161,310 completed assertions with no detected failure. Advancing 10 or 11 phases between ten-second reports is normal; reporting and phase boundaries are independent.
actual is nominal selected PWM frequency. pwm_ms is elapsed time since
the execution phase began, excluding initial loading/verification but
including the brief trapped-I/O pauses. It is not a count of only the
intervals when PWM was enabled. A timestamp ending in Z is UTC.
Completion, failures and incomplete runs¶
A valid completed run requires:
- At least
3600000milliseconds of execution-phase elapsed time. - A complete four-pattern cycle at the stop boundary.
- No pending failure packet, protocol error, control fault or progress timeout.
- The final
PASSand zero-failure statistics.
The final line has this shape; elapsed milliseconds and totals vary by run:
PASS: one-hour soak complete (functional, not timing qualification); actual=20000000Hz pwm_ms=<at-least-3600000>; RESET# LOW
STATS: successes=<total> failures=0 sram_byte_checks=<total> math_assertions=<total> stack_checks=<total> loop_checks=<total> completed_cycles=<total>
The Pico fails closed on loader/image/clock errors, CPU-reported mismatches, malformed reports and I/O control faults. A five-second lack of phase progress, or an incomplete failure packet that times out, also fails. Some shared trap faults fail closed and reboot; any reboot invalidates the current run rather than automatically resuming it.
x or a console disconnect produces an incomplete STOP, not a PASS.
An operator abort/disconnect does not increment the mismatch failure count;
therefore failures=0 alone does not prove completion. Reconnecting never
automatically starts or resumes the soak.
After completion, failure or abort, the firmware asserts RESET, stops PWM and isolates both Pico data paths. A stopped PWM output must not be assumed to be physically LOW without measurement.
Build, flash and run¶
All commands below run from the repository root. Do not flash or reopen the serial port during an existing soak unless intentionally ending it.
Fourteen-hour variant¶
Build in a separate directory to retain the previous one-hour firmware:
cmake -S . -B build/soak14h -G Ninja -DPICO_BOARD=pico2_w
cmake --build build/soak14h --target z80_stage06_math_soak_14h_20mhz
UF2:
build/soak14h/src/stage06_sram_dma/z80_stage06_math_soak_14h_20mhz.uf2
Use this UF2 instead of the one-hour image in the flash procedure below.
The banner must say starts 14 hours, and RUN must report minimum=50400s.
f starts a fresh 14-hour run; there is no live duration-change command.
The final PASS requires at least 50,400,000 ms, zero failures and a
complete four-pattern cycle. Success text begins PASS: 14-hour soak complete.
All arithmetic, SRAM coverage, port reporting, error stops and counters are
identical. Totals use 64-bit arithmetic; successful checks can exceed
4,294,967,295 during this longer run. Keep external power and USB stable
and prevent the host from sleeping for the entire run. On macOS, a logger
can use caffeinate -i -w <logger-PID> to prevent idle sleep for its lifetime;
keep a laptop's lid open and its power connected. Closing a read-only log
viewer does not stop the serial owner, but closing the serial connection
invalidates the run.
Expected 14-hour completion summary¶
The following table summarizes the recorded passing run of 19-20 October
2026. It is a human-readable example of the expected completion report,
not a table printed by the Pico firmware: the firmware emits PASS and
STATS, while the host logger records start/finish times and serial state.
Future runs will have different dates, elapsed time and totals. Require
at least 14 hours, zero failures, a complete four-phase cycle and a final
PASS rather than an exact match to these counts.
| Metric | Result |
|---|---|
| Overall result | PASS |
| Z80 clock | 20 MHz, scope-measured on the project prototype |
| Started | 19 October 2026, 18:40:12 AEDT |
| Finished | 20 October 2026, 08:40:14 AEDT |
| Recorded execution time | 14 hours, 1.738 seconds |
| Total successful checks | 4,332,172,256 |
| Failures | 0 |
| SRAM byte comparisons | 3,109,421,056 |
| Arithmetic assertions | 1,221,558,272 |
| Completed arithmetic test vectors | 111,050,752 |
| Stack checks | 271,120 |
| Loop checks | 921,808 |
| Complete four-phase cycles | 13,556 |
| Completed phases | 54,224 |
| Final RESET# | LOW - CPU held in reset |
| Final PWM clock | Stopped |
| Serial connection | Closed |
AEDT is UTC+11. The recorded execution time comes from
pwm_ms=50401738, not subtraction of the rounded wall-clock timestamps.
As described above, it includes brief I/O-trap pauses. This PASS establishes
functional endurance for the tested CPU/arithmetic/stack/SRAM workload;
it does not establish electrical timing margins or qualify CP/M and
disk I/O at 20 MHz.
Build the isolated target¶
Use the project's firmware toolchain setup with CMake, Ninja, Pico SDK and Arm GNU tools available:
cmake -S . -B build/pwm17-20 -G Ninja -DPICO_BOARD=pico2_w
cmake --build build/pwm17-20 --target z80_stage06_math_soak_20mhz
Generated firmware:
build/pwm17-20/src/stage06_sram_dma/z80_stage06_math_soak_20mhz.uf2
The build assembles the maintained Z80 source and embeds it in the Pico application. A build-time size check prevents code overlapping the reference table. The normal firmware's clock limit remains unchanged.
Flash only with all ICs powered¶
Close any existing serial console/logger after its run has finished. With external 5 V applied before USB, identify the intended Pico:
picotool info -a
Normal-mode identification can return a nonzero status while listing the USB-connected Pico; that is not a flash-verification result. If exactly one intended Pico is connected, flash, verify and boot:
picotool load -v -x \
build/pwm17-20/src/stage06_sram_dma/z80_stage06_math_soak_20mhz.uf2 -f
If multiple devices are attached, select the intended device with picotool's
--bus and --address options from its current identification output; do
not assume USB addresses remain constant. Require verification success.
Booting the firmware does not start the destructive test.
Start from a serial console¶
Connect USB serial with DTR asserted. A typical macOS port and command are:
picocom -b 115200 /dev/cu.usbmodem1101
Choose the actual device path on your machine. USB CDC does not use the 115200 setting as a physical Z80 timing reference.
Check the banner:
20MHz math/SRAM soak ready; f + Enter starts one hour; x aborts immediately.
Pico clk_sys=120000000Hz; nominal PWM=20000000Hz, not measured.
That banner reports the firmware's PWM target and does not include a physical measurement. The project prototype's Z80 clock has independently been measured at 20 MHz with an oscilloscope.
| Command | Action |
|---|---|
f + Enter |
Load/verify the image, then start a fresh one-hour run |
h + Enter |
Show help |
s + Enter |
Show state and current statistics |
x immediately |
Abort without waiting for Enter |
An abort discards the rest of its input line; press Enter before a subsequent command. Expect LOAD, then RUN, then progress/statistics roughly every ten seconds. Keep external power and USB connected throughout.
View live results without disturbing the serial owner¶
Only one process should own the serial connection. If a logger already owns it, do not open picocom as a second reader: changing DTR or disconnecting can invalidate the run.
Instead, open a foreground terminal that follows the logger's actual file:
tail -n 20 -F /path/to/captured-soak.log
Use the real log path printed by the active logger. Ctrl+C in this read-only
viewer stops the viewer only; it does not send x or stop the soak. Commands
must go through the process owning the serial connection. Keep the host awake
and retain the final PASS/FAIL and statistics, not just an early sample.
For reproducible evidence, record the firmware SHA-256, board/rail conditions, configured clocks and complete timestamped serial output. Do not turn a failed/interrupted attempt into a pass by silently restarting and discarding its earlier evidence.
Host validation¶
The controller tests check DTR/manual-start gating, image loading, clock rejection, abort, disconnect, failure reporting, protocol/control faults and progress timeouts. Simulated time verifies the exact hour boundary, complete-cycle requirement and statistics without waiting a physical hour.
The instruction-execution test uses the container's C Z80 emulator. It runs the actual generated resident image through two complete cycles: eight phases, 16,384 vector checks and all four SRAM patterns twice. It independently checks the final work bytes after each phase, reference-table preservation and the stack guard.
Fault injection corrupts each arithmetic-result/flag/comparison expectation,
the stack guard, and the first/middle/last work addresses (2000h, 8000h,
FFFFh). These cases must produce the correct failure packet without a
phase-success marker.
Run the controller tests natively and the instruction tests in the Apple container:
cmake -S src/common/tests -B build/host-control -G Ninja
cmake --build build/host-control --target math_soak_test math_soak_14h_test
ctest --test-dir build/host-control -R '^math_soak_' --output-on-failure
python3 scripts/z80_container.py test
The container requirements are described in firmware testing. These checks do not access or interrupt a physical board.
Host success is not a physical one-hour result. Likewise, a physical soak does not replace scope measurements, full instruction-set conformance, interrupt/I/O-read testing, repeated cold starts or testing across voltage and temperature conditions.
VS Code tasks¶
Choose Tasks: Run Task in the Z80ROMlessSBC workspace.
| Diagnostic | Build task | Deployment task |
|---|---|---|
| Phase 6 one-hour 20 MHz soak | Build Pico - Phase 6 one-hour 20 MHz soak | Flash Pico - Phase 6 one-hour 20 MHz soak |
| Phase 6 14-hour 20 MHz soak | Build Pico - Phase 6 14-hour 20 MHz soak | Flash Pico - Phase 6 14-hour 20 MHz soak |
Deployment tasks force-update without checking the previous firmware phase. Complete this phase's hardware prerequisites and save work before flashing. See Pico tools.