RISC-V online emulator with WebAssembly generated by Rust.
The online emulator is available here:
- rvemu.app: Run a RISC-V binary you uploaded.
- rvemu.app/xv6: Run
xv6
.
The emulator supports RV64GC ISA (RV64IMAFD, Zicsr, Zifencei, RV64C), privileged ISA, CSRs, virtual memory system (Sv39), peripheral devices (UART, CLINT, PLIC, Virtio), and device tree. See the "Features List" section for the details of features.
These features are compliant with "The RISC-V Instruction Set Manual Volume I: Unprivileged ISA Document Version 20191213" and "The RISC-V Instruction Set Manual Volume II: Privileged Architecture Document Version 20190608-Priv-MSU-Ratified" in the RISC-V specifications.
The emulator can run both in your browser and in your terminal. Also, the emulator can be embedded in your project by the crate registry.
You can run xv6
, a simple Unix-like
operating system, in rvemu.app/xv6.
You also be able to run an arbitrary RISC-V binary in rvemu.app. The online emulator supports the following commands:
- upload: Upload local RISC-V binaries for the execution on the emulator.
- ls: List the files you uploaded.
- run [file]: Execute a file which you uploaded or some files are already embedded.
- help: Print all commands you can use.
See the "Build RISC-V binary" section for more information to build RISC-V binary.
The option --kernel
or -k
specifies a kernel image, and --file
or -f
specifies a root filesystem image.
Linux
$ ./target/release/rvemu-cli -k examples/linux-bbl.bin -f examples/busybear.bin
xv6
$ ./target/release/rvemu-cli -k examples/xv6-kernel.text -f examples/xv6-fs.img
Bare-metal binary
You can use an arbitrary RISC-V binary and you can skip the -f
option. An ELF
binary should have no headers.
$ ./target/release/rvemu-cli -k <your-binary>
The wasm-pack build
command generates a pkg
directory and makes Rust source
code into .wasm
binary. It also generates the JavaScript API for using our
Rust-generated WebAssembly. The toolchain's supported target is
wasm32-unknown-unknown
. You need to execute this command whenever you change
your Rust code.
// This is the alias of `wasm-pack build lib/rvemu-wasm --out-dir <path-to-rvemu>/public/pkg --target web --no-typescript`.
$ make rvemu-wasm
This command installs dependencies in the node_modules
directory. Need
npm install --save
in the public
directory at the first time and whenever
you change dependencies in package.json.
$ npm install --save // at the public directory
You can see the website via http://localhost:8000. npm start
is the alias of
python3 -m http.server
so you need Python3 in your environment.
$ npm start // at the public directory
Build the emulator as a CLI tool.
$ make rvemu-cli
You might need to build riscv toolchain.
// In the riscv-gnu-toolchain directory.
// https://github.com/riscv/riscv-gnu-toolchain
$ ./configure --prefix=/opt/riscv --with-arch=rv64gc
$ make
$ make linux
You need to make an ELF file without headers, which starts at the address
0x8000_0000
by the following instructions:
// Make an assembly file from a C file.
$ riscv64-unknown-elf-gcc -S -nostdlib foo.c
// Make a binary file from an assembly file with start position 0x8000_0000.
$l riscv64-unknown-elf-gcc -Wl,-Ttext=0x80000000 -nostdlib -o foo foo.s
// Remove headers from a binary file.
$ riscv64-unknown-elf-objcopy -O binary foo foo.text
The page Running 64- and 32-bit RISC-V Linux on QEMU helps to build a Linux image. When you compile this project in a x86 computer, you may need to:
- update
CC := gcc
toCC := riscv64-unknown-elf-gcc
inriscv-pk/build/Makefile
- comment out the "build bbl" part in
busybear-linux/scripts/build.sh
because the build script for cross compiling in riscv-pk is broken. See https://github.com/riscv/riscv-pk/blob/master/configure#L1146-L1148
You can see the binaries for unit testings in
riscv/riscv-tests.
The following command executes all rv64ua/d/f/i/m-p-*
binaries.
TODO: not all tests are passed for now.
$ make test
$ perf record -F99 --call-graph dwarf ./target/release/rvemu-cli -k examples/xv6-kernel.text -f examples/xv6-fs.img
$ perf report
The site is hosted by a firebase.
$ firebase deploy
The emulator supports the following features:
- RV64G ISA
- RV64I (v2.1): supports 52/52 instructions (
fence
does nothing for now) - RV64M (v2.0): supports 13/13 instructions
- RV64A (v2.1): supports 22/22 instructions (No atomicity for now)
- RV64F (v2.2): supports 30/30 instructions
- RV64D (v2.2): supports 32/32 instructions
- Zifencei (v2.0): supports 1/1 instructions (
fence.i
does nothing for now) - Zicsr (v2.0): supports 6/6 instructions (No atomicity for now)
- RV64I (v2.1): supports 52/52 instructions (
- RV64C ISA (v2.0): support 36/36 instructions
- Privileged ISA: supports 7/7 instructions (
sfence.vma
,hfence.bvma
, andhfence.gvma
do nothing for now) - Control and status registers (CSRs)
- Machine-level CSRs
- Supervisor-level CSRs
- User-level CSRs
- Virtual memory system (Sv39)
- Devices
- UART: universal asynchronous receiver-transmitter
- CLINT: core local interruptor
- PLIC: platform level interrupt controller
- Virtio: virtual I/O
- Device tree
To set up environment:
- rustc
- rustup nightly
- wasm-pack
- dtc (apt install device-tree-compiler)
- Nightly Rust
- Python3
- wasm-pack
- npm
- xterm
- xterm-addon-fit
- dtc: device tree compiler