Skip to main content

astli

SystemVerilog language tooling in pure Rust: a preprocessor, a lossless syntax tree, and a formatter built on them.

Why

A Rust tool that wants to understand SystemVerilog has had to bind a C++ frontend. That works, but the FFI hands back opaque objects: walking a syntax tree means writing a binding for every node and method you touch, and the C++ build is slow and hard to cache. bender is where that friction showed up.

astli is the frontend as a Rust library. The tree is ordinary Rust data that keeps every byte of the source, comments and whitespace included, so a tool can walk it, query it, and print it back exactly.

The formatter is the first thing built on it. A linter, a language server, or deeper analysis could follow.

Scope

astli lexes, preprocesses and parses; it does not elaborate or type-check. slang is the state of the art for SystemVerilog, a complete compiler, and the right tool whenever you need one. astli does not try to replace it.

Status

Pre-1.0, and the API still changes. What exists:

  • Preprocessor. All directives, macro expansion, includes, and filelists with +incdir+ and +define+.
  • Parser. Design units, declarations, classes, instances, generate blocks, statements and expressions. Assertions, covergroups and a few rarer constructs are kept verbatim for now, so nothing is ever lost; docs/grammar-coverage.md has the detail.
  • Formatter. The lowRISC style. It checks that every result preprocesses to the same thing as its input, and refuses a file rather than change what it means.

All of it is tested against open-source designs, fetched by scripts/fetch-corpus.sh.

Formatting

cargo install astli-cli
astli fmt top.sv            # print the formatted file
astli fmt -w rtl/*.sv       # rewrite in place
astli fmt --check -f src.f  # fail if any file in a filelist is unformatted
astli fmt --diff top.sv     # show what would change
astli fmt -                 # stdin to stdout

Each file is formatted on its own: includes are not followed and no +define+ reaches the formatter, so the output depends only on the file.

As a library

[dependencies]
astli = "0.1"
use astli::parse::SyntaxTree;
use astli::syntax::ast::{AstNode, ModuleDecl};

let tree = SyntaxTree::read("top.sv")?;

for module in tree.root().descendants().filter_map(ModuleDecl::cast) {
    if let Some(name) = module.name() {
        println!("module {}", name.text());
    }
}

print!("{}", astli::fmt::format(&tree)?);

astli re-exports each astli-* crate as a module; they can also be used on their own. docs/api.md explains the shape of the API.

Development

astli-cli is the workspace's default member, so cargo run needs no -p. Besides fmt, the driver has one subcommand per stage, each printing what that stage made of a file:

cargo run -- lex        top.sv
cargo run -- preprocess top.sv -I include --emit text
cargo run -- parse      top.sv --quiet

The same default member means every other cargo command needs --workspace: cargo nextest run --workspace, not cargo nextest run. -P quick skips the tests that read the corpus. Hooks run through prek: prek install.

docs/plan.md has the architecture and the decisions behind it.

Path
crates/astli-text Spans, the file store, reading a file
crates/astli-diag Rendering a diagnostic, with its macro and include chain
crates/astli-syntax SyntaxKind, the lexer, the rowan tree types
crates/astli-preproc Directives, macros, includes
crates/astli-parse The grammar, and the tree it builds
crates/astli-fmt The formatter
crates/astli The umbrella: every library crate, as a module
crates/astli-cli The driver, a binary named astli
docs/ Design and planning

Acknowledgements

  • slang, the reference for how SystemVerilog behaves. The preprocessor is tested against it, file by file.
  • rust-analyzer, whose architecture this follows: an event-based parser, a lossless tree, and typed views generated from a tree grammar.
  • rowan, logos and ungrammar, which it is built on.
  • lowRISC's style guide, which the formatter implements.
  • The open-source designs in the test corpus, for being real code.

Licence

MIT or Apache-2.0, at your option. Unless you state otherwise, any contribution you submit is licensed the same way, without further terms.

Release files for astli 0.1.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for astli 0.1.1
File Size Uploaded
astli-0.1.1.tar.gz 156.7 kB Details

Built distributions (wheels)

Table of built distributions (wheels) for astli 0.1.1
File
astli-0.1.1-py3-none-win_amd64.whl Python 3 none Windows x86-64 Details
astli-0.1.1-py3-none-musllinux_1_2_x86_64.whl Python 3 none Linux musl 1.2+ x86-64 Details
astli-0.1.1-py3-none-musllinux_1_2_aarch64.whl Python 3 none Linux musl 1.2+ ARM64 Details
astli-0.1.1-py3-none-manylinux_2_28_x86_64.whl Python 3 none Linux glibc 2.28+ x86-64 Details
astli-0.1.1-py3-none-manylinux_2_28_aarch64.whl Python 3 none Linux glibc 2.28+ ARM64 Details
astli-0.1.1-py3-none-macosx_11_0_arm64.whl Python 3 none macOS 11.0+ ARM64 Details
astli-0.1.1-py3-none-macosx_10_12_x86_64.whl Python 3 none macOS 10.12+ x86-64 Details

Total release size: 7.5 MB

Release files / astli-0.1.1.tar.gz

Download URL astli-0.1.1.tar.gz
Size 156.7 kB
Tags Source
SHA-256 checksum
How to use checksums
fcba2dea06ee07a0e85ba16a18b64ac580fcfadbae2ba34d1e7d1eed48846c57
BLAKE2b-256 checksum
How to use checksums
b915f4d24fb01a3055c9b2c680a88ef1e987230bd4f18338df165a55871713ee
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.12.19 {"installer":{"name":"uv","version":"0.12.19","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / astli-0.1.1-py3-none-win_amd64.whl

Download URL astli-0.1.1-py3-none-win_amd64.whl
Size 866.7 kB
Tags Python 3 Windows x86-64
SHA-256 checksum
How to use checksums
2074030fdb5ee0c6f6b92fab33b79439b9e01d52040a0e9124ef73a8e0749caa
BLAKE2b-256 checksum
How to use checksums
67ff6ce2fe89ac9edf58102f3cb175677da3b6dd29f6fb35b84050121cfe4658
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.12.19 {"installer":{"name":"uv","version":"0.12.19","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / astli-0.1.1-py3-none-musllinux_1_2_x86_64.whl

Download URL astli-0.1.1-py3-none-musllinux_1_2_x86_64.whl
Size 1.1 MB
Tags Linux musl 1.2+ x86-64 Python 3
SHA-256 checksum
How to use checksums
852c7532744333e27ff84b72f621bb60e2f11db7c7fd5e62fe17bc93d9f94a95
BLAKE2b-256 checksum
How to use checksums
d83febf5da58f791a5d4b40787ac22443c205af0c6492d952e607fdf6e11e4a6
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.12.19 {"installer":{"name":"uv","version":"0.12.19","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / astli-0.1.1-py3-none-musllinux_1_2_aarch64.whl

Download URL astli-0.1.1-py3-none-musllinux_1_2_aarch64.whl
Size 1.2 MB
Tags Linux musl 1.2+ ARM64 Python 3
SHA-256 checksum
How to use checksums
0985328499973185ec840db4a10d231b3f99fa40297b47b2368d43d7e0ab6d1c
BLAKE2b-256 checksum
How to use checksums
a26884ba52419a5855b55bd840a52524fea140a65592dc182583e0ee6865512c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.12.19 {"installer":{"name":"uv","version":"0.12.19","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / astli-0.1.1-py3-none-manylinux_2_28_x86_64.whl

Download URL astli-0.1.1-py3-none-manylinux_2_28_x86_64.whl
Size 1.1 MB
Tags Linux glibc 2.28+ x86-64 Python 3
SHA-256 checksum
How to use checksums
37129ba6e348d7ce6db6f0b9b45ffc96e0dc192926538287dae3590eeaf9ed66
BLAKE2b-256 checksum
How to use checksums
5dfa75098d045837866390a3aa0ef53cfb8e84ce942b2804ef522e247e3711c6
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.12.19 {"installer":{"name":"uv","version":"0.12.19","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / astli-0.1.1-py3-none-manylinux_2_28_aarch64.whl

Download URL astli-0.1.1-py3-none-manylinux_2_28_aarch64.whl
Size 1.1 MB
Tags Linux glibc 2.28+ ARM64 Python 3
SHA-256 checksum
How to use checksums
29d968a4ca0fb5af1cc4738d604f129f3d6607b5f031bc05a70c0d65be54a99d
BLAKE2b-256 checksum
How to use checksums
bde78777f0c8cd7a348af511218384606d6fc3c154ffb478c234c8adc0258d71
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.12.19 {"installer":{"name":"uv","version":"0.12.19","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / astli-0.1.1-py3-none-macosx_11_0_arm64.whl

Download URL astli-0.1.1-py3-none-macosx_11_0_arm64.whl
Size 962.1 kB
Tags Python 3 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
54663874c99c48f8c3cf58769788cf5173eef4d874a017b6b94f33bd9e6f58b5
BLAKE2b-256 checksum
How to use checksums
7461956e1a985c9d87a47cd6c01e043ad629fdf86113497cbf42100f59d4c8db
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.12.19 {"installer":{"name":"uv","version":"0.12.19","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / astli-0.1.1-py3-none-macosx_10_12_x86_64.whl

Download URL astli-0.1.1-py3-none-macosx_10_12_x86_64.whl
Size 1.0 MB
Tags Python 3 macOS 10.12+ x86-64
SHA-256 checksum
How to use checksums
1d6c166dcf58707fdca630df884fe79746f333db49a07c18fd9b7337efdfe597
BLAKE2b-256 checksum
How to use checksums
bd6ccf35a719856d0a74cbc1fbf8de0e21185de7a9e4a9c2c954cd4acf5c39a7
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.12.19 {"installer":{"name":"uv","version":"0.12.19","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release history Release notifications | RSS feed

This release

0.1.1 This release

8 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page