summaryrefslogtreecommitdiff
path: root/chiselFrontend/src/main
diff options
context:
space:
mode:
authorJim Lawson2016-08-16 11:59:20 -0700
committerJim Lawson2016-08-17 13:41:43 -0700
commitf41f2533c55e506f7d5bf2ee0198de4d9a3dbea3 (patch)
tree4a9786dd4e468d9517517603b06b123e1e35b44f /chiselFrontend/src/main
parenta264157a47f56216cebf2d98c1c8118c344dad5f (diff)
Reduce rocket-chip elaboration errors.
Diffstat (limited to 'chiselFrontend/src/main')
-rw-r--r--chiselFrontend/src/main/scala/chisel3/core/BiConnect.scala24
-rw-r--r--chiselFrontend/src/main/scala/chisel3/core/Binder.scala3
-rw-r--r--chiselFrontend/src/main/scala/chisel3/core/Binding.scala33
-rw-r--r--chiselFrontend/src/main/scala/chisel3/core/Module.scala14
-rw-r--r--chiselFrontend/src/main/scala/chisel3/core/MonoConnect.scala2
-rw-r--r--chiselFrontend/src/main/scala/chisel3/core/Reg.scala4
-rw-r--r--chiselFrontend/src/main/scala/chisel3/internal/CompileOptions.scala6
7 files changed, 65 insertions, 21 deletions
diff --git a/chiselFrontend/src/main/scala/chisel3/core/BiConnect.scala b/chiselFrontend/src/main/scala/chisel3/core/BiConnect.scala
index 71de50f6..b7fd65a5 100644
--- a/chiselFrontend/src/main/scala/chisel3/core/BiConnect.scala
+++ b/chiselFrontend/src/main/scala/chisel3/core/BiConnect.scala
@@ -166,8 +166,28 @@ object BiConnect {
case (Some(Output), None) => issueConnectR2L(left, right)
case (None, Some(Input)) => issueConnectR2L(left, right)
- case (Some(Input), Some(Input)) => throw BothDriversException
- case (Some(Output), Some(Output)) => throw NeitherDriverException
+ case (Some(Input), Some(Input)) => {
+ if (compileOptions.portDeterminesDirection)
+ (left.binding, right.binding) match {
+ case (PortBinding(_, _), PortBinding(_, _)) => throw BothDriversException
+ case (PortBinding(_, _), _) => issueConnectL2R(left, right)
+ case (_, PortBinding(_, _)) => issueConnectR2L(left, right)
+ case _ => throw BothDriversException
+ } else {
+ throw BothDriversException
+ }
+ }
+ case (Some(Output), Some(Output)) => {
+ if (compileOptions.portDeterminesDirection)
+ (left.binding, right.binding) match {
+ case (PortBinding(_, _), PortBinding(_, _)) => throw BothDriversException
+ case (PortBinding(_, _), _) => issueConnectR2L(left, right)
+ case (_, PortBinding(_, _)) => issueConnectL2R(left, right)
+ case _ => throw BothDriversException
+ } else {
+ throw BothDriversException
+ }
+ }
case (None, None) => throw UnknownDriverException
}
}
diff --git a/chiselFrontend/src/main/scala/chisel3/core/Binder.scala b/chiselFrontend/src/main/scala/chisel3/core/Binder.scala
index c7346dce..08c0519e 100644
--- a/chiselFrontend/src/main/scala/chisel3/core/Binder.scala
+++ b/chiselFrontend/src/main/scala/chisel3/core/Binder.scala
@@ -58,7 +58,8 @@ case class RegBinder(enclosure: Module) extends Binder[RegBinding] {
def apply(in: UnboundBinding) = RegBinding(enclosure)
}
+// Notice how WireBinder uses the direction of the UnboundNode
case class WireBinder(enclosure: Module) extends Binder[WireBinding] {
- def apply(in: UnboundBinding) = WireBinding(enclosure)
+ def apply(in: UnboundBinding) = WireBinding(enclosure, in.direction)
}
diff --git a/chiselFrontend/src/main/scala/chisel3/core/Binding.scala b/chiselFrontend/src/main/scala/chisel3/core/Binding.scala
index 75a80e4f..555ba4d5 100644
--- a/chiselFrontend/src/main/scala/chisel3/core/Binding.scala
+++ b/chiselFrontend/src/main/scala/chisel3/core/Binding.scala
@@ -1,5 +1,7 @@
package chisel3.core
+import chisel3.internal.Builder.compileOptions
+
/**
* The purpose of a Binding is to indicate what type of hardware 'entity' a
* specific Data's leaf Elements is actually bound to. All Data starts as being
@@ -88,6 +90,8 @@ object Binding {
case unbound @ UnboundBinding(_) => {
element.binding = binder(unbound)
}
+ // If autoIOWrap is enabled and we're rebinding a PortBinding, just ignore the rebinding.
+ case portBound @ PortBinding(_, _) if (compileOptions.autoIOWrap && binder.isInstanceOf[PortBinder]) =>
case binding => throw AlreadyBoundException(binding.toString)
}
)
@@ -113,15 +117,24 @@ object Binding {
// Excepts if any root element is unbound and thus not on the hardware graph
def checkSynthesizable(target: Data, error_prelude: String): Unit = {
- // This is called is we support autoIOWrap
- def elementOfIO(element: Data): Boolean = {
+ // This is called if we support autoIOWrap
+ def elementOfIO(element: Element): Boolean = {
element._parent match {
case None => false
case Some(x: Module) => {
- // io.flatten eliminates Clock elements, so we need to use io.allElements
- val ports = x.io.allElements
- val isIOElement = ports.contains(element) || element == x.clock || element == x.reset
- isIOElement
+ // Have we defined the IO ports for this module? If not, do so now.
+ if (!x.ioDefined) {
+ x.computePorts
+ element.binding match {
+ case SynthesizableBinding() => true
+ case _ => false
+ }
+ } else {
+ // io.flatten eliminates Clock elements, so we need to use io.allElements
+ val ports = x.io.allElements
+ val isIOElement = ports.contains(element) || element == x.clock || element == x.reset
+ isIOElement
+ }
}
}
}
@@ -132,7 +145,7 @@ object Binding {
case binding =>
// The following kludge is an attempt to provide backward compatibility
// It should be done at at higher level.
- if (!(autoIOWrap && elementOfIO(element)))
+ if (!(compileOptions.autoIOWrap && elementOfIO(element)))
throw NotSynthesizableException
else
Binding.bind(element, PortBinder(element._parent.get), "Error: IO")
@@ -142,8 +155,6 @@ object Binding {
case BindingException(message) => throw BindingException(s"$error_prelude$message")
}
}
- // This should be configure by options in Driver.
- private[chisel3] var autoIOWrap = true
}
// Location refers to 'where' in the Module hierarchy this lives
@@ -196,5 +207,5 @@ case class PortBinding(enclosure: Module, direction: Option[Direction])
case class RegBinding(enclosure: Module)
extends SynthesizableBinding with ConstrainedBinding with UndirectionedBinding
-case class WireBinding(enclosure: Module)
- extends SynthesizableBinding with ConstrainedBinding with UndirectionedBinding
+case class WireBinding(enclosure: Module, direction: Option[Direction])
+ extends SynthesizableBinding with ConstrainedBinding
diff --git a/chiselFrontend/src/main/scala/chisel3/core/Module.scala b/chiselFrontend/src/main/scala/chisel3/core/Module.scala
index bbed4d9f..450f5b58 100644
--- a/chiselFrontend/src/main/scala/chisel3/core/Module.scala
+++ b/chiselFrontend/src/main/scala/chisel3/core/Module.scala
@@ -4,13 +4,11 @@ package chisel3.core
import scala.collection.mutable.ArrayBuffer
import scala.language.experimental.macros
-
import chisel3.internal._
-import chisel3.internal.Builder.pushCommand
-import chisel3.internal.Builder.dynamicContext
+import chisel3.internal.Builder._
import chisel3.internal.firrtl._
-import chisel3.internal.firrtl.{Command, Component, DefInstance, DefInvalid, ModuleIO}
-import chisel3.internal.sourceinfo.{SourceInfo, InstTransform, UnlocatableSourceInfo}
+import chisel3.internal.firrtl.{Command => _, _}
+import chisel3.internal.sourceinfo.{InstTransform, SourceInfo, UnlocatableSourceInfo}
object Module {
/** A wrapper method that all Module instantiations must be wrapped in
@@ -65,7 +63,7 @@ extends HasId {
iodef
}
- private[this] var ioDefined: Boolean = false
+ private[core] var ioDefined: Boolean = false
/**
* This must wrap the datatype used to set the io field of any Module.
@@ -115,6 +113,10 @@ extends HasId {
private[core] def computePorts: Seq[firrtl.Port] =
for((name, port) <- ports) yield {
+ // If we're auto-wrapping IO definitions, do so now.
+ if (compileOptions.autoIOWrap && name == "io" && !ioDefined) {
+ IO(port)
+ }
// Port definitions need to know input or output at top-level.
// By FIRRTL semantics, 'flipped' becomes an Input
val direction = if(Data.isFlipped(port)) Direction.Input else Direction.Output
diff --git a/chiselFrontend/src/main/scala/chisel3/core/MonoConnect.scala b/chiselFrontend/src/main/scala/chisel3/core/MonoConnect.scala
index bf8e7e28..e0c95e80 100644
--- a/chiselFrontend/src/main/scala/chisel3/core/MonoConnect.scala
+++ b/chiselFrontend/src/main/scala/chisel3/core/MonoConnect.scala
@@ -118,6 +118,7 @@ object MonoConnect {
// CURRENT MOD CURRENT MOD
case (Some(Output), _) => issueConnect(sink, source)
case (None, _) => issueConnect(sink, source)
+ case (_, None) if (compileOptions.internalConnectionToInputOk) => issueConnect(sink, source)
case (Some(Input), _) => throw UnwritableSinkException
}
}
@@ -134,6 +135,7 @@ object MonoConnect {
case (Some(Output), Some(Output)) => issueConnect(sink, source)
case (Some(Output), Some(Input)) => issueConnect(sink, source)
case (_, None) => throw UnreadableSourceException
+ case (Some(Input), Some(Output)) if (compileOptions.tryConnectionsSwapped) => issueConnect(source, sink)
case (Some(Input), _) => throw UnwritableSinkException
}
}
diff --git a/chiselFrontend/src/main/scala/chisel3/core/Reg.scala b/chiselFrontend/src/main/scala/chisel3/core/Reg.scala
index f5706833..6c357461 100644
--- a/chiselFrontend/src/main/scala/chisel3/core/Reg.scala
+++ b/chiselFrontend/src/main/scala/chisel3/core/Reg.scala
@@ -10,7 +10,9 @@ import chisel3.internal.sourceinfo.{SourceInfo, UnlocatableSourceInfo}
object Reg {
private[core] def makeType[T <: Data](t: T = null, next: T = null, init: T = null): T = {
if (t ne null) {
- Binding.checkUnbound(t, s"t ($t) must be unbound Type. Try using cloneType?")
+ if (Builder.compileOptions.regTypeMustBeUnbound) {
+ Binding.checkUnbound(t, s"t ($t) must be unbound Type. Try using cloneType?")
+ }
t.chiselCloneType
} else if (next ne null) {
next.cloneTypeWidth(Width())
diff --git a/chiselFrontend/src/main/scala/chisel3/internal/CompileOptions.scala b/chiselFrontend/src/main/scala/chisel3/internal/CompileOptions.scala
index 12789855..b809b8fe 100644
--- a/chiselFrontend/src/main/scala/chisel3/internal/CompileOptions.scala
+++ b/chiselFrontend/src/main/scala/chisel3/internal/CompileOptions.scala
@@ -9,8 +9,14 @@ package chisel3.internal
class CompileOptions(optionsMap: Map[String, String]) {
// The default for settings related to "strictness".
val strictDefault: String = optionsMap.getOrElse("strict", "false")
+ val looseDefault: String = (!(strictDefault.toBoolean)).toString
// Should Bundle connections require a strict match of fields.
// If true and the same fields aren't present in both source and sink, a MissingFieldException,
// MissingLeftFieldException, or MissingRightFieldException will be thrown.
val connectFieldsMustMatch: Boolean = optionsMap.getOrElse("connectFieldsMustMatch", strictDefault).toBoolean
+ val regTypeMustBeUnbound: Boolean = optionsMap.getOrElse("regTypeMustBeUnbound", strictDefault).toBoolean
+ val autoIOWrap: Boolean = optionsMap.getOrElse("autoIOWrap", looseDefault).toBoolean
+ val portDeterminesDirection: Boolean = optionsMap.getOrElse("portDeterminesDirection", looseDefault).toBoolean
+ val internalConnectionToInputOk: Boolean = optionsMap.getOrElse("internalConnectionToInputOk", looseDefault).toBoolean
+ val tryConnectionsSwapped: Boolean = optionsMap.getOrElse("tryConnectionsSwapped", looseDefault).toBoolean
}