Skip to content

paulmialane/riscemu

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

6 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

riscemu

riscemu is a minimal RISC-V emulator written in Rust. It currently supports only the RV32I instruction set.

Usage

fn main() {
    let cpu = Cpu::default();
    let mem = Memory::default();
    let mut machine = Machine { cpu, mem };

    // Load an ELF program at a given base address.
    // 0x10000 can be used for Position Independent Executables.
    // Otherwise, you can use 0x0 as the base.
    machine.load_elf("path_to_elf", 0x10000).unwrap();

    machine.step_on();      // Run the program
    machine.inspect_cpu();  // Inspect CPU registers
    machine.inspect_mem();  // Inspect memory content
}

Disclaimer

This is a very minimal implementation, done as a side project. Many behaviors of a real RISC-V CPU are not implemented, and it is intended only for experimenting with small programs.

Some functions like inspect_cpu() or inspect_mem() are not fully developed yet.

If you find errors or want to contribute improvements, please open an issue or submit a pull request.

Tips and Examples

  • Run small programs only.
  • For very simple programs, there is no return address handling, so execution can be undefined. We use ecall to trap the CPU and inspect results.

Example: computing the Fibonacci sequence:

int main() {
    int n = 10;
    int a = 0;
    int b = 1;
    int c = 0;

    for (int i = 2; i <= n; i++) {
        c = a + b;
        a = b;
        b = c;
    }

    // Store the syscall ID (93 = exit) and result in RISC-V registers
    register int syscall_id asm("a7") = 93; // exit syscall
    register int code asm("a0") = b;       // exit code = Fibonacci(n)

    asm volatile("ecall" : : "r"(syscall_id), "r"(code) : "memory");
    // The following instructions are not executed. 
    // When inspecting the CPU, you can find `b` stored in `a0 (x10)`
    return b;
}

Cross-compiling

To run programs on riscemu, cross-compile using a RISC-V toolchain (unless you're already on a RISC-V machine). Example:

riscv64-linux-gnu-gcc -march=rv32i -mabi=ilp32 -nostdlib -nostartfiles \
-Wl,-e,main -static -Ttext=0x0 fibo_rec.c -o fibo_rec.elf

Notes:

  • -nostdlib and -nostartfiles disable standard library and startup code.
  • -Wl,-e,main sets the ELF entry point to the main function.
  • -Ttext=0x0 sets the program load base address. Adjust if using position-independent code.

About

A risc-V emulator project

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages