Making open source SystemVerilog synthesis easier with the UHDM plugin for Yosys

Published:

Topics: Open source tools, Open ASICs

At Antmicro we strongly believe that open source flows are key to bringing software-driven innovation into the ASIC space, in order to build a collaborative ecosystem and scalable, reproducible and publicly available components tested in CI.

Since much of the chipmaking industry uses SystemVerilog for their development and verification, open source parsing and synthesis tools are needed for this HDL.

Last year we enabled a fully open source SystemVerilog parse and synthesize flow of OpenTitan’s Ibex core using UHDM and Yosys, which couldn’t be achieved without UHDM (Universal Hardware Data Model) and Surelog, two open source tools developed within the CHIPS Alliance. The original work introduced changes into Yosys which effectively meant that in order to use our flow, you had to use a specific Yosys version; thanks to our recent work, the UHDM plugin can be used with vanilla Yosys, and is a drop-in replacement for the built-in Verilog support.

UHDM and the Yosys UHDM plugin

UHDM is an intermediate format for expressing designs which auto-generates the VPI (Verilog Programming Interface) used by other tools to traverse designs. This allows us to decouple parsing and elaboration from the actual tool, which means extending the frontend provides benefits in all the supported “backend” tools. Thanks to Antmicro’s work, UHDM is accepted by multiple tools, most notably Yosys and Verilator, the most popular open source choices for HDL synthesis and simulation respectively.

Yosys allows you to dynamically load plugins that extend its basic functionality. Using this feature, we can easily add UHDM support to local Yosys installations (e.g. installed with your regular package manager) without the need to rebuild anything. To make it even easier for users to install the plugin, we provide an installation script on our GitHub releases page:

# make sure curl, jq, tar and wget are installed
apt install curl jq tar wget
# download and unpack the latest release of the plugin
curl https://api.github.com/repos/antmicro/yosys-uhdm-plugin-integration/releases/latest | jq .assets[1] | grep "browser_download_url" | grep -Eo 'https://[^\"]*' | xargs wget -O - | tar -xz
# make sure yosys is installed and correctly configured
yosys –version
yosys-config –help 
./install_plugin.sh

The plugin is now ready to be used.

Consider the following Verilog code:

module top (
  input clk,
  output [3:0] led
);
  localparam BITS = 4;
  localparam LOG2DELAY = 22;

  wire bufg;
  BUFG bufgctrl (
      .I(clk),
      .O(bufg)
  );
  reg [BITS+LOG2DELAY-1:0] counter = 0;
  always @(posedge bufg) begin
    counter <= counter + 1;
  end
  assign led[3:0] = counter >> LOG2DELAY;
endmodule

Running the synthesis using the plugin is very simple:

yosys> plugin -i uhdm
yosys> read_verilog_with_uhdm -parse counter.v 
1. Executing Verilog with UHDM frontend.
[INF:CM0023] Creating log file ./slpp_all/surelog.log.

[WRN:PA0205] counter.v:1: No timescale set for "top".

[INF:CP0300] Compilation...

[INF:CP0303] counter.v:1: Compile module "work@top".
(...)
Generating RTLIL representation for module `\top'.

yosys> synth_xilinx

2. Executing SYNTH_XILINX pass.

(...)
                                                                                                                                                                                                                                                   
3.50. Printing statistics.                                                                                                                                                                                                                                                                
                                                                                                                                                                                                                                                                                          
=== top ===                                                                                                                                                                                                                                                                               
                                                                                                                                                                                                                                                                                          
   Number of wires:                 10                                                                                                                                                                                                                                                    
   Number of wire bits:            167                                                                                                                                                                                                                                                    
   Number of public wires:           4                                                                                                                                                                                                                                                    
   Number of public wire bits:      32                                                                                                                                                                                                                                                    
   Number of memories:               0                                                                                                                                                                                                                                                    
   Number of memory bits:            0                                                                                                                                                                                                                                                    
   Number of processes:              0                                                                                                                                                                                                                                                    
   Number of cells:                 40                                                                                                                                                                                                                                                    
     BUFG                            1                                                                                                                                                                                                                                                    
     CARRY4                          7                                                                                                                                                                                                                                                    
     FDRE                           26                                                                                                                                                                                                                                                    
     IBUF                            1                                                                                                                                                                                                                                                    
     INV                             1                                                                                                                                                                                                                                                    
     OBUF                            4                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                          
   Estimated number of LCs:          0                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                          
3.51. Executing CHECK pass (checking for obvious problems).                                                                                                                                                                                                                               
Checking module top...                                                                                                                                                                                                                                                                    
Found and reported 0 problems.                                                                                                                                                                                                                                                            
                                                                                                                                                                                                                                                                                          
yosys> write_edif counter.edif                                                                                                                                                                                                                                                            
                                                                                                                                                                                                                                                                                          
4. Executing EDIF backend.                                                                                                                                                                                                                                                                

As a result we get a counter.edif file that can be further processed to get the bitstream.

Demo below.

For more information about the installation process and the plugin itself please refer to the README.md file.

How it works

When we started designing the UHDM plugin, we focused on the end user experience. We wanted to make sure that a user who already is familiar with Yosys could easily add the UHDM plugin into their existing flows. In order to achieve that, we use Surelog as a static library compiled into the plugin. This way, we are providing all the dependencies in a single dynamically loaded library.

Diagram of the flow

When converting the design from the UHDM format, the plugin uses two helper functions: visit_one_to_one (traversing 1-1 relations in VPI) and visit_one_to_many (traversing 1-many relations in VPI). Those helper functions accept a lambda that is executed for each of the nodes according to its type and an appropriate AST is created. When UHDM is converted into Yosys AST it is passed to another frontend (already existing in Yosys) that converts AST nodes to RTLIL. RTLIL is used to represent netlist data with the addition of addressable memories and processes. This approach allowed us to add new functionality to Yosys without modifying any of the existing code.

Comparing SystemVerilog support

The SystemVerilog test suite, that we developed and donated into the CHIPS Alliance, was very useful in comparing support of different SystemVerilog features between multiple tools. It runs tests covering a range of SystemVerilog features on different tools and generates a table with results. While closely tracking our progress using sv-tests we were able to significantly surpass the number of individual tests passing using UHDM frontend, compared to tests passed using the regular Yosys Verilog frontend.
This proves that the UHDM plugin is ready to be used in your SystemVerilog projects!

Antmicro’s and CHIPS’ ongoing effort is to enable fully open source toolchains for both FPGA and ASIC, as well as open source synthesis flow for both public CIs and hybrid installations. If you want to introduce more software-driven innovation into your hardware development flows and develop tools customized for your needs, reach out to us at contact@antmicro.com and find out how we can help with your project.

See Also: