Core#

This section covers the definition of configuration/declaration files for users to describe the sources and parameters that compose an HDL project. Several JSON/YAML/INI formats are supported by different tools in the ecosystem. Here, we don’t want to focus as much on the specific file format as we do want to understand the structure of the data. A Python module is proposed for interacting with those file formats.

Introduction#

FuseSoC is a package manager and build abstraction tool for FPGA/ASIC development, written in Python. It is based on a declarative data sctructure, defined as a YAML configuration file format named Core API (CAPI). The current version 2 of the format is named CAPI2 (see fusesoc.rtfd.io: ref/capi2). A single YAML file can be used for defining all the sources and parameters related to multiple tools for simulation, verification, synthesis, etc.

Initially, FuseSoC was a monolith that allowed interacting with FPGA/ASIC tools directly. Later, Edalize was split, and an API named EDA Metadata (EDAM) was proposed for the interaction from FuseSoC or other frontends. Hdlmake is one of the projects that can use Edalize through EDAM.

Nevertheless, the proposal for funneling all open source project management tools through Edalize didn’t engage the broad open source hardware tooling community. Multiple projects (such as VUnit, pyIPCMI, PyFPGA, tsfpga or Xeda ) provide independent APIs and CLIs for interacting with FPGA/ASIC tools. Most of them are also standalone monoliths with custom configuration file formats. Therefore, workflows are not compatible, and users need duplicated configurations for addressing the requirements of each tool.

There have been some integration efforts; for instance, supporting VUnit scripts as FuseSoC/Edalize targets. However, there is a paradigm conflict, since FuseSoC expects to be the entrypoint and Edalize is to be the backend. Therefore, integration of other tools is only conceived as plugins in the already constrained framework. Doing so breaks the workflows that the user bases of other projects do rely on.

The proposal in this bundle is to provide a reusable Python module named pyCAPI, for reading CAPI files and manipulating the data through a pythonic API. pyCAPI allows FPGA/ASIC tool management projects to consume *.core configuration files non-intrusively, by providing complementary import APIs. Thus the CLIs in the existing workflows are preserved, without forcing FuseSoC as a frontend and/or Edalize as a backend. Hopefully, pyCAPI reduces the burden for users to try and learn new tools, while developers/maintainers can carefully analyse possible integration strategies with regard to the other APIs in the architecture.

pyCAPI usage block diagram

Fig. 2 Usage of pyCAPI as a utility library for multiple EDA management projects.#

FuseSoC does contain some Python code for reading and parsing CAPI2 files (see olofk/fusesoc: fusesoc/capi2). Unfortunately, it is challenging to work with. On the one hand, it uses pyyaml for reading *.core files as Python dictionaries and lists. As a result, the procedure for providing Python classes is manual and prone to error. On the other hand, the format is documented in the sources of the code, but the code itself is undocumented.

Conversely, pyCAPI is a proof of concept based on Python dataclasses for direct (un)marshalling of YAML to/from Python classes. Hence, the CAPI2 format is not supported as-is yet: some non compliant fields were modified, and the prototype is limited to reading filesets. This work-in-progress version of CAPI is marked as 3, for avoiding conflicts with existing *.core files. Still, pyCAPI does already allow VUnit to read *.core files for declaring HDL sources and the logical_name of the libraries where they need to be compiled. I.e., it allows providing a working proof of concept, constrainted to the simulation/verification scope of this bundle.

Feedback and contributions for making pyCAPI compatible with and supported by FuseSoC, VUnit, PyFPGA, pyIPCMI, etc. are very welcome! Open an issue or join the chat!

CAPI reference#

class pyCAPI.IpCoreConfig[source]#

Each core file must contain an ‘ipcore’ field with the metadata of the design.

name: str = None#
namespace: str = None#
version: str = None#
class pyCAPI.FilesetConfig[source]#

A Fileset is a group of sources of the same type, to be used together.

file_type: str#
files: List[str] = None#
logical_name: str#
path: str#
class pyCAPI.Config[source]#

Definition of the CAPI 3 format for core configuration files.

CAPI: int = None#
filesets: Dict[str, FilesetConfig] = None#
ipcore: IpCoreConfig = None#
pyCAPI.LoadCoreFile(coreFilePath)[source]#

Load a CAPI 3 compliant core configuration file and unmarshal it.

Parameters:

coreFilePath – location of the *.core file to be loaded.

pyCAPI.VUnit.AddCoreFilesets(vunitHandle, core, filesets)[source]#

Add the sources of some filesets from a CAPI 3 compliant core, into a VUnit handle through VUnit’s API (add_library and add_source_files).

Parameters:
  • vunitHandle – handle to the VUnit object instance.

  • core – CAPI 3 compliant object (coming from LoadCoreFile).

  • filesets – name of the filesets to be added into the VUnit handle.

References#