Chisel的IO类型
DecoupledIO
src/main/scala/chisel3/util/Decoupled.scala
/** A concrete subclass of ReadyValidIO signaling that the user expects a
* "decoupled" interface: 'valid' indicates that the producer has
* put valid data in 'bits', and 'ready' indicates that the consumer is ready
* to accept the data this cycle. No requirements are placed on the signaling
* of ready or valid.
*/
class DecoupledIO[+T <: Data](gen: T) extends ReadyValidIO[T](gen)
{
override def cloneType: this.type = new DecoupledIO(gen).asInstanceOf[this.type]
}
而ReadyValidIO在同一个文件中定义
/** An I/O Bundle containing 'valid' and 'ready' signals that handshake
* the transfer of data stored in the 'bits' subfield.
* The base protocol implied by the directionality is that the consumer
* uses the flipped interface. Actual semantics of ready/valid are
* enforced via use of concrete subclasses.
*/
abstract class ReadyValidIO[+T <: Data](gen: T) extends Bundle
{
val ready = Input(Bool())
val valid = Output(Bool())
val bits = Output(gen.chiselCloneType)
}
于是可以看出,DecoupledIO中,有一个ready输入信号和一个valid输出信号。
input, output, flip
chiselFrontend/src/main/scala/chisel3/core/Data.scala
sealed abstract class Direction(name: String) {
override def toString: String = name
def flip: Direction
}
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 }
}
因此Chisel中有2种方向对象:Input和Output,并且flip是一个函数,返回相反方向的对象。
同时可以用Input和Output来定义信号的输入输出类型,这个可以在rocket-chip里面看到很多。
/**
* Input, Output, and Flipped are used to define the directions of Module IOs.
*
* Note that they currently clone their source argument, including its bindings.
*
* Thus, an error will be thrown if these are used on bound Data
*/
object Input {
def apply[T<:Data](source: T)(implicit compileOptions: CompileOptions): T = {
val target = source.chiselCloneType
Data.setFirrtlDirection(target, Direction.Input)
Binding.bind(target, InputBinder, "Error: Cannot set as input ")
}
}
object Output {
def apply[T<:Data](source: T)(implicit compileOptions: CompileOptions): T = {
val target = source.chiselCloneType
Data.setFirrtlDirection(target, Direction.Output)
Binding.bind(target, OutputBinder, "Error: Cannot set as output ")
}
}
object Flipped {
def apply[T<:Data](source: T)(implicit compileOptions: CompileOptions): T = {
val target = source.chiselCloneType
Data.setFirrtlDirection(target, Data.getFirrtlDirection(source).flip)
Binding.bind(target, FlippedBinder, "Error: Cannot flip ")
}
}
asInput,asOutput的定义:
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
}
implicit class AddDirectionToData[T<:Data](val target: T) extends AnyVal {
def asInput(implicit opts: CompileOptions): T = {
if (opts.deprecateOldDirectionMethods)
Builder.deprecated("Input(Data) should be used over Data.asInput")
Input(target)
}
def asOutput(implicit opts: CompileOptions): T = {
if (opts.deprecateOldDirectionMethods)
Builder.deprecated("Output(Data) should be used over Data.asOutput")
Output(target)
}
def flip()(implicit opts: CompileOptions): T = {
if (opts.deprecateOldDirectionMethods)
Builder.deprecated("Flipped(Data) should be used over Data.flip")
Flipped(target)
}
}
}