diff options
| author | Jack Koenig | 2019-03-29 15:10:13 -0700 |
|---|---|---|
| committer | GitHub | 2019-03-29 15:10:13 -0700 |
| commit | 69e8250dd47210cee809c9ae231c1e320d76c084 (patch) | |
| tree | aa639ef424141d07adfaadb06712a90ebbe34a14 /chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala | |
| parent | 0d00420ba2d00a957ace9112ab570fe52abea9d3 (diff) | |
Ignore empty aggregates elements when binding aggregate direction (#946)
Previously, including an empty aggregate in a Bundle would cause
a MixedDirectionAggregateException because it has no elements and thus
doesn't have a direction
* Add SampleElementBinding for Vec sample elements
* Add ActualDirection.Empty for bound empty aggregates
Diffstat (limited to 'chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala')
| -rw-r--r-- | chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala | 76 |
1 files changed, 37 insertions, 39 deletions
diff --git a/chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala b/chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala index b2f01c2a..7a6b9b56 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala @@ -16,7 +16,7 @@ import chisel3.SourceInfoDoc * of) other Data objects. */ sealed abstract class Aggregate extends Data { - private[chisel3] override def bind(target: Binding, parentDirection: SpecifiedDirection) { // scalastyle:ignore cyclomatic.complexity line.size.limit + private[chisel3] override def bind(target: Binding, parentDirection: SpecifiedDirection) { binding = target val resolvedDirection = SpecifiedDirection.fromParent(parentDirection, specifiedDirection) @@ -25,41 +25,13 @@ sealed abstract class Aggregate extends Data { } // Check that children obey the directionality rules. - val childDirections = getElements.map(_.direction).toSet - direction = if (childDirections == Set()) { // Sadly, Scala can't do set matching - // If empty, use my assigned direction - resolvedDirection match { - case SpecifiedDirection.Unspecified | SpecifiedDirection.Flip => ActualDirection.Unspecified - case SpecifiedDirection.Output => ActualDirection.Output - case SpecifiedDirection.Input => ActualDirection.Input - } - } else if (childDirections == Set(ActualDirection.Unspecified)) { - ActualDirection.Unspecified - } else if (childDirections == Set(ActualDirection.Input)) { - ActualDirection.Input - } else if (childDirections == Set(ActualDirection.Output)) { - ActualDirection.Output - } else if (childDirections subsetOf - Set(ActualDirection.Output, ActualDirection.Input, - ActualDirection.Bidirectional(ActualDirection.Default), - ActualDirection.Bidirectional(ActualDirection.Flipped))) { - resolvedDirection match { - case SpecifiedDirection.Unspecified => ActualDirection.Bidirectional(ActualDirection.Default) - case SpecifiedDirection.Flip => ActualDirection.Bidirectional(ActualDirection.Flipped) - case _ => throw new RuntimeException("Unexpected forced Input / Output") - } - } else { - this match { - // Anything flies in compatibility mode - case t: Record if !t.compileOptions.dontAssumeDirectionality => resolvedDirection match { - case SpecifiedDirection.Unspecified => ActualDirection.Bidirectional(ActualDirection.Default) - case SpecifiedDirection.Flip => ActualDirection.Bidirectional(ActualDirection.Flipped) - case _ => ActualDirection.Bidirectional(ActualDirection.Default) - } - case _ => - val childWithDirections = getElements zip getElements.map(_.direction) - throw Binding.MixedDirectionAggregateException(s"Aggregate '$this' can't have elements that are both directioned and undirectioned: $childWithDirections") // scalastyle:ignore line.size.limit - } + val childDirections = getElements.map(_.direction).toSet - ActualDirection.Empty + direction = ActualDirection.fromChildren(childDirections, resolvedDirection) match { + case Some(dir) => dir + case None => + val childWithDirections = getElements zip getElements.map(_.direction) + throw Binding.MixedDirectionAggregateException( + s"Aggregate '$this' can't have elements that are both directioned and undirectioned: $childWithDirections") } } @@ -164,10 +136,26 @@ sealed class Vec[T <: Data] private[core] (gen: => T, val length: Int) case _ => false } + private[chisel3] override def bind(target: Binding, parentDirection: SpecifiedDirection) { + binding = target + + val resolvedDirection = SpecifiedDirection.fromParent(parentDirection, specifiedDirection) + sample_element.bind(SampleElementBinding(this), resolvedDirection) + for (child <- getElements) { // assume that all children are the same + child.bind(ChildBinding(this), resolvedDirection) + } + + // Note: this differs from the Aggregate.bind behavior on an empty Vec, since this looks at the + // sample element instead of actual elements. + direction = sample_element.direction + } + // Note: the constructor takes a gen() function instead of a Seq to enforce // that all elements must be the same and because it makes FIRRTL generation // simpler. private val self: Seq[T] = Vector.fill(length)(gen) + for ((elt, i) <- self.zipWithIndex) + elt.setRef(this, i) /** * sample_element 'tracks' all changes to the elements. @@ -253,9 +241,6 @@ sealed class Vec[T <: Data] private[core] (gen: => T, val length: Int) override def getElements: Seq[Data] = (0 until length).map(apply(_)) - for ((elt, i) <- self.zipWithIndex) - elt.setRef(this, i) - /** Default "pretty-print" implementation * Analogous to printing a Seq * Results in "Vec(elt0, elt1, ...)" @@ -441,6 +426,19 @@ trait VecLike[T <: Data] extends collection.IndexedSeq[T] with HasId with Source * RTL writers should use [[Bundle]]. See [[Record#elements]] for an example. */ abstract class Record(private[chisel3] implicit val compileOptions: CompileOptions) extends Aggregate { + private[chisel3] override def bind(target: Binding, parentDirection: SpecifiedDirection): Unit = { + try { + super.bind(target, parentDirection) + } catch { // nasty compatibility mode shim, where anything flies + case e: Binding.MixedDirectionAggregateException if !compileOptions.dontAssumeDirectionality => + val resolvedDirection = SpecifiedDirection.fromParent(parentDirection, specifiedDirection) + direction = resolvedDirection match { + case SpecifiedDirection.Unspecified => ActualDirection.Bidirectional(ActualDirection.Default) + case SpecifiedDirection.Flip => ActualDirection.Bidirectional(ActualDirection.Flipped) + case _ => ActualDirection.Bidirectional(ActualDirection.Default) + } + } + } /** The collection of [[Data]] * |
