Skip to content

Commit

Permalink
Refactor util/Arbiters to chisel3
Browse files Browse the repository at this point in the history
  • Loading branch information
rvsv39 committed Oct 7, 2022
1 parent 223c4c2 commit a7ac0ea
Showing 1 changed file with 26 additions and 25 deletions.
51 changes: 26 additions & 25 deletions src/main/scala/util/Arbiters.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2,41 +2,42 @@

package freechips.rocketchip.util

import Chisel._
import chisel3._
import chisel3.util._
import freechips.rocketchip.config.Parameters

/** A generalized locking RR arbiter that addresses the limitations of the
* version in the Chisel standard library */
abstract class HellaLockingArbiter[T <: Data](typ: T, arbN: Int, rr: Boolean = false)
extends Module {

val io = new Bundle {
val in = Vec(arbN, Decoupled(typ.cloneType)).flip
val io = IO(new Bundle {
val in = Flipped(Vec(arbN, Decoupled(typ.cloneType)))
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)))
VecInit.tabulate(n) { i =>
Mux(rot < (n - i).U, norm(i.U + rot), norm(rot - (n - i).U))
}
}

val lockIdx = Reg(init = UInt(0, log2Up(arbN)))
val locked = Reg(init = Bool(false))
val lockIdx = RegInit(0.U(log2Up(arbN).W))
val locked = RegInit(false.B)

val choice = if (rr) {
PriorityMux(
rotateLeft(Vec(io.in.map(_.valid)), lockIdx + UInt(1)),
rotateLeft(Vec((0 until arbN).map(UInt(_))), lockIdx + UInt(1)))
rotateLeft(VecInit(io.in.map(_.valid)), lockIdx + 1.U),
rotateLeft(VecInit((0 until arbN).map(_.U)), lockIdx + 1.U))
} else {
PriorityEncoder(io.in.map(_.valid))
}

val chosen = Mux(locked, lockIdx, choice)

for (i <- 0 until arbN) {
io.in(i).ready := io.out.ready && chosen === UInt(i)
io.in(i).ready := io.out.ready && chosen === i.U
}

io.out.valid := io.in(chosen).valid
Expand All @@ -53,16 +54,16 @@ class HellaPeekingArbiter[T <: Data](
extends HellaLockingArbiter(typ, arbN, rr) {

def realNeedsLock(data: T): Bool =
needsLock.map(_(data)).getOrElse(Bool(true))
needsLock.map(_(data)).getOrElse(true.B)

when (io.out.fire()) {
when (io.out.fire) {
when (!locked && realNeedsLock(io.out.bits)) {
lockIdx := choice
locked := Bool(true)
locked := true.B
}
// the unlock statement takes precedent
when (canUnlock(io.out.bits)) {
locked := Bool(false)
locked := false.B
}
}
}
Expand All @@ -75,38 +76,38 @@ class HellaCountingArbiter[T <: Data](
extends HellaLockingArbiter(typ, arbN, rr) {

def realNeedsLock(data: T): Bool =
needsLock.map(_(data)).getOrElse(Bool(true))
needsLock.map(_(data)).getOrElse(true.B)

// 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 (io.out.fire) {
when (!locked && realNeedsLock(io.out.bits)) {
lockIdx := choice
locked := Bool(true)
locked := true.B
lock_ctr.inc()
}

when (locked) {
when (lock_ctr.inc()) { locked := Bool(false) }
when (lock_ctr.inc()) { locked := false.B }
}
}
}

/** This arbiter preserves the order of responses */
class InOrderArbiter[T <: Data, U <: Data](reqTyp: T, respTyp: U, n: Int)
(implicit p: Parameters) extends Module {
val io = new Bundle {
val in_req = Vec(n, Decoupled(reqTyp)).flip
val io = IO(new Bundle {
val in_req = Flipped(Vec(n, Decoupled(reqTyp)))
val in_resp = Vec(n, Decoupled(respTyp))
val out_req = Decoupled(reqTyp)
val out_resp = Decoupled(respTyp).flip
}
val out_resp = Flipped(Decoupled(respTyp))
})

if (n > 1) {
val route_q = Module(new Queue(UInt(width = log2Up(n)), 2))
val route_q = Module(new Queue(UInt(log2Up(n).W), 2))
val req_arb = Module(new RRArbiter(reqTyp, n))
req_arb.io.in <> io.in_req

Expand All @@ -133,7 +134,7 @@ class InOrderArbiter[T <: Data, U <: Data](reqTyp: T, respTyp: U, n: Int)
val resp_valid = resp_helper.fire(resp_ready)
for (i <- 0 until n) {
io.in_resp(i).bits := io.out_resp.bits
io.in_resp(i).valid := resp_valid && resp_sel === UInt(i)
io.in_resp(i).valid := resp_valid && resp_sel === i.U
}

route_q.io.deq.ready := resp_helper.fire(route_q.io.deq.valid)
Expand Down

0 comments on commit a7ac0ea

Please sign in to comment.