This pull request improves the MLIR import functionality in PyCDE by
supporting custom op conversion during module import. Key changes
include:
- Adding new parameters (module_str, file, importer, debug) to the
import_mlir function for enhanced flexibility.
- Modifying the lowering passes list with new entries for Kanagawa
dialect lowering.
- Updating import_hw_module to accept an optional builder_type parameter
for custom module building.
This PR adds support for importing Kanagawa IR into PyCDE and improves
the overall pass management and proxy caching in the system.
- Added a new test file for Kanagawa IR import and lowering.
- Updated the System and _OpCache functionality to change type hints and
weak reference handling.
- Revised the imported module creation and pass-phase execution logic.
This commit refactors and adds an option to AIGERRunner.
1. Create ExternalSolverPass base class to reduce code duplication between AIGERRunner and ABCRunner passes, providing shared options and dependent dialects through inheritance.
2. Add --ignore-abc-failures command line option to circt-synth tool to enable continue-on-failure behavior for ABC optimization. Currently the pass fails if there are multiple clocks so it's convenient to just skip them.
- Register the kanagawa dialect in Python bindings
- Register kanagawa dialect passes
- Add C API header and implementation for kanagawa dialect
- Add integration test for kanagawa dialect and passes
Follows the same pattern as pipeline dialect registration in commit 5c4d8ae.
Fix a bug in the Grand Central pass where it was deleting instances and
modules, but not keeping the instance graph up to date.
Signed-off-by: Schuyler Eldridge <schuyler.eldridge@sifive.com>
Change the Grand Central View lowering pass to now allow for Grand Central
Companions to be multiply instantiated. This should have technically been
possible for a long time [[1]] as long as there was a guarantee that there
was never going to be a leaf that was _outside_ the companion.
This is a pretty simple change to just loop over all instances and
extract (add a `lowerToBind` attribute) for the ones which are in the
design. The other, subtle blocker is that without the `InstanceInfo`,
doing the check of "in the design" was tedious. Now this is pretty
straightforward.
[1]: 2d3a040f43
Signed-off-by: Schuyler Eldridge <schuyler.eldridge@sifive.com>
In preparation to remove the exactly-one-instance check of each Grand
Central Companion module, inline the function doing this check and get
this in the right shape to switch it over to allow for multiple
instantiation.
Signed-off-by: Schuyler Eldridge <schuyler.eldridge@sifive.com>
Change FIRRTL's inject-dut-hier pass to move all annotations onto the
wrapper [^1] when in `moveDut=true` mode. Additionally, when in this
mode, the WRAPPER will be named using the `name` field of this pass'
controlling annotation. Previously, this would only move the
`MarkDUTAnnotation` when operating in this mode. This fixes an internal
issue where Object Model paths were not being updated when using this pass
in `moveDut=true` mode.
[^1]: This is using the terminology of the pass which views this as taking
all the logic inside the original DUT and shoving it into a wrapper
instantiated inside the DUT. When in `moveDut=true` mode, it is more
natural to think of the pass as creating a wrapper around the original
DUT. However, to adopt this alternative terminology would be modal.
I.e., "wrapper" would mean something different when in `movedDut=true`
mode which would be confusing.
Signed-off-by: Schuyler Eldridge <schuyler.eldridge@sifive.com>
Refactor the InjectDUTHierarchy pass to not introduce the notion of a
`newDUT` variable. This only confuses things. Instead setup the DUT and
its internal wrapper immediately and then reuse these terms in all places.
Signed-off-by: Schuyler Eldridge <schuyler.eldridge@sifive.com>
Re-enable the canonicalizers and constant folders for `comb.extract`,
`comb.concat`, and arrays of `comb.mux` that have operands defined in
different blocks.
Also remove the `hasOperandsOutsideOfBlock` function which is no longer
needed.
This commit enhances FIRRTL canonicalization with several new optimization patterns:
**Reduction-Cat Patterns:**
- Replace table-driven patterns for AndR/OrR/XorR with cat operands with C++
- AndRCat: Optimizes andr(cat(...)) by handling zero constants (-> 0) and all-ones constants (identity)
- OrRCat: Optimizes orr(cat(...)) by handling non-zero constants (-> 1) and zero constants (identity)
- XorRCat: Optimizes xorr(cat(...)) by preserving non-zero constants and eliminating zero constants
**Cat Optimization Patterns:**
- FlattenCat: Flattens nested cat operations into single cat operations for better optimization opportunities
- CatOfConstant: Folds successive constant operands in cat operations (e.g., cat(x, 3, 5, y) -> cat(x, 29, y))
- BitsOfCat: Optimizes bits extraction from cat operations by extracting directly from the appropriate operand when possible
The new patterns replace the previous table-driven AndRCat*, OrRCat*, and XorRCat* patterns since it's
too complicated to handle the condition in tablegen
Re-enable the canonicalizers and constant folders for `comb.replicate`,
`comb.parity`, `comb.shl`, `comb.shru`, `comb.shrs`, `comb.mux`, and
`comb.icmp` that have operands defined in different blocks.
Re-enable the canonicalizers and constant folders for `comb.add`,
`comb.sub`, `comb.mul`, `comb.divu`, `comb.divs`, `comb.modu`, and
`comb.mods` that have operands defined in different blocks.
This patch converts CatPrimOp from a binary operation to a variadic operation that can accept multiple operands. The change is mostly mechanical:
- Updating the fold method to handle multiple operands
- Modifying canonicalization patterns to work with the new variadic form (https://mlir.llvm.org/docs/DeclarativeRewrites/#supporting-variadic-ops)
- Updating the FIRRTL to HW lowering to handle variadic concatenation
- Adjusting the FIREmitter FIRRTLVistior
Now that #8517 has landed, re-enable the canonicalizers and constant
folders for `comb.and`, `comb.or`, and `comb.xor` that have operands
defined in different blocks.
Add the *RemoveControlFlow* pass to the LLHD dialect. It operates on all
`llhd.combinational` ops in an `hw.module` if the op has no side-effects
and the control flow is acyclic. The pass moves all operations in the
`lhld.combinational` op body into its entry block and inserts `comb.mux`
ops to resolve block arguments. All blocks besides the entry block are
then removed.
A future loop unrolling pass would get rid of any cycles in the control
flow, such that this pass can then pick up the remaining control flow
lowering.
This is an important pass in lowering behavioral circuit descriptions,
such as `always` blocks in Verilog or `process`es in VHDL, to a set of
equivalent Comb dialect ops in the module body.
Shoutout to @maerhart for doing all the heavy lifting for this pass on
his experimental branch!
Co-authored-by: Martin Erhart <martin.erhart@sifive.com>
Fix a bug where an analysis was used before being initialized when
running in debug mode with the Grand Central pass. This bug was
unreachable when _not_ running in debug mode.
Signed-off-by: Schuyler Eldridge <schuyler.eldridge@sifive.com>
Move a definition closer to its usage site in the Grand Central pass.
This is working towards enabling multiple instantiation of Grand Central
Views.
Signed-off-by: Schuyler Eldridge <schuyler.eldridge@sifive.com>
Tweak the Grand Central pass to use module port info instead of instance
port info when doing annotation validation checking.
Signed-off-by: Schuyler Eldridge <schuyler.eldridge@sifive.com>
Historically, we would assert that every tracker was used exactly
once. However, with certain combinations of multiple instantiation and
dedup, we can run into duplicate trackers. Specifically, like in the
test case, if there are two modules that dedup, but they are
instantiated multiple times in modules that do not dedup, we can end
up with duplicate trackers that point to the same thing. When dedup is
working, the paths are distinct, and it is only at the end that we
realize they are pointing to the same thing.
This handles that case, by actually checking the path associated with
duplicated trackers. If the trackers ultimately ended up pointing to
the same thing, this is now allowed. It is still an error to have
the same tracker pointing to multiple different paths through the
hierarchy.
Finally, this removed the sentinel PathInfoTableEntry objects we would
create simply to check uniqueness. Now that we are actually using the
paths to confirm uniqueness or lack thereof, we don't need the sigil,
and putting in a PathInfoTableEntry without a path means we can't
perform the new check. These only existed for unused paths, which the
situation described above in dedup can create. Since they're dead, we
can now safely just skip them.
Running CSE on a whole design is neither necessary nor advisable. It forces all the dialects used to support CSE but at least one (which we use) has issues with it. So we add a PR which targets redundant operations in the `kanagawa` dialect which passes assume to be non-redundant.
Also updates `kanagawatool` to add new passes which are now necessary.
This patch modifies the nightly integration tests workflow to only use
ccache when the build type is Release. This helps optimize CI resources
by avoiding unnecessary caching for debug builds, which have shown cache
hit rates of less than 0.5%. By focusing caching efforts on Release builds,
we can improve overall CI efficiency and reduce storage requirements.
Clang 14 on my macOS machine complains about the `definition` and
`declaration` local bindings being captured by the `allAttrsMatch`
lambda. Looks like this is technically illegal, but gcc and some later
flavors of clang accept this.
Update the LLHD pass intended to inline all function calls.
This commit renames the pass from "FunctionElimination" to
"InlineCalls", since the updated pass no longer deletes the functions.
Instead, MLIR's SymbolDCE pass should be used after call inlining to get
rid of any unused function definitions.
The pass logic is also adjusted to support nested function calls. This
allows deeply nested call graphs to be completely inlined, which is a
prerequisite for many synthesis-related passes that may follow in the
pipeline. A stack of called functions is used to track function nesting
and prevent recursive calls from infinitely expanding.
As before, the pass produces an error diagnostic for any call op nested
within an HW module that cannot be inlined.
This commit also adds the call inlining pass to the circt-verilog
pipeline, alongside an additional SymbolDCE run to clean up the unused
functions afterwards.
Co-authored-by: Martin Erhart <martin.erhart@sifive.com>
This commit introduces a new infrastructure for running external logic
synthesis tools (ABC, Yosys, etc.) on AIG modules through AIGER format
export/import.
The implementation provides two new passes, AIGERRunner and ABCRunner, that
export modules to AIGER format, run external solvers, and import optimized
results back to MLIR. The system includes sophisticated multi-bit value
handling with automatic decomposition during export and reconstruction during
import. The pass integrates seamlessly with the circt-synth tool to support
ABC optimization commands.
The core Converter class tracks bit-level mappings between MLIR and AIGER
representations, enabling accurate reconstruction of multi-bit values after
optimization. String placeholder replacement provides flexible solver command
configuration, supporting various external tools with different command-line
interfaces.
For testing purpose yosys-abc is mainly used
- Add LongestPathAnalysisWithTrace wrapper class to enable analysis manager
caching by default enabling trace functionality
- Move PrintLongestPathAnalysisPass implementation to separate file
(PrintLongestPathAnalysis.cpp) for better separation of concerns
- Update pass to use cached analysis results via getAnalysis<> instead of
creating new analysis instances
Add the WrapProceduralOps pass that takes operations such as `func.call`
or `scf.if` in HW module body and wraps them inside `llhd.combinational`
ops. This allows those operations to be inlined or lowered to the CF
dialect since the `llhd.combinational` op provides an SSACFG region.
Add the pass to the circt-verilog pipeline, alongside a lowering from
SCF to CF. This makes the core dialect output of circt-verilog more
regular, and will allow us to fully inline function calls and fully
unroll loops in the future.
This commit implements a comprehensive AIGER (And-Inverter Graph) export
functionality for CIRCT, supporting both ASCII (.aag) and binary (.aig)
formats as specified in the AIGER format specification.
The implementation provides complete AIGER export with proper literal
assignment and encoding for both ASCII and binary AIGER formats using
LEB128 encoding. Multi-bit values are automatically flattened to individual
bits to comply with AIGER's single-bit nature. The exporter handles AIG
operations including and_inv for AND gates and inverters, sequential
elements through seq.compreg for latches, and combinational operations
such as comb.concat, comb.extract, and comb.replicate. Constant propagation
is supported for hw.constant operations, and symbol tables are generated
with proper bit indexing.
The design includes an extensible handler interface for custom export
behavior (which is currently not used but will be utilized in a future PR
for the AIGER runner pass) and performs topological sorting to ensure
proper AIGER ordering constraints. The implementation uses equivalence
classes for efficient bit-level value tracking and proper delta encoding for
binary format AND gates.
This enables CIRCT to export AIG dialect operations to standard
AIGER format for use with external verification and synthesis tools.
- Fix lexer tokenization by removing premature whitespace skipping
- Add location-aware error reporting with SMLoc tracking throughout parser
The tokenization fix resolves issues where whitespace was being consumed
prematurely, causing parsing errors.
Extend the HoistSignals pass to also run on `llhd.combinational` ops.
This only covers probes for now, similar to how the pass handles
`scf.if` operations.
Don't check Valgrind in a test that is expected to fail due to Slang v3
issues.
Fixes#8587
Co-authored-by: Fabian Schuiki <fabian@schuiki.ch>
Signed-off-by: Schuyler Eldridge <schuyler.eldridge@sifive.com>
Initial setup for handling SystemVerilog Assertions by adding
AssertionExpr class and integrating LTL dialect. This enables the
foundation for converting SVA expressions to LTL.
Handle concurrent assertion statements by inserting Verif operations
assert and assume operations.
Use `AssertionExpr` to parse the expression.
Add a helper function to convert values to MLIR i1 type for LTL operations.
The function validates that moore::IntType inputs are 1-bit wide and creates
a ConversionOp to handle the conversion from SystemVerilog logic types.
SystemVerilog assertions evaluate expressions to Boolean values where only
'true' results in true, with 'unknown' and 'high impedance' values both
evaluating to false.
This conversion is needed for LTL operations, which only work with i1
types.
Add support for simple assertion expressions. Simple assertions consist
of an expression, handled by 'Expression.h', and an optional repetition.
Add conversion of the expression type to i1, which is the required input
value of LTL operations.
Add additional timing visitor to add LTL clock operation.
Enable the LLHD passes that have been updated in the past few months in
circt-verilog's pass pipeline. This contains revised versions of the
Mem2Reg, Deseq, and LowerProcesses passes, alongside a new HoistSignals
pass and the CombineDrives pass factored out of Sig2Reg.
This also disables the SROA pass on LLHD, moving it to only operate on
Moore modules. @maerhart has been looking into fixing an upstream bug in
SROA when it's used on operations in graph regions. Until that is fixed,
we can just skip SROA on HW modules for now.
Also add an end-to-end test for circt-verilog to ensure that the basic
forms of registers get detected and lowered properly.