RAVEN is a free RISC-V simulator and IDE that runs in your terminal. Write assembly, assemble with one keystroke, and step through the program while the registers, memory, cache, the five-stage pipeline, and address translation all update as it runs. You see what the machine does, not just what it prints.
Write, assemble, run, debug, and profile your RISC-V programs in a single window. No toolchain to install, no black boxes to trust.
Built-in editor with syntax highlighting for instructions, registers, directives, and labels. Press Ctrl+R to assemble instantly, with no Makefile and no terminal juggling. Import .asm files from other simulators or export your work as a binary. It even loads ELF32 RISC-V binaries built by a real toolchain.
Run free, pause, or advance one instruction at a time. See exactly which register changes, by how much, and why. Set breakpoints on any instruction.
Integer registers shown with ABI names (ra, sp, a0–a7, s0–s11…) plus hex and decimal side by side. Recently changed registers are highlighted automatically, and the float bank is one keypress away.
Each instruction is decoded into its fields: opcode, rd, rs1, rs2, funct3, funct7, sign-extended immediate. Understand encoding, not just mnemonics.
Step the classic IF, ID, EX, MEM, WB pipeline one cycle at a time. See instructions flow through each stage, watch forwarding paths light up, and catch load-use stalls, branch flushes, and cache stalls as they happen.
A working MMU walks the page table and translates virtual addresses to physical ones a page at a time. See VPN to PPN mappings, TLB hits and misses, page faults, and the live page-table tree. Flip between Sv32, a custom scheme, or hardware-accurate manual mode.
Base integer (RV32I), multiply/divide (M), atomics (A), and single-precision float (F). Every instruction your textbook covers, plus the pseudo-instructions used in real code. Spawn extra harts and watch several cores run at once.
A full I-cache + D-cache simulator tracks every fetch and memory access. Configure geometry and replacement policy, then watch hit rates, AMAT, and IPC update live. Compare configurations with a built-in baseline export.
RAVEN is built around one loop: write code, run it, and see exactly what happens inside the machine.
Type RISC-V assembly in the built-in editor. Syntax highlighting colours instructions, registers, labels, and directives. Ghost hints show operand syntax as you type. Press Ctrl+R to assemble instantly; any error points at the exact line and reason.
Step instruction by instruction or run free. The instruction list shows the current PC, decoded type badge, and execution heat. Registers and memory update on every step.
Switch to the Cache, Pipeline, or VM tab to see hit rates, AMAT, IPC, pipeline stalls, and address translation. Change a policy or a scheme, run again, and compare.
The sequential view runs instruction by instruction. The pipeline view runs cycle by cycle, so you can see the hazards, stalls, and forwarding paths that the textbook only draws on paper.
Most simulators hide the cache. RAVEN shows the whole thing: per-access tracking, live statistics, a visual matrix of every cache line, and configurable policies so you can test what you learned in class.
Programs use virtual addresses; RAM uses physical ones. RAVEN's MMU walks the page table, translates one page at a time, and caches the result in the TLB, and it shows you every step.
satp and its own tables.satp, straight from RAM: pointer entries expand into child tables, leaves are (super)pages, and cached entries are marked.sfence.vma, and sret back to retry the access.Every example in RAVEN is ready to open, step through, and experiment with. Start with these, then write your own.
.data arr: .word 33,12,7,25,9,13,5,1,44,3,18,2,29,8,21,6,10,17,14,4 msg: .asciz "Quicksort (20 elements)" nl: .byte 10, 0 .text printStrLn msg la a0, arr ; base address li a1, 0 ; lo = 0 li a2, 19 ; hi = 19 call quicksort la t0, arr li t4, 20 li t1, 0 print_loop: slli t2, t1, 2 add t2, t0, t2 lw t3, 0(t2) print t3 printStr nl addi t1, t1, 1 blt t1, t4, print_loop li a0, 0 li a7, 93 ; syscall: exit ecall ; quicksort(a0=base, a1=lo, a2=hi) quicksort: bge a1, a2, qs_done push ra push s1 ; base push s2 ; lo push s3 ; hi push s4 ; pivot index mv s1, a0 mv s2, a1 mv s3, a2 call partition ; → a0 = pivot index mv s4, a0 mv a0, s1 mv a1, s2 addi a2, s4, -1 call quicksort ; recurse left mv a0, s1 addi a1, s4, 1 mv a2, s3 call quicksort ; recurse right pop s4 pop s3 pop s2 pop s1 pop ra qs_done: ret ; partition(a0=base, a1=lo, a2=hi) → a0 = pivot index partition: push ra push s0 ; pivot value push s1 ; base push s2 ; lo push s3 ; hi push s4 ; i push s5 ; j mv s1, a0 mv s2, a1 mv s3, a2 slli t0, s3, 2 add t0, s1, t0 lw s0, 0(t0) ; pivot = arr[hi] addi s4, s2, -1 ; i = lo - 1 mv s5, s2 ; j = lo part_loop: bge s5, s3, part_done slli t1, s5, 2 add t1, s1, t1 lw t2, 0(t1) ; arr[j] blt s0, t2, skip_swap addi s4, s4, 1 ; i++ beq s4, s5, skip_swap slli t3, s4, 2 add t3, s1, t3 lw t4, 0(t3) ; arr[i] sw t2, 0(t3) ; arr[i] = arr[j] sw t4, 0(t1) ; arr[j] = arr[i] skip_swap: addi s5, s5, 1 j part_loop part_done: addi t0, s4, 1 ; pivotIndex = i + 1 slli t1, t0, 2 add t1, s1, t1 lw t2, 0(t1) slli t3, s3, 2 add t3, s1, t3 lw t4, 0(t3) sw t4, 0(t1) ; swap pivot into place sw t2, 0(t3) mv a0, t0 pop s5 pop s4 pop s3 pop s2 pop s1 pop s0 pop ra ret
Full recursive quicksort on a 20-element integer array. Demonstrates proper RISC-V calling convention with push/pop to save callee-saved registers across recursive calls.
call + stack frame via push/pops0–s5)exit(93) via raw ecall.data arr: .word 20,1,19,2,18,3,17,4,16,5,15,6,14,7,13,8,12,9,11,10 msg: .asciz "Sorted values:" nl: .byte 10, 0 .text printStrLn msg la t0, arr ; base address li t4, 20 ; n = 20 li t1, 0 ; i = 0 outer: li t2, 0 sub s2, t4, t1 addi s2, s2, -1 ; limit = n - 1 - i inner: slli t3, t2, 2 ; offset = j * 4 add t3, t0, t3 ; &arr[j] addi t5, t3, 4 ; &arr[j+1] lw s0, 0(t3) lw s1, 0(t5) blt s0, s1, no_swap sw s1, 0(t3) sw s0, 0(t5) no_swap: addi t2, t2, 1 blt t2, s2, inner addi t1, t1, 1 blt t1, t4, outer li t2, 0 print_loop: slli t3, t2, 2 add t3, t0, t3 lw a0, 0(t3) print a0 printStr nl addi t2, t2, 1 blt t2, t4, print_loop li a0, 0 li a7, 93 ; syscall: exit ecall
Classic O(n²) sort over a 20-element array in .data. Great for watching D-cache access patterns in the Cache tab, where the tight inner loop shows excellent spatial locality.
.word directiveslli + add)lw / swbltexit(93) via raw ecall.data buf: .space 64 .text ; Linux-style syscall ABI: ; a7 = syscall number ; a0..a5 = arguments ; a0 = return value li a0, 0 ; fd = stdin (0) la a1, buf li a2, 64 ; max bytes li a7, 63 ; read(fd, buf, count) ecall ; → a0 = bytes read mv t0, a0 ; save byte count li a0, 1 ; fd = stdout (1) la a1, buf mv a2, t0 ; exact bytes to echo li a7, 64 ; write(fd, buf, count) ecall li a0, 0 li a7, 93 ; exit(0) ecall
No pseudo-instructions. Pure Linux-style ecall: put the syscall number in a7, arguments in a0–a5, fire ecall. Return value lands in a0. Reads a line from stdin and writes it straight back to stdout.
read(63): stdin → bufferwrite(64): buffer → stdoutexit(93): clean exit.spaceread used as write length.data prompt: .asciz "Your name? " greet: .asciz "Hi, " buf: .space 64 .text ; --- write prompt to stdout --- li a0, 1 ; fd = stdout la a1, prompt li a2, 11 ; len("Your name? ") li a7, 64 ; write ecall ; --- read name from stdin --- li a0, 0 ; fd = stdin la a1, buf li a2, 64 ; max bytes li a7, 63 ; read ecall ; → a0 = bytes read mv t0, a0 ; save byte count ; --- write "Hi, " to stdout --- li a0, 1 la a1, greet li a2, 4 ; len("Hi, ") li a7, 64 ; write ecall ; --- write the name back --- li a0, 1 la a1, buf mv a2, t0 ; bytes_read from earlier li a7, 64 ; write ecall li a0, 0 li a7, 93 ; exit(0) ecall
Composes output from three separate write calls (a prompt string, a greeting prefix, and the user's input), all using raw Linux ABI. No pseudo-instructions, no helpers.
write(64) callsread reused as write lengthla (load address)exit(93): Linux-compatible clean exitFrom basic arithmetic to atomics and floating-point. RAVEN supports the complete standard instruction set, so you never hit a wall mid-course.
The same core that powers the IDE also runs from the command line and ships as a Rust crate, so you can script runs, grade assignments, and build your own tools on top of RAVEN.
Assemble, simulate, and export stats without opening the TUI. Point it at a .s source, a FALC .bin, or an ELF, and redirect the numbers to a file.
The raven-engine crate runs the assembler and simulator headless, so you can embed them in tests, autograders, and other Rust tools.
use raven_engine::Falcon; let result = Falcon::new() .asm(".text\n li a0, 42\n li a7, 93\n ecall\n") .max_cycles(10_000) .run()?; assert_eq!(result.exit_code, Some(42)); assert_eq!(result.reg("a0"), 42); // result.stdout(), result.pc(), result.read_word(addr)…
RAVEN is a single binary. No toolchain to install and no container to set up.
Grab the binary for your OS from the Releases page and run it directly. RAVEN opens immediately.
Requires Rust (rustup.rs). Gives you the latest version and full access to the source.
If you're studying RISC-V for a university course, on your own, or just out of curiosity, RAVEN is built for you. Register naming, memory layout, and calling conventions follow the standard spec exactly, so what you see here is what you'll see on the exam.