# simavr: an AVR simulator that borrows its device list from avr-gcc

> simavr emulates Atmel AVR parts in C, loading ELF and HEX firmware directly and staying stable for devices with 128KB of flash or less. Its tracing feature adds zero bytes to your firmware, and PlatformIO starts it by default when you select a debug build.

**buserror/simavr** — simavr is a lean, mean and hackable AVR simulator for linux & OSX

- Repository: https://github.com/buserror/simavr
- Stars: 1,792 · Forks: 422
- Language: C
- License: GPL-3.0
- Published: 2026-10-16 · Updated: 2026-10-16 · Language: en
- Canonical page: https://hysenlabs.com/projects/buserror-simavr

## New targets come from avr-gcc's register definitions

Most simulators ship a device database that goes stale. simavr takes a different route: it uses avr-gcc's own register definition, and the stated reason is to simplify creating new targets for supported AVR devices. That is a design decision with a clear payoff. The compiler you already use is the authority on what registers a part has, so a part that avr-gcc supports is a part the simulator can plausibly emulate, and adding one is a matter of code rather than data authoring. The stated goal underneath is a core made to be small and compact, and hackable, so you can prototype an AVR project quickly. That is also the honest description of its ceiling: it is a parts simulator, not a board simulator with a display and a filesystem.

## Three install routes, and one is a plain make

On macOS the README recommends Homebrew with a tap from the osx-cross organisation:

```shell
brew tap osx-cross/avr
brew install --HEAD simavr
```

On Ubuntu it is in the Bionic package source:

```shell
apt-get install simavr
```

with a parenthetical note that the command is available as simavr, not run_avr. Otherwise make is enough to start using bin/simavr from the build tree, and to put the command system wide you run make install with RELEASE=1. That variable is the build switch worth understanding: the Makefile sets RELEASE to 0 by default and passes it down to every subdirectory, where the comments explain that a normal build links against the shared library in the current build tree, so you do not have to install anything to run simavr or the examples, while package building is the case that needs RELEASE=1. DESTDIR defaults to /usr/local and doubles as the PREFIX.

## Stable at 128KB of flash, preliminary above it

The stability statement is precise and is the limit to plan around. The AVR core is described as stable for use with parts with 128KB flash or less, with preliminary support for the bigger parts. The ATmega2560 sits in the second category, so if your product is built on one of them you should expect to find the edges yourself. Related scope limits are easier to read off the supported I/O list: EEPROM, the watchdog, I/O ports including pin interrupts, 8 and 16 bit timers in normal, CTC and fast PWM modes with the overflow interrupt, the UART with tx and rx interrupts and a loopback mode, SPI as master or slave with its interrupt, I2C as master or slave, external interrupts INT0 and onwards, the ADC, and self programming for bootloaders. The emulated core list covers the ATmega family from the 8 up to the 2560, several ATTiny parts, and the AT90USB162 with USB.

## Tracing costs zero bytes because the section is never linked

The built in logic analyzer is the feature that makes simavr worth the setup. Firmware declares which signals to trace with a special structure, marked with an _MMCU_ tag, and the example in the README traces the USART data register and its ready interrupt:

```c
const struct avr_mmcu_vcd_trace_t _mytrace[]  _MMCU_ = {
    { AVR_MCU_VCD_SYMBOL("UDR0"), .what = (void*)&UDR0, },
    { AVR_MCU_VCD_SYMBOL("UDRE0"), .mask = (1 << UDRE0), .what = (void*)&UCSR0A, },
};
```

That generates a trace every time UDR0 changes and every time the UDRE0 interrupt is raised. The cost argument is the part to remember: the _MMCU_ tag tells gcc the code needs compiling, but it is not linked into the program, so it takes literally zero bytes. It is a code section private to simavr. The output is a VCD file you open in gtkwave, down to the AVR cycle, and the README notes you can go further and feed a VCD file captured from a real logic analyzer back into the simulation, so hardware and simulation can be compared against the same visualisation.

## PlatformIO starts it for you; the Arduino path goes through PyAvrOCD

The integration list is the strongest argument for adoption, because most people meet simavr through a tool they already use. It is the default debugging tool for supported AVR MCUs in PlatformIO: select a debug build without specifying a tool and simavr is started. For the Arduino IDE 2 there is basic support through PyAvrOCD, where you install a debug enabled Arduino board package and choose the programmer simavr; the support covers assembly level debugging and a PERIPHERAL pane giving access to the I/O registers. A VS Code extension, the Arduino Maker Workshop, integrates simavr via the same PyAvrOCD and adds instruction level debugging, memory inspection and peripheral register display. PICSimLab includes it among the simulators it drives, and Simutron is a GUI for simavr that the README notes does not appear to be active. gdb support is described as fully working, including what the README calls passive modes.

## The examples directory is a board emulator catalogue

examples/ is the best argument that this is meant to be extended rather than merely used. Each board_* directory is a small board definition that emulates the parts a particular piece of hardware has: board_ds1338 for a real time clock chip, board_hd44780 and board_ssd1306 and board_sh1106 for character and graphical displays, board_i2cslave and board_usi_i2cslave and board_vhci for bus level work, board_ledramp and board_timer_64led for output patterns, board_rotenc for a rotary encoder, and board_simduino for the Arduino compatibility layer. There is also examples/parts/ for reusable peripheral pieces and a separate Makefile.opengl for the example that does OpenGL rendering of a display. The repository root is simavr/, tests/ and doc/, plus Makefile.common, which is why a plain make at the top builds the simulator, the tests, the examples and the parts in one go.

## Against the hardware or a heavier emulator

There are two honest alternatives. The first is real hardware, which is always the ground truth and is what you are trying to avoid: flashing and testing a firmware change takes minutes per iteration and needs the board on your desk. The second is a heavier system emulator, which models a whole board with a CPU, memory map and peripherals, at the cost of being slower to start, heavier to run and slower to modify when you need a new peripheral. simavr's position between them is deliberate: a lean core with real peripheral models, cheap enough to run in a test suite. The README states the use case directly, that you can run test units on your shipping firmware to validate it before you ship a new version and prevent regressions. If your board has an unusual analogue front end, an LCD you cannot model, or timing that only shows up in silicon, no simulator substitutes for the bench.

## Conclusion

simavr fits firmware work where the loop of flash and test is too slow, because you can run test units on shipping firmware without hardware, and its integration with PlatformIO means a debug build starts the simulator with no tool choice at all. Skip it for parts above 128KB of flash, where the README calls support preliminary, and skip it if you need a full SoC simulation, since this is a lean core rather than a system emulator. Before you commit, build it and run the tests directory, because the Makefile makes that a single target, and read the manual linked from the repository, since the README defers most usage detail there. Note also that the project publishes no GitHub releases, so your version is whatever you build from the master branch, whose last push was on 2026-10-13. The licence is GPL-3.0.

## FAQ

### How do I install simavr?

On macOS the README recommends brew tap osx-cross/avr followed by brew install --HEAD simavr, on Ubuntu it is in the Bionic package source with apt-get install simavr, and elsewhere make is enough to use bin/simavr while make install RELEASE=1 installs the command system wide.

### How do I get waveforms out of simavr?

Declare signals in the firmware with the _MMCU_ tagged trace structure and simavr writes a VCD file you can open in gtkwave. The trace declarations are not linked into the program, so they add zero bytes, and you can also feed a VCD file captured from a real logic analyzer into the simulation.

### Which AVR parts does simavr support well?

The README states the AVR core is stable for parts with 128KB of flash or less, with preliminary support for the bigger parts. Emulated cores listed include the ATmega family from the 8 through the 2560, several ATTiny parts, and the AT90USB162.

## Sources

- [buserror/simavr on GitHub](https://github.com/buserror/simavr)
- [Issues](https://github.com/buserror/simavr/issues)
- [License: GPL-3.0](https://github.com/buserror/simavr/blob/master/LICENSE)
- [README](https://github.com/buserror/simavr/blob/master/README.md)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/buserror-simavr
