1
0
rocket-chip/src/main/scala/util/Timer.scala

75 lines
2.0 KiB
Scala
Raw Normal View History

/// See LICENSE for license details.
package util
import Chisel._
/** Timer with a statically-specified period.
* Can take multiple inflight start-stop events with ID
* Will continue to count down as long as at least one event is inflight
*/
class Timer(initCount: Int, maxInflight: Int) extends Module {
val io = new Bundle {
val start = Valid(UInt(width = log2Up(maxInflight))).flip
val stop = Valid(UInt(width = log2Up(maxInflight))).flip
val timeout = Valid(UInt(width = log2Up(maxInflight)))
}
val inflight = Reg(init = Vec.fill(maxInflight) { Bool(false) })
val countdown = Reg(UInt(width = log2Up(initCount)))
val active = inflight.reduce(_ || _)
when (active) {
countdown := countdown - UInt(1)
}
when (io.start.valid) {
inflight(io.start.bits) := Bool(true)
countdown := UInt(initCount - 1)
}
when (io.stop.valid) {
inflight(io.stop.bits) := Bool(false)
}
io.timeout.valid := countdown === UInt(0) && active
io.timeout.bits := PriorityEncoder(inflight)
assert(!io.stop.valid || inflight(io.stop.bits),
"Timer stop for transaction that's not inflight")
}
object Timer {
def apply(initCount: Int, start: Bool, stop: Bool): Bool = {
val timer = Module(new Timer(initCount, 1))
timer.io.start.valid := start
timer.io.start.bits := UInt(0)
timer.io.stop.valid := stop
timer.io.stop.bits := UInt(0)
timer.io.timeout.valid
}
}
/** Timer with a statically-specified period. */
class DynamicTimer(w: Int) extends Module {
val io = new Bundle {
val start = Bool(INPUT)
val period = UInt(INPUT, w)
val stop = Bool(INPUT)
val timeout = Bool(OUTPUT)
}
val countdown = Reg(init = UInt(0, w))
val active = Reg(init = Bool(false))
when (io.start) {
countdown := io.period
active := Bool(true)
} .elsewhen (io.stop || countdown === UInt(0)) {
active := Bool(false)
} .elsewhen (active) {
countdown := countdown - UInt(1)
}
io.timeout := countdown === UInt(0) && active
}