[WIP] SFBUILD/F4BUILD - Vendor-independent build system for F4PGA #2455
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
This is an update to #2225. I squashed everything into a separate branch since the commit history is quite long and chaotic and the branch was rebased by @mkurc-ant, no longer matching my local version which was based on Quicklogic's fork.
What is this?
sfbuild (not a final name) is a CLI tool written in Python that serves as a frontend for executing flows. On the other hand, sfbuild aims to provide developers with an ability to easily add platforms and modify/extend flows in a vendor-independent way. The philosophy behind this tool is to generate and execute flows dynamically based on user and developer-provided configurations and metadata that descibes the tools utilized within the flow (think edalize wrappers on steroids).
How to use it?
Example usage:
builds target
bitstream
using a list of source files (one entry:counter.v
),arty.xdc
as constraints,top
being the name of a top module. Additionally it will createbuild/arty_35
directory to output all files and will produce logs from synh and pack stages. The target isXC7A35TICSG324-1L
chip.You can provide any depency with
-D
flag followed by a symbolic dependency name and a path or list of paths. In a similar manner, you can provide values with-V
flag. You can learn more about differences between dependencies and values in a later section.Alternatively the configuration can be provided through a JSON.
Ok, but how does it work and what does any of that mean?
sfbuild splits a flow into stages, where each stage represents an instance of a module. A module is similar to an edatool, from edalize in a sense that it wraps an external tool, but contains more metadata and has more complex configuration interface. Each module features a set of inputs and outputs which are represented by symbolic dependencies. A symbolic dependency is a name given to a file/set of files that play a particular role in the flow. By using symbolic dependencies instead of explicit paths, sfbuild is able to perform dependency resolution without requiring the user to figure any of the logic behind flow, as long as they are able to provide necessary dependencies.
In the example above,
-t bitstream
is a request for building a dependency whose symbolic name isbitstream
. Requesting this dependency causes sfbuild to perform dependency resolution on stages associated with the target platform (xc7a50t
). If there are any dependencies required for buildingbitstream
that cannot be built, the user would be notified and would have to provide them explicitely. That's where the-Dsources=[counter.v]
and-Dxdc=[arty.xdc]
come into play. Since EDA tools may have optional outputs, we can also provide sfbuild with explicit paths for dependencies to force their production. That's the case with-Dsynth_log=synth.log
and-Dpack_log=pack.log
. Finally, there are also optional inputs, which are dependencies that will be taken as an input for a stage when present, but if they are missing the flow would resolve anyway.Dependencies are always meant to be files, so sfbuild can check for their existence and whether they are up-to-date (yes-there's modification tracking, to avoid unnecessary re-runs (can be disabled with
--nocache
flag). Because of that, any configuration/input for an EDA tool that is not a file (eg. a CLI option) is represented a a value. This works just like dependencies, but without tracking and allows passing dictionaries (eg.vpr_options
).On the developer side, all platforms are defined by their respective flow-definitions. Those are JSONS located under
sfbuild/platforms
. They instantiate a set of stages, default values, as well as choose parameters for constructing stages (Plenty of modules modules can be parametrized, which affects their I/O - something that's not possible with values/dependencies. Seegeneric_script_wrapper
for example).About modules
Modules are stored in directories whose names follow the
sf_<module_category>_modules
.There are essentially three stages of module's lifetime.
Quicklogic
Since the development was based o Quicklogic's fork, this won't work out-of-the-box with EOS-S3 and K4N8 platforms.
Aside from pulling Quicklogic changes, there are also other changes that need to be done in order to make it work with those targets and by that I mean resolving collisions between platform-specific scripts. F4PGA when installed for all families will overwrite some platform-specific scripts with their counter-parts that were meant to be used for another platform. If you resolve these conflicts by renaming the scripts to the name you can find in platform flow definitions (
sfbuild/platforms
), you should get an F4PGA installation that's compatible both with Xilinx and Quicklogic devices (at least when using sfbuild, the original wrappers will be broken).