I'm Adithya Sunil and I have been working on porting BaseJump STL to FuseSoC under the GSoC’21 program at FOSSi. From the day the selected projects were announced to this very day, this whole journey has been nothing short of a roller coaster ride. It had its ups and downs but it's been full of excitement either way. This is one summer I will always look back to as one of the most productive. I have most certainly learnt a lot from the project and perhaps even more from my mentors. Now, let me try to summarize my work over this summer and the project.
About the Project
BaseJump STL is to the hardware world as C++ STL is to the software world. It is a comprehensive hardware library for SystemVerilog that seeks to contain all the commonly used hardware primitives. FuseSoC is a package manager and set of build tools for reusable hardware building blocks facilitating the sharing of designs between projects and reusing open IP cores.
The objective of my project is to port BaseJump STL to FuseSoC so that new projects can directly reuse these hand-optimized IP cores rather than starting from scratch. BaseJump STL has the hardware primitives defined in the form of SystemVerilog modules. FuseSoC makes use of core files that reference the provider, file sets and default targets allowing for the reuse of IP cores in the process of creating, building and simulating SoC solutions. FuseSoC allows for easier tracking and downloading of dependencies as well as versioning using VLNV tags making it much more convenient to work with large cores as well as keep track of changes to these cores. This project will involve porting all the modules as well as the testing infrastructure in BaseJump STL to work with FuseSoC.
- Create core files for all BaseJump STL modules
- Add lint targets for all cores
- Port testbenches to work with verilator
- Add verilator testbench targets for cores with testbenches
- Create FuseSoC generator for generated cores like
To see more details about my contributions you can check out my progress report below.
GitHub — adithyasunil26/GSoC-21-Project-Report: Final report for Google Summer of Code 2021 project…
Organisation: The Free and Open Source Silicon Foundation (FOSSi) Mentors: Dan Petrisko, Prof. Michael B. Taylor and…
The Journey (and more about the project)
The first thing I did before starting the project was fully understanding the need for the project and state at that time of BaseJump STL and FuseSoC. I have summarized it as follows.
FuseSoC is a package manager and set of build tools for reusable hardware building blocks facilitating the sharing of designs between projects and reusing open IP cores. One of the major challenges of working on fairly large and complicated hardware projects is tracking dependencies and versioning these dependencies. FuseSoC is a simple and effective solution to this problem.
- FuseSoC is non-intrusive: Most existing designs require no changes to work with FuseSoC
- FuseSoC is modular: FuseSoC can be used to create an end-to-end flow
- FuseSoC is extendable: Supports a wide variety of simulating and EDA tools and new EDA tools can also be added pretty easily
- FuseSoC is standard-compliant: Much effort has gone into leveraging existing standards such as IP-XACT and vendor-specific core formats where applicable
- FuseSoC is resourceful: FuseSoC already has a standard core library currently consisting of over 100 cores. Other core libraries exist, and more can be added to complement the standard library.
- FuseSoC is free software: It puts no restrictions on the cores and can be used to manage your company’s internal proprietary core collections as well as public open-source projects
- FuseSoC is battle-proven: It has been used to successfully build or simulate projects such as Nyuzi, Pulpino, VScale, various OpenRISC SoCs, picorv32, osvvm and more.
Why is it important?
BaseJump STL contains a lot of hardware blocks that come in handy when working on projects. Still, it may not be easy to use for many as one would have to manually handle the parameters and modify them to fit their existing project structure, which may already be using FuseSoC. On the other hand, having FuseSoC cores for the BaseJump STL blocks would make it a matter of just adding a few lines (if not a single line) to your current project core to use that block across your project. Yes, it’s as simple as that.
How is this done?
FuseSoC makes use of cores. The FuseSoC package manager can discover cores stored locally or remotely and combine them into full hardware designs.
A FuseSoC core can be defined as a reasonably self-contained, reusable piece of IP. It is analogous to packages in npm. All the details of a core, such as the source files as well as the targets, dependencies and parameters, are contained in a description file known as the core file. These files have a
.core filename extension.
So you might have guessed by this point that a big part of my job is to make these core files for the different cores in BaseJump. The other objectives of the project include creating test benches for different target simulators and EDA tools as required.
The porting process was actually quite straightforward. Each core module must have a core file with which FuseSoC can recognise it and reference it across different cores. So, the first step is creating core files for BaseJump STL modules. The next step in the process would be adding targets for the cores. Targets are workflows or simulators that you would like to push the core through. A simple first target would be a verilator lint-only and the next one would be a verilator testbench. Along with the targets, for the correct functioning of the modules, we need to have all the parameters of each core defined in the core file and set as required for each target or left empty if we want to pass the default value.
For those who are curious about the structure of a core file, I have added below the first core file I made which was for the
Verilator is an open-source tool that converts Verilog code to its cycle-accurate behavioural model in C++ or SystemC. It does not simply convert the code, but it also compiles the code into much faster-optimized models, which are in turn wrapped inside C++ or SystemC modules.
Verilator models execute 10 times faster than standalone SystemC and 100 times faster than interpreted Verilog simulators like Icarus Verilog on a single thread. Multi-threading yields another 2–10x speedup.
Verilog is similar or has better performance than the closed-source simulators used in the industry. Verilator being open-sourced provides the best cycles/dollar as you only need to spend on the computes and not licenses.
Verilator is very unforgiving in terms of non-synthesizable code blocks. To be able to use testbenches with verilator, they will have to be synthesizable. Commonly used shortcuts in Verilog testbenches such as manual delay elements cannot be present when working with verilator.
In addition to the SystemVerilog testbench, we will have to write a C++/SystemC wrapper file that instantiates the verilated models. C++ compilers then compile these C++/SystemC files. The resulting executable performs the design simulation.
Generators in FuseSoC are used to produce and specialize cores on demand. Core files contain a list of file sets with files written in SystemVerilog, C++, etc. These files are usually created to fulfil a general purpose in all use cases, but this is impossible in some instances. Certain applications require specialized files that are generated on demand based on certain parameters. This is where generators come into play.
Generators serve as a mechanism to generate core files on the fly during the FuseSoC build flow. There are 3 main components required for generating core files during the build flow:
- Generator file: A generator file can be written in any language that is executable on the command line and accepts YAML configuration files as its first argument. Shown below is a generator file I have created to run a python script that generates a SystemVerilog file
bsg_round_robin_arb.vand adds it to the core that calls this generator.
- Generator core: These are core files that contain a section called
generatorsthat is used to notify FuseSoC that they contain a generator and describe how to use it. Each core can have multiple generators defined in it. FuseSoC will use the defined interpreter to run the command and pass the configuration file as the first argument. Shown below is a generator core written for the previously described
- Core using the generator: The final step in the generator creation process is calling the generator from a core in which we wish to insert the generated file. This is done by adding a
generatesection to the core where the generator is registered and invoking the generator in the targets requiring it. Shown below is the core file
bsg_round_robin_arbthat requires the SystemVerilog file generated by the generator.
The generate section of the above core shows the generator being referenced and the value of the parameter
channels being defined.
bsg_fakeram generates black-boxed SRAMs that can be used in CAD flows when SRAM generators are absent or don’t exist. On giving a simple JSON configuration file containing technology node and SRAM sizing details as input, the generator will create the required block-box SRAM modules.
A sample configuration file is as follows
To use the BSG Black-box SRAM generator through fusesoc, we need to create a FuseSoC generator. I followed an approach similar to that of
bsg_round_robin_arn from previous week. The FuseSoC generator is as follows
The generator core is as follows
Now to use this in a core, we can simply call it like any other FuseSoC generator. The only parameter required is the config file location which has to be defined for
bsg_fakeram to work. An example core and config file are as follows
Running this core will generate the following black-box SRAM module
To demonstrate the functioning of the project i.e., BaseJump STL integration into FuseSoC, a design has been created that makes use of BaseJump STL cores.
I have created a simple ALU that performs AND, XOR, NAND and ADD functions on its inputs. The block has 2 input signals A and B and a 2 -bit control signal which acts as the select line for selecting the operation to be performed on the inputs. The block has a single output signal which is the result of the selected operation.
The AND, XOR, NAND and ADD cores are available in BaseJump STL.
The SystemVerilog description for the design is as follows
A simple testbench can be written to test its functionality
The FuseSoC core file is as follows
The functionality of this core has been verified and it is working as expected. The next step in the process is to integrate a generator into this core. I have added the
bsg_fakeram generator to this core and linked the ALU to the generated black-boxed SRAM. The SRAM module is added to the testbench and the pins are connected as required. The testbench is as follows
The new core file is as follows
The outputs of this core have also been verified manually and it is as expected.
This demonstrates a use case of the project. A lot of circuits can be constructed using the cores available in BaseJump STL and the integration of FuseSoC streamlines this process and allows users to define multiple flows for simulations or synthesis without having to manually handle the dependencies themselves as it is all taken care of by FuseSoC.
Empty testbenches were added for all the cores so that testbench targets can be run now. These empty testbenches can later be modified into real testbenches as and when required.
A sample empty testbench is as follows.
The targets have also been added to all the cores.
Yosys is a framework for Verilog RTL synthesis. It currently has extensive support for Verilog-2005 and limited support for SystemVerilog.
Some of the features of yosys are as follows
- Process almost any synthesizable Verilog-2005 design
- Converting Verilog to BLIF / EDIF/ BTOR / SMT-LIB / simple RTL Verilog / etc.
- Built-in formal methods for checking properties and equivalence
- Mapping to ASIC standard cell libraries (in Liberty File Format)
- Mapping to Xilinx 7-Series and Lattice iCE40 FPGAs
- Foundation and/or front-end for custom flows
FuseSoC has yosys support which makes it easy to synthesize through FuseSoC. Yosys is also used as a part of other flows like Symbiflow and Icestorm. Adding a Yosys target to BaseJump STL cores will allow for easier synthesis which would in turn help in FPGA development.
A yosys target can be defined as follows
arch parameter is used to tell yosys which series of FPGA’s we wish to synthesize for as yosys supports multiple vendors. The output format parameter is used to select the output format as json, edif or blif. The
-sv tag passed to yosys enables SystemVerilog support.
A small modification had to be made to the current BaseJumo macros in order to use the modules with yosys.
Yosys does not allow the use of bare default parameters and hence the marco is modified as follows
This will allow yosys to synthesize all the cores that contain only supported SystemVerilog features.
This sums up the journey of this project from the very beginning to the end.
- Core files have been created for all the BaseJump STL modules
- Lint targets have been added and tested
- All existing and compatible testbenches were modified to work with verilator
- Verilator testbenches have been added to the cores
- FuseSoC generator created for
- Empty testbenches have been added for modules without testbenches (can be modified later as required to perform actual testing)
- FuseSoC generator created for
- ALU module created as a proof of concept of the project and tested successfully
- Yosys targets have been added to all cores
- Started work on porting
The proposed project is completed. All the objectives that were a part of the proposal have been completed. Certain additional objectives had been undertaken along the course of the project to better the project, allow it to serve more users and create the foundation for future additions to this project. Many of these objectives have also been completed while some of them are in progress or yet to be done. I will continue working on this project in my free time and try to complete these objectives in a systematic manner.
- Establish a CI\CD pipeline for BaseJump STL
- Complete porting
- Add FuseSoC targets for industrial tools like VCS to the BaseJump STL cores.
- Explore the possibility of adding open-source FPGA and ASIC flows