generalize NastiReadDataArbiter
This commit is contained in:
parent
cedef98045
commit
11eacda84a
@ -311,48 +311,6 @@ class NastiArbiter(val arbN: Int)(implicit p: Parameters) extends NastiModule {
|
|||||||
} else { io.slave <> io.master.head }
|
} else { io.slave <> io.master.head }
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Locking RR arbiter for Nasti read data channel
|
|
||||||
* Arbiter locks until last message in channel is sent */
|
|
||||||
class NastiReadDataArbiter(arbN: Int)(implicit p: Parameters) extends NastiModule {
|
|
||||||
val io = new Bundle {
|
|
||||||
val in = Vec(Decoupled(new NastiReadDataChannel), arbN).flip
|
|
||||||
val out = Decoupled(new NastiReadDataChannel)
|
|
||||||
}
|
|
||||||
|
|
||||||
def rotateLeft[T <: Data](norm: Vec[T], rot: UInt): Vec[T] = {
|
|
||||||
val n = norm.size
|
|
||||||
Vec.tabulate(n) { i =>
|
|
||||||
Mux(rot < UInt(n - i), norm(UInt(i) + rot), norm(rot - UInt(n - i)))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
val lockIdx = Reg(init = UInt(0, log2Up(arbN)))
|
|
||||||
val locked = Reg(init = Bool(false))
|
|
||||||
|
|
||||||
// use rotation to give priority to the input after the last one granted
|
|
||||||
val choice = PriorityMux(
|
|
||||||
rotateLeft(Vec(io.in.map(_.valid)), lockIdx + UInt(1)),
|
|
||||||
rotateLeft(Vec((0 until arbN).map(UInt(_))), lockIdx + UInt(1)))
|
|
||||||
|
|
||||||
val chosen = Mux(locked, lockIdx, choice)
|
|
||||||
|
|
||||||
for (i <- 0 until arbN) {
|
|
||||||
io.in(i).ready := io.out.ready && chosen === UInt(i)
|
|
||||||
}
|
|
||||||
|
|
||||||
io.out.valid := io.in(chosen).valid
|
|
||||||
io.out.bits := io.in(chosen).bits
|
|
||||||
|
|
||||||
when (io.out.fire()) {
|
|
||||||
when (!locked) {
|
|
||||||
lockIdx := choice
|
|
||||||
locked := !io.out.bits.last
|
|
||||||
} .elsewhen (io.out.bits.last) {
|
|
||||||
locked := Bool(false)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** A slave that send decode error for every request it receives */
|
/** A slave that send decode error for every request it receives */
|
||||||
class NastiErrorSlave(implicit p: Parameters) extends NastiModule {
|
class NastiErrorSlave(implicit p: Parameters) extends NastiModule {
|
||||||
val io = (new NastiIO).flip
|
val io = (new NastiIO).flip
|
||||||
@ -466,7 +424,10 @@ class NastiRouter(addrmap: Seq[(BigInt, BigInt)])(implicit p: Parameters) extend
|
|||||||
io.master.w.ready := w_ready || err_slave.io.w.ready
|
io.master.w.ready := w_ready || err_slave.io.w.ready
|
||||||
|
|
||||||
val b_arb = Module(new RRArbiter(new NastiWriteResponseChannel, nSlaves + 1))
|
val b_arb = Module(new RRArbiter(new NastiWriteResponseChannel, nSlaves + 1))
|
||||||
val r_arb = Module(new NastiReadDataArbiter(nSlaves + 1))
|
val r_arb = Module(new JunctionsPeekingArbiter(
|
||||||
|
new NastiReadDataChannel, nSlaves + 1,
|
||||||
|
// we can unlock if it's the last beat
|
||||||
|
(r: NastiReadDataChannel) => r.last))
|
||||||
|
|
||||||
for (i <- 0 until nSlaves) {
|
for (i <- 0 until nSlaves) {
|
||||||
b_arb.io.in(i) <> io.slave(i).b
|
b_arb.io.in(i) <> io.slave(i).b
|
||||||
|
@ -58,3 +58,87 @@ object HellaQueue {
|
|||||||
q.io.deq
|
q.io.deq
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** A generalized locking RR arbiter that addresses the limitations of the
|
||||||
|
* version in the Chisel standard library */
|
||||||
|
abstract class JunctionsAbstractLockingArbiter[T <: Data](typ: T, arbN: Int)
|
||||||
|
extends Module {
|
||||||
|
|
||||||
|
val io = new Bundle {
|
||||||
|
val in = Vec(Decoupled(typ.cloneType), arbN).flip
|
||||||
|
val out = Decoupled(typ.cloneType)
|
||||||
|
}
|
||||||
|
|
||||||
|
def rotateLeft[T <: Data](norm: Vec[T], rot: UInt): Vec[T] = {
|
||||||
|
val n = norm.size
|
||||||
|
Vec.tabulate(n) { i =>
|
||||||
|
Mux(rot < UInt(n - i), norm(UInt(i) + rot), norm(rot - UInt(n - i)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val lockIdx = Reg(init = UInt(0, log2Up(arbN)))
|
||||||
|
val locked = Reg(init = Bool(false))
|
||||||
|
|
||||||
|
val choice = PriorityMux(
|
||||||
|
rotateLeft(Vec(io.in.map(_.valid)), lockIdx + UInt(1)),
|
||||||
|
rotateLeft(Vec((0 until arbN).map(UInt(_))), lockIdx + UInt(1)))
|
||||||
|
|
||||||
|
val chosen = Mux(locked, lockIdx, choice)
|
||||||
|
|
||||||
|
for (i <- 0 until arbN) {
|
||||||
|
io.in(i).ready := io.out.ready && chosen === UInt(i)
|
||||||
|
}
|
||||||
|
|
||||||
|
io.out.valid := io.in(chosen).valid
|
||||||
|
io.out.bits := io.in(chosen).bits
|
||||||
|
}
|
||||||
|
|
||||||
|
/** This locking arbiter determines when it is safe to unlock
|
||||||
|
* by peeking at the data */
|
||||||
|
class JunctionsPeekingArbiter[T <: Data](
|
||||||
|
typ: T, arbN: Int,
|
||||||
|
canUnlock: T => Bool,
|
||||||
|
needsLock: Option[T => Bool] = None)
|
||||||
|
extends JunctionsAbstractLockingArbiter(typ, arbN) {
|
||||||
|
|
||||||
|
def realNeedsLock(data: T): Bool =
|
||||||
|
needsLock.map(_(data)).getOrElse(Bool(true))
|
||||||
|
|
||||||
|
when (io.out.fire()) {
|
||||||
|
when (!locked && realNeedsLock(io.out.bits)) {
|
||||||
|
lockIdx := choice
|
||||||
|
locked := Bool(true)
|
||||||
|
}
|
||||||
|
// the unlock statement takes precedent
|
||||||
|
when (canUnlock(io.out.bits)) {
|
||||||
|
locked := Bool(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** This arbiter determines when it is safe to unlock by counting transactions */
|
||||||
|
class JunctionsCountingArbiter[T <: Data](
|
||||||
|
typ: T, arbN: Int, count: Int,
|
||||||
|
val needsLock: Option[T => Bool] = None)
|
||||||
|
extends JunctionsAbstractLockingArbiter(typ, arbN) {
|
||||||
|
|
||||||
|
def realNeedsLock(data: T): Bool =
|
||||||
|
needsLock.map(_(data)).getOrElse(Bool(true))
|
||||||
|
|
||||||
|
// if count is 1, you should use a non-locking arbiter
|
||||||
|
require(count > 1, "CountingArbiter cannot have count <= 1")
|
||||||
|
|
||||||
|
val lock_ctr = Counter(count)
|
||||||
|
|
||||||
|
when (io.out.fire()) {
|
||||||
|
when (!locked && realNeedsLock(io.out.bits)) {
|
||||||
|
lockIdx := choice
|
||||||
|
locked := Bool(true)
|
||||||
|
lock_ctr.inc()
|
||||||
|
}
|
||||||
|
|
||||||
|
when (locked) {
|
||||||
|
when (lock_ctr.inc()) { locked := Bool(false) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user