diff options
| author | Jack | 2022-11-11 06:53:04 +0000 |
|---|---|---|
| committer | Jack | 2022-11-11 06:53:04 +0000 |
| commit | 3ce953c81f06519351c48277e3474b5720ec07ff (patch) | |
| tree | ac79dcb80d0528c2ae86ca21da4cf424715ab645 /core/src/main/scala/chisel3/experimental | |
| parent | adccde9998c91875e5490cff6d5822ffacc593ed (diff) | |
| parent | c8046636a25474be4c547c6fe9c6d742ea7b1d13 (diff) | |
Merge branch '3.5.x' into 3.5-release
Diffstat (limited to 'core/src/main/scala/chisel3/experimental')
9 files changed, 185 insertions, 24 deletions
diff --git a/core/src/main/scala/chisel3/experimental/Analog.scala b/core/src/main/scala/chisel3/experimental/Analog.scala index a366f0c3..7d89025c 100644 --- a/core/src/main/scala/chisel3/experimental/Analog.scala +++ b/core/src/main/scala/chisel3/experimental/Analog.scala @@ -69,7 +69,8 @@ final class Analog private (private[chisel3] val width: Width) extends Element { } targetTopBinding match { - case _: WireBinding | _: PortBinding => direction = ActualDirection.Bidirectional(ActualDirection.Default) + case _: WireBinding | _: PortBinding | _: ViewBinding | _: AggregateViewBinding => + direction = ActualDirection.Bidirectional(ActualDirection.Default) case x => throwException(s"Analog can only be Ports and Wires, not '$x'") } binding = target diff --git a/core/src/main/scala/chisel3/experimental/Attach.scala b/core/src/main/scala/chisel3/experimental/Attach.scala new file mode 100644 index 00000000..5c9cfe53 --- /dev/null +++ b/core/src/main/scala/chisel3/experimental/Attach.scala @@ -0,0 +1,45 @@ +// SPDX-License-Identifier: Apache-2.0 + +package chisel3.experimental + +import chisel3.RawModule +import chisel3.internal._ +import chisel3.internal.Builder.pushCommand +import chisel3.internal.firrtl._ +import chisel3.internal.sourceinfo.SourceInfo + +object attach { + // Exceptions that can be generated by attach + case class AttachException(message: String) extends ChiselException(message) + def ConditionalAttachException: AttachException = + AttachException(": Conditional attach is not allowed!") + + // Actual implementation + private[chisel3] def impl(elts: Seq[Analog], contextModule: RawModule)(implicit sourceInfo: SourceInfo): Unit = { + if (Builder.whenDepth != 0) throw ConditionalAttachException + + // TODO Check that references are valid and can be attached + + pushCommand(Attach(sourceInfo, elts.map(_.lref))) + } + + /** Create an electrical connection between [[Analog]] components + * + * @param elts The components to attach + * + * @example + * {{{ + * val a1 = Wire(Analog(32.W)) + * val a2 = Wire(Analog(32.W)) + * attach(a1, a2) + * }}} + */ + def apply(elts: Analog*)(implicit sourceInfo: SourceInfo): Unit = { + try { + impl(elts, Builder.forcedUserModule) + } catch { + case AttachException(message) => + throwException(elts.mkString("Attaching (", ", ", s") failed @$message")) + } + } +} diff --git a/core/src/main/scala/chisel3/experimental/OpaqueType.scala b/core/src/main/scala/chisel3/experimental/OpaqueType.scala new file mode 100644 index 00000000..e7a2a15d --- /dev/null +++ b/core/src/main/scala/chisel3/experimental/OpaqueType.scala @@ -0,0 +1,27 @@ +// SPDX-License-Identifier: Apache-2.0 + +package chisel3.experimental + +import chisel3._ + +/** Indicates if this Record represents an "Opaque Type" + * + * Opaque types provide a mechanism for user-defined types + * that do not impose any "boxing" overhead in the emitted FIRRTL and Verilog. + * You can think about an opaque type Record as a box around + * a single element that only exists at Chisel elaboration time. + * Put another way, if this trait is mixed into a Record, + * the Record may only contain a single element with an empty name + * and there will be no `_` in the name for that element in the emitted Verilog. + * + * @see RecordSpec in Chisel's tests for example usage and expected output + */ +trait OpaqueType { self: Record => + + /** If set to true, indicates that this Record is an OpaqueType + * + * Users can override this if they need more dynamic control over the behavior for when + * instances of this type are considered opaque + */ + def opaqueType: Boolean = true +} diff --git a/core/src/main/scala/chisel3/experimental/Trace.scala b/core/src/main/scala/chisel3/experimental/Trace.scala index 4ab615a5..eb2ed46a 100644 --- a/core/src/main/scala/chisel3/experimental/Trace.scala +++ b/core/src/main/scala/chisel3/experimental/Trace.scala @@ -1,7 +1,7 @@ package chisel3.experimental import chisel3.internal.HasId -import chisel3.{Aggregate, Data, Element, Module} +import chisel3.{Aggregate, Data, Element, Module, RawModule} import firrtl.AnnotationSeq import firrtl.annotations.{Annotation, CompleteTarget, SingleTargetAnnotation} import firrtl.transforms.DontTouchAllTargets @@ -22,13 +22,22 @@ import firrtl.transforms.DontTouchAllTargets object Trace { /** Trace a Instance name. */ - def traceName(x: Module): Unit = { + @deprecated("switch to traceNameV2 (until Chisel 3.6)", "3.5.5") + def traceName(x: Module): Unit = traceName(x: RawModule) + + /** Trace a Instance name. */ + @deprecated("switch to traceNameV2 (until Chisel 3.6)", "3.5.5") + def traceName(x: RawModule): Unit = { annotate(new ChiselAnnotation { def toFirrtl: Annotation = TraceNameAnnotation(x.toAbsoluteTarget, x.toAbsoluteTarget) }) } - /** Trace a Data name. */ + /** Trace a Data name. This adds "don't touch" semantics to anything traced. */ + @deprecated( + "switch to traceNameV2 (until Chisel 3.6) and add dontTouch if you want \"don't touch\" behavior", + "3.5.5" + ) def traceName(x: Data): Unit = { x match { case aggregate: Aggregate => @@ -43,7 +52,29 @@ object Trace { } } - /** An Annotation that records the original target annotate from Chisel. + /** Trace an Instance name. */ + def traceNameV2(x: RawModule): Unit = { + annotate(new ChiselAnnotation { + def toFirrtl: Annotation = TraceAnnotation(x.toAbsoluteTarget, x.toAbsoluteTarget) + }) + } + + /** Trace a Data name. This does NOT add "don't touch" semantics to the traced data. If you want this behavior, use an explicit [[chisel3.dontTouch]]. */ + def traceNameV2(x: Data): Unit = { + x match { + case aggregate: Aggregate => + annotate(new ChiselAnnotation { + def toFirrtl: Annotation = TraceAnnotation(aggregate.toAbsoluteTarget, aggregate.toAbsoluteTarget) + }) + aggregate.elementsIterator.foreach(traceNameV2) + case element: Element => + annotate(new ChiselAnnotation { + def toFirrtl: Annotation = TraceAnnotation(element.toAbsoluteTarget, element.toAbsoluteTarget) + }) + } + } + + /** An Annotation that records the original target annotate from Chisel. This adds don't touch behavior. * * @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. @@ -54,6 +85,16 @@ object Trace { def duplicate(n: T): Annotation = this.copy(target = n) } + /** An Annotation that records the original target annotate from Chisel. This does NOT add don't touch behavior. + * + * @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 TraceAnnotation[T <: CompleteTarget](target: T, chiselTarget: T) + extends SingleTargetAnnotation[T] { + 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` */ @@ -65,5 +106,6 @@ object Trace { */ def finalTargetMap(annos: AnnotationSeq): Map[CompleteTarget, Seq[CompleteTarget]] = annos.collect { case TraceNameAnnotation(t, chiselTarget) => chiselTarget -> t + case TraceAnnotation(t, chiselTarget) => chiselTarget -> t }.groupBy(_._1).map { case (k, v) => k -> v.map(_._2) } } diff --git a/core/src/main/scala/chisel3/experimental/dataview/DataView.scala b/core/src/main/scala/chisel3/experimental/dataview/DataView.scala index 7f20964d..cc555b11 100644 --- a/core/src/main/scala/chisel3/experimental/dataview/DataView.scala +++ b/core/src/main/scala/chisel3/experimental/dataview/DataView.scala @@ -592,4 +592,27 @@ object PartialDataView { implicit sourceInfo: SourceInfo ): DataView[T, V] = new DataView[T, V](mkView, mapping, _total = false) + + /** Constructs a non-total [[DataView]] mapping from a [[Bundle]] type to a parent [[Bundle]] type + * + * @param mkView a function constructing an instance `V` from an instance of `T` + * @return the [[DataView]] that enables viewing instances of a [[Bundle]] as instances of a parent type + */ + def supertype[T <: Bundle, V <: Bundle]( + mkView: T => V + )( + implicit ev: SubTypeOf[T, V], + sourceInfo: SourceInfo + ): DataView[T, V] = + mapping[T, V]( + mkView, + { + case (a, b) => + val aElts = a.elements + val bElts = b.elements + val bKeys = bElts.keySet + val keys = aElts.keysIterator.filter(bKeys.contains) + keys.map(k => aElts(k) -> bElts(k)).toSeq + } + ) } diff --git a/core/src/main/scala/chisel3/experimental/dataview/package.scala b/core/src/main/scala/chisel3/experimental/dataview/package.scala index 71ae2d8f..a52e88cf 100644 --- a/core/src/main/scala/chisel3/experimental/dataview/package.scala +++ b/core/src/main/scala/chisel3/experimental/dataview/package.scala @@ -43,24 +43,14 @@ package object dataview { "${A} is not a subtype of ${B}! Did you mean .viewAs[${B}]? " + "Please see https://www.chisel-lang.org/chisel3/docs/cookbooks/dataview" ) - private type SubTypeOf[A, B] = A <:< B + private[dataview] type SubTypeOf[A, B] = A <:< B /** Provides `viewAsSupertype` for subclasses of [[Bundle]] */ implicit class BundleUpcastable[T <: Bundle](target: T) { /** View a [[Bundle]] or [[Record]] as a parent type (upcast) */ def viewAsSupertype[V <: Bundle](proto: V)(implicit ev: SubTypeOf[T, V], sourceInfo: SourceInfo): V = { - implicit val dataView = PartialDataView.mapping[T, V]( - _ => proto, - { - case (a, b) => - val aElts = a.elements - val bElts = b.elements - val bKeys = bElts.keySet - val keys = aElts.keysIterator.filter(bKeys.contains) - keys.map(k => aElts(k) -> bElts(k)).toSeq - } - ) + implicit val dataView = PartialDataView.supertype[T, V](_ => proto) target.viewAs[V] } } diff --git a/core/src/main/scala/chisel3/experimental/hierarchy/Definition.scala b/core/src/main/scala/chisel3/experimental/hierarchy/Definition.scala index 36bf6f87..99eacc7d 100644 --- a/core/src/main/scala/chisel3/experimental/hierarchy/Definition.scala +++ b/core/src/main/scala/chisel3/experimental/hierarchy/Definition.scala @@ -103,7 +103,7 @@ object Definition extends SourceInfoDoc { ): Definition[T] = { val dynamicContext = { val context = Builder.captureContext() - new DynamicContext(Nil, context.throwOnFirstError, context.warnReflectiveNaming) + new DynamicContext(Nil, context.throwOnFirstError, context.warnReflectiveNaming, context.warningsAsErrors) } Builder.globalNamespace.copyTo(dynamicContext.globalNamespace) dynamicContext.inDefinition = true diff --git a/core/src/main/scala/chisel3/experimental/hierarchy/Lookupable.scala b/core/src/main/scala/chisel3/experimental/hierarchy/Lookupable.scala index c83479b0..aa35455d 100644 --- a/core/src/main/scala/chisel3/experimental/hierarchy/Lookupable.scala +++ b/core/src/main/scala/chisel3/experimental/hierarchy/Lookupable.scala @@ -335,11 +335,20 @@ object Lookupable { } def instanceLookup[A](that: A => B, instance: Instance[A]): C = { val ret = that(instance.proto) - val ioMap: Option[Map[Data, Data]] = instance.underlying match { - case Clone(x: ModuleClone[_]) => Some(x.ioMap) - case Proto(x: BaseModule) => Some(x.getChiselPorts.map { case (_, data) => data -> data }.toMap) - case _ => None + + def getIoMap(hierarchy: Hierarchy[_]): Option[Map[Data, Data]] = { + hierarchy.underlying match { + case Clone(x: ModuleClone[_]) => Some(x.ioMap) + case Proto(x: BaseModule) => Some(x.getChiselPorts.map { case (_, data) => data -> data }.toMap) + case Clone(x: InstantiableClone[_]) => getIoMap(x._innerContext) + case Clone(x: InstanceClone[_]) => None + case other => { + Builder.exception(s"Internal Error! Unexpected case where we can't get IO Map: $other") + } + } } + val ioMap = getIoMap(instance) + if (isView(ret)) { cloneViewToContext(ret, instance.cache, ioMap, instance.getInnerDataContext) } else { diff --git a/core/src/main/scala/chisel3/experimental/package.scala b/core/src/main/scala/chisel3/experimental/package.scala index b1d9cae4..39131943 100644 --- a/core/src/main/scala/chisel3/experimental/package.scala +++ b/core/src/main/scala/chisel3/experimental/package.scala @@ -235,9 +235,33 @@ package object experimental { } } - // Use to add a prefix to any component generated in input scope + /** Use to add a prefix to any components generated in the provided scope. + * + * @example {{{ + * + * val x1 = prefix("first") { + * // Anything generated here will be prefixed with "first" + * } + * + * val x2 = prefix(mysignal) { + * // Anything generated here will be prefixed with the name of mysignal + * } + * + * }}} + */ val prefix = chisel3.internal.prefix - // Use to remove prefixes not in provided scope + + /** Use to clear existing prefixes so no signals within the scope are prefixed + * by signals/names outside the scope + * + * @example {{{ + * + * val x1 = prefix("first") { + * // Anything generated here will have no prefix. + * // The result returned from this would *still* be called `x1` however. + * } + * }}} + */ val noPrefix = chisel3.internal.noPrefix // ****************************** Hardware equivalents of Scala Tuples ****************************** |
