Skip to content

Latest commit

 

History

29 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

DFTools

Reproducible, source-pinned binary releases of the open-source EDA toolchain DFHDL depends on, packaged as a set of Apptainer images and run via Scalapptainer.

DFHDL runs these tools through DFTools by default; users can opt into local installations with --tools-location local. The DFTools release cycle is independent of the DFHDL library release: bumping a tool pin rebuilds and retests only the image(s) that contain it, and publishes only if the tests pass.

Images

Tools are clustered by shared heavy dependency / hard linkage, so a tool bump rebuilds the smallest possible image:

image tools notes
synth-verilog yosys (in-tree slang SV frontend), eqy no VHDL/LLVM — stays lean
synth-vhdl yosys + ghdl (frontend) + ghdl-yosys-plugin yosys -m ghdl; carries LLVM
pnr nextpnr-ecp5, nextpnr-himbaechel, ecppack, gowin_pack consumes yosys JSON
pnr-xilinx nextpnr-xilinx, bbasm, fasm2frames, xc7frames2bit, prjxray-db openXC7; Xilinx 7-series only⁴
sim-llvm nvc + ghdl (simulator) the two VHDL sims share one LLVM
sim-verilator verilator (+ g++/make/perl) keeps a C++ build env at runtime¹
sim-iverilog iverilog, vvp small, self-contained
sim-xezim xezim Rust SV simulator; built in lockstep with xezim-core
wavegen surfer, gtkwave (+ vcd2fst/fst2vcd/… converters), wavecrux³ GUI; X11-forwarded
program openFPGALoader small
hmi ffmpeg, fpga-isv media + interactive-sim viewer GUI (X11); single-stage²

¹ Verilator emits C++ that is compiled into the simulation at use-time inside the image, so per Verilator's docs g++/make/perl and the libfl/zlib/lz4 dev headers are runtime requirements (only verilator's own autoconf/flex/bison are stripped).

² hmi bundles ffmpeg (prebuilt Ubuntu archive package, unpinned — floats with ubuntu:24.04) and fpga-isv (the interactive-sim-viewer Python/Tk GUI, source-pinned via FPGA_ISV_REV and installed into the shared venv). Both are pure-Python/wheels or prebuilt, so there is no build toolchain to strip and it stays a single stage — the exception to the two-stage build-from-source pattern below. fpga-isv is a GUI, X11-forwarded like wavegen.

³ wavecrux is the upstream-prebuilt WaveCrux AppImage (closed source during its public beta), pinned by version and sha256 (WAVECRUX_REV/WAVECRUX_SHA256) and extracted into the image at build time (no FUSE needed at runtime). Upstream ships x86_64 only, so it is present only in the linux-x64 wavegen image; the aarch64 image carries the source-built viewers alone. Revisit both (and the pin style) when the canonical Ferrite-Engineering/wavecrux source repo opens post-beta.

⁴ openXC7 is a fork of nextpnr (openXC7/nextpnr-xilinx, built with -DARCH=xilinx), not an arch of the YosysHQ tree in pnr, so it cannot share that image; it also carries a ~500 MB prjxray bit database that ECP5/Gowin users should not pay for. Keeping them apart means a Trellis or Apicula pin bump never rebuilds this image, and vice versa. The per-part chip databases nextpnr places against are not in the image (90-670 MB each): they are generated by scripts/chipdb.sc and published as their own assets, see below. NEXTPNR_XILINX_REV must stay at or after 6680df93: below it create_clock does not propagate past the input BUFG and every build silently reports "PASS at 12.00 MHz".

ghdl appears in two images on purpose: the synthesis frontend ghdl (synth-vhdl, plugin-ABI-bound to yosys) and the simulator ghdl (sim-llvm) are pinned independently (GHDL_SYNTH_REV / GHDL_SIM_REV), so a simulator bump never perturbs the synthesis image and vice versa. Proprietary tools (Vivado, Quartus, Diamond, Gowin Designer, QuestaSim) are out of scope — used only via --tools-location local.

Layout

path purpose
pins.env single source of truth for source revisions (tag/commit per tool)
images/*.def one multi-stage Apptainer recipe per image
build/common.sh shared build helpers (clone, venv, manifest)
build/strip-runtime.sh prune build-only artifacts; strip binaries
scripts/build.sc build.sc <image> [dest.sif] — Scalapptainer build driver
scripts/test.sc test.sc probe <image> <sif> / test.sc dfhdl <sif-dir> <dfhdl-dir>
scripts/affected-images.sh maps a diff to the affected image(s)
scripts/chipdb.sc generate the nextpnr-xilinx chip databases from a built pnr-xilinx image
scripts/lockfile.sc rename sifs and chipdbs to immutable names + (re)generate dftools.lock.json
.github/workflows/release.yml detect → build+test → DFHDL gate → publish

How each image stays minimal

Every .def (except hmi, single-stage — see ² above) is a two-stage build: a heavy build stage installs full toolchains and installs the tools into /opt/dftools; the prefix is pruned and stripped (build/strip-runtime.sh), then a minimal final stage copies only /opt/dftools and installs just the runtime shared libraries (no compilers, sources, or headers — except sim-verilator, which intentionally keeps a C++ build env). The base (ubuntu:24.04, ~28 MB) is the only OS overhead per image; SIF has no cross-image layer sharing, so each image carries its own slim base — kept small relative to the tool payloads (LLVM, yosys, trellis DB, …).

The LLVM backend is used for ghdl/nvc so the recipes build on both linux-x64 and linux-arm64.

Reproducibility & pinning

Every tool is built from a specific tag or commit in pins.env — never a moving branch. Change one line to bump a tool; CI rebuilds only the affected image(s). After the first green build, harden branch-head commit pins to exact SHAs.

Building & testing locally

Requires Apptainer (native Linux) or, on Windows/macOS, the WSL2/Lima backend that Scalapptainer provisions. From the repository root:

scala-cli run scripts/build.sc -- synth-verilog                 # real root (CI/Docker)
DFTOOLS_NONROOT=1 scala-cli run scripts/build.sc -- synth-verilog   # unprivileged dev build
scala-cli run scripts/test.sc  -- probe synth-verilog dftools-synth-verilog.sif

Releases

Each release tag holds a dftools.lock.json plus the per-image assets. Asset names are immutable and content-addresseddftools-<image>-<arch>-<sha12>.sif (+ .sha256 and .MANIFEST.txt) — so a published asset is never mutated in place: a changed image lands under a new name and old tags stay valid.

The lockfile is the tag's only version-keyed artifact. It maps each image+arch to the sha256 of its sif and the asset carrying those bytes:

{ "tag": "v0.2.0",
  "images": { "sim-verilator": { "linux-x64": { "sha256": "ab12…",
                                                 "asset": "dftools-sim-verilator-linux-x64-ab12….sif" } } },
  "chipdbs": { "xc7a100tcsg324": { "sha256": "cd34…",
                                   "asset": "dftools-chipdb-xc7a100tcsg324-cd34….bin.gz" } } }

The chipdbs section carries the nextpnr-xilinx chip databases the same way, with two differences: a chipdb is byte-identical on every platform, so it is not keyed by arch, and it is published gzipped while the recorded digest is of the decompressed bytes, which is what DFHDL caches and mmaps. A chipdb is only valid for the nextpnr-xilinx build that produced it, so the set is regenerated exactly when the pnr-xilinx image is, and carried forward untouched otherwise.

DFHDL bundles this lockfile at build time and resolves/caches each image by sha256, not by tag — so bumping the tag re-downloads only the image(s) whose digest actually changed, and the rest of the set is a cache hit. Only rebuilt images are refreshed on a re-publish; the lockfile is regenerated (seeded from the prior one on the tag) to point at the current set.

License

DFTools packaging (recipes, scripts, CI) is Apache-2.0. Bundled tools retain their own upstream licenses.

About

DFiant HDL EDA FOSS Tool Dependencies

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages