summaryrefslogtreecommitdiff
path: root/chiselFrontend/src/main/scala/chisel3/core/Data.scala
diff options
context:
space:
mode:
authorJim Lawson2016-08-18 12:35:34 -0700
committerJim Lawson2016-08-18 12:35:34 -0700
commitd18274e307271809db2c27676f1dca40a49c9627 (patch)
tree2632a0e409bea3f9069c5ebfb555cc1ec04caa4f /chiselFrontend/src/main/scala/chisel3/core/Data.scala
parentddb7278760029be9d960ba8bf2b06ac8a8aac767 (diff)
parent7922f8d4998dd902ee18a6e85e4a404a1f29eb3f (diff)
Merge branch 'sdtwigg_connectwrap_renamechisel3' into gsdt_tests
Revive support for firrtl flip direction. Remove compileOptions.internalConnectionToInputOk
Diffstat (limited to 'chiselFrontend/src/main/scala/chisel3/core/Data.scala')
-rw-r--r--chiselFrontend/src/main/scala/chisel3/core/Data.scala200
1 files changed, 160 insertions, 40 deletions
diff --git a/chiselFrontend/src/main/scala/chisel3/core/Data.scala b/chiselFrontend/src/main/scala/chisel3/core/Data.scala
index 8826af51..cb6d427d 100644
--- a/chiselFrontend/src/main/scala/chisel3/core/Data.scala
+++ b/chiselFrontend/src/main/scala/chisel3/core/Data.scala
@@ -13,13 +13,102 @@ sealed abstract class Direction(name: String) {
override def toString: String = name
def flip: Direction
}
-object INPUT extends Direction("input") { override def flip: Direction = OUTPUT }
-object OUTPUT extends Direction("output") { override def flip: Direction = INPUT }
-object NO_DIR extends Direction("?") { override def flip: Direction = NO_DIR }
+object Direction {
+ object Input extends Direction("input") { override def flip: Direction = Output }
+ object Output extends Direction("output") { override def flip: Direction = Input }
+ object Unspecified extends Direction("unspecified") { override def flip: Direction = Input }
+}
+
+@deprecated("debug doesn't do anything in Chisel3 as no pruning happens in the frontend", "chisel3")
+object debug { // scalastyle:ignore object.name
+ def apply (arg: Data): Data = arg
+}
+
+object DataMirror {
+ def widthOf(target: Data): Width = target.width
+}
+
+/**
+* Input, Output, and Flipped are used to define the directions of Module IOs.
+*
+* Note that they do not currently call target to be a newType or cloneType.
+* This is nominally for performance reasons to avoid too many extra copies when
+* something is flipped multiple times.
+*
+* Thus, an error will be thrown if these are used on bound Data
+*/
+object Input {
+ def apply[T<:Data](target: T): T = {
+ Data.setFirrtlDirection(target, Direction.Input)
+ Binding.bind(target, InputBinder, "Error: Cannot set as input ")
+ }
+}
+object Output {
+ def apply[T<:Data](target: T): T = {
+ Data.setFirrtlDirection(target, Direction.Output)
+ Binding.bind(target, OutputBinder, "Error: Cannot set as output ")
+ }
+}
+object Flipped {
+ def apply[T<:Data](target: T): T = {
+ Data.setFirrtlDirection(target, Data.getFirrtlDirection(target).flip)
+ Binding.bind(target, FlippedBinder, "Error: Cannot flip ")
+ }
+}
+
+object Data {
+ /**
+ * This function returns true if the FIRRTL type of this Data should be flipped
+ * relative to other nodes.
+ *
+ * Note that the current scheme only applies Flip to Elements or Vec chains of
+ * Elements.
+ *
+ * A Bundle is never marked flip, instead preferring its root fields to be marked
+ *
+ * The Vec check is due to the fact that flip must be factored out of the vec, ie:
+ * must have flip field: Vec(UInt) instead of field: Vec(flip UInt)
+ */
+ private[chisel3] def isFlipped(target: Data): Boolean = target match {
+ case (element: Element) => element.binding.direction == Some(Direction.Input)
+ case (vec: Vec[Data @unchecked]) => isFlipped(vec.sample_element)
+ case (bundle: Bundle) => false
+ }
+
+ /** This function returns the "firrtl" flipped-ness for the specified object.
+ *
+ * @param target the object for which we want the "firrtl" flipped-ness.
+ */
+ private[chisel3] def isFirrtlFlipped(target: Data): Boolean = {
+ Data.getFirrtlDirection(target) == Direction.Input
+ }
+
+ /** This function gets the "firrtl" direction for the specified object.
+ *
+ * @param target the object for which we want to get the "firrtl" direction.
+ */
+ private[chisel3] def getFirrtlDirection(target: Data): Direction = target match {
+ case (vec: Vec[Data @unchecked]) => vec.sample_element.firrtlDirection
+ case _ => target.firrtlDirection
+ }
+
+ /** This function sets the "firrtl" direction for the specified object.
+ *
+ * @param target the object for which we want to set the "firrtl" direction.
+ */
+ private[chisel3] def setFirrtlDirection(target: Data, direction: Direction): Unit = target match {
+ case (vec: Vec[Data @unchecked]) => vec.sample_element.firrtlDirection = direction
+ case _ => target.firrtlDirection = direction
+ }
-/** Mixing in this trait flips the direction of an Aggregate. */
-trait Flipped extends Data {
- this.overrideDirection(_.flip, !_)
+ implicit class AddDirectionToData[T<:Data](val target: T) extends AnyVal {
+ @deprecated("Input(Data) should be used over Data.asInput", "gchisel")
+ def asInput: T = Input(target)
+ @deprecated("Output(Data) should be used over Data.asOutput", "gchisel")
+ def asOutput: T = Output(target)
+ @deprecated("Flipped(Data) should be used over Data.flip", "gchisel")
+ def flip(): T = Flipped(target)
+ }
}
/** This forms the root of the type system for wire data types. The data value
@@ -27,42 +116,56 @@ trait Flipped extends Data {
* time) of bits, and must have methods to pack / unpack structured data to /
* from bits.
*/
-abstract class Data(dirArg: Direction) extends HasId {
- def dir: Direction = dirVar
-
- // Sucks this is mutable state, but cloneType doesn't take a Direction arg
- private var isFlipVar = dirArg == INPUT
- private var dirVar = dirArg
- private[core] def isFlip = isFlipVar
-
- private[core] def overrideDirection(newDir: Direction => Direction,
- newFlip: Boolean => Boolean): this.type = {
- this.isFlipVar = newFlip(this.isFlipVar)
- for (field <- this.flatten)
- (field: Data).dirVar = newDir((field: Data).dirVar)
- this
- }
- def asInput: this.type = cloneType.overrideDirection(_ => INPUT, _ => true)
- def asOutput: this.type = cloneType.overrideDirection(_ => OUTPUT, _ => false)
- def flip(): this.type = cloneType.overrideDirection(_.flip, !_)
+abstract class Data extends HasId {
+ // Return ALL elements at root of this type.
+ // Contasts with flatten, which returns just Bits
+ private[chisel3] def allElements: Seq[Element]
private[core] def badConnect(that: Data)(implicit sourceInfo: SourceInfo): Unit =
throwException(s"cannot connect ${this} and ${that}")
- private[core] def connect(that: Data)(implicit sourceInfo: SourceInfo): Unit =
- pushCommand(Connect(sourceInfo, this.lref, that.ref))
- private[core] def bulkConnect(that: Data)(implicit sourceInfo: SourceInfo): Unit =
- pushCommand(BulkConnect(sourceInfo, this.lref, that.lref))
- private[core] def lref: Node = Node(this)
+ private[chisel3] def connect(that: Data)(implicit sourceInfo: SourceInfo): Unit = {
+ Binding.checkSynthesizable(this, s"'this' ($this)")
+ Binding.checkSynthesizable(that, s"'that' ($that)")
+ try {
+ MonoConnect.connect(sourceInfo, this, that, Builder.forcedModule)
+ } catch {
+ case MonoConnect.MonoConnectException(message) =>
+ throwException(
+ s"Connection between sink ($this) and source ($that) failed @$message"
+ )
+ }
+ }
+ private[chisel3] def bulkConnect(that: Data)(implicit sourceInfo: SourceInfo): Unit = {
+ Binding.checkSynthesizable(this, s"'this' ($this)")
+ Binding.checkSynthesizable(that, s"'that' ($that)")
+ try {
+ BiConnect.connect(sourceInfo, this, that, Builder.forcedModule)
+ } catch {
+ case BiConnect.BiConnectException(message) =>
+ throwException(
+ s"Connection between left ($this) and source ($that) failed @$message"
+ )
+ }
+ }
+ private[chisel3] def lref: Node = Node(this)
private[chisel3] def ref: Arg = if (isLit) litArg.get else lref
private[core] def cloneTypeWidth(width: Width): this.type
private[chisel3] def toType: String
private[core] def width: Width
- def := (that: Data)(implicit sourceInfo: SourceInfo): Unit = this badConnect that
-
- def <> (that: Data)(implicit sourceInfo: SourceInfo): Unit = this badConnect that
-
def cloneType: this.type
+ def chiselCloneType: this.type = {
+ // Call the user-supplied cloneType method
+ val clone = this.cloneType
+ Data.setFirrtlDirection(clone, Data.getFirrtlDirection(this))
+ //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)
+ }
+ clone
+ }
+ final def := (that: Data)(implicit sourceInfo: SourceInfo): Unit = this connect that
+ final def <> (that: Data)(implicit sourceInfo: SourceInfo): Unit = this bulkConnect that
def litArg(): Option[LitArg] = None
def litValue(): BigInt = litArg.get.num
def isLit(): Boolean = litArg.isDefined
@@ -100,7 +203,7 @@ abstract class Data(dirArg: Direction) extends HasId {
def do_fromBits(that: Bits)(implicit sourceInfo: SourceInfo): this.type = {
var i = 0
- val wire = Wire(this.cloneType)
+ val wire = Wire(this.chiselCloneType)
val bits =
if (that.width.known && that.width.get >= wire.width.get) {
that
@@ -132,6 +235,10 @@ abstract class Data(dirArg: Direction) extends HasId {
def do_asUInt(implicit sourceInfo: SourceInfo): UInt =
SeqUtils.do_asUInt(this.flatten)(sourceInfo)
+
+ // firrtlDirection is the direction we report to firrtl.
+ // It maintains the user-specified value (as opposed to the "actual" or applied/propagated value).
+ var firrtlDirection: Direction = Direction.Unspecified
}
object Wire {
@@ -147,9 +254,14 @@ object Wire {
def do_apply[T <: Data](t: T, init: T)(implicit sourceInfo: SourceInfo): T = {
val x = Reg.makeType(t, null.asInstanceOf[T], init)
+
+ // Bind each element of x to being a Wire
+ Binding.bind(x, WireBinder(Builder.forcedModule), "Error: t")
+
pushCommand(DefWire(sourceInfo, x))
pushCommand(DefInvalid(sourceInfo, x.ref))
if (init != null) {
+ Binding.checkSynthesizable(init, s"'init' ($init)")
x := init
}
x
@@ -157,18 +269,26 @@ object Wire {
}
object Clock {
- def apply(dir: Direction = NO_DIR): Clock = new Clock(dir)
+ def apply(): Clock = new Clock
+ def apply(dir: Direction): Clock = {
+ val result = apply()
+ dir match {
+ case Direction.Input => Input(result)
+ case Direction.Output => Output(result)
+ case Direction.Unspecified => result
+ }
+ }
}
// TODO: Document this.
-sealed class Clock(dirArg: Direction) extends Element(dirArg, Width(1)) {
- def cloneType: this.type = Clock(dirArg).asInstanceOf[this.type]
+sealed class Clock extends Element(Width(1)) {
+ def cloneType: this.type = Clock().asInstanceOf[this.type]
private[chisel3] override def flatten: IndexedSeq[Bits] = IndexedSeq()
private[core] def cloneTypeWidth(width: Width): this.type = cloneType
private[chisel3] def toType = "Clock"
- override def := (that: Data)(implicit sourceInfo: SourceInfo): Unit = that match {
- case _: Clock => this connect that
- case _ => this badConnect that
+ override def connect (that: Data)(implicit sourceInfo: SourceInfo): Unit = that match {
+ case _: Clock => super.connect(that)(sourceInfo)
+ case _ => super.badConnect(that)(sourceInfo)
}
}