76 lines
3.0 KiB
Scala
76 lines
3.0 KiB
Scala
// See LICENSE.Berkeley for license details.
|
|
|
|
package uncore.agents
|
|
|
|
import Chisel._
|
|
import uncore.tilelink._
|
|
import config._
|
|
|
|
class MMIOTileLinkManagerData(implicit p: Parameters)
|
|
extends TLBundle()(p)
|
|
with HasClientId
|
|
with HasClientTransactionId
|
|
|
|
class MMIOTileLinkManager(implicit p: Parameters)
|
|
extends CoherenceAgentModule()(p) {
|
|
val io = new ManagerTLIO
|
|
|
|
// MMIO requests should never need probe or release
|
|
io.inner.probe.valid := Bool(false)
|
|
io.inner.release.ready := Bool(false)
|
|
|
|
val multibeat_fire = io.outer.acquire.fire() && io.oacq().hasMultibeatData()
|
|
val multibeat_start = multibeat_fire && io.oacq().addr_beat === UInt(0)
|
|
val multibeat_end = multibeat_fire && io.oacq().addr_beat === UInt(outerDataBeats - 1)
|
|
|
|
// Acquire and Grant are basically passthru,
|
|
// except client_id and client_xact_id need to be converted.
|
|
// Associate the inner client_id and client_xact_id
|
|
// with the outer client_xact_id.
|
|
val xact_pending = Reg(init = UInt(0, maxManagerXacts))
|
|
val xact_id_sel = PriorityEncoder(~xact_pending)
|
|
val xact_id_reg = RegEnable(xact_id_sel, multibeat_start)
|
|
val xact_multibeat = Reg(init = Bool(false))
|
|
val outer_xact_id = Mux(xact_multibeat, xact_id_reg, xact_id_sel)
|
|
val xact_free = !xact_pending.andR
|
|
val xact_buffer = Reg(Vec(maxManagerXacts, new MMIOTileLinkManagerData))
|
|
|
|
io.inner.acquire.ready := io.outer.acquire.ready && xact_free
|
|
io.outer.acquire.valid := io.inner.acquire.valid && xact_free
|
|
io.outer.acquire.bits <> io.inner.acquire.bits
|
|
io.outer.acquire.bits.client_xact_id := outer_xact_id
|
|
|
|
def isLastBeat[T <: TileLinkChannel with HasTileLinkBeatId](in: T): Bool =
|
|
!in.hasMultibeatData() || in.addr_beat === UInt(outerDataBeats - 1)
|
|
|
|
def addPendingBitOnAcq[T <: AcquireMetadata](in: DecoupledIO[T]): UInt =
|
|
Mux(in.fire() && isLastBeat(in.bits), UIntToOH(in.bits.client_xact_id), UInt(0))
|
|
|
|
def clearPendingBitOnGnt[T <: GrantMetadata](in: DecoupledIO[T]): UInt =
|
|
~Mux(in.fire() && isLastBeat(in.bits) && !in.bits.requiresAck(),
|
|
UIntToOH(in.bits.manager_xact_id), UInt(0))
|
|
|
|
def clearPendingBitOnFin(in: DecoupledIO[Finish]): UInt =
|
|
~Mux(in.fire(), UIntToOH(in.bits.manager_xact_id), UInt(0))
|
|
|
|
xact_pending := (xact_pending | addPendingBitOnAcq(io.outer.acquire)) &
|
|
clearPendingBitOnFin(io.inner.finish) &
|
|
clearPendingBitOnGnt(io.inner.grant)
|
|
|
|
when (io.outer.acquire.fire() && isLastBeat(io.outer.acquire.bits)) {
|
|
xact_buffer(outer_xact_id) <> io.iacq()
|
|
}
|
|
|
|
when (multibeat_start) { xact_multibeat := Bool(true) }
|
|
when (multibeat_end) { xact_multibeat := Bool(false) }
|
|
|
|
val gnt_xact = xact_buffer(io.ognt().client_xact_id)
|
|
io.outer.grant.ready := io.inner.grant.ready
|
|
io.inner.grant.valid := io.outer.grant.valid
|
|
io.inner.grant.bits <> io.outer.grant.bits
|
|
io.inner.grant.bits.client_id := gnt_xact.client_id
|
|
io.inner.grant.bits.client_xact_id := gnt_xact.client_xact_id
|
|
io.inner.grant.bits.manager_xact_id := io.ognt().client_xact_id
|
|
io.inner.finish.ready := Bool(true)
|
|
}
|