Skip to content

Commit

Permalink
Support dynamic credit count in senders for CreditedIO
Browse files Browse the repository at this point in the history
(cherry picked from commit 5a5c127)
  • Loading branch information
jerryz123 committed May 18, 2023
1 parent 3806bd8 commit d3b1223
Showing 1 changed file with 23 additions and 17 deletions.
40 changes: 23 additions & 17 deletions src/main/scala/util/CreditedIO.scala
Original file line number Diff line number Diff line change
Expand Up @@ -45,35 +45,37 @@ final class CreditedIO[T <: Data](gen: T) extends Bundle

/** Provide a DecoupledIO interface for sending CreditedIO[Data].
* Convert an IrrevocableIO input to DecoupledIO via Decoupled().
* depth controls the maximum number of Data beats inflight.
* Sender powers on with credits=depth, so sender and receiver must agree on depth.
* maxDepth controls the maximum number of Data beats inflight.
* Sender powers on with credits=maxDepth, so sender and receiver must agree on maxDepth.
* pipe=false increases the receiver=>sender trip time by one cycle.
* pipe=true causes debit to depend on credit.
*/
def toSender(depth: Int, pipe: Boolean = true): DecoupledIO[T] = {
require (depth >= 1)
def toSender(depth: UInt, maxDepth: Int, pipe: Boolean): DecoupledIO[T] = {
require (maxDepth >= 1)
val res = Wire(DecoupledIO(genType))
val counter = new CreditedIOCounter(depth, depth)
val counter = new CreditedIOCounter(maxDepth, depth, maxDepth)
counter.update(this)
res.ready := !counter.empty || (pipe.B && credit)
debit := res.fire()
bits := res.bits
res
}
def toSender(maxDepth: Int, pipe: Boolean = true): DecoupledIO[T] =
toSender(maxDepth.U, maxDepth, pipe)

/** Provide an IrrevocableIO interface for receiving CreditedIO[Data].
* Conversion to DecoupledIO is done via application of Decoupled().
* depth controls the Queue depth and thus maximum number of elements inflight.
* maxDepth controls the Queue depth and thus maximum number of elements inflight.
* flow=false increases the sender=>receiver trip time by one cycle.
* flow=true causes credit to depend on debit.
*/
def toReceiver(depth: Int, flow: Boolean = true): IrrevocableIO[T] = {
require (depth >= 1)
def toReceiver(maxDepth: Int, flow: Boolean = true): IrrevocableIO[T] = {
require (maxDepth >= 1)
val enq = Wire(DecoupledIO(genType))
enq.valid := debit
enq.bits := bits
assert (!enq.valid || enq.ready)
val res = Queue.irrevocable(enq, depth, pipe=true, flow=flow)
val res = Queue.irrevocable(enq, maxDepth, pipe=true, flow=flow)
credit := res.fire()
res
}
Expand Down Expand Up @@ -106,36 +108,40 @@ object CreditedIO
{
def apply[T <: Data](genType: T) = new CreditedIO(genType)

def fromSender[T <: Data](x: ReadyValidIO[T], depth: Int, pipe: Boolean = true): CreditedIO[T] = {
def fromSender[T <: Data](x: ReadyValidIO[T], depth: UInt, maxDepth: Int, pipe: Boolean): CreditedIO[T] = {
val res = Wire(CreditedIO(chiselTypeOf(x.bits)))
val dec = res.toSender(depth, pipe)
val dec = res.toSender(depth, maxDepth, pipe)
dec.valid := x.valid
dec.bits := x.bits
x.ready := dec.ready
res
}

def fromReceiver[T <: Data](x: ReadyValidIO[T], depth: Int, flow: Boolean = true): CreditedIO[T] = {
def fromSender[T <: Data](x: ReadyValidIO[T], maxDepth: Int, pipe: Boolean = true): CreditedIO[T] =
fromSender(x, maxDepth.U, maxDepth, pipe)

def fromReceiver[T <: Data](x: ReadyValidIO[T], maxDepth: Int, flow: Boolean = true): CreditedIO[T] = {
val res = Wire(CreditedIO(chiselTypeOf(x.bits)))
val irr = res.toReceiver(depth, flow)
val irr = res.toReceiver(maxDepth, flow)
x.valid := irr.valid
x.bits := irr.bits
irr.ready := x.ready
res
}
}

class CreditedIOCounter(val init: Int, val depth: Int) {
class CreditedIOCounter(val init: Int, val depth: UInt, val maxDepth: Int) {
require (0 <= init)
require (init <= depth)
require (init <= maxDepth)
assert (depth <= maxDepth.U, "Depth exceeding maxDepth for CreditedIO")

private val v = RegInit(init.U(log2Ceil(depth+1).W))
private val v = RegInit(init.U(log2Ceil(maxDepth+1).W))
private val nextV = WireInit(v)

val value = v + 0.U
val nextValue = nextV + 0.U

def full: Bool = v === depth.U
def full: Bool = v >= depth
def empty: Bool = v === 0.U

def update(credit: Bool, debit: Bool): Unit = {
Expand Down

0 comments on commit d3b1223

Please sign in to comment.