Commit Graph

10108 Commits

Author SHA1 Message Date
Hideto Ueno 9e5a9af8d3
[AIG][Python] Add Python bindings for LongestPathAnalysis (#8659)
This commit adds comprehensive Python bindings for AIG timing analysis, providing a high-level interface for critical path analysis

- LongestPathAnalysis class for performing timing analysis on AIG circuits
- LongestPathCollection with efficient caching and statistical methods
- Dataclasses (DataflowPath, Object, DebugPoint, OpenPath) for structured path representation with full type annotations
- Flamegraph generation for visualization
- Statistical analysis methods (percentiles, delay distribution)

The Python API builds on the C API, providing JSON deserialization into structured Python objects with caching for performance. The flamegraph output format enables visualization of critical timing paths through the circuit hierarchy.

Usage example:
```python
  analysis = LongestPathAnalysis(module)
  collection = analysis.get_all_paths("module_name")
  collection.print_summary()
  print(collection.longest_path.to_flamegraph())
````
2025-07-08 19:08:50 -07:00
Schuyler Eldridge ce0ad8a2ad
[arc] Fix dropped [[nodiscard]], error instead
Fix a potential problem where a `LogicalResult` would get dropped.  Check
the result and error if it failed instead of silently dropping it.

Signed-off-by: Schuyler Eldridge <schuyler.eldridge@sifive.com>
2025-07-08 14:53:11 -04:00
Martin Erhart 1e5ee92a3f
[RTG] Add LowerValidateToLabels pass (#8666) 2025-07-08 19:50:23 +01:00
Schuyler Eldridge c7e10d7c35
[FIRRTL] Remove firrtl_black_box_resource_files.f
Remove the generation of `firrtl_black_box_resource_files.f`.  This file
was originally controllable by the `BlackBoxResourceFileNameAnno`, but
that has since been removed.  This file is, additionally, no longer load
bearing and can be completely dropped.

Signed-off-by: Schuyler Eldridge <schuyler.eldridge@sifive.com>
2025-07-08 14:33:16 -04:00
Schuyler Eldridge 900639652a
[FIRRTL] Delete BlackBoxResourceFileNameAnno
Remove `BlackBoxResourceFileNameAnno` since this has not been load beagin
after it was removed from Chisel [[1]].  This annotation was used to
control the name of a file which was produced that listed all blackboxes
in the design.  Instead, use the default name always.

Note: I plan to remove this file entirely in a follow-on as this appears
to be completely unused.

[1]: 70f5c7066b

Signed-off-by: Schuyler Eldridge <schuyler.eldridge@sifive.com>
2025-07-08 14:33:13 -04:00
Fabian Schuiki ceec72901a
[FIRRTL] Use NonConstUInt1Type for LTL intrinsics
Change the result type of LTL intrinsic ops from `UInt1Type` to
`NonConstUInt1Type`. The latter defines a default builder, which then
allows the `build` method of ops like `LTLAndIntrinsicOp` to drop the
result type argument and automatically populate it with `uint<1>`. This
should then also simplify the C API.

This only adds an additional build method and shouldn't change any
existing use case.

Thanks @sequencer for pointing this out!

Fixes #8653.
2025-07-08 11:12:40 -07:00
Jacques Pienaar 2a5764e164
Convert to CF before running LLHD inline. (#8667)
The LLHD inliner doesn't check if the parent op only supports single
block regions when inlining a call (while the function body of the call
may already be multiblock). This flips the lowering to CF to before LLHD
inline to avoid a common variant of this (inlining into SCF ops).
2025-07-08 10:07:29 -07:00
Jacques Pienaar b033712e91
[importverilog] Lvalue RangelSelect and ElementSelect to use range. (#8663)
This makes it uniform with how the RvalueExprVisitor handles it.

Resolves: #8657
2025-07-08 10:07:12 -07:00
Fabian Schuiki 9ef39afe15
[LLHD] Make Deseq pass emit seq.firreg instead of seq.compreg (#8662)
The LLHD Deseq pass detects clocks and optional asynchronous resets. It
currently, mistakenly, creates `seq.compreg` ops with those clocks and
resets. The `seq.compreg` op turns out to have a _synchronous_ reset
though, making the lowering invalid. Use the `seq.firreg` op instead, as
it allows the reset type to be specified explicitly. This requries an
additional `comb.mux` to be created for potential enable signals, which
`seq.firreg` does not support directly.

We should really nail down the semantics of `seq.compreg` in a follow-up
commit. The documentation is very vague, and Deseq is likely not the
last pass mistakenly assuming the explicit reset of `seq.compreg` is
assumed to be asynchronous.
2025-07-08 09:47:11 -07:00
Hideto Ueno c8a189fe09
[circt-synth] Add `-emit-bytecode` option (#8661)
This PR adds `emit-bytecode` option to circt-synth following firtool or circt-dis tool driver.
2025-07-07 19:25:19 -07:00
Jacques Pienaar b5c025ccd9
[seq] Simplify clock enabled when constant enabled. (#8655)
If always enabled, it is equivalent/always better to just use compreg op.
2025-07-07 19:10:47 -07:00
Fabian Schuiki 944a6738e1
[LLHD] Add loop unrolling pass (#8620)
Add an LLHD pass that unrolls loops with statically-known bounds.

The pass computes the dominance info for `llhd.combinational` ops, finds
loop back-edges by looking for blocks that branch back to blocks that
dominate them, which yields initial *loop head* and *back-edge* pairs.
Based on these the pass populates a data structure with loop metadata,
including the blocks in the loop body, exit control flow edges, the exit
condition, induction variable, and loop bounds. After gathering this
information, the loop body is simply stamped out muliple times, the few
relevant control flow edges are adjusted, and a rough cleanup of unused
blocks and values is performed.

The current implementation of the pass is *very* conservative. The loops
are required to have very simple control flow, and the induction
variable must go from 0 to a positive upper bound in increments of 1.
We'll want to relax these constraints in the future and allow other
increments/decrements, comparison predicates, and more.

Thanks again to @maerhart for doing a lot of initial work for this on
his experimental branch.

Co-authored-by: Martin Erhart <martin.erhart@sifive.com>
2025-07-07 18:27:06 -07:00
John Demme 63f35fdff2
[PyCDE] Add bundle transform and rework coerce (#8660)
Enhances bundle handling by adding per-channel transform support
and refining bundle coercion, while also updating the ESI operations’
usage checks.

- Distinguish empty vs. multiple uses in PackBundleOp/UnpackBundleOp
  verify functions
- Extend Bundle.get_to_from to handle up to two channels and return
  optional results
- Introduce BundleSignal.transform for per-channel data transforms
- Overhaul coerce logic
2025-07-07 17:39:56 -07:00
John Demme 8c1865c5a9
[ESI] Make RAM delarations' addresses unsigned (#8658)
Using signless ints as the address was just wrong. It was probably done
to avoid incomplete lowerings, which have been addressed. Changes RAM
declaration addresses to use unsigned integer types throughout the
ESI dialect and its tests, updating both the code generator and
expected outputs.

- Switch address ports to unsigned (uiN) in MLIR tests and service
  definitions.
- Update service port generation and SystemVerilog memory
  instantiation to use unsigned address types, inserting bitcasts to
  signless for indexing.
- Adjust PyCDE front end and software integration tests to use
  UInt addressing.
2025-07-07 12:43:12 -07:00
John Demme 137b13de04 [HWArithToHW] Add support for unpacked arrays
Pass did not support unpacked arrays.
2025-07-07 19:11:21 +00:00
Samuel Coward f26f1ed5c1
[Datapath] Operator definitions and canonicalization patterns (#8647)
Building on the boiler plate definition adding two operators
* `datapath.compress` - compressor tree circuit
* `datapath.partial_product` - partial product generation circuit

The key idea is to view datapath operators as generators of circuits that satisfy some contract, for example in the case of the `datapath.compress` summing it's results is equivalent to summing it's inputs. This allows us to defer implementing these critical circuits until later in the synthesis flow.

In a simple example, we can fold a*b+c using the datapath dialect to remove a carry-propagate adder:
```mlir
%0 = comb.mul %a, %b : i4
%1 = comb.add %0, %c : i4
```
Which is equivalent to:
```mlir
%0:4 = datapath.partial_product %a, %b : (i4, i4) -> (i4, i4, i4, i4)
%1:2 = datapath.compress %0#0, %0#1, %0#2, %0#3, %c : i4 [5 -> 2]
%2 = comb.add %1#0, %1#1 : i4
```
2025-07-07 11:50:56 -07:00
John Demme 74736548c8
[PyCDE] Improve location information (#8635)
- Move from single location to stack
- Add location to a bunch of places it was missing
2025-07-07 08:58:16 -07:00
Martin Erhart 587474b1aa
[RTG] Add EmbedValidationValuesPass (#8648) 2025-07-07 15:43:07 +01:00
Hideto Ueno 4bb54cdf9d
[AIG][CAPI] Add C API for LongestPathAnalysis (#8652)
This commit introduces C API bindings for AIG LongestPathAnalysis and LongestPathCollection, enabling longest path analysis of AIG circuits from C and other languages.

The API uses JSON serialization for path data exchange, providing a stable interface while the underlying data structures evolve. Paths are automatically sorted by delay in descending order for efficient critical path analysis.
2025-07-04 19:28:56 -07:00
Hideto Ueno 796f83ba94
[AIG][NFC] Introduce a helper struct to manage result paths (#8651)
Add LongestPathCollection class to manage and own path data
2025-07-03 15:57:30 -07:00
Hideto Ueno 02eff0608d
[AIG] Enhance longest path analysis with detailed timing statistics and JSON output (#8644)
This patch improves the AIG longest path analysis pass with:
- Detailed timing level statistics showing delay distribution
- Critical path details for top K fanout points
- Path history with intermediate debug points
- JSON output format option for machine-readable results
- Improved documentation and command-line options

The enhanced analysis provides more comprehensive timing information
for debugging and optimizing AIG circuits, with both human-readable
and machine-parseable output formats.
2025-07-03 13:01:19 -07:00
Schuyler Eldridge d9e5efd4d8
[FIRRTL] Report all lint errors, not just first
Change FIRRTL's linting pass to report all lint errors instead of just the
first lint error.

Signed-off-by: Schuyler Eldridge <schuyler.eldridge@sifive.com>
2025-07-03 15:43:51 -04:00
Fabian Schuiki 27fc29747c
[ExportVerilog] Add support for hw.array_inject (#8645)
Extend the PrepareForEmission part of ExportVerilog to lower
`hw.array_inject` into a bit of procedural Verilog code that overwrites
the injected array index:

```systemverilog
// %b = hw.array_inject %a[%i], %v
logic [N-1:0] b;
always_comb begin
  b = a;
  b[i] = v;
end
```

Unfortunately assignment patterns like `'{0: x, 1: y, 2: z}` only
support constant expressions for the array indices. The only options to
mutate a single array entry that I am aware of are the procedural style
implement in this commit, and creating a separate mux/ternary op for
each index separately, which feels like total overkill.
2025-07-03 11:46:25 -07:00
Schuyler Eldridge c4ce58c90c
[HW] Remove defensive, unnecessary default
Remove some defensive coding that added a default case to a fully covered
switch statement.  This is a compile time warning if not removed.

Signed-off-by: Schuyler Eldridge <schuyler.eldridge@sifive.com>
2025-07-03 14:36:37 -04:00
Schuyler Eldridge 35d521e75c
[FIRRTL] Refactor Linting pass, NFC
Refactor FIRRTL's linting pass to use a pattern where an object is created
which tracks state for the operation in question.  While not currently
used this way, I want to add state and this second object gives me some
place to put it without having to clear state in the actual pass itself.

This makes no functional changes to the code and just reogranizes existing
methods into this new class and then uses it in the pass.

Signed-off-by: Schuyler Eldridge <schuyler.eldridge@sifive.com>
2025-07-03 14:32:34 -04:00
Fabian Schuiki 6a4f6c7269
[circt-verilog] Add MapArithToComb pass to pipeline (#8649)
Add the MapArithToComb pass to the circt-verilog pipeline. The
canonicalizers in the CF dialect produce `arith.select` and
`arith.constant` operations, but we would like the circt-verilog
pipeline to produce pure HW/Comb/Seq output where possible.

In the future we might want to move the pass from `Transforms` to
`Conversions`.
2025-07-03 10:45:20 -07:00
Hideto Ueno 8fbefed670
[Python] Add Python bindings for AIG dialect (#8646)
This commit adds comprehensive Python bindings for the AIG (And-Inverter Graph) dialect.

The implementation includes an AIG C API header with dialect registration and an AIG C API implementation with pass registration.
It adds an AIG Python dialect TableGen file and Python dialect module. The AIG Python module C++ bindings are implemented using nanobind.

The implementation follows the pattern used by other CIRCT dialects
and enables Python users to work with AIG operations like and_inv through the
circt.dialects.aig module.
2025-07-03 09:04:50 -07:00
Martin Erhart f2e5637ba0
[RTG] Add ValidationTypeInterface (#8639)
Co-authored-by: Fabian Schuiki <fabian@schuiki.ch>
2025-07-03 11:24:53 +01:00
Samuel Coward 3011bf1a20
[Datapath] Datapath Dialect Definition (#8638)
The datapath dialect will be used as part of the growing synthesis capabilities, where arithmetic operators such as comb.mul and multi-input comb.add can be lowered to gates via the datapath dialect. The datapath dialect allows us to directly express efficient circuits such as compressor trees, in the IR itself, allowing us to manipulate and combine arithmetic operations.

The key idea is to view datapath operators as generators of circuits that satisfy some contract, for example in the case of the datapath.compress summing it's results is equivalent to summing it's inputs. This allows us to defer implementing these critical circuits until later in the synthesis flow.

In a simple example, we can fold a*b+c using the datapath dialect to remove a carry-propagate adder:

```mlir
%0 = comb.mul %a, %b : i4
%1 = comb.add %0, %c : i4
```
Which is equivalent to:
```mlir
%0:4 = datapath.pp %a, %b : 4 x i4
%1:2 = datapath.compress %0#0, %0#1, %0#2, %0#3, %c : 5 x i4 -> (i4, i4)
%2 = comb.add %1#0, %1#1 : i4
```
This is the first in a series of commits to add datapath synthesis capabilities that will include the following (implemented but not merged):
2025-07-02 14:31:24 -07:00
Fabian Schuiki 62eefbd9c6
[LLHD] Use initial signal value to fill gaps in CombineDrives (#8636)
If the CombineDrives pass can see and reason about all uses of a signal,
use the signal's initial value to fill in any undriven parts of the
signal. This works around a somewhat common pattern in input Verilog
where an array signal has some of its elements completely unused --
neither read nor written:

```systemverilog
logic [1:0][31:0] a;
assign a[0] = ...;
assign ... = a[0];
// a[1] is completely unused
```

Driving previously undriven parts of the signal with their initial value
is valid if we can guarantee that there are truly no drivers to those
parts. In that case, adding a driver does not cause any drive conflicts,
and the driven value is the same as the value already on the signal,
namely the initial value.

One caveat is that this transform is only valid if the initial value of
the signal is a constant. This is not always guaranteed, with the
initial value potentially being provided by a constant passed in through
a port. The Deseq pass faces a similar issue where real-world Verilog
usage makes use of somewhat unclear semantics in initialization order.
We should revisit the `llhd.sig` op at a later stage and consider using
@uenoku's `seq.initial` mechanism to ensure that the value is static
during runtime, or make the signal initial value an attribute.
2025-07-02 09:35:49 -07:00
Yicheng Liu 8c9625232c
[circt-bmc] Support registers with reset signals (#8622) 2025-07-02 16:52:51 +01:00
Robert Young b5a0c46876
[FIRRTL] Allow layers to RWProbe into the design (#8641)
* Revert "[FIRRTL] Verify RWProbeOp target has layer requirements. (#7372)"

This reverts commit 4415b9c2f7.

* Add test for sinking RWProbe into layer
2025-07-02 11:16:45 -04:00
Hideto Ueno d77bd7f21d
[AIG] Fix history's instance path update in LongestPathAnalysis (#8637)
Fix incorrect instance path update  in the LocalVisitor::visit method for hw::InstanceOp. This ensures correct instance path construction when traversing through nested module instances.
2025-07-02 02:59:57 -07:00
Martin Erhart c5ce0d5473
[RTG] Add UniqueValidateOpsPass (#8633) 2025-07-02 09:36:04 +01:00
Martin Erhart 89cacf0259
[RTG] Add validate operation (#8631) 2025-07-02 09:19:51 +01:00
Hideto Ueno 4205d72807
[AIG] Refactor Longest Path Analysis with hierarchical path support (#8630)
This patch refactors the Longest Path Analysis in the AIG dialect with several
enhancements:

- Refactor DataflowPath to use a clean variant-based API for different endpoint types
- Reorganize the API with purpose-specific methods replacing complex tuple returns
- Add support for hierarchical path elaboration with prependPaths methods
- Introduce a unified getAllPaths convenience method to collect all timing paths
- Simplify the PrintLongestPathAnalysis pass to use the new API

The refactoring enables more comprehensive timing path analysis across module
boundaries with proper hierarchical instance information while providing a
cleaner, more maintainable API.
2025-07-01 12:26:50 -07:00
Fabian Schuiki 5f87d2acfc
[LLHD] Remove drive-only signals in Sig2Reg pass (#8629)
Extend the Sig2Reg LLHD pass to completely remove a signal and all its
associated drives if the signal is only driven, but never probe or used
in any other way.
2025-07-01 09:01:13 -07:00
Fabian Schuiki e636298d73
[ImportVerilog] Detect and fixup two-state-exhaustive case statements (#8628)
Case statements often occur in the following form in real-world Verilog:

```
module Foo(input logic [1:0] a, output logic [3:0] z);
  always_comb begin
    case (a)
      2'd0: z = 4'b0001;
      2'd1: z = 4'b0010;
      2'd2: z = 4'b0100;
      2'd3: z = 4'b1000;
    endcase
  end
endmodule
```

The intention being that the case statement exhaustively covers all
possible `a` input values, and assigns a corresponding `z` output value.
This case statement _is_ exhaustive assuming two-state logic. However,
the Verilog `logic` type is four-state, where the bits in `a` can also
have the value X and Z. If `a` contains X or Z, none of the case
statements would execute and `z` would not be assigned, essentially
creating a latch.

In practice, logic synthesizers fold X and Z values to 0 or 1 however
they see fit, often in an attempt to minimize logic. For this case
statement the obvious assumption is that the input is two-state and the
match is exhaustive. This does not work in simulation, though.

This commit makes ImportVerilog detect if a case statement is exhaustive
assuming two-state logic. If it is, the last case item is treated as the
default, being executed regardless of its case value. As a result, the
above example generates a CFG where all possible paths through the case
statement assign the output `z`. This then ensures that the case
statement can be lowered to properly in circt-verilog, without
generating conditional drives or latches.

The core dialects of CIRCT currently don't represent X and Z well, and
most of ImportVerilog and the circt-verilog pipeline assumes all values
are two-state. Once we add X and Z handling to the core dialects, we
will have to revisit this behavior and make it opt-out.

Fixes #8626.
2025-07-01 08:52:00 -07:00
Fabian Schuiki 8d45153676
[MooreToCore] Remove unused variable; NFC 2025-07-01 08:39:57 -07:00
Liam Jay 4397470a0f
[MooreToCore] Lower exponentiation to math.ipowi (PowSOpConversion) (#8574)
Replace for-loop-like logic in the `PowSOpConversion` in `MooreToCore`
with the `math.ipowi` op from the upstream Math dialect. Also add the
Math dialect to the MooreToCore conversion pass dependent dialects.
Update tests accordingly.
2025-07-01 08:27:47 -07:00
Martin Erhart ae167116fa
[RTG] Add CAPI and python bindings to register passes (#8632) 2025-07-01 13:30:29 +01:00
Hideto Ueno b281d7e250 [CI] Add `|| true` for `git clang-format`
git clang-format exists with non-zero exit code when a change is applied.
github action fails immediately after that by default so add `|| true`.
2025-06-30 21:32:07 -07:00
Schuyler Eldridge ee18ff67f5
[ci] Fix issues in cleanup cache
Fix an issue where the appropriate permissions were not set in the
`uploadReleaseArtifacts.yml` job that are necessary, transitively for the
`cleanupCache.yml` job.

Remove a deleted `dry_run` parameter passed to the `cleanupCache.yml` job
from the UBTI-static job.

Don't use `bash` unnecessarily as it isn't installed by default in alpine.

Signed-off-by: Schuyler Eldridge <schuyler.eldridge@sifive.com>
2025-06-30 22:44:37 -04:00
Hideto Ueno d40693a51c
[Support] Add concatPath method to InstancePathCache (#8627)
Add a new method to InstancePathCache that concatenates two instance paths.
This complements the existing prependInstance and appendInstance methods,
providing a more complete API for manipulating instance paths.
2025-06-30 18:31:32 -07:00
Schuyler Eldridge 81140f6a2c
[FIRRTL] Fix Grand Central companion not-in-design (#8625)
Fix a regression introduced in 88f5d5a56 where a Grand Central companion
instantiated only under the test harness would cause the companion to be
instantiated in the Grand Central directory and not under the test harness
directory.  An early exit if no instances are in the design was
incorrectly dropped.

Signed-off-by: Schuyler Eldridge <schuyler.eldridge@sifive.com>
2025-06-30 19:21:13 -04:00
John Demme 23d266549e
[PyCDE] Import MLIR: provide hook to preprocess ops (#8624)
Adds the ability for users to load the MLIR file and preprocess
or skip pre-lowering ops.
2025-06-30 12:43:48 -07:00
Hideto Ueno f0d44e9966 [CI] Change cache cleanup threshold from 1/2 to 1/3
Sometimes cache sizes for Windows CI builds on main branch are smaller
compared to caches from other branches for unknown reasons. In that case,
a cache from a successful build could be accidentally removed when using
the 1/2 threshold. This commit reduces the threshold to 1/3 to be more
conservative and preserve successful build caches.
2025-06-30 08:21:12 -07:00
Hideto Ueno 3d8a532574
[CI] Add smarter cache cleanup with size-based filtering (#8580)
Updated cache cleanup system so that we can remove small caches (likely from failed builds) and maintain only the most recent successful builds. Previously cache is saved even when the step fails so cache hit rate dramatically decreases after the compilation failure in the early stage (via trivial error or manual cancelation).

This commit adds new cleanupCache step (renamed from garbageCollection step since I thought cleanup is better name). 
This implementation uses a dynamic size threshold of 1/2 of maximum cache size as the cleanup threshold. It employs regex pattern matching to find caches with `.*PATTERN.*` for flexible matching. The system keeps the top 1 cache to preserve the most recent successful build and is safe by default with dry-run mode enabled to prevent accidental deletions.

The changes add a reusable cleanup workflow at .github/workflows/cleanupCache.yml and integrate cache cleanup into unified build workflows. Cache cleanup has been added to short integration tests with cache key pattern generation and reuse implemented.

The cache cleanup logic calculates the threshold as 50% of largest cache size, then deletes all caches smaller than the threshold (failed builds) and deletes caches beyond top 1 that exceed the threshold (old builds). It uses regex matching for flexible cache key patterns.

The workflows updated include unifiedBuildTestAndInstall.yml, unifiedBuildTestAndInstallStatic.yml, and shortIntegrationTests.yml and windowsCI.
2025-06-30 02:46:23 -07:00
Schuyler Eldridge e835e1ab3e
[FIRRTL] Avoid interface cast in inject-dut-hier (#8619)
Fix a nightly failure observed with gcc release builds due to a cast of an
interface to an operation.  This is known to be problematic.

Signed-off-by: Schuyler Eldridge <schuyler.eldridge@sifive.com>
Co-authored-by: Andrew Young <youngar17@gmail.com>
2025-06-28 18:28:16 -04:00
Hideto Ueno 1b810c5d4a
[FIRRTL] Fix cat canonicalization to handle mixed signed/unsigned operands (#8621)
This commit enhances the cat operation canonicalization in FIRRTLFolds.cpp to properly handle cases where operands have mixed signed and unsigned types.

The implementation now tracks whether signed and unsigned operands exist during cat flattening. When mixed types are present, it adds explicit casting of signed values to unsigned using AsUIntPrimOp. Single operand cases are also properly cast to unsigned if needed.

Fix #8618
2025-06-28 14:29:05 -07:00