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.mdhas 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)
| File | Size | Uploaded | |
|---|---|---|---|
| astli-0.1.1.tar.gz | 156.7 kB | Details |
Built distributions (wheels)
| File | Reset | |||
|---|---|---|---|---|
| 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}
|