PathNotFoundException in CheckCombLoops transform #2547
Description
Checklist
- Did you specify the current behavior?
- Did you specify the expected behavior?
- Did you provide a code example showing the problem?
- Did you describe your environment?
- Did you specify relevant external information?
What is the current behavior?
If you try to emit Verilog for the CycleTest
module in the following design, the CheckCombLoops
transform will throw a PathNotFoundException
:
import chisel3._
class CycleTest extends Module {
val m = Module(new Passthrough)
m.in := m.out
}
class Passthrough extends Module {
val in = IO(Input(Bool()))
val out = IO(Output(Bool()))
out := in
}
What is the expected behavior?
The CheckCombLoops
transform should emit a CombLoopException
.
Steps to Reproduce
Here's a Scastie which reproduces the error: https://scastie.scala-lang.org/X4WMiHaDQLWs9nc1IAZviA
Here's the relevant portion of the stacktrace:
firrtl.graph.PathNotFoundException: Unreachable node
at firrtl.graph.DiGraph.path(DiGraph.scala:225)
at firrtl.graph.DiGraph.path(DiGraph.scala:207)
at firrtl.transforms.CheckCombLoops.$anonfun$expandInstancePaths$2(CheckCombLoops.scala:187)
at scala.collection.immutable.List.map(List.scala:250)
at scala.collection.immutable.List.map(List.scala:79)
at firrtl.transforms.CheckCombLoops.expandInstancePaths(CheckCombLoops.scala:182)
at firrtl.transforms.CheckCombLoops.$anonfun$run$18(CheckCombLoops.scala:281)
at scala.collection.immutable.List.foreach(List.scala:333)
at firrtl.transforms.CheckCombLoops.$anonfun$run$7(CheckCombLoops.scala:274)
at firrtl.transforms.CheckCombLoops.$anonfun$run$7$adapted(CheckCombLoops.scala:252)
at scala.collection.immutable.List.foreach(List.scala:333)
at firrtl.transforms.CheckCombLoops.run(CheckCombLoops.scala:252)
at firrtl.transforms.CheckCombLoops.execute(CheckCombLoops.scala:319)
at firrtl.Transform.transform(Compiler.scala:280)
at firrtl.Transform.transform$(Compiler.scala:280)
at firrtl.transforms.CheckCombLoops.transform(CheckCombLoops.scala:101)
It looks like the m.in := m.out
connection in the CycleTest
module is the source of the problem. It creates two connected LogicNode
s which have the same inst
(m
in this case). Since they have the same inst
, the if
statement on line 184 of expandInstancePaths
matches, and on line 187 we try to find the path from out
to in
inside the Passthrough
module, but no such path exists (only the reverse of that path exists). Thus, line 187 throws the PathNotFoundException
.
Adding an intermediate wire in the parent module (CycleTest
) does indeed cause the PathNotFoundException
to go away, and we get the expected CombLoopException
. Not that we'd want to require users to do that, it just further illustrates the cause of the bug: there needs to be a direct connection from a module's output-to-input port to fool the expandInstancePaths
method into thinking that this is an internal path in that module.
Your environment
- Chisel Version: 3.5.4
- FIRRTL Version: 1.5.4
- OS: macOS 12.5.1
External Information
N/A
Activity