I uploaded to GitHub a RISC-V CPU emulator for the RV32I instruction set written in C. It was a fun little project which did not take very long and gave me a chance to get more familiar with this instruction set.

There are a few RISC-V software versions out there, but my hope was to write something very simple and accessible. It only has 130 lines of code including comments!

Each loop though main() is effectively a single RISC-V clock tick. So one instruction per tick/loop. At the end of each loop I print out the program counter, the instruction’s name, some registers and decoded opcode parameters, then it waits for a keypress. This way you can single-step through your code and see the internals of the CPU!

Have fun!

-Ted

Here’s the link to the code: RISC-V C Version

Example Single-stepping through some RV32I code:

PC:0x0 Opcode:0x403150b3 SRA rd:1 rs1:2 rs2:3 U_immediate:0x40315 J_immediate:0x15c02 B_immediate:0xc00 I_immediate:0x403 S_immediate:0x401 funct3:0x5 funct7:0x20

Regs: r0:0 r1:800 r2:1000 r3:1 r4:4 r5:0 r6:0 r7:0 r8:0 r9:0 r10:0 r11:0 r12:0 r13:0 r14:0 r15:0 r16:0 r17:0 r18:0 r19:0 r20:0 r21:0 r22:0 r23:0 r24:0 r25:0 r26:0 r27:0 r28:0 r29:0 r30:0 r31:0

Memory: Addr0:0 Addr1:0 Addr2:0 Addr3:0 Addr4:0 Addr5:0 Addr6:0

PC:0x4 Opcode:0x3120b3 SLT rd:1 rs1:2 rs2:3 U_immediate:0x312 J_immediate:0x12802 B_immediate:0x800 I_immediate:0x3 S_immediate:0x1 funct3:0x2 funct7:0x0

Regs: r0:0 r1:0 r2:1000 r3:1 r4:4 r5:0 r6:0 r7:0 r8:0 r9:0 r10:0 r11:0 r12:0 r13:0 r14:0 r15:0 r16:0 r17:0 r18:0 r19:0 r20:0 r21:0 r22:0 r23:0 r24:0 r25:0 r26:0 r27:0 r28:0 r29:0 r30:0 r31:0

Memory: Addr0:0 Addr1:0 Addr2:0 Addr3:0 Addr4:0 Addr5:0 Addr6:0

PC:0x8 Opcode:0x3100b3 ADD rd:1 rs1:2 rs2:3 U_immediate:0x310 J_immediate:0x10802 B_immediate:0x800 I_immediate:0x3 S_immediate:0x1 funct3:0x0 funct7:0x0

Regs: r0:0 r1:1001 r2:1000 r3:1 r4:4 r5:0 r6:0 r7:0 r8:0 r9:0 r10:0 r11:0 r12:0 r13:0 r14:0 r15:0 r16:0 r17:0 r18:0 r19:0 r20:0 r21:0 r22:0 r23:0 r24:0 r25:0 r26:0 r27:0 r28:0 r29:0 r30:0 r31:0

Memory: Addr0:0 Addr1:0 Addr2:0 Addr3:0 Addr4:0 Addr5:0 Addr6:0

PC:0xc Opcode:0x40315093 SRAI rd:1 rs1:2 rs2:3 U_immediate:0x40315 J_immediate:0x15c02 B_immediate:0xc00 I_immediate:0x403 S_immediate:0x401 funct3:0x5 funct7:0x20

Regs: r0:0 r1:200 r2:1000 r3:1 r4:4 r5:0 r6:0 r7:0 r8:0 r9:0 r10:0 r11:0 r12:0 r13:0 r14:0 r15:0 r16:0 r17:0 r18:0 r19:0 r20:0 r21:0 r22:0 r23:0 r24:0 r25:0 r26:0 r27:0 r28:0 r29:0 r30:0 r31:0

Memory: Addr0:0 Addr1:0 Addr2:0 Addr3:0 Addr4:0 Addr5:0 Addr6:0

PC:0x10 Opcode:0x315093 SRLI rd:1 rs1:2 rs2:3 U_immediate:0x315 J_immediate:0x15802 B_immediate:0x800 I_immediate:0x3 S_immediate:0x1 funct3:0x5 funct7:0x0

Regs: r0:0 r1:200 r2:1000 r3:1 r4:4 r5:0 r6:0 r7:0 r8:0 r9:0 r10:0 r11:0 r12:0 r13:0 r14:0 r15:0 r16:0 r17:0 r18:0 r19:0 r20:0 r21:0 r22:0 r23:0 r24:0 r25:0 r26:0 r27:0 r28:0 r29:0 r30:0 r31:0

Memory: Addr0:0 Addr1:0 Addr2:0 Addr3:0 Addr4:0 Addr5:0 Addr6:0

PC:0x14 Opcode:0x311093 SLLI rd:1 rs1:2 rs2:3 U_immediate:0x311 J_immediate:0x11802 B_immediate:0x800 I_immediate:0x3 S_immediate:0x1 funct3:0x1 funct7:0x0

Regs: r0:0 r1:8000 r2:1000 r3:1 r4:4 r5:0 r6:0 r7:0 r8:0 r9:0 r10:0 r11:0 r12:0 r13:0 r14:0 r15:0 r16:0 r17:0 r18:0 r19:0 r20:0 r21:0 r22:0 r23:0 r24:0 r25:0 r26:0 r27:0 r28:0 r29:0 r30:0 r31:0

Memory: Addr0:0 Addr1:0 Addr2:0 Addr3:0 Addr4:0 Addr5:0 Addr6:0