Skip to content

Commit

Permalink
Intern Width
Browse files Browse the repository at this point in the history
* UnknownWidth becomes a case object
* KnownWidths 0-1024 are interned
  • Loading branch information
jackkoenig committed Jul 2, 2024
1 parent d499a88 commit abfb317
Show file tree
Hide file tree
Showing 10 changed files with 41 additions and 17 deletions.
4 changes: 2 additions & 2 deletions core/src/main/scala/chisel3/Aggregate.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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.
Expand Down
8 changes: 4 additions & 4 deletions core/src/main/scala/chisel3/Bits.scala
Original file line number Diff line number Diff line change
Expand Up @@ -80,16 +80,16 @@ 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)
}

/** @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)
}
Expand Down Expand Up @@ -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")
Expand Down
2 changes: 1 addition & 1 deletion core/src/main/scala/chisel3/ChiselEnum.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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))

Expand Down
2 changes: 1 addition & 1 deletion core/src/main/scala/chisel3/Data.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
30 changes: 27 additions & 3 deletions core/src/main/scala/chisel3/Width.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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
Expand All @@ -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)
}
}
4 changes: 2 additions & 2 deletions core/src/main/scala/chisel3/internal/firrtl/Converter.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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))
Expand Down Expand Up @@ -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)
}

Expand Down
2 changes: 1 addition & 1 deletion core/src/main/scala/chisel3/internal/firrtl/package.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
2 changes: 1 addition & 1 deletion core/src/main/scala/chisel3/properties/Property.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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}]"

Expand Down
2 changes: 1 addition & 1 deletion panamaconverter/src/PanamaCIRCTConverter.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
2 changes: 1 addition & 1 deletion src/test/scala/chiselTests/ChiselEnum.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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))
Expand Down

0 comments on commit abfb317

Please sign in to comment.