Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Add DataProduct for Iterables and primitive types #3856

Merged
merged 1 commit into from
Feb 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ trait DataProduct[-A] {

/** Low priority built-in implementations of [[DataProduct]]
*
* @note This trait exists so that `dataDataProduct` can be lower priority than `seqDataProduct` to resolve ambiguity
* @note This trait exists so that `dataDataProduct` can be lower priority than `iterableDataProduct` to resolve ambiguity
*/
sealed trait LowPriorityDataProduct {

Expand All @@ -63,6 +63,25 @@ sealed trait LowPriorityDataProduct {
*/
object DataProduct extends LowPriorityDataProduct {

/** Factory method for constructing [[DataProduct]]s */
def apply[A](f: (A, String) => Iterator[(Data, String)]): DataProduct[A] = new DataProduct[A] {
def dataIterator(a: A, path: String): Iterator[(Data, String)] = f(a, path)
}

/** Factory for constructing [[DataProduct]] for types that do not contain any [[Data]] */
def empty[A]: DataProduct[A] = apply[A] { case _ => Iterator.empty }

// DataProducts for simple primitive types
implicit val charDataProduct: DataProduct[Char] = empty
implicit val stringDataProduct: DataProduct[String] = empty
implicit val intDataProduct: DataProduct[Int] = empty
implicit val byteDataProduct: DataProduct[Byte] = empty
implicit val shortDataProduct: DataProduct[Short] = empty
implicit val longDataProduct: DataProduct[Long] = empty
implicit val bigIntDataProduct: DataProduct[BigInt] = empty
implicit val floatDataProduct: DataProduct[Float] = empty
implicit val doubleDataProduct: DataProduct[Double] = empty

/** [[DataProduct]] implementation for [[BaseModule]] */
implicit val userModuleDataProduct: DataProduct[BaseModule] = new DataProduct[BaseModule] {
def dataIterator(a: BaseModule, path: String): Iterator[(Data, String)] = {
Expand All @@ -82,7 +101,8 @@ object DataProduct extends LowPriorityDataProduct {
}

/** [[DataProduct]] implementation for any `Seq[A]` where `A` has an implementation of `DataProduct`. */
implicit def seqDataProduct[A: DataProduct]: DataProduct[Seq[A]] = new DataProduct[Seq[A]] {
@deprecated("Use iterableDataProduct instead", "Chisel 7.0")
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 {
Expand All @@ -92,6 +112,17 @@ object DataProduct extends LowPriorityDataProduct {
}
}

/** [[DataProduct]] implementation for any `Iterable[A]` where `A` has an implementation of `DataProduct`. */
implicit def iterableDataProduct[A: DataProduct, F[A] <: IterableOnce[A]]: DataProduct[F[A]] = new DataProduct[F[A]] {
def dataIterator(a: F[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 [[scala.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)] = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -514,6 +514,7 @@ object Lookupable {
implicit val lookupShort: SimpleLookupable[Short] = new SimpleLookupable[Short]()
implicit val lookupLong: SimpleLookupable[Long] = new SimpleLookupable[Long]()
implicit val lookupFloat: SimpleLookupable[Float] = new SimpleLookupable[Float]()
implicit val lookupDouble: SimpleLookupable[Double] = new SimpleLookupable[Double]()
implicit val lookupChar: SimpleLookupable[Char] = new SimpleLookupable[Char]()
implicit val lookupString: SimpleLookupable[String] = new SimpleLookupable[String]()
implicit val lookupBoolean: SimpleLookupable[Boolean] = new SimpleLookupable[Boolean]()
Expand Down
39 changes: 39 additions & 0 deletions src/test/scala/chiselTests/experimental/DataView.scala
Original file line number Diff line number Diff line change
Expand Up @@ -552,6 +552,45 @@ class DataViewSpec extends ChiselFlatSpec {
verilog should include("assign z = sel ? b : d;")
}

it should "support primitive types in the view target" in {
class MyBundle(val name: String) extends Bundle {
val x = UInt(8.W)
}
implicit val view: DataView[(UInt, Char, String, Int, Byte, Short, Long, BigInt, Float, Double), MyBundle] =
DataView(
tup => new MyBundle(tup.productIterator.toList.tail.mkString("_")),
_._1 -> _.x
)
class MyModule extends Module {
val in = IO(Input(UInt(8.W)))
val bun = (in, 'a', "b", 0, 1.toByte, 2.toShort, 3L, BigInt(4), 5.0f, 6.0).viewAs[MyBundle]
val out = IO(Output(chiselTypeOf(bun)))
out := bun
bun.name should be("a_b_0_1_2_3_4_5.0_6.0")
}
val chirrtl = ChiselStage.emitCHIRRTL(new MyModule)
chirrtl should include("connect out.x, in")
}

it should "support views of Options" in {
class MyBundle(w: Option[Int]) extends Bundle {
val x = w.map(v => UInt(v.W))
}
implicit val view: DataView[Option[UInt], MyBundle] = DataView.mapping(
opt => new MyBundle(opt.map(_.getWidth)),
{ case (opt, bun) => opt.zip(bun.x).map { case (o, b) => o -> b } }
)
class MyModule extends Module {
val in = IO(Input(UInt(8.W)))
val out1 = IO(Output(new MyBundle(Some(8))))
val out2 = IO(Output(new MyBundle(None)))
out1 := Option(in).viewAs[MyBundle]
out2 := Option.empty[UInt].viewAs[MyBundle]
}
val chirrtl = ChiselStage.emitCHIRRTL(new MyModule)
chirrtl should include("connect out1.x, in")
}

// This example should be turned into a built-in feature
it should "enable viewing Seqs as Vecs" in {

Expand Down
Loading