Stephen Smith's Blog

Musings on Machine Learning…

Simulating RISC-V on a Raspberry Pi

with one comment


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.

Written by smist08

April 1, 2023 at 8:06 pm

One Response

Subscribe to comments with RSS.

  1. […] 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…  […]


Leave a comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.