diff options
| author | Jack Koenig | 2022-01-10 10:39:52 -0800 |
|---|---|---|
| committer | Jack Koenig | 2022-01-10 15:53:55 -0800 |
| commit | 3131c0daad41dea78bede4517669e376c41a325a (patch) | |
| tree | 55baed78a6a01f80ff3952a08233ca553a19964f /core/src/main/scala/chisel3/experimental | |
| parent | dd36f97a82746cec0b25b94651581fe799e24579 (diff) | |
Apply scalafmt
Command:
sbt scalafmtAll
Diffstat (limited to 'core/src/main/scala/chisel3/experimental')
13 files changed, 913 insertions, 459 deletions
diff --git a/core/src/main/scala/chisel3/experimental/Analog.scala b/core/src/main/scala/chisel3/experimental/Analog.scala index e94bae2d..a366f0c3 100644 --- a/core/src/main/scala/chisel3/experimental/Analog.scala +++ b/core/src/main/scala/chisel3/experimental/Analog.scala @@ -5,7 +5,18 @@ package chisel3.experimental import chisel3.internal.firrtl.Width import chisel3.internal.sourceinfo.SourceInfo import chisel3.internal._ -import chisel3.{ActualDirection, Bits, CompileOptions, Data, Element, PString, Printable, RawModule, SpecifiedDirection, UInt} +import chisel3.{ + ActualDirection, + Bits, + CompileOptions, + Data, + Element, + PString, + Printable, + RawModule, + SpecifiedDirection, + UInt +} import scala.collection.mutable @@ -47,7 +58,7 @@ final class Analog private (private[chisel3] val width: Width) extends Element { _parent.foreach(_.addId(this)) SpecifiedDirection.fromParent(parentDirection, specifiedDirection) match { case SpecifiedDirection.Unspecified | SpecifiedDirection.Flip => - case x => throwException(s"Analog may not have explicit direction, got '$x'") + case x => throwException(s"Analog may not have explicit direction, got '$x'") } val targetTopBinding = target match { case target: TopBinding => target @@ -67,8 +78,12 @@ final class Analog private (private[chisel3] val width: Width) extends Element { override def do_asUInt(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): UInt = throwException("Analog does not support asUInt") - private[chisel3] override def connectFromBits(that: Bits)(implicit sourceInfo: SourceInfo, - compileOptions: CompileOptions): Unit = { + private[chisel3] override def connectFromBits( + that: Bits + )( + implicit sourceInfo: SourceInfo, + compileOptions: CompileOptions + ): Unit = { throwException("Analog does not support connectFromBits") } diff --git a/core/src/main/scala/chisel3/experimental/Trace.scala b/core/src/main/scala/chisel3/experimental/Trace.scala index 2d965c7b..4ab615a5 100644 --- a/core/src/main/scala/chisel3/experimental/Trace.scala +++ b/core/src/main/scala/chisel3/experimental/Trace.scala @@ -18,7 +18,7 @@ import firrtl.transforms.DontTouchAllTargets * // get final reference of `a` Seq(ReferenceTarget("Dut", "Dut", Seq.empty, "a", Seq.empty)) * val firrtlReferenceOfDutA = finalTarget(annos)(dut.a) * }}} - * */ + */ object Trace { /** Trace a Instance name. */ @@ -49,8 +49,8 @@ object Trace { * @param chiselTarget original annotated target in Chisel, which should not be changed or renamed in FIRRTL. */ private case class TraceNameAnnotation[T <: CompleteTarget](target: T, chiselTarget: T) - extends SingleTargetAnnotation[T] - with DontTouchAllTargets { + extends SingleTargetAnnotation[T] + with DontTouchAllTargets { def duplicate(n: T): Annotation = this.copy(target = n) } @@ -64,6 +64,6 @@ object Trace { * This API can be used to gather all final reference to the signal or module which is marked by `traceName` */ def finalTargetMap(annos: AnnotationSeq): Map[CompleteTarget, Seq[CompleteTarget]] = annos.collect { - case TraceNameAnnotation(t, chiselTarget) => chiselTarget -> t - }.groupBy(_._1).map{case (k, v) => k -> v.map(_._2)} + case TraceNameAnnotation(t, chiselTarget) => chiselTarget -> t + }.groupBy(_._1).map { case (k, v) => k -> v.map(_._2) } } diff --git a/core/src/main/scala/chisel3/experimental/dataview/DataProduct.scala b/core/src/main/scala/chisel3/experimental/dataview/DataProduct.scala index 438f97b8..c6ebe604 100644 --- a/core/src/main/scala/chisel3/experimental/dataview/DataProduct.scala +++ b/core/src/main/scala/chisel3/experimental/dataview/DataProduct.scala @@ -3,7 +3,7 @@ package chisel3.experimental.dataview import chisel3.experimental.BaseModule -import chisel3.{Data, Vec, getRecursiveFields} +import chisel3.{getRecursiveFields, Data, Vec} import scala.annotation.implicitNotFound @@ -18,9 +18,12 @@ import scala.annotation.implicitNotFound * @tparam A Type that has elements of type [[Data]] * @see [[https://www.chisel-lang.org/chisel3/docs/explanations/dataview#dataproduct Detailed Documentation]] */ -@implicitNotFound("Could not find implicit value for DataProduct[${A}].\n" + - "Please see https://www.chisel-lang.org/chisel3/docs/explanations/dataview#dataproduct") +@implicitNotFound( + "Could not find implicit value for DataProduct[${A}].\n" + + "Please see https://www.chisel-lang.org/chisel3/docs/explanations/dataview#dataproduct" +) trait DataProduct[-A] { + /** Provides [[Data]] elements within some containing object * * @param a Containing object @@ -59,6 +62,7 @@ sealed trait LowPriorityDataProduct { * @note DataProduct implementations provided in this object are available in the implicit scope */ object DataProduct extends LowPriorityDataProduct { + /** [[DataProduct]] implementation for [[BaseModule]] */ implicit val userModuleDataProduct: DataProduct[BaseModule] = new DataProduct[BaseModule] { def dataIterator(a: BaseModule, path: String): Iterator[(Data, String)] = { @@ -78,19 +82,18 @@ object DataProduct extends LowPriorityDataProduct { } /** [[DataProduct]] implementation for any `Seq[A]` where `A` has an implementation of `DataProduct`. */ - implicit def seqDataProduct[A : DataProduct]: DataProduct[Seq[A]] = new DataProduct[Seq[A]] { + implicit def seqDataProduct[A: DataProduct]: DataProduct[Seq[A]] = new DataProduct[Seq[A]] { def dataIterator(a: Seq[A], path: String): Iterator[(Data, String)] = { val dpa = implicitly[DataProduct[A]] - a.iterator - .zipWithIndex - .flatMap { case (elt, idx) => + a.iterator.zipWithIndex.flatMap { + case (elt, idx) => dpa.dataIterator(elt, s"$path[$idx]") - } + } } } /** [[DataProduct]] implementation for any [[Tuple2]] where each field has an implementation of `DataProduct`. */ - implicit def tuple2DataProduct[A : DataProduct, B : DataProduct]: DataProduct[(A, B)] = new DataProduct[(A, B)] { + implicit def tuple2DataProduct[A: DataProduct, B: DataProduct]: DataProduct[(A, B)] = new DataProduct[(A, B)] { def dataIterator(tup: (A, B), path: String): Iterator[(Data, String)] = { val dpa = implicitly[DataProduct[A]] val dpb = implicitly[DataProduct[B]] @@ -100,7 +103,7 @@ object DataProduct extends LowPriorityDataProduct { } /** [[DataProduct]] implementation for any [[Tuple3]] where each field has an implementation of `DataProduct`. */ - implicit def tuple3DataProduct[A : DataProduct, B : DataProduct, C : DataProduct]: DataProduct[(A, B, C)] = + implicit def tuple3DataProduct[A: DataProduct, B: DataProduct, C: DataProduct]: DataProduct[(A, B, C)] = new DataProduct[(A, B, C)] { def dataIterator(tup: (A, B, C), path: String): Iterator[(Data, String)] = { val dpa = implicitly[DataProduct[A]] @@ -112,7 +115,12 @@ object DataProduct extends LowPriorityDataProduct { } /** [[DataProduct]] implementation for any [[Tuple4]] where each field has an implementation of `DataProduct`. */ - implicit def tuple4DataProduct[A : DataProduct, B : DataProduct, C : DataProduct, D : DataProduct]: DataProduct[(A, B, C, D)] = + implicit def tuple4DataProduct[ + A: DataProduct, + B: DataProduct, + C: DataProduct, + D: DataProduct + ]: DataProduct[(A, B, C, D)] = new DataProduct[(A, B, C, D)] { def dataIterator(tup: (A, B, C, D), path: String): Iterator[(Data, String)] = { val dpa = implicitly[DataProduct[A]] @@ -129,11 +137,12 @@ object DataProduct extends LowPriorityDataProduct { /** [[DataProduct]] implementation for any [[Tuple5]] where each field has an implementation of `DataProduct`. */ implicit def tuple5DataProduct[ - A : DataProduct, - B : DataProduct, - C : DataProduct, - D : DataProduct, - E : DataProduct]: DataProduct[(A, B, C, D, E)] = + A: DataProduct, + B: DataProduct, + C: DataProduct, + D: DataProduct, + E: DataProduct + ]: DataProduct[(A, B, C, D, E)] = new DataProduct[(A, B, C, D, E)] { def dataIterator(tup: (A, B, C, D, E), path: String): Iterator[(Data, String)] = { val dpa = implicitly[DataProduct[A]] @@ -152,12 +161,13 @@ object DataProduct extends LowPriorityDataProduct { /** [[DataProduct]] implementation for any [[Tuple6]] where each field has an implementation of `DataProduct`. */ implicit def tuple6DataProduct[ - A : DataProduct, - B : DataProduct, - C : DataProduct, - D : DataProduct, - E : DataProduct, - F : DataProduct]: DataProduct[(A, B, C, D, E, F)] = + A: DataProduct, + B: DataProduct, + C: DataProduct, + D: DataProduct, + E: DataProduct, + F: DataProduct + ]: DataProduct[(A, B, C, D, E, F)] = new DataProduct[(A, B, C, D, E, F)] { def dataIterator(tup: (A, B, C, D, E, F), path: String): Iterator[(Data, String)] = { val dpa = implicitly[DataProduct[A]] @@ -178,13 +188,14 @@ object DataProduct extends LowPriorityDataProduct { /** [[DataProduct]] implementation for any [[Tuple7]] where each field has an implementation of `DataProduct`. */ implicit def tuple7DataProduct[ - A : DataProduct, - B : DataProduct, - C : DataProduct, - D : DataProduct, - E : DataProduct, - F : DataProduct, - G : DataProduct]: DataProduct[(A, B, C, D, E, F, G)] = + A: DataProduct, + B: DataProduct, + C: DataProduct, + D: DataProduct, + E: DataProduct, + F: DataProduct, + G: DataProduct + ]: DataProduct[(A, B, C, D, E, F, G)] = new DataProduct[(A, B, C, D, E, F, G)] { def dataIterator(tup: (A, B, C, D, E, F, G), path: String): Iterator[(Data, String)] = { val dpa = implicitly[DataProduct[A]] @@ -207,14 +218,15 @@ object DataProduct extends LowPriorityDataProduct { /** [[DataProduct]] implementation for any [[Tuple8]] where each field has an implementation of `DataProduct`. */ implicit def tuple8DataProduct[ - A : DataProduct, - B : DataProduct, - C : DataProduct, - D : DataProduct, - E : DataProduct, - F : DataProduct, - G : DataProduct, - H : DataProduct]: DataProduct[(A, B, C, D, E, F, G, H)] = + A: DataProduct, + B: DataProduct, + C: DataProduct, + D: DataProduct, + E: DataProduct, + F: DataProduct, + G: DataProduct, + H: DataProduct + ]: DataProduct[(A, B, C, D, E, F, G, H)] = new DataProduct[(A, B, C, D, E, F, G, H)] { def dataIterator(tup: (A, B, C, D, E, F, G, H), path: String): Iterator[(Data, String)] = { val dpa = implicitly[DataProduct[A]] @@ -239,15 +251,16 @@ object DataProduct extends LowPriorityDataProduct { /** [[DataProduct]] implementation for any [[Tuple9]] where each field has an implementation of `DataProduct`. */ implicit def tuple9DataProduct[ - A : DataProduct, - B : DataProduct, - C : DataProduct, - D : DataProduct, - E : DataProduct, - F : DataProduct, - G : DataProduct, - H : DataProduct, - I : DataProduct]: DataProduct[(A, B, C, D, E, F, G, H, I)] = + A: DataProduct, + B: DataProduct, + C: DataProduct, + D: DataProduct, + E: DataProduct, + F: DataProduct, + G: DataProduct, + H: DataProduct, + I: DataProduct + ]: DataProduct[(A, B, C, D, E, F, G, H, I)] = new DataProduct[(A, B, C, D, E, F, G, H, I)] { def dataIterator(tup: (A, B, C, D, E, F, G, H, I), path: String): Iterator[(Data, String)] = { val dpa = implicitly[DataProduct[A]] @@ -274,16 +287,17 @@ object DataProduct extends LowPriorityDataProduct { /** [[DataProduct]] implementation for any [[Tuple9]] where each field has an implementation of `DataProduct`. */ implicit def tuple10DataProduct[ - A : DataProduct, - B : DataProduct, - C : DataProduct, - D : DataProduct, - E : DataProduct, - F : DataProduct, - G : DataProduct, - H : DataProduct, - I : DataProduct, - J : DataProduct]: DataProduct[(A, B, C, D, E, F, G, H, I, J)] = + A: DataProduct, + B: DataProduct, + C: DataProduct, + D: DataProduct, + E: DataProduct, + F: DataProduct, + G: DataProduct, + H: DataProduct, + I: DataProduct, + J: DataProduct + ]: DataProduct[(A, B, C, D, E, F, G, H, I, J)] = new DataProduct[(A, B, C, D, E, F, G, H, I, J)] { def dataIterator(tup: (A, B, C, D, E, F, G, H, I, J), path: String): Iterator[(Data, String)] = { val dpa = implicitly[DataProduct[A]] diff --git a/core/src/main/scala/chisel3/experimental/dataview/DataView.scala b/core/src/main/scala/chisel3/experimental/dataview/DataView.scala index c17a5574..7f20964d 100644 --- a/core/src/main/scala/chisel3/experimental/dataview/DataView.scala +++ b/core/src/main/scala/chisel3/experimental/dataview/DataView.scala @@ -11,7 +11,6 @@ import chisel3.ExplicitCompileOptions.Strict import scala.reflect.runtime.universe.WeakTypeTag import annotation.implicitNotFound - /** Mapping between a target type `T` and a view type `V` * * Enables calling `.viewAs[T]` on instances of the target type. @@ -41,9 +40,11 @@ import annotation.implicitNotFound * @see [[DataView$ object DataView]] for factory methods * @see [[PartialDataView object PartialDataView]] for defining non-total `DataViews` */ -@implicitNotFound("Could not find implicit value for DataView[${T}, ${V}].\n" + - "Please see https://www.chisel-lang.org/chisel3/docs/explanations/dataview") -sealed class DataView[T : DataProduct, V <: Data] private[chisel3] ( +@implicitNotFound( + "Could not find implicit value for DataView[${T}, ${V}].\n" + + "Please see https://www.chisel-lang.org/chisel3/docs/explanations/dataview" +) +sealed class DataView[T: DataProduct, V <: Data] private[chisel3] ( /** Function constructing an object of the View type from an object of the Target type */ private[chisel3] val mkView: T => V, /** Function that returns corresponding fields of the target and view */ @@ -51,8 +52,8 @@ sealed class DataView[T : DataProduct, V <: Data] private[chisel3] ( // Aliasing this with a def below to make the ScalaDoc show up for the field _total: Boolean )( - implicit private[chisel3] val sourceInfo: SourceInfo -) { + implicit private[chisel3] val sourceInfo: SourceInfo) { + /** Indicates if the mapping contains every field of the target */ def total: Boolean = _total @@ -89,15 +90,30 @@ sealed class DataView[T : DataProduct, V <: Data] private[chisel3] ( object DataView { /** Default factory method, alias for [[pairs]] */ - def apply[T : DataProduct, V <: Data](mkView: T => V, pairs: ((T, V) => (Data, Data))*)(implicit sourceInfo: SourceInfo): DataView[T, V] = + def apply[T: DataProduct, V <: Data]( + mkView: T => V, + pairs: ((T, V) => (Data, Data))* + )( + implicit sourceInfo: SourceInfo + ): DataView[T, V] = DataView.pairs(mkView, pairs: _*) /** Construct [[DataView]]s with pairs of functions from the target and view to corresponding fields */ - def pairs[T : DataProduct, V <: Data](mkView: T => V, pairs: ((T, V) => (Data, Data))*)(implicit sourceInfo: SourceInfo): DataView[T, V] = + def pairs[T: DataProduct, V <: Data]( + mkView: T => V, + pairs: ((T, V) => (Data, Data))* + )( + implicit sourceInfo: SourceInfo + ): DataView[T, V] = mapping(mkView: T => V, swizzle(pairs)) /** More general factory method for complex mappings */ - def mapping[T : DataProduct, V <: Data](mkView: T => V, mapping: (T, V) => Iterable[(Data, Data)])(implicit sourceInfo: SourceInfo): DataView[T, V] = + def mapping[T: DataProduct, V <: Data]( + mkView: T => V, + mapping: (T, V) => Iterable[(Data, Data)] + )( + implicit sourceInfo: SourceInfo + ): DataView[T, V] = new DataView[T, V](mkView, mapping, _total = true) /** Provides `invert` for invertible [[DataView]]s @@ -107,7 +123,7 @@ object DataView { * * @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]) { + 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 @@ -143,7 +159,10 @@ object DataView { DataView[A, A](chiselTypeOf.apply, { case (x, y) => (x, y) }) /** Provides `DataView[Seq[A], Vec[B]]` for all `A` such that there exists `DataView[A, B]` */ - implicit def seqDataView[A : DataProduct, B <: Data](implicit dv: DataView[A, B], sourceInfo: SourceInfo): DataView[Seq[A], Vec[B]] = { + implicit def seqDataView[A: DataProduct, B <: Data]( + implicit dv: DataView[A, B], + sourceInfo: SourceInfo + ): DataView[Seq[A], Vec[B]] = { // TODO this would need a better way to determine the prototype for the Vec DataView.mapping[Seq[A], Vec[B]]( xs => Vec(xs.size, chiselTypeClone(xs.head.viewAs[B]))(sourceInfo, Strict), // xs.head is not correct in general @@ -151,223 +170,395 @@ object DataView { ) } - /** Provides implementations of [[DataView]] for [[Tuple2]] to [[HWTuple2]] */ - implicit def tuple2DataView[T1 : DataProduct, T2 : DataProduct, V1 <: Data, V2 <: Data]( - implicit v1: DataView[T1, V1], v2: DataView[T2, V2], sourceInfo: SourceInfo + /** Provides implementations of [[DataView]] for [[Tuple2]] to [[HWTuple2]] */ + implicit def tuple2DataView[T1: DataProduct, T2: DataProduct, V1 <: Data, V2 <: Data]( + implicit v1: DataView[T1, V1], + v2: DataView[T2, V2], + sourceInfo: SourceInfo ): DataView[(T1, T2), HWTuple2[V1, V2]] = DataView.mapping( - { case (a, b) => new HWTuple2(a.viewAs[V1].cloneType, b.viewAs[V2].cloneType)}, - { case ((a, b), hwt) => - Seq(a.viewAs[V1] -> hwt._1, - b.viewAs[V2] -> hwt._2) + { case (a, b) => new HWTuple2(a.viewAs[V1].cloneType, b.viewAs[V2].cloneType) }, + { + case ((a, b), hwt) => + Seq(a.viewAs[V1] -> hwt._1, b.viewAs[V2] -> hwt._2) } ) - /** Provides implementations of [[DataView]] for [[Tuple3]] to [[HWTuple3]] */ - implicit def tuple3DataView[ - T1 : DataProduct, T2 : DataProduct, T3 : DataProduct, - V1 <: Data, V2 <: Data, V3 <: Data - ]( - implicit v1: DataView[T1, V1], v2: DataView[T2, V2], v3: DataView[T3, V3], sourceInfo: SourceInfo + /** Provides implementations of [[DataView]] for [[Tuple3]] to [[HWTuple3]] */ + implicit def tuple3DataView[T1: DataProduct, T2: DataProduct, T3: DataProduct, V1 <: Data, V2 <: Data, V3 <: Data]( + implicit v1: DataView[T1, V1], + v2: DataView[T2, V2], + v3: DataView[T3, V3], + sourceInfo: SourceInfo ): DataView[(T1, T2, T3), HWTuple3[V1, V2, V3]] = DataView.mapping( - { case (a, b, c) => new HWTuple3(a.viewAs[V1].cloneType, b.viewAs[V2].cloneType, c.viewAs[V3].cloneType)}, - { case ((a, b, c), hwt) => - Seq(a.viewAs[V1] -> hwt._1, - b.viewAs[V2] -> hwt._2, - c.viewAs[V3] -> hwt._3) + { case (a, b, c) => new HWTuple3(a.viewAs[V1].cloneType, b.viewAs[V2].cloneType, c.viewAs[V3].cloneType) }, + { + case ((a, b, c), hwt) => + Seq(a.viewAs[V1] -> hwt._1, b.viewAs[V2] -> hwt._2, c.viewAs[V3] -> hwt._3) } ) - /** Provides implementations of [[DataView]] for [[Tuple4]] to [[HWTuple4]] */ + /** Provides implementations of [[DataView]] for [[Tuple4]] to [[HWTuple4]] */ implicit def tuple4DataView[ - T1 : DataProduct, T2 : DataProduct, T3 : DataProduct, T4 : DataProduct, - V1 <: Data, V2 <: Data, V3 <: Data, V4 <: Data + T1: DataProduct, + T2: DataProduct, + T3: DataProduct, + T4: DataProduct, + V1 <: Data, + V2 <: Data, + V3 <: Data, + V4 <: Data ]( - implicit v1: DataView[T1, V1], v2: DataView[T2, V2], v3: DataView[T3, V3], v4: DataView[T4, V4], sourceInfo: SourceInfo + implicit v1: DataView[T1, V1], + v2: DataView[T2, V2], + v3: DataView[T3, V3], + v4: DataView[T4, V4], + sourceInfo: SourceInfo ): DataView[(T1, T2, T3, T4), HWTuple4[V1, V2, V3, V4]] = DataView.mapping( - { case (a, b, c, d) => - new HWTuple4(a.viewAs[V1].cloneType, b.viewAs[V2].cloneType, c.viewAs[V3].cloneType, d.viewAs[V4].cloneType - )}, - { case ((a, b, c, d), hwt) => - Seq(a.viewAs[V1] -> hwt._1, - b.viewAs[V2] -> hwt._2, - c.viewAs[V3] -> hwt._3, - d.viewAs[V4] -> hwt._4) + { + case (a, b, c, d) => + new HWTuple4(a.viewAs[V1].cloneType, b.viewAs[V2].cloneType, c.viewAs[V3].cloneType, d.viewAs[V4].cloneType) + }, + { + case ((a, b, c, d), hwt) => + Seq(a.viewAs[V1] -> hwt._1, b.viewAs[V2] -> hwt._2, c.viewAs[V3] -> hwt._3, d.viewAs[V4] -> hwt._4) } ) - /** Provides implementations of [[DataView]] for [[Tuple5]] to [[HWTuple5]] */ + /** Provides implementations of [[DataView]] for [[Tuple5]] to [[HWTuple5]] */ implicit def tuple5DataView[ - T1 : DataProduct, T2 : DataProduct, T3 : DataProduct, T4 : DataProduct, T5 : DataProduct, - V1 <: Data, V2 <: Data, V3 <: Data, V4 <: Data, V5 <: Data + T1: DataProduct, + T2: DataProduct, + T3: DataProduct, + T4: DataProduct, + T5: DataProduct, + V1 <: Data, + V2 <: Data, + V3 <: Data, + V4 <: Data, + V5 <: Data ]( - implicit v1: DataView[T1, V1], v2: DataView[T2, V2], v3: DataView[T3, V3], v4: DataView[T4, V4], v5: DataView[T5, V5], sourceInfo: SourceInfo + implicit v1: DataView[T1, V1], + v2: DataView[T2, V2], + v3: DataView[T3, V3], + v4: DataView[T4, V4], + v5: DataView[T5, V5], + sourceInfo: SourceInfo ): DataView[(T1, T2, T3, T4, T5), HWTuple5[V1, V2, V3, V4, V5]] = { DataView.mapping( - { case tup: Tuple5[T1, T2, T3, T4, T5] => - val (a, b, c, d, e) = tup - new HWTuple5(a.viewAs[V1].cloneType, b.viewAs[V2].cloneType, c.viewAs[V3].cloneType, d.viewAs[V4].cloneType, - e.viewAs[V5].cloneType - ) + { + case tup: Tuple5[T1, T2, T3, T4, T5] => + val (a, b, c, d, e) = tup + new HWTuple5( + a.viewAs[V1].cloneType, + b.viewAs[V2].cloneType, + c.viewAs[V3].cloneType, + d.viewAs[V4].cloneType, + e.viewAs[V5].cloneType + ) }, - { case ((a, b, c, d, e), hwt) => - Seq(a.viewAs[V1] -> hwt._1, - b.viewAs[V2] -> hwt._2, - c.viewAs[V3] -> hwt._3, - d.viewAs[V4] -> hwt._4, - e.viewAs[V5] -> hwt._5) + { + case ((a, b, c, d, e), hwt) => + Seq( + a.viewAs[V1] -> hwt._1, + b.viewAs[V2] -> hwt._2, + c.viewAs[V3] -> hwt._3, + d.viewAs[V4] -> hwt._4, + e.viewAs[V5] -> hwt._5 + ) } ) } - /** Provides implementations of [[DataView]] for [[Tuple6]] to [[HWTuple6]] */ + /** Provides implementations of [[DataView]] for [[Tuple6]] to [[HWTuple6]] */ implicit def tuple6DataView[ - T1 : DataProduct, T2 : DataProduct, T3 : DataProduct, T4 : DataProduct, T5 : DataProduct, - T6 : DataProduct, - V1 <: Data, V2 <: Data, V3 <: Data, V4 <: Data, V5 <: Data, + T1: DataProduct, + T2: DataProduct, + T3: DataProduct, + T4: DataProduct, + T5: DataProduct, + T6: DataProduct, + V1 <: Data, + V2 <: Data, + V3 <: Data, + V4 <: Data, + V5 <: Data, V6 <: Data ]( - implicit v1: DataView[T1, V1], v2: DataView[T2, V2], v3: DataView[T3, V3], v4: DataView[T4, V4], - v5: DataView[T5, V5], v6: DataView[T6, V6], - sourceInfo: SourceInfo + implicit v1: DataView[T1, V1], + v2: DataView[T2, V2], + v3: DataView[T3, V3], + v4: DataView[T4, V4], + v5: DataView[T5, V5], + v6: DataView[T6, V6], + sourceInfo: SourceInfo ): DataView[(T1, T2, T3, T4, T5, T6), HWTuple6[V1, V2, V3, V4, V5, V6]] = DataView.mapping( - { case (a, b, c, d, e, f) => - new HWTuple6(a.viewAs[V1].cloneType, b.viewAs[V2].cloneType, c.viewAs[V3].cloneType, d.viewAs[V4].cloneType, - e.viewAs[V5].cloneType, f.viewAs[V6].cloneType - ) + { + case (a, b, c, d, e, f) => + new HWTuple6( + a.viewAs[V1].cloneType, + b.viewAs[V2].cloneType, + c.viewAs[V3].cloneType, + d.viewAs[V4].cloneType, + e.viewAs[V5].cloneType, + f.viewAs[V6].cloneType + ) }, - { case ((a, b, c, d, e, f), hwt) => - Seq(a.viewAs[V1] -> hwt._1, - b.viewAs[V2] -> hwt._2, - c.viewAs[V3] -> hwt._3, - d.viewAs[V4] -> hwt._4, - e.viewAs[V5] -> hwt._5, - f.viewAs[V6] -> hwt._6) + { + case ((a, b, c, d, e, f), hwt) => + Seq( + a.viewAs[V1] -> hwt._1, + b.viewAs[V2] -> hwt._2, + c.viewAs[V3] -> hwt._3, + d.viewAs[V4] -> hwt._4, + e.viewAs[V5] -> hwt._5, + f.viewAs[V6] -> hwt._6 + ) } ) - /** Provides implementations of [[DataView]] for [[Tuple7]] to [[HWTuple7]] */ + /** Provides implementations of [[DataView]] for [[Tuple7]] to [[HWTuple7]] */ implicit def tuple7DataView[ - T1 : DataProduct, T2 : DataProduct, T3 : DataProduct, T4 : DataProduct, T5 : DataProduct, - T6 : DataProduct, T7 : DataProduct, - V1 <: Data, V2 <: Data, V3 <: Data, V4 <: Data, V5 <: Data, - V6 <: Data, V7 <: Data + T1: DataProduct, + T2: DataProduct, + T3: DataProduct, + T4: DataProduct, + T5: DataProduct, + T6: DataProduct, + T7: DataProduct, + V1 <: Data, + V2 <: Data, + V3 <: Data, + V4 <: Data, + V5 <: Data, + V6 <: Data, + V7 <: Data ]( - implicit v1: DataView[T1, V1], v2: DataView[T2, V2], v3: DataView[T3, V3], v4: DataView[T4, V4], - v5: DataView[T5, V5], v6: DataView[T6, V6], v7: DataView[T7, V7], - sourceInfo: SourceInfo + implicit v1: DataView[T1, V1], + v2: DataView[T2, V2], + v3: DataView[T3, V3], + v4: DataView[T4, V4], + v5: DataView[T5, V5], + v6: DataView[T6, V6], + v7: DataView[T7, V7], + sourceInfo: SourceInfo ): DataView[(T1, T2, T3, T4, T5, T6, T7), HWTuple7[V1, V2, V3, V4, V5, V6, V7]] = DataView.mapping( - { case (a, b, c, d, e, f, g) => - new HWTuple7(a.viewAs[V1].cloneType, b.viewAs[V2].cloneType, c.viewAs[V3].cloneType, d.viewAs[V4].cloneType, - e.viewAs[V5].cloneType, f.viewAs[V6].cloneType, g.viewAs[V7].cloneType - ) + { + case (a, b, c, d, e, f, g) => + new HWTuple7( + a.viewAs[V1].cloneType, + b.viewAs[V2].cloneType, + c.viewAs[V3].cloneType, + d.viewAs[V4].cloneType, + e.viewAs[V5].cloneType, + f.viewAs[V6].cloneType, + g.viewAs[V7].cloneType + ) }, - { case ((a, b, c, d, e, f, g), hwt) => - Seq(a.viewAs[V1] -> hwt._1, - b.viewAs[V2] -> hwt._2, - c.viewAs[V3] -> hwt._3, - d.viewAs[V4] -> hwt._4, - e.viewAs[V5] -> hwt._5, - f.viewAs[V6] -> hwt._6, - g.viewAs[V7] -> hwt._7) + { + case ((a, b, c, d, e, f, g), hwt) => + Seq( + a.viewAs[V1] -> hwt._1, + b.viewAs[V2] -> hwt._2, + c.viewAs[V3] -> hwt._3, + d.viewAs[V4] -> hwt._4, + e.viewAs[V5] -> hwt._5, + f.viewAs[V6] -> hwt._6, + g.viewAs[V7] -> hwt._7 + ) } ) - /** Provides implementations of [[DataView]] for [[Tuple8]] to [[HWTuple8]] */ + /** Provides implementations of [[DataView]] for [[Tuple8]] to [[HWTuple8]] */ implicit def tuple8DataView[ - T1 : DataProduct, T2 : DataProduct, T3 : DataProduct, T4 : DataProduct, T5 : DataProduct, - T6 : DataProduct, T7 : DataProduct, T8 : DataProduct, - V1 <: Data, V2 <: Data, V3 <: Data, V4 <: Data, V5 <: Data, - V6 <: Data, V7 <: Data, V8 <: Data + T1: DataProduct, + T2: DataProduct, + T3: DataProduct, + T4: DataProduct, + T5: DataProduct, + T6: DataProduct, + T7: DataProduct, + T8: DataProduct, + V1 <: Data, + V2 <: Data, + V3 <: Data, + V4 <: Data, + V5 <: Data, + V6 <: Data, + V7 <: Data, + V8 <: Data ]( - implicit v1: DataView[T1, V1], v2: DataView[T2, V2], v3: DataView[T3, V3], v4: DataView[T4, V4], - v5: DataView[T5, V5], v6: DataView[T6, V6], v7: DataView[T7, V7], v8: DataView[T8, V8], - sourceInfo: SourceInfo + implicit v1: DataView[T1, V1], + v2: DataView[T2, V2], + v3: DataView[T3, V3], + v4: DataView[T4, V4], + v5: DataView[T5, V5], + v6: DataView[T6, V6], + v7: DataView[T7, V7], + v8: DataView[T8, V8], + sourceInfo: SourceInfo ): DataView[(T1, T2, T3, T4, T5, T6, T7, T8), HWTuple8[V1, V2, V3, V4, V5, V6, V7, V8]] = DataView.mapping( - { case (a, b, c, d, e, f, g, h) => - new HWTuple8(a.viewAs[V1].cloneType, b.viewAs[V2].cloneType, c.viewAs[V3].cloneType, d.viewAs[V4].cloneType, - e.viewAs[V5].cloneType, f.viewAs[V6].cloneType, g.viewAs[V7].cloneType, h.viewAs[V8].cloneType - ) + { + case (a, b, c, d, e, f, g, h) => + new HWTuple8( + a.viewAs[V1].cloneType, + b.viewAs[V2].cloneType, + c.viewAs[V3].cloneType, + d.viewAs[V4].cloneType, + e.viewAs[V5].cloneType, + f.viewAs[V6].cloneType, + g.viewAs[V7].cloneType, + h.viewAs[V8].cloneType + ) }, - { case ((a, b, c, d, e, f, g, h), hwt) => - Seq(a.viewAs[V1] -> hwt._1, - b.viewAs[V2] -> hwt._2, - c.viewAs[V3] -> hwt._3, - d.viewAs[V4] -> hwt._4, - e.viewAs[V5] -> hwt._5, - f.viewAs[V6] -> hwt._6, - g.viewAs[V7] -> hwt._7, - h.viewAs[V8] -> hwt._8) + { + case ((a, b, c, d, e, f, g, h), hwt) => + Seq( + a.viewAs[V1] -> hwt._1, + b.viewAs[V2] -> hwt._2, + c.viewAs[V3] -> hwt._3, + d.viewAs[V4] -> hwt._4, + e.viewAs[V5] -> hwt._5, + f.viewAs[V6] -> hwt._6, + g.viewAs[V7] -> hwt._7, + h.viewAs[V8] -> hwt._8 + ) } ) - /** Provides implementations of [[DataView]] for [[Tuple9]] to [[HWTuple9]] */ + /** Provides implementations of [[DataView]] for [[Tuple9]] to [[HWTuple9]] */ implicit def tuple9DataView[ - T1 : DataProduct, T2 : DataProduct, T3 : DataProduct, T4 : DataProduct, T5 : DataProduct, - T6 : DataProduct, T7 : DataProduct, T8 : DataProduct, T9 : DataProduct, - V1 <: Data, V2 <: Data, V3 <: Data, V4 <: Data, V5 <: Data, - V6 <: Data, V7 <: Data, V8 <: Data, V9 <: Data + T1: DataProduct, + T2: DataProduct, + T3: DataProduct, + T4: DataProduct, + T5: DataProduct, + T6: DataProduct, + T7: DataProduct, + T8: DataProduct, + T9: DataProduct, + V1 <: Data, + V2 <: Data, + V3 <: Data, + V4 <: Data, + V5 <: Data, + V6 <: Data, + V7 <: Data, + V8 <: Data, + V9 <: Data ]( - implicit v1: DataView[T1, V1], v2: DataView[T2, V2], v3: DataView[T3, V3], v4: DataView[T4, V4], - v5: DataView[T5, V5], v6: DataView[T6, V6], v7: DataView[T7, V7], v8: DataView[T8, V8], - v9: DataView[T9, V9], - sourceInfo: SourceInfo + implicit v1: DataView[T1, V1], + v2: DataView[T2, V2], + v3: DataView[T3, V3], + v4: DataView[T4, V4], + v5: DataView[T5, V5], + v6: DataView[T6, V6], + v7: DataView[T7, V7], + v8: DataView[T8, V8], + v9: DataView[T9, V9], + sourceInfo: SourceInfo ): DataView[(T1, T2, T3, T4, T5, T6, T7, T8, T9), HWTuple9[V1, V2, V3, V4, V5, V6, V7, V8, V9]] = DataView.mapping( - { case (a, b, c, d, e, f, g, h, i) => - new HWTuple9(a.viewAs[V1].cloneType, b.viewAs[V2].cloneType, c.viewAs[V3].cloneType, d.viewAs[V4].cloneType, - e.viewAs[V5].cloneType, f.viewAs[V6].cloneType, g.viewAs[V7].cloneType, h.viewAs[V8].cloneType, - i.viewAs[V9].cloneType - ) + { + case (a, b, c, d, e, f, g, h, i) => + new HWTuple9( + a.viewAs[V1].cloneType, + b.viewAs[V2].cloneType, + c.viewAs[V3].cloneType, + d.viewAs[V4].cloneType, + e.viewAs[V5].cloneType, + f.viewAs[V6].cloneType, + g.viewAs[V7].cloneType, + h.viewAs[V8].cloneType, + i.viewAs[V9].cloneType + ) }, - { case ((a, b, c, d, e, f, g, h, i), hwt) => - Seq(a.viewAs[V1] -> hwt._1, - b.viewAs[V2] -> hwt._2, - c.viewAs[V3] -> hwt._3, - d.viewAs[V4] -> hwt._4, - e.viewAs[V5] -> hwt._5, - f.viewAs[V6] -> hwt._6, - g.viewAs[V7] -> hwt._7, - h.viewAs[V8] -> hwt._8, - i.viewAs[V9] -> hwt._9) + { + case ((a, b, c, d, e, f, g, h, i), hwt) => + Seq( + a.viewAs[V1] -> hwt._1, + b.viewAs[V2] -> hwt._2, + c.viewAs[V3] -> hwt._3, + d.viewAs[V4] -> hwt._4, + e.viewAs[V5] -> hwt._5, + f.viewAs[V6] -> hwt._6, + g.viewAs[V7] -> hwt._7, + h.viewAs[V8] -> hwt._8, + i.viewAs[V9] -> hwt._9 + ) } ) - /** Provides implementations of [[DataView]] for [[Tuple10]] to [[HWTuple10]] */ + /** Provides implementations of [[DataView]] for [[Tuple10]] to [[HWTuple10]] */ implicit def tuple10DataView[ - T1 : DataProduct, T2 : DataProduct, T3 : DataProduct, T4 : DataProduct, T5 : DataProduct, - T6 : DataProduct, T7 : DataProduct, T8 : DataProduct, T9 : DataProduct, T10 : DataProduct, - V1 <: Data, V2 <: Data, V3 <: Data, V4 <: Data, V5 <: Data, - V6 <: Data, V7 <: Data, V8 <: Data, V9 <: Data, V10 <: Data + T1: DataProduct, + T2: DataProduct, + T3: DataProduct, + T4: DataProduct, + T5: DataProduct, + T6: DataProduct, + T7: DataProduct, + T8: DataProduct, + T9: DataProduct, + T10: DataProduct, + V1 <: Data, + V2 <: Data, + V3 <: Data, + V4 <: Data, + V5 <: Data, + V6 <: Data, + V7 <: Data, + V8 <: Data, + V9 <: Data, + V10 <: Data ]( - implicit v1: DataView[T1, V1], v2: DataView[T2, V2], v3: DataView[T3, V3], v4: DataView[T4, V4], - v5: DataView[T5, V5], v6: DataView[T6, V6], v7: DataView[T7, V7], v8: DataView[T8, V8], - v9: DataView[T9, V9], v10: DataView[T10, V10], - sourceInfo: SourceInfo + implicit v1: DataView[T1, V1], + v2: DataView[T2, V2], + v3: DataView[T3, V3], + v4: DataView[T4, V4], + v5: DataView[T5, V5], + v6: DataView[T6, V6], + v7: DataView[T7, V7], + v8: DataView[T8, V8], + v9: DataView[T9, V9], + v10: DataView[T10, V10], + sourceInfo: SourceInfo ): DataView[(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10), HWTuple10[V1, V2, V3, V4, V5, V6, V7, V8, V9, V10]] = DataView.mapping( - { case (a, b, c, d, e, f, g, h, i, j) => - new HWTuple10(a.viewAs[V1].cloneType, b.viewAs[V2].cloneType, c.viewAs[V3].cloneType, d.viewAs[V4].cloneType, - e.viewAs[V5].cloneType, f.viewAs[V6].cloneType, g.viewAs[V7].cloneType, h.viewAs[V8].cloneType, - i.viewAs[V9].cloneType, j.viewAs[V10].cloneType - ) + { + case (a, b, c, d, e, f, g, h, i, j) => + new HWTuple10( + a.viewAs[V1].cloneType, + b.viewAs[V2].cloneType, + c.viewAs[V3].cloneType, + d.viewAs[V4].cloneType, + e.viewAs[V5].cloneType, + f.viewAs[V6].cloneType, + g.viewAs[V7].cloneType, + h.viewAs[V8].cloneType, + i.viewAs[V9].cloneType, + j.viewAs[V10].cloneType + ) }, - { case ((a, b, c, d, e, f, g, h, i, j), hwt) => - Seq(a.viewAs[V1] -> hwt._1, - b.viewAs[V2] -> hwt._2, - c.viewAs[V3] -> hwt._3, - d.viewAs[V4] -> hwt._4, - e.viewAs[V5] -> hwt._5, - f.viewAs[V6] -> hwt._6, - g.viewAs[V7] -> hwt._7, - h.viewAs[V8] -> hwt._8, - i.viewAs[V9] -> hwt._9, - j.viewAs[V10] -> hwt._10) + { + case ((a, b, c, d, e, f, g, h, i, j), hwt) => + Seq( + a.viewAs[V1] -> hwt._1, + b.viewAs[V2] -> hwt._2, + c.viewAs[V3] -> hwt._3, + d.viewAs[V4] -> hwt._4, + e.viewAs[V5] -> hwt._5, + f.viewAs[V6] -> hwt._6, + g.viewAs[V7] -> hwt._7, + h.viewAs[V8] -> hwt._8, + i.viewAs[V9] -> hwt._9, + j.viewAs[V10] -> hwt._10 + ) } ) } @@ -376,14 +567,29 @@ object DataView { object PartialDataView { /** Default factory method, alias for [[pairs]] */ - def apply[T: DataProduct, V <: Data](mkView: T => V, pairs: ((T, V) => (Data, Data))*)(implicit sourceInfo: SourceInfo): DataView[T, V] = + def apply[T: DataProduct, V <: Data]( + mkView: T => V, + pairs: ((T, V) => (Data, Data))* + )( + implicit sourceInfo: SourceInfo + ): DataView[T, V] = PartialDataView.pairs(mkView, pairs: _*) /** Construct [[DataView]]s with pairs of functions from the target and view to corresponding fields */ - def pairs[T: DataProduct, V <: Data](mkView: T => V, pairs: ((T, V) => (Data, Data))*)(implicit sourceInfo: SourceInfo): DataView[T, V] = + def pairs[T: DataProduct, V <: Data]( + mkView: T => V, + pairs: ((T, V) => (Data, Data))* + )( + implicit sourceInfo: SourceInfo + ): DataView[T, V] = mapping(mkView, DataView.swizzle(pairs)) /** More general factory method for complex mappings */ - def mapping[T: DataProduct, V <: Data](mkView: T => V, mapping: (T, V) => Iterable[(Data, Data)])(implicit sourceInfo: SourceInfo): DataView[T, V] = + def mapping[T: DataProduct, V <: Data]( + mkView: T => V, + mapping: (T, V) => Iterable[(Data, Data)] + )( + implicit sourceInfo: SourceInfo + ): DataView[T, V] = new DataView[T, V](mkView, mapping, _total = false) } diff --git a/core/src/main/scala/chisel3/experimental/dataview/package.scala b/core/src/main/scala/chisel3/experimental/dataview/package.scala index 1acf43e1..3278d82c 100644 --- a/core/src/main/scala/chisel3/experimental/dataview/package.scala +++ b/core/src/main/scala/chisel3/experimental/dataview/package.scala @@ -39,27 +39,39 @@ package object dataview { } // This private type alias lets us provide a custom error message for misuing the .viewAs for upcasting Bundles - @implicitNotFound("${A} is not a subtype of ${B}! Did you mean .viewAs[${B}]? " + - "Please see https://www.chisel-lang.org/chisel3/docs/cookbooks/dataview") + @implicitNotFound( + "${A} is not a subtype of ${B}! Did you mean .viewAs[${B}]? " + + "Please see https://www.chisel-lang.org/chisel3/docs/cookbooks/dataview" + ) private type SubTypeOf[A, B] = A <:< B /** Provides `viewAsSupertype` for subclasses of [[Bundle]] */ implicit class BundleUpcastable[T <: Bundle](target: T) { + /** View a [[Bundle]] or [[Record]] as a parent type (upcast) */ def viewAsSupertype[V <: Bundle](proto: V)(implicit ev: SubTypeOf[T, V], sourceInfo: SourceInfo): V = { - implicit val dataView = PartialDataView.mapping[T, V](_ => proto, { - case (a, b) => - val aElts = a.elements - val bElts = b.elements - val bKeys = bElts.keySet - val keys = aElts.keysIterator.filter(bKeys.contains) - keys.map(k => aElts(k) -> bElts(k)).toSeq - }) + implicit val dataView = PartialDataView.mapping[T, V]( + _ => proto, + { + case (a, b) => + val aElts = a.elements + val bElts = b.elements + val bKeys = bElts.keySet + val keys = aElts.keysIterator.filter(bKeys.contains) + keys.map(k => aElts(k) -> bElts(k)).toSeq + } + ) target.viewAs[V] } } - private def nonTotalViewException(dataView: DataView[_, _], target: Any, view: Data, targetFields: Seq[String], viewFields: Seq[String]) = { + private def nonTotalViewException( + dataView: DataView[_, _], + target: Any, + view: Data, + targetFields: Seq[String], + viewFields: Seq[String] + ) = { def missingMsg(name: String, fields: Seq[String]): Option[String] = { val str = fields.mkString(", ") fields.size match { @@ -77,18 +89,17 @@ package object dataview { } // TODO should this be moved to class Aggregate / can it be unified with Aggregate.bind? - private def doBind[T : DataProduct, V <: Data](target: T, view: V, dataView: DataView[T, V]): Unit = { + private def doBind[T: DataProduct, V <: Data](target: T, view: V, dataView: DataView[T, V]): Unit = { val mapping = dataView.mapping(target, view) val total = dataView.total // Lookups to check the mapping results val viewFieldLookup: Map[Data, String] = getRecursiveFields(view, "_").toMap - val targetContains: Data => Boolean = implicitly[DataProduct[T]].dataSet(target) + val targetContains: Data => Boolean = implicitly[DataProduct[T]].dataSet(target) // Resulting bindings for each Element of the View val childBindings = new mutable.HashMap[Data, mutable.ListBuffer[Element]] ++ - viewFieldLookup.view - .collect { case (elt: Element, _) => elt } + viewFieldLookup.view.collect { case (elt: Element, _) => elt } .map(_ -> new mutable.ListBuffer[Element]) def viewFieldName(d: Data): String = @@ -115,7 +126,9 @@ package object dataview { val fieldName = viewFieldName(vex) val vwidth = widthAsString(vex) val twidth = widthAsString(tex) - throw InvalidViewException(s"View field $fieldName has width ${vwidth} that is incompatible with target value $tex's width ${twidth}") + throw InvalidViewException( + s"View field $fieldName has width ${vwidth} that is incompatible with target value $tex's width ${twidth}" + ) } childBindings(vex) += tex } @@ -137,23 +150,24 @@ package object dataview { } // Errors in totality of the View, use var List to keep fast path cheap (no allocation) - var viewNonTotalErrors: List[Data] = Nil + var viewNonTotalErrors: List[Data] = Nil var targetNonTotalErrors: List[String] = Nil val targetSeen: Option[mutable.Set[Data]] = if (total) Some(mutable.Set.empty[Data]) else None - val resultBindings = childBindings.map { case (data, targets) => - val targetsx = targets match { - case collection.Seq(target: Element) => target - case collection.Seq() => - viewNonTotalErrors = data :: viewNonTotalErrors - data.asInstanceOf[Element] // Return the Data itself, will error after this map, cast is safe - case x => - throw InvalidViewException(s"Got $x, expected Seq(_: Direct)") - } - // TODO record and report aliasing errors - targetSeen.foreach(_ += targetsx) - data -> targetsx + val resultBindings = childBindings.map { + case (data, targets) => + val targetsx = targets match { + case collection.Seq(target: Element) => target + case collection.Seq() => + viewNonTotalErrors = data :: viewNonTotalErrors + data.asInstanceOf[Element] // Return the Data itself, will error after this map, cast is safe + case x => + throw InvalidViewException(s"Got $x, expected Seq(_: Direct)") + } + // TODO record and report aliasing errors + targetSeen.foreach(_ += targetsx) + data -> targetsx }.toMap // Check for totality of Target @@ -169,7 +183,7 @@ package object dataview { } view match { - case elt: Element => view.bind(ViewBinding(resultBindings(elt))) + case elt: Element => view.bind(ViewBinding(resultBindings(elt))) case agg: Aggregate => // We record total Data mappings to provide a better .toTarget val topt = target match { @@ -221,31 +235,31 @@ package object dataview { @tailrec private[chisel3] def reify(elt: Element, topBinding: TopBinding): Element = topBinding match { case ViewBinding(target) => reify(target, elt.topBinding) - case _ => elt + case _ => elt } - /** Determine the target of a View if it is a single Target - * - * @note An Aggregate may be a view of unrelated [[Data]] (eg. like a Seq or tuple) and thus this - * there is no single Data representing the Target and this function will return None - * @return The single Data target of this view or None if a single Data doesn't exist - */ - private[chisel3] def reifySingleData(data: Data): Option[Data] = { - val candidate: Option[Data] = - data.binding.collect { // First check if this is a total mapping of an Aggregate - case AggregateViewBinding(_, Some(t)) => t - }.orElse { // Otherwise look via top binding - data.topBindingOpt match { - case None => None - case Some(ViewBinding(target)) => Some(target) - case Some(AggregateViewBinding(lookup, _)) => lookup.get(data) - case Some(_) => None - } + /** Determine the target of a View if it is a single Target + * + * @note An Aggregate may be a view of unrelated [[Data]] (eg. like a Seq or tuple) and thus this + * there is no single Data representing the Target and this function will return None + * @return The single Data target of this view or None if a single Data doesn't exist + */ + private[chisel3] def reifySingleData(data: Data): Option[Data] = { + val candidate: Option[Data] = + data.binding.collect { // First check if this is a total mapping of an Aggregate + case AggregateViewBinding(_, Some(t)) => t + }.orElse { // Otherwise look via top binding + data.topBindingOpt match { + case None => None + case Some(ViewBinding(target)) => Some(target) + case Some(AggregateViewBinding(lookup, _)) => lookup.get(data) + case Some(_) => None } - candidate.flatMap { d => - // Candidate may itself be a view, keep tracing in those cases - if (isView(d)) reifySingleData(d) else Some(d) } + candidate.flatMap { d => + // Candidate may itself be a view, keep tracing in those cases + if (isView(d)) reifySingleData(d) else Some(d) } + } } diff --git a/core/src/main/scala/chisel3/experimental/hierarchy/Definition.scala b/core/src/main/scala/chisel3/experimental/hierarchy/Definition.scala index c7b51072..b498daf0 100644 --- a/core/src/main/scala/chisel3/experimental/hierarchy/Definition.scala +++ b/core/src/main/scala/chisel3/experimental/hierarchy/Definition.scala @@ -13,14 +13,17 @@ import chisel3.internal.BaseModule.IsClone import firrtl.annotations.{IsModule, ModuleTarget} /** User-facing Definition type. - * Represents a definition of an object of type [[A]] which are marked as @instantiable + * Represents a definition of an object of type [[A]] which are marked as @instantiable * Can be created using Definition.apply method. - * + * * These definitions are then used to create multiple [[Instance]]s. * * @param underlying The internal representation of the definition, which may be either be directly the object, or a clone of an object */ -final case class Definition[+A] private[chisel3] (private[chisel3] underlying: Underlying[A]) extends IsLookupable with SealedHierarchy[A] { +final case class Definition[+A] private[chisel3] (private[chisel3] underlying: Underlying[A]) + extends IsLookupable + with SealedHierarchy[A] { + /** Used by Chisel's internal macros. DO NOT USE in your normal Chisel code!!! * Instead, mark the field you are accessing with [[@public]] * @@ -35,14 +38,22 @@ final case class Definition[+A] private[chisel3] (private[chisel3] underlying: U * @param lookup typeclass which contains the correct lookup function, based on the types of A and B * @param macroGenerated a value created in the macro, to make it harder for users to use this API */ - def _lookup[B, C](that: A => B)(implicit lookup: Lookupable[B], macroGenerated: chisel3.internal.MacroGenerated): lookup.C = { + def _lookup[B, C]( + that: A => B + )( + implicit lookup: Lookupable[B], + macroGenerated: chisel3.internal.MacroGenerated + ): lookup.C = { lookup.definitionLookup(that, this) } /** @return the context of any Data's return from inside the instance */ private[chisel3] def getInnerDataContext: Option[BaseModule] = proto match { case value: BaseModule => - val newChild = Module.do_pseudo_apply(new internal.BaseModule.DefinitionClone(value))(chisel3.internal.sourceinfo.UnlocatableSourceInfo, chisel3.ExplicitCompileOptions.Strict) + val newChild = Module.do_pseudo_apply(new internal.BaseModule.DefinitionClone(value))( + chisel3.internal.sourceinfo.UnlocatableSourceInfo, + chisel3.ExplicitCompileOptions.Strict + ) newChild._circuit = value._circuit.orElse(Some(value)) newChild._parent = None Some(newChild) @@ -50,14 +61,14 @@ final case class Definition[+A] private[chisel3] (private[chisel3] underlying: U } override def toDefinition: Definition[A] = this - override def toInstance: Instance[A] = new Instance(underlying) - + override def toInstance: Instance[A] = new Instance(underlying) } /** Factory methods for constructing [[Definition]]s */ object Definition extends SourceInfoDoc { implicit class DefinitionBaseModuleExtensions[T <: BaseModule](d: Definition[T]) { + /** If this is an instance of a Module, returns the toTarget of this instance * @return target of this instance */ @@ -68,6 +79,7 @@ object Definition extends SourceInfoDoc { */ def toAbsoluteTarget: IsModule = d.proto.toAbsoluteTarget } + /** A construction method to build a Definition of a Module * * @param proto the Module being defined @@ -82,7 +94,12 @@ object Definition extends SourceInfoDoc { * * @return the input module as a Definition */ - def do_apply[T <: BaseModule with IsInstantiable](proto: => T) (implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Definition[T] = { + def do_apply[T <: BaseModule with IsInstantiable]( + proto: => T + )( + implicit sourceInfo: SourceInfo, + compileOptions: CompileOptions + ): Definition[T] = { val dynamicContext = new DynamicContext(Nil) Builder.globalNamespace.copyTo(dynamicContext.globalNamespace) dynamicContext.inDefinition = true diff --git a/core/src/main/scala/chisel3/experimental/hierarchy/Hierarchy.scala b/core/src/main/scala/chisel3/experimental/hierarchy/Hierarchy.scala index 4b8d3ccc..2016bb54 100644 --- a/core/src/main/scala/chisel3/experimental/hierarchy/Hierarchy.scala +++ b/core/src/main/scala/chisel3/experimental/hierarchy/Hierarchy.scala @@ -34,28 +34,27 @@ sealed trait Hierarchy[+A] { * E.g. isA[List[Int]] will return true, even if underlying proto is of type List[String] * @return Whether underlying proto is of provided type (with caveats outlined above) */ - def isA[B : TypeTag]: Boolean = { + def isA[B: TypeTag]: Boolean = { val tptag = implicitly[TypeTag[B]] // drop any type information for the comparison, because the proto will not have that information. - val name = tptag.tpe.toString.takeWhile(_ != '[') + val name = tptag.tpe.toString.takeWhile(_ != '[') inBaseClasses(name) } - // This code handles a special-case where, within an mdoc context, the type returned from // scala reflection (typetag) looks different than when returned from java reflection. // This function detects this case and reshapes the string to match. private def modifyReplString(clz: String): String = { - if(clz != null) { + if (clz != null) { clz.split('.').toList match { case "repl" :: "MdocSession" :: app :: rest => s"$app.this." + rest.mkString(".") - case other => clz + case other => clz } } else clz } private lazy val superClasses = calculateSuperClasses(proto.getClass()) private def calculateSuperClasses(clz: Class[_]): Set[String] = { - if(clz != null) { + if (clz != null) { Set(modifyReplString(clz.getCanonicalName())) ++ clz.getInterfaces().flatMap(i => calculateSuperClasses(i)) ++ calculateSuperClasses(clz.getSuperclass()) @@ -65,7 +64,6 @@ sealed trait Hierarchy[+A] { } private def inBaseClasses(clz: String): Boolean = superClasses.contains(clz) - /** Used by Chisel's internal macros. DO NOT USE in your normal Chisel code!!! * Instead, mark the field you are accessing with [[@public]] * @@ -80,7 +78,12 @@ sealed trait Hierarchy[+A] { * @param lookup typeclass which contains the correct lookup function, based on the types of A and B * @param macroGenerated a value created in the macro, to make it harder for users to use this API */ - def _lookup[B, C](that: A => B)(implicit lookup: Lookupable[B], macroGenerated: chisel3.internal.MacroGenerated): lookup.C + def _lookup[B, C]( + that: A => B + )( + implicit lookup: Lookupable[B], + macroGenerated: chisel3.internal.MacroGenerated + ): lookup.C /** @return Return the underlying Definition[A] of this Hierarchy[A] */ def toDefinition: Definition[A] @@ -94,6 +97,7 @@ private[chisel3] trait SealedHierarchy[+A] extends Hierarchy[A] object Hierarchy { implicit class HierarchyBaseModuleExtensions[T <: BaseModule](i: Hierarchy[T]) { + /** Returns the toTarget of this hierarchy * @return target of this hierarchy */ diff --git a/core/src/main/scala/chisel3/experimental/hierarchy/Instance.scala b/core/src/main/scala/chisel3/experimental/hierarchy/Instance.scala index 97b62c23..cc926771 100644 --- a/core/src/main/scala/chisel3/experimental/hierarchy/Instance.scala +++ b/core/src/main/scala/chisel3/experimental/hierarchy/Instance.scala @@ -11,12 +11,12 @@ import chisel3.experimental.BaseModule import firrtl.annotations.IsModule /** User-facing Instance type. - * Represents a unique instance of type [[A]] which are marked as @instantiable + * Represents a unique instance of type [[A]] which are marked as @instantiable * Can be created using Instance.apply method. * * @param underlying The internal representation of the instance, which may be either be directly the object, or a clone of an object */ -final case class Instance[+A] private [chisel3] (private[chisel3] underlying: Underlying[A]) extends SealedHierarchy[A] { +final case class Instance[+A] private[chisel3] (private[chisel3] underlying: Underlying[A]) extends SealedHierarchy[A] { underlying match { case Proto(p: IsClone[_]) => chisel3.internal.throwException("Cannot have a Proto with a clone!") case other => //Ok @@ -24,16 +24,16 @@ final case class Instance[+A] private [chisel3] (private[chisel3] underlying: Un /** @return the context of any Data's return from inside the instance */ private[chisel3] def getInnerDataContext: Option[BaseModule] = underlying match { - case Proto(value: BaseModule) => Some(value) - case Proto(value: IsInstantiable) => None - case Clone(i: BaseModule) => Some(i) + case Proto(value: BaseModule) => Some(value) + case Proto(value: IsInstantiable) => None + case Clone(i: BaseModule) => Some(i) case Clone(i: InstantiableClone[_]) => i.getInnerContext } /** @return the context this instance. Note that for non-module clones, getInnerDataContext will be the same as getClonedParent */ private[chisel3] def getClonedParent: Option[BaseModule] = underlying match { case Proto(value: BaseModule) => value._parent - case Clone(i: BaseModule) => i._parent + case Clone(i: BaseModule) => i._parent case Clone(i: InstantiableClone[_]) => i.getInnerContext } @@ -51,19 +51,25 @@ final case class Instance[+A] private [chisel3] (private[chisel3] underlying: Un * @param lookup typeclass which contains the correct lookup function, based on the types of A and B * @param macroGenerated a value created in the macro, to make it harder for users to use this API */ - def _lookup[B, C](that: A => B)(implicit lookup: Lookupable[B], macroGenerated: chisel3.internal.MacroGenerated): lookup.C = { + def _lookup[B, C]( + that: A => B + )( + implicit lookup: Lookupable[B], + macroGenerated: chisel3.internal.MacroGenerated + ): lookup.C = { lookup.instanceLookup(that, this) } /** Returns the definition of this Instance */ override def toDefinition: Definition[A] = new Definition(Proto(proto)) - override def toInstance: Instance[A] = this + override def toInstance: Instance[A] = this } /** Factory methods for constructing [[Instance]]s */ object Instance extends SourceInfoDoc { implicit class InstanceBaseModuleExtensions[T <: BaseModule](i: Instance[T]) { + /** If this is an instance of a Module, returns the toTarget of this instance * @return target of this instance */ @@ -81,19 +87,26 @@ object Instance extends SourceInfoDoc { } } + /** A constructs an [[Instance]] from a [[Definition]] * * @param definition the Module being created * @return an instance of the module definition */ - def apply[T <: BaseModule with IsInstantiable](definition: Definition[T]): Instance[T] = macro InstanceTransform.apply[T] + def apply[T <: BaseModule with IsInstantiable](definition: Definition[T]): Instance[T] = + macro InstanceTransform.apply[T] /** A constructs an [[Instance]] from a [[Definition]] * * @param definition the Module being created * @return an instance of the module definition */ - def do_apply[T <: BaseModule with IsInstantiable](definition: Definition[T])(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Instance[T] = { + def do_apply[T <: BaseModule with IsInstantiable]( + definition: Definition[T] + )( + implicit sourceInfo: SourceInfo, + compileOptions: CompileOptions + ): Instance[T] = { val ports = experimental.CloneModuleAsRecord(definition.proto) val clone = ports._parent.get.asInstanceOf[ModuleClone[T]] clone._madeFromDefinition = true diff --git a/core/src/main/scala/chisel3/experimental/hierarchy/IsInstantiable.scala b/core/src/main/scala/chisel3/experimental/hierarchy/IsInstantiable.scala index 4f3c2d42..27e06d92 100644 --- a/core/src/main/scala/chisel3/experimental/hierarchy/IsInstantiable.scala +++ b/core/src/main/scala/chisel3/experimental/hierarchy/IsInstantiable.scala @@ -6,7 +6,6 @@ package chisel3.experimental.hierarchy * Instead, use the [[@instantiable]] annotation on your trait or class. * * This trait indicates whether a class can be returned from an Instance. - * */ trait IsInstantiable diff --git a/core/src/main/scala/chisel3/experimental/hierarchy/IsLookupable.scala b/core/src/main/scala/chisel3/experimental/hierarchy/IsLookupable.scala index 37d29a43..a82cbd7d 100644 --- a/core/src/main/scala/chisel3/experimental/hierarchy/IsLookupable.scala +++ b/core/src/main/scala/chisel3/experimental/hierarchy/IsLookupable.scala @@ -4,9 +4,9 @@ package chisel3.experimental.hierarchy /** A User-extendable trait to mark metadata-containers, e.g. parameter case classes, as valid to return unchanged * from an instance. - * + * * This should only be true of the metadata returned is identical for ALL instances! - * + * * @example For instances of the same proto, metadata or other construction parameters * may be useful to access outside of the instance construction. For parameters that are * the same for all instances, we should mark it as IsLookupable diff --git a/core/src/main/scala/chisel3/experimental/hierarchy/LibraryHooks.scala b/core/src/main/scala/chisel3/experimental/hierarchy/LibraryHooks.scala index c16cc633..d4818f63 100644 --- a/core/src/main/scala/chisel3/experimental/hierarchy/LibraryHooks.scala +++ b/core/src/main/scala/chisel3/experimental/hierarchy/LibraryHooks.scala @@ -16,9 +16,12 @@ object LibraryHooks { * definition's Underlying * @note Implicitly requires being inside a Hierarchy Library Extension */ - def buildInstance[A](definition: Definition[A], - createUnderlying: Underlying[A] => Underlying[A] - )(implicit inside: InsideHierarchyLibraryExtension): Instance[A] = { + def buildInstance[A]( + definition: Definition[A], + createUnderlying: Underlying[A] => Underlying[A] + )( + implicit inside: InsideHierarchyLibraryExtension + ): Instance[A] = { new Instance(createUnderlying(definition.underlying)) } diff --git a/core/src/main/scala/chisel3/experimental/hierarchy/Lookupable.scala b/core/src/main/scala/chisel3/experimental/hierarchy/Lookupable.scala index ff4d676c..1223d6ce 100644 --- a/core/src/main/scala/chisel3/experimental/hierarchy/Lookupable.scala +++ b/core/src/main/scala/chisel3/experimental/hierarchy/Lookupable.scala @@ -11,18 +11,20 @@ import scala.collection.mutable.HashMap import chisel3._ import chisel3.experimental.dataview.{isView, reify, reifySingleData} import chisel3.internal.firrtl.{Arg, ILit, Index, Slot, ULit} -import chisel3.internal.{AggregateViewBinding, Builder, ChildBinding, ViewBinding, ViewParent, throwException} +import chisel3.internal.{throwException, AggregateViewBinding, Builder, ChildBinding, ViewBinding, ViewParent} /** Represents lookup typeclass to determine how a value accessed from an original IsInstantiable * should be tweaked to return the Instance's version * Sealed. */ -@implicitNotFound("@public is only legal within a class marked @instantiable and only on vals of type" + - " Data, BaseModule, IsInstantiable, IsLookupable, or Instance[_], or in an Iterable or Option") +@implicitNotFound( + "@public is only legal within a class marked @instantiable and only on vals of type" + + " Data, BaseModule, IsInstantiable, IsLookupable, or Instance[_], or in an Iterable or Option" +) trait Lookupable[-B] { type C // Return type of the lookup /** Function called to modify the returned value of type B from A, into C - * + * * @param that function that selects B from A * @param instance Instance of A, used to determine C's context * @return @@ -35,8 +37,8 @@ trait Lookupable[-B] { * @param definition Definition of A, used to determine C's context * @return */ - def definitionLookup[A](that: A => B, definition: Definition[A]): C - protected def getProto[A](h: Hierarchy[A]): A = h.proto + def definitionLookup[A](that: A => B, definition: Definition[A]): C + protected def getProto[A](h: Hierarchy[A]): A = h.proto protected def getUnderlying[A](h: Hierarchy[A]): Underlying[A] = h.underlying } @@ -48,8 +50,13 @@ object Lookupable { * @param context new context * @return */ - private[chisel3] def cloneDataToContext[T <: Data](data: T, context: BaseModule) - (implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): T = { + private[chisel3] def cloneDataToContext[T <: Data]( + data: T, + context: BaseModule + )( + implicit sourceInfo: SourceInfo, + compileOptions: CompileOptions + ): T = { internal.requireIsHardware(data, "cross module reference type") data._parent match { case None => data @@ -68,11 +75,18 @@ object Lookupable { } // The business logic of lookupData // Also called by cloneViewToContext which potentially needs to lookup stuff from ioMap or the cache - private[chisel3] def doLookupData[A, B <: Data](data: B, cache: HashMap[Data, Data], ioMap: Option[Map[Data, Data]], context: Option[BaseModule]) - (implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): B = { + private[chisel3] def doLookupData[A, B <: Data]( + data: B, + cache: HashMap[Data, Data], + ioMap: Option[Map[Data, Data]], + context: Option[BaseModule] + )( + implicit sourceInfo: SourceInfo, + compileOptions: CompileOptions + ): B = { def impl[C <: Data](d: C): C = d match { case x: Data if ioMap.nonEmpty && ioMap.get.contains(x) => ioMap.get(x).asInstanceOf[C] - case x: Data if cache.contains(x) => cache(x).asInstanceOf[C] + case x: Data if cache.contains(x) => cache(x).asInstanceOf[C] case _ => assert(context.nonEmpty) // TODO is this even possible? Better error message here val ret = cloneDataToContext(d, context.get) @@ -105,12 +119,13 @@ object Lookupable { * Invariants that elt is a Child of something of the type of data is dynamically checked as we traverse */ private def mapRootAndExtractSubField[A <: Data](arg: A, f: Data => Data): A = { - def err(msg: String) = throwException(s"Internal Error! $msg") + def err(msg: String) = throwException(s"Internal Error! $msg") def unrollCoordinates(res: List[Arg], d: Data): (List[Arg], Data) = d.binding.get match { - case ChildBinding(parent) => d.getRef match { - case arg @ (_: Slot | _: Index) => unrollCoordinates(arg :: res, parent) - case other => err(s"Unroll coordinates failed for '$arg'! Unexpected arg '$other'") - } + case ChildBinding(parent) => + d.getRef match { + case arg @ (_: Slot | _: Index) => unrollCoordinates(arg :: res, parent) + case other => err(s"Unroll coordinates failed for '$arg'! Unexpected arg '$other'") + } case _ => (res, d) } def applyCoordinates(fullCoor: List[Arg], start: Data): Data = { @@ -133,15 +148,22 @@ object Lookupable { try { result.asInstanceOf[A] } catch { - case _: ClassCastException => err(s"Applying '$coor' to '$newRoot' somehow resulted in '$result'") + case _: ClassCastException => err(s"Applying '$coor' to '$newRoot' somehow resulted in '$result'") } } // TODO this logic is complicated, can any of it be unified with viewAs? // If `.viewAs` would capture its arguments, we could potentially use it // TODO Describe what this is doing at a high level - private[chisel3] def cloneViewToContext[A, B <: Data](data: B, cache: HashMap[Data, Data], ioMap: Option[Map[Data, Data]], context: Option[BaseModule]) - (implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): B = { + private[chisel3] def cloneViewToContext[A, B <: Data]( + data: B, + cache: HashMap[Data, Data], + ioMap: Option[Map[Data, Data]], + context: Option[BaseModule] + )( + implicit sourceInfo: SourceInfo, + compileOptions: CompileOptions + ): B = { // alias to shorten lookups def lookupData[C <: Data](d: C) = doLookupData(d, cache, ioMap, context) @@ -150,29 +172,31 @@ object Lookupable { // We have to lookup the target(s) of the view since they may need to be underlying into the current context val newBinding = data.topBinding match { case ViewBinding(target) => ViewBinding(lookupData(reify(target))) - case avb @ AggregateViewBinding(map, targetOpt) => data match { - case _: Element => ViewBinding(lookupData(reify(map(data)))) - case _: Aggregate => - // Provide a 1:1 mapping if possible - val singleTargetOpt = targetOpt.filter(_ => avb == data.binding.get).flatMap(reifySingleData) - singleTargetOpt match { - case Some(singleTarget) => // It is 1:1! - // This is a little tricky because the values in newMap need to point to Elements of newTarget - val newTarget = lookupData(singleTarget) - val newMap = coiterate(result, data).map { case (res, from) => - (res: Data) -> mapRootAndExtractSubField(map(from), _ => newTarget) - }.toMap - AggregateViewBinding(newMap, Some(newTarget)) + case avb @ AggregateViewBinding(map, targetOpt) => + data match { + case _: Element => ViewBinding(lookupData(reify(map(data)))) + case _: Aggregate => + // Provide a 1:1 mapping if possible + val singleTargetOpt = targetOpt.filter(_ => avb == data.binding.get).flatMap(reifySingleData) + singleTargetOpt match { + case Some(singleTarget) => // It is 1:1! + // This is a little tricky because the values in newMap need to point to Elements of newTarget + val newTarget = lookupData(singleTarget) + val newMap = coiterate(result, data).map { + case (res, from) => + (res: Data) -> mapRootAndExtractSubField(map(from), _ => newTarget) + }.toMap + AggregateViewBinding(newMap, Some(newTarget)) - case None => // No 1:1 mapping so we have to do a flat binding - // Just remap each Element of this aggregate - val newMap = coiterate(result, data).map { - // Upcast res to Data since Maps are invariant in the Key type parameter - case (res, from) => (res: Data) -> lookupData(reify(map(from))) - }.toMap - AggregateViewBinding(newMap, None) - } - } + case None => // No 1:1 mapping so we have to do a flat binding + // Just remap each Element of this aggregate + val newMap = coiterate(result, data).map { + // Upcast res to Data since Maps are invariant in the Key type parameter + case (res, from) => (res: Data) -> lookupData(reify(map(from))) + }.toMap + AggregateViewBinding(newMap, None) + } + } } // TODO Unify the following with `.viewAs` @@ -188,7 +212,7 @@ object Lookupable { case (agg: Aggregate, _) if agg != result => Builder.unnamedViews += agg case _ => // Do nothing - } + } } result.bind(newBinding) @@ -196,6 +220,7 @@ object Lookupable { result.forceName(None, "view", Builder.viewNamespace) result } + /** Given a module (either original or a clone), clone it to a new context * * This function effectively recurses up the parents of module to find whether: @@ -208,8 +233,13 @@ object Lookupable { * @param context new context * @return original or clone in the new context */ - private[chisel3] def cloneModuleToContext[T <: BaseModule](module: Underlying[T], context: BaseModule) - (implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Underlying[T] = { + private[chisel3] def cloneModuleToContext[T <: BaseModule]( + module: Underlying[T], + context: BaseModule + )( + implicit sourceInfo: SourceInfo, + compileOptions: CompileOptions + ): Underlying[T] = { // Recursive call def rec[A <: BaseModule](m: A): Underlying[A] = { def clone(x: A, p: Option[BaseModule], name: () => String): Underlying[A] = { @@ -221,7 +251,7 @@ object Lookupable { case (c, ctx) if ctx == c => Proto(c) case (c, ctx: IsClone[_]) if ctx.hasSameProto(c) => Clone(ctx.asInstanceOf[IsClone[A]]) case (c, ctx) if c._parent.isEmpty => Proto(c) - case (_, _) => + case (_, _) => cloneModuleToContext(Proto(m._parent.get), context) match { case Proto(p) => Proto(m) case Clone(p: BaseModule) => @@ -254,93 +284,107 @@ object Lookupable { type B = X type C = X def definitionLookup[A](that: A => B, definition: Definition[A]): C = that(definition.proto) - def instanceLookup[A](that: A => B, instance: Instance[A]): C = that(instance.proto) + def instanceLookup[A](that: A => B, instance: Instance[A]): C = that(instance.proto) } - implicit def lookupInstance[B <: BaseModule](implicit sourceInfo: SourceInfo, compileOptions: CompileOptions) = new Lookupable[Instance[B]] { - type C = Instance[B] - def definitionLookup[A](that: A => Instance[B], definition: Definition[A]): C = { - val ret = that(definition.proto) - new Instance(cloneModuleToContext(ret.underlying, definition.getInnerDataContext.get)) - } - def instanceLookup[A](that: A => Instance[B], instance: Instance[A]): C = { - val ret = that(instance.proto) - instance.underlying match { - // If instance is just a normal module, no changing of context is necessary - case Proto(_) => new Instance(ret.underlying) - case Clone(_) => new Instance(cloneModuleToContext(ret.underlying, instance.getInnerDataContext.get)) + implicit def lookupInstance[B <: BaseModule](implicit sourceInfo: SourceInfo, compileOptions: CompileOptions) = + new Lookupable[Instance[B]] { + type C = Instance[B] + def definitionLookup[A](that: A => Instance[B], definition: Definition[A]): C = { + val ret = that(definition.proto) + new Instance(cloneModuleToContext(ret.underlying, definition.getInnerDataContext.get)) } - } - } - - implicit def lookupModule[B <: BaseModule](implicit sourceInfo: SourceInfo, compileOptions: CompileOptions) = new Lookupable[B] { - type C = Instance[B] - def definitionLookup[A](that: A => B, definition: Definition[A]): C = { - val ret = that(definition.proto) - new Instance(cloneModuleToContext(Proto(ret), definition.getInnerDataContext.get)) - } - def instanceLookup[A](that: A => B, instance: Instance[A]): C = { - val ret = that(instance.proto) - instance.underlying match { - // If instance is just a normal module, no changing of context is necessary - case Proto(_) => new Instance(Proto(ret)) - case Clone(_) => new Instance(cloneModuleToContext(Proto(ret), instance.getInnerDataContext.get)) + def instanceLookup[A](that: A => Instance[B], instance: Instance[A]): C = { + val ret = that(instance.proto) + instance.underlying match { + // If instance is just a normal module, no changing of context is necessary + case Proto(_) => new Instance(ret.underlying) + case Clone(_) => new Instance(cloneModuleToContext(ret.underlying, instance.getInnerDataContext.get)) + } } } - } - implicit def lookupData[B <: Data](implicit sourceInfo: SourceInfo, compileOptions: CompileOptions) = new Lookupable[B] { - type C = B - def definitionLookup[A](that: A => B, definition: Definition[A]): C = { - val ret = that(definition.proto) - if (isView(ret)) { - ??? // TODO!!!!!! cloneViewToContext(ret, instance, ioMap, instance.getInnerDataContext) - } else { - doLookupData(ret, definition.cache, None, definition.getInnerDataContext) + implicit def lookupModule[B <: BaseModule](implicit sourceInfo: SourceInfo, compileOptions: CompileOptions) = + new Lookupable[B] { + type C = Instance[B] + def definitionLookup[A](that: A => B, definition: Definition[A]): C = { + val ret = that(definition.proto) + new Instance(cloneModuleToContext(Proto(ret), definition.getInnerDataContext.get)) } - } - def instanceLookup[A](that: A => B, instance: Instance[A]): C = { - val ret = that(instance.proto) - val ioMap: Option[Map[Data, Data]] = instance.underlying match { - case Clone(x: ModuleClone[_]) => Some(x.ioMap) - case Proto(x: BaseModule) => Some(x.getChiselPorts.map { case (_, data) => data -> data }.toMap) - case _ => None + def instanceLookup[A](that: A => B, instance: Instance[A]): C = { + val ret = that(instance.proto) + instance.underlying match { + // If instance is just a normal module, no changing of context is necessary + case Proto(_) => new Instance(Proto(ret)) + case Clone(_) => new Instance(cloneModuleToContext(Proto(ret), instance.getInnerDataContext.get)) + } } - if (isView(ret)) { - cloneViewToContext(ret, instance.cache, ioMap, instance.getInnerDataContext) - } else { - doLookupData(ret, instance.cache, ioMap, instance.getInnerDataContext) + } + + implicit def lookupData[B <: Data](implicit sourceInfo: SourceInfo, compileOptions: CompileOptions) = + new Lookupable[B] { + type C = B + def definitionLookup[A](that: A => B, definition: Definition[A]): C = { + val ret = that(definition.proto) + if (isView(ret)) { + ??? // TODO!!!!!! cloneViewToContext(ret, instance, ioMap, instance.getInnerDataContext) + } else { + doLookupData(ret, definition.cache, None, definition.getInnerDataContext) + } } + def instanceLookup[A](that: A => B, instance: Instance[A]): C = { + val ret = that(instance.proto) + val ioMap: Option[Map[Data, Data]] = instance.underlying match { + case Clone(x: ModuleClone[_]) => Some(x.ioMap) + case Proto(x: BaseModule) => Some(x.getChiselPorts.map { case (_, data) => data -> data }.toMap) + case _ => None + } + if (isView(ret)) { + cloneViewToContext(ret, instance.cache, ioMap, instance.getInnerDataContext) + } else { + doLookupData(ret, instance.cache, ioMap, instance.getInnerDataContext) + } + } } - } import scala.language.higherKinds // Required to avoid warning for lookupIterable type parameter - implicit def lookupIterable[B, F[_] <: Iterable[_]](implicit sourceInfo: SourceInfo, compileOptions: CompileOptions, lookupable: Lookupable[B]) = new Lookupable[F[B]] { + implicit def lookupIterable[B, F[_] <: Iterable[_]]( + implicit sourceInfo: SourceInfo, + compileOptions: CompileOptions, + lookupable: Lookupable[B] + ) = new Lookupable[F[B]] { type C = F[lookupable.C] def definitionLookup[A](that: A => F[B], definition: Definition[A]): C = { val ret = that(definition.proto).asInstanceOf[Iterable[B]] - ret.map{ x: B => lookupable.definitionLookup[A](_ => x, definition) }.asInstanceOf[C] + ret.map { x: B => lookupable.definitionLookup[A](_ => x, definition) }.asInstanceOf[C] } def instanceLookup[A](that: A => F[B], instance: Instance[A]): C = { import instance._ val ret = that(proto).asInstanceOf[Iterable[B]] - ret.map{ x: B => lookupable.instanceLookup[A](_ => x, instance) }.asInstanceOf[C] + ret.map { x: B => lookupable.instanceLookup[A](_ => x, instance) }.asInstanceOf[C] } } - implicit def lookupOption[B](implicit sourceInfo: SourceInfo, compileOptions: CompileOptions, lookupable: Lookupable[B]) = new Lookupable[Option[B]] { + implicit def lookupOption[B]( + implicit sourceInfo: SourceInfo, + compileOptions: CompileOptions, + lookupable: Lookupable[B] + ) = new Lookupable[Option[B]] { type C = Option[lookupable.C] def definitionLookup[A](that: A => Option[B], definition: Definition[A]): C = { val ret = that(definition.proto) - ret.map{ x: B => lookupable.definitionLookup[A](_ => x, definition) } + ret.map { x: B => lookupable.definitionLookup[A](_ => x, definition) } } def instanceLookup[A](that: A => Option[B], instance: Instance[A]): C = { import instance._ val ret = that(proto) - ret.map{ x: B => lookupable.instanceLookup[A](_ => x, instance) } + ret.map { x: B => lookupable.instanceLookup[A](_ => x, instance) } } } - implicit def lookupIsInstantiable[B <: IsInstantiable](implicit sourceInfo: SourceInfo, compileOptions: CompileOptions) = new Lookupable[B] { + implicit def lookupIsInstantiable[B <: IsInstantiable]( + implicit sourceInfo: SourceInfo, + compileOptions: CompileOptions + ) = new Lookupable[B] { type C = Instance[B] def definitionLookup[A](that: A => B, definition: Definition[A]): C = { val ret = that(definition.proto) @@ -360,8 +404,9 @@ object Lookupable { } } - implicit def lookupIsLookupable[B <: IsLookupable](implicit sourceInfo: SourceInfo, compileOptions: CompileOptions) = new SimpleLookupable[B]() - + implicit def lookupIsLookupable[B <: IsLookupable](implicit sourceInfo: SourceInfo, compileOptions: CompileOptions) = + new SimpleLookupable[B]() + implicit val lookupInt = new SimpleLookupable[Int]() implicit val lookupByte = new SimpleLookupable[Byte]() implicit val lookupShort = new SimpleLookupable[Short]() diff --git a/core/src/main/scala/chisel3/experimental/package.scala b/core/src/main/scala/chisel3/experimental/package.scala index 5397a1c3..ce258a25 100644 --- a/core/src/main/scala/chisel3/experimental/package.scala +++ b/core/src/main/scala/chisel3/experimental/package.scala @@ -16,9 +16,9 @@ package object experimental { import chisel3.internal.BaseModule // Implicit conversions for BlackBox Parameters - implicit def fromIntToIntParam(x: Int): IntParam = IntParam(BigInt(x)) - implicit def fromLongToIntParam(x: Long): IntParam = IntParam(BigInt(x)) - implicit def fromBigIntToIntParam(x: BigInt): IntParam = IntParam(x) + implicit def fromIntToIntParam(x: Int): IntParam = IntParam(BigInt(x)) + implicit def fromLongToIntParam(x: Long): IntParam = IntParam(BigInt(x)) + implicit def fromBigIntToIntParam(x: BigInt): IntParam = IntParam(x) implicit def fromDoubleToDoubleParam(x: Double): DoubleParam = DoubleParam(x) implicit def fromStringToStringParam(x: String): StringParam = StringParam(x) @@ -32,6 +32,7 @@ package object experimental { type ClonePorts = BaseModule.ClonePorts object CloneModuleAsRecord { + /** Clones an existing module and returns a record of all its top-level ports. * Each element of the record is named with a string matching the * corresponding port's name and shares the port's type. @@ -41,13 +42,18 @@ package object experimental { * q2_io.enq <> q1.io.deq * }}} */ - def apply(proto: BaseModule)(implicit sourceInfo: chisel3.internal.sourceinfo.SourceInfo, compileOptions: CompileOptions): ClonePorts = { + def apply( + proto: BaseModule + )( + implicit sourceInfo: chisel3.internal.sourceinfo.SourceInfo, + compileOptions: CompileOptions + ): ClonePorts = { BaseModule.cloneIORecord(proto) } } val requireIsHardware = chisel3.internal.requireIsHardware - val requireIsChiselType = chisel3.internal.requireIsChiselType + val requireIsChiselType = chisel3.internal.requireIsChiselType type Direction = ActualDirection val Direction = ActualDirection @@ -68,6 +74,7 @@ package object experimental { class dump extends chisel3.internal.naming.dump class treedump extends chisel3.internal.naming.treedump + /** Experimental macro for naming Chisel hardware values * * By default, Chisel uses reflection for naming which only works for public fields of `Bundle` @@ -94,6 +101,7 @@ package object experimental { * }}} */ class chiselName extends chisel3.internal.naming.chiselName + /** Do not name instances of this type in [[chiselName]] * * By default, `chiselName` will include `val` names of instances of annotated classes as a @@ -138,6 +146,7 @@ package object experimental { */ object VecLiterals { implicit class AddVecLiteralConstructor[T <: Data](x: Vec[T]) { + /** Given a generator of a list tuples of the form [Int, Data] * constructs a Vec literal, parallel concept to `BundleLiteral` * @@ -150,15 +159,16 @@ package object experimental { } implicit class AddObjectLiteralConstructor(x: Vec.type) { + /** This provides an literal construction method for cases using * object `Vec` as in `Vec.Lit(1.U, 2.U)` */ def Lit[T <: Data](elems: T*)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Vec[T] = { require(elems.nonEmpty, s"Lit.Vec(...) must have at least one element") - val indexElements = elems.zipWithIndex.map { case (element, index) => (index, element)} + val indexElements = elems.zipWithIndex.map { case (element, index) => (index, element) } val widestElement = elems.maxBy(_.getWidth) val vec: Vec[T] = Vec.apply(indexElements.length, chiselTypeOf(widestElement)) - vec.Lit(indexElements:_*) + vec.Lit(indexElements: _*) } } } @@ -178,7 +188,7 @@ package object experimental { */ final class HWTuple2[+A <: Data, +B <: Data] private[chisel3] (val _1: A, val _2: B) extends Bundle()(Strict) { // Because this implementation exists in chisel3.core, it cannot compile with the plugin, so we implement the behavior manually - override protected def _usingPlugin: Boolean = true + override protected def _usingPlugin: Boolean = true override protected def _cloneTypeImpl: Bundle = new HWTuple2(chiselTypeClone(_1), chiselTypeClone(_2)) } @@ -188,12 +198,16 @@ package object experimental { * `chisel3.experimental.conversions` */ final class HWTuple3[+A <: Data, +B <: Data, +C <: Data] private[chisel3] ( - val _1: A, val _2: B, val _3: C - ) extends Bundle()(Strict) { + val _1: A, + val _2: B, + val _3: C) + extends Bundle()(Strict) { // Because this implementation exists in chisel3.core, it cannot compile with the plugin, so we implement the behavior manually override protected def _usingPlugin: Boolean = true override protected def _cloneTypeImpl: Bundle = new HWTuple3( - chiselTypeClone(_1), chiselTypeClone(_2), chiselTypeClone(_3) + chiselTypeClone(_1), + chiselTypeClone(_2), + chiselTypeClone(_3) ) } @@ -203,12 +217,18 @@ package object experimental { * `chisel3.experimental.conversions` */ final class HWTuple4[+A <: Data, +B <: Data, +C <: Data, +D <: Data] private[chisel3] ( - val _1: A, val _2: B, val _3: C, val _4: D - ) extends Bundle()(Strict) { + val _1: A, + val _2: B, + val _3: C, + val _4: D) + extends Bundle()(Strict) { // Because this implementation exists in chisel3.core, it cannot compile with the plugin, so we implement the behavior manually override protected def _usingPlugin: Boolean = true override protected def _cloneTypeImpl: Bundle = new HWTuple4( - chiselTypeClone(_1), chiselTypeClone(_2), chiselTypeClone(_3), chiselTypeClone(_4) + chiselTypeClone(_1), + chiselTypeClone(_2), + chiselTypeClone(_3), + chiselTypeClone(_4) ) } @@ -218,12 +238,20 @@ package object experimental { * `chisel3.experimental.conversions` */ final class HWTuple5[+A <: Data, +B <: Data, +C <: Data, +D <: Data, +E <: Data] private[chisel3] ( - val _1: A, val _2: B, val _3: C, val _4: D, val _5: E - ) extends Bundle()(Strict) { + val _1: A, + val _2: B, + val _3: C, + val _4: D, + val _5: E) + extends Bundle()(Strict) { // Because this implementation exists in chisel3.core, it cannot compile with the plugin, so we implement the behavior manually override protected def _usingPlugin: Boolean = true override protected def _cloneTypeImpl: Bundle = new HWTuple5( - chiselTypeClone(_1), chiselTypeClone(_2), chiselTypeClone(_3), chiselTypeClone(_4), chiselTypeClone(_5) + chiselTypeClone(_1), + chiselTypeClone(_2), + chiselTypeClone(_3), + chiselTypeClone(_4), + chiselTypeClone(_5) ) } @@ -233,12 +261,21 @@ package object experimental { * `chisel3.experimental.conversions` */ final class HWTuple6[+A <: Data, +B <: Data, +C <: Data, +D <: Data, +E <: Data, +F <: Data] private[chisel3] ( - val _1: A, val _2: B, val _3: C, val _4: D, val _5: E, val _6: F - ) extends Bundle()(Strict) { + val _1: A, + val _2: B, + val _3: C, + val _4: D, + val _5: E, + val _6: F) + extends Bundle()(Strict) { // Because this implementation exists in chisel3.core, it cannot compile with the plugin, so we implement the behavior manually override protected def _usingPlugin: Boolean = true override protected def _cloneTypeImpl: Bundle = new HWTuple6( - chiselTypeClone(_1), chiselTypeClone(_2), chiselTypeClone(_3), chiselTypeClone(_4), chiselTypeClone(_5), + chiselTypeClone(_1), + chiselTypeClone(_2), + chiselTypeClone(_3), + chiselTypeClone(_4), + chiselTypeClone(_5), chiselTypeClone(_6) ) } @@ -248,14 +285,33 @@ package object experimental { * Users may not instantiate this class directly. Instead they should use the implicit conversion from `Tuple7` in * `chisel3.experimental.conversions` */ - final class HWTuple7[+A <: Data, +B <: Data, +C <: Data, +D <: Data, +E <: Data, +F <: Data, +G <: Data] private[chisel3] ( - val _1: A, val _2: B, val _3: C, val _4: D, val _5: E, val _6: F, val _7: G - ) extends Bundle()(Strict) { + final class HWTuple7[ + +A <: Data, + +B <: Data, + +C <: Data, + +D <: Data, + +E <: Data, + +F <: Data, + +G <: Data + ] private[chisel3] ( + val _1: A, + val _2: B, + val _3: C, + val _4: D, + val _5: E, + val _6: F, + val _7: G) + extends Bundle()(Strict) { // Because this implementation exists in chisel3.core, it cannot compile with the plugin, so we implement the behavior manually override protected def _usingPlugin: Boolean = true override protected def _cloneTypeImpl: Bundle = new HWTuple7( - chiselTypeClone(_1), chiselTypeClone(_2), chiselTypeClone(_3), chiselTypeClone(_4), chiselTypeClone(_5), - chiselTypeClone(_6), chiselTypeClone(_7) + chiselTypeClone(_1), + chiselTypeClone(_2), + chiselTypeClone(_3), + chiselTypeClone(_4), + chiselTypeClone(_5), + chiselTypeClone(_6), + chiselTypeClone(_7) ) } @@ -265,15 +321,35 @@ package object experimental { * `chisel3.experimental.conversions` */ final class HWTuple8[ - +A <: Data, +B <: Data, +C <: Data, +D <: Data, +E <: Data, +F <: Data, +G <: Data, +H <: Data + +A <: Data, + +B <: Data, + +C <: Data, + +D <: Data, + +E <: Data, + +F <: Data, + +G <: Data, + +H <: Data ] private[chisel3] ( - val _1: A, val _2: B, val _3: C, val _4: D, val _5: E, val _6: F, val _7: G, val _8: H - ) extends Bundle()(Strict) { + val _1: A, + val _2: B, + val _3: C, + val _4: D, + val _5: E, + val _6: F, + val _7: G, + val _8: H) + extends Bundle()(Strict) { // Because this implementation exists in chisel3.core, it cannot compile with the plugin, so we implement the behavior manually override protected def _usingPlugin: Boolean = true override protected def _cloneTypeImpl: Bundle = new HWTuple8( - chiselTypeClone(_1), chiselTypeClone(_2), chiselTypeClone(_3), chiselTypeClone(_4), chiselTypeClone(_5), - chiselTypeClone(_6), chiselTypeClone(_7), chiselTypeClone(_8) + chiselTypeClone(_1), + chiselTypeClone(_2), + chiselTypeClone(_3), + chiselTypeClone(_4), + chiselTypeClone(_5), + chiselTypeClone(_6), + chiselTypeClone(_7), + chiselTypeClone(_8) ) } @@ -283,34 +359,82 @@ package object experimental { * `chisel3.experimental.conversions` */ final class HWTuple9[ - +A <: Data, +B <: Data, +C <: Data, +D <: Data, +E <: Data, +F <: Data, +G <: Data, +H <: Data, +I <: Data + +A <: Data, + +B <: Data, + +C <: Data, + +D <: Data, + +E <: Data, + +F <: Data, + +G <: Data, + +H <: Data, + +I <: Data ] private[chisel3] ( - val _1: A, val _2: B, val _3: C, val _4: D, val _5: E, val _6: F, val _7: G, val _8: H, val _9: I - ) extends Bundle()(Strict) { + val _1: A, + val _2: B, + val _3: C, + val _4: D, + val _5: E, + val _6: F, + val _7: G, + val _8: H, + val _9: I) + extends Bundle()(Strict) { // Because this implementation exists in chisel3.core, it cannot compile with the plugin, so we implement the behavior manually override protected def _usingPlugin: Boolean = true override protected def _cloneTypeImpl: Bundle = new HWTuple9( - chiselTypeClone(_1), chiselTypeClone(_2), chiselTypeClone(_3), chiselTypeClone(_4), chiselTypeClone(_5), - chiselTypeClone(_6), chiselTypeClone(_7), chiselTypeClone(_8), chiselTypeClone(_9) + chiselTypeClone(_1), + chiselTypeClone(_2), + chiselTypeClone(_3), + chiselTypeClone(_4), + chiselTypeClone(_5), + chiselTypeClone(_6), + chiselTypeClone(_7), + chiselTypeClone(_8), + chiselTypeClone(_9) ) } - /** [[Data]] equivalent of Scala's [[Tuple9]] * * Users may not instantiate this class directly. Instead they should use the implicit conversion from `Tuple9` in * `chisel3.experimental.conversions` */ final class HWTuple10[ - +A <: Data, +B <: Data, +C <: Data, +D <: Data, +E <: Data, +F <: Data, +G <: Data, +H <: Data, +I <: Data, +J <: Data + +A <: Data, + +B <: Data, + +C <: Data, + +D <: Data, + +E <: Data, + +F <: Data, + +G <: Data, + +H <: Data, + +I <: Data, + +J <: Data ] private[chisel3] ( - val _1: A, val _2: B, val _3: C, val _4: D, val _5: E, val _6: F, val _7: G, val _8: H, val _9: I, val _10: J - ) extends Bundle()(Strict) { + val _1: A, + val _2: B, + val _3: C, + val _4: D, + val _5: E, + val _6: F, + val _7: G, + val _8: H, + val _9: I, + val _10: J) + extends Bundle()(Strict) { // Because this implementation exists in chisel3.core, it cannot compile with the plugin, so we implement the behavior manually override protected def _usingPlugin: Boolean = true override protected def _cloneTypeImpl: Bundle = new HWTuple10( - chiselTypeClone(_1), chiselTypeClone(_2), chiselTypeClone(_3), chiselTypeClone(_4), chiselTypeClone(_5), - chiselTypeClone(_6), chiselTypeClone(_7), chiselTypeClone(_8), chiselTypeClone(_9), chiselTypeClone(_10) + chiselTypeClone(_1), + chiselTypeClone(_2), + chiselTypeClone(_3), + chiselTypeClone(_4), + chiselTypeClone(_5), + chiselTypeClone(_6), + chiselTypeClone(_7), + chiselTypeClone(_8), + chiselTypeClone(_9), + chiselTypeClone(_10) ) } } |
