Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Scala3] Redux: Convert cloneType to an extension method #4467

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
override def _cloneType: Data = AsyncReset()
override def _cloneType: AsyncReset = AsyncReset()

? perhaps? Why is this one different than the others


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()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why isn't this one 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(...).
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If this is an internal API, can we make it private to chisel?

*
* 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
Loading