All Downloads are FREE. Search and download functionalities are using the official Maven repository.
Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
spinal.lib.Flow.scala Maven / Gradle / Ivy
package spinal.lib
import spinal.core._
class FlowFactory extends MSFactory{
object Fragment extends FlowFragmentFactory
def apply[T <: Data](payloadType: HardType[T]) = {
val ret = new Flow(payloadType)
postApply(ret)
ret
}
def apply[T <: Data](payloadType: => T) : Flow[T] = apply(HardType(payloadType))
}
object Flow extends FlowFactory
class Flow[T <: Data](val payloadType: HardType[T]) extends Bundle with IMasterSlave with DataCarrier[T]{
val valid = Bool()
val payload : T = payloadType()
override def clone: Flow[T] = Flow(payloadType).asInstanceOf[this.type]
override def asMaster(): Unit = out(this)
override def asSlave() : Unit = in(this)
override def freeRun(): this.type = this
def setIdle(): this.type = {
valid := False
payload.assignDontCare()
this
}
def toReg() : T = toReg(null.asInstanceOf[T])
def toReg(init: T): T = RegNextWhen(this.payload,this.fire,init)
def <<(that: Flow[T]): Flow[T] = this connectFrom that
def >>(into: Flow[T]): Flow[T] = {
into << this;
into
}
def <-<(that: Flow[T]): Flow[T] = {
this << that.m2sPipe
that
}
def >->(that: Flow[T]): Flow[T] = that <-< this
override def fire: Bool = valid
def combStage() : Flow[T] = {
val ret = Flow(payloadType).setCompositeName(this, "combStage", true)
ret << this
ret
}
def swapPayload[T2 <: Data](that: HardType[T2]) = {
val next = new Flow(that).setCompositeName(this, "swap", true)
next.valid := this.valid
next
}
def toStream : Stream[T] = toStream(null)
def toStream(overflow : Bool) : Stream[T] = {
val ret = Stream(payloadType).setCompositeName(this, "toStream", true)
ret.valid := this.valid
ret.payload := this.payload
if(overflow != null) overflow := ret.valid && !ret.ready
ret
}
def toStream(overflow : Bool,fifoSize: Int, overflowOccupancyAt : Int) : Stream[T] = {
val (ret,occupancy) = this.toStream.queueWithOccupancy(fifoSize)
overflow := occupancy >= overflowOccupancyAt
ret
}
def ccToggle(pushClock: ClockDomain,
popClock: ClockDomain,
withOutputBufferedReset : Boolean = true,
withOutputM2sPipe : Boolean = true) : Flow[T] = {
val cc = new FlowCCByToggle(payloadType, pushClock, popClock, withOutputBufferedReset=withOutputBufferedReset, withOutputM2sPipe=withOutputM2sPipe).setCompositeName(this,"ccToggle", true)
cc.io.input << this
cc.io.output
}
def connectFrom(that: Flow[T]): Flow[T] = {
valid := that.valid
payload := that.payload
that
}
def takeWhen(cond: Bool): Flow[T] = {
val next = new Flow(payloadType).setCompositeName(this, "takeWhen", true)
next.valid := this.valid && cond
next.payload := this.payload
return next
}
def throwWhen(cond: Bool): Flow[T] = {
this takeWhen (!cond)
}
def translateWith[T2 <: Data](that: T2): Flow[T2] = {
val next = new Flow(that)
next.valid := this.valid
next.payload := that
next
}
def translateFrom[T2 <: Data](that: Flow[T2])(dataAssignment: (T, that.payload.type) => Unit): Flow[T] = {
this.valid := that.valid
dataAssignment(this.payload, that.payload)
this
}
def ~[T2 <: Data](that: T2): Flow[T2] = translateWith(that)
def ~~[T2 <: Data](translate: (T) => T2): Flow[T2] = map(translate)
def map[T2 <: Data](translate: (T) => T2): Flow[T2] = (this ~ translate(this.payload))
def m2sPipe : Flow[T] = m2sPipe()
def m2sPipe(holdPayload : Boolean = false, flush : Bool = null): Flow[T] = {
if(!holdPayload) {
val ret = RegNext(this)
ret.valid.init(False)
if(flush != null) when(flush){ ret.valid := False }
ret
} else {
val ret = Reg(this)
ret.valid.init(False)
ret.valid := this.valid
when(this.valid){
ret.payload := this.payload
}
if(flush != null) when(flush){ ret.valid := False }
ret
}.setCompositeName(this, "m2sPipe", true)
}
def stage() : Flow[T] = this.m2sPipe()
def push(that : T): Unit ={
valid := True
payload := that
}
def default(that : T): Unit ={
valid := False
payload := that
}
def queueWithOccupancy(size: Int): (Stream[T], UInt) = {
val fifo = new StreamFifo(payloadType, size).setCompositeName(this,"queueWithOccupancy", true)
fifo.io.push << this.toStream
fifo.io.push.ready.allowPruning()
return (fifo.io.pop, fifo.io.occupancy)
}
def queueWithAvailability(size: Int): (Stream[T], UInt) = {
val fifo = new StreamFifo(payloadType, size).setCompositeName(this,"queueWithAvailability", true)
fifo.io.push << this.toStream
fifo.io.push.ready.allowPruning()
return (fifo.io.pop, fifo.io.availability)
}
}
/** Create a new Flow that is always valid, with a given payload */
object ValidFlow {
def apply[T <: Data](payload: T): Flow[T] = {
val flow = Flow(payload)
flow.push(payload)
flow
}
}
object RegFlow{
def apply[T <: Data](dataType : T) : Flow[T] = {
val reg = Reg(Flow(dataType))
reg.valid init(False)
reg
}
}
object FlowCCByToggle {
def apply[T <: Data](input: Flow[T], inputClock: ClockDomain = ClockDomain.current, outputClock: ClockDomain = ClockDomain.current): Flow[T] = {
val c = new FlowCCByToggle[T](input.payload, inputClock, outputClock)
c.io.input connectFrom input
return c.io.output
}
}
class FlowCCByToggle[T <: Data](dataType: HardType[T],
inputClock: ClockDomain,
outputClock: ClockDomain,
withOutputBufferedReset : Boolean = true,
withOutputM2sPipe : Boolean = true) extends Component {
val io = new Bundle {
val input = slave Flow (dataType)
val output = master Flow (dataType)
}
val finalOutputClock = outputClock.withOptionalBufferedResetFrom(withOutputBufferedReset && inputClock.hasResetSignal)(inputClock)
val doInit = inputClock.canInit && finalOutputClock.canInit
val inputArea = new ClockingArea(inputClock) {
val target = Reg(Bool())
val data = Reg(io.input.payload)
when(io.input.valid) {
target := !target
data := io.input.payload
}
}
val outputArea = new ClockingArea(finalOutputClock) {
val target = BufferCC(inputArea.target, doInit generate False, randBoot = !doInit)
val hit = RegNext(target)
val flow = cloneOf(io.input)
flow.valid := (target =/= hit)
flow.payload := inputArea.data
flow.payload.addTag(crossClockDomain)
io.output << (if(withOutputM2sPipe) flow.m2sPipe(holdPayload = true) else flow)
}
if(doInit){
inputArea.target init(False)
outputArea.hit init(False)
}else{
inputArea.target.randBoot()
outputArea.hit.randBoot()
}
}