diff options
Diffstat (limited to 'core/src/main/scala/chisel3/internal')
| -rw-r--r-- | core/src/main/scala/chisel3/internal/BiConnect.scala | 9 | ||||
| -rw-r--r-- | core/src/main/scala/chisel3/internal/MonoConnect.scala | 30 |
2 files changed, 28 insertions, 11 deletions
diff --git a/core/src/main/scala/chisel3/internal/BiConnect.scala b/core/src/main/scala/chisel3/internal/BiConnect.scala index e8fb2361..74376598 100644 --- a/core/src/main/scala/chisel3/internal/BiConnect.scala +++ b/core/src/main/scala/chisel3/internal/BiConnect.scala @@ -227,9 +227,12 @@ private[chisel3] object BiConnect { context_mod: RawModule ): Unit = { // Verify right has no extra fields that left doesn't have - for ((field, right_sub) <- right_r.elements) { - if (!left_r.elements.isDefinedAt(field)) { - if (connectCompileOptions.connectFieldsMustMatch) { + + // For each field in left, descend with right. + // Don't bother doing this check if we don't expect it to necessarily pass. + if (connectCompileOptions.connectFieldsMustMatch) { + for ((field, right_sub) <- right_r.elements) { + if (!left_r.elements.isDefinedAt(field)) { throw MissingLeftFieldException(field) } } diff --git a/core/src/main/scala/chisel3/internal/MonoConnect.scala b/core/src/main/scala/chisel3/internal/MonoConnect.scala index 31364804..4e762a7c 100644 --- a/core/src/main/scala/chisel3/internal/MonoConnect.scala +++ b/core/src/main/scala/chisel3/internal/MonoConnect.scala @@ -322,21 +322,35 @@ private[chisel3] object MonoConnect { else false } - /** Trace flow from child Data to its parent. */ - @tailrec private[chisel3] def traceFlow(currentlyFlipped: Boolean, data: Data, context_mod: RawModule): Boolean = { - import SpecifiedDirection.{Input => SInput, Flip => SFlip} + /** Trace flow from child Data to its parent. + * + * Returns true if, given the context, + * this signal can be a sink when wantsToBeSink = true, + * or if it can be a source when wantsToBeSink = false. + * Always returns true if the Data does not actually correspond + * to a Port. + */ + @tailrec private[chisel3] def traceFlow( + wantToBeSink: Boolean, + currentlyFlipped: Boolean, + data: Data, + context_mod: RawModule + ): Boolean = { val sdir = data.specifiedDirection - val flipped = sdir == SInput || sdir == SFlip + val coercedFlip = sdir == SpecifiedDirection.Input + val coercedAlign = sdir == SpecifiedDirection.Output + val flipped = sdir == SpecifiedDirection.Flip + val traceFlipped = ((flipped ^ currentlyFlipped) || coercedFlip) && (!coercedAlign) data.binding.get match { - case ChildBinding(parent) => traceFlow(flipped ^ currentlyFlipped, parent, context_mod) + case ChildBinding(parent) => traceFlow(wantToBeSink, traceFlipped, parent, context_mod) case PortBinding(enclosure) => val childPort = enclosure != context_mod - childPort ^ flipped ^ currentlyFlipped + wantToBeSink ^ childPort ^ traceFlipped case _ => true } } - def canBeSink(data: Data, context_mod: RawModule): Boolean = traceFlow(true, data, context_mod) - def canBeSource(data: Data, context_mod: RawModule): Boolean = traceFlow(false, data, context_mod) + def canBeSink(data: Data, context_mod: RawModule): Boolean = traceFlow(true, false, data, context_mod) + def canBeSource(data: Data, context_mod: RawModule): Boolean = traceFlow(false, false, data, context_mod) /** Check whether two aggregates can be bulk connected (<=) in FIRRTL. (MonoConnect case) * |
