-
Notifications
You must be signed in to change notification settings - Fork 647
Description
Type of issue: Feature Request
Is your feature request related to a problem? Please describe.
ChiselEnum allows us to manually specify values for enum members, but the width of such user-supplied values is discarded. This is undesirable if we wish to explicitly set the ChiselEnum's width to a fixed value, and this scenario is common. For example, a device's config register may be 32-bit long, yet only several values are defined with others being reserved. It would be nice if we can write code like:
object ConfRegValue extends ChiselEnum {
val Mode1 = Value(0.U(32.W))
val Mode2 = Value(1.U(32.W))
val Mode3 = Value(2.U(32.W))
val Mode4 = Value(3.U(32.W))
}
val input = Wire(UInt(32.W))
val (mode, valid) = ConfRegValue.safe(input)Currently, this code throws an exception at elaboration:
[60] Exception in thread "main" chisel3.package$ChiselException: The UInt being cast to ConfRegValue is wider than ConfRegValue's width (2)
[60] at ... ()
[60] at Top.$anonfun$x$1$1(Top.scala:19)
[60] at chisel3.internal.plugin.package$.autoNameRecursivelyProduct(package.scala:48)
[60] at Top.<init>(Top.scala:19)
[60] at Elaborate$.$anonfun$new$1(Elaborate.scala:9)
[60] at chisel3.Module$.evaluate(Module.scala:94)
[60] at chisel3.Module$.do_apply(Module.scala:37)
[60] at chisel3.stage.phases.Elaborate.$anonfun$transform$2(Elaborate.scala:53)
[60] at chisel3.internal.Builder$.$anonfun$buildImpl$1(Builder.scala:1071)
[60] at scala.util.DynamicVariable.withValue(DynamicVariable.scala:59)
[60] at chisel3.internal.Builder$.buildImpl(Builder.scala:1061)
[60] at chisel3.internal.Builder$.$anonfun$build$1(Builder.scala:1053)
[60] at logger.Logger$.$anonfun$makeScope$4(Logger.scala:148)
[60] at scala.util.DynamicVariable.withValue(DynamicVariable.scala:59)
[60] at logger.Logger$.makeScope(Logger.scala:146)
[60] at logger.Logger$.makeScope(Logger.scala:133)
[60] at ... ()
[60] at ... (Stack trace trimmed to user code only. Rerun with --full-stacktrace to see the full stack trace)
From the code excerpt below, we can see that currently do_Value only considers the input's litValue, then infer the width using its bitLength.
chisel/core/src/main/scala/chisel3/ChiselEnum.scala
Lines 247 to 248 in c4ca27e
| width = (1.max(id.bitLength)).W | |
| id += 1 |
chisel/core/src/main/scala/chisel3/ChiselEnum.scala
Lines 263 to 264 in c4ca27e
| this.id = id.litValue | |
| do_Value(name) |
Describe the solution you'd like
ChiselEnum's underlying width should respect user-defined values if they exist. A max operation may be performed if the provided widths are jagged.
Describe alternatives you've considered
- Overriding
getWidth. This passes the width check, but the generated value relies on private propertywidth, which is not overridable and still wrong.
Additional context
N/A.
What is the use case for implementing this feature?
See the first section for a use case.