Replies: 2 comments 1 reply
|
I've been thinking about this lately. It's a very hard problem because SystemVerilog has many mechanisms for non-local behavior, and many projects make it much harder on themselves by insisting on the single-unit setup which defeats parallel parsing. That said, I think the right approach is an external cache for the syntax trees, as you described, along with externalizing the instance cache at the AST layer, so that whole chunks of the AST can be reused across compilations. This is going to be a lot of work to tackle. I don't think it's feasible to throw this at an LLM; even if it gets something working the resulting diff will be unreviewable. If you want to try this yourself you'll need to do it in many small manageable pieces and be open to reworking it many times. Alternatively it's something I might get to myself later this year. |
|
Just a quick note (as I was passing by), on a partial solution I had to such issues. My current structure uses a tree, much like the AST, but replicating data in my own memory space. Then, upon rebuilding, I delete the scope branchs linked to the modified file(s) and only recompute the appropriate references for the newly introduced changes. This provided significant speedups and would allow for a "messy" buffer reuse or reload from an external source (as I don't keep data from slang buffers). I came across https://github.com/hudson-trading/slang-server which somehow claim to use a |
Uh oh!
There was an error while loading. Please reload this page.
Hi Mike and the slang community,
I'd like to revisit incremental compilation in slang — specifically the
workflow where one source file changes and a tool wants to re-derive
elaboration results without paying the cost of a full rebuild. I've read
the prior threads (#733, #1166, #1247, #1675) and want to be respectful
of the constraints called out there before pitching anything.
Context
I'm building an open-source MCP server that wraps pyslang to provide
code-intelligence for SystemVerilog projects: hierarchy search, symbol
definitions / references / dependencies, file enumeration, and similar
navigation queries. The goal is to reach the responsiveness of existing
commercial-grade RTL code-intelligence solutions — sub-second
navigation queries against a fully-elaborated design database — using
slang as the engine.
For the "user just edited file X; tell me which errors that caused"
operation, the current pyslang/slang shape forces a full re-parse +
full re-elaboration on every edit. On a ~900-file industrial design
that's a multi-minute round trip. Commercial-grade equivalents claim
1–5 second feedback; reaching anything close with slang alone seems
blocked on missing API surface.
What I've tried
Parse-tree cache keyed by
(path, sha256). Reuses parsedSyntaxTreeobjects across rebuilds. Saves ~10–15% of cold-rebuildtime. This is the upper bound of "incremental" I can build today.
Per-file
SyntaxTree.fromFile()thenCompilation.addSyntaxTree().Works, but as How to update when RTL changes #733 documents, the
Compilationitself is rebuiltfrom scratch each time — AST + symbol resolution + elaboration all
redo from zero.
What I read as the current limits
From #733 and others:
SourceManagertext can't be unloaded safely — downstream symbolshold pointers into it.
SyntaxTrees from differentSourceManagers can't be combined intoone
Compilation("not really avoidable").change the interpretation of file B.
generate-block expansion depends on instance-site parameter overrides.
The combination implies "swap one tree, keep the rest" doesn't fit the
existing data model.
What would unlock this
I'd love to discuss whether any of these are tractable as long-term
goals:
A) A
Compilation::replaceTree(old, new)APIReturn a fresh
Compilation(or mutate in place) with one treeswapped, and re-resolve only the symbols whose dependencies cross
that tree's boundary. Closest to what salsa / rust-analyzer do.
Speculative shape (purely illustrative, not a proposal for the exact
signature):
The hard part is the dependency tracking — macros,
bind, andpackage imports create cross-file edges that aren't statically
declared. The framework would need to either invalidate
conservatively or track macro-expansion provenance.
B) A
CompilationScopefor trees that can be torn down and rebuiltLess ambitious: a sub-Compilation grouping that can be replaced
atomically while preserving the rest. A tool could partition trees
into "stable infrastructure" (UVM headers, std libraries) and
"edit-volatile" (user RTL).
C) A persistent tree pool keyed by content hash, owned by slang
An explicit API for the pattern several tools are already
implementing externally: "give me a Compilation built from these
(path, content_hash)trees; slang owns the cache and decides whatto reuse."
Questions
answer? The internal-cache work mentioned in Caching performance boost is huge! #1247 suggests
substantial memoization landed — does any of it overlap with what
would be needed for cross-invocation incremental?
per-tree work, that an API like Option A could surface to users?
pyslang, possibly upstream — where would you point them? Which
architectural unit would need to gain incremental awareness?
Why I'm asking
pyslang is already powering several language servers (#1191 Diplomat,
#1072) and the same wall-clock issue surfaces there. A first-class
API would benefit not just one tool but the broader RTL-tooling
ecosystem that's been growing on slang.
Happy to contribute design / prototyping cycles if there's interest.
And if the answer is "no, and here's why" — knowing that directly
helps the tooling community plan around it.
Thanks for the work you've put into slang and pyslang. It's a
fantastic foundation.
All reactions