It works every time

... 60% of the time

Generating and testing of a RISC-V core - Week 1 of GSoC 2016

As introduced in last week's post, the title of my GSoC 16 project is "RISC-V port to Parallella" so the first thing I had to do was getting familiar with the RISC-V ecosystem. One of the best ways to do so was by viewing some of the recorded videos from the 1st RISC-V Workshop presentations that are available on Youtube. To get up to speed with the most important concepts I recommend the following presentations:

  • Introductions and Welcome (Krste Asanović) [Video] [Slides]
  • RISC-V Software Toolchain (Andrew Waterman) [Video] [Slides]
  • RISC-V “Rocket Chip” SoC Generator in Chisel (Yunsup Lee) [Video] [Slides]
  • Structure of the RISC-V Software Stack (Sagar Karandikar) [Video] [Slides]
  • Debugging on RISC-V (Albert Ou) [Video] [Slides]
  • Porting New Code to RISC-V with OpenEmbedded (Martin Maas) [Video] [Slides]
  • RISC-V Testing Environments (Stephen Twigg) [Video] [Slides]

And some extra ones if you are interested in Chisel, the Scalla-based language that is used to describe the hardware implementations of UCB's RISC-V cores (Rocket with in-order pipe, BOOM with out-of-order pipe and any future ones).

  • Chisel Quick Tutorial (Jonathan Bachrach) [Video] [Slides]
  • Working with Rocket Chip, Adding Extensions, ASIC and FPGA Infrastructure (Colin Schmidt) [Video] [Slides]

If you are deeply interested in RISC-V and the current developments of the community I suggest that you follow up with the rest of the Workshops that were organised (2nd and 3rd) and of-course try to attend the 4th RISC-V Workshop that is happening on July 12-13 in MIT.

Our RISC-V port to Parallella will use a fairly standard core generated with Rocket Chip from the Chisel sources (the linked technical paper is a very good introduction). The end result will be Verilog RTL (in mostly unreadable form, only Chisel sources are human readable) that we can then proceed to include into the rest of the Parallella FPGA design which is hosted in Parallella's OH (Open Hardware) repository. However I won't go into details about it here since this is related to work that will happen in the following couple of weeks and will be described in following blog posts.

In order to compile software for your core you can use the RISC-V GNU toolchain that is also included as a submodule (riscv-tools). There are two paths that you can take: either build against Newlib C library to compile programs that will be run ontop of a proxy kernel (pk) or build against the GNU C library (glibc) to compile Linux and other programs to run ontop of it. I build both versions along with the Linux kernel (riscv-linux repo currently tracks the 4.1 release) using the provided instructions and everything worked as expected while simulating with Spike, the reference RISC-V ISA simulator.

The main Rocket-Chip repository is linked with Git submodules for all the repositories that contain sources (mostly Chisel) that it needs to access in order to properly generate everything correctly using its own wrapper files which reside in src/main/scala/ folder. Each submodule that is included is linked at a certain commit that is known to work by the developers so that everything is stable enough for development purposes at least. I personally didn't have even a single issue while generating the default RV64G ISA based core (64-bit with [I]nteger, [M]ultiply / Division, [A]tomic and Single or [D]ouble precision [F]loating point support extensions - acronym: IMAFD a.k.a G) which includes L1 instruction and data caches, a TLB and an FPU along with MemIO and HostIO interfaces to access the outside world.

In a typical FPGA setup (as shown in the diagram from Y.Lee's presentation of Rocket Chip), those two interfaces are needed for main memory accesses and to boot the RISC-V core (bootstrap sequence). The latter is also used to control the core's CSRs (control-status registers) and support system calls (for I/O) from the target machine (running a RISC-V proxy kernel or Linux kernel) towards the host machine (e.g Zynq FPGA dual core ARM processor) running an instance of riscv-fesvr (front end server) to dispatch the system calls on its OS (e.g ARM Linux).

To customise the core you can also change values inside the Configs.scala source file. This file contains a bunch of configurations for different setups targeted for different use cases (C++ model, normal size FPGA, small FPGA, VLSI etc). All the make scripts accept a CONFIG=XXX (e.g DefaultFPGAConfig) variable that sets the desired configuration to use while building the C++ simulator or the Verilog RTL for FPGA or VLSI. This is a very handy feature if you want to experiment with the many options available and quickly generate and test them on software or hardware forms.

It is a good idea to build the software toolchain (Newlib path is fine) before generating any cores since it is needed to compile and run the tests to verify correct operation of your core either with the C++ simulator or with Synopsys VCS. Unfortunately I can only use the former since I don't have access to the latter. One cannot just use a Verilog simulator of his choice (e.g Verilator, Icarus Verilog, Modelsim, QuestSim) since the provided testbenches use DirectC routines (VCS's way of gluing Verilog testbenches to arbitrary C/C++ code). Luckily the C++ simulator provides VCD output and I was able to use GTKWave to view the generated waveforms of the tests.

I also append a session with the simple commands needed to build the RISC-V toolchain and generate a RV64G core for FPGA implementation. These will be included in the final build scripts that I am preparing for the full automation of everything needed to build in order to have a RISC-V core working inside the Zynq device of Parallella.

# Download and initialize the Rocket Chip repository
git clone
cd rocket-chip
git submodule update --init
export TOP=$(pwd)

# Install necessary packages (Ubuntu)
sudo apt-get install autoconf automake autotools-dev curl \
libmpc-dev libmpfr-dev libgmp-dev gawk build-essential bison flex \
texinfo gperf libtool patchutils bc

# Build the RISC-V Toolchain (Newlib version for use without an OS)
export RISCV=$TOP/riscv-tools
# Add everything that will be built to our path for easy access)
export PATH=$PATH:$RISCV/bin
git submodule update --init --recursive
# Edit build.common file
# with JOBS = No of Cores / Threads your machine supports

# Test the RISC-V Toolchain by compiling a simple program
# and then running it with Spike (ISA simulator)
# using the provided proxy kernel (pk)
cd $TOP
echo -e '#include <stdio.h>\n int main(void) \
{ printf("Hello world!\\n"); return 0; }' > hello.c
riscv64-unknown-elf-gcc -o hello hello.c
spike pk hello

# Optional: Build the Rocket Chip emulator
# Change -j8 to -jN = No of Cores / Threads your machine supports
cd $TOP/emulator
# Run Tests (WARNING this might take a lot of time)
# make -j8 run-asm-tests
# make -j8 run-bmark-tests
# It is better to just run specific tests, e.g:
make output/rv64ui-p-add.out

# Optional: Build the Rocket Chip emulator with VCD output capabilities
# Change -j8 to -jN = No of Cores / Threads your machine supports
cd $TOP/emulator
# If you don't have vcd2vpd utility open src/main/scala/Testing.scala
# file and replace wherever you see .vpd with .vcd (6 instances)
make debug
# Run Tests (WARNING this might take a lot of time and storage)
# make -j8 run-asm-tests-debug
# make -j8 run-bmark-tests-debug
# It is better to just run specific tests and it doesn't need the above
# hack for vcd2vpd utility absence, e.g:
make output/rv64ui-p-add.vcd

# Generate Rocket Chip Verilog RTL for FPGAs (inside fsim/generated-src/)
# Default configuration is "DefaultFPGAConfig" but you can change it
# e.g to "SmallFPGAConfig" if the default implementation (with FPU)
# doesn't fit your device. Use make CONFIG=ConfigName verilog to set the
# desired config from those available in (src/main/scala/Configs.scala)
# Final Verilog RTL output file is named Top.ConfigName.v
cd $TOP/fsim
make verilog

The focus for next week is to package the generated RV64G core as an IP block for easy instantiation in a simple design with just that (for testing on Zedboard) or as part of a larger design (Parallella OH).

Written by Elias Kouskoumvekakis on Monday May 30, 2016

Permalink - Category: news - Tag: gsoc2016

« Welcome! - Packaging the RISC-V rocket core with Vivado GUI - Week 2 of GSoC 2016 »

comments powered by Disqus