-
Notifications
You must be signed in to change notification settings - Fork 2
Description
The asymmetry of how Reg, RegNext, and RegInit set their widths can lead to unexpected behavior.
h/t @antonblanchard
Type of issue: bug report | feature request | other enhancement
Impact: API modification
Development Phase: request
Other information
There's an old PR referencing and documenting some of this behavior: chipsalliance/chisel#455
If the current behavior is a bug, please provide the steps to reproduce the problem:
Consider the following example. While foo, bar, and baz have almost identical construction, foo has an unset width, bar was a width of 8, and baz is a bundle with an internal signal of width 8.
package examples
import chisel3._
import chisel3.stage.{ChiselStage, ChiselGeneratorAnnotation}
import chisel3.internal.sourceinfo.UnlocatableSourceInfo
object NoInfo {
implicit val noInfo = UnlocatableSourceInfo
}
import NoInfo._
class DelayedBundle extends Bundle {
val in = UInt(8.W)
}
class Delayed extends MultiIOModule {
val in = IO(Input(UInt(8.W)))
val bundle = IO(Input(new DelayedBundle))
/** The width of foo is unset */
val foo = RegNext(in)
/** The width of bar is set to 8.W */
val bar = Reg(chiselTypeOf(in))
bar := in
/** The width of baz is set to 8.W */
val baz = RegNext(bundle)
Seq(foo, bar, baz).foreach(a => println(a.widthOption))
}
object Delayed extends App {
(new ChiselStage).execute(Array.empty, Seq(ChiselGeneratorAnnotation(() => new Delayed)))
}This results in the following FIRRTL:
circuit Delayed :
module Delayed :
input clock : Clock
input reset : UInt<1>
input in : UInt<8>
input bundle : {in : UInt<8>}
reg foo : UInt, clock
foo <= in
reg bar : UInt<8>, clock
bar <= in
reg baz : {in : UInt<8>}, clock
baz.in <= bundle.in
To be very concrete, I have implicit classes for doing automatic conversion to bits, words, etc. (i.e., (Bits) => Vec[UInt]). These rely on having widths known. Using these methods on foo will cause the implicit class methods to error out complaining that they can't be used on something that has an unknown width. However, they work with bar. This is unintuitive behavior as it would seem that foo and bar are identical constructions.
I do realize that RegNext(0.U) is probably the reason why this exists the way it does.
What is the current behavior?
The width of a RegNext is always unset when given a subtype of Bits.
What is the expected behavior?
The width of a RegNext should be set to the type of whatever is next.
Please tell us about your environment:
What is the use case for changing the behavior?
This clarifies unintuitive behavior and unifies behavior for RegNext when given different types.