FuseSoC
=======

ifdef::env-github,env-browser[:outfilesuffix: .adoc]
FuseSoC is a package manager and a set of build tools for HDL code.

Its main purpose is to increase reuse of IP cores and be an aid for creating, building and simulating SoC solutions.

The package manager part can be seen as an apt, portage, yum, dnf, pacman for FPGA/ASIC IP cores. A simple ini file describes mainly which files the IP core contains, which other IP cores it depends on and where FuseSoC shall fetch the code.

A collection of cores together with a top-level is called a system, and systems can be simulated or passed through the FPGA vendor tools to build a loadable FPGA image.

Currently FuseSoc supports simulations with ModelSim, Icarus Verilog, Verilator, GHDL, Isim and Xsim. It also supports building FPGA images with Project Icestorm, Xilinx ISE and Altera Quartus.

Core description files
----------------------

capi (Core API) is the format for core description files. Current version is version 1.0. A capi 1.0 file is identified by the string "CAPI=1" in the beginning of a file. The rest of the file is a standard http://en.wikipedia.org/wiki/INI_file[INI file] that is compatible with Python's http://docs.python.org/2/library/configparser.html[configparser] module. The options available for `.core` files are described in the link:capi1{outfilesuffix}[Core API definition]

link:createcore{outfilesuffix}[This tutorial] describes how to create your own .core files

Core naming rules
~~~~~~~~~~~~~~~~~

FuseSoC uses `VLNV` tags to uniquely identify a core. `VLNV` is a concept borrowed from the IP-XACT and stands for Vendor Library Name Version. This means that the name of the cores consists of four parts, which are generally separated by ':', such as `librecores.org:peripherals:uart16550:1.5`. In FuseSoC, it is allowed to leave out all parts of the VLNV tag except for the name part, e.g `::uart16550`. In those cases, the Vendor and Library parts will be empty strings, and the version will be set to 0.

As the VLNV concept was introduced in FuseSoC after many core files had already been created, FuseSoC still supports parsing files with the legacy naming convention. These can either be of the format `name`, in which case they will be translated internally to VLNV tags with the Name field set, and Version set to 0, or they can be of the format `name-version`, which will also set the Version field.

FuseSoC will pick up the core identifer from the `name` option in the `[main]` section of `.core` files. If no identifier is specified there, the name of the core file without the `.core` suffix will be used and treated as a legacy name.

As an extension to the VLNV naming scheme, FuseSoC also support specifying a revision of a core file. This is a fifth field that can be added to both legacy and VLNV names by adding `-r<revision>` as a suffix (e.g. `::uart16550:1.5-r1`, `uart16550-1.5-r1`, `uart16550-r1`). This is used to make updates to the `.core` file even if the source of the core is unchanged.

Core libraries
~~~~~~~~~~~~~~

A collection of one or more cores in a directory tree is called a core library. FuseSoC supports working with multiple core libraries. The locations of the libraries are specified in the FuseSoC configuration file, `fusesoc.conf`

To find a configuration file, FuseSoC will first look for `fusesoc.conf` in the current directory, and if there is no file there, it will search next in `$XDG_CONFIG_HOME/fusesoc` (i.e. `~/.config/fusesoc` on Linux and `%LOCALAPPDATA%\fusesoc` in Windows) and lastly in `/etc/fusesoc`

By running `fusesoc init` after FuseSoC is installed, the standard libraries will be installed, and a default configuration file will be created in `$XDG_CONFIG_HOME/fusesoc/fusesoc.conf` with the following contents:

    [main]
    cores_root = ~/.local/share/fusesoc/orpsoc-cores ~/.local/share/fusesoc/fusesoc-cores

Core search order
^^^^^^^^^^^^^^^^^

Once FuseSoC has found its configuration file, it will parse the `cores_root` option in the `[main]` section of `fusesoc.conf`. This option is a space-separated list of library locations which are searched in the order they appear. Additional library locations can be added on the command line by setting the `--cores-root` parameter when FuseSoC is launched. The library locations specified from the command-line will be parsed after those in `fusesoc.conf`

For each library location, FuseSoC will recursively search for files with a _.core_ suffix. Each of these files will be parsed and addded to the in-memory FuseSoC database if they are valid `.core` files.

Once a `.core` file is encountered in a directory and successfully parsed, FuseSoC will not search its subdirectories. Several `.core` files can reside in the same directory and they will all be parsed.

.Locations of core description files. 
========
. library/mor1kx/mor1kx-3.2.core
. library/mor1kx/mor1kx.core
. cores/uart16550/uart16550.core
. de0_nano/de0_nano.core
. de0_nano/uart/spi/simple_spi.core +
_1 and 2 reside in the same directory and are both parsed. 5 is not parsed since it resides in a subdirectory of 4_
========

If several cores with the same VLNV identifier are encountered the latter will replace the former. This can be used to override cores in a library with an alternative core in another library by specifying them in a library that will be parsed later, either temporarily by adding `--cores-root` to the command-line, or permanently by adding the other library at the end of the `cores_root` parameter in the configuration file.

Making changes to cores in a library
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

A common situation is that a user wants to use their own copy of a core, instead of the one provided by a library, for example to fix a bug or add new functionality. The following steps can be used to achieve this:

.Replace a core in a library with a user-specified version
==========
1. Create a new directory to keep the user-copies of the cores (this directory will be referred to as `$corelib` from now on)
2. Download the core source (the repository or URL can be found in the `[provider]` section of the original core)
3. *If the downloaded core already contains a .core file, this step is ignored* Copy the original .core file to the root of the downloaded core. Edit the file and remove the `[provider]` section. (This will stop FuseSoC from downloading the core and use files from the directory containing the .core file instead)
4. Add `$corelib` to the end of your library search path, either by editing `fusesoc.conf` or by adding `--cores-root=$corelib` to the command-line arguments
5. Verify that the new core is found by running fusesoc core-info $core. Check the output to see that "Core root: " is set to the directory where the core was downloaded
==========

Backends
--------

FPGA implementation
~~~~~~~~~~~~~~~~~~~

FPGA implementation flows are used to build binary FPGA configuration files (bitstreams) to be downloaded to an FPGA target. The FPGA implementation flows are uusually tied to a single FPGA vendor's devices

- link:icestorm{outfilesuffix}[IceStorm]

Running simulations
~~~~~~~~~~~~~~~~~~~

Simulation flows are used to simulate HDL designs and are generally independent of the intended target device. Exceptions to this are when vendor-specific modules are instantiated in the source code, which might require vendor-specific libraries that are only available for some simulators.

To run a simulation with FuseSoC, the `sim` subcommand is used followed by general simulator options, the core to simulate and core-specific options.


`fusesoc sim <core> --help` lists all core-specific options

Example:

`fusesoc sim --sim=modelsim de0_nano --vcd --timeout=100000 --bootrom_file=spi_uimage_loader.vh`

The above command would build a simulation model and run a simulation of the de0_nano core using the core's default testbench and explicitly using modelsim. If no simulator is selected, FuseSoC will use the default simulator which is selected by the core. A different testbench can be selected by setting the --testbench option. Use `fusesoc sim --help` to list all general simulator options

The parameters vcd, timeout and bootrom_file would be passed to the simulator. While all three parameters look the same on the CLI (expect for vcd, which has no value associated with it), they are handled differently inside of FuseSoC.

`vcd` and `timeout` would be passed as plusargs to the simulator at run-time, while `bootrom_file` would be passed as a top-level parameter during compile-time.

The cores themselves are responsible for describing in the .core file which externally accessible parameters they support. This is what the corresponding sections in the .core file look like

----
[parameter timeout]
datatype    = int
description = Abort test case after n cycles
paramtype   = plusarg
scope       = public

[parameter vcd]
datatype    = bool
description = Enable VCD logging
paramtype   = plusarg
scope       = public

[parameter bootrom_file]
datatype    = file
description = Initial boot ROM contents (in Verilog hex format)
paramtype   = vlogparam
scope       = private
----

An observation to make here is that only the last parameter is actually defined in de0_nano.core. The first two parameters are specified in the .core file for vlog_tb_utils, which is a dependency of de0_nano. By setting their `scope=public`, these parameters become available for other cores which depend on them.


Backend-specific information
^^^^^^^^^^^^^^^^^^^^^^^^^^^^

- link:ghdl{outfilesuffix}[GHDL]
- link:modelsim{outfilesuffix}[ModelSim]
- link:rivierapro{outfilesuffix}[Riviera Pro]
- link:xsim{outfilesuffix}[xsim]

Migration guide
^^^^^^^^^^^^^^^
As new features are added to FuseSoC, some older features become obsolete. Read the link:migrations{outfilesuffix}[migration guide] to learn how to keep the .core files up-to-date with the latest best practices
