Simulating RISC-V on a Raspberry Pi
Introduction
Last time, we assembled a small RISC-V program to run on my FPGA RISC-V core running on a Digilent Basys3 development board. To do this we used RARS, which is a quite good Assembler, Debugger, Simulator for RISC-V; in this article I thought I’d point out some other tools available from the official RISC-V github page, including the full GNU C toolchain.
The intent of RISC-V is to be as open source as possible. The main page for the RISC-V Github site contains links to all the RISC-V specifications as well as quite a bit of software including simulators and test tools to test your RISC-V implementation. There is a sister github site for collaborative software such as the GNU RISC-V toolchain which includes a C/C++ compiler, macro assembler and various library and linking tools.
Generally these tools are oriented towards Linux and MacOS and some won’t work in Windows since they require a case sensitive file system. You need to build all these tools yourself, but building them on Ubuntu Linux is fairly straightforward and well documented on the Github sites. I was able to build all these tools on a Raspberry Pi, however it took a full day to do so, and it requires the 64-bit version of the Raspberry Pi OS.

Building the RISC-V Tools
I don’t yet own a real RISC-V processor and my FPGA experiments are nowhere near being able to run Linux. This means I need to compile my RISC-V programs on an Intel or ARM processor, then I can either run the program on a simulator or try it on my FPGA CPU. Building the cross compiler is interesting since it has to first build the compiler executables using the host Intel or ARM GNU compiler and when this is finished use the resulting compiler to compile the C runtime library, so that this is produced in proper RISC-V machine code.
Below I’ll give the commands I used to build and run all the tools on the Raspberry Pi using the 64-bit version of the Raspberry Pi OS. The instructions on the RISCV Github page document the procedures for an Intel version of Linux, but most things work on ARM unmodified.
Install the Prerequisites
These are the recommended packages to install first:
pi@raspberrypi:~ $ sudo apt-get install autoconf automake autotools-dev curl python3 python3-pip libmpc-dev libmpfr-dev libgmp-dev gawk build-essential bison flex texinfo gperf libtool patchutils bc zlib1g-dev libexpat-dev libtinfo5 libncurses5 libncurses5-dev libncursesw5-dev device-tree-compiler git pkg-config
Build the GNU Toolchain
This is the long step where you need to let the make step run overnight.
pi@raspberrypi:~ $ git clone https://github.com/riscv/riscv-gnu-toolchain
pi@raspberrypi:~ $ cd riscv-gnu-toolchain
pi@raspberrypi:~ $ ./configure --prefix=/opt/riscv --enable-multilib --with-arch=rv32i
pi@raspberrypi:~ $ sudo make
pi@raspberrypi:~ $ cd ..
You now have the GNU GCC compiler and build tools. To use them add:
export PATH=$PATH:/opt/riscv/bin
export RISCV=/opt/risc
To the end of your .bashrc file and start a new terminal window so these settings take effect. You can now compile a C program. Here is hello.c being compiled:
pi@raspberrypi:~ $ cat hello.c
#include <stdio.h>
void main()
{
printf("Hello Raspberry Pi World\n");
}
pi@raspberrypi:~ $ riscv32-unknown-elf-gcc hello.c -o hello
pi@raspberrypi:~ $
You can’t run this program quite yet since this program is compiled to RISCV machine code. The unwieldy names of the tools are so the RISC-V versions don’t conflict with the ARM tools and cause havoc.
Build the Spike Simulator
To run the program, we’ll build the Spike simulator which will interpret our RISCV machine code and execute it as if it is running on a real CPU. There is a second library, we’ll build which provides support for some basic operating system calls along with a boot loader to get our simulated CPU up and running. First we build the simulator:
pi@raspberrypi:~ $ git clone https://github.com/riscv/riscv-isa-sim
pi@raspberrypi:~ $ cd riscv-isa-sim
pi@raspberrypi:~/riscv-isa-sim $ mkdir build
pi@raspberrypi:~/riscv-isa-sim $ cd build
pi@raspberrypi:~/riscv-isa-sim/build $ ../configure --prefix=$RISCV --with-isa=rv32i
pi@raspberrypi:~/riscv-isa-sim/build $ make
pi@raspberrypi:~/riscv-isa-sim/build $ sudo make install
pi@raspberrypi:~/riscv-isa-sim/build $ cd ..
pi@raspberrypi:~/riscv-isa-sim $ cd ..
Now we build the component which simulates some Linux system calls and provides a boot loader.
pi@raspberrypi:~ $ git clone https://github.com/riscv/riscv-pk
pi@raspberrypi:~ $ cd riscv-pk/
pi@raspberrypi:~/riscv-pk $ mkdir build
pi@raspberrypi:~/riscv-pk $ cd build
pi@raspberrypi:~/riscv-pk/build $ ../configure --prefix=$RISCV --host=riscv32-unknown-elf
pi@raspberrypi:~/riscv-pk/build $ make
pi@raspberrypi:~/riscv-pk/build $ sudo make install
With this we have the simulator built and we can now run our program:
pi@raspberrypi:~ $ spike /opt/riscv/riscv32-unknown-elf/bin/pk hello
bbl loader
Hello Raspberry Pi World
pi@raspberrypi:~ $
The string “bbl loader” is from the Berkeley boot loader and then we get the string that our program printed out.
If you want to see the RISC-V Assembly Language generated by the GCC compiler, you can use the objdump utility to disassemble the hello executable program:
pi@raspberrypi:~ $ riscv32-unknown-elf-objdump -d hello >hello.txt
Then below is a snippet of the main routine that we wrote. You can also browse the startup code and C library code that is contained there as well.
0001018c <main>:
1018c: ff010113 add sp,sp,-16
10190: 00112623 sw ra,12(sp)
10194: 00812423 sw s0,8(sp)
10198: 01010413 add s0,sp,16
1019c: 000137b7 lui a5,0x13
101a0: 66478513 add a0,a5,1636 # 13664 <__modsi3+0x30>
101a4: 260000ef jal 10404 <puts>
101a8: 00000013 nop
101ac: 00c12083 lw ra,12(sp)
101b0: 00812403 lw s0,8(sp)
101b4: 01010113 add sp,sp,16
101b8: 00008067 ret
Summary
It is pretty cool that you can simulate a RISC-V processor on a Raspberry Pi and do development targeting RISC-V systems. Even though the Raspberry Pi is such an inexpensive system, it is still powerful enough to allow cross platform simulation and development. If you are interested in RISC-V development, but aren’t ready to purchase RISC-V hardware yet, then this is a good way to get started.
[…] Introduction Last time, we assembled a small RISC-V program to run on my FPGA RISC-V core running on a Digilent Basys3 development board.To do this we used RARS, which is a quite good Assembler, Debugger, Simulator for RISC-V; in this article I thought I’d point out some other tools available from… […]
Simulating RISC-V on a Raspberry Pi | Raspberry...
April 13, 2023 at 9:06 pm