diff options
| author | Jim Lawson | 2016-08-18 12:35:34 -0700 |
|---|---|---|
| committer | Jim Lawson | 2016-08-18 12:35:34 -0700 |
| commit | d18274e307271809db2c27676f1dca40a49c9627 (patch) | |
| tree | 2632a0e409bea3f9069c5ebfb555cc1ec04caa4f /chiselFrontend/src/main/scala/chisel3/core/Data.scala | |
| parent | ddb7278760029be9d960ba8bf2b06ac8a8aac767 (diff) | |
| parent | 7922f8d4998dd902ee18a6e85e4a404a1f29eb3f (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.scala | 200 |
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) } } |
