summaryrefslogtreecommitdiff
path: root/chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala
diff options
context:
space:
mode:
authorJack Koenig2019-03-29 15:10:13 -0700
committerGitHub2019-03-29 15:10:13 -0700
commit69e8250dd47210cee809c9ae231c1e320d76c084 (patch)
treeaa639ef424141d07adfaadb06712a90ebbe34a14 /chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala
parent0d00420ba2d00a957ace9112ab570fe52abea9d3 (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.scala76
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]]
*