Skip to content

Respect user-specified widths in ChiselEnum #4989

@CSharperMantle

Description

@CSharperMantle

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.

width = (1.max(id.bitLength)).W
id += 1

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 property width, 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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions