Accuracy report
What we check our twins against, how many cases we ran, and where the twins still differ from real chips. The gaps are listed as plainly as the passes.
How to read this page
- Every number comes from a dated evidence file in our product repository. Each file records how its runs were made, and most record the source revision too. The file names are under Sources.
- The records are from October and November 2026. Our code has changed since, and the runs have not been repeated on today's code. Each section shows the latest record.
- We only claim what firmware can see: instructions, registers, memory, interrupts, pins, buses, timers and console output. We do not claim analog values, radio, power, heat, mechanics or exact timing.
- When a real board and its twin differ for a known reason, such as a calibration byte that is unique to each chip, we call that line explained. An explained line is still a difference. It is never counted as a match.
The labels verified, provisional and unsupported are explained in Core concepts.
Processor cores
We run the same random programs on our processor core and on an independent simulator, then compare every register, flag, memory write and fault. To show the check works, we plant a bug in our core and confirm that the comparison catches it.
| Core | Checked against | Programs in the latest record | Differences |
|---|---|---|---|
| Arm Cortex-M, six versions (M0 to M33) | Unicorn 2.1.4 | 120,000 (11,960,000 over all recorded runs) | 0 |
| Arm Cortex-R5 and R52 | Unicorn 2.1.4 and QEMU 10.0.13 | 34,000 | 0 |
| ESP32 and ESP32-S3 (Xtensa) | Espressif's QEMU | 60,000 | 0 |
| RISC-V (RV32) | Unicorn 2.1.4 and QEMU | 60,000 | 0 |
| MIPS, Renesas RX, RL78 and RH850, Infineon TriCore | Unicorn, QEMU or the GNU simulator | 4,000 to 100,000 per core | 0 |
The Arm comparison found 7 bugs in our core, all fixed. It also found 26 places where the reference itself departs from the Arm manual. Each one is written down with the rule it breaks.
Gaps
- Most of the 11,960,000 Arm programs were recorded without their source revision. Only 360,000, in three runs, are tied to a revision.
- On Cortex-M, interrupt entry, the interrupt controller and memory protection are not compared, because the reference does not model them.
- Cortex-M23 is checked against a Cortex-M33 model, because no M23 reference exists.
- RISC-V, MIPS, RX, RL78, RH850, TriCore, MSP430 and Power e200 results are provisional. The references differ from the vendor manuals in places, and for Power e200 the reference is a different core.
- PIC, 8051 and TI C28x have no independent reference. We check them against a second model we wrote ourselves and against the vendor's instruction tables. That is not independent.
- AVR has no software reference. It is checked only against real chips, below.
Real boards
We run the same firmware on a real board and on its twin, then compare the output line by line or register by register. Nothing is attached to the boards except USB. Each board is one physical unit.
| Board | What we compared | Matched | Explained | Unexplained |
|---|---|---|---|---|
| Arduino Uno clone (ATmega328P) | 15 test programs, including 2,062 random instruction blocks with cycle counts, and 3 unmodified Arduino examples | 6,036 of 6,080 lines | 44 | 0 |
| Arduino Mega 2560 clone (ATmega2560) | 12 test programs, including 1,700 random instruction cases, and the same 3 examples | 4,642 of 4,660 lines | 15 | 3 in the first run (floating pins), explained afterwards |
| ESP32 dev board (ESP32-D0WD-V3) | ROM banner, unmodified ESP-IDF hello_world on one and two cores, a 592-line register report | 689 of 711 lines | 1, and 21 lines the comparison skips by design | 0 |
| Raspberry Pi Pico (RP2040) | Unmodified hello_usb and hello_timer, a register report | 431 values | 6, and 6 skipped | 0 |
| Raspberry Pi Pico 2 (RP2350, Arm) | Unmodified hello_usb and hello_timer, a register report | 310 values | 2, and 3 skipped | 0 |
| NUCLEO-F767ZI (STM32F767) | Reset values of 2,117 registers; 4,505 register write and read steps | 2,086 and 4,501 | 31 and 4 | 0 |
| Arduino UNO Q (STM32U585) | Register reset values and write and read steps together | 13,426 of 13,650 | 224 | 0 |
| Adafruit Qualia (ESP32-S3) | 3,783 registers in ROM mode; a 59-line test program | 3,542; 40 lines | 241; 9, plus 10 lines where the chip disagrees with itself between runs | 0 |
| PJRC Teensy 4.1 (i.MX RT1062) | A register report and two PJRC examples | 599 lines | 110, and 19 skipped | 0 |
On real processors, random instruction programs also agree: 5,500 of 5,500 on the NUCLEO-F767ZI and 900 of 900 on the UNO Q. On the Uno and Mega clones we planted bugs in the twin, and every one changed lines against the recorded chip output, so the comparison catches them.
The real chips changed our twins. For example, on the ATmega328P an interrupt request is sampled one cycle before the current instruction ends; on the ATmega2560 the RAMPZ register keeps 3 bits, where the data sheet names 2; on the RP2350 two bits of every memory-protection address register always read as one.
Gaps
- One unit per board. A value that only one chip shows may belong to that chip, not to the part.
- Some register values in the NUCLEO-F767ZI and UNO Q twins come from what the unit showed, with no document behind them. They match by construction.
- Most matching registers read zero on both sides. A matching reset value says nothing about what a peripheral does.
- Explained lines are still differences: analog levels, floating pins, per-chip calibration, what a boot loader leaves behind, memory that nothing wrote, and every time measurement on the NUCLEO-F767ZI.
- On the NUCLEO-F767ZI, 121 of 2,973 extra write and read steps on blocks outside the plan (advanced timers, SPI) differ. They are not fixed.
- The AVR, ESP32, Pico and Pico 2 results are verified for the lines listed only. The NUCLEO-F767ZI, UNO Q, Qualia and Teensy results are provisional: some values have no independent source, and the test suite that judged the NUCLEO-F767ZI was retired.
- Not compared on real chips: watchdogs, EEPROM writes, deep sleep modes, real analog inputs, and on the Pico boards PIO, DMA and the second core of the Pico 2.
Sensor twins and their drivers
We build firmware on unmodified driver code published for each part, by the chip maker or by a breakout-board maker, and run it against a twin we generated from the part's datasheet. The driver's own calls must succeed.
On 2026-10-24, 44 cases across 27 sensor and IC parts all behaved as specified:
- 18 run unmodified driver code and pass.
- 13 run driver code that breaks the datasheet, such as reading a result before the conversion has run. The twin follows the datasheet, so that firmware fails, as intended.
- 13 run the same driver code with that one step fixed, and pass.
Gaps
- No physical sensor was used. The reference is the driver and the datasheet. A driver that works on a real chip by timing luck fails on the twin.
- Parts outside these 27 are not checked this way. In one recorded proof run, 72 of 2,128 checked properties failed across 50 of 166 generated twins.
- A sensor reading is the number the twin reports in its registers, not a model of what the chip measures.
Generated microcontroller twins
We generate a twin from vendor documents without using a board's measurements, then compare its reset values with what the real chip reads:
| Part | Reset values right, from documents alone |
|---|---|
| STM32F767ZI | 1,914 of 2,082 |
| STM32U585 | 3,306 of 4,072 |
| ESP32-S3 | 2,924 of 3,372 |
We also ran 32 independent firmware images, such as Zephyr, vendor HAL and FreeRTOS examples, on generated twins: 24 pass, 4 are inconclusive, 3 did not run, and 1 fails (the MicroPython self-test on the STM32F407).
Gaps
- Three parts only, and most reset values are zero, so this says little about behavior.
Timing
Timing is functional by default: instructions do not cost their real cycle counts. A 1,000-step loop on the NUCLEO-F767ZI takes 18,054 cycles on the chip and 11,011 on the twin, 39% short. The optional estimate layer gives 16,039, 11% short, and misses its own accuracy targets. The AVR boards are the exception: their cycle counts were compared with the chip, as above.
Not covered
- Analog values, radio, power, heat and mechanics.
- Physics in the 3D world is a preview. A new physics engine is being compared with Project Chrono, a reference engine. It is not in the product yet, and agreeing with another engine is not agreeing with the real world.
What we left out
- Coverage counts. This page is about accuracy, not about how many parts we support.
- An earlier hardware check that found two bugs in an MPU6050 model. Its records are not in today's repository.
- Earlier summary percentages that cannot be reproduced from the records.
Sources
Evidence files in the product repository, under eval-results/:
- Processor cores: cpu-differential.json, isa-cortex-r-armr.json, isa-cortex-r-armr-sys.json, mips-differential.json, rx-differential.json, rl78-differential.json, rh850-differential.json, new-isas-tricore.json, new-isas-tricore-qemu.json, new-isas-ppc-e200.json, new-isas-msp430.json, new-isas-pic.json, new-isas-mcs51.json, isa-c28x-differential.json
- Real boards: board-avr-2026-10-24-step2.json, board-avr-mega2560-2026-10-25.json, board-esp32-*.json, board-pico-rp2040-*.json, board-pico2-*.json, board-nucleo-identical-2026-10-25.json and -2026-10-27.json, board-unoq-identical-2026-10-27-2.json, board-qualia-identical-2026-10-27.json, board-teensy41-identical-2026-10-28.json
- Sensor twins: twin-factory-oracles-2026-10-24.json, formal-twin.json
- Generated microcontroller twins: generator-confidence-2026-11-05.json
- Timing: cycle-model-2026-10-27-r3.json