diff options
| author | Aditya Naik | 2021-12-09 11:19:27 -0800 |
|---|---|---|
| committer | GitHub | 2021-12-09 19:19:27 +0000 |
| commit | 3f21bbb52363c3105f6a0ff961fa7a411dd0c7ab (patch) | |
| tree | 51091d93308f2f6f781e47128b1c6f26af2898f2 /core | |
| parent | 849d4a0b7f6f7ea056c5280b9d319dadf5225022 (diff) | |
Better MonoConnect error messages (#2248)
Co-authored-by: Megan Wachs <megan@sifive.com>
Diffstat (limited to 'core')
| -rw-r--r-- | core/src/main/scala/chisel3/Data.scala | 2 | ||||
| -rw-r--r-- | core/src/main/scala/chisel3/internal/MonoConnect.scala | 72 |
2 files changed, 38 insertions, 36 deletions
diff --git a/core/src/main/scala/chisel3/Data.scala b/core/src/main/scala/chisel3/Data.scala index 89908401..d67a3af6 100644 --- a/core/src/main/scala/chisel3/Data.scala +++ b/core/src/main/scala/chisel3/Data.scala @@ -494,7 +494,7 @@ abstract class Data extends HasId with NamedComponent with SourceInfoDoc { } catch { case MonoConnectException(message) => throwException( - s"Connection between sink ($this) and source ($that) failed @$message" + s"Connection between sink ($this) and source ($that) failed @: $message" ) } } else { diff --git a/core/src/main/scala/chisel3/internal/MonoConnect.scala b/core/src/main/scala/chisel3/internal/MonoConnect.scala index 5cbab329..6173fc91 100644 --- a/core/src/main/scala/chisel3/internal/MonoConnect.scala +++ b/core/src/main/scala/chisel3/internal/MonoConnect.scala @@ -36,33 +36,35 @@ import chisel3.internal.sourceinfo.SourceInfo */ private[chisel3] object MonoConnect { + def formatName(data: Data) = s"""${data.earlyName} in ${data.parentNameOpt.getOrElse("(unknown)")}""" + // These are all the possible exceptions that can be thrown. // These are from element-level connection - def UnreadableSourceException = - MonoConnectException(": Source is unreadable from current module.") - def UnwritableSinkException = - MonoConnectException(": Sink is unwriteable by current module.") - def SourceEscapedWhenScopeException = - MonoConnectException(": Source has escaped the scope of the when in which it was constructed.") - def SinkEscapedWhenScopeException = - MonoConnectException(": Sink has escaped the scope of the when in which it was constructed.") + def UnreadableSourceException(sink: Data, source: Data) = + MonoConnectException(s"""${formatName(source)} cannot be read from module ${sink.parentNameOpt.getOrElse("(unknown)")}.""") + def UnwritableSinkException(sink: Data, source: Data) = + MonoConnectException(s"""${formatName(sink)} cannot be written from module ${source.parentNameOpt.getOrElse("(unknown)")}.""") + def SourceEscapedWhenScopeException(source: Data) = + MonoConnectException(s"Source ${formatName(source)} has escaped the scope of the when in which it was constructed.") + def SinkEscapedWhenScopeException(sink: Data) = + MonoConnectException(s"Sink ${formatName(sink)} has escaped the scope of the when in which it was constructed.") def UnknownRelationException = - MonoConnectException(": Sink or source unavailable to current module.") + MonoConnectException("Sink or source unavailable to current module.") // These are when recursing down aggregate types def MismatchedVecException = - MonoConnectException(": Sink and Source are different length Vecs.") + MonoConnectException("Sink and Source are different length Vecs.") def MissingFieldException(field: String) = - MonoConnectException(s": Source Record missing field ($field).") - def MismatchedException(sink: String, source: String) = - MonoConnectException(s": Sink ($sink) and Source ($source) have different types.") + MonoConnectException(s"Source Record missing field ($field).") + def MismatchedException(sink: Data, source: Data) = + MonoConnectException(s"Sink (${sink.cloneType.toString}) and Source (${source.cloneType.toString}) have different types.") def DontCareCantBeSink = - MonoConnectException(": DontCare cannot be a connection sink (LHS)") - def AnalogCantBeMonoSink = - MonoConnectException(": Analog cannot participate in a mono connection (sink - LHS)") - def AnalogCantBeMonoSource = - MonoConnectException(": Analog cannot participate in a mono connection (source - RHS)") - def AnalogMonoConnectionException = - MonoConnectException(": Analog cannot participate in a mono connection (source and sink)") + MonoConnectException("DontCare cannot be a connection sink") + def AnalogCantBeMonoSink(sink: Data) = + MonoConnectException(s"Sink ${formatName(sink)} of type Analog cannot participate in a mono connection (:=)") + def AnalogCantBeMonoSource(source: Data) = + MonoConnectException(s"Source ${formatName(source)} of type Analog cannot participate in a mono connection (:=)") + def AnalogMonoConnectionException(source: Data, sink: Data) = + MonoConnectException(s"Source ${formatName(source)} and sink ${formatName(sink)} of type Analog cannot participate in a mono connection (:=)") def checkWhenVisibility(x: Data): Boolean = { x.topBinding match { @@ -169,13 +171,13 @@ private[chisel3] object MonoConnect { // DontCare as a sink is illegal. case (DontCare, _) => throw DontCareCantBeSink // Analog is illegal in mono connections. - case (_: Analog, _:Analog) => throw AnalogMonoConnectionException + case (_: Analog, _:Analog) => throw AnalogMonoConnectionException(source, sink) // Analog is illegal in mono connections. - case (_: Analog, _) => throw AnalogCantBeMonoSink + case (_: Analog, _) => throw AnalogCantBeMonoSink(sink) // Analog is illegal in mono connections. - case (_, _: Analog) => throw AnalogCantBeMonoSource + case (_, _: Analog) => throw AnalogCantBeMonoSource(source) // Sink and source are different subtypes of data so fail - case (sink, source) => throw MismatchedException(sink.toString, source.toString) + case (sink, source) => throw MismatchedException(sink, source) } // This function (finally) issues the connection operation @@ -196,7 +198,7 @@ private[chisel3] object MonoConnect { val source = reify(_source) // If source has no location, assume in context module // This can occur if is a literal, unbound will error previously - val sink_mod: BaseModule = sink.topBinding.location.getOrElse(throw UnwritableSinkException) + val sink_mod: BaseModule = sink.topBinding.location.getOrElse(throw UnwritableSinkException(sink, source)) val source_mod: BaseModule = source.topBinding.location.getOrElse(context_mod) val sink_parent = Builder.retrieveParent(sink_mod, context_mod).getOrElse(None) @@ -206,11 +208,11 @@ private[chisel3] object MonoConnect { val source_direction = BindingDirection.from(source.topBinding, source.direction) if (!checkWhenVisibility(sink)) { - throw SinkEscapedWhenScopeException + throw SinkEscapedWhenScopeException(sink) } if (!checkWhenVisibility(source)) { - throw SourceEscapedWhenScopeException + throw SourceEscapedWhenScopeException(source) } // CASE: Context is same module that both left node and right node are in @@ -220,7 +222,7 @@ private[chisel3] object MonoConnect { // CURRENT MOD CURRENT MOD case (Output, _) => issueConnect(sink, source) case (Internal, _) => issueConnect(sink, source) - case (Input, _) => throw UnwritableSinkException + case (Input, _) => throw UnwritableSinkException(sink, source) } } @@ -238,11 +240,11 @@ private[chisel3] object MonoConnect { if (!(connectCompileOptions.dontAssumeDirectionality)) { issueConnect(sink, source) } else { - throw UnreadableSourceException + throw UnreadableSourceException(sink, source) } } case (Input, Output) if (!(connectCompileOptions.dontTryConnectionsSwapped)) => issueConnect(source, sink) - case (Input, _) => throw UnwritableSinkException + case (Input, _) => throw UnwritableSinkException(sink, source) } } @@ -253,8 +255,8 @@ private[chisel3] object MonoConnect { // SINK SOURCE // CHILD MOD CURRENT MOD case (Input, _) => issueConnect(sink, source) - case (Output, _) => throw UnwritableSinkException - case (Internal, _) => throw UnwritableSinkException + case (Output, _) => throw UnwritableSinkException(sink, source) + case (Internal, _) => throw UnwritableSinkException(sink, source) } } @@ -268,15 +270,15 @@ private[chisel3] object MonoConnect { // CHILD MOD CHILD MOD case (Input, Input) => issueConnect(sink, source) case (Input, Output) => issueConnect(sink, source) - case (Output, _) => throw UnwritableSinkException + case (Output, _) => throw UnwritableSinkException(sink, source) case (_, Internal) => { if (!(connectCompileOptions.dontAssumeDirectionality)) { issueConnect(sink, source) } else { - throw UnreadableSourceException + throw UnreadableSourceException(sink, source) } } - case (Internal, _) => throw UnwritableSinkException + case (Internal, _) => throw UnwritableSinkException(sink, source) } } |
