[rocket] cleanup mshr logic
This commit is contained in:
parent
dae6772624
commit
38c5af5bad
@ -175,15 +175,18 @@ class MSHR(id: Int, edge: TLEdgeOut)(implicit cfg: DCacheConfig, p: Parameters)
|
|||||||
val req_tag = req.addr >> untagBits
|
val req_tag = req.addr >> untagBits
|
||||||
val req_block_addr = (req.addr >> blockOffBits) << blockOffBits
|
val req_block_addr = (req.addr >> blockOffBits) << blockOffBits
|
||||||
val idx_match = req_idx === io.req_bits.addr(untagBits-1,blockOffBits)
|
val idx_match = req_idx === io.req_bits.addr(untagBits-1,blockOffBits)
|
||||||
|
|
||||||
|
val new_coh = Reg(init=ClientMetadata.onReset)
|
||||||
|
val (_, shrink_param, coh_on_clear) = req.old_meta.coh.onCacheControl(M_FLUSH)
|
||||||
|
val grow_param = new_coh.onAccess(req.cmd)._2
|
||||||
|
val coh_on_grant = new_coh.onGrant(req.cmd, io.mem_grant.bits.param)
|
||||||
// We only accept secondary misses if we haven't yet sent an Acquire to outer memory
|
// We only accept secondary misses if we haven't yet sent an Acquire to outer memory
|
||||||
// or if the Acquire that was sent will obtain a Grant with sufficient permissions
|
// or if the Acquire that was sent will obtain a Grant with sufficient permissions
|
||||||
// to let us replay this new request. I.e. we don't handle multiple outstanding
|
// to let us replay this new request. I.e. we don't handle multiple outstanding
|
||||||
// Acquires on the same block for now.
|
// Acquires on the same block for now.
|
||||||
val cmd_requires_second_acquire =
|
val (cmd_requires_second_acquire, is_hit_again, _, dirtier_coh, dirtier_cmd) =
|
||||||
req.old_meta.coh.requiresAcquireOnSecondaryMiss(req.cmd, io.req_bits.cmd)
|
new_coh.onSecondaryAccess(req.cmd, io.req_bits.cmd)
|
||||||
// Track whether or not a secondary acquire will cause the coherence state
|
|
||||||
// to go from clean to dirty.
|
|
||||||
val dirties_coh = Reg(Bool())
|
|
||||||
val states_before_refill = Seq(s_wb_req, s_wb_resp, s_meta_clear)
|
val states_before_refill = Seq(s_wb_req, s_wb_resp, s_meta_clear)
|
||||||
val (_, _, refill_done, refill_address_inc) = edge.addr_inc(io.mem_grant)
|
val (_, _, refill_done, refill_address_inc) = edge.addr_inc(io.mem_grant)
|
||||||
val sec_rdy = idx_match &&
|
val sec_rdy = idx_match &&
|
||||||
@ -196,19 +199,6 @@ class MSHR(id: Int, edge: TLEdgeOut)(implicit cfg: DCacheConfig, p: Parameters)
|
|||||||
rpq.io.enq.bits := io.req_bits
|
rpq.io.enq.bits := io.req_bits
|
||||||
rpq.io.deq.ready := (io.replay.ready && state === s_drain_rpq) || state === s_invalid
|
rpq.io.deq.ready := (io.replay.ready && state === s_drain_rpq) || state === s_invalid
|
||||||
|
|
||||||
// TODO clean all this coh state business up
|
|
||||||
val new_coh_state = Reg(init=ClientMetadata.onReset)
|
|
||||||
val grow_param = Reg(init=UInt(0))
|
|
||||||
val coh_on_grant = Mux(dirties_coh,
|
|
||||||
ClientMetadata.maximum,
|
|
||||||
req.old_meta.coh.onGrant(req.cmd, io.mem_grant.bits.param))
|
|
||||||
val (is_hit, missed_param, coh_on_hit) = io.req_bits.old_meta.coh.onAccess(io.req_bits.cmd)
|
|
||||||
val (needs_wb, _, _) = io.req_bits.old_meta.coh.onCacheControl(M_FLUSH)
|
|
||||||
val (_, shrink_param, _) = req.old_meta.coh.onCacheControl(M_FLUSH)
|
|
||||||
val (hit_again, missed_again_param, _) = req.old_meta.coh.onCacheControl(io.req_bits.cmd)
|
|
||||||
val (_, _, clear_coh_state) = req.old_meta.coh.onCacheControl(M_FLUSH)
|
|
||||||
val (_, after_wb_param, _) = ClientMetadata.onReset.onAccess(req.cmd)
|
|
||||||
|
|
||||||
when (state === s_drain_rpq && !rpq.io.deq.valid) {
|
when (state === s_drain_rpq && !rpq.io.deq.valid) {
|
||||||
state := s_invalid
|
state := s_invalid
|
||||||
}
|
}
|
||||||
@ -220,14 +210,13 @@ class MSHR(id: Int, edge: TLEdgeOut)(implicit cfg: DCacheConfig, p: Parameters)
|
|||||||
state := s_meta_write_resp
|
state := s_meta_write_resp
|
||||||
}
|
}
|
||||||
when (state === s_refill_resp && refill_done) {
|
when (state === s_refill_resp && refill_done) {
|
||||||
|
new_coh := coh_on_grant
|
||||||
state := s_meta_write_req
|
state := s_meta_write_req
|
||||||
new_coh_state := coh_on_grant
|
|
||||||
}
|
}
|
||||||
when (io.mem_acquire.fire()) { // s_refill_req
|
when (io.mem_acquire.fire()) { // s_refill_req
|
||||||
state := s_refill_resp
|
state := s_refill_resp
|
||||||
}
|
}
|
||||||
when (state === s_meta_clear && io.meta_write.ready) {
|
when (state === s_meta_clear && io.meta_write.ready) {
|
||||||
grow_param := after_wb_param
|
|
||||||
state := s_refill_req
|
state := s_refill_req
|
||||||
}
|
}
|
||||||
when (state === s_wb_resp && io.mem_grant.valid) {
|
when (state === s_wb_resp && io.mem_grant.valid) {
|
||||||
@ -240,24 +229,26 @@ class MSHR(id: Int, edge: TLEdgeOut)(implicit cfg: DCacheConfig, p: Parameters)
|
|||||||
//If we get a secondary miss that needs more permissions before we've sent
|
//If we get a secondary miss that needs more permissions before we've sent
|
||||||
// out the primary miss's Acquire, we can upgrade the permissions we're
|
// out the primary miss's Acquire, we can upgrade the permissions we're
|
||||||
// going to ask for in s_refill_req
|
// going to ask for in s_refill_req
|
||||||
when(cmd_requires_second_acquire) {
|
req.cmd := dirtier_cmd
|
||||||
req.cmd := io.req_bits.cmd
|
when (is_hit_again) {
|
||||||
when(!hit_again) { grow_param := missed_again_param }
|
new_coh := dirtier_coh
|
||||||
}
|
}
|
||||||
dirties_coh := dirties_coh || isWrite(io.req_bits.cmd)
|
|
||||||
}
|
}
|
||||||
when (io.req_pri_val && io.req_pri_rdy) {
|
when (io.req_pri_val && io.req_pri_rdy) {
|
||||||
req := io.req_bits
|
req := io.req_bits
|
||||||
dirties_coh := isWrite(io.req_bits.cmd)
|
val old_coh = io.req_bits.old_meta.coh
|
||||||
|
val needs_wb = old_coh.onCacheControl(M_FLUSH)._1
|
||||||
|
val (is_hit, _, coh_on_hit) = old_coh.onAccess(io.req_bits.cmd)
|
||||||
when (io.req_bits.tag_match) {
|
when (io.req_bits.tag_match) {
|
||||||
when (is_hit) { // set dirty bit
|
when (is_hit) { // set dirty bit
|
||||||
|
new_coh := coh_on_hit
|
||||||
state := s_meta_write_req
|
state := s_meta_write_req
|
||||||
new_coh_state := coh_on_hit
|
|
||||||
}.otherwise { // upgrade permissions
|
}.otherwise { // upgrade permissions
|
||||||
|
new_coh := old_coh
|
||||||
state := s_refill_req
|
state := s_refill_req
|
||||||
grow_param := missed_param
|
|
||||||
}
|
}
|
||||||
}.otherwise { // writback if necessary and refill
|
}.otherwise { // writback if necessary and refill
|
||||||
|
new_coh := ClientMetadata.onReset
|
||||||
state := Mux(needs_wb, s_wb_req, s_meta_clear)
|
state := Mux(needs_wb, s_wb_req, s_meta_clear)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -284,7 +275,7 @@ class MSHR(id: Int, edge: TLEdgeOut)(implicit cfg: DCacheConfig, p: Parameters)
|
|||||||
|
|
||||||
io.meta_write.valid := state.isOneOf(s_meta_write_req, s_meta_clear)
|
io.meta_write.valid := state.isOneOf(s_meta_write_req, s_meta_clear)
|
||||||
io.meta_write.bits.idx := req_idx
|
io.meta_write.bits.idx := req_idx
|
||||||
io.meta_write.bits.data.coh := Mux(state === s_meta_clear, clear_coh_state, new_coh_state)
|
io.meta_write.bits.data.coh := Mux(state === s_meta_clear, coh_on_clear, new_coh)
|
||||||
io.meta_write.bits.data.tag := io.tag
|
io.meta_write.bits.data.tag := io.tag
|
||||||
io.meta_write.bits.way_en := req.way_en
|
io.meta_write.bits.way_en := req.way_en
|
||||||
|
|
||||||
|
@ -88,12 +88,6 @@ class ClientMetadata extends Bundle {
|
|||||||
Cat(wr, toT) -> Dirty))
|
Cat(wr, toT) -> Dirty))
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Does a secondary miss on the block require another Acquire message */
|
|
||||||
def requiresAcquireOnSecondaryMiss(first_cmd: UInt, second_cmd: UInt): Bool = {
|
|
||||||
import MemoryOpCategories._
|
|
||||||
isWriteIntent(second_cmd) && !isWriteIntent(first_cmd)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Does this cache have permissions on this block sufficient to perform op,
|
/** Does this cache have permissions on this block sufficient to perform op,
|
||||||
* and what to do next (Acquire message param or updated metadata). */
|
* and what to do next (Acquire message param or updated metadata). */
|
||||||
def onAccess(cmd: UInt): (Bool, UInt, ClientMetadata) = {
|
def onAccess(cmd: UInt): (Bool, UInt, ClientMetadata) = {
|
||||||
@ -101,6 +95,20 @@ class ClientMetadata extends Bundle {
|
|||||||
(r._1, r._2, ClientMetadata(r._2))
|
(r._1, r._2, ClientMetadata(r._2))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Does a secondary miss on the block require another Acquire message */
|
||||||
|
def onSecondaryAccess(first_cmd: UInt, second_cmd: UInt): (Bool, Bool, UInt, ClientMetadata, UInt) = {
|
||||||
|
import MemoryOpCategories._
|
||||||
|
val r1 = growStarter(first_cmd)
|
||||||
|
val r2 = growStarter(second_cmd)
|
||||||
|
val needs_second_acq = isWriteIntent(second_cmd) && !isWriteIntent(first_cmd)
|
||||||
|
val hit_again = r1._1 && r2._1
|
||||||
|
val dirties = categorize(second_cmd) === wr
|
||||||
|
val biggest_grow_param = Mux(dirties, r2._2, r1._2)
|
||||||
|
val dirtiest_state = ClientMetadata(biggest_grow_param)
|
||||||
|
val dirtiest_cmd = Mux(dirties, second_cmd, first_cmd)
|
||||||
|
(needs_second_acq, hit_again, biggest_grow_param, dirtiest_state, dirtiest_cmd)
|
||||||
|
}
|
||||||
|
|
||||||
/** Metadata change on a returned Grant */
|
/** Metadata change on a returned Grant */
|
||||||
def onGrant(cmd: UInt, param: UInt): ClientMetadata = ClientMetadata(growFinisher(cmd, param))
|
def onGrant(cmd: UInt, param: UInt): ClientMetadata = ClientMetadata(growFinisher(cmd, param))
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user