Skip to content

Commit

Permalink
[Scala3] Scala2 compatibility changes (#4483)
Browse files Browse the repository at this point in the history
  • Loading branch information
adkian-sifive authored Nov 14, 2024
1 parent eb31402 commit bbcc405
Show file tree
Hide file tree
Showing 21 changed files with 236 additions and 152 deletions.
2 changes: 2 additions & 0 deletions core/src/main/scala-2/chisel3/Aggregate.scala
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,8 @@ sealed class Vec[T <: Data] private[chisel3] (gen: => T, length: Int)
): T = _reduceTreeImpl(redOp, layerOp)
}

object Vec extends VecFactory

object VecInit extends VecInitImpl with SourceInfoDoc {

/** Creates a new [[Vec]] composed of elements of the input Seq of [[Data]]
Expand Down
8 changes: 8 additions & 0 deletions core/src/main/scala-2/chisel3/Bits.scala
Original file line number Diff line number Diff line change
Expand Up @@ -282,6 +282,8 @@ sealed abstract class Bits(private[chisel3] val width: Width) extends BitsImpl w
def do_##(that: Bits)(implicit sourceInfo: SourceInfo): UInt = _impl_##(that)
}

object Bits extends UIntFactory

/** A data type for unsigned integers, represented as a binary bitvector. Defines arithmetic operations between other
* integer types.
*
Expand Down Expand Up @@ -553,6 +555,8 @@ sealed class UInt private[chisel3] (width: Width) extends Bits(width) with UIntI
override def do_asSInt(implicit sourceInfo: SourceInfo): SInt = _asSIntImpl
}

object UInt extends UIntFactory

/** A data type for signed integers, represented as a binary bitvector. Defines arithmetic operations between other
* integer types.
*
Expand Down Expand Up @@ -734,6 +738,8 @@ sealed class SInt private[chisel3] (width: Width) extends Bits(width) with SIntI
override def do_asSInt(implicit sourceInfo: SourceInfo): SInt = _asSIntImpl
}

object SInt extends SIntFactory

sealed trait Reset extends ResetImpl with ToBoolable {

/** Casts this $coll to an [[AsyncReset]] */
Expand Down Expand Up @@ -876,3 +882,5 @@ sealed class Bool() extends UInt(1.W) with BoolImpl with Reset {
/** @group SourceInfoTransformMacro */
def do_asAsyncReset(implicit sourceInfo: SourceInfo): AsyncReset = _asAsyncResetImpl
}

object Bool extends BoolFactory
Original file line number Diff line number Diff line change
Expand Up @@ -13,33 +13,11 @@ import scala.language.experimental.macros
*
* See apply methods for use
*/
object printf {
object printf extends PrintfImpl {

/** Named class for [[printf]]s. */
final class Printf private[chisel3] (val pable: Printable) extends VerificationStatement

/** Helper for packing escape characters */
private[chisel3] def format(formatIn: String): String = {
require(formatIn.forall(c => c.toInt > 0 && c.toInt < 128), "format strings must comprise non-null ASCII values")
def escaped(x: Char) = {
require(x.toInt >= 0, s"char ${x} to Int ${x.toInt} must be >= 0")
if (x == '"' || x == '\\') {
s"\\${x}"
} else if (x == '\n') {
"\\n"
} else if (x == '\t') {
"\\t"
} else {
require(
x.toInt >= 32,
s"char ${x} to Int ${x.toInt} must be >= 32"
) // TODO \xNN once FIRRTL issue #59 is resolved
x
}
}
formatIn.map(escaped).mkString("")
}

/** Prints a message in simulation
*
* Prints a message every cycle. If defined within the scope of a [[when]] block, the message
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,9 @@
package chisel3

import chisel3.experimental.{BaseModule, SourceInfo}
import chisel3.internal._
import chisel3.internal.Builder.pushCommand
import chisel3.internal.firrtl.ir._
import chisel3.layer.block

import scala.language.experimental.macros

/** Base class for all verification statements: Assert, Assume, Cover, Stop and Printf. */
abstract class VerificationStatement extends NamedComponent {
_parent.foreach(_.addId(this))
}

/** Scaladoc information for internal verification statement macros
* that are used in objects assert, assume and cover.
*
Expand All @@ -29,7 +20,7 @@ abstract class VerificationStatement extends NamedComponent {
*/
trait VerifPrintMacrosDoc

object assert extends VerifPrintMacrosDoc {
object assert extends assertImpl with VerifPrintMacrosDoc {

/** Named class for assertions. */
final class Assert private[chisel3] () extends VerificationStatement
Expand Down Expand Up @@ -79,15 +70,9 @@ object assert extends VerifPrintMacrosDoc {

def apply(cond: Bool)(implicit sourceInfo: SourceInfo): Assert =
macro VerifStmtMacrosCompat.assert._applyMacroWithNoMessage

/** An elaboration-time assertion. Calls the built-in Scala assert function. */
def apply(cond: Boolean, message: => String): Unit = Predef.assert(cond, message)

/** An elaboration-time assertion. Calls the built-in Scala assert function. */
def apply(cond: Boolean): Unit = Predef.assert(cond, "")
}

object assume extends VerifPrintMacrosDoc {
object assume extends assumeImpl with VerifPrintMacrosDoc {

/** Named class for assumptions. */
final class Assume private[chisel3] () extends VerificationStatement
Expand Down Expand Up @@ -141,12 +126,6 @@ object assume extends VerifPrintMacrosDoc {

def apply(cond: Bool)(implicit sourceInfo: SourceInfo): Assume =
macro VerifStmtMacrosCompat.assume._applyMacroWithNoMessage

/** An elaboration-time assumption. Calls the built-in Scala assume function. */
def apply(cond: Boolean, message: => String): Unit = Predef.assume(cond, message)

/** An elaboration-time assumption. Calls the built-in Scala assume function. */
def apply(cond: Boolean): Unit = Predef.assume(cond, "")
}

object cover extends VerifPrintMacrosDoc {
Expand All @@ -171,37 +150,3 @@ object cover extends VerifPrintMacrosDoc {
def apply(cond: Bool)(implicit sourceInfo: SourceInfo): Cover =
macro VerifStmtMacrosCompat.cover._applyMacroWithNoMessage
}

object stop {

/** Terminate execution, indicating success and printing a message.
*
* @param message a message describing why simulation was stopped
*/
def apply(message: String)(implicit sourceInfo: SourceInfo): Stop = buildStopCommand(Some(PString(message)))

/** Terminate execution, indicating success and printing a message.
*
* @param message a printable describing why simulation was stopped
*/
def apply(message: Printable)(implicit sourceInfo: SourceInfo): Stop = buildStopCommand(Some(message))

/** Terminate execution, indicating success.
*/
def apply()(implicit sourceInfo: SourceInfo): Stop = buildStopCommand(None)

/** Named class for [[stop]]s. */
final class Stop private[chisel3] () extends VerificationStatement

private def buildStopCommand(message: Option[Printable])(implicit sourceInfo: SourceInfo): Stop = {
val stopId = new Stop()
block(layers.Verification, skipIfAlreadyInBlock = true, skipIfLayersEnabled = true) {
message.foreach(Printable.checkScope(_))
when(!Module.reset.asBool) {
message.foreach(PrintfMacrosCompat.printfWithoutReset(_))
pushCommand(Stop(stopId, sourceInfo, Builder.forcedClock.ref, 0))
}
}
stopId
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import scala.reflect.macros.blackbox.Context
sealed trait ChiselSubtypeOf[A, B]

object ChiselSubtypeOf {
// TODO return an empty tree here instead of a quasiquote for scala3 compatibility
def genChiselSubtypeOf[A: c.WeakTypeTag, B: c.WeakTypeTag](c: Context): c.Tree = {
import c.universe._

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// SPDX-License-Identifier: Apache-2.0

package chisel3.experimental.dataview

import chisel3._
import scala.reflect.runtime.universe.WeakTypeTag

private[chisel3] trait InvertibleDataView {
def swapArgs[A, B, C, D](f: (A, B) => Iterable[(C, D)]): (B, A) => Iterable[(D, C)] = {
case (b, a) => f(a, b).map(_.swap)
}

/** Provides `invert` for invertible [[DataView]]s
*
* This must be done as an extension method because it applies an addition constraint on the `Target`
* type parameter, namely that it must be a subtype of [[Data]].
*
* @note [[PartialDataView]]s are **not** invertible and will result in an elaboration time exception
*/
implicit class InvertibleDataView[T <: Data: WeakTypeTag, V <: Data: WeakTypeTag](view: DataView[T, V]) {
def invert(mkView: V => T): DataView[V, T] = {
// It would've been nice to make this a compiler error, but it's unclear how to make that work.
// We tried having separate TotalDataView and PartialDataView and only defining inversion for
// TotalDataView. For some reason, implicit resolution wouldn't invert TotalDataViews. This is
// probably because it was looking for the super-type DataView and since invertDataView was
// only defined on TotalDataView, it wasn't included in implicit resolution. Thus we end up
// with a runtime check.
if (!view.total) {
val tt = implicitly[WeakTypeTag[T]].tpe
val vv = implicitly[WeakTypeTag[V]].tpe
val msg = s"Cannot invert '$view' as it is non-total.\n Try providing a DataView[$vv, $tt]." +
s"\n Please see https://www.chisel-lang.org/chisel3/docs/explanations/dataview."
throw InvalidViewException(msg)
}
implicit val sourceInfo = view.sourceInfo
new DataView[V, T](mkView, swapArgs(view.mapping), view.total)
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package chisel3.experimental

/** Classes or traits which will be used with the [[Definition]] + [[Instance]] api should be marked
* with the [[instantiable]] annotation at the class/trait definition.
*
* @example {{{
* @instantiable
* class MyModule extends Module {
* ...
* }
*
* val d = Definition(new MyModule)
* val i0 = Instance(d)
* val i1 = Instance(d)
* }}}
*/
class instantiable extends chisel3.internal.instantiable

/** Classes marked with [[instantiable]] can have their vals marked with the [[public]] annotation to
* enable accessing these values from a [[Definition]] or [[Instance]] of the class.
*
* Only vals of the the following types can be marked [[public]]:
* 1. IsInstantiable
* 2. IsLookupable
* 3. Data
* 4. BaseModule
* 5. Iterable/Option containing a type that meets these requirements
* 6. Basic type like String, Int, BigInt etc.
*
* @example {{{
* @instantiable
* class MyModule extends Module {
* @public val in = IO(Input(UInt(3.W)))
* @public val out = IO(Output(UInt(3.W)))
* ..
* }
*
* val d = Definition(new MyModule)
* val i0 = Instance(d)
* val i1 = Instance(d)
*
* i1.in := i0.out
* }}}
*/
class public extends chisel3.internal.public
Original file line number Diff line number Diff line change
Expand Up @@ -54,13 +54,13 @@ object Instantiate extends InstantiateImpl {
f: K => A
)(
implicit sourceInfo: SourceInfo
): Instance[A] = _instanceImpl(args, f)
): Instance[A] = _instanceImpl(args, f, implicitly[ru.WeakTypeTag[A]])

/** This is not part of the public API, do not call directly! */
def _definition[K, A <: BaseModule: ru.WeakTypeTag](
args: K,
f: K => A
): Definition[A] = _definitionImpl(args, f)
): Definition[A] = _definitionImpl(args, f, implicitly[ru.WeakTypeTag[A]])

private object internal {

Expand Down
4 changes: 3 additions & 1 deletion core/src/main/scala-2/chisel3/internal/SourceInfoMacro.scala
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,12 @@ package chisel3.internal.sourceinfo
import scala.language.experimental.macros
import scala.reflect.macros.blackbox.Context

import chisel3.internal.sourceinfo.SourceInfoFileResolver

/** Provides a macro that returns the source information at the invocation point.
*/
@deprecated("Public APIs in chisel3.internal are deprecated", "Chisel 3.6")
object SourceInfoMacro {
private[chisel3] object SourceInfoMacro {
def generate_source_info(c: Context): c.Tree = {
import c.universe._
val p = c.enclosingPosition
Expand Down
4 changes: 2 additions & 2 deletions core/src/main/scala/chisel3/AggregateImpl.scala
Original file line number Diff line number Diff line change
Expand Up @@ -136,10 +136,10 @@ private[chisel3] trait AggregateImpl extends Data { thiz: Aggregate =>
}

override private[chisel3] def _fromUInt(that: UInt)(implicit sourceInfo: SourceInfo): Data = {
val _asUInt = _resizeToWidth(that, this.widthOption)(identity)
val _asUInt = _resizeToWidth(that, this.widthOption, true)(identity)
// If that is a literal and all constituent Elements can be represented as literals, return a literal
val ((_, allLit), rvalues) = {
this.flatten.toList.mapAccumulate((0, _asUInt.isLit)) {
this.flatten.toList.mapAccumulate[(Int, Boolean), Element]((0, _asUInt.isLit)) {
case ((lo, literal), elt) =>
val hi = lo + elt.getWidth
// Chisel only supports zero width extraction if hi = -1 and lo = 0, so do it manually
Expand Down
12 changes: 6 additions & 6 deletions core/src/main/scala/chisel3/BitsImpl.scala
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ private[chisel3] trait BitsImpl extends Element { self: Bits =>
}

protected def _headImpl(n: Int)(implicit sourceInfo: SourceInfo): UInt = {
width match {
this.width match {
case KnownWidth(x) => require(x >= n, s"Can't head($n) for width $x < $n")
case UnknownWidth => ()
}
Expand Down Expand Up @@ -193,9 +193,9 @@ private[chisel3] trait BitsImpl extends Element { self: Bits =>
protected def _asSIntImpl(implicit sourceInfo: SourceInfo): SInt

protected def _asBoolImpl(implicit sourceInfo: SourceInfo): Bool = {
width match {
this.width match {
case KnownWidth(1) => this(0)
case _ => throwException(s"can't covert ${this.getClass.getSimpleName}$width to Bool")
case _ => throwException(s"can't covert ${this.getClass.getSimpleName}${this.width} to Bool")
}
}

Expand Down Expand Up @@ -388,7 +388,7 @@ private[chisel3] trait UIntImpl extends BitsImpl with Num[UInt] { self: UInt =>
override private[chisel3] def _asUIntImpl(first: Boolean)(implicit sourceInfo: SourceInfo): UInt = this

override private[chisel3] def _fromUInt(that: UInt)(implicit sourceInfo: SourceInfo): this.type = {
_resizeToWidth(that, this.widthOption)(identity).asInstanceOf[this.type]
_resizeToWidth(that, this.widthOption, true)(identity).asInstanceOf[this.type]
}

private def subtractAsSInt(that: UInt)(implicit sourceInfo: SourceInfo): SInt =
Expand Down Expand Up @@ -514,7 +514,7 @@ private[chisel3] trait SIntImpl extends BitsImpl with Num[SInt] { self: SInt =>
override def _asSIntImpl(implicit sourceInfo: SourceInfo): SInt = this

override private[chisel3] def _fromUInt(that: UInt)(implicit sourceInfo: SourceInfo): this.type =
_resizeToWidth(that.asSInt, this.widthOption)(_.asSInt).asInstanceOf[this.type]
_resizeToWidth(that.asSInt, this.widthOption, false)(_.asSInt).asInstanceOf[this.type]
}

private[chisel3] trait ResetImpl extends Element { self: Reset =>
Expand Down Expand Up @@ -640,6 +640,6 @@ private[chisel3] trait BoolImpl extends UIntImpl { self: Bool =>
pushOp(DefPrim(sourceInfo, AsyncReset(), AsAsyncResetOp, ref))

override private[chisel3] def _fromUInt(that: UInt)(implicit sourceInfo: SourceInfo): this.type = {
_resizeToWidth(that, this.widthOption)(identity).asBool.asInstanceOf[this.type]
_resizeToWidth(that, this.widthOption, true)(identity).asBool.asInstanceOf[this.type]
}
}
28 changes: 28 additions & 0 deletions core/src/main/scala/chisel3/PrintfImpl.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// SPDX-License-Identifier: Apache-2.0

package chisel3

private[chisel3] trait PrintfImpl {

/** Helper for packing escape characters */
private[chisel3] def format(formatIn: String): String = {
require(formatIn.forall(c => c.toInt > 0 && c.toInt < 128), "format strings must comprise non-null ASCII values")
def escaped(x: Char) = {
require(x.toInt >= 0, s"char ${x} to Int ${x.toInt} must be >= 0")
if (x == '"' || x == '\\') {
s"\\${x}"
} else if (x == '\n') {
"\\n"
} else if (x == '\t') {
"\\t"
} else {
require(
x.toInt >= 32,
s"char ${x} to Int ${x.toInt} must be >= 32"
) // TODO \xNN once FIRRTL issue #59 is resolved
x
}
}
formatIn.map(escaped).mkString("")
}
}
Loading

0 comments on commit bbcc405

Please sign in to comment.