[FIRRTL] CheckCombLoops crashes on a forceable register reference cast to a layer-colored RWProbe
Nobody has claimed this yet.
- Dominant language
- C++
- Stars
- 2.2k
- Forks
- 524
- Avg merge
- 3d 2h
- Merged PRs (30d)
- 46
Description
Summary
firrtl-check-comb-loops crashes on a forceable register whose writable SSA reference is cast to a layer-colored reference and defined as an output probe.
The input passes parsing and verification. No force/release statement is needed, and the design has no combinational feedback.
Environment
- CIRCT revision:
eade0de61bc5a0d2ba1b9da951b69efcab19f8ce(HEAD) - firtool version: 1.158.0
- Platform: Linux x86-64
Reproducer
module {
firrtl.circuit "Repro" {
firrtl.layer @Test bind {}
firrtl.module @Repro(
in %clock: !firrtl.clock,
in %data: !firrtl.uint<8>,
out %out: !firrtl.uint<8>,
out %probe: !firrtl.rwprobe<uint<8>, @Test>
) {
%target, %target_ref = firrtl.reg %clock forceable
: !firrtl.clock, !firrtl.uint<8>, !firrtl.rwprobe<uint<8>>
firrtl.connect %target, %data : !firrtl.uint<8>
firrtl.connect %out, %target : !firrtl.uint<8>
firrtl.layerblock @Test {
%ref = firrtl.ref.cast %target_ref
: (!firrtl.rwprobe<uint<8>>) -> !firrtl.rwprobe<uint<8>, @Test>
firrtl.ref.define %probe, %ref : !firrtl.rwprobe<uint<8>, @Test>
}
}
}
}
# Succeeds.
circt-opt repro.mlir -o /dev/null
# Aborts with exit code 134.
circt-opt --firrtl-check-comb-loops repro.mlir -o /dev/null
Expected Behavior
The pass succeeds without reporting a combinational cycle.
Actual Behavior
llvm/ADT/EquivalenceClasses.h:192:
Assertion `MI != member_end() && "Value is not in the set!"' failed.
Relevant stack frames:
DiscoverLoops::addToPortPathsIfRWProbe
DiscoverLoops::dfsTraverse
CheckCombLoopsPass::runOnOperation
Suspected Cause
In CheckCombLoops.cpp, the connectivity graph builder matches hw::CombDataFlow before Forceable. RegOp implements both interfaces, so the register takes the former branch and skips recordProbe().
Additionally, ref.cast does not establish writable-reference equivalence between its input and output. ref.define registers the cast result and output probe, but not the original register reference.
Later, addToPortPathsIfRWProbe() calls getLeaderValue() for the original reference, which is absent from the equivalence set.
As a control, defining an uncolored output probe directly from %target_ref, without the cast/layer block, passes the analysis.
`
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by running the provided repro with and without --firrtl-check-comb-loops, then inspect CheckCombLoops.cpp around DiscoverLoops::addToPortPathsIfRWProbe and the CombDataFlow/Forceable handling. Trace how the ref.cast and ref.define values enter the writable-reference equivalence set; done means the reproducer completes without an assertion and reports no combinational cycle.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- cpp
- Domain
- compilers
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 74/100