RISC-V Tools Setup

Slide to adjust verbosity level 

This post only explains the setup procedure for the additional tools needed for the RISC-V development. Installation procedure for the PyGears tools has been discussed in the previous post.

Relevant pygears_riscv git commit: pygears_riscv@bba9a4a

If I want to approach this project the TDD way, I need to be ready to test the design from the start. Hence, I will start by obtaining the “golden design”, aka “reference model”, aka “test oracle”, depending on the terminology, and setting up the infrastructure to it with PyGears.

sudo apt-get install autoconf automake autotools-dev curl libmpc-dev libmpfr-dev libgmp-dev libusb-1.0-0-dev gawk build-essential bison flex texinfo gperf libtool patchutils bc zlib1g-dev device-tree-compiler pkg-config libexpat-dev

export RISCV=/tools/riscv-tools

git clone https://github.com/riscv/riscv-tools.git $RISCV/_install
cd $RISCV/_install
git submodule update --init --recursive

echo "" >> /tools/tools.sh
echo "# Environment for riscv-tools" >> /tools/tools.sh
echo "export RISCV=/tools/riscv-tools" >> /tools/tools.sh
echo "export PATH=\$RISCV/bin:\$PATH" >> /tools/tools.sh
source /tools/tools.sh

Finally, lets try if I can simulate a simple program. I ended up with the following simple linker script bare.ld:

. = 0x80000000;

Next, I created a proof of concept assembly file hello.s.

;; # Very simple assembly program that will cause Spike to terminate gracefully.

  .global _start


  ;; # The actual instruction I'd like to test.
  li a1, 1

  ;; # Write the value 1 to tohost, telling Spike to quit with an exit code of 0.
  li t0, 1
  la t1, tohost
  sw t0, 0(t1)

  ;; # Spin until Spike terminates the simulation.
  1: j 1b

;; # Expose tohost and fromhost to Spike so we can communicate with it.
  .global tohost
tohost:   .dword 0
  .global fromhost
fromhost: .dword 0

I ended up with the following command to call GCC:

riscv64-unknown-elf-gcc -march=rv32i -mabi=ilp32 -nostdlib -T bare.ld hello.s -o hello

I can now invoke Spike simulator for the basic 32-bit ISA (--isa=rv32i option) to test the instruction execution and print the list of the instructions it their execution order (-l option):

spike -l --isa=rv32i hello

Command produces output given below.

 core   0: 0x0000000000001000 (0x00000297) auipc   t0, 0x0
 core   0: 0x0000000000001004 (0x02028593) addi    a1, t0, 32
 core   0: 0x0000000000001008 (0xf1402573) csrr    a0, mhartid
 core   0: 0x000000000000100c (0x0182a283) lw      t0, 24(t0)
 core   0: 0x0000000000001010 (0x00028067) jr      t0
 core   0: 0xffffffff80000000 (0x00100593) li      a1, 1
 core   0: 0xffffffff80000004 (0x00100293) li      t0, 1
 core   0: 0xffffffff80000008 (0x00000317) auipc   t1, 0x0
 core   0: 0xffffffff8000000c (0x01030313) addi    t1, t1, 16
 core   0: 0xffffffff80000010 (0x00532023) sw      t0, 0(t1)
 core   0: 0xffffffff80000014 (0x0000006f) j       pc + 0x0

Invoking from Python

I’d like to have at least one test per RISC-V instruction I implement and run them as often as possible. Hence I need them automated. Specifically, my automated tests need to check whether an instruction introduces the same changes to the memory and registers in my design as it does in the Spike simulator. Unfortunately, Spike doesn’t offer an option of executing commands from the script, so I’ll have to run it in the interactive mode and send commands to him live. Let’s put all this functionality inside pygears_riscv/spike.py.

Now, I can interact with Spike on a pretty high level:

from spike import Spike

with Spike('spike -d --isa=rv32i hello') as sp:
    print('A1 value before: ', hex(sp.reg(1)))
    print('A1 value after:  ', hex(sp.reg(1)))


comments powered by Disqus