summaryrefslogtreecommitdiff
path: root/chiselFrontend
diff options
context:
space:
mode:
Diffstat (limited to 'chiselFrontend')
-rw-r--r--chiselFrontend/src/main/scala/chisel3/core/Binding.scala36
-rw-r--r--chiselFrontend/src/main/scala/chisel3/core/Bits.scala2
-rw-r--r--chiselFrontend/src/main/scala/chisel3/core/Data.scala13
3 files changed, 48 insertions, 3 deletions
diff --git a/chiselFrontend/src/main/scala/chisel3/core/Binding.scala b/chiselFrontend/src/main/scala/chisel3/core/Binding.scala
index 5378f3ae..467cb4eb 100644
--- a/chiselFrontend/src/main/scala/chisel3/core/Binding.scala
+++ b/chiselFrontend/src/main/scala/chisel3/core/Binding.scala
@@ -53,6 +53,7 @@ object Binding {
case class BindingException(message: String) extends Exception(message)
def AlreadyBoundException(binding: String) = BindingException(s": Already bound to $binding")
def NotSynthesizableException = BindingException(s": Not bound to synthesizable node, currently only Type description")
+ def MissingIOWrapperException = BindingException(": Missing IO() wrapper")
// This recursively walks down the Data tree to look at all the leaf 'Element's
// Will build up an error string in case something goes wrong
@@ -138,6 +139,29 @@ object Binding {
}
}
}
+
+ /** Diagnose a binding error caused by a missing IO() wrapper.
+ * @param element the element triggering the binding error.
+ * @return true if the element is a member of the module's io but ioDefined is false.
+ */
+ def isMissingIOWrapper(element: Element): Boolean = {
+ element._parent match {
+ case None => false
+ case Some(x: Module) => {
+ // If the IO() wrapper has been executed, it isn't missing.
+ if (x.ioDefined) {
+ false
+ } else {
+ // TODO: We should issue the message only once, and if we get here,
+ // we know the wrapper is missing, whether or not the element is a member of io.
+ // But if it's not an io element, we want to issue the complementary "unbound" error.
+ // Revisit this when we collect error messages instead of throwing exceptions.
+ x.io.flatten.contains(element)
+ }
+ }
+ }
+ }
+
try walkToBinding(
target,
element => element.binding match {
@@ -145,10 +169,16 @@ object Binding {
case binding =>
// The following kludge is an attempt to provide backward compatibility
// It should be done at at higher level.
- if ((forcedModule.compileOptions.requireIOWrap || !elementOfIO(element)))
- throw NotSynthesizableException
- else
+ if ((forcedModule.compileOptions.requireIOWrap || !elementOfIO(element))) {
+ // Generate a better error message if this is a result of a missing IO() wrapper.
+ if (isMissingIOWrapper(element)) {
+ throw MissingIOWrapperException
+ } else {
+ throw NotSynthesizableException
+ }
+ } else {
Binding.bind(element, PortBinder(element._parent.get), "Error: IO")
+ }
}
)
catch {
diff --git a/chiselFrontend/src/main/scala/chisel3/core/Bits.scala b/chiselFrontend/src/main/scala/chisel3/core/Bits.scala
index 00d0cc14..a5d954b6 100644
--- a/chiselFrontend/src/main/scala/chisel3/core/Bits.scala
+++ b/chiselFrontend/src/main/scala/chisel3/core/Bits.scala
@@ -460,6 +460,7 @@ sealed class UInt private[core] (width: Width, lit: Option[ULit] = None)
override def do_<= (that: UInt)(implicit sourceInfo: SourceInfo): Bool = compop(sourceInfo, LessEqOp, that)
override def do_>= (that: UInt)(implicit sourceInfo: SourceInfo): Bool = compop(sourceInfo, GreaterEqOp, that)
+ @deprecated("Use '=/=', which avoids potential precedence problems", "chisel3")
final def != (that: UInt): Bool = macro SourceInfoTransform.thatArg
final def =/= (that: UInt): Bool = macro SourceInfoTransform.thatArg
final def === (that: UInt): Bool = macro SourceInfoTransform.thatArg
@@ -655,6 +656,7 @@ sealed class SInt private (width: Width, lit: Option[SLit] = None)
override def do_<= (that: SInt)(implicit sourceInfo: SourceInfo): Bool = compop(sourceInfo, LessEqOp, that)
override def do_>= (that: SInt)(implicit sourceInfo: SourceInfo): Bool = compop(sourceInfo, GreaterEqOp, that)
+ @deprecated("Use '=/=', which avoids potential precedence problems", "chisel3")
final def != (that: SInt): Bool = macro SourceInfoTransform.thatArg
final def =/= (that: SInt): Bool = macro SourceInfoTransform.thatArg
final def === (that: SInt): Bool = macro SourceInfoTransform.thatArg
diff --git a/chiselFrontend/src/main/scala/chisel3/core/Data.scala b/chiselFrontend/src/main/scala/chisel3/core/Data.scala
index 0e473e7e..86858e5d 100644
--- a/chiselFrontend/src/main/scala/chisel3/core/Data.scala
+++ b/chiselFrontend/src/main/scala/chisel3/core/Data.scala
@@ -173,7 +173,19 @@ abstract class Data extends HasId {
private[core] def width: Width
private[core] def legacyConnect(that: Data)(implicit sourceInfo: SourceInfo): Unit
+ /** cloneType must be defined for any Chisel object extending Data.
+ * It is responsible for constructing a basic copy of the object being cloned.
+ * If cloneType needs to recursively clone elements of an object, it should call
+ * the cloneType methods on those elements.
+ * @return a copy of the object.
+ */
def cloneType: this.type
+
+ /** chiselCloneType is called at the top-level of a clone chain.
+ * It calls the client's cloneType() method to construct a basic copy of the object being cloned,
+ * then performs any fixups required to reconstruct the appropriate core state of the cloned object.
+ * @return a copy of the object with appropriate core state.
+ */
def chiselCloneType: this.type = {
// Call the user-supplied cloneType method
val clone = this.cloneType
@@ -181,6 +193,7 @@ abstract class Data extends HasId {
//TODO(twigg): Do recursively for better error messages
for((clone_elem, source_elem) <- clone.allElements zip this.allElements) {
clone_elem.binding = UnboundBinding(source_elem.binding.direction)
+ Data.setFirrtlDirection(clone_elem, Data.getFirrtlDirection(source_elem))
}
clone
}