RISC-V Blog Series Introduction

Slide to adjust verbosity level 

Welcome to the blog series in which I’ll be implementing the RISC-V ISA (Instruction Set Architecture) in hardware using functional approach with PyGears. My aim is to show how PyGears offers a way to build hardware in an incremental, evolutionary fashion, where the architecture, implementation and the verification environment evolve together, as opposed to the standard approach where these steps mostly happen in sequence. Developing hardware in such an agile way offers many benefits to the hardware design process, with some of them being that:

  • I don’t need to take into the account all the requirements from the start in order to design the architecture before I start the implementation.

  • I can get an MVP (Minimum Viable Product) early, which means that I can start system testing early and try to catch errors in the design’s functional requirements as early as possible.

  • I can maintain my MVP, so that the customer can try to use the hardware at different stages throughout the development.

“Hardware” and “requirements change” are two things that were not meant to go together, but the electronics industry is developing at an ever accelerating pace so this needs to change.

Why PyGears?

Since the biggest issue with maintaining a large hardware design is synchronization (as with any other massively parallel system: think multithreading in software), PyGears tries to face it upfront by forcing each module to implement a flow-controlled interface, which turns modules into “gears” in PyGears terminology (checkout this quick introduction to gears). Gears are not built around the state, but are formed to group and abstract some functionality, while the state is embedded in the data sent between the gears. This further alleviates the synchronization problem and pipelined architectures arise naturally, as I intend to show while implementing RISC-V ISA.

\draw[thick] (0, 0) \gear{10}{2}{2.4}{16}{2}{prod}{Producer};
\draw[thick,xshift=120mm] \gear{10}{2}{2.4}{16}{2}{cons}{Consumer};
\draw[-Triangle,line width=2mm] (3, 1) -- node[above] {Data [T]} ++(6, 0);
\draw[-Triangle,line width=0.5mm] (3, -0.5) -- node[above] {Valid} ++(6, 0);
\draw[Triangle-,line width=0.5mm] (3, -1.5) -- node[above] {Ready} ++(6, 0);
\node (A) [cylinder, draw,minimum height=6.8cm,minimum width=3.8cm, label=below:DTI] at (6,0) {};

DTI - Data Transfer Interface

Gears are also assigned data types for their interfaces, which dramatically eases their composition. If gears are easily composable, then they can be used in wider variety of situations, hence they are reusable. It makes sense then to create well-thought-out and well-tested libraries of gears (like cookbook and common libraries shipped with PyGears), which pays off in the long run by reducing the design time and reducing the number of bugs.

Furthermore, PyGears is written in Python and offers a way to run RTL simulation together with asynchronous Python functions, in which arbitrary functionality for stimulus generation, value checking, logging and gathering statistics.

Writing tests as a design tool

Usually the hardware implementation effort is split between the design and verification teams, where the design team leaves all the testing to the verification. I think that this is a bad dichotomy and tend to agree with the TDD (Test-Driven Development) philosophy which points-out the importance of the developers tests. These are the tests written by the designers continuously during the development, which test each of the functional requirements of the design.

For the RISC-V implementation, I plan on treating each instruction in the ISA as a separate functional requirement, so I should have a following flow:

  1. Write a test that feeds the instruction to the processor and checks the memory and register state after the execution against the Spike RISC-V ISA simulator (which will serve as a reference model),

  2. Implement the instruction in hardware and verify that the test passes together with all the tests for the previously implemented instructions,

  3. Refactor the processor implementation.

Besides functional correctness, one additional important processor design quality parameter is its throughput. So, in addition to the functional tests for each of the instructions, I plan to use Vivado to test attainable frequency for my design.

Setup

For this series I’ll be working on Ubuntu 18.04. For the detailed description of the tools I’m going to use and how to set them up, please refer to PyGears tools setup. You can of course choose an alternative to all these tools (except for the PyGears framework itself I hope). Furthermore, PyGears has been tested to work on Windows and openSUSE as well, so feel free to use the OS of your choice. In short you will need:

  1. PyGears,

  2. An RTL simulator: I’ll be using mostly Verilator since it is open-source, but I will try to provide an option in the code to run Questa or Cadence simulators as well,

  3. A waveform viewer: I’ll be using GtkWave since again it is open-source, but if you plan on using a proprietary simulator, they will come with a waveform viewer,

  4. A constrained random solver: I’ll try to use SCV. Again proprietary simulators have support for this too,

  5. Various RISC-V tools, for which I will make further posts on how to setup and use.

I’ll be using Spacemacs for editing files and running Python scripts, but I’ll try to test the procedures I layout in blog posts on PyCharm as well.

Logistics

All the files related to the RISC-V implementation will be pyblished inside pygears_riscv git repository. At the beginning of each blog post, I will state which exact git commit contains code relevant to that post, so that you can get back in history and inspect files at that development stage. Before you can run the scripts from the pygears_riscv repository, you need to set it up:

git clone https://github.com/bogdanvuk/pygears_riscv.git

cd pygears_riscv

python setup.py develop

Notice also a slider at the beginning of the post. It allows you to choose the verbosity of the text. I plan to use it for all future posts in a fashion similar to this:

  • Verbosity level 1: Only as much information as needed to reproduce the results the post is discussing,

  • Verbosity level 2: Additional details and explanations about each of the steps involved in the discussed procedure,

  • Verbosity level 3: Various digressions, brain dumps, detailed results of the procedure steps (log files, command outputs), etc.

Comments

comments powered by Disqus