rules_xlsynth now selects XLS artifacts from MODULE.bazel through the xls
module extension. A workspace instantiates one or more named bundles with
xls.toolchain(...), exposes them with use_repo(...), and registers one
default bundle with register_toolchains("@<name>//:all").
bazel_dep(name = "rules_xlsynth", version = "<release>")
xls = use_extension("@rules_xlsynth//:extensions.bzl", "xls")
xls.toolchain(
name = "workspace_xls",
xls_version = "0.39.0",
xlsynth_driver_version = "0.36.0",
artifact_source = "auto",
installed_tools_root_prefix = "/opt/xlsynth",
installed_driver_root_prefix = "/opt/xlsynth-driver",
)
xls.toolchain(
name = "legacy_xls",
xls_version = "0.37.0",
xlsynth_driver_version = "0.32.0",
artifact_source = "download_only",
)
use_repo(xls, "workspace_xls", "legacy_xls")
register_toolchains("@workspace_xls//:all")artifact_source chooses how each bundle repo is materialized:
autoprobes the consumer-owned installed layout and otherwise downloads the release artifacts.installed_onlyrequires the matching installed layout.download_onlyalways downloads the release artifacts.local_pathsuseslocal_tools_path,local_dslx_stdlib_path,local_driver_path, andlocal_libxls_path.
For the installed-layout modes, rules_xlsynth derives exact-version paths as:
<installed_tools_root_prefix>/v<xls_version>for the tools tree<installed_tools_root_prefix>/v<xls_version>/xls/dslx/stdlibfor the DSLX stdlib<installed_tools_root_prefix>/v<xls_version>/libxls.{so,dylib}forlibxls<installed_driver_root_prefix>/<xlsynth_driver_version>/bin/xlsynth-driverfor the driver binary
The attributes accepted by each mode are strict:
local_pathsrequires all fourlocal_*attrs and does not acceptxls_versionorxlsynth_driver_version.autoandinstalled_onlyrequirexls_version,xlsynth_driver_version,installed_tools_root_prefix, andinstalled_driver_root_prefix, and do not accept anylocal_*attrs.download_onlyrequiresxls_versionandxlsynth_driver_version, and does not accept anylocal_*orinstalled_*attrs.
Download-backed modes also have one host prerequisite: when auto falls back
to downloading, or when download_only is selected, the repository rule
installs xlsynth-driver with rustup run nightly cargo install. The host
running module resolution must have rustup available. If the nightly
toolchain is missing, rules_xlsynth bootstraps a repo-local rustup home
before installing the driver.
Each xls.toolchain(...) call exports a small repo surface:
@<name>//:allforregister_toolchains(...)@<name>//:bundlefor explicitxls_bundleoverrides@<name>//:libxlsand@<name>//:libxls_linkfor native consumers@<name>//:dslx_stdlibfor packages that need the standard library tree@<name>//:xlsynth_sys_artifact_configfor the modern single-filexlsynth-sysbuild-script contract@<name>//:xlsynth_sys_legacy_stdliband@<name>//:xlsynth_sys_legacy_dsofor frozenxlsynth-sysreleases that still use the pairedDSLX_STDLIB_PATH/XLS_DSO_PATHcontract@<name>//:xlsynth_sys_depfor the preferredxlsynth-sysruntime-plus-link contract@<name>//:xlsynth_sys_runtime_filesand@<name>//:xlsynth_sys_link_depas compatibility exports for callers that still spell runtime and link separately
xlsynth-sys consumers should prefer xlsynth_sys_artifact_config,
xlsynth_sys_dep, and, for frozen releases, xlsynth_sys_legacy_stdlib plus
xlsynth_sys_legacy_dso, rather than spelling generic bundle internals like
artifact_config, libxls_file, libxls, or dslx_stdlib directly in
downstream MODULE.bazel files.
Supported DSLX rules may opt out of the registered default bundle with
xls_bundle = "@<name>//:bundle". Today that escape hatch is available on
dslx_library, dslx_test, dslx_to_ir, dslx_prove_quickcheck_test,
dslx_to_sv_types, dslx_to_pipeline, dslx_to_pipeline_eco, and
dslx_stitch_pipeline.
dslx_to_pipeline(
name = "legacy_pipeline",
delay_model = "asap7",
pipeline_stages = 1,
top = "main",
deps = [":my_dslx_library"],
xls_bundle = "@legacy_xls//:bundle",
)Artifact-path build settings such as
--@rules_xlsynth//config:driver_path=...,
--@rules_xlsynth//config:tools_path=...,
--@rules_xlsynth//config:runtime_library_path=..., and
--@rules_xlsynth//config:dslx_stdlib_path=... are no longer supported.
Artifact selection lives only in MODULE.bazel. The remaining
@rules_xlsynth//config:* settings are behavior knobs, such as extra DSLX
search paths or warning toggles.
Self-hosted examples in this repo:
examples/workspace_toolchain_smoke/shows one registered default bundle and one explicitxls_bundleoverride without any.bazelrcartifact flags.examples/workspace_toolchain_local_dev/shows alocal_pathsworkspace rooted at/tmp/xls-local-dev/.
load("@rules_xlsynth//:rules.bzl", "dslx_library", "dslx_test")
dslx_library(
name = "my_dslx_library",
srcs = ["my_dslx_library.x"],
)
# `dslx_test` can run all the inline tests in an associated library.
dslx_test(
name = "my_dslx_library_test",
deps = [":my_dslx_library"],
)load("@rules_xlsynth//:rules.bzl", "dslx_fmt_test")
dslx_fmt_test(
name = "dslx_fmt_test",
srcs = glob(["*.x"]),
)load("@rules_xlsynth//:rules.bzl", "dslx_to_sv_types")
dslx_to_sv_types(
name = "my_dslx_library_pkg",
deps = [":my_dslx_library"],
sv_enum_case_naming_policy = "unqualified",
sv_struct_field_ordering = "as_declared",
)sv_enum_case_naming_policy is required. Allowed values (matching
xlsynth-driver) are unqualified and enum_qualified.
sv_struct_field_ordering is optional. Allowed values are as_declared
(default) and reversed.
The selected bundle records whether its xlsynth-driver supports the
--sv_enum_case_naming_policy CLI flag. Older bundles still work with
sv_enum_case_naming_policy = "unqualified"; enum_qualified only works when
the chosen workspace bundle or explicit xls_bundle advertises support.
Older bundles also keep working with the default
sv_struct_field_ordering = "as_declared" behavior. The explicit reversed
mode only works when the chosen workspace bundle or explicit xls_bundle
advertises support for --sv_struct_field_ordering.
Given a DSLX library target as a dependency, this rule will generate:
- an unoptimized IR file (simply IR converted DSLX); i.e.
my_dslx_library_ir.ir - an optimized IR file (optimized IR from the previous step); i.e.
my_dslx_library_ir.opt.ir
for a given top entry point.
load("@rules_xlsynth//:rules.bzl", "dslx_to_ir")
dslx_to_ir(
name = "my_dslx_library_ir",
lib = ":my_dslx_library",
top = "main",
)load("@rules_xlsynth//:rules.bzl", "ir_to_delay_info")
ir_to_delay_info(
name = "my_dslx_library_delay_info",
ir = ":my_dslx_library_ir",
delay_model = "asap7",
top = "main",
)load("@rules_xlsynth//:rules.bzl", "dslx_prove_quickcheck_test")
# Tests that we can prove the quickcheck holds for its entire input domain.
dslx_prove_quickcheck_test(
name = "quickcheck_various_things_proof_test",
lib = ":my_dslx_library",
top = "quickcheck_various_things",
)Given an IR target (typically from dslx_to_ir) as input via ir_src, this rule runs the ir2gates tool to produce a text file containing gate-level analysis (e.g., gate counts, depth).
load("@rules_xlsynth//:rules.bzl", "ir_to_gates")
ir_to_gates(
name = "my_ir_gates_analysis",
ir_src = ":my_dslx_library_ir", # Target providing IrInfo
)When the gate graph is large the "FRAIGing" optimization process can be slow, so there is a boolean option on the rule that allows users to disable it.
load("@rules_xlsynth//:rules.bzl", "ir_to_gates")
ir_to_gates(
name = "my_ir_gates_analysis_nofraig",
ir_src = ":my_dslx_library_ir",
fraig = False,
)load("@rules_xlsynth//:rules.bzl", "dslx_stitch_pipeline")
dslx_stitch_pipeline(
name = "my_pipeline",
lib = ":my_dslx_library",
top = "foo",
)stages- optional explicit list of stage function names to stitch when auto-discovery is not desired.input_valid_signal/output_valid_signal- when provided, additionalvalidhandshaking logic is generated.reset- name of the reset signal to thread through the generated wrapper. Use together withreset_active_lowto control polarity.reset_active_low-Truewhen the reset signal is active low (defaults toFalse).flop_inputs-Trueto insert an input register stage in front of the first stitched stage (defaults toTrue).flop_outputs-Trueto insert an output register stage after the final stage (defaults toTrue).
The flop_inputs and flop_outputs flags give fine-grained control over where pipeline registers are placed. For example, the sample/BUILD.bazel file contains demonstrations that verify:
flop_inputs = True, flop_outputs = False- only input side flops.flop_inputs = False, flop_outputs = True- only output side flops.
Corresponding golden SystemVerilog files live next to the BUILD file so you can observe the emitted RTL.