Chipyard: Setting up a RISC-V security testing environment

My master’s thesis work has been in RISC-V security, a topic that has gained substantial relevance following major flaws discovered in popular (but very proprietary) CPU cores manufactured by companies like Intel, ARM, and AMD. An advantage to researchers interested in investigating micro architecture security is that RISC-V cores are completely open source, available to free inspection by a researcher and straightforward (sort of) to modify.

Why this sort of research is important will be the subject of another article. For now, I will be focusing on the nuts and bolts of exploring this topic.

Setting Up Chipyard

In order to get started on evaluating the security of these new “open cores,” we will need a basic testing environment. Most of the code describing these cores is freely available on GitHub and is published by the Berkeley Architecture Research team. The main repository we’re going to use is Chipyard. This is more or less a standard environment for RISC-V development at present.

Requirements

This has been tested on a virtual machine running Ubuntu 18.04.1 LTS. The operating system was clean-installed. We need to make sure some basic things exist — hopefully if you’re a hardware developer you’ve already got most of this going. In Ubuntu 18.04, most of this can be handled with sudo apt-get install build-essential git, but you may want to check versions below to be sure.

  • gcc, (the GNU C Compiler), with a version greater than 7.3. Watch for this. If you are on an earlier version of Ubuntu (for example) you may find you’re on a much older version of GCC.
  • make, with a version of 4.x or later.
  • git
  • libmpc-dev was a requirement that, when not installed, threw an extremely hard to find error about GCC requiring GMP to build.
  • device-tree-compiler

You can install the known requirements listed above with the following.

$ apt-get install -y build-essential git libmpc-dev device-tree-compiler

Cloning and compiling Chipyard, RISC-V Tools

Begin by cloning Chipyard. This is based on initial setup instructions from within Chipyard’s documentation, and is the “basic” installation.

$ git clone https://github.com/ucb-bar/chipyard.git
$ cd chipyard
$ ./scripts/init-submodules-no-riscv-tools.sh

That will clone down the repository and expand all sub-modules. From here, we need the RISC-V toolchain, which will include all of our necessary compiler tools to generate binaries for the RISC-V architecture.

$ ./scripts/build-toolchains.sh

Some versions of the guide will ask you to run it with a parameter, e.g. ./scripts/build-toolchains.sh riscv-tools, but I found this causes problems.

That will take a while to run. Remember that if you are able to compile with multiple cores, you may benefit from setting the MAKEFLAGS=-jN environment variable, where N is the number of cores you have available. Additionally, don’t forget you can use terminal multiplexers like screen to keep long compilations running when you cannot, for example, keep an ssh session open for the whole compile.

Once compilation runs, be sure to source env.sh from within your Chipyard root directory. This file is emitted at the end of the toolchain compilation process and will set the environment variables necessary for other tools to find certain critical parts of the toolchain later. Place that source command in your .bashrc to ensure it’s ready to go each time you open your simulation machine.

Verilator

Once you have Chipyard installed and compiled, you will need some sort of Verilog simulation tool. The most typical open source solution is verilator.

$ apt-get install verilator

This will allow you to simulate the CPU designs generated by the toolchain.

Chipyard also supports VCS simulation, but that is a proprietary tool and this guide is avoiding proprietary tools wherever possible.

Java

Because the RISC-V cores are defined in CHISEL, a Java Runtime Environment is necessary. CHISEL (Constructing Hardware In a Scala Embedded Language) is, essentially, a Scala library in the same sense that you import package in a language like Python. You need it to generate the synthesizable Verilog from the Chisel code.

This requirement can be satisfied by running:

$ apt-get install default-jre

Chipyard should handle importing the necessary Scala and Chisel tools on first run of the simulator below.

Testing the Basics

Chipyard basically consists of these components:

  • A hardware construction toolchain meant to generate synthesizable Verilog from CHISEL, a “hardware construction language” (HCL) defined as a SCALA library.
  • Base CHISEL source for RISC-V cores, especially the Rocket core and Berkeley Out-of-Order Machine (BOOM) core.
  • A cross-compiler toolchain (riscv-gnu-toolchain) that will allow you to compile source for the RISC-V architecture.
  • Simulation tools for the cores.

We’re largely following along with the Chipyard documentation here to verify functionality. Once we know everything works correctly we can begin exploring more interesting problems.

First, navigate to chipyard/sims/verilator/ and make from that directory. Assuming everything worked in your toolchain setup above, Chipyard will generate synthesizable Verilog for a basic Rocket core from the Chisel source. When that is done, you’ll have a binary named simulator-example-RocketConfig in chipyard/sims/verilator/ (which would be the working directory). From here, we can run make run-asm-tests to test the basic functionality of the core.

At the very end of all of this, you should see some output that looks similar to the following:

  [ PASSED ] /home/brad/chipyard/sims/verilator/output/example.TestHarness.RocketConfig/rv64ui-v-lwu.out       Completed after 64605 cycles
  [ PASSED ] /home/brad/chipyard/sims/verilator/output/example.TestHarness.RocketConfig/rv64ui-v-sd.out        Completed after 84357 cycles
  [ PASSED ] /home/brad/chipyard/sims/verilator/output/example.TestHarness.RocketConfig/rv64ui-v-slliw.out     Completed after 47145 cycles
  [ PASSED ] /home/brad/chipyard/sims/verilator/output/example.TestHarness.RocketConfig/rv64ui-v-sllw.out      Completed after 65052 cycles
  [ PASSED ] /home/brad/chipyard/sims/verilator/output/example.TestHarness.RocketConfig/rv64ui-v-sltiu.out     Completed after 47052 cycles
  [ PASSED ] /home/brad/chipyard/sims/verilator/output/example.TestHarness.RocketConfig/rv64ui-v-sltu.out      Completed after 52589 cycles
  [ PASSED ] /home/brad/chipyard/sims/verilator/output/example.TestHarness.RocketConfig/rv64ui-v-sraiw.out     Completed after 52203 cycles
  [ PASSED ] /home/brad/chipyard/sims/verilator/output/example.TestHarness.RocketConfig/rv64ui-v-sraw.out      Completed after 65579 cycles
  [ PASSED ] /home/brad/chipyard/sims/verilator/output/example.TestHarness.RocketConfig/rv64ui-v-srliw.out     Completed after 47203 cycles
  [ PASSED ] /home/brad/chipyard/sims/verilator/output/example.TestHarness.RocketConfig/rv64ui-v-srlw.out      Completed after 65396 cycles
  [ PASSED ] /home/brad/chipyard/sims/verilator/output/example.TestHarness.RocketConfig/rv64ui-v-subw.out      Completed after 52501 cycles

And now we have Chipyard up and running!

Conclusion

Getting in to RISC-V development is not easy. There’s a lot of toolchain balkanization, and the tools are rapidly changing as we go. Getting fully in to RISC-V development requires some knowledge of:

  • Basic logic design.
  • Computer architecture.
  • The RISC-V assembly language (which can be explored in the excellent primer, The RISC-V Reader by David Patterson and Andrew Waterman).
  • C language programming, especially as related to the Linux kernel.
  • The Chisel Hardware Construction Language (HCL). A good tutorial on this is Digital Design for CHISEL by Martin Schoeberl. In addition to this, a good understanding of SCALA is advised since Chisel is, more or less, a SCALA library / extension.
  • The Verilog Hardware Descriptor Language (HDL), which is what Chisel ultimately generates.

Hopefully this has helped you instantiate at least a good starter environment to experiment within.