Shake-based build system for Haskell-based FPGA projects, featuring:
Currently, shake-fpga is yet to be published on Hackages, so you will need to
include it in your cabal.project file as follows:
source-repository-package
type: git
location: https://github.com/poscat0x04/shake-fpga
tag: 1a202b258db7f19cfea4fc5a8ca9bae84333f374You should also clone the repository and do a cabal install exe:shake-fpga to
install the shake-fpga executable.
After you've included shake-fpga in your project, you can now configure your
project to use shake-fpga
The first thing you want to do is to add
write-ghc-environment-files: alwaysto your cabal.project file, since the ghc environment file is required for
clash to function.
Then you should include clash-prelude, ghc-typelits-extra,
ghc-typelits-knownnat, ghc-typelits-natnormalise in your .cabal file as
library dependencies(build-depends). Also enable these plugins like so:
library
ghc-options:
-fplugin GHC.TypeLits.Extra.Solver
-fplugin GHC.TypeLits.Normalise
-fplugin GHC.TypeLits.KnownNat.SolverNow run a cabal build to generate the ghc environment file needed by clash.
Once the environment file is generated, you can proceed to configuring
shake-fpga.yaml
The shake-fpga.yaml has the following structure:
hdl: <hdl to target, verilog/systemverilog or vhdl>
targets:
- module: <Haskell module name>
alias: <alias for target>
topEntity: <top entity (i.e. function) name>
part: <chip part>
xdc: <path to xdc file>
linkComponents:
- test:<name of test>You can have multiple targets in a single cabal package.
To show the avaiable targets given a shake-fpga.yaml, run shake-fpga -- -h
A typical output would look something like the following:
Targets:
- clean
- _build/Adder/deps.mk
- _build/Adder/wire/clash/clash-manifest.json
- _build/Adder/wire/vivado/synth+implement.tcl
- _build/Adder/wire/vivado/out.bit
- _build/Adder/wire/verilator/libVmodel.a
- _build/Adder/wire/verilator/libverilated.a
- _build/Adder/wire/verilator/Vmodel-c.h
- _build/Adder/wire/verilator/Vmodel-c.cpp
- _build/Adder/wire/verilator/Vmodel-c.o
- _build/Adder/wire/verilated/libVmodel-c.a
- _build/Adder/wire/verilated/Vmodel-c.o
- _build/Adder/wire/haskellBinding/Verilated.hsc
- adder:bit
- adder:verilate
- adder:clash
- adder
cleanis a phony rule that removes the_builddirectory_build/Adder/deps.mkis a makefile generated by clash that contains the.hsdependencies of the target Haskell module, and is used by shake to trigger rebuilds._build/Adder/wire/clash/clash-manifest.jsonis a JSON file generated by clash that contains information about the top module (e.g. its name, ports, and types). It is used by shake to generate binding to the verilated model._build/Adder/wire/vivado/synth+implement.tclis a TCL script generated by shake-fpga that runs the synthesis and implementation flow in Vivado._build/Adder/wire/vivado/out.bitis the bitstream file generated by Vivado after the synthesis and implementation flow._build/Adder/wire/verilator/libVmodel.ais the verilated model of the top module, and_build/Adder/wire/verilator/libverilated.ais the runtime for the verilated model. Both are generated via a single invocation of verilator. (see also: https://verilator.org/guide/latest/files.html)_build/Adder/wire/verilator/Vmodel-c.h,_build/Adder/wire/verilator/Vmodel-c.cppand_build/Adder/wire/verilator/Vmodel-c.oare the c++ header, source and object files generated respectively. It is a thin wrapper that translate the c++ interface to a c interface that Haskell can interact with._build/Adder/wire/verilated/libVmodel-c.ais the combined archive ofverilator/Vmodel-c.o,libVmodel.aandlibverilated.a, whereas_build/Adder/wire/verilated/Vmodel-c.ois the combined object file of the three._build/Adder/wire/haskellBinding/Verilated.hscis the hsc2hs binding toVmodel-cadder:bitis a phony rule that builds the bitstream using the TCL script.adder:verilateis a phony rule that buildsVmodel-cadder:clashis a phony rule that runs the clash compilation for the top entity/function.
If you'd like to verify your design in Haskell, you should use fpgaHooks in
your Setup.hs file. What it does is it injects 2 hooks into the build process:
one before the configuration process that essentially adds various fields to
your .cabal file that are needed to run the verilated model in Haskell, and
one after the configuration process that builds the verilated model as well as
the Haskell binding (module name is Verilated). Note that the configuration
filename is non-configurable and is always shake-fpga.yaml
To do this, use the following SetupHooks.hs file:
module SetupHooks (setupHooks) where
import Distribution.FPGA.Hooks
setupHooks = fpgaHooksas well as set the following options in your .cabal file:
build-type: Hooks
custom-setup
setup-depends:
, base
, shake-fpgaThe following cli tools should be in PATH:
vivado: if you want to build bitstreamsverilator,pkg-configand c/c++ compilers: if you want to build the verilated models
Additionally the following libraries are required for verilated models:
lz4zlib
The program should be run from the project root.
A shake-fpga.yaml file should be present in the project root.