summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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/package.scala149
-rw-r--r--docs/src/explanations/dataview.md40
-rw-r--r--src/main/scala/chisel3/experimental/conversions/package.scala128
-rw-r--r--src/test/scala/chiselTests/experimental/DataView.scala102
-rw-r--r--src/test/scala/chiselTests/experimental/DataViewTargetSpec.scala3
-rw-r--r--src/test/scala/chiselTests/experimental/Tuple.scala163
-rw-r--r--src/test/scala/chiselTests/experimental/hierarchy/InstanceSpec.scala2
9 files changed, 946 insertions, 128 deletions
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/package.scala b/core/src/main/scala/chisel3/experimental/package.scala
index 0fc79487..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.
@@ -166,4 +167,150 @@ package object experimental {
val prefix = chisel3.internal.prefix
// Use to remove prefixes not in provided scope
val noPrefix = chisel3.internal.noPrefix
+
+ // ****************************** 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/docs/src/explanations/dataview.md b/docs/src/explanations/dataview.md
index a04bbec7..bb8dbdd1 100644
--- a/docs/src/explanations/dataview.md
+++ b/docs/src/explanations/dataview.md
@@ -10,7 +10,6 @@ _New in Chisel 3.5_
```scala mdoc:invisible
import chisel3._
-import chisel3.stage.ChiselStage.emitVerilog
```
## Introduction
@@ -91,7 +90,7 @@ class MyModule extends RawModule {
Of course, this would result in very different looking Verilog:
```scala mdoc:verilog
-emitVerilog(new MyModule {
+getVerilogString(new MyModule {
override def desiredName = "MyModule"
axi := DontCare // Just to generate Verilog in this stub
})
@@ -147,7 +146,7 @@ class AXIStub extends RawModule {
This will generate Verilog that matches the standard naming convention:
```scala mdoc:verilog
-emitVerilog(new AXIStub)
+getVerilogString(new AXIStub)
```
Note that if both the _Target_ and the _View_ types are subtypes of `Data` (as they are in this example),
@@ -175,7 +174,7 @@ class ConnectionExample extends RawModule {
This results in the corresponding fields being connected in the emitted Verilog:
```scala mdoc:verilog
-emitVerilog(new ConnectionExample)
+getVerilogString(new ConnectionExample)
```
## Other Use Cases
@@ -206,17 +205,6 @@ The issue, is that Chisel primitives like `Mux` and `:=` only operate on subtype
Tuples (as members of the Scala standard library), are not subclasses of `Data`.
`DataView` provides a mechanism to _view_ a `Tuple` as if it were a `Data`:
-<!-- TODO replace this with stdlib import -->
-
-```scala mdoc:invisible
-// ProductDataProduct
-implicit val productDataProduct: DataProduct[Product] = new DataProduct[Product] {
- def dataIterator(a: Product, path: String): Iterator[(Data, String)] = {
- a.productIterator.zipWithIndex.collect { case (d: Data, i) => d -> s"$path._$i" }
- }
-}
-```
-
```scala mdoc
// We need a type to represent the Tuple
class HWTuple2[A <: Data, B <: Data](val _1: A, val _2: B) extends Bundle
@@ -259,16 +247,24 @@ class TupleExample extends RawModule {
```scala mdoc:invisible
// Always emit Verilog to make sure it actually works
-emitVerilog(new TupleExample)
+getVerilogString(new TupleExample)
```
Note that this example ignored `DataProduct` which is another required piece (see [the documentation
about it below](#dataproduct)).
-All of this is slated to be included the Chisel standard library.
+All of this is available to users via a single import:
+```scala mdoc:reset
+import chisel3.experimental.conversions._
+```
## Totality and PartialDataView
+```scala mdoc:reset:invisible
+import chisel3._
+import chisel3.experimental.dataview._
+```
+
A `DataView` is _total_ if all fields of the _Target_ type and all fields of the _View_ type are
included in the mapping.
Chisel will error if a field is accidentally left out from a `DataView`.
@@ -293,7 +289,7 @@ class BadMapping extends Module {
out := in.viewAs[BundleB]
}
// We must run Chisel to see the error
-emitVerilog(new BadMapping)
+getVerilogString(new BadMapping)
```
As that error suggests, if we *want* the view to be non-total, we can use a `PartialDataView`:
@@ -309,7 +305,7 @@ class PartialDataViewModule extends Module {
```
```scala mdoc:verilog
-emitVerilog(new PartialDataViewModule)
+getVerilogString(new PartialDataViewModule)
```
While `PartialDataViews` need not be total for the _Target_, both `PartialDataViews` and `DataViews`
@@ -327,7 +323,7 @@ class PartialDataViewModule2 extends Module {
out.viewAs[BundleA] := in
}
// We must run Chisel to see the error
-emitVerilog(new PartialDataViewModule2)
+getVerilogString(new PartialDataViewModule2)
```
As noted, the mapping must **always** be total for the `View`.
@@ -440,7 +436,7 @@ class FooToBar extends Module {
```
```scala mdoc:verilog
-emitVerilog(new FooToBar)
+getVerilogString(new FooToBar)
```
However, it's possible that some user of `Foo` and `Bar` wants different behavior,
@@ -460,7 +456,7 @@ class FooToBarSwizzled extends Module {
```
```scala mdoc:verilog
-emitVerilog(new FooToBarSwizzled)
+getVerilogString(new FooToBarSwizzled)
```
### DataProduct
diff --git a/src/main/scala/chisel3/experimental/conversions/package.scala b/src/main/scala/chisel3/experimental/conversions/package.scala
new file mode 100644
index 00000000..574f9f96
--- /dev/null
+++ b/src/main/scala/chisel3/experimental/conversions/package.scala
@@ -0,0 +1,128 @@
+
+package chisel3.experimental
+
+import chisel3._
+import chisel3.experimental.dataview._
+import scala.language.implicitConversions
+
+/** Implicit conversions from some Scala standard library types and [[Data]]
+ *
+ * @note As this leans heavily on the experimental [[DataView]] feature, these APIs are experimental and subject to change
+ */
+package object conversions {
+
+ /** Implicit conversion between `Seq` and `Vec` */
+ implicit def seq2vec[A : DataProduct, B <: Data](xs: Seq[A])(implicit dv: DataView[A, B]): Vec[B] =
+ xs.viewAs[Vec[B]]
+
+ /** Implicit conversion between [[Tuple2]] and [[HWTuple2]] */
+ implicit def tuple2hwtuple[T1 : DataProduct, T2 : DataProduct, V1 <: Data, V2 <: Data](
+ tup: (T1, T2)
+ )(
+ implicit v1: DataView[T1, V1], v2: DataView[T2, V2]
+ ): HWTuple2[V1, V2] = {
+ tup.viewAs[HWTuple2[V1, V2]]
+ }
+
+ /** Implicit conversion between [[Tuple3]] and [[HWTuple3]] */
+ implicit def tuple3hwtuple[T1 : DataProduct, T2 : DataProduct, T3 : DataProduct, V1 <: Data, V2 <: Data, V3 <: Data](
+ tup: (T1, T2, T3)
+ )(
+ implicit v1: DataView[T1, V1], v2: DataView[T2, V2], v3: DataView[T3, V3]
+ ): HWTuple3[V1, V2, V3] = {
+ tup.viewAs[HWTuple3[V1, V2, V3]]
+ }
+
+ /** Implicit conversion between [[Tuple4]] and [[HWTuple4]] */
+ implicit def tuple4hwtuple[
+ T1 : DataProduct, T2 : DataProduct, T3 : DataProduct, T4 : DataProduct,
+ V1 <: Data, V2 <: Data, V3 <: Data, V4 <: Data
+ ](
+ tup: (T1, T2, T3, T4)
+ )(
+ implicit v1: DataView[T1, V1], v2: DataView[T2, V2], v3: DataView[T3, V3], v4: DataView[T4, V4]
+ ): HWTuple4[V1, V2, V3, V4] = {
+ tup.viewAs[HWTuple4[V1, V2, V3, V4]]
+ }
+
+ /** Implicit conversion between [[Tuple5]] and [[HWTuple5]] */
+ implicit def tuple5hwtuple[
+ T1 : DataProduct, T2 : DataProduct, T3 : DataProduct, T4 : DataProduct, T5 : DataProduct,
+ V1 <: Data, V2 <: Data, V3 <: Data, V4 <: Data, V5 <: Data
+ ](
+ tup: (T1, T2, T3, T4, T5)
+ )(
+ implicit v1: DataView[T1, V1], v2: DataView[T2, V2], v3: DataView[T3, V3], v4: DataView[T4, V4], v5: DataView[T5, V5]
+ ): HWTuple5[V1, V2, V3, V4, V5] = {
+ tup.viewAs[HWTuple5[V1, V2, V3, V4, V5]]
+ }
+
+ /** Implicit conversion between [[Tuple6]] and [[HWTuple6]] */
+ implicit def tuple6hwtuple[
+ T1 : DataProduct, T2 : DataProduct, T3 : DataProduct, T4 : DataProduct, T5 : DataProduct, T6 : DataProduct,
+ V1 <: Data, V2 <: Data, V3 <: Data, V4 <: Data, V5 <: Data, V6 <: Data
+ ](
+ tup: (T1, T2, T3, T4, T5, T6)
+ )(
+ 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]
+ ): HWTuple6[V1, V2, V3, V4, V5, V6] = {
+ tup.viewAs[HWTuple6[V1, V2, V3, V4, V5, V6]]
+ }
+
+ /** Implicit conversion between [[Tuple7]] and [[HWTuple7]] */
+ implicit def tuple7hwtuple[
+ 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
+ ](
+ tup: (T1, T2, T3, T4, T5, T6, T7)
+ )(
+ 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]
+ ): HWTuple7[V1, V2, V3, V4, V5, V6, V7] = {
+ tup.viewAs[HWTuple7[V1, V2, V3, V4, V5, V6, V7]]
+ }
+
+ /** Implicit conversion between [[Tuple8]] and [[HWTuple8]] */
+ implicit def tuple8hwtuple[
+ 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
+ ](
+ tup: (T1, T2, T3, T4, T5, T6, T7, T8)
+ )(
+ 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]
+ ): HWTuple8[V1, V2, V3, V4, V5, V6, V7, V8] = {
+ tup.viewAs[HWTuple8[V1, V2, V3, V4, V5, V6, V7, V8]]
+ }
+
+ /** Implicit conversion between [[Tuple9]] and [[HWTuple9]] */
+ implicit def tuple9hwtuple[
+ 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
+ ](
+ tup: (T1, T2, T3, T4, T5, T6, T7, T8, T9)
+ )(
+ 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]
+ ): HWTuple9[V1, V2, V3, V4, V5, V6, V7, V8, V9] = {
+ tup.viewAs[HWTuple9[V1, V2, V3, V4, V5, V6, V7, V8, V9]]
+ }
+
+ /** Implicit conversion between [[Tuple10]] and [[HWTuple10]] */
+ implicit def tuple10hwtuple[
+ 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
+ ](
+ tup: (T1, T2, T3, T4, T5, T6, T7, T8, T9, T10)
+ )(
+ 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]
+ ): HWTuple10[V1, V2, V3, V4, V5, V6, V7, V8, V9, V10] = {
+ tup.viewAs[HWTuple10[V1, V2, V3, V4, V5, V6, V7, V8, V9, V10]]
+ }
+}
diff --git a/src/test/scala/chiselTests/experimental/DataView.scala b/src/test/scala/chiselTests/experimental/DataView.scala
index d1620e88..399b0cbc 100644
--- a/src/test/scala/chiselTests/experimental/DataView.scala
+++ b/src/test/scala/chiselTests/experimental/DataView.scala
@@ -5,7 +5,9 @@ package chiselTests.experimental
import chiselTests.ChiselFlatSpec
import chisel3._
import chisel3.experimental.dataview._
+import chisel3.experimental.conversions._
import chisel3.experimental.DataMirror.internal.chiselTypeClone
+import chisel3.experimental.HWTuple2
import chisel3.stage.ChiselStage
import chisel3.util.{Decoupled, DecoupledIO}
@@ -50,69 +52,6 @@ object FlatDecoupledDataView {
implicit val view2 = view.invert(_ => new FlatDecoupled)
}
-// This should become part of Chisel in a later PR
-object Tuple2DataProduct {
- implicit def tuple2DataProduct[A : DataProduct, B : DataProduct] = 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")
- }
- }
-}
-
-// This should become part of Chisel in a later PR
-object HWTuple {
- import Tuple2DataProduct._
-
- class HWTuple2[A <: Data, B <: Data](val _1: A, val _2: B) extends Bundle
-
- implicit def view[T1 : DataProduct, T2 : DataProduct, V1 <: Data, V2 <: Data](
- implicit v1: DataView[T1, V1], v2: DataView[T2, V2]
- ): 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)
- }
- )
-
- implicit def tuple2hwtuple[T1 : DataProduct, T2 : DataProduct, V1 <: Data, V2 <: Data](
- tup: (T1, T2))(implicit v1: DataView[T1, V1], v2: DataView[T2, V2]
- ): HWTuple2[V1, V2] = tup.viewAs[HWTuple2[V1, V2]]
-}
-
-// This should become part of Chisel in a later PR
-object SeqDataProduct {
- // Should we special case Seq[Data]?
- 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]")
- }
- }
- }
-}
-
-object SeqToVec {
- import SeqDataProduct._
-
- // TODO this would need a better way to determine the prototype for the Vec
- implicit def seqVec[A : DataProduct, B <: Data](implicit dv: DataView[A, B]): DataView[Seq[A], Vec[B]] =
- DataView.mapping[Seq[A], Vec[B]](
- xs => Vec(xs.size, chiselTypeClone(xs.head.viewAs[B])), // xs.head is not correct in general
- { case (s, v) => s.zip(v).map { case (a, b) => a.viewAs[B] -> b } }
- )
-
- implicit def seq2Vec[A : DataProduct, B <: Data](xs: Seq[A])(implicit dv: DataView[A, B]): Vec[B] =
- xs.viewAs[Vec[B]]
-}
-
class DataViewSpec extends ChiselFlatSpec {
behavior of "DataView"
@@ -327,15 +266,14 @@ class DataViewSpec extends ChiselFlatSpec {
chirrtl should include ("z.fizz <= b.foo")
}
- // This example should be turned into a built-in feature
- it should "enable implementing \"HardwareTuple\"" in {
- import HWTuple._
-
+ it should "enable using Seq like Data" in {
class MyModule extends Module {
val a, b, c, d = IO(Input(UInt(8.W)))
val sel = IO(Input(Bool()))
val y, z = IO(Output(UInt(8.W)))
- (y, z) := Mux(sel, (a, b), (c, d))
+ // Unclear why the implicit conversion does not work in this case for Seq
+ // That being said, it's easy enough to cast via `.viewAs` with or without
+ Seq(y, z) := Mux(sel, Seq(a, b).viewAs, Seq(c, d).viewAs[Vec[UInt]])
}
// Verilog instead of CHIRRTL because the optimizations make it much prettier
val verilog = ChiselStage.emitVerilog(new MyModule)
@@ -343,25 +281,8 @@ class DataViewSpec extends ChiselFlatSpec {
verilog should include ("assign z = sel ? b : d;")
}
- it should "support nesting of tuples" in {
- import Tuple2DataProduct._
- import HWTuple._
-
- class MyModule extends Module {
- val a, b, c, d = IO(Input(UInt(8.W)))
- val w, x, y, z = IO(Output(UInt(8.W)))
- ((w, x), (y, z)) := ((a, b), (c, d))
- }
- val chirrtl = ChiselStage.emitChirrtl(new MyModule)
- chirrtl should include ("w <= a")
- chirrtl should include ("x <= b")
- chirrtl should include ("y <= c")
- chirrtl should include ("z <= d")
- }
-
// This example should be turned into a built-in feature
it should "enable viewing Seqs as Vecs" in {
- import SeqToVec._
class MyModule extends Module {
val a, b, c = IO(Input(UInt(8.W)))
@@ -376,11 +297,6 @@ class DataViewSpec extends ChiselFlatSpec {
}
it should "support recursive composition of views" in {
- import Tuple2DataProduct._
- import SeqDataProduct._
- import SeqToVec._
- import HWTuple._
-
class MyModule extends Module {
val a, b, c, d = IO(Input(UInt(8.W)))
val w, x, y, z = IO(Output(UInt(8.W)))
@@ -398,10 +314,6 @@ class DataViewSpec extends ChiselFlatSpec {
}
it should "error if you try to dynamically index a Vec view" in {
- import SeqDataProduct._
- import SeqToVec._
- import Tuple2DataProduct._
- import HWTuple._
class MyModule extends Module {
val inA, inB = IO(Input(UInt(8.W)))
@@ -434,7 +346,6 @@ class DataViewSpec extends ChiselFlatSpec {
}
it should "error if the mapping is non-total in the target" in {
- import Tuple2DataProduct._
implicit val dv = DataView[(UInt, UInt), UInt](_ => UInt(), _._1 -> _)
class MyModule extends Module {
val a, b = IO(Input(UInt(8.W)))
@@ -533,7 +444,6 @@ class DataViewSpec extends ChiselFlatSpec {
}
it should "NOT error if the mapping is non-total in the target" in {
- import Tuple2DataProduct._
implicit val dv = PartialDataView[(UInt, UInt), UInt](_ => UInt(), _._2 -> _)
class MyModule extends Module {
val a, b = IO(Input(UInt(8.W)))
diff --git a/src/test/scala/chiselTests/experimental/DataViewTargetSpec.scala b/src/test/scala/chiselTests/experimental/DataViewTargetSpec.scala
index 92091631..a17b0f40 100644
--- a/src/test/scala/chiselTests/experimental/DataViewTargetSpec.scala
+++ b/src/test/scala/chiselTests/experimental/DataViewTargetSpec.scala
@@ -4,8 +4,8 @@ package chiselTests.experimental
import chisel3._
import chisel3.experimental.dataview._
+import chisel3.experimental.conversions._
import chisel3.experimental.{ChiselAnnotation, annotate}
-import chisel3.stage.ChiselStage
import chiselTests.ChiselFlatSpec
object DataViewTargetSpec {
@@ -127,7 +127,6 @@ class DataViewTargetSpec extends ChiselFlatSpec {
}
it should "support annotating views that cannot be mapped to a single ReferenceTarget" in {
- import HWTuple._
class MyBundle extends Bundle {
val a, b = Input(UInt(8.W))
val c, d = Output(UInt(8.W))
diff --git a/src/test/scala/chiselTests/experimental/Tuple.scala b/src/test/scala/chiselTests/experimental/Tuple.scala
new file mode 100644
index 00000000..5f897fbc
--- /dev/null
+++ b/src/test/scala/chiselTests/experimental/Tuple.scala
@@ -0,0 +1,163 @@
+// See LICENSE for license details.
+
+package chiselTests.experimental
+
+import chiselTests.ChiselFlatSpec
+import chisel3._
+import chisel3.experimental.conversions._
+import chisel3.stage.ChiselStage
+
+class TupleSpec extends ChiselFlatSpec {
+
+ behavior of "Tuple"
+
+ it should "enable using Tuple2 like Data" in {
+ class MyModule extends Module {
+ val a, b, c, d = IO(Input(UInt(8.W)))
+ val sel = IO(Input(Bool()))
+ val y, z = IO(Output(UInt(8.W)))
+ (y, z) := Mux(sel, (a, b), (c, d))
+ }
+ // Verilog instead of CHIRRTL because the optimizations make it much prettier
+ val verilog = ChiselStage.emitVerilog(new MyModule)
+ verilog should include ("assign y = sel ? a : c;")
+ verilog should include ("assign z = sel ? b : d;")
+ }
+
+ it should "support nesting of tuples" in {
+ class MyModule extends Module {
+ val a, b, c, d = IO(Input(UInt(8.W)))
+ val w, x, y, z = IO(Output(UInt(8.W)))
+ ((w, x), (y, z)) := ((a, b), (c, d))
+ }
+ val chirrtl = ChiselStage.emitChirrtl(new MyModule)
+ chirrtl should include ("w <= a")
+ chirrtl should include ("x <= b")
+ chirrtl should include ("y <= c")
+ chirrtl should include ("z <= d")
+ }
+
+ it should "enable using Tuple3 like Data" in {
+ class MyModule extends Module {
+ val a, b, c = IO(Input(UInt(8.W)))
+ val f, g, h = IO(Input(UInt(8.W)))
+ val sel = IO(Input(Bool()))
+ val v, w, x = IO(Output(UInt(8.W)))
+ (v, w, x) := Mux(sel, (a, b, c), (f, g, h))
+ }
+ // Verilog instead of CHIRRTL because the optimizations make it much prettier
+ val verilog = ChiselStage.emitVerilog(new MyModule)
+ verilog should include ("assign v = sel ? a : f;")
+ verilog should include ("assign w = sel ? b : g;")
+ verilog should include ("assign x = sel ? c : h;")
+ }
+
+ it should "enable using Tuple4 like Data" in {
+ class MyModule extends Module {
+ val a, b, c, d = IO(Input(UInt(8.W)))
+ val f, g, h, i = IO(Input(UInt(8.W)))
+ val sel = IO(Input(Bool()))
+ val v, w, x, y = IO(Output(UInt(8.W)))
+ (v, w, x, y) := Mux(sel, (a, b, c, d), (f, g, h, i))
+ }
+ // Verilog instead of CHIRRTL because the optimizations make it much prettier
+ val verilog = ChiselStage.emitVerilog(new MyModule)
+ verilog should include ("assign v = sel ? a : f;")
+ verilog should include ("assign w = sel ? b : g;")
+ verilog should include ("assign x = sel ? c : h;")
+ verilog should include ("assign y = sel ? d : i;")
+ }
+
+ it should "enable using Tuple5 like Data" in {
+ class MyModule extends Module {
+ val a0, a1, a2, a3, a4 = IO(Input(UInt(8.W)))
+ val b0, b1, b2, b3, b4 = IO(Input(UInt(8.W)))
+ val sel = IO(Input(Bool()))
+ val z0, z1, z2, z3, z4 = IO(Output(UInt(8.W)))
+ (z0, z1, z2, z3, z4) := Mux(sel, (a0, a1, a2, a3, a4), (b0, b1, b2, b3, b4))
+ }
+ // Verilog instead of CHIRRTL because the optimizations make it much prettier
+ val verilog = ChiselStage.emitVerilog(new MyModule)
+ for (i <- 0 until 5) {
+ verilog should include(s"assign z$i = sel ? a$i : b$i;")
+ }
+ }
+
+ it should "enable using Tuple6 like Data" in {
+ class MyModule extends Module {
+ val a0, a1, a2, a3, a4, a5 = IO(Input(UInt(8.W)))
+ val b0, b1, b2, b3, b4, b5 = IO(Input(UInt(8.W)))
+ val sel = IO(Input(Bool()))
+ val z0, z1, z2, z3, z4, z5 = IO(Output(UInt(8.W)))
+ (z0, z1, z2, z3, z4, z5) := Mux(sel, (a0, a1, a2, a3, a4, a5), (b0, b1, b2, b3, b4, b5))
+ }
+ // Verilog instead of CHIRRTL because the optimizations make it much prettier
+ val verilog = ChiselStage.emitVerilog(new MyModule)
+ for (i <- 0 until 6) {
+ verilog should include(s"assign z$i = sel ? a$i : b$i;")
+ }
+ }
+
+ it should "enable using Tuple7 like Data" in {
+ class MyModule extends Module {
+ val a0, a1, a2, a3, a4, a5, a6 = IO(Input(UInt(8.W)))
+ val b0, b1, b2, b3, b4, b5, b6 = IO(Input(UInt(8.W)))
+ val sel = IO(Input(Bool()))
+ val z0, z1, z2, z3, z4, z5, z6 = IO(Output(UInt(8.W)))
+ (z0, z1, z2, z3, z4, z5, z6) := Mux(sel, (a0, a1, a2, a3, a4, a5, a6), (b0, b1, b2, b3, b4, b5, b6))
+ }
+ // Verilog instead of CHIRRTL because the optimizations make it much prettier
+ val verilog = ChiselStage.emitVerilog(new MyModule)
+ for (i <- 0 until 7) {
+ verilog should include(s"assign z$i = sel ? a$i : b$i;")
+ }
+ }
+
+ it should "enable using Tuple8 like Data" in {
+ class MyModule extends Module {
+ val a0, a1, a2, a3, a4, a5, a6, a7 = IO(Input(UInt(8.W)))
+ val b0, b1, b2, b3, b4, b5, b6, b7 = IO(Input(UInt(8.W)))
+ val sel = IO(Input(Bool()))
+ val z0, z1, z2, z3, z4, z5, z6, z7 = IO(Output(UInt(8.W)))
+ (z0, z1, z2, z3, z4, z5, z6, z7) := Mux(sel, (a0, a1, a2, a3, a4, a5, a6, a7), (b0, b1, b2, b3, b4, b5, b6, b7))
+ }
+ // Verilog instead of CHIRRTL because the optimizations make it much prettier
+ val verilog = ChiselStage.emitVerilog(new MyModule)
+ for (i <- 0 until 8) {
+ verilog should include(s"assign z$i = sel ? a$i : b$i;")
+ }
+ }
+
+ it should "enable using Tuple9 like Data" in {
+ class MyModule extends Module {
+ val a0, a1, a2, a3, a4, a5, a6, a7, a8 = IO(Input(UInt(8.W)))
+ val b0, b1, b2, b3, b4, b5, b6, b7, b8 = IO(Input(UInt(8.W)))
+ val sel = IO(Input(Bool()))
+ val z0, z1, z2, z3, z4, z5, z6, z7, z8 = IO(Output(UInt(8.W)))
+ (z0, z1, z2, z3, z4, z5, z6, z7, z8) :=
+ Mux(sel, (a0, a1, a2, a3, a4, a5, a6, a7, a8), (b0, b1, b2, b3, b4, b5, b6, b7, b8))
+ }
+ // Verilog instead of CHIRRTL because the optimizations make it much prettier
+ val verilog = ChiselStage.emitVerilog(new MyModule)
+ for (i <- 0 until 9) {
+ verilog should include(s"assign z$i = sel ? a$i : b$i;")
+ }
+ }
+
+ it should "enable using Tuple10 like Data" in {
+ class MyModule extends Module {
+ val a0, a1, a2, a3, a4, a5, a6, a7, a8, a9 = IO(Input(UInt(8.W)))
+ val b0, b1, b2, b3, b4, b5, b6, b7, b8, b9 = IO(Input(UInt(8.W)))
+ val sel = IO(Input(Bool()))
+ val z0, z1, z2, z3, z4, z5, z6, z7, z8, z9 = IO(Output(UInt(8.W)))
+ (z0, z1, z2, z3, z4, z5, z6, z7, z8, z9) :=
+ Mux(sel, (a0, a1, a2, a3, a4, a5, a6, a7, a8, a9), (b0, b1, b2, b3, b4, b5, b6, b7, b8, b9))
+ }
+ // Verilog instead of CHIRRTL because the optimizations make it much prettier
+ val verilog = ChiselStage.emitVerilog(new MyModule)
+ for (i <- 0 until 10) {
+ verilog should include(s"assign z$i = sel ? a$i : b$i;")
+ }
+ }
+
+}
diff --git a/src/test/scala/chiselTests/experimental/hierarchy/InstanceSpec.scala b/src/test/scala/chiselTests/experimental/hierarchy/InstanceSpec.scala
index 929e3875..9ceb9b40 100644
--- a/src/test/scala/chiselTests/experimental/hierarchy/InstanceSpec.scala
+++ b/src/test/scala/chiselTests/experimental/hierarchy/InstanceSpec.scala
@@ -629,7 +629,7 @@ class InstanceSpec extends ChiselFunSpec with Utils {
}
it("7.3: should work with DataView + implicit conversion") {
- import chiselTests.experimental.SeqToVec._
+ import chisel3.experimental.conversions._
@instantiable
class MyModule extends RawModule {
private val a = IO(Input(UInt(8.W)))