Baremetal Multicore in Spike
The purpose of this tutorial is to show you how to run a baremetal program in Spike, which is the RISC-V simulator. Baremetal means that it does not rely on a kernel like riscv-pk. This tutorial assumes you are working in a Linux environment.
Getting RISC-V Tools
Please follow the steps described on this github: https://github.com/riscv/riscv-tools
Make sure to always set the
RISCV environment variable and ammend your
PATH variable if you would like to be able to access all RISC-V tools. For me I added a lines to my
~/.bashrc file so that everything is set up when I open a terminal window:
Compiling Some Code
Now to get started on coding, download this tarball. A short overview of what is in here:
hello.cis the C file that contains our main function and makes the print statements.
init.sis some assembly code that we use to initialize our stack pointer and jump to the main function.
link.ldis the linker script that tells the linker where to put everything in memory. It puts our code at
0x80000000, which is the start of memory in Spike.
Makefileis the make recipe for how to build our project.
Once you have extracted this code you can run
make inside the hello folder. This will create a couple of files. The file
a.out is the file that we will run in a minute.
In order to have output in Spike without having to deal with the RISC-V front-end server. I decided to add a custom CSR (control and status register) which outputs a character corresponding to the value that is written to the register. So when you write to the CSR, using the
csrrw instruction, it will print the character corresponding to the value it contains (see the output_char function in
hello.c as an example).
To achieve this I made a couple of changes to the spike source code, which you can find in this diff file. It adds the definition of the CSR to
encoding.h and how to handle writes in
You need to apply these changes to the source code in the riscv-tools that you built earlier. Go to the source code directory of your riscv-tools checkout. Go to the sub-folder named riscv-isa-sim and make your changes. Then go into the build directory and type
make and after that
Running Your Code
Going back to the directory where you build the bare metal hello world program. You can now execute:
spike -p2 a.out
This should print two lines. One saying "Core 0" and the other saying "Core 1". You can change the number after the
-p to denote how many cores you would like to run with.
Debugging Your Code
Now you will probably want to start modifying the C code to do what you want. So it is useful to know how to debug your code.
When running your code you can add the
-d flag to Spike, which enters a debug session. Every time you press enter it will execute an instruction and print which instruction that is. For more options on debugging you can see the README.md file on the riscv-isa-sim repository.
Besides the Spike debugger, it is also useful to see the instructions of your compiled code. You can use
make dump to get the dump of your program. This way you can see the program counter values that are produced by Spike and compare them with those in your program.
As you may have noticed, the print statements look very clean for a multi-threaded application. All of core 0's characters are print before core 1 start printing. This is not really what you expect if two threads are running in parallel. What I would expect is that the characters are interleaved.
The reason for this is that Spike by default runs 5000 instructions on core 0 and then runs 5000 instructions on core 1. To make it so that the instructions of the two cores are interleaved, we need to make a small adjustment to Spike's source-code. In
riscv-tools/riscv-isa-sim/riscv/sim.h look for the line that says
static const size_t INTERLEAVE = 5000; . Change 5000 to 1 and then go to the
risv-tools/riscv-isa-sim/build/ directory. In the build directory, run the
make command and then the
make install command.
If you rerun our hello world application again, the letters will be interleaved as we expected earlier.