Checklist
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 LogicNodes 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
Checklist
What is the current behavior?
If you try to emit Verilog for the
CycleTestmodule in the following design, theCheckCombLoopstransform will throw aPathNotFoundException:What is the expected behavior?
The
CheckCombLoopstransform should emit aCombLoopException.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:
It looks like the
m.in := m.outconnection in theCycleTestmodule is the source of the problem. It creates two connectedLogicNodes which have the sameinst(min this case). Since they have the sameinst, theifstatement on line 184 ofexpandInstancePathsmatches, and on line 187 we try to find the path fromouttoininside thePassthroughmodule, but no such path exists (only the reverse of that path exists). Thus, line 187 throws thePathNotFoundException.Adding an intermediate wire in the parent module (
CycleTest) does indeed cause thePathNotFoundExceptionto go away, and we get the expectedCombLoopException. 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 theexpandInstancePathsmethod into thinking that this is an internal path in that module.Your environment
External Information
N/A