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.

CoreChecked againstPrograms in the latest recordDifferences
Arm Cortex-M, six versions (M0 to M33)Unicorn 2.1.4120,000 (11,960,000 over all recorded runs)0
Arm Cortex-R5 and R52Unicorn 2.1.4 and QEMU 10.0.1334,0000
ESP32 and ESP32-S3 (Xtensa)Espressif's QEMU60,0000
RISC-V (RV32)Unicorn 2.1.4 and QEMU60,0000
MIPS, Renesas RX, RL78 and RH850, Infineon TriCoreUnicorn, QEMU or the GNU simulator4,000 to 100,000 per core0

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.

BoardWhat we comparedMatchedExplainedUnexplained
Arduino Uno clone (ATmega328P)15 test programs, including 2,062 random instruction blocks with cycle counts, and 3 unmodified Arduino examples6,036 of 6,080 lines440
Arduino Mega 2560 clone (ATmega2560)12 test programs, including 1,700 random instruction cases, and the same 3 examples4,642 of 4,660 lines153 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 report689 of 711 lines1, and 21 lines the comparison skips by design0
Raspberry Pi Pico (RP2040)Unmodified hello_usb and hello_timer, a register report431 values6, and 6 skipped0
Raspberry Pi Pico 2 (RP2350, Arm)Unmodified hello_usb and hello_timer, a register report310 values2, and 3 skipped0
NUCLEO-F767ZI (STM32F767)Reset values of 2,117 registers; 4,505 register write and read steps2,086 and 4,50131 and 40
Arduino UNO Q (STM32U585)Register reset values and write and read steps together13,426 of 13,6502240
Adafruit Qualia (ESP32-S3)3,783 registers in ROM mode; a 59-line test program3,542; 40 lines241; 9, plus 10 lines where the chip disagrees with itself between runs0
PJRC Teensy 4.1 (i.MX RT1062)A register report and two PJRC examples599 lines110, and 19 skipped0

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:

PartReset values right, from documents alone
STM32F767ZI1,914 of 2,082
STM32U5853,306 of 4,072
ESP32-S32,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