Rust bindings to the functionality in the "Accelerated Hardware Synthesis" library.
use xlsynth::{DslxToIrPackageResult, XlsIrValue, IrPackage, IrFunction, XlsynthError};
fn sample() -> Result<XlsIrValue, XlsynthError> {
let converted: DslxToIrPackageResult = xlsynth::convert_dslx_to_ir(
"fn id(x: u32) -> u32 { x }",
std::path::Path::new("/memfile/sample.x"),
&xlsynth::DslxConvertOptions::default())?;
assert!(converted.warnings.is_empty());
let package: IrPackage = converted.ir;
let mangled = xlsynth::mangle_dslx_name("sample", "id")?;
let f: IrFunction = package.get_function(&mangled)?;
let mol: XlsIrValue = XlsIrValue::u32(42);
// Use the IR interpreter.
let interp_result: XlsIrValue = f.interpret(std::slice::from_ref(&mol))?;
// Use the IR JIT.
let jit = xlsynth::IrFunctionJit::new(&f)?;
let jit_result: xlsynth::RunResult = jit.run(&[mol])?;
assert_eq!(jit_result.value, interp_result);
Ok(jit_result.value)
}
fn main() {
assert_eq!(sample().unwrap(), XlsIrValue::u32(42));
}The xlsynth crate builds on top of the shared library libxls.{so,dylib} releases created in
https://github.com/xlsynth/xlsynth/releases/ -- this is the underlying C/C++ core.
xlsynth-sys: wraps the shared library with Rust FFI bindingsxlsynth-vast: standalone, Rust-native Verilog/SystemVerilog AST construction, register-building and expression-reduction helpers, and deterministic emission; does not requirelibxlsxlsynth-codegen: Rust-native lowering of XLS block IR to deterministic SystemVerilog, including state, aggregate values, block hierarchy, foreign instantiations, and optional pipeline-stage formattingxlsynth: provides Rust objects for interacting with core facilities; this includes:- DSLX parsing/typechecking, conversion to XLS IR
- IR building
- JIT compilation and IR interpretation
- Configuration-driven register-generation templates for
xlsynth-vast - Building Rust and SystemVerilog bridges for interacting with XLS/DSLX artifacts
sample-usage: demonstrates use of the APIs provided by thexlsynthcratexlsynth-estimator: Rust implementation of the XLS IR operation-level delay estimation methodologyxlsynth-g8r: experimental XLS IR to gate mapping libraryxlsynth-vastly: Verilog/SystemVerilog simulation and VCD comparison utilities
cargo test --workspace does not select tests that run Icarus or Yosys.
Select those suites explicitly:
cargo test --workspace --features iverilog-tests,yosys-testsiverilog-tests selects RTL simulation in codegen, driver, g8r, test-helpers,
and vastly. yosys-tests selects codegen synthesis-equivalence and
SystemVerilog-consumption tests; these do not require Liberty files or a PDK.
Mapped-netlist fuzz checks additionally require XLSYNTH_LIBERTY_FILES.
Missing or unusable tools are failures in
selected suites, never successful skips. In vastly, reference-sim-tests
remains an alias for iverilog-tests. These flags select tests, not public
runtime APIs. Existing prerequisites such as XLS tools, Slang (including for
run-verilog-pipeline tests), protoc, and enabled solver backends are unchanged.
See codegen validation for tool paths
and codegen fuzzing for Yosys/Liberty configuration.
This shows sample use of the driver program which integrates XLS functionality for command line use:
echo 'fn f(x: u32, y: u32) -> u32 { x + y }' > /tmp/add.x
cargo run -p xlsynth-driver -- dslx2ir --dslx_input_file /tmp/add.x --dslx_top f > /tmp/add.ir
cargo run -p xlsynth-driver -- ir2gates /tmp/add.irBy default the crate attempts to download the shared library and DSLX standard library that it needs for out-of-the-box operation, and stages the downloaded shared library where Cargo-run binaries can find it. However, this can also be specified manually at build time with the following environment variables:
cargo clean
export XLS_DSO_PATH=$HOME/opt/xlsynth/lib/libxls-v0.0.173-ubuntu2004.so
export DSLX_STDLIB_PATH=$HOME/opt/xlsynth/latest/xls/dslx/stdlib/
cargo build -vv -p xlsynth-sys |& grep "Using XLS_DSO_PATH"
# For manually supplied DSOs, ensure host binaries (including Cargo build scripts) can locate the
# DSO at build/test time.
export LD_LIBRARY_PATH="$(dirname "$XLS_DSO_PATH")":$LD_LIBRARY_PATH
cargo test --workspaceNote: XLS_DSO_PATH and DSLX_STDLIB_PATH are a paired build-time override for supplying
pre-fetched XLS artifacts (DSO + DSLX stdlib). Setting only one will not enable the override.
Build systems that prefer a single declared input can instead set XLSYNTH_ARTIFACT_CONFIG to a
TOML file containing dso_path and dslx_stdlib_path.
- If
XLSYNTH_ARTIFACT_CONFIGis set, it takes precedence overXLS_DSO_PATHandDSLX_STDLIB_PATH, and the paired env override is ignored. XLSYNTH_ARTIFACT_CONFIGitself must be an absolute path.dso_pathanddslx_stdlib_pathinside that TOML may be absolute paths, or relative paths resolved from the TOML file's directory.- Build systems that declare the shared library separately can set
XLSYNTH_SYS_LINK_MODE=declaredsobuild.rsrecords the artifact paths without emitting its own native-l...directives.
For a containerized contributor build, see the container build and test reference. Full validation is the contributor default and runs workspace checks, tests, and pre-commit with networking disabled after preparation. The same Dockerfile is exercised in CI, where the container lane explicitly selects build-only and only compiles the workspace offline.
The xlsynth Rust crate leverages a dynamic library with XLS' core functionality (i.e. libxls.so
/ libxls.dylib).
The DSO is built and released for multiple platforms via GitHub actions at xlsynth/xlsynth/releases.
The version that this crate expects is described in xlsynth-sys/build.rs as
RELEASE_LIB_VERSION_TAG. By default, this crate pulls the dynamic library from the targeted
release.
To link against a local version of the public API, instead of a released version, supply the
DEV_XLS_DSO_WORKSPACE environment variable pointing at the workspace root where the built shared
library resides; e.g.
$ export DEV_XLS_DSO_WORKSPACE=$HOME/proj/xlsynth/
$ ls $DEV_XLS_DSO_WORKSPACE/bazel-bin/xls/public/libxls.* | egrep '(.dylib|.so)$'
/home/cdleary/proj/xlsynth//bazel-bin/xls/public/libxls.so
$ cargo clean # Make sure we pick up the new env var.
$ cargo test -vv |& grep -i "DSO from workspace"
[xlsynth-sys ...] cargo:info=Using DSO from workspace: ...Where in ~/proj/xlsynth/ (the root of the xlsynth workspace) we build the DSO with
bazel build -c opt //xls/public:libxls.soThe pre-commit tool is used to help with local checks before PRs are created:
sudo apt-get install pre-commit
pre-commit install
pre-commit run --all-filesThis pre-commit step is also run as part of continuous integration.
Python helper scripts now live under scripts/ at the repo root. Invoke them from the workspace root, e.g.:
python3 scripts/update_golden_files.py
python3 scripts/run_all_fuzz_tests.py --fuzz-bin-args=-max_total_time=5This repository publishes crates to crates.io via the GitHub Actions workflow in .github/workflows/publish.yml. The workflow runs when a v* tag is pushed.
- Look at the latest release tag (
vX.Y.Z) and choose the next tag version. - For the normal mainline release flow, bump
Yand resetZto0(for example,v0.33.0->v0.34.0). - Before creating the tag, check that the workspace
Cargo.tomlversions already match the intended tag version (for example,xlsynth/Cargo.tomlandxlsynth-sys/Cargo.toml).- If they do not match, update the workspace crate versions to the intended tag version, commit that change (and merge it to the release branch or
main, as appropriate), and then create the tag on that commit.
- If they do not match, update the workspace crate versions to the intended tag version, commit that change (and merge it to the release branch or
- Create and push the tag (
git tag vX.Y.Zthengit push origin vX.Y.Z). - The publish workflow validates that the checked-in crate versions match the tag, runs tests, and publishes the crates.
Treat every pushed release tag as immutable. The publish workflow is restartable after a partial release: it skips an exact crate version that is already present in the crates.io sparse index and continues with missing crates. Never move or reuse a pushed release tag for different source. Fix forward with a new patch version instead.
Important: the version for the next release is often already "waiting" in the repository. After every successful release, the workflow regenerates the version compatibility metadata. Ordinary regeneration preserves existing compatibility rows and does not backfill historical gaps for tags without publish_order.toml. When a newly discovered release tag contains publish_order.toml, the release is included only when every crate declared in that historical file is visible in the crates.io sparse index. A tag without publish_order.toml is not made ineligible by that absence and does not trigger a crates.io release-set check; scripts/gen_version_compat.py --recompute-all-entries may reconstruct those rows during an intentional full audit. Each tag's historical crate list is authoritative, so crates introduced later do not retroactively change older release requirements. If a known-broken cached row is discovered, remove it explicitly as a data correction. After a successful mainline .0 release, the workflow also bumps the workspace manifests to the next minor version. A .0 release therefore produces both follow-up commits:
Bump version numbers after successful publishUpdate version metadata after successful publish
For example, after publishing v0.33.0, the automation bumped the workspace manifests to 0.34.0. That means the next mainline tag should usually be v0.34.0 (unless you intentionally prepare a different release), not v0.33.1.
If you intentionally release a patch version (Z != 0), first make the checked-in crate versions match that patch tag. The workflow updates version metadata after a successful patch release, but it performs the automatic post-publish version bump only for .0 tags.
The following versioning convention applies to the underlying DSO/dylib artifacts (e.g., libxls.so, libxls.dylib) released by the xlsynth/xlsynth repository, not to the versioning of this Rust crate itself. Occasionally, we need to create a successor to a patch release without bumping the minor or major version. In these cases, we use a dash-suffixed version tag (e.g., v0.0.219-1, v0.0.219-2). The plain form (e.g., v0.0.219) is implicitly equivalent to v0.0.219-0. This allows us to cherry-pick fixes onto a patch release when necessary.
Note: We hope to eventually switch to bumping the v0.X.0 field for such successors, so that these dash releases can instead become patch releases, using the patch field as intended by semantic versioning. Until then, please be aware of this convention when working with release artifacts and tooling.