diff --git a/core/src/main/scala/chisel3/Aggregate.scala b/core/src/main/scala/chisel3/Aggregate.scala index 7947b732d69..ccf627eb9e7 100644 --- a/core/src/main/scala/chisel3/Aggregate.scala +++ b/core/src/main/scala/chisel3/Aggregate.scala @@ -514,7 +514,7 @@ sealed class Vec[T <: Data] private[chisel3] (gen: => T, val length: Int) extend if (m < n) Some(index -> lit) else None case (KnownWidth(_), _) => None - case (UnknownWidth(), _) => + case (UnknownWidth, _) => None case _ => Some(index -> lit) @@ -1226,7 +1226,7 @@ abstract class Record extends Aggregate { case (field, value) => field.width match { // If width is unknown, then it is set by the literal value. - case UnknownWidth() => field -> value + case UnknownWidth => field -> value case width @ KnownWidth(widthValue) => val valuex = if (widthValue < value.width.get) { // For legacy reasons, 0.U is 1-bit, don't warn when it comes up as a literal value for 0-bit Bundle lit field. diff --git a/core/src/main/scala/chisel3/Bits.scala b/core/src/main/scala/chisel3/Bits.scala index 56b15fb9d75..0dbce845894 100644 --- a/core/src/main/scala/chisel3/Bits.scala +++ b/core/src/main/scala/chisel3/Bits.scala @@ -80,7 +80,7 @@ sealed abstract class Bits(private[chisel3] val width: Width) extends Element wi case KnownWidth(x) => require(x >= n, s"Can't tail($n) for width $x < $n") Width(x - n) - case UnknownWidth() => Width() + case UnknownWidth => Width() } binop(sourceInfo, UInt(width = w), TailOp, n) } @@ -88,8 +88,8 @@ sealed abstract class Bits(private[chisel3] val width: Width) extends Element wi /** @group SourceInfoTransformMacro */ def do_head(n: Int)(implicit sourceInfo: SourceInfo): UInt = { width match { - case KnownWidth(x) => require(x >= n, s"Can't head($n) for width $x < $n") - case UnknownWidth() => + case KnownWidth(x) => require(x >= n, s"Can't head($n) for width $x < $n") + case UnknownWidth => () } binop(sourceInfo, UInt(Width(n)), HeadOp, n) } @@ -695,7 +695,7 @@ sealed class UInt private[chisel3] (width: Width) extends Bits(width) with Num[U resultWidth match { // To emulate old FIRRTL behavior where minimum width is 1, we need to insert pad(_, 1) whenever // the width is or could be 0. Thus we check if it is known to be 0 or is unknown. - case w @ (KnownWidth(0) | UnknownWidth()) => + case w @ (KnownWidth(0) | UnknownWidth) => // Because we are inserting an extra op but we want stable emission (so the user can diff the output), // we need to seed a name to avoid name collisions. op.autoSeed("_shrLegacyWidthFixup") diff --git a/core/src/main/scala/chisel3/ChiselEnum.scala b/core/src/main/scala/chisel3/ChiselEnum.scala index bd357aa8f81..12b4cb3bf36 100644 --- a/core/src/main/scala/chisel3/ChiselEnum.scala +++ b/core/src/main/scala/chisel3/ChiselEnum.scala @@ -275,7 +275,7 @@ abstract class ChiselEnum { val result = new Type // We have to use UnknownWidth here, because we don't actually know what the final width will be - result.bindToLiteral(id, UnknownWidth()) + result.bindToLiteral(id, UnknownWidth) enumRecords.append(EnumRecord(result, name)) diff --git a/core/src/main/scala/chisel3/Data.scala b/core/src/main/scala/chisel3/Data.scala index 218f3d994fd..39815f5916a 100644 --- a/core/src/main/scala/chisel3/Data.scala +++ b/core/src/main/scala/chisel3/Data.scala @@ -1202,7 +1202,7 @@ final case object DontCare extends Element with connectable.ConnectableDocs { // otherwise this "Chisel" object will end up on the UserModule's id list. // We make it private to chisel3 so it has to be accessed through the package object. - private[chisel3] override val width: Width = UnknownWidth() + private[chisel3] override val width: Width = UnknownWidth bind(DontCareBinding(), SpecifiedDirection.Output) override def cloneType: this.type = DontCare diff --git a/core/src/main/scala/chisel3/Width.scala b/core/src/main/scala/chisel3/Width.scala index c0dc5f9dd05..3c1abf5e79e 100644 --- a/core/src/main/scala/chisel3/Width.scala +++ b/core/src/main/scala/chisel3/Width.scala @@ -4,7 +4,7 @@ package chisel3 object Width { def apply(x: Int): Width = KnownWidth(x) - def apply(): Width = UnknownWidth() + def apply(): Width = UnknownWidth } sealed abstract class Width { @@ -28,14 +28,24 @@ sealed abstract class Width { protected def op(that: Width, f: (W, W) => W): Width } -sealed case class UnknownWidth() extends Width { +case object UnknownWidth extends Width { def known: Boolean = false def get: Int = None.get def op(that: Width, f: (W, W) => W): Width = this override def toString: String = "" + + @deprecated("UnknownWidth is now a case object, remove the parentheses", "Chisel 7.0") + def apply(): UnknownWidth.type = this + + @deprecated("UnknownWidth is now a case object, remove the parentheses", "Chisel 7.0") + def unapply(x: UnknownWidth.type): Boolean = true } -sealed case class KnownWidth(value: Int) extends Width { +sealed case class KnownWidth private (value: Int) extends Width { + + @deprecated("Use the companion object appy method (remove the \"new\")", "Chisel 7.0") + def this(value: Int, dummy: Int = 0) = this(value.toInt) + require(value >= 0, s"Widths must be non-negative, got $value") def known: Boolean = true def get: Int = value @@ -45,3 +55,17 @@ sealed case class KnownWidth(value: Int) extends Width { } override def toString: String = s"<${value.toString}>" } +object KnownWidth { + private val maxCached = 1024 + private val cache = new Array[KnownWidth](maxCached + 1) + def apply(value: Int): KnownWidth = { + if (0 <= value && value <= maxCached) { + var w = cache(value) + if (w eq null) { + w = new KnownWidth(value) + cache(value) = w + } + w + } else new KnownWidth(value) + } +} diff --git a/core/src/main/scala/chisel3/internal/firrtl/Converter.scala b/core/src/main/scala/chisel3/internal/firrtl/Converter.scala index de4500cf59a..fc0232aadba 100644 --- a/core/src/main/scala/chisel3/internal/firrtl/Converter.scala +++ b/core/src/main/scala/chisel3/internal/firrtl/Converter.scala @@ -81,7 +81,7 @@ private[chisel3] object Converter { case ModuleCloneIO(mod, name) => if (mod eq ctx.id) clonedModuleIOError(mod, name, info) else fir.Reference(name) - case u @ ULit(n, UnknownWidth()) => + case u @ ULit(n, UnknownWidth) => fir.UIntLiteral(n, fir.IntWidth(u.minWidth)) case ULit(n, w) => fir.UIntLiteral(n, convert(w)) @@ -343,7 +343,7 @@ private[chisel3] object Converter { } def convert(width: Width): fir.Width = width match { - case UnknownWidth() => fir.UnknownWidth + case UnknownWidth => fir.UnknownWidth case KnownWidth(value) => fir.IntWidth(value) } diff --git a/core/src/main/scala/chisel3/internal/firrtl/package.scala b/core/src/main/scala/chisel3/internal/firrtl/package.scala index a9f2bc6eae1..567850ed9cc 100644 --- a/core/src/main/scala/chisel3/internal/firrtl/package.scala +++ b/core/src/main/scala/chisel3/internal/firrtl/package.scala @@ -9,7 +9,7 @@ package object firrtl { val Width = chisel3.Width @deprecated("This type has moved to package chisel3", "Chisel 6.0") - type UnknownWidth = chisel3.UnknownWidth + type UnknownWidth = chisel3.UnknownWidth.type @deprecated("This type has moved to package chisel3", "Chisel 6.0") val UnknownWidth = chisel3.UnknownWidth diff --git a/core/src/main/scala/chisel3/properties/Property.scala b/core/src/main/scala/chisel3/properties/Property.scala index 9a3ed98667a..2e3391b3f78 100644 --- a/core/src/main/scala/chisel3/properties/Property.scala +++ b/core/src/main/scala/chisel3/properties/Property.scala @@ -261,7 +261,7 @@ sealed trait Property[T] extends Element { self => def toPrintable: Printable = { throwException(s"Properties do not support hardware printing" + this._errorContext) } - private[chisel3] def width: Width = UnknownWidth() + private[chisel3] def width: Width = UnknownWidth override def typeName: String = s"Property[${tpe.getPropertyType().serialize}]" diff --git a/panamaconverter/src/PanamaCIRCTConverter.scala b/panamaconverter/src/PanamaCIRCTConverter.scala index 017d0e65b5c..31b97874386 100644 --- a/panamaconverter/src/PanamaCIRCTConverter.scala +++ b/panamaconverter/src/PanamaCIRCTConverter.scala @@ -489,7 +489,7 @@ class PanamaCIRCTConverter(val circt: PanamaCIRCT, fos: Option[FirtoolOptions], ): Reference.Value = { def referToNewConstant(n: BigInt, w: Width, isSigned: Boolean): Reference.Value = { val (firWidth, valWidth) = w match { - case _: UnknownWidth => + case UnknownWidth => // We need to keep the most significant sign bit for signed literals val bitLen = if (!isSigned) max(n.bitLength, 1) else n.bitLength + 1 (fir.IntWidth(bitLen), bitLen) diff --git a/src/test/scala/chiselTests/ChiselEnum.scala b/src/test/scala/chiselTests/ChiselEnum.scala index 5481ec97944..8d61a9fbd65 100644 --- a/src/test/scala/chiselTests/ChiselEnum.scala +++ b/src/test/scala/chiselTests/ChiselEnum.scala @@ -86,7 +86,7 @@ class SafeCastFromNonLit extends Module { } class CastFromNonLitWidth(w: Option[Int] = None) extends Module { - val width = if (w.isDefined) w.get.W else UnknownWidth() + val width = if (w.isDefined) w.get.W else UnknownWidth val io = IO(new Bundle { val in = Input(UInt(width))