summaryrefslogtreecommitdiff
path: root/core/src/main/scala/chisel3/internal
diff options
context:
space:
mode:
Diffstat (limited to 'core/src/main/scala/chisel3/internal')
-rw-r--r--core/src/main/scala/chisel3/internal/BiConnect.scala9
-rw-r--r--core/src/main/scala/chisel3/internal/MonoConnect.scala30
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)
*