1
0

Voluntary Writeback tracker rewrite

This commit is contained in:
Henry Cook 2015-04-27 12:56:33 -07:00
parent 11b5222d01
commit 09e30041ed

View File

@ -337,8 +337,7 @@ class L2DataArray(delay: Int) extends L2HellaCacheModule {
io.write.ready := Bool(true) io.write.ready := Bool(true)
} }
class L2HellaCacheBank extends HierarchicalCoherenceAgent class L2HellaCacheBank extends HierarchicalCoherenceAgent with L2HellaCacheParameters {
with L2HellaCacheParameters {
require(isPow2(nSets)) require(isPow2(nSets))
require(isPow2(nWays)) require(isPow2(nWays))
@ -357,8 +356,7 @@ class TSHRFileIO extends HierarchicalTLIO {
val data = new L2DataRWIO val data = new L2DataRWIO
} }
class TSHRFile 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
@ -381,7 +379,6 @@ class TSHRFile extends L2HellaCacheModule
val acquire_idx = Mux(acquireMatches.orR, val acquire_idx = Mux(acquireMatches.orR,
PriorityEncoder(acquireMatches), PriorityEncoder(acquireMatches),
PriorityEncoder(acquireReadys)) PriorityEncoder(acquireReadys))
val block_acquires = acquireConflicts.orR val block_acquires = acquireConflicts.orR
io.inner.acquire.ready := acquireReadys.orR && !block_acquires io.inner.acquire.ready := acquireReadys.orR && !block_acquires
trackerAcquireIOs.zipWithIndex.foreach { trackerAcquireIOs.zipWithIndex.foreach {
@ -432,7 +429,7 @@ class L2XactTrackerIO extends HierarchicalXactTrackerIO {
} }
abstract class L2XactTracker extends XactTracker with L2HellaCacheParameters { abstract class L2XactTracker extends XactTracker with L2HellaCacheParameters {
class CacheBlockBuffer { class CacheBlockBuffer { // TODO
val buffer = Reg(Bits(width = params(CacheBlockBytes)*8)) val buffer = Reg(Bits(width = params(CacheBlockBytes)*8))
def internal = Vec.fill(internalDataBeats){ Bits(width = rowBits) }.fromBits(buffer) def internal = Vec.fill(internalDataBeats){ Bits(width = rowBits) }.fromBits(buffer)
@ -477,127 +474,118 @@ abstract class L2XactTracker extends XactTracker with L2HellaCacheParameters {
val isPartial = a.wmask() != Acquire.fullWriteMask val isPartial = a.wmask() != Acquire.fullWriteMask
addPendingBitWhenBeat(in.fire() && isPartial && Bool(ignoresWriteMask), a) addPendingBitWhenBeat(in.fire() && isPartial && Bool(ignoresWriteMask), a)
} }
def pinAllReadyValidLow[T <: Data](b: Bundle) {
b.elements.foreach {
_._2 match {
case d: DecoupledIO[T] =>
if(d.ready.dir == OUTPUT) d.ready := Bool(false)
else if(d.valid.dir == OUTPUT) d.valid := Bool(false)
case v: ValidIO[T] => if(v.valid.dir == OUTPUT) v.valid := Bool(false)
case b: Bundle => pinAllReadyValidLow(b)
case _ =>
}
}
}
} }
class L2VoluntaryReleaseTracker(trackerId: Int) extends L2XactTracker { class L2VoluntaryReleaseTracker(trackerId: Int) extends L2XactTracker {
val io = new L2XactTrackerIO val io = new L2XactTrackerIO
pinAllReadyValidLow(io)
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_busy :: s_meta_write :: Nil = Enum(UInt(), 5)
val state = Reg(init=s_idle) val state = Reg(init=s_idle)
val xact = Reg(Bundle(new ReleaseFromSrc, { case TLId => params(InnerTLId); case TLDataBits => 0 })) val xact = Reg(Bundle(new ReleaseFromSrc, { case TLId => params(InnerTLId); case TLDataBits => 0 }))
val xact_tag_match = Reg{ Bool() } val data_buffer = Vec.fill(innerDataBeats){ Reg(init=UInt(0, width = innerDataBits)) }
val xact_old_meta = Reg{ new L2Metadata }
val xact_way_en = Reg{ Bits(width = nWays) } val xact_way_en = Reg{ Bits(width = nWays) }
val data_buffer = Vec.fill(innerDataBeats){ Reg(io.irel().data.clone) } val xact_old_meta = Reg{ new L2Metadata }
val coh = xact_old_meta.coh val coh = xact_old_meta.coh
val collect_irel_data = Reg(init=Bool(false)) val pending_irels = Reg(init=Bits(0, width = io.inner.tlDataBeats))
val irel_data_valid = Reg(init=Bits(0, width = innerDataBeats)) val pending_writes = Reg(init=Bits(0, width = io.inner.tlDataBeats))
val irel_data_done = connectIncomingDataBeatCounter(io.inner.release) val pending_ignt = Reg(init=Bool(false))
val (write_data_cnt, write_data_done) = connectInternalDataBeatCounter(io.data.write)
io.has_acquire_conflict := Bool(false) val all_pending_done =
io.has_acquire_match := Bool(false) !(pending_writes.orR ||
io.has_release_match := io.irel().isVoluntary() pending_ignt)
io.outer.acquire.valid := Bool(false) // Accept a voluntary Release (and any further beats of data)
io.outer.probe.ready := Bool(false) pending_irels := (pending_irels & dropPendingBitWhenBeatHasData(io.inner.release))
io.outer.release.valid := Bool(false) io.inner.release.ready := state === s_idle || pending_irels.orR
io.outer.grant.ready := Bool(false) when(io.inner.release.fire()) { data_buffer(io.irel().addr_beat) := io.irel().data }
io.inner.acquire.ready := Bool(false)
io.inner.probe.valid := Bool(false)
io.inner.release.ready := Bool(false)
io.inner.grant.valid := Bool(false)
io.inner.finish.ready := Bool(false)
io.inner.grant.bits := coh.inner.makeGrant(xact, UInt(trackerId)) // Begin a transaction by getting the current block metadata
io.meta.read.valid := state === s_meta_read
io.data.read.valid := Bool(false)
io.data.write.valid := Bool(false)
io.data.write.bits.id := UInt(trackerId)
io.data.write.bits.way_en := xact_way_en
io.data.write.bits.addr_idx := xact.addr_block(idxMSB,idxLSB)
io.data.write.bits.addr_beat := write_data_cnt
io.data.write.bits.wmask := SInt(-1)
io.data.write.bits.data := data_buffer(write_data_cnt)
io.meta.read.valid := Bool(false)
io.meta.read.bits.id := UInt(trackerId) io.meta.read.bits.id := UInt(trackerId)
io.meta.read.bits.idx := xact.addr_block(idxMSB,idxLSB) io.meta.read.bits.idx := xact.addr_block(idxMSB,idxLSB)
io.meta.read.bits.tag := xact.addr_block >> UInt(idxBits) io.meta.read.bits.tag := xact.addr_block >> UInt(idxBits)
io.meta.write.valid := Bool(false)
// Write the voluntarily written back data to this cache
pending_writes := (pending_writes & dropPendingBit(io.data.write)) |
addPendingBitWhenBeatHasData(io.inner.release)
val curr_write_beat = PriorityEncoder(pending_writes)
io.data.write.valid := state === s_busy && pending_writes.orR
io.data.write.bits.id := UInt(trackerId)
io.data.write.bits.way_en := xact_way_en
io.data.write.bits.addr_idx := xact.addr_block(idxMSB,idxLSB)
io.data.write.bits.addr_beat := curr_write_beat
io.data.write.bits.wmask := SInt(-1)
io.data.write.bits.data := data_buffer(curr_write_beat)
// Send an acknowledgement
io.inner.grant.valid := state === s_busy && pending_ignt && !pending_irels
io.inner.grant.bits := coh.inner.makeGrant(xact, UInt(trackerId))
when(io.inner.grant.fire()) { pending_ignt := Bool(false) }
// End a transaction by updating the block metadata
io.meta.write.valid := state === s_meta_write
io.meta.write.bits.id := UInt(trackerId) io.meta.write.bits.id := UInt(trackerId)
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) 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 := Mux(xact.hasData(),
io.wb.req.valid := Bool(false) xact_old_meta.coh.outer.onHit(M_XWR),
xact_old_meta.coh.outer)
when(collect_irel_data) { // State machine updates and transaction handler metadata intialization
io.inner.release.ready := Bool(true) when(state === s_idle && io.inner.release.valid) {
when(io.inner.release.valid) {
data_buffer(io.irel().addr_beat) := io.irel().data
irel_data_valid(io.irel().addr_beat) := Bool(true)
}
when(irel_data_done) { collect_irel_data := Bool(false) }
}
switch (state) {
is(s_idle) {
io.inner.release.ready := Bool(true)
when( io.inner.release.valid ) {
xact := io.irel() xact := io.irel()
data_buffer(io.irel().addr_beat) := io.irel().data when(io.irel().hasMultibeatData()) {
collect_irel_data := io.irel().hasMultibeatData() pending_irels := dropPendingBitWhenBeatHasData(io.inner.release)
irel_data_valid := io.irel().hasData() << io.irel().addr_beat }. otherwise {
pending_irels := UInt(0)
}
pending_writes := addPendingBitWhenBeatHasData(io.inner.release)
pending_ignt := io.irel().requiresAck()
state := s_meta_read state := s_meta_read
} }
} when(state === s_meta_read && io.meta.read.ready) { state := s_meta_resp }
is(s_meta_read) { when(state === s_meta_resp && io.meta.resp.valid) {
io.meta.read.valid := Bool(true)
when(io.meta.read.ready) { state := s_meta_resp }
}
is(s_meta_resp) {
when(io.meta.resp.valid) {
xact_tag_match := io.meta.resp.bits.tag_match
xact_old_meta := io.meta.resp.bits.meta xact_old_meta := io.meta.resp.bits.meta
xact_way_en := io.meta.resp.bits.way_en xact_way_en := io.meta.resp.bits.way_en
state := Mux(io.meta.resp.bits.tag_match, state := s_busy
Mux(xact.hasData(), s_data_write, s_meta_write),
Mux(xact.requiresAck(), s_inner_grant, s_idle))
}
}
is(s_data_write) {
io.data.write.valid := !collect_irel_data || irel_data_valid(write_data_cnt)
when(write_data_done) { state := s_meta_write }
}
is(s_meta_write) {
io.meta.write.valid := Bool(true)
when(io.meta.write.ready) {
state := Mux(xact.requiresAck(), s_inner_grant, s_idle) // Need a Grant.voluntaryAck?
}
}
is(s_inner_grant) {
io.inner.grant.valid := !collect_irel_data
when(io.inner.grant.ready) {
state := Mux(io.ignt().requiresAck(), s_inner_finish, s_idle)
}
}
is(s_inner_finish) {
io.inner.finish.ready := Bool(true)
when(io.inner.finish.valid) { state := s_idle }
}
} }
when(state === s_busy && all_pending_done) { state := s_meta_write }
when(state === s_meta_write && io.meta.write.ready) { state := s_idle }
// These IOs are used for routing in the parent
io.has_release_match := io.irel().isVoluntary()
io.has_acquire_match := Bool(false)
io.has_acquire_conflict := Bool(false)
// Checks for illegal behavior // Checks for illegal behavior
assert(!(state === s_meta_resp && io.meta.resp.valid && !io.meta.resp.bits.tag_match), assert(!(state === s_meta_resp && io.meta.resp.valid && !io.meta.resp.bits.tag_match),
"VoluntaryReleaseTracker accepted Release for a block not resident in this cache!") "VoluntaryReleaseTracker accepted Release for a block not resident in this cache!")
assert(!(state === s_idle && io.inner.release.fire() && !io.irel().isVoluntary()),
"VoluntaryReleaseTracker accepted Release that wasn't voluntary!")
} }
class L2AcquireTracker(trackerId: Int) extends L2XactTracker { class L2AcquireTracker(trackerId: Int) extends L2XactTracker {
val io = new L2XactTrackerIO val io = new L2XactTrackerIO
pinAllReadyValidLow(io)
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)
@ -742,6 +730,20 @@ class L2AcquireTracker(trackerId: Int) extends L2XactTracker {
// Track whether any beats are missing from a PutBlock // Track whether any beats are missing from a PutBlock
pending_puts := (pending_puts & dropPendingBitWhenBeatHasData(io.inner.acquire)) pending_puts := (pending_puts & dropPendingBitWhenBeatHasData(io.inner.acquire))
// Begin a transaction by getting the current block metadata
io.meta.read.valid := state === s_meta_read
io.meta.read.bits.id := UInt(trackerId)
io.meta.read.bits.idx := xact.addr_block(idxMSB,idxLSB)
io.meta.read.bits.tag := xact.addr_block >> UInt(idxBits)
// Issue a request to the writeback unit
io.wb.req.valid := state === s_wb_req
io.wb.req.bits.id := UInt(trackerId)
io.wb.req.bits.idx := xact.addr_block(idxMSB,idxLSB)
io.wb.req.bits.tag := xact_old_meta.tag
io.wb.req.bits.coh := xact_old_meta.coh
io.wb.req.bits.way_en := xact_way_en
// Track which clients yet need to be probed and make Probe message // Track which clients yet need to be probed and make Probe message
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)
@ -773,10 +775,7 @@ class L2AcquireTracker(trackerId: Int) extends L2XactTracker {
op_code = xact.op_code()), op_code = xact.op_code()),
Bundle(Acquire(xact))(outerTLParams)) Bundle(Acquire(xact))(outerTLParams))
// Probes from the outer memory system are handled in the WritebackUnit // Handle the response from outer memory
io.outer.probe.ready := Bool(false)
io.outer.release.valid := Bool(false)
io.outer.grant.ready := state === s_busy io.outer.grant.ready := state === s_busy
val pending_coh_on_ognt = HierarchicalMetadata( val pending_coh_on_ognt = HierarchicalMetadata(
ManagerMetadata.onReset, ManagerMetadata.onReset,
@ -853,11 +852,7 @@ class L2AcquireTracker(trackerId: Int) extends L2XactTracker {
io.data.write.bits.wmask := wmask_buffer(curr_write_beat) io.data.write.bits.wmask := wmask_buffer(curr_write_beat)
io.data.write.bits.data := data_buffer(curr_write_beat) io.data.write.bits.data := data_buffer(curr_write_beat)
io.meta.read.valid := state === s_meta_read // End a transaction by updating the block metadata
io.meta.read.bits.id := UInt(trackerId)
io.meta.read.bits.idx := xact.addr_block(idxMSB,idxLSB)
io.meta.read.bits.tag := xact.addr_block >> UInt(idxBits)
io.meta.write.valid := state === s_meta_write io.meta.write.valid := state === s_meta_write
io.meta.write.bits.id := UInt(trackerId) io.meta.write.bits.id := UInt(trackerId)
io.meta.write.bits.idx := xact.addr_block(idxMSB,idxLSB) io.meta.write.bits.idx := xact.addr_block(idxMSB,idxLSB)
@ -865,13 +860,6 @@ class L2AcquireTracker(trackerId: Int) extends L2XactTracker {
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 := pending_coh io.meta.write.bits.data.coh := pending_coh
io.wb.req.valid := state === s_wb_req
io.wb.req.bits.id := UInt(trackerId)
io.wb.req.bits.idx := xact.addr_block(idxMSB,idxLSB)
io.wb.req.bits.tag := xact_old_meta.tag
io.wb.req.bits.coh := xact_old_meta.coh
io.wb.req.bits.way_en := xact_way_en
// Handling of secondary misses (Gets and Puts only for now) // Handling of secondary misses (Gets and Puts only for now)
when(io.inner.acquire.fire() && io.iacq().hasData()) { // state <= s_meta_wrtie when(io.inner.acquire.fire() && io.iacq().hasData()) { // state <= s_meta_wrtie
val beat = io.iacq().addr_beat val beat = io.iacq().addr_beat
@ -988,6 +976,7 @@ class L2WritebackUnitIO extends HierarchicalXactTrackerIO {
class L2WritebackUnit(trackerId: Int) extends L2XactTracker { class L2WritebackUnit(trackerId: Int) extends L2XactTracker {
val io = new L2WritebackUnitIO val io = new L2WritebackUnitIO
pinAllReadyValidLow(io)
val s_idle :: s_inner_probe :: s_busy :: s_outer_grant :: s_wb_resp :: Nil = Enum(UInt(), 5) val s_idle :: s_inner_probe :: s_busy :: s_outer_grant :: s_wb_resp :: Nil = Enum(UInt(), 5)
val state = Reg(init=s_idle) val state = Reg(init=s_idle)
@ -1086,11 +1075,4 @@ class L2WritebackUnit(trackerId: Int) extends L2XactTracker {
io.has_release_match := io.irel().conflicts(xact_addr_block) && !io.irel().isVoluntary() && io.inner.release.ready io.has_release_match := io.irel().conflicts(xact_addr_block) && !io.irel().isVoluntary() && io.inner.release.ready
io.has_acquire_match := Bool(false) io.has_acquire_match := Bool(false)
io.has_acquire_conflict := Bool(false) io.has_acquire_conflict := Bool(false)
// IOs pinned low
io.outer.acquire.valid := Bool(false)
io.outer.probe.ready := Bool(false) // TODO: handle these here
io.inner.grant.valid := Bool(false)
io.inner.acquire.ready := Bool(false)
io.inner.finish.ready := Bool(false)
} }