1
0

TileLink refactor; TileLinkPorts now available. L2Banks no longer have unique ids (suitable for hierarhical P&R).

This commit is contained in:
Henry Cook 2015-04-17 16:55:20 -07:00
parent ce3271aef2
commit ba7a8b1752
7 changed files with 460 additions and 465 deletions

View File

@ -25,16 +25,16 @@ object DataQueueLocation {
} }
} }
class L2BroadcastHub(bankId: Int) extends ManagerCoherenceAgent class L2BroadcastHub extends ManagerCoherenceAgent
with BroadcastHubParameters { with BroadcastHubParameters {
val internalDataBits = new DataQueueLocation().getWidth val internalDataBits = new DataQueueLocation().getWidth
val inStoreQueue :: inVolWBQueue :: inClientReleaseQueue :: Nil = Enum(UInt(), nDataQueueLocations) val inStoreQueue :: inVolWBQueue :: inClientReleaseQueue :: Nil = Enum(UInt(), nDataQueueLocations)
// Create SHRs for outstanding transactions // Create SHRs for outstanding transactions
val trackerList = (0 until nReleaseTransactors).map(id => val trackerList = (0 until nReleaseTransactors).map(id =>
Module(new BroadcastVoluntaryReleaseTracker(id, bankId), {case TLDataBits => internalDataBits})) ++ Module(new BroadcastVoluntaryReleaseTracker(id), {case TLDataBits => internalDataBits})) ++
(nReleaseTransactors until nTransactors).map(id => (nReleaseTransactors until nTransactors).map(id =>
Module(new BroadcastAcquireTracker(id, bankId), {case TLDataBits => internalDataBits})) Module(new BroadcastAcquireTracker(id), {case TLDataBits => internalDataBits}))
// Propagate incoherence flags // Propagate incoherence flags
trackerList.map(_.io.incoherent := io.incoherent.toBits) trackerList.map(_.io.incoherent := io.incoherent.toBits)
@ -61,7 +61,7 @@ class L2BroadcastHub(bankId: Int) extends ManagerCoherenceAgent
trackerAcquireIOs.zipWithIndex.foreach { trackerAcquireIOs.zipWithIndex.foreach {
case(tracker, i) => case(tracker, i) =>
tracker.bits := io.inner.acquire.bits tracker.bits := io.inner.acquire.bits
tracker.bits.payload.data := DataQueueLocation(sdq_alloc_id, inStoreQueue).toBits tracker.bits.data := DataQueueLocation(sdq_alloc_id, inStoreQueue).toBits
tracker.valid := io.inner.acquire.valid && !block_acquires && (acquire_idx === UInt(i)) tracker.valid := io.inner.acquire.valid && !block_acquires && (acquire_idx === UInt(i))
} }
@ -82,7 +82,7 @@ class L2BroadcastHub(bankId: Int) extends ManagerCoherenceAgent
case(tracker, i) => case(tracker, i) =>
tracker.valid := io.inner.release.valid && (release_idx === UInt(i)) tracker.valid := io.inner.release.valid && (release_idx === UInt(i))
tracker.bits := io.inner.release.bits tracker.bits := io.inner.release.bits
tracker.bits.payload.data := DataQueueLocation(rel_data_cnt, tracker.bits.data := DataQueueLocation(rel_data_cnt,
(if(i < nReleaseTransactors) inVolWBQueue (if(i < nReleaseTransactors) inVolWBQueue
else inClientReleaseQueue)).toBits else inClientReleaseQueue)).toBits
} }
@ -91,17 +91,17 @@ class L2BroadcastHub(bankId: Int) extends ManagerCoherenceAgent
// Wire probe requests and grant reply to clients, finish acks from clients // Wire probe requests and grant reply to clients, finish acks from clients
// Note that we bypass the Grant data subbundles // Note that we bypass the Grant data subbundles
io.inner.grant.bits.payload.data := io.outer.grant.bits.data io.inner.grant.bits.data := io.outer.grant.bits.data
io.inner.grant.bits.payload.addr_beat := io.outer.grant.bits.addr_beat io.inner.grant.bits.addr_beat := io.outer.grant.bits.addr_beat
doOutputArbitration(io.inner.grant, trackerList.map(_.io.inner.grant)) doOutputArbitration(io.inner.grant, trackerList.map(_.io.inner.grant))
doOutputArbitration(io.inner.probe, trackerList.map(_.io.inner.probe)) doOutputArbitration(io.inner.probe, trackerList.map(_.io.inner.probe))
doInputRouting(io.inner.finish, trackerList.map(_.io.inner.finish)) doInputRouting(io.inner.finish, trackerList.map(_.io.inner.finish))
// Create an arbiter for the one memory port // Create an arbiter for the one memory port
val outer_arb = Module(new HeaderlessUncachedTileLinkIOArbiter(trackerList.size), val outer_arb = Module(new ClientUncachedTileLinkIOArbiter(trackerList.size),
{ case TLId => params(OuterTLId) { case TLId => params(OuterTLId)
case TLDataBits => internalDataBits }) case TLDataBits => internalDataBits })
outer_arb.io.in zip trackerList map { case(arb, t) => arb <> t.io.outer } outer_arb.io.in <> trackerList.map(_.io.outer)
// Get the pending data out of the store data queue // Get the pending data out of the store data queue
val outer_data_ptr = new DataQueueLocation().fromBits(outer_arb.io.out.acquire.bits.data) val outer_data_ptr = new DataQueueLocation().fromBits(outer_arb.io.out.acquire.bits.data)
val is_in_sdq = outer_data_ptr.loc === inStoreQueue val is_in_sdq = outer_data_ptr.loc === inStoreQueue
@ -124,12 +124,11 @@ class BroadcastXactTracker extends XactTracker {
val io = new ManagerXactTrackerIO val io = new ManagerXactTrackerIO
} }
class BroadcastVoluntaryReleaseTracker(trackerId: Int, bankId: Int) extends BroadcastXactTracker { class BroadcastVoluntaryReleaseTracker(trackerId: Int) extends BroadcastXactTracker {
val s_idle :: s_outer :: s_grant :: s_ack :: Nil = Enum(UInt(), 4) val s_idle :: s_outer :: s_grant :: s_ack :: Nil = Enum(UInt(), 4)
val state = Reg(init=s_idle) val state = Reg(init=s_idle)
val xact_src = Reg(io.inner.release.bits.header.src.clone) val xact = Reg(Bundle(new ReleaseFromSrc, { case TLId => params(InnerTLId); case TLDataBits => 0 }))
val xact = Reg(Bundle(new Release, { case TLId => params(InnerTLId); case TLDataBits => 0 }))
val data_buffer = Vec.fill(innerDataBeats){ Reg(io.irel().data.clone) } val data_buffer = Vec.fill(innerDataBeats){ Reg(io.irel().data.clone) }
val coh = ManagerMetadata.onReset val coh = ManagerMetadata.onReset
@ -150,9 +149,7 @@ class BroadcastVoluntaryReleaseTracker(trackerId: Int, bankId: Int) extends Broa
io.inner.grant.valid := Bool(false) io.inner.grant.valid := Bool(false)
io.inner.finish.ready := Bool(false) io.inner.finish.ready := Bool(false)
io.inner.grant.bits.header.src := UInt(bankId) io.inner.grant.bits := coh.makeGrant(xact, UInt(trackerId))
io.inner.grant.bits.header.dst := xact_src
io.inner.grant.bits.payload := coh.makeGrant(xact, UInt(trackerId))
//TODO: Use io.outer.release instead? //TODO: Use io.outer.release instead?
io.outer.acquire.bits := Bundle( io.outer.acquire.bits := Bundle(
@ -175,7 +172,6 @@ class BroadcastVoluntaryReleaseTracker(trackerId: Int, bankId: Int) extends Broa
is(s_idle) { is(s_idle) {
io.inner.release.ready := Bool(true) io.inner.release.ready := Bool(true)
when( io.inner.release.valid ) { when( io.inner.release.valid ) {
xact_src := io.inner.release.bits.header.src
xact := io.irel() xact := io.irel()
data_buffer(UInt(0)) := io.irel().data data_buffer(UInt(0)) := io.irel().data
collect_irel_data := io.irel().hasMultibeatData() collect_irel_data := io.irel().hasMultibeatData()
@ -207,12 +203,11 @@ class BroadcastVoluntaryReleaseTracker(trackerId: Int, bankId: Int) extends Broa
} }
} }
class BroadcastAcquireTracker(trackerId: Int, bankId: Int) extends BroadcastXactTracker { class BroadcastAcquireTracker(trackerId: Int) extends BroadcastXactTracker {
val s_idle :: s_probe :: s_mem_read :: s_mem_write :: s_make_grant :: s_mem_resp :: s_ack :: Nil = Enum(UInt(), 7) val s_idle :: s_probe :: s_mem_read :: s_mem_write :: s_make_grant :: s_mem_resp :: s_ack :: Nil = Enum(UInt(), 7)
val state = Reg(init=s_idle) val state = Reg(init=s_idle)
val xact_src = Reg(io.inner.acquire.bits.header.src.clone) val xact = Reg(Bundle(new AcquireFromSrc, { case TLId => params(InnerTLId); case TLDataBits => 0 }))
val xact = Reg(Bundle(new Acquire, { case TLId => params(InnerTLId); case TLDataBits => 0 }))
val data_buffer = Vec.fill(innerDataBeats){ Reg(io.iacq().data.clone) } val data_buffer = Vec.fill(innerDataBeats){ Reg(io.iacq().data.clone) }
val coh = ManagerMetadata.onReset val coh = ManagerMetadata.onReset
@ -225,9 +220,9 @@ class BroadcastAcquireTracker(trackerId: Int, bankId: Int) extends BroadcastXact
val pending_probes = Reg(init=Bits(0, width = io.inner.tlNCoherentClients)) val pending_probes = Reg(init=Bits(0, width = io.inner.tlNCoherentClients))
val curr_p_id = PriorityEncoder(pending_probes) val curr_p_id = PriorityEncoder(pending_probes)
val full_sharers = coh.full() val full_sharers = coh.full()
val probe_self = io.inner.acquire.bits.payload.requiresSelfProbe() val probe_self = io.inner.acquire.bits.requiresSelfProbe()
val mask_self_true = UInt(UInt(1) << io.inner.acquire.bits.header.src, width = io.inner.tlNCoherentClients) val mask_self_true = UInt(UInt(1) << io.inner.acquire.bits.client_id, width = io.inner.tlNCoherentClients)
val mask_self_false = ~UInt(UInt(1) << io.inner.acquire.bits.header.src, width = io.inner.tlNCoherentClients) val mask_self_false = ~UInt(UInt(1) << io.inner.acquire.bits.client_id, width = io.inner.tlNCoherentClients)
val mask_self = Mux(probe_self, full_sharers | mask_self_true, full_sharers & mask_self_false) val mask_self = Mux(probe_self, full_sharers | mask_self_true, full_sharers & mask_self_false)
val mask_incoherent = mask_self & ~io.incoherent.toBits val mask_incoherent = mask_self & ~io.incoherent.toBits
@ -272,21 +267,17 @@ class BroadcastAcquireTracker(trackerId: Int, bankId: Int) extends BroadcastXact
io.outer.grant.ready := Bool(false) io.outer.grant.ready := Bool(false)
io.inner.probe.valid := Bool(false) io.inner.probe.valid := Bool(false)
io.inner.probe.bits.header.src := UInt(bankId) io.inner.probe.bits := coh.makeProbe(curr_p_id, xact)
io.inner.probe.bits.header.dst := curr_p_id
io.inner.probe.bits.payload := coh.makeProbe(xact)
io.inner.grant.valid := Bool(false) io.inner.grant.valid := Bool(false)
io.inner.grant.bits.header.src := UInt(bankId) io.inner.grant.bits := coh.makeGrant(xact, UInt(trackerId)) // Data bypassed in parent
io.inner.grant.bits.header.dst := xact_src
io.inner.grant.bits.payload := coh.makeGrant(xact, UInt(trackerId)) // Data bypassed in parent
io.inner.acquire.ready := Bool(false) io.inner.acquire.ready := Bool(false)
io.inner.release.ready := Bool(false) io.inner.release.ready := Bool(false)
io.inner.finish.ready := Bool(false) io.inner.finish.ready := Bool(false)
assert(!(state != s_idle && collect_iacq_data && io.inner.acquire.fire() && assert(!(state != s_idle && collect_iacq_data && io.inner.acquire.fire() &&
io.inner.acquire.bits.header.src != xact_src), io.iacq().client_id != xact.client_id),
"AcquireTracker accepted data beat from different network source than initial request.") "AcquireTracker accepted data beat from different network source than initial request.")
assert(!(state != s_idle && collect_iacq_data && io.inner.acquire.fire() && assert(!(state != s_idle && collect_iacq_data && io.inner.acquire.fire() &&
@ -316,7 +307,6 @@ class BroadcastAcquireTracker(trackerId: Int, bankId: Int) extends BroadcastXact
is(s_idle) { is(s_idle) {
io.inner.acquire.ready := Bool(true) io.inner.acquire.ready := Bool(true)
when(io.inner.acquire.valid) { when(io.inner.acquire.valid) {
xact_src := io.inner.acquire.bits.header.src
xact := io.iacq() xact := io.iacq()
data_buffer(UInt(0)) := io.iacq().data data_buffer(UInt(0)) := io.iacq().data
collect_iacq_data := io.iacq().hasMultibeatData() collect_iacq_data := io.iacq().hasMultibeatData()

View File

@ -188,7 +188,7 @@ abstract class L2HellaCacheModule extends Module with L2HellaCacheParameters {
ins: Seq[DecoupledIO[T]]) { ins: Seq[DecoupledIO[T]]) {
val arb = Module(new RRArbiter(out.bits.clone, ins.size)) val arb = Module(new RRArbiter(out.bits.clone, ins.size))
out <> arb.io.out out <> arb.io.out
arb.io.in zip ins map { case (a, in) => a <> in } arb.io.in <> ins
} }
def doInternalInputRouting[T <: HasL2Id](in: ValidIO[T], outs: Seq[ValidIO[T]]) { def doInternalInputRouting[T <: HasL2Id](in: ValidIO[T], outs: Seq[ValidIO[T]]) {
@ -342,14 +342,14 @@ class L2SecondaryMissInfo extends TLBundle
with HasTileLinkBeatId with HasTileLinkBeatId
with HasClientTransactionId with HasClientTransactionId
class L2HellaCacheBank(bankId: Int) extends HierarchicalCoherenceAgent class L2HellaCacheBank extends HierarchicalCoherenceAgent
with L2HellaCacheParameters { with L2HellaCacheParameters {
require(isPow2(nSets)) require(isPow2(nSets))
require(isPow2(nWays)) require(isPow2(nWays))
val meta = Module(new L2MetadataArray) // TODO: add delay knob val meta = Module(new L2MetadataArray) // TODO: add delay knob
val data = Module(new L2DataArray(1)) val data = Module(new L2DataArray(1))
val tshrfile = Module(new TSHRFile(bankId)) val tshrfile = Module(new TSHRFile)
tshrfile.io.inner <> io.inner tshrfile.io.inner <> io.inner
io.outer <> tshrfile.io.outer io.outer <> tshrfile.io.outer
io.incoherent <> tshrfile.io.incoherent io.incoherent <> tshrfile.io.incoherent
@ -362,24 +362,21 @@ class TSHRFileIO extends HierarchicalTLIO {
val data = new L2DataRWIO val data = new L2DataRWIO
} }
class TSHRFile(bankId: Int) extends L2HellaCacheModule class TSHRFile extends L2HellaCacheModule
with HasCoherenceAgentWiringHelpers { with HasCoherenceAgentWiringHelpers {
val io = new TSHRFileIO val io = new TSHRFileIO
// Create TSHRs for outstanding transactions // Create TSHRs for outstanding transactions
val trackerList = (0 until nReleaseTransactors).map { id => val trackerList = (0 until nReleaseTransactors).map(id => Module(new L2VoluntaryReleaseTracker(id))) ++
Module(new L2VoluntaryReleaseTracker(id, bankId)) (nReleaseTransactors until nTransactors).map(id => Module(new L2AcquireTracker(id)))
} ++ (nReleaseTransactors until nTransactors).map { id =>
Module(new L2AcquireTracker(id, bankId))
}
// WritebackUnit evicts data from L2, including invalidating L1s // WritebackUnit evicts data from L2, including invalidating L1s
val wb = Module(new L2WritebackUnit(nTransactors, bankId)) val wb = Module(new L2WritebackUnit(nTransactors))
doInternalOutputArbitration(wb.io.wb.req, trackerList.map(_.io.wb.req)) doInternalOutputArbitration(wb.io.wb.req, trackerList.map(_.io.wb.req))
doInternalInputRouting(wb.io.wb.resp, trackerList.map(_.io.wb.resp)) doInternalInputRouting(wb.io.wb.resp, trackerList.map(_.io.wb.resp))
// Propagate incoherence flags // Propagate incoherence flags
(trackerList.map(_.io.incoherent) :+ wb.io.incoherent).map( _ := io.incoherent.toBits) (trackerList.map(_.io.incoherent) :+ wb.io.incoherent) foreach { _ := io.incoherent.toBits }
// Handle acquire transaction initiation // Handle acquire transaction initiation
val trackerAcquireIOs = trackerList.map(_.io.inner.acquire) val trackerAcquireIOs = trackerList.map(_.io.inner.acquire)
@ -419,8 +416,8 @@ class TSHRFile(bankId: Int) extends L2HellaCacheModule
// Create an arbiter for the one memory port // Create an arbiter for the one memory port
val outerList = trackerList.map(_.io.outer) :+ wb.io.outer val outerList = trackerList.map(_.io.outer) :+ wb.io.outer
val outer_arb = Module(new HeaderlessTileLinkIOArbiter(outerList.size))(outerTLParams) val outer_arb = Module(new ClientTileLinkIOArbiter(outerList.size))(outerTLParams)
outerList zip outer_arb.io.in map { case(out, arb) => out <> arb } outer_arb.io.in <> outerList
io.outer <> outer_arb.io.out io.outer <> outer_arb.io.out
// Wire local memory arrays // Wire local memory arrays
@ -480,21 +477,20 @@ abstract class L2XactTracker extends XactTracker with L2HellaCacheParameters {
def dropPendingBitInternal[T <: HasL2BeatAddr] (in: ValidIO[T]) = def dropPendingBitInternal[T <: HasL2BeatAddr] (in: ValidIO[T]) =
~Fill(in.bits.refillCycles, in.valid) | ~UIntToOH(in.bits.addr_beat) ~Fill(in.bits.refillCycles, in.valid) | ~UIntToOH(in.bits.addr_beat)
def addPendingBitWhenBeatHasPartialWritemask(in: DecoupledIO[LogicalNetworkIO[Acquire]]): UInt = { def addPendingBitWhenBeatHasPartialWritemask(in: DecoupledIO[AcquireFromSrc]): UInt = {
val a = in.bits.payload val a = in.bits
val isPartial = a.wmask() != Acquire.fullWriteMask val isPartial = a.wmask() != Acquire.fullWriteMask
addPendingBitWhenBeat(in.fire() && isPartial && Bool(ignoresWriteMask), in.bits.payload) addPendingBitWhenBeat(in.fire() && isPartial && Bool(ignoresWriteMask), a)
} }
} }
class L2VoluntaryReleaseTracker(trackerId: Int, bankId: Int) extends L2XactTracker { class L2VoluntaryReleaseTracker(trackerId: Int) extends L2XactTracker {
val io = new L2XactTrackerIO val io = new L2XactTrackerIO
val s_idle :: s_meta_read :: s_meta_resp :: s_data_write :: s_meta_write :: s_inner_grant :: s_inner_finish :: Nil = Enum(UInt(), 7) val s_idle :: s_meta_read :: s_meta_resp :: s_data_write :: s_meta_write :: s_inner_grant :: s_inner_finish :: Nil = Enum(UInt(), 7)
val state = Reg(init=s_idle) val state = Reg(init=s_idle)
val xact_src = Reg(io.inner.release.bits.header.src.clone) val xact = Reg(Bundle(new ReleaseFromSrc, { case TLId => params(InnerTLId); case TLDataBits => 0 }))
val xact = Reg(Bundle(new Release, { case TLId => params(InnerTLId); case TLDataBits => 0 }))
val xact_tag_match = Reg{ Bool() } val xact_tag_match = Reg{ Bool() }
val xact_old_meta = Reg{ new L2Metadata } val xact_old_meta = Reg{ new L2Metadata }
val xact_way_en = Reg{ Bits(width = nWays) } val xact_way_en = Reg{ Bits(width = nWays) }
@ -520,9 +516,7 @@ class L2VoluntaryReleaseTracker(trackerId: Int, bankId: Int) extends L2XactTrack
io.inner.grant.valid := Bool(false) io.inner.grant.valid := Bool(false)
io.inner.finish.ready := Bool(false) io.inner.finish.ready := Bool(false)
io.inner.grant.bits.header.src := UInt(bankId) io.inner.grant.bits := coh.inner.makeGrant(xact, UInt(trackerId))
io.inner.grant.bits.header.dst := xact_src
io.inner.grant.bits.payload := coh.inner.makeGrant(xact, UInt(trackerId))
io.data.read.valid := Bool(false) io.data.read.valid := Bool(false)
io.data.write.valid := Bool(false) io.data.write.valid := Bool(false)
@ -541,7 +535,7 @@ class L2VoluntaryReleaseTracker(trackerId: Int, bankId: Int) extends L2XactTrack
io.meta.write.bits.idx := xact.addr_block(idxMSB,idxLSB) io.meta.write.bits.idx := xact.addr_block(idxMSB,idxLSB)
io.meta.write.bits.way_en := xact_way_en io.meta.write.bits.way_en := xact_way_en
io.meta.write.bits.data.tag := xact.addr_block >> UInt(idxBits) io.meta.write.bits.data.tag := xact.addr_block >> UInt(idxBits)
io.meta.write.bits.data.coh.inner := xact_old_meta.coh.inner.onRelease(xact, xact_src) io.meta.write.bits.data.coh.inner := xact_old_meta.coh.inner.onRelease(xact)
io.meta.write.bits.data.coh.outer := xact_old_meta.coh.outer.onHit(M_XWR) // WB is a write io.meta.write.bits.data.coh.outer := xact_old_meta.coh.outer.onHit(M_XWR) // WB is a write
io.wb.req.valid := Bool(false) io.wb.req.valid := Bool(false)
@ -558,7 +552,6 @@ class L2VoluntaryReleaseTracker(trackerId: Int, bankId: Int) extends L2XactTrack
is(s_idle) { is(s_idle) {
io.inner.release.ready := Bool(true) io.inner.release.ready := Bool(true)
when( io.inner.release.valid ) { when( io.inner.release.valid ) {
xact_src := io.inner.release.bits.header.src
xact := io.irel() xact := io.irel()
data_buffer(io.irel().addr_beat) := io.irel().data data_buffer(io.irel().addr_beat) := io.irel().data
collect_irel_data := io.irel().hasMultibeatData() collect_irel_data := io.irel().hasMultibeatData()
@ -608,15 +601,14 @@ class L2VoluntaryReleaseTracker(trackerId: Int, bankId: Int) extends L2XactTrack
} }
class L2AcquireTracker(trackerId: Int, bankId: Int) extends L2XactTracker { class L2AcquireTracker(trackerId: Int) extends L2XactTracker {
val io = new L2XactTrackerIO val io = new L2XactTrackerIO
val s_idle :: s_meta_read :: s_meta_resp :: s_wb_req :: s_wb_resp :: s_inner_probe :: s_outer_acquire :: s_busy :: s_meta_write :: Nil = Enum(UInt(), 9) val s_idle :: s_meta_read :: s_meta_resp :: s_wb_req :: s_wb_resp :: s_inner_probe :: s_outer_acquire :: s_busy :: s_meta_write :: Nil = Enum(UInt(), 9)
val state = Reg(init=s_idle) val state = Reg(init=s_idle)
// State holding transaction metadata // State holding transaction metadata
val xact_src = Reg(io.inner.acquire.bits.header.src.clone) val xact = Reg(Bundle(new AcquireFromSrc, { case TLId => params(InnerTLId) }))
val xact = Reg(Bundle(new Acquire, { case TLId => params(InnerTLId) }))
val data_buffer = Vec.fill(innerDataBeats){ Reg(init=UInt(0, width = innerDataBits)) } val data_buffer = Vec.fill(innerDataBeats){ Reg(init=UInt(0, width = innerDataBits)) }
val wmask_buffer = Vec.fill(innerDataBeats){ Reg(init=UInt(0,width = innerDataBits/8)) } val wmask_buffer = Vec.fill(innerDataBeats){ Reg(init=UInt(0,width = innerDataBits/8)) }
val xact_tag_match = Reg{ Bool() } val xact_tag_match = Reg{ Bool() }
@ -631,16 +623,23 @@ class L2AcquireTracker(trackerId: Int, bankId: Int) extends L2XactTracker {
// TODO add ignt.dst <- iacq.src // TODO add ignt.dst <- iacq.src
// State holding progress made on processing this transaction // State holding progress made on processing this transaction
val iacq_data_done = val iacq_data_done = connectIncomingDataBeatCounter(io.inner.acquire)
connectIncomingDataBeatCounter(io.inner.acquire) val pending_irels = connectTwoWayBeatCounter(
val pending_irels = max = io.inner.tlNCoherentClients,
connectTwoWayBeatCounter(io.inner.tlNCoherentClients, io.inner.probe, io.inner.release)._1 up = io.inner.probe,
down = io.inner.release)._1
val (pending_ognts, oacq_data_idx, oacq_data_done, ognt_data_idx, ognt_data_done) = val (pending_ognts, oacq_data_idx, oacq_data_done, ognt_data_idx, ognt_data_done) =
connectHeaderlessTwoWayBeatCounter(1, io.outer.acquire, io.outer.grant, xact.addr_beat) connectTwoWayBeatCounter(
val (ignt_data_idx, ignt_data_done) = max = 1,
connectOutgoingDataBeatCounter(io.inner.grant, ignt_q.io.deq.bits.addr_beat) up = io.outer.acquire,
val pending_ifins = down = io.outer.grant,
connectTwoWayBeatCounter(nSecondaryMisses, io.inner.grant, io.inner.finish, (g: Grant) => g.requiresAck())._1 beat = xact.addr_beat)
val (ignt_data_idx, ignt_data_done) = connectOutgoingDataBeatCounter(io.inner.grant, ignt_q.io.deq.bits.addr_beat)
val pending_ifins = connectTwoWayBeatCounter(
max = nSecondaryMisses,
up = io.inner.grant,
down = io.inner.finish,
track = (g: Grant) => g.requiresAck())._1
val pending_puts = Reg(init=Bits(0, width = io.inner.tlDataBeats)) val pending_puts = Reg(init=Bits(0, width = io.inner.tlDataBeats))
val pending_iprbs = Reg(init = Bits(0, width = io.inner.tlNCoherentClients)) val pending_iprbs = Reg(init = Bits(0, width = io.inner.tlNCoherentClients))
val pending_reads = Reg(init=Bits(0, width = io.inner.tlDataBeats)) val pending_reads = Reg(init=Bits(0, width = io.inner.tlDataBeats))
@ -695,9 +694,9 @@ class L2AcquireTracker(trackerId: Int, bankId: Int) extends L2XactTracker {
def mergeDataInternal[T <: HasL2Data with HasL2BeatAddr](in: ValidIO[T]) { def mergeDataInternal[T <: HasL2Data with HasL2BeatAddr](in: ValidIO[T]) {
when(in.valid) { mergeData(rowBits)(in.bits.addr_beat, in.bits.data) } when(in.valid) { mergeData(rowBits)(in.bits.addr_beat, in.bits.data) }
} }
def mergeDataInner[T <: HasTileLinkData with HasTileLinkBeatId](in: DecoupledIO[LogicalNetworkIO[T]]) { def mergeDataInner[T <: HasTileLinkData with HasTileLinkBeatId](in: DecoupledIO[T]) {
when(in.fire() && in.bits.payload.hasData()) { when(in.fire() && in.bits.hasData()) {
mergeData(innerDataBits)(in.bits.payload.addr_beat, in.bits.payload.data) mergeData(innerDataBits)(in.bits.addr_beat, in.bits.data)
} }
} }
def mergeDataOuter[T <: HasTileLinkData with HasTileLinkBeatId](in: DecoupledIO[T]) { def mergeDataOuter[T <: HasTileLinkData with HasTileLinkBeatId](in: DecoupledIO[T]) {
@ -713,7 +712,7 @@ class L2AcquireTracker(trackerId: Int, bankId: Int) extends L2XactTracker {
// and Puts-under-Put from the same client // and Puts-under-Put from the same client
val can_merge_iacq_get = (xact.isBuiltInType(Acquire.getType) && val can_merge_iacq_get = (xact.isBuiltInType(Acquire.getType) &&
io.iacq().isBuiltInType(Acquire.getType)) && io.iacq().isBuiltInType(Acquire.getType)) &&
xact_src === io.inner.acquire.bits.header.src && //TODO xact.client_id === io.iacq().client_id && //TODO remove
xact.conflicts(io.iacq()) && xact.conflicts(io.iacq()) &&
state != s_idle && state != s_meta_write && state != s_idle && state != s_meta_write &&
!all_pending_done && !all_pending_done &&
@ -728,7 +727,7 @@ class L2AcquireTracker(trackerId: Int, bankId: Int) extends L2XactTracker {
io.iacq().isBuiltInType(Acquire.putType)) || io.iacq().isBuiltInType(Acquire.putType)) ||
(xact.isBuiltInType(Acquire.putBlockType) && (xact.isBuiltInType(Acquire.putBlockType) &&
io.iacq().isBuiltInType(Acquire.putBlockType))) && io.iacq().isBuiltInType(Acquire.putBlockType))) &&
xact_src === io.inner.acquire.bits.header.src && //TODO xact.client_id === io.iacq().client_id && //TODO remove
xact.conflicts(io.iacq()) && xact.conflicts(io.iacq()) &&
state != s_idle && state != s_meta_write && state != s_idle && state != s_meta_write &&
!all_pending_done && !all_pending_done &&
@ -749,17 +748,13 @@ class L2AcquireTracker(trackerId: Int, bankId: Int) extends L2XactTracker {
pending_iprbs := pending_iprbs & dropPendingBitAtDest(io.inner.probe) pending_iprbs := pending_iprbs & dropPendingBitAtDest(io.inner.probe)
val curr_probe_dst = PriorityEncoder(pending_iprbs) val curr_probe_dst = PriorityEncoder(pending_iprbs)
io.inner.probe.valid := state === s_inner_probe && pending_iprbs.orR io.inner.probe.valid := state === s_inner_probe && pending_iprbs.orR
io.inner.probe.bits.header.src := UInt(bankId) io.inner.probe.bits := pending_coh.inner.makeProbe(curr_probe_dst, xact)
io.inner.probe.bits.header.dst := curr_probe_dst
io.inner.probe.bits.payload := pending_coh.inner.makeProbe(xact)
// Handle incoming releases from clients, which may reduce sharer counts // Handle incoming releases from clients, which may reduce sharer counts
// and/or write back dirty data // and/or write back dirty data
io.inner.release.ready := state === s_inner_probe io.inner.release.ready := state === s_inner_probe
val pending_coh_on_irel = HierarchicalMetadata( val pending_coh_on_irel = HierarchicalMetadata(
pending_coh.inner.onRelease( // Drop sharer pending_coh.inner.onRelease(io.irel()), // Drop sharer
incoming = io.irel(),
src = io.inner.release.bits.header.src),
Mux(io.irel().hasData(), // Dirty writeback Mux(io.irel().hasData(), // Dirty writeback
pending_coh.outer.onHit(M_XWR), pending_coh.outer.onHit(M_XWR),
pending_coh.outer)) pending_coh.outer))
@ -804,23 +799,18 @@ class L2AcquireTracker(trackerId: Int, bankId: Int) extends L2XactTracker {
ignt_q.io.deq.valid && ignt_q.io.deq.valid &&
(!io.ignt().hasData() || (!io.ignt().hasData() ||
pending_ignt_data(ignt_data_idx)) pending_ignt_data(ignt_data_idx))
io.inner.grant.bits.header.src := UInt(bankId) io.inner.grant.bits := pending_coh.inner.makeGrant(
io.inner.grant.bits.header.dst := xact_src // TODO: ignt_q.io.deq.bits.src dst = xact.client_id, // TODO: ignt_q.io.deq.bits.src
io.inner.grant.bits.payload := pending_coh.inner.makeGrant( acq = xact,
acq = xact, client_xact_id = ignt_q.io.deq.bits.client_xact_id,
manager_xact_id = UInt(trackerId), manager_xact_id = UInt(trackerId),
addr_beat = ignt_data_idx, addr_beat = ignt_data_idx,
data = Mux(xact.is(Acquire.putAtomicType), data = Mux(xact.is(Acquire.putAtomicType),
amo_result, amo_result,
data_buffer(ignt_data_idx))) data_buffer(ignt_data_idx)))
// TODO: improve the ManagerMetadata.makeGrant to deal with possibility of
// multiple client transaction ids from merged secondary misses
io.ignt().client_xact_id := ignt_q.io.deq.bits.client_xact_id
val pending_coh_on_ignt = HierarchicalMetadata( val pending_coh_on_ignt = HierarchicalMetadata(
pending_coh.inner.onGrant( pending_coh.inner.onGrant(io.ignt()),
outgoing = io.ignt(),
dst = io.inner.grant.bits.header.dst),
Mux(ognt_data_done, Mux(ognt_data_done,
pending_coh_on_ognt.outer, pending_coh_on_ognt.outer,
pending_coh.outer)) pending_coh.outer))
@ -904,7 +894,6 @@ class L2AcquireTracker(trackerId: Int, bankId: Int) extends L2XactTracker {
// State machine updates and transaction handler metadata intialization // State machine updates and transaction handler metadata intialization
when(state === s_idle && io.inner.acquire.valid) { when(state === s_idle && io.inner.acquire.valid) {
xact_src := io.inner.acquire.bits.header.src
xact := io.iacq() xact := io.iacq()
xact.data := UInt(0) xact.data := UInt(0)
pending_puts := Mux( // Make sure to collect all data from a PutBlock pending_puts := Mux( // Make sure to collect all data from a PutBlock
@ -943,8 +932,8 @@ class L2AcquireTracker(trackerId: Int, bankId: Int) extends L2XactTracker {
val full_sharers = coh.inner.full() val full_sharers = coh.inner.full()
val mask_self = Mux( val mask_self = Mux(
xact.requiresSelfProbe(), xact.requiresSelfProbe(),
coh.inner.full() | UIntToOH(xact_src), coh.inner.full() | UIntToOH(xact.client_id),
coh.inner.full() & ~UIntToOH(xact_src)) coh.inner.full() & ~UIntToOH(xact.client_id))
val mask_incoherent = mask_self & ~io.incoherent.toBits val mask_incoherent = mask_self & ~io.incoherent.toBits
pending_iprbs := mask_incoherent pending_iprbs := mask_incoherent
} }
@ -984,7 +973,7 @@ class L2AcquireTracker(trackerId: Int, bankId: Int) extends L2XactTracker {
// Checks for illegal behavior // Checks for illegal behavior
assert(!(state != s_idle && io.inner.acquire.fire() && assert(!(state != s_idle && io.inner.acquire.fire() &&
io.inner.acquire.bits.header.src != xact_src), io.inner.acquire.bits.client_id != xact.client_id),
"AcquireTracker accepted data beat from different network source than initial request.") "AcquireTracker accepted data beat from different network source than initial request.")
} }
@ -1007,7 +996,7 @@ class L2WritebackUnitIO extends HierarchicalXactTrackerIO {
val data = new L2DataRWIO val data = new L2DataRWIO
} }
class L2WritebackUnit(trackerId: Int, bankId: Int) extends L2XactTracker { class L2WritebackUnit(trackerId: Int) extends L2XactTracker {
val io = new L2WritebackUnitIO val io = new L2WritebackUnitIO
val s_idle :: s_inner_probe :: s_data_read :: s_data_resp :: s_outer_release :: s_outer_grant :: s_wb_resp :: Nil = Enum(UInt(), 7) val s_idle :: s_inner_probe :: s_data_read :: s_data_resp :: s_outer_release :: s_outer_grant :: s_wb_resp :: Nil = Enum(UInt(), 7)
@ -1031,9 +1020,7 @@ class L2WritebackUnit(trackerId: Int, bankId: Int) extends L2XactTracker {
val (read_data_cnt, read_data_done) = connectInternalDataBeatCounter(io.data.read) val (read_data_cnt, read_data_done) = connectInternalDataBeatCounter(io.data.read)
val resp_data_done = connectInternalDataBeatCounter(io.data.resp) val resp_data_done = connectInternalDataBeatCounter(io.data.resp)
val pending_icoh_on_irel = xact_coh.inner.onRelease( val pending_icoh_on_irel = xact_coh.inner.onRelease(io.irel())
incoming = io.irel(),
src = io.inner.release.bits.header.src)
val pending_ocoh_on_irel = xact_coh.outer.onHit(M_XWR) // WB is a write val pending_ocoh_on_irel = xact_coh.outer.onHit(M_XWR) // WB is a write
val pending_ofin_on_ognt = io.ognt().makeFinish() val pending_ofin_on_ognt = io.ognt().makeFinish()
@ -1054,10 +1041,7 @@ class L2WritebackUnit(trackerId: Int, bankId: Int) extends L2XactTracker {
io.outer.grant.ready := Bool(false) // default io.outer.grant.ready := Bool(false) // default
io.inner.probe.valid := Bool(false) io.inner.probe.valid := Bool(false)
io.inner.probe.bits.header.src := UInt(bankId) io.inner.probe.bits := xact_coh.inner.makeProbeForVoluntaryWriteback(curr_probe_dst, xact_addr_block)
io.inner.probe.bits.header.dst := curr_probe_dst
io.inner.probe.bits.payload :=
xact_coh.inner.makeProbeForVoluntaryWriteback(xact_addr_block)
io.inner.grant.valid := Bool(false) io.inner.grant.valid := Bool(false)
io.inner.acquire.ready := Bool(false) io.inner.acquire.ready := Bool(false)

View File

@ -60,7 +60,7 @@ class SCRIO extends HTIFBundle {
class HTIFModuleIO extends HTIFBundle { class HTIFModuleIO extends HTIFBundle {
val host = new HostIO val host = new HostIO
val cpu = Vec.fill(nCores){new HTIFIO}.flip val cpu = Vec.fill(nCores){new HTIFIO}.flip
val mem = new HeaderlessUncachedTileLinkIO val mem = new ClientUncachedTileLinkIO
val scr = new SCRIO val scr = new SCRIO
} }

View File

@ -18,16 +18,26 @@ case object MIFDataBits extends Field[Int]
case object MIFTagBits extends Field[Int] case object MIFTagBits extends Field[Int]
case object MIFDataBeats extends Field[Int] case object MIFDataBeats extends Field[Int]
trait HasMemData extends Bundle { trait MIFParameters extends UsesParameters {
val data = Bits(width = params(MIFDataBits)) val mifTagBits = params(MIFTagBits)
val mifAddrBits = params(MIFAddrBits)
val mifDataBits = params(MIFDataBits)
val mifDataBeats = params(MIFDataBeats)
}
abstract class MIFBundle extends Bundle with MIFParameters
abstract class MIFModule extends Module with MIFParameters
trait HasMemData extends MIFBundle {
val data = Bits(width = mifDataBits)
} }
trait HasMemAddr extends Bundle { trait HasMemAddr extends MIFBundle {
val addr = UInt(width = params(MIFAddrBits)) val addr = UInt(width = mifAddrBits)
} }
trait HasMemTag extends Bundle { trait HasMemTag extends MIFBundle {
val tag = UInt(width = params(MIFTagBits)) val tag = UInt(width = mifTagBits)
} }
class MemReqCmd extends HasMemAddr with HasMemTag { class MemReqCmd extends HasMemAddr with HasMemTag {
@ -56,7 +66,7 @@ class MemSerializedIO(w: Int) extends Bundle
val resp = Valid(Bits(width = w)).flip val resp = Valid(Bits(width = w)).flip
} }
class MemSerdes(w: Int) extends Module class MemSerdes(w: Int) extends MIFModule
{ {
val io = new Bundle { val io = new Bundle {
val wide = new MemIO().flip val wide = new MemIO().flip
@ -65,7 +75,6 @@ class MemSerdes(w: Int) extends Module
val abits = io.wide.req_cmd.bits.toBits.getWidth val abits = io.wide.req_cmd.bits.toBits.getWidth
val dbits = io.wide.req_data.bits.toBits.getWidth val dbits = io.wide.req_data.bits.toBits.getWidth
val rbits = io.wide.resp.bits.getWidth val rbits = io.wide.resp.bits.getWidth
val dbeats = params(MIFDataBeats)
val out_buf = Reg(Bits()) val out_buf = Reg(Bits())
val in_buf = Reg(Bits()) val in_buf = Reg(Bits())
@ -73,7 +82,7 @@ class MemSerdes(w: Int) extends Module
val s_idle :: s_read_addr :: s_write_addr :: s_write_idle :: s_write_data :: Nil = Enum(UInt(), 5) val s_idle :: s_read_addr :: s_write_addr :: s_write_idle :: s_write_data :: Nil = Enum(UInt(), 5)
val state = Reg(init=s_idle) val state = Reg(init=s_idle)
val send_cnt = Reg(init=UInt(0, log2Up((max(abits, dbits)+w-1)/w))) val send_cnt = Reg(init=UInt(0, log2Up((max(abits, dbits)+w-1)/w)))
val data_send_cnt = Reg(init=UInt(0, log2Up(dbeats))) val data_send_cnt = Reg(init=UInt(0, log2Up(mifDataBeats)))
val adone = io.narrow.req.ready && send_cnt === UInt((abits-1)/w) val adone = io.narrow.req.ready && send_cnt === UInt((abits-1)/w)
val ddone = io.narrow.req.ready && send_cnt === UInt((dbits-1)/w) val ddone = io.narrow.req.ready && send_cnt === UInt((dbits-1)/w)
@ -109,12 +118,12 @@ class MemSerdes(w: Int) extends Module
} }
when (state === s_write_data && ddone) { when (state === s_write_data && ddone) {
data_send_cnt := data_send_cnt + UInt(1) data_send_cnt := data_send_cnt + UInt(1)
state := Mux(data_send_cnt === UInt(dbeats-1), s_idle, s_write_idle) state := Mux(data_send_cnt === UInt(mifDataBeats-1), s_idle, s_write_idle)
send_cnt := UInt(0) send_cnt := UInt(0)
} }
val recv_cnt = Reg(init=UInt(0, log2Up((rbits+w-1)/w))) val recv_cnt = Reg(init=UInt(0, log2Up((rbits+w-1)/w)))
val data_recv_cnt = Reg(init=UInt(0, log2Up(dbeats))) val data_recv_cnt = Reg(init=UInt(0, log2Up(mifDataBeats)))
val resp_val = Reg(init=Bool(false)) val resp_val = Reg(init=Bool(false))
resp_val := Bool(false) resp_val := Bool(false)
@ -143,11 +152,11 @@ class MemDesser(w: Int) extends Module // test rig side
val abits = io.wide.req_cmd.bits.toBits.getWidth val abits = io.wide.req_cmd.bits.toBits.getWidth
val dbits = io.wide.req_data.bits.toBits.getWidth val dbits = io.wide.req_data.bits.toBits.getWidth
val rbits = io.wide.resp.bits.getWidth val rbits = io.wide.resp.bits.getWidth
val dbeats = params(MIFDataBeats) val mifDataBeats = params(MIFDataBeats)
require(dbits >= abits && rbits >= dbits) require(dbits >= abits && rbits >= dbits)
val recv_cnt = Reg(init=UInt(0, log2Up((rbits+w-1)/w))) val recv_cnt = Reg(init=UInt(0, log2Up((rbits+w-1)/w)))
val data_recv_cnt = Reg(init=UInt(0, log2Up(dbeats))) val data_recv_cnt = Reg(init=UInt(0, log2Up(mifDataBeats)))
val adone = io.narrow.req.valid && recv_cnt === UInt((abits-1)/w) val adone = io.narrow.req.valid && recv_cnt === UInt((abits-1)/w)
val ddone = io.narrow.req.valid && recv_cnt === UInt((dbits-1)/w) val ddone = io.narrow.req.valid && recv_cnt === UInt((dbits-1)/w)
val rdone = io.narrow.resp.valid && recv_cnt === UInt((rbits-1)/w) val rdone = io.narrow.resp.valid && recv_cnt === UInt((rbits-1)/w)
@ -175,13 +184,13 @@ class MemDesser(w: Int) extends Module // test rig side
} }
when (state === s_data && io.wide.req_data.ready) { when (state === s_data && io.wide.req_data.ready) {
state := s_data_recv state := s_data_recv
when (data_recv_cnt === UInt(dbeats-1)) { when (data_recv_cnt === UInt(mifDataBeats-1)) {
state := s_cmd_recv state := s_cmd_recv
} }
data_recv_cnt := data_recv_cnt + UInt(1) data_recv_cnt := data_recv_cnt + UInt(1)
} }
when (rdone) { // state === s_reply when (rdone) { // state === s_reply
when (data_recv_cnt === UInt(dbeats-1)) { when (data_recv_cnt === UInt(mifDataBeats-1)) {
state := s_cmd_recv state := s_cmd_recv
} }
recv_cnt := UInt(0) recv_cnt := UInt(0)
@ -195,7 +204,7 @@ class MemDesser(w: Int) extends Module // test rig side
io.wide.req_data.valid := state === s_data io.wide.req_data.valid := state === s_data
io.wide.req_data.bits.data := in_buf >> UInt(((rbits+w-1)/w - (dbits+w-1)/w)*w) io.wide.req_data.bits.data := in_buf >> UInt(((rbits+w-1)/w - (dbits+w-1)/w)*w)
val dataq = Module(new Queue(new MemResp, dbeats)) val dataq = Module(new Queue(new MemResp, mifDataBeats))
dataq.io.enq <> io.wide.resp dataq.io.enq <> io.wide.resp
dataq.io.deq.ready := recv_cnt === UInt((rbits-1)/w) dataq.io.deq.ready := recv_cnt === UInt((rbits-1)/w)
@ -203,19 +212,12 @@ class MemDesser(w: Int) extends Module // test rig side
io.narrow.resp.bits := dataq.io.deq.bits.toBits >> (recv_cnt * UInt(w)) io.narrow.resp.bits := dataq.io.deq.bits.toBits >> (recv_cnt * UInt(w))
} }
//Adapter between a TileLinkIO and a UncachedTileLinkIO, merges voluntary
//Adapter betweewn an UncachedTileLinkIO and a mem controller MemIO //Adapter betweewn an UncachedTileLinkIO and a mem controller MemIO
class MemIOTileLinkIOConverter(qDepth: Int) extends TLModule { class MemIOTileLinkIOConverter(qDepth: Int) extends TLModule with MIFParameters {
val io = new Bundle { val io = new Bundle {
val tl = new TileLinkIO().flip val tl = new ManagerTileLinkIO
val mem = new MemIO val mem = new MemIO
} }
val mifTagBits = params(MIFTagBits)
val mifAddrBits = params(MIFAddrBits)
val mifDataBits = params(MIFDataBits)
val mifDataBeats = params(MIFDataBeats)
val dataBits = tlDataBits*tlDataBeats val dataBits = tlDataBits*tlDataBeats
val dstIdBits = params(LNHeaderBits) val dstIdBits = params(LNHeaderBits)
require(tlDataBits*tlDataBeats == mifDataBits*mifDataBeats, "Data sizes between LLC and MC don't agree") require(tlDataBits*tlDataBeats == mifDataBits*mifDataBeats, "Data sizes between LLC and MC don't agree")
@ -227,12 +229,12 @@ class MemIOTileLinkIOConverter(qDepth: Int) extends TLModule {
io.tl.finish.ready := Bool(true) io.tl.finish.ready := Bool(true)
io.mem.resp.ready := Bool(false) io.mem.resp.ready := Bool(false)
val gnt_arb = Module(new Arbiter(new LogicalNetworkIO(new Grant), 2)) val gnt_arb = Module(new Arbiter(new GrantToDst, 2))
io.tl.grant <> gnt_arb.io.out io.tl.grant <> gnt_arb.io.out
val dst_off = dstIdBits + tlClientXactIdBits val dst_off = dstIdBits + tlClientXactIdBits
val acq_has_data = io.tl.acquire.bits.payload.hasData() val acq_has_data = io.tl.acquire.bits.hasData()
val rel_has_data = io.tl.release.bits.payload.hasData() val rel_has_data = io.tl.release.bits.hasData()
// Decompose outgoing TL Acquires into MemIO cmd and data // Decompose outgoing TL Acquires into MemIO cmd and data
val active_out = Reg(init=Bool(false)) val active_out = Reg(init=Bool(false))
@ -248,13 +250,12 @@ class MemIOTileLinkIOConverter(qDepth: Int) extends TLModule {
val make_grant_ack = Reg(init=Bool(false)) val make_grant_ack = Reg(init=Bool(false))
gnt_arb.io.in(1).valid := Bool(false) gnt_arb.io.in(1).valid := Bool(false)
gnt_arb.io.in(1).bits.payload := Grant( gnt_arb.io.in(1).bits := Grant(
is_builtin_type = Bool(true), dst = (if(dstIdBits > 0) tag_out(dst_off, tlClientXactIdBits + 1) else UInt(0)),
g_type = Mux(data_from_rel, Grant.voluntaryAckType, Grant.putAckType), is_builtin_type = Bool(true),
client_xact_id = tag_out >> UInt(1), g_type = Mux(data_from_rel, Grant.voluntaryAckType, Grant.putAckType),
manager_xact_id = UInt(0)) client_xact_id = tag_out >> UInt(1),
gnt_arb.io.in(1).bits.header.dst := (if(dstIdBits > 0) tag_out(dst_off, tlClientXactIdBits + 1) else UInt(0)) manager_xact_id = UInt(0))
gnt_arb.io.in(1).bits.header.src := UInt(0)
if(tlDataBits != mifDataBits || tlDataBeats != mifDataBeats) { if(tlDataBits != mifDataBits || tlDataBeats != mifDataBeats) {
val mem_cmd_q = Module(new Queue(new MemReqCmd, qDepth)) val mem_cmd_q = Module(new Queue(new MemReqCmd, qDepth))
@ -263,7 +264,7 @@ class MemIOTileLinkIOConverter(qDepth: Int) extends TLModule {
mem_data_q.io.enq.valid := Bool(false) mem_data_q.io.enq.valid := Bool(false)
val (mif_cnt_out, mif_wrap_out) = Counter(mem_data_q.io.enq.fire(), mifDataBeats) val (mif_cnt_out, mif_wrap_out) = Counter(mem_data_q.io.enq.fire(), mifDataBeats)
val mif_done_out = Reg(init=Bool(false)) val mif_done_out = Reg(init=Bool(false))
val tl_buf_out = Vec.fill(tlDataBeats){ Reg(io.tl.acquire.bits.payload.data.clone) } val tl_buf_out = Vec.fill(tlDataBeats){ Reg(io.tl.acquire.bits.data.clone) }
val mif_buf_out = Vec.fill(mifDataBeats){ new MemData } val mif_buf_out = Vec.fill(mifDataBeats){ new MemData }
mif_buf_out := mif_buf_out.fromBits(tl_buf_out.toBits) mif_buf_out := mif_buf_out.fromBits(tl_buf_out.toBits)
val mif_prog_out = (mif_cnt_out+UInt(1, width = log2Up(mifDataBeats+1)))*UInt(mifDataBits) val mif_prog_out = (mif_cnt_out+UInt(1, width = log2Up(mifDataBeats+1)))*UInt(mifDataBits)
@ -275,27 +276,27 @@ class MemIOTileLinkIOConverter(qDepth: Int) extends TLModule {
when(io.tl.release.valid) { when(io.tl.release.valid) {
active_out := Bool(true) active_out := Bool(true)
cmd_sent_out := Bool(false) cmd_sent_out := Bool(false)
tag_out := Cat(io.tl.release.bits.header.src, tag_out := Cat(io.tl.release.bits.client_id,
io.tl.release.bits.payload.client_xact_id, io.tl.release.bits.client_xact_id,
io.tl.release.bits.payload.isVoluntary()) io.tl.release.bits.isVoluntary())
addr_out := io.tl.release.bits.payload.addr_block addr_out := io.tl.release.bits.addr_block
has_data := rel_has_data has_data := rel_has_data
data_from_rel := Bool(true) data_from_rel := Bool(true)
make_grant_ack := io.tl.release.bits.payload.requiresAck() make_grant_ack := io.tl.release.bits.requiresAck()
tl_done_out := tl_wrap_out tl_done_out := tl_wrap_out
tl_buf_out(tl_cnt_out) := io.tl.release.bits.payload.data tl_buf_out(tl_cnt_out) := io.tl.release.bits.data
} .elsewhen(io.tl.acquire.valid) { } .elsewhen(io.tl.acquire.valid) {
active_out := Bool(true) active_out := Bool(true)
cmd_sent_out := Bool(false) cmd_sent_out := Bool(false)
tag_out := Cat(io.tl.release.bits.header.src, tag_out := Cat(io.tl.release.bits.client_id,
io.tl.acquire.bits.payload.client_xact_id, io.tl.acquire.bits.client_xact_id,
io.tl.acquire.bits.payload.isBuiltInType()) io.tl.acquire.bits.isBuiltInType())
addr_out := io.tl.acquire.bits.payload.addr_block addr_out := io.tl.acquire.bits.addr_block
has_data := acq_has_data has_data := acq_has_data
data_from_rel := Bool(false) data_from_rel := Bool(false)
make_grant_ack := acq_has_data make_grant_ack := acq_has_data
tl_done_out := tl_wrap_out tl_done_out := tl_wrap_out
tl_buf_out(tl_cnt_out) := io.tl.acquire.bits.payload.data tl_buf_out(tl_cnt_out) := io.tl.acquire.bits.data
} }
} }
when(active_out) { when(active_out) {
@ -306,8 +307,8 @@ class MemIOTileLinkIOConverter(qDepth: Int) extends TLModule {
io.tl.acquire.ready := Bool(true) io.tl.acquire.ready := Bool(true)
when(io.tl.acquire.valid) { when(io.tl.acquire.valid) {
tl_buf_out(tl_cnt_out) := Mux(data_from_rel, tl_buf_out(tl_cnt_out) := Mux(data_from_rel,
io.tl.release.bits.payload.data, io.tl.release.bits.data,
io.tl.acquire.bits.payload.data) io.tl.acquire.bits.data)
} }
} }
when(!mif_done_out) { when(!mif_done_out) {
@ -338,8 +339,8 @@ class MemIOTileLinkIOConverter(qDepth: Int) extends TLModule {
io.mem.req_cmd.bits.tag := tag_out io.mem.req_cmd.bits.tag := tag_out
io.mem.req_cmd.bits.addr := addr_out io.mem.req_cmd.bits.addr := addr_out
io.mem.req_data.bits.data := Mux(data_from_rel, io.mem.req_data.bits.data := Mux(data_from_rel,
io.tl.release.bits.payload.data, io.tl.release.bits.data,
io.tl.acquire.bits.payload.data) io.tl.acquire.bits.data)
when(!active_out){ when(!active_out){
io.tl.release.ready := io.mem.req_data.ready io.tl.release.ready := io.mem.req_data.ready
io.tl.acquire.ready := io.mem.req_data.ready && !io.tl.release.valid io.tl.acquire.ready := io.mem.req_data.ready && !io.tl.release.valid
@ -352,12 +353,12 @@ class MemIOTileLinkIOConverter(qDepth: Int) extends TLModule {
tl_done_out := tl_wrap_out tl_done_out := tl_wrap_out
when(io.tl.release.valid) { when(io.tl.release.valid) {
data_from_rel := Bool(true) data_from_rel := Bool(true)
make_grant_ack := io.tl.release.bits.payload.requiresAck() make_grant_ack := io.tl.release.bits.requiresAck()
io.mem.req_data.bits.data := io.tl.release.bits.payload.data io.mem.req_data.bits.data := io.tl.release.bits.data
val tag = Cat(io.tl.release.bits.header.src, val tag = Cat(io.tl.release.bits.client_id,
io.tl.release.bits.payload.client_xact_id, io.tl.release.bits.client_xact_id,
io.tl.release.bits.payload.isVoluntary()) io.tl.release.bits.isVoluntary())
val addr = io.tl.release.bits.payload.addr_block val addr = io.tl.release.bits.addr_block
io.mem.req_cmd.bits.tag := tag io.mem.req_cmd.bits.tag := tag
io.mem.req_cmd.bits.addr := addr io.mem.req_cmd.bits.addr := addr
io.mem.req_cmd.bits.rw := rel_has_data io.mem.req_cmd.bits.rw := rel_has_data
@ -367,12 +368,12 @@ class MemIOTileLinkIOConverter(qDepth: Int) extends TLModule {
} .elsewhen(io.tl.acquire.valid) { } .elsewhen(io.tl.acquire.valid) {
data_from_rel := Bool(false) data_from_rel := Bool(false)
make_grant_ack := acq_has_data // i.e. is it a Put make_grant_ack := acq_has_data // i.e. is it a Put
io.mem.req_data.bits.data := io.tl.acquire.bits.payload.data io.mem.req_data.bits.data := io.tl.acquire.bits.data
io.mem.req_cmd.bits.rw := acq_has_data io.mem.req_cmd.bits.rw := acq_has_data
val tag = Cat(io.tl.acquire.bits.header.src, val tag = Cat(io.tl.acquire.bits.client_id,
io.tl.acquire.bits.payload.client_xact_id, io.tl.acquire.bits.client_xact_id,
io.tl.acquire.bits.payload.isBuiltInType()) io.tl.acquire.bits.isBuiltInType())
val addr = io.tl.acquire.bits.payload.addr_block val addr = io.tl.acquire.bits.addr_block
io.mem.req_cmd.bits.tag := tag io.mem.req_cmd.bits.tag := tag
io.mem.req_cmd.bits.addr := addr io.mem.req_cmd.bits.addr := addr
io.mem.req_cmd.bits.rw := acq_has_data io.mem.req_cmd.bits.rw := acq_has_data
@ -407,28 +408,25 @@ class MemIOTileLinkIOConverter(qDepth: Int) extends TLModule {
// Aggregate incoming MemIO responses into TL Grants // Aggregate incoming MemIO responses into TL Grants
val active_in = Reg(init=Bool(false)) val active_in = Reg(init=Bool(false))
val (tl_cnt_in, tl_wrap_in) = Counter(io.tl.grant.fire() && io.tl.grant.bits.payload.hasMultibeatData(), tlDataBeats) val (tl_cnt_in, tl_wrap_in) = Counter(io.tl.grant.fire() && io.tl.grant.bits.hasMultibeatData(), tlDataBeats)
val tag_in = Reg(UInt(width = mifTagBits)) val tag_in = Reg(UInt(width = mifTagBits))
if(tlDataBits != mifDataBits || tlDataBeats != mifDataBeats) { if(tlDataBits != mifDataBits || tlDataBeats != mifDataBeats) {
val (mif_cnt_in, mif_wrap_in) = Counter(io.mem.resp.fire(), mifDataBeats) // TODO: Assumes all resps have data val (mif_cnt_in, mif_wrap_in) = Counter(io.mem.resp.fire(), mifDataBeats) // TODO: Assumes all resps have data
val mif_done_in = Reg(init=Bool(false)) val mif_done_in = Reg(init=Bool(false))
val mif_buf_in = Vec.fill(mifDataBeats){ Reg(new MemData) } val mif_buf_in = Vec.fill(mifDataBeats){ Reg(new MemData) }
val tl_buf_in = Vec.fill(tlDataBeats){ io.tl.acquire.bits.payload.data.clone } val tl_buf_in = Vec.fill(tlDataBeats){ io.tl.acquire.bits.data.clone }
tl_buf_in := tl_buf_in.fromBits(mif_buf_in.toBits) tl_buf_in := tl_buf_in.fromBits(mif_buf_in.toBits)
val tl_prog_in = (tl_cnt_in+UInt(1, width = log2Up(tlDataBeats+1)))*UInt(tlDataBits) val tl_prog_in = (tl_cnt_in+UInt(1, width = log2Up(tlDataBeats+1)))*UInt(tlDataBits)
val mif_prog_in = mif_cnt_in*UInt(mifDataBits) val mif_prog_in = mif_cnt_in*UInt(mifDataBits)
gnt_arb.io.in(0).bits.payload := Grant( gnt_arb.io.in(0).bits := Grant(
is_builtin_type = tag_in(0), dst = (if(dstIdBits > 0) tag_in(dst_off, tlClientXactIdBits + 1) else UInt(0)),
g_type = Mux(tag_in(0), is_builtin_type = tag_in(0),
Grant.getDataBlockType, g_type = Mux(tag_in(0), Grant.getDataBlockType, UInt(0)), // TODO: Assumes MI or MEI protocol
UInt(0)), // TODO: Assumes MI or MEI protocol client_xact_id = tag_in >> UInt(1),
client_xact_id = tag_in >> UInt(1), manager_xact_id = UInt(0),
manager_xact_id = UInt(0), addr_beat = tl_cnt_in,
addr_beat = tl_cnt_in, data = tl_buf_in(tl_cnt_in))
data = tl_buf_in(tl_cnt_in))
gnt_arb.io.in(0).bits.header.dst := (if(dstIdBits > 0) tag_in(dst_off, tlClientXactIdBits + 1) else UInt(0))
gnt_arb.io.in(0).bits.header.src := UInt(0)
when(!active_in) { when(!active_in) {
io.mem.resp.ready := Bool(true) io.mem.resp.ready := Bool(true)
@ -453,17 +451,14 @@ class MemIOTileLinkIOConverter(qDepth: Int) extends TLModule {
} else { // Don't generate all the uneeded data buffers and flow resp } else { // Don't generate all the uneeded data buffers and flow resp
gnt_arb.io.in(0).valid := io.mem.resp.valid gnt_arb.io.in(0).valid := io.mem.resp.valid
io.mem.resp.ready := gnt_arb.io.in(0).ready io.mem.resp.ready := gnt_arb.io.in(0).ready
gnt_arb.io.in(0).bits.payload := Grant( gnt_arb.io.in(0).bits := Grant(
is_builtin_type = io.mem.resp.bits.tag(0), dst = (if(dstIdBits > 0) io.mem.resp.bits.tag(dst_off, tlClientXactIdBits + 1) else UInt(0)),
g_type = Mux(io.mem.resp.bits.tag(0), is_builtin_type = io.mem.resp.bits.tag(0),
Grant.getDataBlockType, g_type = Mux(io.mem.resp.bits.tag(0), Grant.getDataBlockType, UInt(0)), // TODO: Assumes MI or MEI protocol
UInt(0)), // TODO: Assumes MI or MEI protocol client_xact_id = io.mem.resp.bits.tag >> UInt(1),
client_xact_id = io.mem.resp.bits.tag >> UInt(1), manager_xact_id = UInt(0),
manager_xact_id = UInt(0), addr_beat = tl_cnt_in,
addr_beat = tl_cnt_in, data = io.mem.resp.bits.data)
data = io.mem.resp.bits.data)
gnt_arb.io.in(0).bits.header.dst := (if(dstIdBits > 0) io.mem.resp.bits.tag(dst_off, tlClientXactIdBits + 1) else UInt(0))
gnt_arb.io.in(0).bits.header.src := UInt(0)
} }
} }
@ -522,28 +517,28 @@ object HellaQueue
} }
} }
class MemPipeIOMemIOConverter(numRequests: Int, refillCycles: Int) extends Module { class MemPipeIOMemIOConverter(numRequests: Int) extends MIFModule {
val io = new Bundle { val io = new Bundle {
val cpu = new MemIO().flip val cpu = new MemIO().flip
val mem = new MemPipeIO val mem = new MemPipeIO
} }
val numEntries = numRequests * refillCycles val numEntries = numRequests * mifDataBeats
val size = log2Down(numEntries) + 1 val size = log2Down(numEntries) + 1
val inc = Bool() val inc = Bool()
val dec = Bool() val dec = Bool()
val count = Reg(init=UInt(numEntries, size)) val count = Reg(init=UInt(numEntries, size))
val watermark = count >= UInt(refillCycles) val watermark = count >= UInt(mifDataBeats)
when (inc && !dec) { when (inc && !dec) {
count := count + UInt(1) count := count + UInt(1)
} }
when (!inc && dec) { when (!inc && dec) {
count := count - UInt(refillCycles) count := count - UInt(mifDataBeats)
} }
when (inc && dec) { when (inc && dec) {
count := count - UInt(refillCycles-1) count := count - UInt(mifDataBeats-1)
} }
val cmdq_mask = io.cpu.req_cmd.bits.rw || watermark val cmdq_mask = io.cpu.req_cmd.bits.rw || watermark
@ -573,17 +568,17 @@ class MemPipeIOMemIOConverter(numRequests: Int, refillCycles: Int) extends Modul
dec := io.mem.req_cmd.fire() && !io.mem.req_cmd.bits.rw dec := io.mem.req_cmd.fire() && !io.mem.req_cmd.bits.rw
} }
class MemPipeIOTileLinkIOConverter(outstanding: Int, refillCycles: Int) extends Module { class MemPipeIOTileLinkIOConverter(outstanding: Int) extends MIFModule {
val io = new Bundle { val io = new Bundle {
val tl = new TileLinkIO().flip val tl = new ManagerTileLinkIO
val mem = new MemPipeIO val mem = new MemPipeIO
} }
val a = Module(new MemIOTileLinkIOConverter(1)) val a = Module(new MemIOTileLinkIOConverter(1))
val b = Module(new MemPipeIOMemIOConverter(outstanding, refillCycles)) val b = Module(new MemPipeIOMemIOConverter(outstanding))
a.io.tl <> io.tl a.io.tl <> io.tl
b.io.cpu.req_cmd <> Queue(a.io.mem.req_cmd, 2, pipe=true) b.io.cpu.req_cmd <> Queue(a.io.mem.req_cmd, 2, pipe=true)
b.io.cpu.req_data <> Queue(a.io.mem.req_data, refillCycles, pipe=true) b.io.cpu.req_data <> Queue(a.io.mem.req_data, mifDataBeats, pipe=true)
a.io.mem.resp <> b.io.cpu.resp a.io.mem.resp <> b.io.cpu.resp
b.io.mem <> io.mem b.io.mem <> io.mem
} }

View File

@ -108,17 +108,18 @@ class ManagerMetadata extends CoherenceMetadata {
def requiresProbesOnVoluntaryWriteback(dummy: Int = 0): Bool = def requiresProbesOnVoluntaryWriteback(dummy: Int = 0): Bool =
co.requiresProbes(M_FLUSH, this) co.requiresProbes(M_FLUSH, this)
def makeProbe(cmd: UInt, addr_block: UInt): Probe = def makeProbe(dst: UInt, cmd: UInt, addr_block: UInt): ProbeToDst =
Bundle(Probe(co.getProbeType(cmd, this), addr_block), { case TLId => id }) Bundle(Probe(dst, co.getProbeType(cmd, this), addr_block), { case TLId => id })
def makeProbe(acq: Acquire): Probe = def makeProbe(dst: UInt, acq: Acquire): ProbeToDst =
Bundle(Probe(co.getProbeType(acq, this), acq.addr_block), { case TLId => id }) Bundle(Probe(dst, co.getProbeType(acq, this), acq.addr_block), { case TLId => id })
def makeProbeForVoluntaryWriteback(addr_block: UInt): Probe = def makeProbeForVoluntaryWriteback(dst: UInt, addr_block: UInt): ProbeToDst =
makeProbe(M_FLUSH, addr_block) makeProbe(dst, M_FLUSH, addr_block)
def makeGrant(rel: Release, manager_xact_id: UInt): Grant = { def makeGrant(rel: ReleaseFromSrc, manager_xact_id: UInt): GrantToDst = {
Bundle(Grant( Bundle(Grant(
dst = rel.client_id,
is_builtin_type = Bool(true), is_builtin_type = Bool(true),
g_type = Grant.voluntaryAckType, g_type = Grant.voluntaryAckType,
client_xact_id = rel.client_xact_id, client_xact_id = rel.client_xact_id,
@ -126,11 +127,12 @@ class ManagerMetadata extends CoherenceMetadata {
} }
def makeGrant( def makeGrant(
acq: Acquire, acq: AcquireFromSrc,
manager_xact_id: UInt, manager_xact_id: UInt,
addr_beat: UInt = UInt(0), addr_beat: UInt = UInt(0),
data: UInt = UInt(0)): Grant = { data: UInt = UInt(0)): GrantToDst = {
Bundle(Grant( Bundle(Grant(
dst = acq.client_id,
is_builtin_type = acq.isBuiltInType(), is_builtin_type = acq.isBuiltInType(),
g_type = Mux(acq.isBuiltInType(), g_type = Mux(acq.isBuiltInType(),
acq.getBuiltInGrantType(), acq.getBuiltInGrantType(),
@ -141,11 +143,24 @@ class ManagerMetadata extends CoherenceMetadata {
data = data), { case TLId => id }) data = data), { case TLId => id })
} }
def onRelease(incoming: Release, src: UInt): ManagerMetadata = def makeGrant(
Bundle(co.managerMetadataOnRelease(incoming, src, this), { case TLId => id }) dst: UInt,
acq: AcquireFromSrc,
client_xact_id: UInt,
manager_xact_id: UInt,
addr_beat: UInt,
data: UInt): GrantToDst = {
val g = makeGrant(acq, manager_xact_id, addr_beat, data)
g.client_id := dst
g.client_xact_id := client_xact_id
g
}
def onRelease(incoming: ReleaseFromSrc): ManagerMetadata =
Bundle(co.managerMetadataOnRelease(incoming, incoming.client_id, this), { case TLId => id })
def onGrant(outgoing: Grant, dst: UInt): ManagerMetadata = def onGrant(outgoing: GrantToDst): ManagerMetadata =
Bundle(co.managerMetadataOnGrant(outgoing, dst, this), { case TLId => id }) Bundle(co.managerMetadataOnGrant(outgoing, outgoing.client_id, this), { case TLId => id })
} }
object ManagerMetadata { object ManagerMetadata {

View File

@ -23,12 +23,14 @@ case object TLDataBits extends Field[Int]
case object TLDataBeats extends Field[Int] case object TLDataBeats extends Field[Int]
case object TLNetworkIsOrderedP2P extends Field[Boolean] case object TLNetworkIsOrderedP2P extends Field[Boolean]
abstract trait TileLinkParameters extends UsesParameters { trait TileLinkParameters extends UsesParameters {
val tlCoh = params(TLCoherencePolicy) val tlCoh = params(TLCoherencePolicy)
val tlNManagers = params(TLNManagers) val tlNManagers = params(TLNManagers)
val tlNClients = params(TLNClients) val tlNClients = params(TLNClients)
val tlNCoherentClients = params(TLNCoherentClients) val tlNCoherentClients = params(TLNCoherentClients)
val tlNIncoherentClients = params(TLNIncoherentClients) val tlNIncoherentClients = params(TLNIncoherentClients)
val tlClientIdBits = log2Up(tlNClients)
val tlManagerIdBits = log2Up(tlNManagers)
val tlMaxClientXacts = params(TLMaxClientXacts) val tlMaxClientXacts = params(TLMaxClientXacts)
val tlMaxClientPorts = params(TLMaxClientPorts) val tlMaxClientPorts = params(TLMaxClientPorts)
val tlMaxManagerXacts = params(TLMaxManagerXacts) val tlMaxManagerXacts = params(TLMaxManagerXacts)
@ -98,6 +100,10 @@ trait HasTileLinkData extends HasTileLinkBeatId {
def hasMultibeatData(dummy: Int = 0): Bool def hasMultibeatData(dummy: Int = 0): Bool
} }
trait HasClientId extends TLBundle {
val client_id = UInt(width = tlClientIdBits)
}
// Actual TileLink channel bundle definitions // Actual TileLink channel bundle definitions
class Acquire extends ClientToManagerChannel class Acquire extends ClientToManagerChannel
@ -350,12 +356,19 @@ class Probe extends ManagerToClientChannel
} }
object Probe { object Probe {
def apply(p_type: UInt, addr_block: UInt) = { def apply(p_type: UInt, addr_block: UInt): Probe = {
val prb = new Probe val prb = new Probe
prb.p_type := p_type prb.p_type := p_type
prb.addr_block := addr_block prb.addr_block := addr_block
prb prb
} }
def apply(dst: UInt, p_type: UInt, addr_block: UInt): ProbeToDst = {
val prb = new ProbeToDst
prb.client_id := dst
prb.p_type := p_type
prb.addr_block := addr_block
prb
}
} }
class Release extends ClientToManagerChannel class Release extends ClientToManagerChannel
@ -435,8 +448,8 @@ object Grant {
g_type: UInt, g_type: UInt,
client_xact_id: UInt, client_xact_id: UInt,
manager_xact_id: UInt, manager_xact_id: UInt,
addr_beat: UInt = UInt(0), addr_beat: UInt,
data: UInt = UInt(0)): Grant = { data: UInt): Grant = {
val gnt = new Grant val gnt = new Grant
gnt.is_builtin_type := is_builtin_type gnt.is_builtin_type := is_builtin_type
gnt.g_type := g_type gnt.g_type := g_type
@ -446,6 +459,25 @@ object Grant {
gnt.data := data gnt.data := data
gnt gnt
} }
def apply(
dst: UInt,
is_builtin_type: Bool,
g_type: UInt,
client_xact_id: UInt,
manager_xact_id: UInt,
addr_beat: UInt = UInt(0),
data: UInt = UInt(0)): GrantToDst = {
val gnt = new GrantToDst
gnt.client_id := dst
gnt.is_builtin_type := is_builtin_type
gnt.g_type := g_type
gnt.client_xact_id := client_xact_id
gnt.manager_xact_id := manager_xact_id
gnt.addr_beat := addr_beat
gnt.data := data
gnt
}
} }
class Finish extends ClientToManagerChannel with HasManagerTransactionId { class Finish extends ClientToManagerChannel with HasManagerTransactionId {
@ -453,7 +485,14 @@ class Finish extends ClientToManagerChannel with HasManagerTransactionId {
def hasMultibeatData(dummy: Int = 0) = Bool(false) def hasMultibeatData(dummy: Int = 0) = Bool(false)
} }
// Complete IO definitions for two types of TileLink clients // These subtypes include a field for the source or destination ClientId
class AcquireFromSrc extends Acquire with HasClientId
class ProbeToDst extends Probe with HasClientId
class ReleaseFromSrc extends Release with HasClientId
class GrantToDst extends Grant with HasClientId
// Complete IO definitions for two types of TileLink clients, including
// networking headers
class UncachedTileLinkIO extends TLBundle { class UncachedTileLinkIO extends TLBundle {
val acquire = new DecoupledIO(new LogicalNetworkIO(new Acquire)) val acquire = new DecoupledIO(new LogicalNetworkIO(new Acquire))
val grant = new DecoupledIO(new LogicalNetworkIO(new Grant)).flip val grant = new DecoupledIO(new LogicalNetworkIO(new Grant)).flip
@ -479,28 +518,36 @@ class TileLinkIOWrapper extends TLModule {
io.out.release.valid := Bool(false) io.out.release.valid := Bool(false)
} }
// This version of TileLinkIO does not contain network headers for packets // This version of TileLinkIO does not contain network headers. The headers
// that originate in the Clients (i.e. Acquire and Release). These headers // are provided in the top-level that instantiates the clients and network,
// are provided in the top-level that instantiates the clients and network. // probably using a TileLinkClientPort module.
// By eliding the header subbundles within the clients we can enable // By eliding the header subbundles within the clients we can enable
// hierarchical P&R while minimizing unconnected port errors in GDS. // hierarchical P&R while minimizing unconnected port errors in GDS.
// Secondly, this version of the interface elides Finish messages, with the // Secondly, this version of the interface elides Finish messages, with the
// assumption that a FinishUnit has been coupled to the TileLinkIO port // assumption that a FinishUnit has been coupled to the TileLinkIO port
// to deal with acking received Grants. // to deal with acking received Grants.
class HeaderlessUncachedTileLinkIO extends TLBundle { class ClientUncachedTileLinkIO extends TLBundle {
val acquire = new DecoupledIO(new Acquire) val acquire = new DecoupledIO(new Acquire)
val grant = new DecoupledIO(new Grant).flip val grant = new DecoupledIO(new Grant).flip
} }
class HeaderlessTileLinkIO extends HeaderlessUncachedTileLinkIO { class ClientTileLinkIO extends ClientUncachedTileLinkIO {
val probe = new DecoupledIO(new Probe).flip val probe = new DecoupledIO(new Probe).flip
val release = new DecoupledIO(new Release) val release = new DecoupledIO(new Release)
} }
class HeaderlessTileLinkIOWrapper extends TLModule { class ManagerTileLinkIO extends TLBundle {
val acquire = new DecoupledIO(new AcquireFromSrc).flip
val grant = new DecoupledIO(new GrantToDst)
val finish = new DecoupledIO(new Finish).flip
val probe = new DecoupledIO(new ProbeToDst)
val release = new DecoupledIO(new ReleaseFromSrc).flip
}
class ClientTileLinkIOWrapper extends TLModule {
val io = new Bundle { val io = new Bundle {
val in = new HeaderlessUncachedTileLinkIO().flip val in = new ClientUncachedTileLinkIO().flip
val out = new HeaderlessTileLinkIO val out = new ClientTileLinkIO
} }
io.out.acquire <> io.in.acquire io.out.acquire <> io.in.acquire
io.out.grant <> io.in.grant io.out.grant <> io.in.grant
@ -509,17 +556,17 @@ class HeaderlessTileLinkIOWrapper extends TLModule {
} }
object TileLinkIOWrapper { object TileLinkIOWrapper {
def apply(utl: HeaderlessUncachedTileLinkIO, p: Parameters): HeaderlessTileLinkIO = { def apply(utl: ClientUncachedTileLinkIO, p: Parameters): ClientTileLinkIO = {
val conv = Module(new HeaderlessTileLinkIOWrapper)(p) val conv = Module(new ClientTileLinkIOWrapper)(p)
conv.io.in <> utl conv.io.in <> utl
conv.io.out conv.io.out
} }
def apply(utl: HeaderlessUncachedTileLinkIO): HeaderlessTileLinkIO = { def apply(utl: ClientUncachedTileLinkIO): ClientTileLinkIO = {
val conv = Module(new HeaderlessTileLinkIOWrapper) val conv = Module(new ClientTileLinkIOWrapper)
conv.io.in <> utl conv.io.in <> utl
conv.io.out conv.io.out
} }
def apply(tl: HeaderlessTileLinkIO): HeaderlessTileLinkIO = tl def apply(tl: ClientTileLinkIO): ClientTileLinkIO = tl
def apply(utl: UncachedTileLinkIO, p: Parameters): TileLinkIO = { def apply(utl: UncachedTileLinkIO, p: Parameters): TileLinkIO = {
val conv = Module(new TileLinkIOWrapper)(p) val conv = Module(new TileLinkIOWrapper)(p)
conv.io.in <> utl conv.io.in <> utl
@ -533,89 +580,6 @@ object TileLinkIOWrapper {
def apply(tl: TileLinkIO): TileLinkIO = tl def apply(tl: TileLinkIO): TileLinkIO = tl
} }
trait HasDataBeatCounters {
type HasBeat = TileLinkChannel with HasTileLinkBeatId
type HasClientId = TileLinkChannel with HasClientTransactionId
type LNAcquire = LogicalNetworkIO[Acquire]
type LNRelease = LogicalNetworkIO[Release]
type LNGrant = LogicalNetworkIO[Grant]
def connectDataBeatCounter[S <: TileLinkChannel : ClassTag](inc: Bool, data: S, beat: UInt) = {
val multi = data.hasMultibeatData()
val (multi_cnt, multi_done) = Counter(inc && multi, data.tlDataBeats)
val cnt = Mux(multi, multi_cnt, beat)
val done = Mux(multi, multi_done, inc)
(cnt, done)
}
def connectOutgoingDataBeatCounter[T <: Data : TypeTag](
in: DecoupledIO[T],
beat: UInt = UInt(0)): (UInt, Bool) = {
in.bits match {
case p: TileLinkChannel if typeTag[T].tpe <:< typeTag[TileLinkChannel].tpe =>
connectDataBeatCounter(in.fire(), p, beat)
case ln: LNGrant if typeTag[T].tpe <:< typeTag[LNGrant].tpe =>
connectDataBeatCounter(in.fire(), ln.payload, beat)
case _ => { require(false, "Don't know how to connect a beat counter to " + typeTag[T].tpe); (UInt(0), Bool(false))}
}
}
def connectIncomingDataBeatCounters[T <: HasClientId : ClassTag](
in: DecoupledIO[LogicalNetworkIO[T]],
entries: Int,
getId: LogicalNetworkIO[T] => UInt): Vec[Bool] = {
Vec((0 until entries).map { i =>
connectDataBeatCounter(in.fire() && getId(in.bits) === UInt(i), in.bits.payload, UInt(0))._2
})
}
def connectIncomingDataBeatCounter[T <: Data : TypeTag](in: DecoupledIO[T]): Bool = {
in.bits match {
case p: TileLinkChannel if typeTag[T].tpe <:< typeTag[TileLinkChannel].tpe =>
connectDataBeatCounter(in.fire(), p, UInt(0))._2
case ln: LNAcquire if typeTag[T].tpe =:= typeTag[LNAcquire].tpe =>
connectDataBeatCounter(in.fire(), ln.payload, UInt(0))._2
case ln: LNRelease if typeTag[T].tpe =:= typeTag[LNRelease].tpe =>
connectDataBeatCounter(in.fire(), ln.payload, UInt(0))._2
case ln: LNGrant if typeTag[T].tpe =:= typeTag[LNGrant].tpe =>
connectDataBeatCounter(in.fire(), ln.payload, UInt(0))._2
case _ => { require(false, "Don't know how to connect a beat counter to " + typeTag[T].tpe); Bool(false)}
}
}
def connectHeaderlessTwoWayBeatCounter[ T <: TileLinkChannel : ClassTag, S <: TileLinkChannel : ClassTag](
max: Int,
up: DecoupledIO[T],
down: DecoupledIO[S],
beat: UInt): (Bool, UInt, Bool, UInt, Bool) = {
val cnt = Reg(init = UInt(0, width = log2Up(max+1)))
val (up_idx, do_inc) = connectDataBeatCounter(up.fire(), up.bits, beat)
val (down_idx, do_dec) = connectDataBeatCounter(down.fire(), down.bits, beat)
//Module.assert(!(do_dec && cnt === UInt(0)), "Decrementing 2way beat counter before ever incrementing")
cnt := Mux(do_dec,
Mux(do_inc, cnt, cnt - UInt(1)),
Mux(do_inc, cnt + UInt(1), cnt))
(cnt > UInt(0), up_idx, do_inc, down_idx, do_dec)
}
def connectTwoWayBeatCounter[ T <: TileLinkChannel : ClassTag, S <: TileLinkChannel : ClassTag](
max: Int,
up: DecoupledIO[LogicalNetworkIO[T]],
down: DecoupledIO[LogicalNetworkIO[S]],
inc: T => Bool = (t: T) => Bool(true),
dec: S => Bool = (s: S) => Bool(true)): (Bool, UInt, Bool, UInt, Bool) = {
val cnt = Reg(init = UInt(0, width = log2Up(max+1)))
val (up_idx, up_done) = connectDataBeatCounter(up.fire(), up.bits.payload, UInt(0))
val (down_idx, down_done) = connectDataBeatCounter(down.fire(), down.bits.payload, UInt(0))
val do_inc = up_done && inc(up.bits.payload)
val do_dec = down_done && dec(down.bits.payload)
cnt := Mux(do_dec,
Mux(do_inc, cnt, cnt - UInt(1)),
Mux(do_inc, cnt + UInt(1), cnt))
(cnt > UInt(0), up_idx, up_done, down_idx, down_done)
}
}
class FinishQueueEntry extends TLBundle { class FinishQueueEntry extends TLBundle {
val fin = new Finish val fin = new Finish
val dst = UInt(width = log2Up(params(LNEndpoints))) val dst = UInt(width = log2Up(params(LNEndpoints)))
@ -623,8 +587,7 @@ class FinishQueueEntry extends TLBundle {
class FinishQueue(entries: Int) extends Queue(new FinishQueueEntry, entries) class FinishQueue(entries: Int) extends Queue(new FinishQueueEntry, entries)
class FinishUnit(srcId: Int = 0, outstanding: Int = 2) extends TLModule class FinishUnit(srcId: Int = 0, outstanding: Int = 2) extends TLModule with HasDataBeatCounters {
with HasDataBeatCounters {
val io = new Bundle { val io = new Bundle {
val grant = Decoupled(new LogicalNetworkIO(new Grant)).flip val grant = Decoupled(new LogicalNetworkIO(new Grant)).flip
val refill = Decoupled(new Grant) val refill = Decoupled(new Grant)
@ -645,12 +608,12 @@ class FinishUnit(srcId: Int = 0, outstanding: Int = 2) extends TLModule
// a multibeat Grant. But Grants from multiple managers or transactions may // a multibeat Grant. But Grants from multiple managers or transactions may
// get interleaved, so we could need a counter for each. // get interleaved, so we could need a counter for each.
val done = if(tlNetworkDoesNotInterleaveBeats) { val done = if(tlNetworkDoesNotInterleaveBeats) {
connectIncomingDataBeatCounter(io.grant) connectIncomingDataBeatCounterWithHeader(io.grant)
} else { } else {
val entries = 1 << tlClientXactIdBits val entries = 1 << tlClientXactIdBits
def getId(g: LogicalNetworkIO[Grant]) = g.payload.client_xact_id def getId(g: LogicalNetworkIO[Grant]) = g.payload.client_xact_id
assert(getId(io.grant.bits) <= UInt(entries), "Not enough grant beat counters, only " + entries + " entries.") assert(getId(io.grant.bits) <= UInt(entries), "Not enough grant beat counters, only " + entries + " entries.")
connectIncomingDataBeatCounters(io.grant, entries, getId).reduce(_||_) connectIncomingDataBeatCountersWithHeader(io.grant, entries, getId).reduce(_||_)
} }
val q = Module(new FinishQueue(outstanding)) val q = Module(new FinishQueue(outstanding))
q.io.enq.valid := io.grant.fire() && g.requiresAck() && (!g.hasMultibeatData() || done) q.io.enq.valid := io.grant.fire() && g.requiresAck() && (!g.hasMultibeatData() || done)
@ -670,30 +633,7 @@ class FinishUnit(srcId: Int = 0, outstanding: Int = 2) extends TLModule
} }
} }
object TileLinkHeaderOverwriter { object ClientTileLinkHeaderCreator {
def apply[T <: ClientToManagerChannel](
in: DecoupledIO[LogicalNetworkIO[T]],
clientId: Int,
passThrough: Boolean): DecoupledIO[LogicalNetworkIO[T]] = {
val out = in.clone.asDirectionless
out.bits.payload := in.bits.payload
out.bits.header.src := UInt(clientId)
out.bits.header.dst := (if(passThrough) in.bits.header.dst else UInt(0))
out.valid := in.valid
in.ready := out.ready
out
}
def apply[T <: ClientToManagerChannel with HasCacheBlockAddress](
in: DecoupledIO[LogicalNetworkIO[T]],
clientId: Int,
nBanks: Int,
addrConvert: UInt => UInt): DecoupledIO[LogicalNetworkIO[T]] = {
val out: DecoupledIO[LogicalNetworkIO[T]] = apply(in, clientId, false)
out.bits.header.dst := addrConvert(in.bits.payload.addr_block)
out
}
def apply[T <: ClientToManagerChannel with HasCacheBlockAddress : ClassTag]( def apply[T <: ClientToManagerChannel with HasCacheBlockAddress : ClassTag](
in: DecoupledIO[T], in: DecoupledIO[T],
clientId: Int, clientId: Int,
@ -708,9 +648,24 @@ object TileLinkHeaderOverwriter {
} }
} }
class TileLinkNetworkPort(clientId: Int, addrConvert: UInt => UInt) extends TLModule { object ManagerTileLinkHeaderCreator {
def apply[T <: ManagerToClientChannel with HasClientId : ClassTag](
in: DecoupledIO[T],
managerId: Int,
idConvert: UInt => UInt): DecoupledIO[LogicalNetworkIO[T]] = {
val out = new DecoupledIO(new LogicalNetworkIO(in.bits.clone)).asDirectionless
out.bits.payload := in.bits
out.bits.header.src := UInt(managerId)
out.bits.header.dst := idConvert(in.bits.client_id)
out.valid := in.valid
in.ready := out.ready
out
}
}
class ClientTileLinkNetworkPort(clientId: Int, addrConvert: UInt => UInt) extends TLModule {
val io = new Bundle { val io = new Bundle {
val client = new HeaderlessTileLinkIO().flip val client = new ClientTileLinkIO().flip
val network = new TileLinkIO val network = new TileLinkIO
} }
@ -718,8 +673,8 @@ class TileLinkNetworkPort(clientId: Int, addrConvert: UInt => UInt) extends TLMo
finisher.io.grant <> io.network.grant finisher.io.grant <> io.network.grant
io.network.finish <> finisher.io.finish io.network.finish <> finisher.io.finish
val acq_with_header = TileLinkHeaderOverwriter(io.client.acquire, clientId, addrConvert) val acq_with_header = ClientTileLinkHeaderCreator(io.client.acquire, clientId, addrConvert)
val rel_with_header = TileLinkHeaderOverwriter(io.client.release, clientId, addrConvert) val rel_with_header = ClientTileLinkHeaderCreator(io.client.release, clientId, addrConvert)
val prb_without_header = DecoupledLogicalNetworkIOUnwrapper(io.network.probe) val prb_without_header = DecoupledLogicalNetworkIOUnwrapper(io.network.probe)
val gnt_without_header = finisher.io.refill val gnt_without_header = finisher.io.refill
@ -731,58 +686,63 @@ class TileLinkNetworkPort(clientId: Int, addrConvert: UInt => UInt) extends TLMo
io.client.grant <> gnt_without_header io.client.grant <> gnt_without_header
} }
object TileLinkNetworkPort { class ManagerTileLinkNetworkPort(managerId: Int, idConvert: UInt => UInt) extends TLModule {
def apply[T <: Data]( val io = new Bundle {
client: HeaderlessTileLinkIO, val manager = new ManagerTileLinkIO().flip
clientId: Int = 0, val network = new TileLinkIO().flip
addrConvert: UInt => UInt = u => UInt(0))(implicit p: Parameters): TileLinkIO = {
val port = Module(new TileLinkNetworkPort(clientId, addrConvert))(p)
port.io.client <> client
port.io.network
} }
io.network.grant <> ManagerTileLinkHeaderCreator(io.manager.grant, managerId, (u: UInt) => u)
io.network.probe <> ManagerTileLinkHeaderCreator(io.manager.probe, managerId, idConvert)
io.manager.acquire.bits.client_id := io.network.acquire.bits.header.src
io.manager.acquire <> DecoupledLogicalNetworkIOUnwrapper(io.network.acquire)
io.manager.release.bits.client_id := io.network.release.bits.header.src
io.manager.release <> DecoupledLogicalNetworkIOUnwrapper(io.network.release)
io.manager.finish <> DecoupledLogicalNetworkIOUnwrapper(io.network.finish)
} }
class TileLinkEnqueuer(depths: (Int, Int, Int, Int, Int)) extends Module { case class TileLinkDepths(acq: Int, prb: Int, rel: Int, gnt: Int, fin: Int)
class TileLinkEnqueuer(depths: TileLinkDepths) extends Module {
val io = new Bundle { val io = new Bundle {
val client = new TileLinkIO().flip val client = new TileLinkIO().flip
val manager = new TileLinkIO val manager = new TileLinkIO
} }
io.manager.acquire <> (if(depths._1 > 0) Queue(io.client.acquire, depths._1) else io.client.acquire) io.manager.acquire <> (if(depths.acq > 0) Queue(io.client.acquire, depths.acq) else io.client.acquire)
io.client.probe <> (if(depths._2 > 0) Queue(io.manager.probe, depths._2) else io.manager.probe) io.client.probe <> (if(depths.prb > 0) Queue(io.manager.probe, depths.prb) else io.manager.probe)
io.manager.release <> (if(depths._3 > 0) Queue(io.client.release, depths._3) else io.client.release) io.manager.release <> (if(depths.rel > 0) Queue(io.client.release, depths.rel) else io.client.release)
io.client.grant <> (if(depths._4 > 0) Queue(io.manager.grant, depths._4) else io.manager.grant) io.client.grant <> (if(depths.gnt > 0) Queue(io.manager.grant, depths.gnt) else io.manager.grant)
io.manager.finish <> (if(depths._5 > 0) Queue(io.client.finish, depths._5) else io.client.finish) io.manager.finish <> (if(depths.fin > 0) Queue(io.client.finish, depths.fin) else io.client.finish)
} }
object TileLinkEnqueuer { object TileLinkEnqueuer {
def apply(in: TileLinkIO, depths: (Int, Int, Int, Int, Int))(p: Parameters): TileLinkIO = { def apply(in: TileLinkIO, depths: TileLinkDepths)(p: Parameters): TileLinkIO = {
val t = Module(new TileLinkEnqueuer(depths))(p) val t = Module(new TileLinkEnqueuer(depths))(p)
t.io.client <> in t.io.client <> in
t.io.manager t.io.manager
} }
def apply(in: TileLinkIO, depth: Int)(p: Parameters): TileLinkIO = { def apply(in: TileLinkIO, depth: Int)(p: Parameters): TileLinkIO = {
apply(in, (depth, depth, depth, depth, depth))(p) apply(in, TileLinkDepths(depth, depth, depth, depth, depth))(p)
} }
} }
abstract trait HasArbiterTypes { /** Utility functions for constructing TileLinkIO arbiters */
trait TileLinkArbiterLike extends TileLinkParameters {
// Some shorthand type variables
type ManagerSourcedWithId = ManagerToClientChannel with HasClientTransactionId type ManagerSourcedWithId = ManagerToClientChannel with HasClientTransactionId
type ClientSourcedWithId = ClientToManagerChannel with HasClientTransactionId type ClientSourcedWithId = ClientToManagerChannel with HasClientTransactionId
type ClientSourcedWithIdAndData = ClientToManagerChannel with type ClientSourcedWithIdAndData = ClientToManagerChannel with HasClientTransactionId with HasTileLinkData
HasClientTransactionId with
HasTileLinkData
}
// Utility functions for constructing TileLinkIO arbiters val arbN: Int // The number of ports on the client side
trait TileLinkArbiterLike extends HasArbiterTypes with TileLinkParameters{
val arbN: Int // These abstract funcs are filled in depending on whether the arbiter mucks with the
// These are filled in depending on whether the arbiter mucks with the // outgoing client ids to track sourcing and then needs to revert them on the way back
// client ids and then needs to revert them on the way back
def clientSourcedClientXactId(in: ClientSourcedWithId, id: Int): Bits def clientSourcedClientXactId(in: ClientSourcedWithId, id: Int): Bits
def managerSourcedClientXactId(in: ManagerSourcedWithId): Bits def managerSourcedClientXactId(in: ManagerSourcedWithId): Bits
def arbIdx(in: ManagerSourcedWithId): UInt def arbIdx(in: ManagerSourcedWithId): UInt
def hookupClientSource[M <: ClientSourcedWithIdAndData : ClassTag]( // The following functions are all wiring helpers for each of the different types of TileLink channels
def hookupClientSource[M <: ClientSourcedWithIdAndData](
clts: Seq[DecoupledIO[LogicalNetworkIO[M]]], clts: Seq[DecoupledIO[LogicalNetworkIO[M]]],
mngr: DecoupledIO[LogicalNetworkIO[M]]) { mngr: DecoupledIO[LogicalNetworkIO[M]]) {
def hasData(m: LogicalNetworkIO[M]) = m.payload.hasMultibeatData() def hasData(m: LogicalNetworkIO[M]) = m.payload.hasMultibeatData()
@ -796,7 +756,7 @@ trait TileLinkArbiterLike extends HasArbiterTypes with TileLinkParameters{
arb.io.out <> mngr arb.io.out <> mngr
} }
def hookupClientSourceHeaderless[M <: ClientSourcedWithIdAndData : ClassTag]( def hookupClientSourceHeaderless[M <: ClientSourcedWithIdAndData](
clts: Seq[DecoupledIO[M]], clts: Seq[DecoupledIO[M]],
mngr: DecoupledIO[M]) { mngr: DecoupledIO[M]) {
def hasData(m: M) = m.hasMultibeatData() def hasData(m: M) = m.hasMultibeatData()
@ -854,23 +814,20 @@ trait TileLinkArbiterLike extends HasArbiterTypes with TileLinkParameters{
} }
} }
def hookupManagerSourceBroadcast[M <: Data]( def hookupManagerSourceBroadcast[M <: Data](clts: Seq[DecoupledIO[M]], mngr: DecoupledIO[M]) {
clts: Seq[DecoupledIO[M]],
mngr: DecoupledIO[M]) {
clts.map{ _.valid := mngr.valid } clts.map{ _.valid := mngr.valid }
clts.map{ _.bits := mngr.bits } clts.map{ _.bits := mngr.bits }
mngr.ready := clts.map(_.ready).reduce(_&&_) mngr.ready := clts.map(_.ready).reduce(_&&_)
} }
def hookupFinish[M <: LogicalNetworkIO[Finish] : ClassTag]( def hookupFinish[M <: LogicalNetworkIO[Finish]]( clts: Seq[DecoupledIO[M]], mngr: DecoupledIO[M]) {
clts: Seq[DecoupledIO[M]],
mngr: DecoupledIO[M]) {
val arb = Module(new RRArbiter(mngr.bits.clone, arbN)) val arb = Module(new RRArbiter(mngr.bits.clone, arbN))
arb.io.in zip clts map { case (arb, req) => arb <> req } arb.io.in <> clts
arb.io.out <> mngr arb.io.out <> mngr
} }
} }
/** Abstract base case for any Arbiters that have UncachedTileLinkIOs */
abstract class UncachedTileLinkIOArbiter(val arbN: Int) extends Module with TileLinkArbiterLike { abstract class UncachedTileLinkIOArbiter(val arbN: Int) extends Module with TileLinkArbiterLike {
val io = new Bundle { val io = new Bundle {
val in = Vec.fill(arbN){new UncachedTileLinkIO}.flip val in = Vec.fill(arbN){new UncachedTileLinkIO}.flip
@ -881,6 +838,7 @@ abstract class UncachedTileLinkIOArbiter(val arbN: Int) extends Module with Tile
hookupManagerSourceWithId(io.in.map(_.grant), io.out.grant) hookupManagerSourceWithId(io.in.map(_.grant), io.out.grant)
} }
/** Abstract base case for any Arbiters that have cached TileLinkIOs */
abstract class TileLinkIOArbiter(val arbN: Int) extends Module with TileLinkArbiterLike { abstract class TileLinkIOArbiter(val arbN: Int) extends Module with TileLinkArbiterLike {
val io = new Bundle { val io = new Bundle {
val in = Vec.fill(arbN){new TileLinkIO}.flip val in = Vec.fill(arbN){new TileLinkIO}.flip
@ -893,31 +851,7 @@ abstract class TileLinkIOArbiter(val arbN: Int) extends Module with TileLinkArbi
hookupManagerSourceWithId(io.in.map(_.grant), io.out.grant) hookupManagerSourceWithId(io.in.map(_.grant), io.out.grant)
} }
class HeaderlessUncachedTileLinkIOArbiter(val arbN: Int) extends Module /** Appends the port index of the arbiter to the client_xact_id */
with TileLinkArbiterLike
with AppendsArbiterId {
val io = new Bundle {
val in = Vec.fill(arbN){new HeaderlessUncachedTileLinkIO}.flip
val out = new HeaderlessUncachedTileLinkIO
}
hookupClientSourceHeaderless(io.in.map(_.acquire), io.out.acquire)
hookupManagerSourceHeaderlessWithId(io.in.map(_.grant), io.out.grant)
}
class HeaderlessTileLinkIOArbiter(val arbN: Int) extends Module
with TileLinkArbiterLike
with AppendsArbiterId {
val io = new Bundle {
val in = Vec.fill(arbN){new HeaderlessTileLinkIO}.flip
val out = new HeaderlessTileLinkIO
}
hookupClientSourceHeaderless(io.in.map(_.acquire), io.out.acquire)
hookupClientSourceHeaderless(io.in.map(_.release), io.out.release)
hookupManagerSourceBroadcast(io.in.map(_.probe), io.out.probe)
hookupManagerSourceHeaderlessWithId(io.in.map(_.grant), io.out.grant)
}
// Appends the port index of the arbiter to the client_xact_id
trait AppendsArbiterId extends TileLinkArbiterLike { trait AppendsArbiterId extends TileLinkArbiterLike {
def clientSourcedClientXactId(in: ClientSourcedWithId, id: Int) = def clientSourcedClientXactId(in: ClientSourcedWithId, id: Int) =
Cat(in.client_xact_id, UInt(id, log2Up(arbN))) Cat(in.client_xact_id, UInt(id, log2Up(arbN)))
@ -926,24 +860,125 @@ trait AppendsArbiterId extends TileLinkArbiterLike {
def arbIdx(in: ManagerSourcedWithId) = in.client_xact_id(log2Up(arbN)-1,0).toUInt def arbIdx(in: ManagerSourcedWithId) = in.client_xact_id(log2Up(arbN)-1,0).toUInt
} }
// Uses the client_xact_id as is (assumes it has been set to port index) /** Uses the client_xact_id as is (assumes it has been set to port index) */
trait PassesId extends TileLinkArbiterLike { trait PassesId extends TileLinkArbiterLike {
def clientSourcedClientXactId(in: ClientSourcedWithId, id: Int) = in.client_xact_id def clientSourcedClientXactId(in: ClientSourcedWithId, id: Int) = in.client_xact_id
def managerSourcedClientXactId(in: ManagerSourcedWithId) = in.client_xact_id def managerSourcedClientXactId(in: ManagerSourcedWithId) = in.client_xact_id
def arbIdx(in: ManagerSourcedWithId) = in.client_xact_id def arbIdx(in: ManagerSourcedWithId) = in.client_xact_id
} }
// Overwrites some default client_xact_id with the port idx /** Overwrites some default client_xact_id with the port idx */
trait UsesNewId extends TileLinkArbiterLike { trait UsesNewId extends TileLinkArbiterLike {
def clientSourcedClientXactId(in: ClientSourcedWithId, id: Int) = UInt(id, log2Up(arbN)) def clientSourcedClientXactId(in: ClientSourcedWithId, id: Int) = UInt(id, log2Up(arbN))
def managerSourcedClientXactId(in: ManagerSourcedWithId) = UInt(0) def managerSourcedClientXactId(in: ManagerSourcedWithId) = UInt(0)
def arbIdx(in: ManagerSourcedWithId) = in.client_xact_id def arbIdx(in: ManagerSourcedWithId) = in.client_xact_id
} }
// Mix-in id generation traits to make concrete arbiter classes // Now we can mix-in thevarious id-generation traits to make concrete arbiter classes
class UncachedTileLinkIOArbiterThatAppendsArbiterId(val n: Int) extends UncachedTileLinkIOArbiter(n) with AppendsArbiterId class UncachedTileLinkIOArbiterThatAppendsArbiterId(val n: Int) extends UncachedTileLinkIOArbiter(n) with AppendsArbiterId
class UncachedTileLinkIOArbiterThatPassesId(val n: Int) extends UncachedTileLinkIOArbiter(n) with PassesId class UncachedTileLinkIOArbiterThatPassesId(val n: Int) extends UncachedTileLinkIOArbiter(n) with PassesId
class UncachedTileLinkIOArbiterThatUsesNewId(val n: Int) extends UncachedTileLinkIOArbiter(n) with UsesNewId class UncachedTileLinkIOArbiterThatUsesNewId(val n: Int) extends UncachedTileLinkIOArbiter(n) with UsesNewId
class TileLinkIOArbiterThatAppendsArbiterId(val n: Int) extends TileLinkIOArbiter(n) with AppendsArbiterId class TileLinkIOArbiterThatAppendsArbiterId(val n: Int) extends TileLinkIOArbiter(n) with AppendsArbiterId
class TileLinkIOArbiterThatPassesId(val n: Int) extends TileLinkIOArbiter(n) with PassesId class TileLinkIOArbiterThatPassesId(val n: Int) extends TileLinkIOArbiter(n) with PassesId
class TileLinkIOArbiterThatUsesNewId(val n: Int) extends TileLinkIOArbiter(n) with UsesNewId class TileLinkIOArbiterThatUsesNewId(val n: Int) extends TileLinkIOArbiter(n) with UsesNewId
/** Concrete uncached client-side arbiter that appends the arbiter's port id to client_xact_id */
class ClientUncachedTileLinkIOArbiter(val arbN: Int) extends Module with TileLinkArbiterLike with AppendsArbiterId {
val io = new Bundle {
val in = Vec.fill(arbN){new ClientUncachedTileLinkIO}.flip
val out = new ClientUncachedTileLinkIO
}
hookupClientSourceHeaderless(io.in.map(_.acquire), io.out.acquire)
hookupManagerSourceHeaderlessWithId(io.in.map(_.grant), io.out.grant)
}
/** Concrete client-side arbiter that appends the arbiter's port id to client_xact_id */
class ClientTileLinkIOArbiter(val arbN: Int) extends Module with TileLinkArbiterLike with AppendsArbiterId {
val io = new Bundle {
val in = Vec.fill(arbN){new ClientTileLinkIO}.flip
val out = new ClientTileLinkIO
}
hookupClientSourceHeaderless(io.in.map(_.acquire), io.out.acquire)
hookupClientSourceHeaderless(io.in.map(_.release), io.out.release)
hookupManagerSourceBroadcast(io.in.map(_.probe), io.out.probe)
hookupManagerSourceHeaderlessWithId(io.in.map(_.grant), io.out.grant)
}
/** Utility trait containing wiring functions to keep track of how many data beats have
* been sent or recieved over a particular TileLinkChannel or pair of channels.
*
* Won't count message types that don't have data.
* Used in XactTrackers and FinishUnit.
*/
trait HasDataBeatCounters {
type HasBeat = TileLinkChannel with HasTileLinkBeatId
/** Returns the current count on this channel and when a message is done
* @param inc increment the counter (usually .valid or .fire())
* @param data the actual channel data
* @param beat count to return for single-beat messages
*/
def connectDataBeatCounter[S <: TileLinkChannel](inc: Bool, data: S, beat: UInt) = {
val multi = data.hasMultibeatData()
val (multi_cnt, multi_done) = Counter(inc && multi, data.tlDataBeats)
val cnt = Mux(multi, multi_cnt, beat)
val done = Mux(multi, multi_done, inc)
(cnt, done)
}
/** Counter for beats on outgoing DecoupledIOs */
def connectOutgoingDataBeatCounter[T <: TileLinkChannel](in: DecoupledIO[T], beat: UInt = UInt(0)): (UInt, Bool) =
connectDataBeatCounter(in.fire(), in.bits, beat)
/** Returns done but not cnt. Use the addr_beat subbundle instead of cnt for beats on
* incoming channels in case of network reordering.
*/
def connectIncomingDataBeatCounter[T <: TileLinkChannel](in: DecoupledIO[T]): Bool =
connectDataBeatCounter(in.fire(), in.bits, UInt(0))._2
/** Counter for beats on incoming DecoupledIO[LogicalNetworkIO[]]s returns done */
def connectIncomingDataBeatCounterWithHeader[T <: TileLinkChannel](in: DecoupledIO[LogicalNetworkIO[T]]): Bool =
connectDataBeatCounter(in.fire(), in.bits.payload, UInt(0))._2
/** If the network might interleave beats from different messages, we need a Vec of counters,
* one for every outstanding message id that might be interleaved.
*
* @param getId mapping from Message to counter id
*/
def connectIncomingDataBeatCountersWithHeader[T <: TileLinkChannel with HasClientTransactionId](
in: DecoupledIO[LogicalNetworkIO[T]],
entries: Int,
getId: LogicalNetworkIO[T] => UInt): Vec[Bool] = {
Vec((0 until entries).map { i =>
connectDataBeatCounter(in.fire() && getId(in.bits) === UInt(i), in.bits.payload, UInt(0))._2
})
}
/** Provides counters on two channels, as well a meta-counter that tracks how many
* messages have been sent over the up channel but not yet responded to over the down channel
*
* @param max max number of outstanding ups with no down
* @param up outgoing channel
* @param down incoming channel
* @param beat overrides cnts on single-beat messages
* @param track whether up's message should be tracked
* @return a tuple containing whether their are outstanding messages, up's count,
* up's done, down's count, down's done
*/
def connectTwoWayBeatCounter[T <: TileLinkChannel, S <: TileLinkChannel](
max: Int,
up: DecoupledIO[T],
down: DecoupledIO[S],
beat: UInt = UInt(0),
track: T => Bool = (t: T) => Bool(true)): (Bool, UInt, Bool, UInt, Bool) = {
val cnt = Reg(init = UInt(0, width = log2Up(max+1)))
val (up_idx, up_done) = connectDataBeatCounter(up.fire(), up.bits, beat)
val (down_idx, down_done) = connectDataBeatCounter(down.fire(), down.bits, beat)
val do_inc = up_done && track(up.bits)
val do_dec = down_done
cnt := Mux(do_dec,
Mux(do_inc, cnt, cnt - UInt(1)),
Mux(do_inc, cnt + UInt(1), cnt))
(cnt > UInt(0), up_idx, up_done, down_idx, down_done)
}
}

View File

@ -32,19 +32,19 @@ abstract class CoherenceAgentBundle extends Bundle with CoherenceAgentParameters
abstract class CoherenceAgentModule extends Module with CoherenceAgentParameters abstract class CoherenceAgentModule extends Module with CoherenceAgentParameters
trait HasCoherenceAgentWiringHelpers { trait HasCoherenceAgentWiringHelpers {
def doOutputArbitration[T <: TileLinkChannel : ClassTag]( def doOutputArbitration[T <: TileLinkChannel](
out: DecoupledIO[LogicalNetworkIO[T]], out: DecoupledIO[T],
ins: Seq[DecoupledIO[LogicalNetworkIO[T]]]) { ins: Seq[DecoupledIO[T]]) {
def lock(o: LogicalNetworkIO[T]) = o.payload.hasMultibeatData() def lock(o: T) = o.hasMultibeatData()
val arb = Module(new LockingRRArbiter( out.bits.clone, ins.size, out.bits.payload.tlDataBeats, lock _)) val arb = Module(new LockingRRArbiter(out.bits.clone, ins.size, out.bits.tlDataBeats, lock _))
out <> arb.io.out out <> arb.io.out
arb.io.in zip ins map { case (a, in) => a <> in } arb.io.in <> ins
} }
def doInputRouting[T <: HasManagerTransactionId]( def doInputRouting[T <: HasManagerTransactionId](
in: DecoupledIO[LogicalNetworkIO[T]], in: DecoupledIO[T],
outs: Seq[DecoupledIO[LogicalNetworkIO[T]]]) { outs: Seq[DecoupledIO[T]]) {
val idx = in.bits.payload.manager_xact_id val idx = in.bits.manager_xact_id
outs.map(_.bits := in.bits) outs.map(_.bits := in.bits)
outs.zipWithIndex.map { case (o,i) => o.valid := in.valid && idx === UInt(i) } outs.zipWithIndex.map { case (o,i) => o.valid := in.valid && idx === UInt(i) }
in.ready := Vec(outs.map(_.ready)).read(idx) in.ready := Vec(outs.map(_.ready)).read(idx)
@ -52,23 +52,23 @@ trait HasCoherenceAgentWiringHelpers {
} }
trait HasInnerTLIO extends CoherenceAgentBundle { trait HasInnerTLIO extends CoherenceAgentBundle {
val inner = Bundle(new TileLinkIO)(innerTLParams).flip val inner = Bundle(new ManagerTileLinkIO)(innerTLParams)
val incoherent = Vec.fill(inner.tlNCoherentClients){Bool()}.asInput val incoherent = Vec.fill(inner.tlNCoherentClients){Bool()}.asInput
def iacq(dummy: Int = 0) = inner.acquire.bits.payload def iacq(dummy: Int = 0) = inner.acquire.bits
def iprb(dummy: Int = 0) = inner.probe.bits.payload def iprb(dummy: Int = 0) = inner.probe.bits
def irel(dummy: Int = 0) = inner.release.bits.payload def irel(dummy: Int = 0) = inner.release.bits
def ignt(dummy: Int = 0) = inner.grant.bits.payload def ignt(dummy: Int = 0) = inner.grant.bits
def ifin(dummy: Int = 0) = inner.finish.bits.payload def ifin(dummy: Int = 0) = inner.finish.bits
} }
trait HasUncachedOuterTLIO extends CoherenceAgentBundle { trait HasUncachedOuterTLIO extends CoherenceAgentBundle {
val outer = Bundle(new HeaderlessUncachedTileLinkIO)(outerTLParams) val outer = Bundle(new ClientUncachedTileLinkIO)(outerTLParams)
def oacq(dummy: Int = 0) = outer.acquire.bits def oacq(dummy: Int = 0) = outer.acquire.bits
def ognt(dummy: Int = 0) = outer.grant.bits def ognt(dummy: Int = 0) = outer.grant.bits
} }
trait HasCachedOuterTLIO extends CoherenceAgentBundle { trait HasCachedOuterTLIO extends CoherenceAgentBundle {
val outer = Bundle(new HeaderlessTileLinkIO)(outerTLParams) val outer = Bundle(new ClientTileLinkIO)(outerTLParams)
def oacq(dummy: Int = 0) = outer.acquire.bits def oacq(dummy: Int = 0) = outer.acquire.bits
def oprb(dummy: Int = 0) = outer.probe.bits def oprb(dummy: Int = 0) = outer.probe.bits
def orel(dummy: Int = 0) = outer.release.bits def orel(dummy: Int = 0) = outer.release.bits
@ -78,8 +78,8 @@ trait HasCachedOuterTLIO extends CoherenceAgentBundle {
class ManagerTLIO extends HasInnerTLIO with HasUncachedOuterTLIO class ManagerTLIO extends HasInnerTLIO with HasUncachedOuterTLIO
abstract class CoherenceAgent extends CoherenceAgentModule { abstract class CoherenceAgent extends CoherenceAgentModule {
def innerTL: TileLinkIO def innerTL: ManagerTileLinkIO
def outerTL: HeaderlessTileLinkIO def outerTL: ClientTileLinkIO
def incoherent: Vec[Bool] def incoherent: Vec[Bool]
} }
@ -109,49 +109,25 @@ trait HasTrackerConflictIO extends Bundle {
class ManagerXactTrackerIO extends ManagerTLIO with HasTrackerConflictIO class ManagerXactTrackerIO extends ManagerTLIO with HasTrackerConflictIO
class HierarchicalXactTrackerIO extends HierarchicalTLIO with HasTrackerConflictIO class HierarchicalXactTrackerIO extends HierarchicalTLIO with HasTrackerConflictIO
abstract class XactTracker extends CoherenceAgentModule abstract class XactTracker extends CoherenceAgentModule with HasDataBeatCounters {
with HasDataBeatCounters {
def addPendingBitWhenBeat[T <: HasBeat](inc: Bool, in: T): UInt = def addPendingBitWhenBeat[T <: HasBeat](inc: Bool, in: T): UInt =
Fill(in.tlDataBeats, inc) & UIntToOH(in.addr_beat) Fill(in.tlDataBeats, inc) & UIntToOH(in.addr_beat)
def dropPendingBitWhenBeat[T <: HasBeat](dec: Bool, in: T): UInt = def dropPendingBitWhenBeat[T <: HasBeat](dec: Bool, in: T): UInt =
~Fill(in.tlDataBeats, dec) | ~UIntToOH(in.addr_beat) ~Fill(in.tlDataBeats, dec) | ~UIntToOH(in.addr_beat)
def addPendingBitWhenBeatHasData[T <: Data : TypeTag](in: DecoupledIO[T]): UInt = { def addPendingBitWhenBeatHasData[T <: HasBeat](in: DecoupledIO[T]): UInt =
in.bits match { addPendingBitWhenBeat(in.fire() && in.bits.hasData(), in.bits)
case p: HasBeat if typeTag[T].tpe <:< typeTag[HasBeat].tpe =>
addPendingBitWhenBeat(in.fire() && p.hasData(), p)
case ln: LNAcquire if typeTag[T].tpe <:< typeTag[LNAcquire].tpe =>
addPendingBitWhenBeat(in.fire() && ln.payload.hasData(), ln.payload)
case ln: LNRelease if typeTag[T].tpe <:< typeTag[LNRelease].tpe =>
addPendingBitWhenBeat(in.fire() && ln.payload.hasData(), ln.payload)
case ln: LNGrant if typeTag[T].tpe <:< typeTag[LNGrant].tpe =>
addPendingBitWhenBeat(in.fire() && ln.payload.hasData(), ln.payload)
case _ => { require(false, "Don't know how track beats of " + typeTag[T].tpe); UInt(0) }
}
}
def addPendingBitWhenBeatIsGetOrAtomic(in: DecoupledIO[LogicalNetworkIO[Acquire]]): UInt = { def addPendingBitWhenBeatIsGetOrAtomic(in: DecoupledIO[AcquireFromSrc]): UInt = {
val a = in.bits.payload val a = in.bits
val isGetOrAtomic = a.isBuiltInType() && val isGetOrAtomic = a.isBuiltInType() &&
(Vec(Acquire.getType, Acquire.getBlockType, Acquire.putAtomicType).contains(a.a_type)) (Vec(Acquire.getType, Acquire.getBlockType, Acquire.putAtomicType).contains(a.a_type))
addPendingBitWhenBeat(in.fire() && isGetOrAtomic, in.bits.payload) addPendingBitWhenBeat(in.fire() && isGetOrAtomic, a)
} }
def dropPendingBitWhenBeatHasData[T <: Data : TypeTag](in: DecoupledIO[T]): UInt = { def dropPendingBitWhenBeatHasData[T <: HasBeat](in: DecoupledIO[T]): UInt =
in.bits match { dropPendingBitWhenBeat(in.fire() && in.bits.hasData(), in.bits)
case p: HasBeat if typeTag[T].tpe <:< typeTag[HasBeat].tpe =>
dropPendingBitWhenBeat(in.fire() && p.hasData(), p)
case ln: LNAcquire if typeTag[T].tpe <:< typeTag[LNAcquire].tpe =>
dropPendingBitWhenBeat(in.fire() && ln.payload.hasData(), ln.payload)
case ln: LNRelease if typeTag[T].tpe <:< typeTag[LNRelease].tpe =>
dropPendingBitWhenBeat(in.fire() && ln.payload.hasData(), ln.payload)
case ln: LNGrant if typeTag[T].tpe <:< typeTag[LNGrant].tpe =>
dropPendingBitWhenBeat(in.fire() && ln.payload.hasData(), ln.payload)
case _ => { require(false, "Don't know how track beats of " + typeTag[T].tpe); UInt(0) }
}
}
def dropPendingBitAtDest(in: DecoupledIO[LogicalNetworkIO[Probe]]): UInt = { def dropPendingBitAtDest(in: DecoupledIO[ProbeToDst]): UInt =
~Fill(in.bits.payload.tlNCoherentClients, in.fire()) | ~UIntToOH(in.bits.header.dst) ~Fill(in.bits.tlNCoherentClients, in.fire()) | ~UIntToOH(in.bits.client_id)
}
} }