llvm / llvm/circt

[Comb] Assertion failure in type inference for width-changing ops (e.g. ConcatOp) with symbolic hw::IntType

Open
#10,207 1 comment 0 reactions 0 assignees View on GitHub
Dominant language
C++
Stars
2.2k
Forks
524
Avg merge
3d 2h
Merged PRs (30d)
46

Description

Hi everyone,

I am developing a pass to outline structurally isomorphic logic cones into parameterized `hw.module`s. While 1:1 type mappings (like `comb.and`, `comb.or`, `comb.xor`) work with symbolic `hw::IntType`, I hit a roadblock with width-changing operations.

### The Problem
`firtool` and `circt-opt` crash with an assertion failure when the extracted logic includes operations that compute their result bit-widths by doing integer arithmetic on operand widths, such as `comb.concat` or `comb.add` (with carry).

The crash occurs because the internal type-inference APIs (like `getTotalWidth`) assume concrete `IntegerType` widths. When they try to cast our symbolic `hw::IntType` to an `IntegerType` to sum the literal bit counts, the cast fails and the compiler aborts.

### Steps to Reproduce
If we construct an IR where a `comb.concat` receives a symbolic parameter (e.g., concatenating a 1-bit constant with a `WIDTH` parameter to detect overflow), it triggers the crash.

**Here is a minimal snippet:**

```mlir
hw.module @extracted_concat(in %in_0 : !hw.int<#hw.param.decl.ref<"WIDTH">>, out out_0 : !hw.int<#hw.param.expr.add<#hw.param.decl.ref<"WIDTH">>, 1>>) {
%c0_i1 = hw.constant 0 : i1
%0 = comb.concat %c0_i1, %in_0 : i1, !hw.int<#hw.param.decl.ref<"WIDTH">>
hw.output %0 : !hw.int<#hw.param.expr.add<#hw.param.decl.ref<"WIDTH">>, 1>>
}
```

**Crash Log:**
```mlir
circt-opt: include/circt/Dialect/HW/HWTypes.h:164: BaseTy circt::hw::type_cast(mlir::Type) [with BaseTy = mlir::IntegerType]: Assertion `type_isa(type) && "type must convert to requested type"' failed.
...
#14 getTotalWidth(mlir::ValueRange) lib/Dialect/Comb/CombOps.cpp
#15 circt::comb::ConcatOp::inferReturnTypes(...)
```

### Proposed Direction
To properly support symbolic widths, it seems we need to extend the type-inference utilities so that width computations produce symbolic expressions (e.g., `WIDTH + 1` via `hw::ParamExprAttr`) instead of raw integers.

I believe we should update ops like `ConcatOp::getTotalWidth` to build these expressions rather than casting to integers, only resolving to concrete values when parameters are bound.

Is this transition toward symbolic expressions for type inference already on the roadmap for the `comb` dialect? Are you interested on that? If so, can I work on it?

I would appreciate any thoughts on this!

Contributor guide

No contributing guide indexed for this repository

Research direction

Start with include/circt/Dialect/HW/HWTypes.h around the type cast assertion, then inspect getTotalWidth and ConcatOp::inferReturnTypes in lib/Dialect/Comb/CombOps.cpp. Reproduce the failure with circt-opt or firtool using the provided symbolic-width comb.concat IR. Done means width inference builds symbolic expressions such as WIDTH + 1 instead of assuming concrete IntegerType widths, while still resolving concrete values when parameters are bound.

Written by the indexing model from the issue text.

Assessment

Tech stack
cpp
Domain
compilers
Issue type
Bug
Difficulty
5/5
Estimated time
Over a week
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
38/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.