dart_emu 0.3.0 copy "dart_emu: ^0.3.0" to clipboard
dart_emu: ^0.3.0 copied to clipboard

A RISC-V system emulator (RV64 and RV32) ported from TinyEMU. Boots Linux with stream-based I/O for CLI, Flutter, and web applications.

dart_emu #

style: very good analysis License: MIT

A RISC-V system emulator for Dart, ported from TinyEMU. Boots Linux with stream-based I/O for embedding in CLI, Flutter, and web applications.

Features #

  • RV64IMAFDC and RV32IMAFDC instruction sets with full privilege levels (Machine, Supervisor, User)
  • SV39 (RV64) and SV32 (RV32) virtual memory with hardware page table walking
  • RV32 runs on all Dart platforms including web (no 64-bit integer dependency)
  • VirtIO console, block device, and network device
  • User-mode networking with DNS, DHCP, and TCP/UDP proxy
  • Stream-based facade for platform-agnostic embedding
  • Lifecycle status tracking via EmulatorStatus
  • YAML-based machine configuration with ZIP bundle support
  • Supports both file-path and in-memory BIOS/kernel loading

Library Usage #

import 'package:dart_emu/dart_emu.dart';

final config = MachineConfig(
  xlen: Xlen.rv64,        // or Xlen.rv32 for 32-bit (web-compatible)
  biosData: biosBytes,     // Uint8List
  kernelData: kernelBytes, // Uint8List
  cmdLine: 'console=hvc0 root=/dev/vda rw',
  blockDevices: [MemoryBlockDevice.fromData(rootfsBytes)],
  ethDevices: [UserNetDevice()], // user-mode networking
);

final emulator = Emulator(config);

// Listen to console output
emulator.output.listen((bytes) => handleOutput(bytes));

// Track lifecycle
emulator.status.listen((status) => print('Status: $status'));

// Send console input
emulator.sendInput(inputBytes);

// Run (completes when guest shuts down or stop() is called)
await emulator.start();

// Clean up
await emulator.dispose();

Flutter / Web Integration #

Use Xlen.rv32 for web targets. RV32 avoids 64-bit integer operations that are unsupported in JavaScript.

final config = MachineConfig(
  xlen: Xlen.rv32,
  biosData: biosBytes,
  kernelData: kernelBytes,
  cmdLine: 'console=hvc0 root=/dev/vda rw',
  blockDevices: [MemoryBlockDevice.fromData(rootfsBytes)],
  ethDevices: [UserNetDevice()],
);

final emulator = Emulator(config);

emulator.output.listen((bytes) {
  terminalController.write(bytes);
});

emulator.status.listen((status) {
  setState(() => _status = status);
});

emulator.start(); // runs in the event loop

See the example directory for a complete Flutter app with a terminal UI, config picker, and ZIP bundle loading.

CLI Usage #

Install globally:

dart pub global activate dart_emu

Run with a configuration file:

dart_emu run --config data/alpine_vm.yaml

Run with individual options:

dart_emu run --bios bbl64.bin --kernel kernel-riscv64.bin --drive rootfs.bin

Web Platform #

The RV32 configuration is fully web-compatible. It uses Uint32List for integer registers and ByteData-backed storage for FP registers, avoiding all 64-bit integer APIs (Int64List, getUint64, setUint64) that are unsupported in JavaScript.

Build the example for web:

cd example
flutter build web --release

To skip the config picker and boot the demo directly, add ?boot=32 to the URL.

Building Root Filesystems #

Docker-based image builders are included for creating rootfs images.

RV64 (Alpine Linux):

tool/image_builder/build.sh riscv64           # minimal (256MB)
tool/image_builder/build.sh riscv64 dev       # with gcc, make, git, nano (512MB)

RV32 (Buildroot + musl):

tool/image_builder/build_buildroot.sh         # minimal (256MB)
tool/image_builder/build_buildroot.sh dev     # with tcc, make, git, nano (512MB)

The RV32 dev image includes TCC (Tiny C Compiler) instead of GCC for practical compile times inside the emulator.

Images are packaged as ZIP bundles in data/ that the Flutter app can load via drag-and-drop or file picker.

Configuration #

Machine configuration uses YAML files:

version: 1
machine: riscv64
memory_size: 256
bios: bbl64.bin
kernel: kernel-riscv64.bin
cmdline: "console=hvc0 root=/dev/vda rw"
drive0:
  file: rootfs/alpine-riscv64-rootfs.bin
eth0:
  driver: user

For RV32:

version: 1
machine: riscv32
memory_size: 256
bios: bbl32.bin
kernel: kernel-riscv32.bin
cmdline: "console=hvc0 root=/dev/vda rw"
drive0:
  file: rootfs/alpine-riscv32-rootfs.bin
eth0:
  driver: user
1
likes
160
points
112
downloads

Publisher

unverified uploader

Weekly Downloads

A RISC-V system emulator (RV64 and RV32) ported from TinyEMU. Boots Linux with stream-based I/O for CLI, Flutter, and web applications.

Repository (GitHub)
View/report issues

Topics

#emulator #riscv #virtual-machine

Documentation

API reference

License

MIT (license)

Dependencies

args, mason_logger, yaml

More

Packages that depend on dart_emu