The emulator and the test benches
When the board was no longer available, the project carried on on the PC: the same kernel, compiled for the desktop computer, around a simulated 6502. Then, piece by piece, the board’s hardware itself.
On this page
The principle: the real kernel, not an imitation
An ordinary emulator rewrites a machine’s behaviour. Eliott65’s does something else: it compiles the kernel sources, unchanged, for the PC, and replaces only the “platform” (a few hundred lines): the parts that, on the board, deal with the hardware.
The simulated 6502 is the 65C02 core from Phosphoneo, another emulator by the same author, copied as is. It has two decisive qualities:
- it produces one bus access per cycle, exactly like the real 6502 as seen by the PIO + DMA bus;
- it passes the SingleStepTests suite: 50,800 cases, 254 instructions, 100%.
First attempt: the start-up program displays just as on the board, and 4.1 seconds of machine time are simulated in 0.24 seconds. With a virtual USB stick, the shell starts on its own and runs three processes with pre-emption.
The benches: the board’s hardware, simulated
What the first emulator did not cover remained: the PIO, the DMA, the video, the USB. Three benches added it.
The bus
A PIO interpreter runs the real bus program, with a model of the DMA and the three buffers, and the 6502 timings measured on the board. Compared against the eight settings measured on the board, the model gives the same successes and the same failures, for the same reasons, and speeds within 1%.
The video
The real DVI driver runs on the PC, with a model of its DMA and PIO, and a simulated screen decodes the signal produced. Result: a signal compliant with 640 × 480, and 0 pixels different from the expected image on the test pattern, the start-up screen and the shell. A single bit deliberately flipped is duly detected.
An instructive obstacle: on a 64-bit PC, the driver’s line list (pointers) took 8 bytes per entry, whereas the RP2040’s DMA reads 32-bit words. Rather than “cheating” with the driver, the emulator is compiled as 32-bit.
The USB
The real USB driver runs inside a model of the RP2040’s USB controller, facing devices simulated from the board’s log: hub, low-speed keyboard and mouse, a fast USB stick backed by a disk image. The shell is loaded from the simulated USB stick and driven from the simulated USB keyboard.
This bench found a real flaw: a single read error while loading the shell stopped it from starting. It also makes it possible to plug in, move and yank out devices while running, including in the middle of a write.
True to the board?
When the board came back, a tool played the same scenarios on both sides:
- a calculation program (binary and decimal additions and subtractions with their flags, comparisons, shifts): 28,416 bytes of identical results, byte for byte;
- the shell screens: 30 lines out of 30 identical;
- the USB driver log: 19 lines out of 19 identical.
Timing, on the other hand, was calibrated on the board’s measurement (7.20 MHz), not predicted: the project states it that way. The bus model, which ignores competition from the video, gave 2.9% too much. At 270 MHz it was re-calibrated on the new measurement (7.716 MHz, zero difference), then set to a predicted speed (7.494 MHz) after the bus fix. The board then measured 7.707 MHz: the emulator now runs at that speed (v0.59.1). The same model served as an investigation tool: see The bus.
The window
A second executable opens a window (SDL2): the live screen, and the PC’s real keyboard, converted into USB reports and passed through the virtual USB keyboard. It runs in real time: 3.12 s for 3 s simulated.
The screenshots in this wiki come from this emulator.
The debugger (v0.56)
The emulator can also watch a 6502 program run. These tools only switch on when asked for: without them, nothing changes or slows down.
- Symbols from the 64tass assembler, produced with each program: addresses are shown by name
(
JSR $10BB ; e65_quitter). - A trace of every instruction (cycle, process, address, instruction, registers), between two bounds.
- Breakpoints, on an address or a symbol, optionally for a single process.
- A watch: a stop as soon as a byte of memory changes.
- A console: single step, continue, registers, memory, disassembly, symbols; it can also be driven by a script.
The disassembler is the one from Phosphoneo’s 65C02 core.
What the emulator does not claim to do
- It does not model the competition between the video and the bus for the DMA, nor the spread of timings from one chip to another.
- The simulated USB is 3 to 4 times faster than the real USB stick: the waits of the stick and its flash are not modelled, and the project does not know how much is due to each.