diff options
| author | mergify[bot] | 2022-04-12 00:09:55 +0000 |
|---|---|---|
| committer | GitHub | 2022-04-12 00:09:55 +0000 |
| commit | 898142ba05b04fb1602b249fd1ae81baa3f47f89 (patch) | |
| tree | 75304868c8e8a43abc79a5e125c51167fccce6b4 /core/src/main/scala/chisel3/experimental/dataview | |
| parent | d766e8f7270579406d54abc9015d494cd199c6ce (diff) | |
Enhance views to [sometimes] support dynamic indexing and implement FlatIO (backport #2476) (#2479)
* Capture 1:1 mappings of Aggregates inside of views
This is implemented by including any corresponding Aggregates from the
DataView.mapping in the AggregateViewBinding.childMap (which is now of
type Map[Data, Data]).
This enables dynamically indexing Vecs that are themselves elements of
larger Aggregates in views when the corresponding element of the view is
a Vec of the same type. It also increases the number of cases where a
single Target can represent part of a view.
(cherry picked from commit 1f6b1ca14ccf86918065073c3f6f3626dd83a68e)
* Add FlatIO API for creating ports from Bundles without a prefix
(cherry picked from commit 772a3a1fe3b9372b7c2d7cd2d424b2adcd633cdb)
* [docs] Add FlatIO to the general cookbook
(cherry picked from commit b4159641350f238f0f899b69954142ce8ee11544)
Co-authored-by: Jack Koenig <koenig@sifive.com>
Diffstat (limited to 'core/src/main/scala/chisel3/experimental/dataview')
| -rw-r--r-- | core/src/main/scala/chisel3/experimental/dataview/package.scala | 55 |
1 files changed, 29 insertions, 26 deletions
diff --git a/core/src/main/scala/chisel3/experimental/dataview/package.scala b/core/src/main/scala/chisel3/experimental/dataview/package.scala index 891ecb81..c583c516 100644 --- a/core/src/main/scala/chisel3/experimental/dataview/package.scala +++ b/core/src/main/scala/chisel3/experimental/dataview/package.scala @@ -97,11 +97,16 @@ package object dataview { val targetContains: Data => Boolean = implicitly[DataProduct[T]].dataSet(target) // Resulting bindings for each Element of the View - val childBindings = + // Kept separate from Aggregates for totality checking + val elementBindings = new mutable.HashMap[Data, mutable.ListBuffer[Element]] ++ viewFieldLookup.view.collect { case (elt: Element, _) => elt } .map(_ -> new mutable.ListBuffer[Element]) + // Record any Aggregates that correspond 1:1 for reification + // Using Data instead of Aggregate to avoid unnecessary checks + val aggregateMappings = mutable.ArrayBuffer.empty[(Data, Data)] + def viewFieldName(d: Data): String = viewFieldLookup.get(d).map(_ + " ").getOrElse("") + d.toString @@ -130,7 +135,7 @@ package object dataview { s"View field $fieldName has width ${vwidth} that is incompatible with target value $tex's width ${twidth}" ) } - childBindings(vex) += tex + elementBindings(vex) += tex } mapping.foreach { @@ -145,7 +150,7 @@ package object dataview { } getMatchedFields(aa, ba).foreach { case (aelt: Element, belt: Element) => onElt(aelt, belt) - case _ => // Ignore matching of Aggregates + case (t, v) => aggregateMappings += (v -> t) } } @@ -155,7 +160,7 @@ package object dataview { val targetSeen: Option[mutable.Set[Data]] = if (total) Some(mutable.Set.empty[Data]) else None - val resultBindings = childBindings.map { + val elementResult = elementBindings.map { case (data, targets) => val targetsx = targets match { case collection.Seq(target: Element) => target @@ -183,23 +188,25 @@ package object dataview { } view match { - case elt: Element => view.bind(ViewBinding(resultBindings(elt))) + case elt: Element => view.bind(ViewBinding(elementResult(elt))) case agg: Aggregate => - // We record total Data mappings to provide a better .toTarget - val topt = target match { - case d: Data if total => Some(d) + // Don't forget the potential mapping of the view to the target! + target match { + case d: Data if total => + aggregateMappings += (agg -> d) case _ => - // Record views that don't have the simpler .toTarget for later renaming - Builder.unnamedViews += view - None } - // TODO We must also record children as unnamed, some could be namable but this requires changes to the Binding + + val fullResult = elementResult ++ aggregateMappings + + // We need to record any Aggregates that don't have a 1-1 mapping (including the view + // itself) getRecursiveFields.lazily(view, "_").foreach { - case (agg: Aggregate, _) if agg != view => - Builder.unnamedViews += agg + case (unnamed: Aggregate, _) if !fullResult.contains(unnamed) => + Builder.unnamedViews += unnamed case _ => // Do nothing } - agg.bind(AggregateViewBinding(resultBindings, topt)) + agg.bind(AggregateViewBinding(fullResult)) } } @@ -208,8 +215,8 @@ package object dataview { private def unfoldView(elt: Element): LazyList[Element] = { def rec(e: Element): LazyList[Element] = e.topBindingOpt match { case Some(ViewBinding(target)) => target #:: rec(target) - case Some(AggregateViewBinding(mapping, _)) => - val target = mapping(e) + case Some(avb: AggregateViewBinding) => + val target = avb.lookup(e).get target #:: rec(target) case Some(_) | None => LazyList.empty } @@ -246,15 +253,11 @@ package object dataview { */ private[chisel3] def reifySingleData(data: Data): Option[Data] = { val candidate: Option[Data] = - data.binding.collect { // First check if this is a total mapping of an Aggregate - case AggregateViewBinding(_, Some(t)) => t - }.orElse { // Otherwise look via top binding - data.topBindingOpt match { - case None => None - case Some(ViewBinding(target)) => Some(target) - case Some(AggregateViewBinding(lookup, _)) => lookup.get(data) - case Some(_) => None - } + data.topBindingOpt match { + case None => None + case Some(ViewBinding(target)) => Some(target) + case Some(AggregateViewBinding(lookup)) => lookup.get(data) + case Some(_) => None } candidate.flatMap { d => // Candidate may itself be a view, keep tracing in those cases |
