Category

Blog

SystemVerilog Linting and Formatting with FuseSoC – Verible Integration

By Blog

This post was originally published at Antmicro.

Although new ASIC design methodologies and tools such as Chisel are on the rise, most ASIC projects still use SystemVerilog, the support of which in open source tools has traditionally lagged behind. This is unfortunate, as using proprietary alternatives with the CI systems of open source projects is neither scalable due to licensing costs and restrictions nor simple due to the need for license management and obfuscation.

Antmicro, Google and the CHIPS Alliance, which we are members of, have been working together with the lowRISC project to address this issue by implementing relevant tools and useful integrations in the open source domain. One large milestone on this route is Verible, an open source Flex/YACC SystemVerilog parser, linter and formatter recently open sourced by our partner and customer, Google.

Among other developments in that space, Antmicro has been helping to make Verible support some SystemVerilog features required for working with practical use cases, such as lowRISC’s ibex, a 32-bit RISC-V core used in the open source security project, OpenTitan. But to generate adoption, ease of use is just as important as features, which is why Verible was recently exposed to a wider audience by integrating it with FuseSoC.

One of the main advantages of an open source linter/formatter is how easy it is to integrate it with existing workflows of open source projects. As it happens, many open source FPGA/ASIC projects, including OpenTitan, are managed with FuseSoC, an open source tooling and IP package manager (from our fellow FOSSi veteran Olof Kindgren) which we also use and support. Thanks to the integration of Verible with FuseSoC, linting and formatting automation becomes much easier.

Below you will find a simple example and explanation of how to use the integration The example contains an accompanying CI setup which you can mimic in your own project.

Demo

We will use the following example repository to explain the usage of Verible with FuseSoC.
We will show how to build Verible binaries, download ibex – a small 32 bit RISC-V CPU core – and run FuseSoC to perform linting/formatting using Verible.

Prerequisites

Install the prerequisites (tested on Ubuntu 18.04):

sudo apt update
sudo apt install cmake ninja-build wget python3 python3-pip python3-setuptools make tar git
sudo pip3 install fusesoc

Building Verible

Verible can be built using the Bazel build system.
Bazel is not available in the debian/ubuntu apt repositories. To install Bazel you should add Bazel’s apt repository:

curl https://bazel.build/bazel-release.pub.gpg | sudo apt-key add -
echo "deb [arch=amd64] https://storage.googleapis.com/bazel-apt stable jdk1.8" | sudo tee /etc/apt/sources.list.d/bazel.list
sudo apt update && sudo apt install bazel

To build Verible, a C++11 compatible compiler is required. After the installation of bazel, Verible can be built and installed:

git clone https://github.com/google/Verible
cd Verible
bazel build -c opt //...
bazel run :install -c opt -- `pwd`/../Verible_bin
export PATH=`pwd`/../Verible_bin/:$PATH

Alternatively, you can download pre-built Verible binaries from the Verible release page. Refer to the Verible documentation and Bazel installation instructions for more details.

Running Verible tools with FuseSoC

FuseSoC uses tool backends available in edalize, which is another workflow automation project from the same author that we contribute to regularly. In order to use the Verible tools with FuseSoC you need to define a tool section in the FuseSoC core target file. Ibex already includes the integration, so you can use its ibex_core.core file as an example.

Verible linter with FuseSoC on ibex

To perform linting in ibex_core, use:

git clone https://github.com/lowRISC/ibex
cd ibex
#add Verible lint rules
sed -i '132i\          - "-generate-label"\n          - "-unpacked-dimensions-range-ordering"\n          - "-explicit-parameter-storage-type"\n          - "-line-length"\n          - "-module-filename"\n          - "-no-trailing-spaces"\n          - "-undersized-binary-literal"\n          - "-struct-union-name-style"\n          - "-case-missing-default"\n          - "-explicit-task-lifetime"\n          - "-explicit-function-lifetime"' ibex_core.core

fusesoc --cores-root. run --target=lint --tool=veriblelint lowrisc:ibex:ibex_core:0.1

Verible formatter with FuseSoC on ibex

To format the ibex_core with Verible:

#add Veribleformat rules
sed -i '154i\          - "--max_search_states"\n          - "10000000"' ibex_core.core
fusesoc --cores-root . run --target=format --no-export lowrisc:ibex:ibex_core:0.1

The demo also shows how the Verible linter can be incorporated into CI pipelines for automatic detection of lint errors. To demonstrate that, a Pull Request containing an intentional lint error has been opened. An automatically executed CI pipeline was able to detect the issues with the code and inform the developers about the failed build status. The output of the lint command can provide useful information about a possible cause of the error. Early detection of lint errors can reduce the number of bugs and improve the overall code quality. Using a linter can accelerate development and reduce costs by finding errors at an early stage of the process. Moreover, incorporating the Verible formatter in CI can also ensure that incoming contributions automatically employ the project’s coding style.

More detailed instructions regarding building and using Verible with FuseSoC can be found in the README file located in the demo repository.

If you are involved in FPGA and ASIC development and want your project to be portable, modular and harness other benefits of a software-driven, open-source-based approach, Antmicro is there to help. As a key service provider in both RISC-V Foundation and CHIPS Alliance, we have lots of readily available SoC building blocks, tools and capabilities to assist you in developing your next product or platform.

Open Source USB test suite

By Blog

Note: the open source test suite will be demonstrated at the CHIPS Alliance booth at the RISC-V Summit 2019 – join us Dec 10-12 in the San Jose Convention Center!

USB is often a daunting topic for developers, and implementing support for it from scratch is a time consuming task. When the expected result is more complicated than a USB-to-serial bridge, the solution would be to either use a hardware transceiver or, especially for older USB standards, use an open source core to implement one directly in the FPGA fabric. But which core to use?

There are many different USB IP cores available, implemented in languages ranging from traditional HDLs like Verilog to modern alternatives like migen (or its new variant, nmigen). Most of them come with their own set of test cases, often checking their internal mechanisms and not corresponding directly to those in other projects. What was lacking is a unified test suite that would run each core through the same set of scenarios, providing a direct, apples-to-apples comparison of their behavior.

A solution from Antmicro, a CHIPS Alliance Gold member, is an open source test suite for USB IP cores, available on their Github. It currently supports USB1.1 and will be extended for higher revisions in the future.

In the test suite, Antmicro is making use of several open source technologies that they have come to appreciate through other projects. The tests are implemented using Cocotb and the low-level details are handled by the newly created cocotb_usb package. This means that even complicated tests, like those that verify the enumeration procedure under different OSes can be written with easy to understand, Python syntax.

from cocotb_usb.harness import get_harness
from cocotb_usb.device import UsbDevice
from cocotb_usb.descriptors import Descriptor

@cocotb.test()
def test_enumeration(dut):
    harness = get_harness(dut)
    yield harness.reset()
    yield harness.connect()

    yield Timer(1e3, units="us")

    yield harness.port_reset(1e3)
    yield harness
          .get_device_descriptor(response=model
              .deviceDescriptor.get())

    yield harness.set_device_address(DEVICE_ADDRESS)

Test suite architecture

As the various IP cores often provide different interfaces towards the user, from different kinds of FIFOs to expected signals to drive the bidirectional USB pins, they are wrapped in a unified layer to create a simple SoC, also written in Python using LiteX. It provides various helper blocks and takes care of the bus infrastructure, clocking and reset logic, generating Verilog output for the whole system ready to be tested under any number of open source simulators. A minimalistic testbench file provides a unified interface as the top object for the simulation.

USB testing diagram

Python package

At the heart of the test suite is cocotb_usb, a Python package providing API for sending and receiving various USB packets, handling low-level bus states, verifying descriptor contents and checking timings. This is done by providing a UsbTest object that acts as a host and interacts with the device under test. Depending on your needs, you can output single packets, use whole transactions with e.g. automated retries upon receiving “not acknowledged” tokens, or just use high-level functions like get_config_descriptor() and let the library handle all the details. Meanwhile, the UsbDevice class provides means to store all of the descriptors that the core can report in an organized way.

The test results can be viewed in a standard Cocotb XML results file, the behavior of all signals in the system at all points can be checked in a VCD signal dump (to be viewed e.g. in GTKWave) and we use open source sigrok decoders to obtain packets and transactions, to be exported for viewing in Wireshark.

Test results in GTKWave

Current checks

Currently tested cores are:

  • ValentyUSB – CPU-less IP core written in LiteX, using the eptri interface
  • Foboot – target with VexRiscv CPU running bare-metal Foboot firmware (it utilizes the epfifo interface of the ValentyUSB core)
  • usb1_device – a USB1.1 IP core developed by asics.ws in Verilog
  • TinyFPGA USB bootloader – IP core written in Verilog with interesting features, like providing an interface to program SPI flash memory over USB
  • tnt`s USB IP core – target with a PicoRV32 CPU, running bare-metal firmware interfacing with the Verilog IP core

So, what tests are supported? They range from a simple control packet handling with both single and multiple transfers, through handling SOF packets, validating clock recovery in the presence of an imperfect clock signal, to complex enumeration scenarios under Linux, Windows 10 and macOS. There are also some special cases, like testing the ValentyUSB core without a CPU by configuring it through a Wishbone bus, or verifying behavior of the TinyFPGA-Bootloader by using CDC transfers to send a boot command to the core.

Contributing

While full blown documentation is coming soon, there are ways to get involved right now:

  • First, to run the test suite, go to the repository and follow the steps in the README,
  • To write your own test, take a look at our tests folder and the functions provided by the UsbTest class,
  • To run the tests on another IP core, you will need to prepare a simple LiteX wrapper, a config file with expected descriptor values that the core will return and a Makefile that will point to the needed files and provide the needed steps,
  • If you would like to test a different USB class that your target supports, head to the cocotb_usb repository and feel free to extend it with that class’ descriptors and requests.

Podcast – Embedded Computing Design – Five Minutes With… Zvonimir Bandic, Chairman, Chips Alliance

By Blog

Zvonimir Bandic wears lots of hats. He is the Senior Director of Hardware Platforms for Western Digital; he’s a Member of the Board of Directors for the RISC-V Foundation, and he’s the Chairman of the Chips Alliance. It’s that latter capacity that we discussed in this week’s Five Minutes With…discussion. The organization focuses on things like open source hardware, software tools, RTL development, and related topics. They will be holding their inaugural workshop in just a few weeks, so it was timely to understand the purpose of the Alliance. And now I do, as will you.

Listen to the Podcast »