From 8c02f39034d5cfe7298bf5e488f15423e4ca3f06 Mon Sep 17 00:00:00 2001 From: Jack Koenig Date: Sat, 27 Jan 2024 13:21:29 -0800 Subject: [PATCH] Convert cloneType to an extension method This removes much of the use of this.type in Chisel which is necessary to upgrade to Scala 3. --- core/src/main/scala-2/chisel3/Bits.scala | 6 +- .../main/scala/chisel3/AggregateImpl.scala | 18 +++--- core/src/main/scala/chisel3/BitsImpl.scala | 20 +++---- .../main/scala/chisel3/ChiselEnumImpl.scala | 5 +- core/src/main/scala/chisel3/ClockImpl.scala | 2 +- core/src/main/scala/chisel3/DataImpl.scala | 55 ++++++++++++------- core/src/main/scala/chisel3/ModuleImpl.scala | 2 +- .../scala/chisel3/experimental/Analog.scala | 2 +- .../scala/chisel3/experimental/package.scala | 3 +- .../main/scala/chisel3/internal/package.scala | 2 +- .../scala/chisel3/probe/ProbeValueBase.scala | 2 +- .../scala/chisel3/properties/Property.scala | 12 +--- 12 files changed, 65 insertions(+), 64 deletions(-) diff --git a/core/src/main/scala-2/chisel3/Bits.scala b/core/src/main/scala-2/chisel3/Bits.scala index 28254f82e5c..370a3c9d703 100644 --- a/core/src/main/scala-2/chisel3/Bits.scala +++ b/core/src/main/scala-2/chisel3/Bits.scala @@ -160,10 +160,10 @@ sealed abstract class Bits(private[chisel3] val width: Width) extends BitsImpl w * @note For [[SInt]]s only, this will do sign extension. * @group Bitwise */ - final def pad(that: Int): this.type = macro SourceInfoTransform.thatArg + final def pad(that: Int): Bits = macro SourceInfoWhiteboxTransform.thatArg /** @group SourceInfoTransformMacro */ - def do_pad(that: Int)(implicit sourceInfo: SourceInfo): this.type = _padImpl(that) + def do_pad(that: Int)(implicit sourceInfo: SourceInfo): Bits = _padImpl(that) /** Bitwise inversion operator * @@ -182,8 +182,6 @@ sealed abstract class Bits(private[chisel3] val width: Width) extends BitsImpl w * $sumWidthInt * @group Bitwise */ - // REVIEW TODO: redundant - // REVIEW TODO: should these return this.type or Bits? final def <<(that: BigInt): Bits = macro SourceInfoWhiteboxTransform.thatArg /** @group SourceInfoTransformMacro */ diff --git a/core/src/main/scala/chisel3/AggregateImpl.scala b/core/src/main/scala/chisel3/AggregateImpl.scala index 035e07450df..e58a714bc5c 100644 --- a/core/src/main/scala/chisel3/AggregateImpl.scala +++ b/core/src/main/scala/chisel3/AggregateImpl.scala @@ -421,9 +421,7 @@ private[chisel3] abstract class VecImpl[T <: Data] private[chisel3] (gen: => T, */ def apply(idx: Int): T = self(idx) - override def cloneType: this.type = { - new Vec(gen.cloneTypeFull, length).asInstanceOf[this.type] - } + override def _cloneType: Vec[T] = new Vec(gen.cloneTypeFull, length) override def getElements: Seq[Data] = self @@ -491,7 +489,7 @@ private[chisel3] abstract class VecImpl[T <: Data] private[chisel3] (gen: => T, elementInitializers: (Int, T)* )( implicit sourceInfo: SourceInfo - ): this.type = { + ): Vec[T] = { def checkLiteralConstruction(): Unit = { val dupKeys = elementInitializers.map { x => x._1 }.groupBy(x => x).flatMap { @@ -543,7 +541,7 @@ private[chisel3] abstract class VecImpl[T <: Data] private[chisel3] (gen: => T, requireIsChiselType(this, "vec literal constructor model") checkLiteralConstruction() - val clone = cloneType + val clone = this.cloneType val cloneFields = getRecursiveFields(clone, "(vec root)").toMap // Create the Vec literal binding from litArgs of arguments @@ -832,8 +830,10 @@ private[chisel3] trait RecordImpl extends AggregateImpl { thiz: Record => } } - override def cloneType: this.type = { - val clone = _cloneTypeImpl.asInstanceOf[this.type] + // Note that _cloneTypeImpl is implemented by the compiler plugin and must be a different method name because + // We want to run checkClone after calling _cloneTypeImpl + final override def _cloneType: Data = { + val clone = _cloneTypeImpl checkClone(clone) clone } @@ -953,10 +953,10 @@ private[chisel3] trait RecordImpl extends AggregateImpl { thiz: Record => * ) * }}} */ - private[chisel3] def _makeLit(elems: (this.type => (Data, Data))*)(implicit sourceInfo: SourceInfo): this.type = { + private[chisel3] def _makeLit(elems: (Data => (Data, Data))*)(implicit sourceInfo: SourceInfo): Data = { requireIsChiselType(this, "bundle literal constructor model") - val clone = cloneType + val clone = this.cloneType val cloneFields = getRecursiveFields(clone, "_").toMap // Create the Bundle literal binding from litargs of arguments diff --git a/core/src/main/scala/chisel3/BitsImpl.scala b/core/src/main/scala/chisel3/BitsImpl.scala index 1aee6a0ff0c..b4d32ed7784 100644 --- a/core/src/main/scala/chisel3/BitsImpl.scala +++ b/core/src/main/scala/chisel3/BitsImpl.scala @@ -21,9 +21,9 @@ private[chisel3] trait BitsImpl extends Element { self: Bits => // Arguments against: generates down to a FIRRTL UInt anyways // Only used for in a few cases, hopefully to be removed - private[chisel3] def cloneTypeWidth(width: Width): this.type + private[chisel3] def cloneTypeWidth(width: Width): Bits - def cloneType: this.type = cloneTypeWidth(width) + override def _cloneType: Data = cloneTypeWidth(width) /** A non-ambiguous name of this `Bits` instance for use in generated Verilog names * Inserts the width directly after the typeName, e.g. UInt4, SInt1 @@ -167,7 +167,7 @@ private[chisel3] trait BitsImpl extends Element { self: Bits => // Pad literal to that width protected def _padLit(that: Int): this.type - protected def _padImpl(that: Int)(implicit sourceInfo: SourceInfo): this.type = this.width match { + protected def _padImpl(that: Int)(implicit sourceInfo: SourceInfo): Bits = this.width match { case KnownWidth(w) if w >= that => this case _ if this.isLit => this._padLit(that) case _ => binop(sourceInfo, cloneTypeWidth(this.width.max(Width(that))), PadOp, that) @@ -222,8 +222,7 @@ private[chisel3] trait UIntImpl extends BitsImpl with Num[UInt] { self: UInt => } } - private[chisel3] override def cloneTypeWidth(w: Width): this.type = - new UInt(w).asInstanceOf[this.type] + private[chisel3] override def cloneTypeWidth(w: Width): UInt = new UInt(w) override protected def _padLit(that: Int): this.type = { val value = this.litValue @@ -403,8 +402,7 @@ private[chisel3] trait SIntImpl extends BitsImpl with Num[SInt] { self: SInt => } } - private[chisel3] override def cloneTypeWidth(w: Width): this.type = - new SInt(w).asInstanceOf[this.type] + private[chisel3] override def cloneTypeWidth(w: Width): SInt = new SInt(w) override protected def _padLit(that: Int): this.type = { val value = this.litValue @@ -529,7 +527,7 @@ private[chisel3] trait ResetTypeImpl extends Element { self: Reset => override def toString: String = stringAccessor("Reset") - def cloneType: this.type = Reset().asInstanceOf[this.type] + override def _cloneType: Data = Reset() override def litOption = None @@ -558,7 +556,7 @@ private[chisel3] trait AsyncResetImpl extends Element { self: AsyncReset => override def toString: String = stringAccessor("AsyncReset") - def cloneType: this.type = AsyncReset().asInstanceOf[this.type] + override def _cloneType: Data = AsyncReset() override def litOption = None @@ -599,9 +597,9 @@ private[chisel3] trait BoolImpl extends UIntImpl { self: Bool => } } - private[chisel3] override def cloneTypeWidth(w: Width): this.type = { + private[chisel3] override def cloneTypeWidth(w: Width): Bool = { require(!w.known || w.get == 1) - new Bool().asInstanceOf[this.type] + new Bool() } /** Convert to a [[scala.Option]] of [[scala.Boolean]] */ diff --git a/core/src/main/scala/chisel3/ChiselEnumImpl.scala b/core/src/main/scala/chisel3/ChiselEnumImpl.scala index f0cfd7534dc..505dadb017e 100644 --- a/core/src/main/scala/chisel3/ChiselEnumImpl.scala +++ b/core/src/main/scala/chisel3/ChiselEnumImpl.scala @@ -30,7 +30,7 @@ private[chisel3] abstract class EnumTypeImpl(private[chisel3] val factory: Chise } } - override def cloneType: this.type = factory().asInstanceOf[this.type] + override def _cloneType: Data = factory() private[chisel3] def compop(sourceInfo: SourceInfo, op: PrimOp, other: EnumType): Bool = { requireIsHardware(this, "bits operated on") @@ -355,7 +355,8 @@ private[chisel3] trait ChiselEnumImpl { self: ChiselEnum => // This is an enum type that can be connected directly to UInts. It is used as a "glue" to cast non-literal UInts // to enums. private[chisel3] class UnsafeEnum(override val width: Width) extends EnumType(UnsafeEnum, selfAnnotating = false) { - override def cloneType: this.type = new UnsafeEnum(width).asInstanceOf[this.type] + + override def _cloneType: Data = new UnsafeEnum(width) } private object UnsafeEnum extends ChiselEnum diff --git a/core/src/main/scala/chisel3/ClockImpl.scala b/core/src/main/scala/chisel3/ClockImpl.scala index cf4e26b8d0e..70f2dfc0b05 100644 --- a/core/src/main/scala/chisel3/ClockImpl.scala +++ b/core/src/main/scala/chisel3/ClockImpl.scala @@ -13,7 +13,7 @@ private[chisel3] trait ClockImpl extends Element { override def toString: String = stringAccessor("Clock") - def cloneType: this.type = Clock().asInstanceOf[this.type] + override def _cloneType: Data = Clock() override def connect(that: Data)(implicit sourceInfo: SourceInfo): Unit = that match { diff --git a/core/src/main/scala/chisel3/DataImpl.scala b/core/src/main/scala/chisel3/DataImpl.scala index 7332c442c81..7f6631e6957 100644 --- a/core/src/main/scala/chisel3/DataImpl.scala +++ b/core/src/main/scala/chisel3/DataImpl.scala @@ -768,28 +768,12 @@ private[chisel3] trait DataImpl extends HasId with NamedComponent { self: Data = private[chisel3] def width: Width private[chisel3] def firrtlConnect(that: Data)(implicit sourceInfo: SourceInfo): Unit - /** Internal API; Chisel users should look at chisel3.chiselTypeOf(...). + /** Private implementation of cloneType * - * cloneType must be defined for any Chisel object extending Data. - * It is responsible for constructing a basic copy of the object being cloned. - * - * @return a copy of the object. - */ - def cloneType: this.type - - /** Internal API; Chisel users should look at chisel3.chiselTypeOf(...). - * - * Returns a copy of this data type, with hardware bindings (if any) removed. - * Directionality data and probe information is still preserved. + * _cloneType must be defined for any Chisel object extending Data. + * It is implemented by Chisel itself or by the compiler plugin for user-defined types. */ - private[chisel3] def cloneTypeFull: this.type = { - val clone = this.cloneType // get a fresh object, without bindings - // Only the top-level direction needs to be fixed up, cloneType should do the rest - clone.specifiedDirection = specifiedDirection - probe.setProbeModifier(clone, probeInfo) - clone.isConst = isConst - clone - } + def _cloneType: Data /** The "strong connect" operator. * @@ -981,6 +965,7 @@ private[chisel3] trait ObjectDataImpl { * * @param lhs The [[Data]] hardware on the left-hand side of the equality */ + // TODO fold this into DataExtensions implicit class DataEquality[T <: Data](lhs: T)(implicit sourceInfo: SourceInfo) { /** Dynamic recursive equality operator for generic [[Data]] @@ -1059,6 +1044,33 @@ private[chisel3] trait ObjectDataImpl { } } } + + implicit class DataExtensions[T <: Data](self: T) { + + /** Internal API; Chisel users should look at chisel3.chiselTypeOf(...). + * + * cloneType must be defined for any Chisel object extending Data. + * It is responsible for constructing a basic copy of the object being cloned. + * + * @return a copy of the object. + */ + def cloneType: T = self._cloneType.asInstanceOf[T] + + /** Internal API; Chisel users should look at chisel3.chiselTypeOf(...). + * + * Returns a copy of this data type, with hardware bindings (if any) removed. + * Directionality data and probe information is still preserved. + */ + private[chisel3] def cloneTypeFull: T = { + val clone = self.cloneType // get a fresh object, without bindings + // Only the top-level direction needs to be fixed up, cloneType should do the rest + clone.specifiedDirection = self.specifiedDirection + // TODO do we need to exclude probe and const from cloneTypeFull on Properties? + probe.setProbeModifier(clone, self.probeInfo) + clone.isConst = self.isConst + clone.asInstanceOf[T] + } + } } trait WireFactory { @@ -1230,7 +1242,8 @@ final case object DontCare extends Element with connectable.ConnectableDocs { private[chisel3] override val width: Width = UnknownWidth bind(DontCareBinding(), SpecifiedDirection.Output) - override def cloneType: this.type = DontCare + + override def _cloneType: Data = DontCare override def toString: String = "DontCare()" diff --git a/core/src/main/scala/chisel3/ModuleImpl.scala b/core/src/main/scala/chisel3/ModuleImpl.scala index 9a4bbc22355..762f36ee2b1 100644 --- a/core/src/main/scala/chisel3/ModuleImpl.scala +++ b/core/src/main/scala/chisel3/ModuleImpl.scala @@ -352,7 +352,7 @@ package internal { private[chisel3] class ClonePorts(elts: (String, Data)*) extends Record { val elements = ListMap(elts.map { case (name, d) => name -> d.cloneTypeFull }: _*) def apply(field: String) = elements(field) - override def cloneType = (new ClonePorts(elts: _*)).asInstanceOf[this.type] + override protected def _cloneTypeImpl: Record = (new ClonePorts(elts: _*)) } private[chisel3] def cloneIORecord( diff --git a/core/src/main/scala/chisel3/experimental/Analog.scala b/core/src/main/scala/chisel3/experimental/Analog.scala index c0136abe0ca..5988ac8ccdc 100644 --- a/core/src/main/scala/chisel3/experimental/Analog.scala +++ b/core/src/main/scala/chisel3/experimental/Analog.scala @@ -34,7 +34,7 @@ final class Analog private (private[chisel3] val width: Width) extends Element { override def litOption: Option[BigInt] = None - def cloneType: this.type = new Analog(width).asInstanceOf[this.type] + override def _cloneType: Data = new Analog(width) // Used to enforce single bulk connect of Analog types, multi-attach is still okay // Note that this really means 1 bulk connect per Module because a port can diff --git a/core/src/main/scala/chisel3/experimental/package.scala b/core/src/main/scala/chisel3/experimental/package.scala index b8e47563ba2..5ddeb479c57 100644 --- a/core/src/main/scala/chisel3/experimental/package.scala +++ b/core/src/main/scala/chisel3/experimental/package.scala @@ -132,7 +132,8 @@ package object experimental { object BundleLiterals { implicit class AddBundleLiteralConstructor[T <: Record](x: T) { def Lit(elems: (T => (Data, Data))*)(implicit sourceInfo: SourceInfo): T = { - x._makeLit(elems: _*) + val fs = elems.map(_.asInstanceOf[Data => (Data, Data)]) + x._makeLit(fs: _*).asInstanceOf[T] } } } diff --git a/core/src/main/scala/chisel3/internal/package.scala b/core/src/main/scala/chisel3/internal/package.scala index b3f41f39557..60afb59e223 100644 --- a/core/src/main/scala/chisel3/internal/package.scala +++ b/core/src/main/scala/chisel3/internal/package.scala @@ -82,7 +82,7 @@ package object internal { val _pad = Wire(UInt(width.W)) _pad := b _pad.asInstanceOf[A] // This cast is safe because we know A is UInt on this path - case u => u.pad(width) + case u => u.pad(width).asInstanceOf[A] } // Resize that to this width (if known) diff --git a/core/src/main/scala/chisel3/probe/ProbeValueBase.scala b/core/src/main/scala/chisel3/probe/ProbeValueBase.scala index f4193cfe122..46d4d36c5c7 100644 --- a/core/src/main/scala/chisel3/probe/ProbeValueBase.scala +++ b/core/src/main/scala/chisel3/probe/ProbeValueBase.scala @@ -28,6 +28,6 @@ private[chisel3] trait ProbeValueBase { } else { source.ref } clone.setRef(ProbeExpr(ref)) } - clone + clone.asInstanceOf[T] } } diff --git a/core/src/main/scala/chisel3/properties/Property.scala b/core/src/main/scala/chisel3/properties/Property.scala index 3542a84da23..07703214c82 100644 --- a/core/src/main/scala/chisel3/properties/Property.scala +++ b/core/src/main/scala/chisel3/properties/Property.scala @@ -278,18 +278,8 @@ sealed trait Property[T] extends Element { self => /** Clone type by simply constructing a new Property[T]. */ - override def cloneType: this.type = new Property[T] { + override def _cloneType: Data = new Property[T] { val tpe = self.tpe - }.asInstanceOf[this.type] - - /** Clone type with extra information preserved. - * - * The only extra information present on a Property type is directionality. - */ - private[chisel3] override def cloneTypeFull: this.type = { - val clone = this.cloneType - clone.specifiedDirection = specifiedDirection - clone } /** Get the IR PropertyType for this Property.