chisel2-deprecated icon indicating copy to clipboard operation
chisel2-deprecated copied to clipboard

Instantiating logic in an early initializer yields improper behavior

Open sdtwigg opened this issue 10 years ago • 0 comments

class Toy extends {val myEarlyReg = Reg(UInt())} with Module {
  val io = new Bundle {
    val in1    = UInt(width=2).asInput
    val out1    = UInt(width=32).asOutput
  }
  io.out2 := myEarlyReg
  myEarlyReg := io.in1

If Toy is the top-level module then an NPE occurs (and is suppressed!) in nameIt(). Further a GetWidthException finally halts compilation. If a width is supplied to myEarlyReg then the previously suppressed NPE halts compilation. In either case, the error message is extremely unhelpful. If Toy is not the top-level module then the myEarlyReg logic will be dumped into the parent of Toy. In this case; however, Chisel will register a non-fatal (?) illegal cross module reference error.

The reason for this behavior is that myEarlyReg is created before the constructor to Module is called (which marks Toy as being the current Module as part of its instantiation). The error message for the top-level module case should be cleaned up. The error for the submodule case should be fatal.

A better overall solution would be to capture node ownership via implicits. This would generate a compile error when Toy is not an inner class (as the implicit definition in Module would not be available). If Toy as an inner Module class of an outer Module class then myEarlyReg would be registered as belonging to the outer class and an error would still occur. That said, inner class that extend Module this scenario is already fairly dangerous (it is very easy to accidentally access a private outer class member from within the inner class) so designers should be avoiding this. A documentation update on the pitfalls of this case should be added.

sdtwigg avatar Apr 01 '15 11:04 sdtwigg