summaryrefslogtreecommitdiff
path: root/core/src/main/scala/chisel3/experimental
diff options
context:
space:
mode:
authorJack2021-12-18 08:27:38 +0000
committerJack2021-12-18 08:27:38 +0000
commitdd9ad534771247ac16eaa47eb9794102736b5102 (patch)
treed4566d317cb8526b79017de1e438aea8217dd1d4 /core/src/main/scala/chisel3/experimental
parent440edc4436fb3a8a4175ae425a0d31c4997ee60f (diff)
parentf50f74f583fba7b98e550c440df091e559ce32b8 (diff)
Merge branch 'master' into 3.5-release
Diffstat (limited to 'core/src/main/scala/chisel3/experimental')
-rw-r--r--core/src/main/scala/chisel3/experimental/Analog.scala4
-rw-r--r--core/src/main/scala/chisel3/experimental/Trace.scala69
-rw-r--r--core/src/main/scala/chisel3/experimental/dataview/DataProduct.scala248
-rw-r--r--core/src/main/scala/chisel3/experimental/dataview/DataView.scala239
-rw-r--r--core/src/main/scala/chisel3/experimental/hierarchy/Definition.scala23
-rw-r--r--core/src/main/scala/chisel3/experimental/hierarchy/Hierarchy.scala112
-rw-r--r--core/src/main/scala/chisel3/experimental/hierarchy/Instance.scala54
-rw-r--r--core/src/main/scala/chisel3/experimental/hierarchy/IsInstantiable.scala2
-rw-r--r--core/src/main/scala/chisel3/experimental/hierarchy/LibraryHooks.scala31
-rw-r--r--core/src/main/scala/chisel3/experimental/hierarchy/Lookupable.scala102
-rw-r--r--core/src/main/scala/chisel3/experimental/hierarchy/Underlying.scala14
-rw-r--r--core/src/main/scala/chisel3/experimental/package.scala150
-rw-r--r--core/src/main/scala/chisel3/experimental/verification/package.scala60
13 files changed, 942 insertions, 166 deletions
diff --git a/core/src/main/scala/chisel3/experimental/Analog.scala b/core/src/main/scala/chisel3/experimental/Analog.scala
index 6cca81f5..e94bae2d 100644
--- a/core/src/main/scala/chisel3/experimental/Analog.scala
+++ b/core/src/main/scala/chisel3/experimental/Analog.scala
@@ -27,9 +27,7 @@ import scala.collection.mutable
final class Analog private (private[chisel3] val width: Width) extends Element {
require(width.known, "Since Analog is only for use in BlackBoxes, width must be known")
- override def toString: String = {
- s"Analog$width$bindingToString"
- }
+ override def toString: String = stringAccessor(s"Analog$width")
private[chisel3] override def typeEquivalent(that: Data): Boolean =
that.isInstanceOf[Analog] && this.width == that.width
diff --git a/core/src/main/scala/chisel3/experimental/Trace.scala b/core/src/main/scala/chisel3/experimental/Trace.scala
new file mode 100644
index 00000000..2d965c7b
--- /dev/null
+++ b/core/src/main/scala/chisel3/experimental/Trace.scala
@@ -0,0 +1,69 @@
+package chisel3.experimental
+
+import chisel3.internal.HasId
+import chisel3.{Aggregate, Data, Element, Module}
+import firrtl.AnnotationSeq
+import firrtl.annotations.{Annotation, CompleteTarget, SingleTargetAnnotation}
+import firrtl.transforms.DontTouchAllTargets
+
+/** The util that records the reference map from original [[Data]]/[[Module]] annotated in Chisel and final FIRRTL.
+ * @example
+ * {{{
+ * class Dut extends Module {
+ * val a = WireDefault(Bool())
+ * Trace.traceName(a)
+ * }
+ * val annos = (new ChiselStage).execute(Seq(ChiselGeneratorAnnotation(() => new Dut)))
+ * val dut = annos.collectFirst { case DesignAnnotation(dut) => dut }.get.asInstanceOf[CollideModule]
+ * // 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. */
+ def traceName(x: Module): Unit = {
+ annotate(new ChiselAnnotation {
+ def toFirrtl: Annotation = TraceNameAnnotation(x.toAbsoluteTarget, x.toAbsoluteTarget)
+ })
+ }
+
+ /** Trace a Data name. */
+ def traceName(x: Data): Unit = {
+ x match {
+ case aggregate: Aggregate =>
+ annotate(new ChiselAnnotation {
+ def toFirrtl: Annotation = TraceNameAnnotation(aggregate.toAbsoluteTarget, aggregate.toAbsoluteTarget)
+ })
+ aggregate.getElements.foreach(traceName)
+ case element: Element =>
+ annotate(new ChiselAnnotation {
+ def toFirrtl: Annotation = TraceNameAnnotation(element.toAbsoluteTarget, element.toAbsoluteTarget)
+ })
+ }
+ }
+
+ /** An Annotation that records the original target annotate from Chisel.
+ *
+ * @param target target that should be renamed by [[firrtl.RenameMap]] in the firrtl transforms.
+ * @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 {
+ def duplicate(n: T): Annotation = this.copy(target = n)
+ }
+
+ /** Get [[CompleteTarget]] of the target `x` for `annos`.
+ * This API can be used to find the final reference to a signal or module which is marked by `traceName`
+ */
+ def finalTarget(annos: AnnotationSeq)(x: HasId): Seq[CompleteTarget] = finalTargetMap(annos)
+ .getOrElse(x.toAbsoluteTarget, Seq.empty)
+
+ /** Get all traced signal/module for `annos`
+ * 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)}
+}
diff --git a/core/src/main/scala/chisel3/experimental/dataview/DataProduct.scala b/core/src/main/scala/chisel3/experimental/dataview/DataProduct.scala
index 55dd8505..438f97b8 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, getRecursiveFields}
+import chisel3.{Data, Vec, getRecursiveFields}
import scala.annotation.implicitNotFound
@@ -41,17 +41,24 @@ trait DataProduct[-A] {
def dataSet(a: A): Data => Boolean = dataIterator(a, "").map(_._1).toSet
}
-/** Encapsulating object for automatically provided implementations of [[DataProduct]]
+/** Low priority built-in implementations of [[DataProduct]]
*
- * @note DataProduct implementations provided in this object are available in the implicit scope
+ * @note This trait exists so that `dataDataProduct` can be lower priority than `seqDataProduct` to resolve ambiguity
*/
-object DataProduct {
+sealed trait LowPriorityDataProduct {
+
/** [[DataProduct]] implementation for [[Data]] */
implicit val dataDataProduct: DataProduct[Data] = new DataProduct[Data] {
def dataIterator(a: Data, path: String): Iterator[(Data, String)] =
getRecursiveFields.lazily(a, path).iterator
}
+}
+/** Encapsulating object for built-in implementations of [[DataProduct]]
+ *
+ * @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)] = {
@@ -69,4 +76,237 @@ object DataProduct {
e => e._id > a._id && e._id <= lastId
}
}
+
+ /** [[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]] {
+ def dataIterator(a: Seq[A], path: String): Iterator[(Data, String)] = {
+ val dpa = implicitly[DataProduct[A]]
+ 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)] {
+ def dataIterator(tup: (A, B), path: String): Iterator[(Data, String)] = {
+ val dpa = implicitly[DataProduct[A]]
+ val dpb = implicitly[DataProduct[B]]
+ val (a, b) = tup
+ dpa.dataIterator(a, s"$path._1") ++ dpb.dataIterator(b, s"$path._2")
+ }
+ }
+
+ /** [[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)] =
+ new DataProduct[(A, B, C)] {
+ def dataIterator(tup: (A, B, C), path: String): Iterator[(Data, String)] = {
+ val dpa = implicitly[DataProduct[A]]
+ val dpb = implicitly[DataProduct[B]]
+ val dpc = implicitly[DataProduct[C]]
+ val (a, b, c) = tup
+ dpa.dataIterator(a, s"$path._1") ++ dpb.dataIterator(b, s"$path._2") ++ dpc.dataIterator(c, s"$path._3")
+ }
+ }
+
+ /** [[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)] =
+ new DataProduct[(A, B, C, D)] {
+ def dataIterator(tup: (A, B, C, D), path: String): Iterator[(Data, String)] = {
+ val dpa = implicitly[DataProduct[A]]
+ val dpb = implicitly[DataProduct[B]]
+ val dpc = implicitly[DataProduct[C]]
+ val dpd = implicitly[DataProduct[D]]
+ val (a, b, c, d) = tup
+ dpa.dataIterator(a, s"$path._1") ++
+ dpb.dataIterator(b, s"$path._2") ++
+ dpc.dataIterator(c, s"$path._3") ++
+ dpd.dataIterator(d, s"$path._4")
+ }
+ }
+
+ /** [[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)] =
+ 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]]
+ val dpb = implicitly[DataProduct[B]]
+ val dpc = implicitly[DataProduct[C]]
+ val dpd = implicitly[DataProduct[D]]
+ val dpe = implicitly[DataProduct[E]]
+ val (a, b, c, d, e) = tup
+ dpa.dataIterator(a, s"$path._1") ++
+ dpb.dataIterator(b, s"$path._2") ++
+ dpc.dataIterator(c, s"$path._3") ++
+ dpd.dataIterator(d, s"$path._4") ++
+ dpe.dataIterator(e, s"$path._5")
+ }
+ }
+
+ /** [[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)] =
+ 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]]
+ val dpb = implicitly[DataProduct[B]]
+ val dpc = implicitly[DataProduct[C]]
+ val dpd = implicitly[DataProduct[D]]
+ val dpe = implicitly[DataProduct[E]]
+ val dpf = implicitly[DataProduct[F]]
+ val (a, b, c, d, e, f) = tup
+ dpa.dataIterator(a, s"$path._1") ++
+ dpb.dataIterator(b, s"$path._2") ++
+ dpc.dataIterator(c, s"$path._3") ++
+ dpd.dataIterator(d, s"$path._4") ++
+ dpe.dataIterator(e, s"$path._5") ++
+ dpf.dataIterator(f, s"$path._6")
+ }
+ }
+
+ /** [[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)] =
+ 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]]
+ val dpb = implicitly[DataProduct[B]]
+ val dpc = implicitly[DataProduct[C]]
+ val dpd = implicitly[DataProduct[D]]
+ val dpe = implicitly[DataProduct[E]]
+ val dpf = implicitly[DataProduct[F]]
+ val dpg = implicitly[DataProduct[G]]
+ val (a, b, c, d, e, f, g) = tup
+ dpa.dataIterator(a, s"$path._1") ++
+ dpb.dataIterator(b, s"$path._2") ++
+ dpc.dataIterator(c, s"$path._3") ++
+ dpd.dataIterator(d, s"$path._4") ++
+ dpe.dataIterator(e, s"$path._5") ++
+ dpf.dataIterator(f, s"$path._6") ++
+ dpg.dataIterator(g, s"$path._7")
+ }
+ }
+
+ /** [[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)] =
+ 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]]
+ val dpb = implicitly[DataProduct[B]]
+ val dpc = implicitly[DataProduct[C]]
+ val dpd = implicitly[DataProduct[D]]
+ val dpe = implicitly[DataProduct[E]]
+ val dpf = implicitly[DataProduct[F]]
+ val dpg = implicitly[DataProduct[G]]
+ val dph = implicitly[DataProduct[H]]
+ val (a, b, c, d, e, f, g, h) = tup
+ dpa.dataIterator(a, s"$path._1") ++
+ dpb.dataIterator(b, s"$path._2") ++
+ dpc.dataIterator(c, s"$path._3") ++
+ dpd.dataIterator(d, s"$path._4") ++
+ dpe.dataIterator(e, s"$path._5") ++
+ dpf.dataIterator(f, s"$path._6") ++
+ dpg.dataIterator(g, s"$path._7") ++
+ dph.dataIterator(h, s"$path._8")
+ }
+ }
+
+ /** [[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)] =
+ 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]]
+ val dpb = implicitly[DataProduct[B]]
+ val dpc = implicitly[DataProduct[C]]
+ val dpd = implicitly[DataProduct[D]]
+ val dpe = implicitly[DataProduct[E]]
+ val dpf = implicitly[DataProduct[F]]
+ val dpg = implicitly[DataProduct[G]]
+ val dph = implicitly[DataProduct[H]]
+ val dpi = implicitly[DataProduct[I]]
+ val (a, b, c, d, e, f, g, h, i) = tup
+ dpa.dataIterator(a, s"$path._1") ++
+ dpb.dataIterator(b, s"$path._2") ++
+ dpc.dataIterator(c, s"$path._3") ++
+ dpd.dataIterator(d, s"$path._4") ++
+ dpe.dataIterator(e, s"$path._5") ++
+ dpf.dataIterator(f, s"$path._6") ++
+ dpg.dataIterator(g, s"$path._7") ++
+ dph.dataIterator(h, s"$path._8") ++
+ dpi.dataIterator(i, s"$path._9")
+ }
+ }
+
+ /** [[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)] =
+ 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]]
+ val dpb = implicitly[DataProduct[B]]
+ val dpc = implicitly[DataProduct[C]]
+ val dpd = implicitly[DataProduct[D]]
+ val dpe = implicitly[DataProduct[E]]
+ val dpf = implicitly[DataProduct[F]]
+ val dpg = implicitly[DataProduct[G]]
+ val dph = implicitly[DataProduct[H]]
+ val dpi = implicitly[DataProduct[I]]
+ val dpj = implicitly[DataProduct[J]]
+ val (a, b, c, d, e, f, g, h, i, j) = tup
+ dpa.dataIterator(a, s"$path._1") ++
+ dpb.dataIterator(b, s"$path._2") ++
+ dpc.dataIterator(c, s"$path._3") ++
+ dpd.dataIterator(d, s"$path._4") ++
+ dpe.dataIterator(e, s"$path._5") ++
+ dpf.dataIterator(f, s"$path._6") ++
+ dpg.dataIterator(g, s"$path._7") ++
+ dph.dataIterator(h, s"$path._8") ++
+ dpi.dataIterator(i, s"$path._9") ++
+ dpj.dataIterator(j, s"$path._10")
+ }
+ }
}
diff --git a/core/src/main/scala/chisel3/experimental/dataview/DataView.scala b/core/src/main/scala/chisel3/experimental/dataview/DataView.scala
index caf004c2..c17a5574 100644
--- a/core/src/main/scala/chisel3/experimental/dataview/DataView.scala
+++ b/core/src/main/scala/chisel3/experimental/dataview/DataView.scala
@@ -3,9 +3,12 @@
package chisel3.experimental.dataview
import chisel3._
-import chisel3.internal.sourceinfo.SourceInfo
-import scala.reflect.runtime.universe.WeakTypeTag
+import chisel3.experimental.DataMirror.internal.chiselTypeClone
+import chisel3.experimental.{HWTuple10, HWTuple2, HWTuple3, HWTuple4, HWTuple5, HWTuple6, HWTuple7, HWTuple8, HWTuple9}
+import chisel3.internal.sourceinfo.{SourceInfo, UnlocatableSourceInfo}
+import chisel3.ExplicitCompileOptions.Strict
+import scala.reflect.runtime.universe.WeakTypeTag
import annotation.implicitNotFound
@@ -132,9 +135,241 @@ object DataView {
case (b, a) => f(a, b).map(_.swap)
}
+ // ****************************** Built-in Implementations of DataView ******************************
+ // Sort of the "Standard library" implementations
+
/** All Chisel Data are viewable as their own type */
implicit def identityView[A <: Data](implicit sourceInfo: SourceInfo): DataView[A, A] =
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]] = {
+ // 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
+ { case (s, v) => s.zip(v).map { case (a, b) => a.viewAs[B] -> b } }
+ )
+ }
+
+ /** 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)
+ }
+ )
+
+ /** 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)
+ }
+ )
+
+ /** 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
+ ](
+ 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)
+ }
+ )
+
+ /** 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
+ ](
+ 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 ((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]] */
+ 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,
+ 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
+ ): 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), 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]] */
+ 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
+ ](
+ 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), 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]] */
+ 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
+ ](
+ 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), 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]] */
+ 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
+ ](
+ 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), 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]] */
+ 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
+ ](
+ 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), 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)
+ }
+ )
}
/** Factory methods for constructing non-total [[DataView]]s */
diff --git a/core/src/main/scala/chisel3/experimental/hierarchy/Definition.scala b/core/src/main/scala/chisel3/experimental/hierarchy/Definition.scala
index 0cc3d131..c7b51072 100644
--- a/core/src/main/scala/chisel3/experimental/hierarchy/Definition.scala
+++ b/core/src/main/scala/chisel3/experimental/hierarchy/Definition.scala
@@ -18,13 +18,9 @@ import firrtl.annotations.{IsModule, ModuleTarget}
*
* These definitions are then used to create multiple [[Instance]]s.
*
- * @param cloned The internal representation of the instance, which may be either be directly the object, or a clone of an object
+ * @param underlying The internal representation of the definition, which may be either be directly the object, or a clone of an object
*/
-case class Definition[+A] private[chisel3] (private[chisel3] cloned: Either[A, IsClone[A]]) extends IsLookupable {
- private[chisel3] def proto: A = cloned match {
- case Left(value: A) => value
- case Right(i: IsClone[A]) => i._proto
- }
+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]]
*
@@ -43,20 +39,20 @@ case class Definition[+A] private[chisel3] (private[chisel3] cloned: Either[A, I
lookup.definitionLookup(that, this)
}
- /** Updated by calls to [[apply]], to avoid recloning returned Data's */
- private [chisel3] val cache = HashMap[Data, Data]()
-
-
/** @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_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)
case value: IsInstantiable => None
}
+ override def toDefinition: Definition[A] = this
+ override def toInstance: Instance[A] = new Instance(underlying)
+
+
}
/** Factory methods for constructing [[Definition]]s */
@@ -90,11 +86,12 @@ object Definition extends SourceInfoDoc {
val dynamicContext = new DynamicContext(Nil)
Builder.globalNamespace.copyTo(dynamicContext.globalNamespace)
dynamicContext.inDefinition = true
- val (ir, module) = Builder.build(Module(proto), dynamicContext)
+ val (ir, module) = Builder.build(Module(proto), dynamicContext, false)
Builder.components ++= ir.components
Builder.annotations ++= ir.annotations
module._circuit = Builder.currentModule
dynamicContext.globalNamespace.copyTo(Builder.globalNamespace)
- new Definition(Left(module))
+ new Definition(Proto(module))
}
+
}
diff --git a/core/src/main/scala/chisel3/experimental/hierarchy/Hierarchy.scala b/core/src/main/scala/chisel3/experimental/hierarchy/Hierarchy.scala
new file mode 100644
index 00000000..503e437b
--- /dev/null
+++ b/core/src/main/scala/chisel3/experimental/hierarchy/Hierarchy.scala
@@ -0,0 +1,112 @@
+// SPDX-License-Identifier: Apache-2.0
+
+package chisel3.experimental.hierarchy
+
+import chisel3._
+import scala.collection.mutable.{HashMap, HashSet}
+import scala.reflect.runtime.universe.TypeTag
+import chisel3.internal.BaseModule.IsClone
+import chisel3.experimental.BaseModule
+import _root_.firrtl.annotations.IsModule
+import scala.annotation.implicitNotFound
+
+/** Super-trait for Instance and Definition
+ *
+ * Enables writing functions which are Instance/Definition agnostic
+ */
+sealed trait Hierarchy[+A] {
+ private[chisel3] def underlying: Underlying[A]
+ private[chisel3] def proto: A = underlying match {
+ case Proto(value: A) => value
+ case Clone(i: IsClone[A]) => i.getProto
+ }
+
+ /** Updated by calls to [[_lookup]], to avoid recloning returned Data's */
+ private[chisel3] val cache = HashMap[Data, Data]()
+ private[chisel3] def getInnerDataContext: Option[BaseModule]
+
+ /** Determine whether underlying proto is of type provided.
+ *
+ * @note IMPORTANT: this function requires summoning a TypeTag[B], which will fail if B is an inner class.
+ * @note IMPORTANT: this function IGNORES type parameters, akin to normal type erasure.
+ * @note IMPORTANT: this function relies on Java reflection for underlying proto, but Scala reflection for provided type
+ *
+ * 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 = {
+ val tptag = implicitly[TypeTag[B]]
+ val name = tptag.tpe.toString
+ 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) {
+ clz.split('.').toList match {
+ case "repl" :: "MdocSession" :: app :: rest => s"$app.this." + rest.mkString(".")
+ case other => clz
+ }
+ } else clz
+ }
+ private lazy val superClasses = calculateSuperClasses(proto.getClass())
+ private def calculateSuperClasses(clz: Class[_]): Set[String] = {
+ if(clz != null) {
+ Set(modifyReplString(clz.getCanonicalName())) ++
+ clz.getInterfaces().flatMap(i => calculateSuperClasses(i)) ++
+ calculateSuperClasses(clz.getSuperclass())
+ } else {
+ Set.empty[String]
+ }
+ }
+ 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]]
+ *
+ * Given a selector function (that) which selects a member from the original, return the
+ * corresponding member from the hierarchy.
+ *
+ * Our @instantiable and @public macros generate the calls to this apply method
+ *
+ * By calling this function, we summon the proper Lookupable typeclass from our implicit scope.
+ *
+ * @param that a user-specified lookup function
+ * @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
+
+ /** @return Return the underlying Definition[A] of this Hierarchy[A] */
+ def toDefinition: Definition[A]
+
+ /** @return Convert this Hierarchy[A] as a top-level Instance[A] */
+ def toInstance: Instance[A]
+}
+
+// Used to effectively seal Hierarchy, without requiring Definition and Instance to be in this file.
+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
+ */
+ def toTarget: IsModule = i match {
+ case d: Definition[T] => new Definition.DefinitionBaseModuleExtensions(d).toTarget
+ case i: Instance[T] => new Instance.InstanceBaseModuleExtensions(i).toTarget
+ }
+
+ /** Returns the toAbsoluteTarget of this hierarchy
+ * @return absoluteTarget of this Hierarchy
+ */
+ def toAbsoluteTarget: IsModule = i match {
+ case d: Definition[T] => new Definition.DefinitionBaseModuleExtensions(d).toAbsoluteTarget
+ case i: Instance[T] => new Instance.InstanceBaseModuleExtensions(i).toAbsoluteTarget
+ }
+ }
+}
diff --git a/core/src/main/scala/chisel3/experimental/hierarchy/Instance.scala b/core/src/main/scala/chisel3/experimental/hierarchy/Instance.scala
index 9b17bfce..97b62c23 100644
--- a/core/src/main/scala/chisel3/experimental/hierarchy/Instance.scala
+++ b/core/src/main/scala/chisel3/experimental/hierarchy/Instance.scala
@@ -14,38 +14,29 @@ import firrtl.annotations.IsModule
* Represents a unique instance of type [[A]] which are marked as @instantiable
* Can be created using Instance.apply method.
*
- * @param cloned The internal representation of the instance, which may be either be directly the object, or a clone of an object
+ * @param underlying The internal representation of the instance, which may be either be directly the object, or a clone of an object
*/
-case class Instance[+A] private [chisel3] (private[chisel3] cloned: Either[A, IsClone[A]]) {
-
- /** Returns the original object which is instantiated here.
- * If this is an instance of a clone, return that clone's original proto
- *
- * @return the original object which was instantiated
- */
- private[chisel3] def proto: A = cloned match {
- case Left(value: A) => value
- case Right(i: IsClone[A]) => i._proto
+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
}
/** @return the context of any Data's return from inside the instance */
- private[chisel3] def getInnerDataContext: Option[BaseModule] = cloned match {
- case Left(value: BaseModule) => Some(value)
- case Left(value: IsInstantiable) => None
- case Right(i: BaseModule) => Some(i)
- case Right(i: InstantiableClone[_]) => i._parent
+ 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 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] = cloned match {
- case Left(value: BaseModule) => value._parent
- case Right(i: BaseModule) => i._parent
- case Right(i: InstantiableClone[_]) => i._parent
+ private[chisel3] def getClonedParent: Option[BaseModule] = underlying match {
+ case Proto(value: BaseModule) => value._parent
+ case Clone(i: BaseModule) => i._parent
+ case Clone(i: InstantiableClone[_]) => i.getInnerContext
}
- /** Updated by calls to [[apply]], to avoid recloning returned Data's */
- private [chisel3] val cache = HashMap[Data, Data]()
-
/** Used by Chisel's internal macros. DO NOT USE in your normal Chisel code!!!
* Instead, mark the field you are accessing with [[@public]]
*
@@ -65,7 +56,8 @@ case class Instance[+A] private [chisel3] (private[chisel3] cloned: Either[A, Is
}
/** Returns the definition of this Instance */
- def toDefinition: Definition[A] = new Definition(Left(proto))
+ override def toDefinition: Definition[A] = new Definition(Proto(proto))
+ override def toInstance: Instance[A] = this
}
@@ -75,17 +67,17 @@ object Instance extends SourceInfoDoc {
/** If this is an instance of a Module, returns the toTarget of this instance
* @return target of this instance
*/
- def toTarget: IsModule = i.cloned match {
- case Left(x: BaseModule) => x.getTarget
- case Right(x: IsClone[_] with BaseModule) => x.getTarget
+ def toTarget: IsModule = i.underlying match {
+ case Proto(x: BaseModule) => x.getTarget
+ case Clone(x: IsClone[_] with BaseModule) => x.getTarget
}
/** If this is an instance of a Module, returns the toAbsoluteTarget of this instance
* @return absoluteTarget of this instance
*/
- def toAbsoluteTarget: IsModule = i.cloned match {
- case Left(x) => x.toAbsoluteTarget
- case Right(x: IsClone[_] with BaseModule) => x.toAbsoluteTarget
+ def toAbsoluteTarget: IsModule = i.underlying match {
+ case Proto(x) => x.toAbsoluteTarget
+ case Clone(x: IsClone[_] with BaseModule) => x.toAbsoluteTarget
}
}
@@ -105,7 +97,7 @@ object Instance extends SourceInfoDoc {
val ports = experimental.CloneModuleAsRecord(definition.proto)
val clone = ports._parent.get.asInstanceOf[ModuleClone[T]]
clone._madeFromDefinition = true
- new Instance(Right(clone))
+ new Instance(Clone(clone))
}
}
diff --git a/core/src/main/scala/chisel3/experimental/hierarchy/IsInstantiable.scala b/core/src/main/scala/chisel3/experimental/hierarchy/IsInstantiable.scala
index 26ba0286..4f3c2d42 100644
--- a/core/src/main/scala/chisel3/experimental/hierarchy/IsInstantiable.scala
+++ b/core/src/main/scala/chisel3/experimental/hierarchy/IsInstantiable.scala
@@ -12,6 +12,6 @@ trait IsInstantiable
object IsInstantiable {
implicit class IsInstantiableExtensions[T <: IsInstantiable](i: T) {
- def toInstance: Instance[T] = new Instance(Left(i))
+ def toInstance: Instance[T] = new Instance(Proto(i))
}
}
diff --git a/core/src/main/scala/chisel3/experimental/hierarchy/LibraryHooks.scala b/core/src/main/scala/chisel3/experimental/hierarchy/LibraryHooks.scala
new file mode 100644
index 00000000..c16cc633
--- /dev/null
+++ b/core/src/main/scala/chisel3/experimental/hierarchy/LibraryHooks.scala
@@ -0,0 +1,31 @@
+// SPDX-License-Identifier: Apache-2.0
+
+package chisel3.experimental.hierarchy
+
+import scala.annotation.implicitNotFound
+
+@implicitNotFound("These functions are only for building hierarchy-compatible Chisel libraries! Users beware!")
+// DO NOT extend unless you know what you are doing!!!!!! Not for the casual user!
+trait InsideHierarchyLibraryExtension
+
+// Collection of public functions to give non-core-Chisel libraries the ability to build integrations with
+// the experimental hierarchy package
+object LibraryHooks {
+
+ /** Builds a new instance given a definition and function to create a new instance-specific Underlying, from the
+ * 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] = {
+ new Instance(createUnderlying(definition.underlying))
+ }
+
+ /** Builds a new definition given an Underlying implementation
+ * @note Implicitly requires being inside a Hierarchy Library Extension
+ */
+ def buildDefinition[A](underlying: Underlying[A])(implicit inside: InsideHierarchyLibraryExtension): Definition[A] = {
+ new 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 b9617723..ff4d676c 100644
--- a/core/src/main/scala/chisel3/experimental/hierarchy/Lookupable.scala
+++ b/core/src/main/scala/chisel3/experimental/hierarchy/Lookupable.scala
@@ -19,7 +19,7 @@ import chisel3.internal.{AggregateViewBinding, Builder, ChildBinding, ViewBindin
*/
@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")
-sealed trait Lookupable[-B] {
+trait Lookupable[-B] {
type C // Return type of the lookup
/** Function called to modify the returned value of type B from A, into C
*
@@ -36,9 +36,11 @@ sealed trait Lookupable[-B] {
* @return
*/
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
}
-private[chisel3] object Lookupable {
+object Lookupable {
/** Clones a data and sets its internal references to its parent module to be in a new context.
*
@@ -52,10 +54,10 @@ private[chisel3] object Lookupable {
data._parent match {
case None => data
case Some(parent) =>
- val newParent = cloneModuleToContext(Left(parent), context)
+ val newParent = cloneModuleToContext(Proto(parent), context)
newParent match {
- case Left(p) if p == parent => data
- case Right(m: BaseModule) =>
+ case Proto(p) if p == parent => data
+ case Clone(m: BaseModule) =>
val newChild = data.cloneTypeFull
newChild.setRef(data.getRef, true)
newChild.bind(internal.CrossModuleBinding)
@@ -145,7 +147,7 @@ private[chisel3] object Lookupable {
val result = data.cloneTypeFull
- // We have to lookup the target(s) of the view since they may need to be cloned into the current context
+ // 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 {
@@ -199,51 +201,51 @@ private[chisel3] object Lookupable {
* This function effectively recurses up the parents of module to find whether:
* (1) A parent is already in the context; then we do nothing and return module
* (2) A parent is in a different clone of the context; then we clone all the parents up
- * to that parent and set their parents to be in this cloned context
+ * to that parent and set their parents to be in this underlying context
* (3) A parent has no root; in that case, we do nothing and return the module.
*
- * @param module original or clone to be cloned into a new context
+ * @param module original or clone to be underlying into a new context
* @param context new context
* @return original or clone in the new context
*/
- private[chisel3] def cloneModuleToContext[T <: BaseModule](module: Either[T, IsClone[T]], context: BaseModule)
- (implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Either[T, IsClone[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): Either[A, IsClone[A]] = {
- def clone(x: A, p: Option[BaseModule], name: () => String): Either[A, IsClone[A]] = {
- val newChild = Module.do_apply(new internal.BaseModule.InstanceClone(x, name))
+ def rec[A <: BaseModule](m: A): Underlying[A] = {
+ def clone(x: A, p: Option[BaseModule], name: () => String): Underlying[A] = {
+ val newChild = Module.do_pseudo_apply(new internal.BaseModule.InstanceClone(x, name))
newChild._parent = p
- Right(newChild)
+ Clone(newChild)
}
(m, context) match {
- case (c, ctx) if ctx == c => Left(c)
- case (c, ctx: IsClone[_]) if ctx.isACloneOf(c) => Right(ctx.asInstanceOf[IsClone[A]])
- case (c, ctx) if c._parent.isEmpty => Left(c)
+ 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 (_, _) =>
- cloneModuleToContext(Left(m._parent.get), context) match {
- case Left(p) => Left(m)
- case Right(p: BaseModule) =>
+ cloneModuleToContext(Proto(m._parent.get), context) match {
+ case Proto(p) => Proto(m)
+ case Clone(p: BaseModule) =>
clone(m, Some(p), () => m.instanceName)
}
}
}
module match {
- case Left(m) => rec(m)
- case Right(m: ModuleClone[_]) =>
+ case Proto(m) => rec(m)
+ case Clone(m: ModuleClone[_]) =>
rec(m) match {
- case Left(mx) => Right(mx)
- case Right(i: InstanceClone[_]) =>
- val newChild = Module.do_apply(new InstanceClone(m._proto, () => m.instanceName))
+ case Proto(mx) => Clone(mx)
+ case Clone(i: InstanceClone[_]) =>
+ val newChild = Module.do_pseudo_apply(new InstanceClone(m.getProto, () => m.instanceName))
newChild._parent = i._parent
- Right(newChild)
+ Clone(newChild)
}
- case Right(m: InstanceClone[_]) =>
+ case Clone(m: InstanceClone[_]) =>
rec(m) match {
- case Left(mx) => Right(mx)
- case Right(i: InstanceClone[_]) =>
- val newChild = Module.do_apply(new InstanceClone(m._proto, () => m.instanceName))
+ case Proto(mx) => Clone(mx)
+ case Clone(i: InstanceClone[_]) =>
+ val newChild = Module.do_pseudo_apply(new InstanceClone(m.getProto, () => m.instanceName))
newChild._parent = i._parent
- Right(newChild)
+ Clone(newChild)
}
}
}
@@ -259,14 +261,14 @@ private[chisel3] object Lookupable {
type C = Instance[B]
def definitionLookup[A](that: A => Instance[B], definition: Definition[A]): C = {
val ret = that(definition.proto)
- new Instance(cloneModuleToContext(ret.cloned, definition.getInnerDataContext.get))
+ 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.cloned match {
+ instance.underlying match {
// If instance is just a normal module, no changing of context is necessary
- case Left(_) => new Instance(ret.cloned)
- case Right(_) => new Instance(cloneModuleToContext(ret.cloned, instance.getInnerDataContext.get))
+ case Proto(_) => new Instance(ret.underlying)
+ case Clone(_) => new Instance(cloneModuleToContext(ret.underlying, instance.getInnerDataContext.get))
}
}
}
@@ -275,14 +277,14 @@ private[chisel3] object Lookupable {
type C = Instance[B]
def definitionLookup[A](that: A => B, definition: Definition[A]): C = {
val ret = that(definition.proto)
- new Instance(cloneModuleToContext(Left(ret), definition.getInnerDataContext.get))
+ new Instance(cloneModuleToContext(Proto(ret), definition.getInnerDataContext.get))
}
def instanceLookup[A](that: A => B, instance: Instance[A]): C = {
val ret = that(instance.proto)
- instance.cloned match {
+ instance.underlying match {
// If instance is just a normal module, no changing of context is necessary
- case Left(_) => new Instance(Left(ret))
- case Right(_) => new Instance(cloneModuleToContext(Left(ret), instance.getInnerDataContext.get))
+ case Proto(_) => new Instance(Proto(ret))
+ case Clone(_) => new Instance(cloneModuleToContext(Proto(ret), instance.getInnerDataContext.get))
}
}
}
@@ -299,9 +301,9 @@ private[chisel3] object Lookupable {
}
def instanceLookup[A](that: A => B, instance: Instance[A]): C = {
val ret = that(instance.proto)
- val ioMap: Option[Map[Data, Data]] = instance.cloned match {
- case Right(x: ModuleClone[_]) => Some(x.ioMap)
- case Left(x: BaseModule) => Some(x.getChiselPorts.map { case (_, data) => data -> data }.toMap)
+ 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)) {
@@ -342,15 +344,19 @@ private[chisel3] object Lookupable {
type C = Instance[B]
def definitionLookup[A](that: A => B, definition: Definition[A]): C = {
val ret = that(definition.proto)
- val cloned = new InstantiableClone(ret)
- cloned._parent = definition.getInnerDataContext
- new Instance(Right(cloned))
+ val underlying = new InstantiableClone[B] {
+ val getProto = ret
+ lazy val _innerContext = definition
+ }
+ new Instance(Clone(underlying))
}
def instanceLookup[A](that: A => B, instance: Instance[A]): C = {
val ret = that(instance.proto)
- val cloned = new InstantiableClone(ret)
- cloned._parent = instance.getInnerDataContext
- new Instance(Right(cloned))
+ val underlying = new InstantiableClone[B] {
+ val getProto = ret
+ lazy val _innerContext = instance
+ }
+ new Instance(Clone(underlying))
}
}
diff --git a/core/src/main/scala/chisel3/experimental/hierarchy/Underlying.scala b/core/src/main/scala/chisel3/experimental/hierarchy/Underlying.scala
new file mode 100644
index 00000000..864cc8af
--- /dev/null
+++ b/core/src/main/scala/chisel3/experimental/hierarchy/Underlying.scala
@@ -0,0 +1,14 @@
+// SPDX-License-Identifier: Apache-2.0
+
+package chisel3.experimental.hierarchy
+
+import chisel3.internal.BaseModule.IsClone
+
+/** Represents the underlying implementation of a Definition or Instance */
+sealed trait Underlying[+T]
+
+/** A clone of a real implementation */
+final case class Clone[+T](isClone: IsClone[T]) extends Underlying[T]
+
+/** An actual implementation */
+final case class Proto[+T](proto: T) extends Underlying[T]
diff --git a/core/src/main/scala/chisel3/experimental/package.scala b/core/src/main/scala/chisel3/experimental/package.scala
index 8018159f..5397a1c3 100644
--- a/core/src/main/scala/chisel3/experimental/package.scala
+++ b/core/src/main/scala/chisel3/experimental/package.scala
@@ -2,7 +2,8 @@
package chisel3
-import chisel3.internal.NamedComponent
+import chisel3.ExplicitCompileOptions.Strict
+import chisel3.experimental.DataMirror.internal.chiselTypeClone
import chisel3.internal.sourceinfo.SourceInfo
/** Package for experimental features, which may have their API changed, be removed, etc.
@@ -167,8 +168,149 @@ package object experimental {
// Use to remove prefixes not in provided scope
val noPrefix = chisel3.internal.noPrefix
- /** Base simulation-only component. */
- abstract class BaseSim extends NamedComponent {
- _parent.foreach(_.addId(this))
+ // ****************************** Hardware equivalents of Scala Tuples ******************************
+ // These are intended to be used via DataView
+
+ /** [[Data]] equivalent of Scala's [[Tuple2]]
+ *
+ * Users may not instantiate this class directly. Instead they should use the implicit conversion from `Tuple2` in
+ * `chisel3.experimental.conversions`
+ */
+ 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 _cloneTypeImpl: Bundle = new HWTuple2(chiselTypeClone(_1), chiselTypeClone(_2))
+ }
+
+ /** [[Data]] equivalent of Scala's [[Tuple3]]
+ *
+ * Users may not instantiate this class directly. Instead they should use the implicit conversion from `Tuple3` in
+ * `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) {
+ // 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)
+ )
+ }
+
+ /** [[Data]] equivalent of Scala's [[Tuple4]]
+ *
+ * Users may not instantiate this class directly. Instead they should use the implicit conversion from `Tuple4` in
+ * `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) {
+ // 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)
+ )
+ }
+
+ /** [[Data]] equivalent of Scala's [[Tuple5]]
+ *
+ * Users may not instantiate this class directly. Instead they should use the implicit conversion from `Tuple5` in
+ * `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) {
+ // 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)
+ )
+ }
+
+ /** [[Data]] equivalent of Scala's [[Tuple6]]
+ *
+ * Users may not instantiate this class directly. Instead they should use the implicit conversion from `Tuple6` in
+ * `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) {
+ // 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(_6)
+ )
+ }
+
+ /** [[Data]] equivalent of Scala's [[Tuple7]]
+ *
+ * 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) {
+ // 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)
+ )
+ }
+
+ /** [[Data]] equivalent of Scala's [[Tuple8]]
+ *
+ * Users may not instantiate this class directly. Instead they should use the implicit conversion from `Tuple8` in
+ * `chisel3.experimental.conversions`
+ */
+ final class HWTuple8[
+ +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) {
+ // 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)
+ )
+ }
+
+ /** [[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 HWTuple9[
+ +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) {
+ // 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)
+ )
+ }
+
+
+ /** [[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
+ ] 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) {
+ // 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)
+ )
}
}
diff --git a/core/src/main/scala/chisel3/experimental/verification/package.scala b/core/src/main/scala/chisel3/experimental/verification/package.scala
deleted file mode 100644
index 190083fd..00000000
--- a/core/src/main/scala/chisel3/experimental/verification/package.scala
+++ /dev/null
@@ -1,60 +0,0 @@
-// SPDX-License-Identifier: Apache-2.0
-
-package chisel3.experimental
-
-import chisel3._
-import chisel3.internal.Builder
-import chisel3.internal.firrtl.{Formal, Verification}
-import chisel3.internal.sourceinfo.SourceInfo
-
-package object verification {
-
- object assert {
- /** Named class for assertions. */
- final class Assert(private[chisel3] val predicate: Bool) extends BaseSim
-
-
- def apply(predicate: Bool, msg: String = "")(
- implicit sourceInfo: SourceInfo,
- compileOptions: CompileOptions): Assert = {
- val a = new Assert(predicate)
- when (!Module.reset.asBool) {
- val clock = Module.clock
- Builder.pushCommand(Verification(a, Formal.Assert, sourceInfo, clock.ref, predicate.ref, msg))
- }
- a
- }
- }
-
- object assume {
- /** Named class for assumes. */
- final class Assume(private[chisel3] val predicate: Bool) extends BaseSim
-
- def apply(predicate: Bool, msg: String = "")(
- implicit sourceInfo: SourceInfo,
- compileOptions: CompileOptions): Assume = {
- val a = new Assume(predicate)
- when (!Module.reset.asBool) {
- val clock = Module.clock
- Builder.pushCommand(Verification(a, Formal.Assume, sourceInfo, clock.ref, predicate.ref, msg))
- }
- a
- }
- }
-
- object cover {
- /** Named class for covers. */
- final class Cover(private[chisel3] val predicate: Bool) extends BaseSim
-
- def apply(predicate: Bool, msg: String = "")(
- implicit sourceInfo: SourceInfo,
- compileOptions: CompileOptions): Cover = {
- val clock = Module.clock
- val c = new Cover(predicate)
- when (!Module.reset.asBool) {
- Builder.pushCommand(Verification(c, Formal.Cover, sourceInfo, clock.ref, predicate.ref, msg))
- }
- c
- }
- }
-}