Note: We are still working on this project and plan to add functionality that will allow you to upload your own RISC-V code to visualize. For now, explore these pre-programmed examples. Have fun learning! :)
This interactive demo is organized into these key sections:
Start by selecting either the Sequential CPU or Pipelined CPU demo below to explore different architecture approaches.
This demo provides interactive visualizations of RISC-V CPU implementations, demonstrating both sequential and pipelined architectures.
A single-cycle implementation. Simple to understand but less efficient.
Features:
A 5-stage pipelined implementation with hazard detection and forwarding for improved performance.
Features:
The Sequential CPU demo executes the following RISC-V program:
addi x1, x0, 15 # Initialize x1 = 15
addi x2, x0, 25 # Initialize x2 = 25
addi x3, x0, 7 # Initialize x3 = 7
addi x4, x0, 18 # Initialize x4 = 18
add x5, x1, x2 # Add: x5 = x1 + x2
sub x6, x2, x1 # Subtract: x6 = x2 - x1
and x7, x1, x3 # Bitwise AND: x7 = x1 & x3
or x8, x1, x3 # Bitwise OR: x8 = x1 | x3
sd x5, 0(x0) # Store x5 to memory[0]
sd x6, 8(x0) # Store x6 to memory[8]
ld x9, 0(x0) # Load from memory[0] to x9
ld x10, 8(x0) # Load from memory[8] to x10
add x11, x9, x10 # x11 = x9 + x10
sub x12, x9, x10 # x12 = x9 - x10
beq x11, x12, skip # Branch if x11 == x12
addi x13, x0, 100 # x13 = 100
or x14, x11, x12 # x14 = x11 | x12
and x15, x11, x12 # x15 = x11 & x12
sd x14, 16(x0) # Store x14 to memory[16]
sd x15, 24(x0) # Store x15 to memory[24]
skip:
addi x16, x0, 50 # x16 = 50
add x17, x16, x15 # x17 = x16 + x15
sub x18, x17, x14 # x18 = x17 - x14
beq x17, x18, end # Branch if x17 == x18
ld x19, 16(x0) # Load from memory[16] to x19
ld x20, 24(x0) # Load from memory[24] to x20
or x21, x19, x20 # x21 = x19 | x20
and x22, x19, x20 # x22 = x19 & x20
sd x21, 32(x0) # Store x21 to memory[32]
sd x22, 40(x0) # Store x22 to memory[40]
end:
nop
This program demonstrates all supported RISC-V instructions in a sequential execution:
The sequential execution allows you to observe how each instruction fully completes before the next one begins, with all data paths and control signals visible during each step.
The Pipelined CPU demo executes the following RISC-V program:
start:
ld x1, 0(x0) # Load n from memory
addi x2, x0, 0 # x2 = 0 (Fib(0))
addi x3, x0, 1 # x3 = 1 (Fib(1))
beq x1, x0, done # If n == 0, return Fib(0)
addi x1, x1, -1 # Decrement n by 1 to account for Fib(1)
beq x1, x0, done1 # If n == 1, return Fib(1)
loop:
add x4, x2, x3 # x4 = x2 + x3 (Fib(n) = Fib(n-1) + Fib(n-2))
add x2, x3, x0 # x2 = x3 (shift Fib(n-1) to Fib(n-2))
add x3, x4, x0 # x3 = x4 (shift Fib(n) to Fib(n-1))
addi x1, x1, -1 # Decrement n
beq x1, x0, done1 # Repeat until n == 0
beq x0, x0, loop
done1:
add x4, x3, x0 # Return Fib(1)
done:
# x4 holds the Fibonacci result
addi x0, x0, 0
nop
This Fibonacci calculator demonstrates pipeline hazards and their resolution:
When the program completes, x4 will contain the 10th Fibonacci number (55). Following the execution shows how the pipeline handles data dependencies and branch predictions in this more complex algorithm. The first instruction demonstrates memory access hazards by loading the value from memory.
Instruction | Format | Operation | Description |
---|---|---|---|
add | R-type | add rd, rs1, rs2 | rd ← rs1 + rs2 |
sub | R-type | sub rd, rs1, rs2 | rd ← rs1 - rs2 |
and | R-type | and rd, rs1, rs2 | rd ← rs1 & rs2 |
or | R-type | or rd, rs1, rs2 | rd ← rs1 | rs2 |
addi | I-type | addi rd, rs1, imm | rd ← rs1 + imm |
ld | I-type | ld rd, offset(rs1) | rd ← Memory[rs1 + offset] |
sd | S-type | sd rs2, offset(rs1) | Memory[rs1 + offset] ← rs2 |
beq | B-type | beq rs1, rs2, offset | if (rs1 == rs2) PC ← PC + offset |
The demo demonstrates two fundamentally different approaches to CPU design:
The pipelined implementation includes mechanisms to handle: