State of the Art — IP & Package Managers¶
Research survey backing the design of the HDL IP Packager. Compiled June 2026. Sources are listed at the bottom and linked inline.
This document answers one question: what does a great package manager look like, and how have people applied those ideas to HDL/IP? It pulls from both the mature software ecosystems (pip, npm, Cargo, Go, Conda, Docker/OCI) and the hardware-specific tools (IP-XACT, FuseSoC, Bender, Orbit, hdlmake, vendor catalogs). The conclusions feed directly into architecture.md.
1. The anatomy of a package manager¶
Across every ecosystem, the same handful of concepts recur. Naming them gives us a checklist for our own design.
| Concept | What it is | Our choice |
|---|---|---|
| Manifest | Human-authored declaration of what a project needs: identity, metadata, direct dependencies with version constraints. | ip.toml (TOML) |
| Lockfile | Machine-generated record of what was actually resolved — exact versions + integrity hashes — for reproducible builds. | ip.lock (implemented) |
| Resolver | Turns constraints into concrete versions. | newest-compatible, SAT-ready (implemented) |
| Registry | Where packages are published and discovered. | local + HTTP (implemented); Git / OCI (planned) |
| Cache | Local, verified copy of fetched packages so builds are offline & reproducible. | content-addressed (implemented) |
| Versioning | The contract for "what changed". | SemVer 2.0.0 |
| Identity | A globally meaningful name. | VLNV (IP-XACT-style) |
The manifest declares constraints; the resolver finds concrete versions that satisfy them; the lockfile records the result. This manifest → resolve → lock loop is the spine of pip, npm, Cargo, Poetry, Go, and Bundler alike (Nesbitt, Package Manager Glossary).
2. Lessons from software package managers¶
Versioning and constraints¶
- Semantic Versioning (
MAJOR.MINOR.PATCH) is the near-universal contract: a major bump signals a breaking change. Constraint syntaxes converge on>=1.0.0,^1.0.0("compatible with"),~1.0.0("approximately"), and exact pins, though the caret/tilde meaning differs per ecosystem — npm and Cargo agree that^means "minor+patch for 1.x, patch only for 0.x" (Nesbitt, Glossary). → We implement SemVer 2.0.0 and adopt the Cargo/npm caret semantics, with a bare constraint defaulting to caret.
Dependency resolution¶
- Version selection is NP-complete (you can encode 3-SAT into a dependency
graph), which is why mature managers ship SAT solvers (e.g. Conda's
libmamba, PubGrub in Dart/uv). - Strategy differs: most pick the newest version satisfying constraints; Go modules use Minimal Version Selection (the oldest that works) for reproducibility without a lockfile (Nesbitt, Design Tradeoffs).
- Conflict handling is a defining tradeoff: pip fails on incompatible
versions; npm nests conflicting copies so each consumer gets what it asked
for. HDL cannot nest transparently — two copies of the same module in one
elaboration collide — so the default is a single version per package (pip-like),
failing loudly on conflict. We refine this: SemVer-compatible dependents unify
(Cargo-style), and an incompatible conflict is governed by a configurable
[resolution] on-conflictpolicy —fail_on_conflict(default),use_latest, orisolate_namespaces(which records the coexistence in the lock/tree, thoughgenstill refuses to emit two versions because automatic name-mangling is unbuilt).
Lockfiles & reproducibility¶
- Cargo set the modern convention: lockfile by default, SemVer enforced,
reproducible builds as a goal. A study across npm/pnpm/Cargo/Poetry/Pipenv/
Gradle/Go found lockfiles deliver build determinism, integrity verification,
and transparency; commit rates vary wildly (Go ~100%, Gradle ~0%)
(Wang et al., The Design Space of Lockfiles).
→ We will commit
ip.lockand store an integrity hash per resolved core.
Publishing & trust¶
- Immutability + yank: Cargo and RubyGems never delete a published version; they yank it (hidden from new resolves, still available to existing lockfiles). This preserves reproducibility while letting you retire a bad release (Nesbitt, Glossary). → Our registry contract is append-only with yank.
Registries & content-addressable storage¶
- An OCI registry (the Docker registry, now an open standard) is a content-addressable, HTTP artifact store where every blob is addressed by its SHA-256 digest, giving automatic dedup and integrity. Since the OCI 1.1 specs (2024), registries store any artifact — Helm charts, WASM, ML models, Terraform modules — not just container images (Chainguard, What are OCI Artifacts; ORAS). → A compelling backend option: publish IP cores as OCI artifacts and reuse the world's existing registry infrastructure (GHCR, ECR, Harbor) instead of inventing a new server. Content-addressing also underpins our local cache.
Supply-chain security (the 2026 baseline)¶
- Driven by EO 14028 and the EU Cyber Resilience Act, three technologies have
gone from buzzword to requirement: SBOM (what's inside), SLSA (build
provenance levels L1–L3), and Sigstore (keyless signing via cosign/Fulcio/
Rekor). SBOMs should be generated at build time when the full dependency
graph is known (AquilaX, Beyond SBOMs;
Practical DevSecOps, SLSA Guide).
→ Roadmap: checksums first, then optional Sigstore signing + an SBOM emitted by
pack.
3. HDL-specific prior art¶
Hardware reuse has its own decades-long history. The key players:
IP-XACT / IEEE 1685 — the metadata standard¶
The XML standard (IEEE 1685, originally from the SPIRIT Consortium; revisions 2009/2014/2022) for describing and packaging IP: components, bus interfaces, address maps, register/field descriptions, and file sets, so tools and organizations can exchange IP and automate integration. It standardizes the VLNV (Vendor-Library-Name-Version) identity we adopt (IP-XACT, Wikipedia; IEEE 1685-2022). → IP-XACT is a description format, not a package manager. We borrow its VLNV identity and will offer IP-XACT export for tool interop, but use TOML (not XML) for the human-authored manifest.
FuseSoC — the de-facto open-source HDL package manager¶
Award-winning Python tool by Olof Kindgren. The unit is a core identified by
a VLNV (e.g. example:ip:fifo), described by a .core file (CAPI2, YAML)
listing sources and dependencies. The package manager searches configurable
core libraries (local dirs or remote repos); the build system resolves
the dependency tree from a top-level core, influenced by constraints (target,
tool, parameters), and flattens to a file list. It abstracts EDA tools via tool
flows and emits EDAM (an intermediate description) consumed by Edalize;
generators produce cores dynamically
(FuseSoC docs;
GitHub).
→ The closest reference design. We adopt VLNV, core libraries (local + remote),
constraint-influenced resolution, and an EDAM-like tool-abstraction layer.
Bender — Git-first dependency manager (PULP, Rust)¶
Manages HDL package dependencies across Git repositories and local paths,
resolves compatible versions, records the exact result in Bender.lock, and
emits ordered source sets for downstream tools. Manifest (Bender.yml) is YAML;
ships as a single static binary
(Bender, GitHub).
→ Validates the manifest+lockfile+ordered-filelist model and Git-as-registry.
Orbit — modern, reproducibility-focused (Rust)¶
Package manager + build system for VHDL/Verilog/SystemVerilog. Manifest is
Orbit.toml; it tokenizes HDL source to find references between design
units automatically. A 3-level Catalog (Channels → Archive → Cache) stores
increasing detail; checksums lock cache contents so they can't be edited, and
an Orbit.lock captures the full state for cross-machine reproducibility
(Orbit Book;
GitHub).
→ Strong endorsement of our choices: TOML manifest, lockfile, and
checksum-verified content-addressed cache. The catalog tiering is a good model.
hdlmake — the older Makefile generator¶
Python tool (CERN/Ohwr): finds file dependencies, writes synthesis/simulation
Makefiles, and fetches IP-core libraries from remote repos. Each module has a
Manifest.py (Python) listing files + dependencies
(Awesome HDL / hdlmake).
→ Shows the pitfall to avoid: a manifest in a Turing-complete language (.py)
is hard to analyze, sandbox, and trust. We keep the manifest declarative (TOML).
Vendor tooling — Vivado IP Packager / IP Integrator¶
AMD/Xilinx IP Packager prepares IP for the IP Catalog, leveraging IP-XACT; IP Integrator connects IP at the block level (interface-based connections, automation, DRCs) and generates RTL. The flow guarantees a consistent experience whether IP is from the vendor, a third party, or custom (UG896 IP Packager). → Confirms IP-XACT as the interop lingua franca and the value of a catalog abstraction. Our IP-XACT export targets exactly this consumer.
4. Comparison at a glance¶
| Tool | Manifest | Lockfile | Identity | Registry | Notable idea |
|---|---|---|---|---|---|
| pip / PyPI | pyproject.toml |
(via pip-tools/uv) | name+version | PyPI index | huge ecosystem, fails on conflict |
| npm | package.json |
package-lock.json |
name+semver | npm registry | nested deps |
| Cargo | Cargo.toml |
Cargo.lock |
name+semver | crates.io | lockfile-by-default, yank |
| Go | go.mod |
go.sum |
module path | proxy/VCS | minimal version selection |
| Docker/OCI | (Dockerfile) | digest pin | repo:tag@digest | OCI registry | content-addressable artifacts |
| IP-XACT | XML | — | VLNV | — | the metadata standard |
| FuseSoC | .core (YAML) |
— | VLNV | core libraries | tool-flow abstraction (EDAM) |
| Bender | Bender.yml |
Bender.lock |
name+semver | Git | Git-first |
| Orbit | Orbit.toml |
Orbit.lock |
name+version | Catalog | checksummed cache, source tokenizing |
| This project | ip.toml (TOML) |
ip.lock |
VLNV | local/Git/HTTP/OCI | TOML + SemVer + OCI backend + IP-XACT export |
5. Design decisions this research drives¶
- TOML manifest (
ip.toml) — declarative (not Python like hdlmake), modern, and the same family as Cargo/Orbit/pyproject.toml. (implemented) - VLNV identity — align with IP-XACT/FuseSoC so names are portable. (implemented)
- SemVer 2.0.0 + caret-default constraints — the dominant library convention. (implemented)
- Single-version resolution, fail-on-conflict — HDL can't nest; mirror pip, not npm. Newest-compatible selection, SAT-ready. (implemented)
- Committed lockfile + per-core integrity hash — reproducibility like Cargo/ Orbit/Go. (implemented)
- Content-addressed cache + pluggable registries, including an OCI backend — reuse battle-tested infrastructure rather than build a server. (cache + local/HTTP registries implemented; Git/OCI backends planned)
- Tool-flow abstraction (EDAM-like) — generate simulator/synthesis inputs from one description, à la FuseSoC. (implemented — Verilator/Vivado/Icarus/GHDL/Yosys)
- IP-XACT export — interop with Vivado and other IEEE-1685 consumers. (implemented)
- Supply-chain on the roadmap — checksums now; Sigstore signing + SBOM later. (checksums + CycloneDX SBOM implemented; Sigstore signing planned)
Sources¶
HDL / IP: - FuseSoC — Understanding FuseSoC (docs) · FuseSoC GitHub - IP-XACT — Wikipedia · IEEE 1685-2022 - Bender — GitHub - Orbit — The Orbit Book · Orbit GitHub - hdlmake — Awesome HDL · Build systems for HDL — Sigasi - Vivado IP Packager — UG896
Software package managers & registries: - Nesbitt — Package Manager Glossary - Nesbitt — Package Manager Design Tradeoffs - Nesbitt — What Package Registries Could Borrow from OCI - Wang et al. — The Design Space of Lockfiles Across Package Managers (arXiv) - Chainguard — What are OCI Artifacts · ORAS — OCI Artifact
Supply-chain security: - AquilaX — Supply Chain Security Beyond SBOMs - Practical DevSecOps — SLSA Framework Guide 2026
Python packaging: - KDnuggets — Python Project Setup 2026 (uv + Ruff + Ty) - Python Packaging Best Practices: setuptools, Poetry, Hatch in 2026