Skip to content

Commit

Permalink
Convert cloneType to an extension method
Browse files Browse the repository at this point in the history
This removes much of the use of this.type in Chisel which is necessary
to upgrade to Scala 3.
  • Loading branch information
jackkoenig authored and adkian-sifive committed Oct 15, 2024
1 parent 6435c69 commit 8c02f39
Show file tree
Hide file tree
Showing 12 changed files with 65 additions and 64 deletions.
6 changes: 2 additions & 4 deletions core/src/main/scala-2/chisel3/Bits.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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
*
Expand All @@ -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 */
Expand Down
18 changes: 9 additions & 9 deletions core/src/main/scala/chisel3/AggregateImpl.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
}
Expand Down Expand Up @@ -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
Expand Down
20 changes: 9 additions & 11 deletions core/src/main/scala/chisel3/BitsImpl.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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

Expand Down Expand Up @@ -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

Expand Down Expand Up @@ -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]] */
Expand Down
5 changes: 3 additions & 2 deletions core/src/main/scala/chisel3/ChiselEnumImpl.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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")
Expand Down Expand Up @@ -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

Expand Down
2 changes: 1 addition & 1 deletion core/src/main/scala/chisel3/ClockImpl.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
55 changes: 34 additions & 21 deletions core/src/main/scala/chisel3/DataImpl.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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.
*
Expand Down Expand Up @@ -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]]
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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()"

Expand Down
2 changes: 1 addition & 1 deletion core/src/main/scala/chisel3/ModuleImpl.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down
2 changes: 1 addition & 1 deletion core/src/main/scala/chisel3/experimental/Analog.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
3 changes: 2 additions & 1 deletion core/src/main/scala/chisel3/experimental/package.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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]
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion core/src/main/scala/chisel3/internal/package.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
2 changes: 1 addition & 1 deletion core/src/main/scala/chisel3/probe/ProbeValueBase.scala
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,6 @@ private[chisel3] trait ProbeValueBase {
} else { source.ref }
clone.setRef(ProbeExpr(ref))
}
clone
clone.asInstanceOf[T]
}
}
12 changes: 1 addition & 11 deletions core/src/main/scala/chisel3/properties/Property.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down

0 comments on commit 8c02f39

Please sign in to comment.