From 6e9740efd138523dca3de5a871104f91d884c476 Mon Sep 17 00:00:00 2001 From: Jiuyang Liu Date: Wed, 22 Sep 2021 02:56:13 +0800 Subject: implement trace API. (#2077) Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>--- .../main/scala/chisel3/experimental/Trace.scala | 69 ++++++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100644 core/src/main/scala/chisel3/experimental/Trace.scala (limited to 'core/src/main/scala/chisel3/experimental') 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)} +} -- cgit v1.2.3 From d1d38bd096fce8b92468720fbedc835ecda40e6b Mon Sep 17 00:00:00 2001 From: Kevin Laeufer Date: Thu, 23 Sep 2021 11:12:26 -0700 Subject: make all verification statements publically available (#2089) --- .../main/scala/chisel3/experimental/package.scala | 5 -- .../experimental/verification/package.scala | 60 ---------------------- 2 files changed, 65 deletions(-) delete mode 100644 core/src/main/scala/chisel3/experimental/verification/package.scala (limited to 'core/src/main/scala/chisel3/experimental') diff --git a/core/src/main/scala/chisel3/experimental/package.scala b/core/src/main/scala/chisel3/experimental/package.scala index 8018159f..0fc79487 100644 --- a/core/src/main/scala/chisel3/experimental/package.scala +++ b/core/src/main/scala/chisel3/experimental/package.scala @@ -166,9 +166,4 @@ package object experimental { val prefix = chisel3.internal.prefix // 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)) - } } 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 - } - } -} -- cgit v1.2.3 From d9722cd96159cd8957cd335d79dbb495260e590d Mon Sep 17 00:00:00 2001 From: Adam Izraelevitz Date: Mon, 25 Oct 2021 15:12:53 -0700 Subject: Add Hierarchy trait (#2204) --- .../experimental/hierarchy/Definition.scala | 12 +--- .../chisel3/experimental/hierarchy/Hierarchy.scala | 67 ++++++++++++++++++++++ .../chisel3/experimental/hierarchy/Instance.scala | 15 +---- 3 files changed, 70 insertions(+), 24 deletions(-) create mode 100644 core/src/main/scala/chisel3/experimental/hierarchy/Hierarchy.scala (limited to 'core/src/main/scala/chisel3/experimental') diff --git a/core/src/main/scala/chisel3/experimental/hierarchy/Definition.scala b/core/src/main/scala/chisel3/experimental/hierarchy/Definition.scala index 0cc3d131..3c4c3c84 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 cloned 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] cloned: Either[A, IsClone[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,10 +39,6 @@ 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 => 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..8dbc5a54 --- /dev/null +++ b/core/src/main/scala/chisel3/experimental/hierarchy/Hierarchy.scala @@ -0,0 +1,67 @@ +// SPDX-License-Identifier: Apache-2.0 + +package chisel3.experimental.hierarchy + +import chisel3._ +import scala.collection.mutable.{HashMap, HashSet} +import scala.reflect.runtime.universe.WeakTypeTag +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 cloned: Either[A, IsClone[A]] + private[chisel3] def proto: A = cloned match { + case Left(value: A) => value + case Right(i: IsClone[A]) => i._proto + } + + /** Updated by calls to [[_lookup]], to avoid recloning returned Data's */ + private[chisel3] val cache = HashMap[Data, Data]() + private[chisel3] def getInnerDataContext: Option[BaseModule] + + + /** 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 hierarhcy. + * + * 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 +} + +// 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..bda52c1b 100644 --- a/core/src/main/scala/chisel3/experimental/hierarchy/Instance.scala +++ b/core/src/main/scala/chisel3/experimental/hierarchy/Instance.scala @@ -16,17 +16,7 @@ import firrtl.annotations.IsModule * * @param cloned 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] cloned: Either[A, IsClone[A]]) extends SealedHierarchy[A] { /** @return the context of any Data's return from inside the instance */ private[chisel3] def getInnerDataContext: Option[BaseModule] = cloned match { @@ -43,9 +33,6 @@ case class Instance[+A] private [chisel3] (private[chisel3] cloned: Either[A, Is case Right(i: InstantiableClone[_]) => i._parent } - /** 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]] * -- cgit v1.2.3 From 5024b706f0638cf3ebbe634b658fa016941e72ac Mon Sep 17 00:00:00 2001 From: Adam Izraelevitz Date: Mon, 25 Oct 2021 16:55:23 -0700 Subject: Bugfix: fix isACloneOf (#2205) --- core/src/main/scala/chisel3/experimental/hierarchy/Lookupable.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'core/src/main/scala/chisel3/experimental') diff --git a/core/src/main/scala/chisel3/experimental/hierarchy/Lookupable.scala b/core/src/main/scala/chisel3/experimental/hierarchy/Lookupable.scala index b9617723..2242c1c4 100644 --- a/core/src/main/scala/chisel3/experimental/hierarchy/Lookupable.scala +++ b/core/src/main/scala/chisel3/experimental/hierarchy/Lookupable.scala @@ -217,7 +217,7 @@ private[chisel3] object Lookupable { } (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: IsClone[_]) if ctx.hasSameProto(c) => Right(ctx.asInstanceOf[IsClone[A]]) case (c, ctx) if c._parent.isEmpty => Left(c) case (_, _) => cloneModuleToContext(Left(m._parent.get), context) match { -- cgit v1.2.3 From 2a68cc0636580db1a5fa98e87727bb3ec870e0bc Mon Sep 17 00:00:00 2001 From: Adam Izraelevitz Date: Wed, 27 Oct 2021 15:51:21 -0700 Subject: Add java reflection to hierarchy (#2209) * Add Hierarchy trait * Add Hierarchy trait * Add Hierarchy scaladoc * Add license * Add isA and tests * Add back isA * Make calculate via lazy val * Apply suggestions from code review Co-authored-by: Megan Wachs * Add shouldNot compile * Update src/test/scala/chiselTests/experimental/hierarchy/InstanceSpec.scala Co-authored-by: Jack Koenig * Made protected vals private Co-authored-by: Megan Wachs Co-authored-by: Jack Koenig Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>--- .../chisel3/experimental/hierarchy/Hierarchy.scala | 31 ++++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) (limited to 'core/src/main/scala/chisel3/experimental') diff --git a/core/src/main/scala/chisel3/experimental/hierarchy/Hierarchy.scala b/core/src/main/scala/chisel3/experimental/hierarchy/Hierarchy.scala index 8dbc5a54..d1ccfb1b 100644 --- a/core/src/main/scala/chisel3/experimental/hierarchy/Hierarchy.scala +++ b/core/src/main/scala/chisel3/experimental/hierarchy/Hierarchy.scala @@ -4,7 +4,7 @@ package chisel3.experimental.hierarchy import chisel3._ import scala.collection.mutable.{HashMap, HashSet} -import scala.reflect.runtime.universe.WeakTypeTag +import scala.reflect.runtime.universe.TypeTag import chisel3.internal.BaseModule.IsClone import chisel3.experimental.BaseModule import _root_.firrtl.annotations.IsModule @@ -25,12 +25,39 @@ sealed trait Hierarchy[+A] { 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) + } + + private lazy val superClasses = calculateSuperClasses(proto.getClass()) + private def calculateSuperClasses(clz: Class[_]): Set[String] = { + if(clz != null) { + Set(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 hierarhcy. + * corresponding member from the hierarchy. * * Our @instantiable and @public macros generate the calls to this apply method * -- cgit v1.2.3 From ef8a9c2148f01e058d2986c9d64f0c35f640790c Mon Sep 17 00:00:00 2001 From: Adam Izraelevitz Date: Wed, 27 Oct 2021 16:52:56 -0700 Subject: Add Select APIs for Hierarchy package (#2210) * Add Hierarchy trait * Add Hierarchy trait * Add Hierarchy scaladoc * Add license * Add isA and tests * Add back isA * Add new Select APIs for hierarchy package * Update scaladoc * Write outlines for tests * Add tests and fixes to new Select functions * Make calculate via lazy val * Apply suggestions from code review Co-authored-by: Megan Wachs * Apply suggestions from code review Co-authored-by: Megan Wachs * Clean up scaladoc * Add shouldNot compile * Apply suggestions from code review Co-authored-by: Megan Wachs * Bugfix all funcs should analyze root too * Add mdoc, bugfix toDefinition * Make func private, add scaladoc * Update src/test/scala/chiselTests/experimental/hierarchy/InstanceSpec.scala Co-authored-by: Jack Koenig * Made protected vals private * Apply suggestions from code review Co-authored-by: Jack Koenig * Address code review comments * Added additional null check Co-authored-by: Megan Wachs Co-authored-by: Jack Koenig --- .../chisel3/experimental/hierarchy/Definition.scala | 5 ++++- .../chisel3/experimental/hierarchy/Hierarchy.scala | 20 +++++++++++++++++++- .../chisel3/experimental/hierarchy/Instance.scala | 7 ++++++- .../chisel3/experimental/hierarchy/Lookupable.scala | 6 +++--- 4 files changed, 32 insertions(+), 6 deletions(-) (limited to 'core/src/main/scala/chisel3/experimental') diff --git a/core/src/main/scala/chisel3/experimental/hierarchy/Definition.scala b/core/src/main/scala/chisel3/experimental/hierarchy/Definition.scala index 3c4c3c84..8f0c88ad 100644 --- a/core/src/main/scala/chisel3/experimental/hierarchy/Definition.scala +++ b/core/src/main/scala/chisel3/experimental/hierarchy/Definition.scala @@ -42,13 +42,16 @@ final case class Definition[+A] private[chisel3] (private[chisel3] cloned: Eithe /** @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(cloned) + } /** Factory methods for constructing [[Definition]]s */ diff --git a/core/src/main/scala/chisel3/experimental/hierarchy/Hierarchy.scala b/core/src/main/scala/chisel3/experimental/hierarchy/Hierarchy.scala index d1ccfb1b..559b0e1a 100644 --- a/core/src/main/scala/chisel3/experimental/hierarchy/Hierarchy.scala +++ b/core/src/main/scala/chisel3/experimental/hierarchy/Hierarchy.scala @@ -40,10 +40,22 @@ sealed trait Hierarchy[+A] { 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(clz.getCanonicalName()) ++ + Set(modifyReplString(clz.getCanonicalName())) ++ clz.getInterfaces().flatMap(i => calculateSuperClasses(i)) ++ calculateSuperClasses(clz.getSuperclass()) } else { @@ -68,6 +80,12 @@ sealed trait Hierarchy[+A] { * @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. diff --git a/core/src/main/scala/chisel3/experimental/hierarchy/Instance.scala b/core/src/main/scala/chisel3/experimental/hierarchy/Instance.scala index bda52c1b..49f882eb 100644 --- a/core/src/main/scala/chisel3/experimental/hierarchy/Instance.scala +++ b/core/src/main/scala/chisel3/experimental/hierarchy/Instance.scala @@ -17,6 +17,10 @@ import firrtl.annotations.IsModule * @param cloned The internal representation of the instance, which may be either be directly the object, or a clone of an object */ final case class Instance[+A] private [chisel3] (private[chisel3] cloned: Either[A, IsClone[A]]) extends SealedHierarchy[A] { + cloned match { + case Left(p: IsClone[_]) => chisel3.internal.throwException("Cannot have a Left 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 { @@ -52,7 +56,8 @@ final case class Instance[+A] private [chisel3] (private[chisel3] cloned: Either } /** Returns the definition of this Instance */ - def toDefinition: Definition[A] = new Definition(Left(proto)) + override def toDefinition: Definition[A] = new Definition(Left(proto)) + override def toInstance: Instance[A] = this } diff --git a/core/src/main/scala/chisel3/experimental/hierarchy/Lookupable.scala b/core/src/main/scala/chisel3/experimental/hierarchy/Lookupable.scala index 2242c1c4..771e2070 100644 --- a/core/src/main/scala/chisel3/experimental/hierarchy/Lookupable.scala +++ b/core/src/main/scala/chisel3/experimental/hierarchy/Lookupable.scala @@ -211,7 +211,7 @@ private[chisel3] object Lookupable { // 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)) + val newChild = Module.do_pseudo_apply(new internal.BaseModule.InstanceClone(x, name)) newChild._parent = p Right(newChild) } @@ -233,7 +233,7 @@ private[chisel3] object Lookupable { rec(m) match { case Left(mx) => Right(mx) case Right(i: InstanceClone[_]) => - val newChild = Module.do_apply(new InstanceClone(m._proto, () => m.instanceName)) + val newChild = Module.do_pseudo_apply(new InstanceClone(m._proto, () => m.instanceName)) newChild._parent = i._parent Right(newChild) } @@ -241,7 +241,7 @@ private[chisel3] object Lookupable { rec(m) match { case Left(mx) => Right(mx) case Right(i: InstanceClone[_]) => - val newChild = Module.do_apply(new InstanceClone(m._proto, () => m.instanceName)) + val newChild = Module.do_pseudo_apply(new InstanceClone(m._proto, () => m.instanceName)) newChild._parent = i._parent Right(newChild) } -- cgit v1.2.3 From 0c43dadf60c1485be348115c20690990f0fea940 Mon Sep 17 00:00:00 2001 From: Adam Izraelevitz Date: Thu, 28 Oct 2021 18:18:34 -0700 Subject: Exposing more APIs from D/I internals (#2220) Exposing more internals of D/I, which are required for supporting D/I with more powerful Chisel libraries: - Exposing IsClone[_] - Exposing InstantiableClone[_] - Gated builders for Instance/Definition - Unsealing Lookupable, with protected accessors for proto and cloned--- .../experimental/hierarchy/Definition.scala | 10 ++- .../chisel3/experimental/hierarchy/Hierarchy.scala | 8 +- .../chisel3/experimental/hierarchy/Instance.scala | 42 ++++----- .../experimental/hierarchy/IsInstantiable.scala | 2 +- .../experimental/hierarchy/LibraryHooks.scala | 31 +++++++ .../experimental/hierarchy/Lookupable.scala | 100 +++++++++++---------- .../experimental/hierarchy/Underlying.scala | 14 +++ 7 files changed, 130 insertions(+), 77 deletions(-) create mode 100644 core/src/main/scala/chisel3/experimental/hierarchy/LibraryHooks.scala create mode 100644 core/src/main/scala/chisel3/experimental/hierarchy/Underlying.scala (limited to 'core/src/main/scala/chisel3/experimental') diff --git a/core/src/main/scala/chisel3/experimental/hierarchy/Definition.scala b/core/src/main/scala/chisel3/experimental/hierarchy/Definition.scala index 8f0c88ad..2ac61807 100644 --- a/core/src/main/scala/chisel3/experimental/hierarchy/Definition.scala +++ b/core/src/main/scala/chisel3/experimental/hierarchy/Definition.scala @@ -18,9 +18,9 @@ import firrtl.annotations.{IsModule, ModuleTarget} * * These definitions are then used to create multiple [[Instance]]s. * - * @param cloned The internal representation of the definition, 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 */ -final case class Definition[+A] private[chisel3] (private[chisel3] cloned: Either[A, IsClone[A]]) extends IsLookupable with SealedHierarchy[A] { +final case class Definition[+A] private[chisel3] (private[chisel3] underlying: Underlying[A]) extends IsLookupable with SealedHierarchy[A] { /** Used by Chisel's internal macros. DO NOT USE in your normal Chisel code!!! * Instead, mark the field you are accessing with [[@public]] * @@ -50,7 +50,8 @@ final case class Definition[+A] private[chisel3] (private[chisel3] cloned: Eithe } override def toDefinition: Definition[A] = this - override def toInstance: Instance[A] = new Instance(cloned) + override def toInstance: Instance[A] = new Instance(underlying) + } @@ -90,6 +91,7 @@ object Definition extends SourceInfoDoc { 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 index 559b0e1a..503e437b 100644 --- a/core/src/main/scala/chisel3/experimental/hierarchy/Hierarchy.scala +++ b/core/src/main/scala/chisel3/experimental/hierarchy/Hierarchy.scala @@ -15,10 +15,10 @@ import scala.annotation.implicitNotFound * Enables writing functions which are Instance/Definition agnostic */ sealed trait Hierarchy[+A] { - private[chisel3] def cloned: Either[A, IsClone[A]] - private[chisel3] def proto: A = cloned match { - case Left(value: A) => value - case Right(i: IsClone[A]) => i._proto + 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 */ diff --git a/core/src/main/scala/chisel3/experimental/hierarchy/Instance.scala b/core/src/main/scala/chisel3/experimental/hierarchy/Instance.scala index 49f882eb..97b62c23 100644 --- a/core/src/main/scala/chisel3/experimental/hierarchy/Instance.scala +++ b/core/src/main/scala/chisel3/experimental/hierarchy/Instance.scala @@ -14,27 +14,27 @@ 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 */ -final case class Instance[+A] private [chisel3] (private[chisel3] cloned: Either[A, IsClone[A]]) extends SealedHierarchy[A] { - cloned match { - case Left(p: IsClone[_]) => chisel3.internal.throwException("Cannot have a Left with a clone!") +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 } /** Used by Chisel's internal macros. DO NOT USE in your normal Chisel code!!! @@ -56,7 +56,7 @@ final case class Instance[+A] private [chisel3] (private[chisel3] cloned: Either } /** Returns the definition of this Instance */ - override def toDefinition: Definition[A] = new Definition(Left(proto)) + override def toDefinition: Definition[A] = new Definition(Proto(proto)) override def toInstance: Instance[A] = this } @@ -67,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 } } @@ -97,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 771e2070..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]] = { + 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.hasSameProto(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_pseudo_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_pseudo_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] -- cgit v1.2.3 From a476329ef7b051aa480903cacd7d62ee46980c84 Mon Sep 17 00:00:00 2001 From: Aditya Naik Date: Tue, 30 Nov 2021 17:45:59 -0800 Subject: Bugfix - definition name index skipping with D/I (#2249) * Bugfix - definition name index skipping with D/I * Add tests to DefinitionSpec * Add failing test * Fix failing test * Update core/src/main/scala/chisel3/internal/Builder.scala Co-authored-by: Jack Koenig * whitespace * revert package private val Co-authored-by: Jack Koenig Co-authored-by: Jack Koenig --- core/src/main/scala/chisel3/experimental/hierarchy/Definition.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'core/src/main/scala/chisel3/experimental') diff --git a/core/src/main/scala/chisel3/experimental/hierarchy/Definition.scala b/core/src/main/scala/chisel3/experimental/hierarchy/Definition.scala index 2ac61807..c7b51072 100644 --- a/core/src/main/scala/chisel3/experimental/hierarchy/Definition.scala +++ b/core/src/main/scala/chisel3/experimental/hierarchy/Definition.scala @@ -86,7 +86,7 @@ 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 -- cgit v1.2.3 From 9dfee489b15642745174d191181ebf6f570db3ca Mon Sep 17 00:00:00 2001 From: Aditya Naik Date: Wed, 1 Dec 2021 16:09:34 -0800 Subject: Refactor Data.toString (#2197) Provides a more intuitive implementation of toString for Data. Utilizes the fact that the compiler plugin provides names earlier than Chisel had in the past so we can accurately guess the name of signals even in the currently elaborating module. Co-authored-by: Megan Wachs Co-authored-by: Jack Koenig --- core/src/main/scala/chisel3/experimental/Analog.scala | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'core/src/main/scala/chisel3/experimental') 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 -- cgit v1.2.3 From 08271081e4af2025fc6c6af97511fd110ef65e5c Mon Sep 17 00:00:00 2001 From: Jack Koenig Date: Wed, 8 Dec 2021 14:21:44 -0800 Subject: Implement DataViews for Seq and Tuple (#2277) * DataProducts for Seq and Tuple2-10 in DataProduct companion object * DataViews for Seq and Tuple 2-10 in DataView companion object * HWTuple2-10 Bundles in chisel3.experimental * Implicit conversions from Seq to Vec and Tuple to HWTuple in chisel3.experimental.conversions--- .../experimental/dataview/DataProduct.scala | 248 ++++++++++++++++++++- .../chisel3/experimental/dataview/DataView.scala | 239 +++++++++++++++++++- .../main/scala/chisel3/experimental/package.scala | 149 ++++++++++++- 3 files changed, 629 insertions(+), 7 deletions(-) (limited to 'core/src/main/scala/chisel3/experimental') 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) + ) + } } -- cgit v1.2.3