fix LRSC issue (RocketChip issue #86)
It was possible that the result of a store-conditional could get lost if it did not depend on the result of the corresponding load-reserved. This was because the MSHR does not update the client state based on the secondary requests. So the LR would acquire the line in clientExcusiveClean, but then we would fail to update the metadata array to change the state to clientExclusiveDirty. The solution is to track whether a secondary acquire would cause the line to be dirty. If so, use M_XWR instead of the primary command to generate the update coherence state.
This commit is contained in:
parent
51edd19e85
commit
dcfcac9530
@ -282,6 +282,12 @@ class MSHR(id: Int)(implicit p: Parameters) extends L1HellaCacheModule()(p) {
|
|||||||
val s_invalid :: s_wb_req :: s_wb_resp :: s_meta_clear :: s_refill_req :: s_refill_resp :: s_meta_write_req :: s_meta_write_resp :: s_drain_rpq :: Nil = Enum(UInt(), 9)
|
val s_invalid :: s_wb_req :: s_wb_resp :: s_meta_clear :: s_refill_req :: s_refill_resp :: s_meta_write_req :: s_meta_write_resp :: s_drain_rpq :: Nil = Enum(UInt(), 9)
|
||||||
val state = Reg(init=s_invalid)
|
val state = Reg(init=s_invalid)
|
||||||
|
|
||||||
|
def stateIsOneOf(check_states: Seq[UInt]): Bool =
|
||||||
|
check_states.map(state === _).reduce(_ || _)
|
||||||
|
|
||||||
|
def stateIsOneOf(st1: UInt, st2: UInt*): Bool =
|
||||||
|
stateIsOneOf(st1 +: st2)
|
||||||
|
|
||||||
val new_coh_state = Reg(init=ClientMetadata.onReset)
|
val new_coh_state = Reg(init=ClientMetadata.onReset)
|
||||||
val req = Reg(new MSHRReqInternal())
|
val req = Reg(new MSHRReqInternal())
|
||||||
val req_idx = req.addr(untagBits-1,blockOffBits)
|
val req_idx = req.addr(untagBits-1,blockOffBits)
|
||||||
@ -292,14 +298,17 @@ class MSHR(id: Int)(implicit p: Parameters) extends L1HellaCacheModule()(p) {
|
|||||||
// Acquires on the same block for now.
|
// Acquires on the same block for now.
|
||||||
val cmd_requires_second_acquire =
|
val cmd_requires_second_acquire =
|
||||||
req.old_meta.coh.requiresAcquireOnSecondaryMiss(req.cmd, io.req_bits.cmd)
|
req.old_meta.coh.requiresAcquireOnSecondaryMiss(req.cmd, io.req_bits.cmd)
|
||||||
val states_before_refill = Vec(s_wb_req, s_wb_resp, s_meta_clear)
|
// Track whether or not a secondary acquire will cause the coherence state
|
||||||
val sec_rdy = idx_match &&
|
// to go from clean to dirty.
|
||||||
(states_before_refill.contains(state) ||
|
val dirties_coh = Reg(Bool())
|
||||||
(Vec(s_refill_req, s_refill_resp).contains(state) &&
|
val states_before_refill = Seq(s_wb_req, s_wb_resp, s_meta_clear)
|
||||||
!cmd_requires_second_acquire))
|
|
||||||
val gnt_multi_data = io.mem_grant.bits.hasMultibeatData()
|
val gnt_multi_data = io.mem_grant.bits.hasMultibeatData()
|
||||||
val (refill_cnt, refill_count_done) = Counter(io.mem_grant.valid && gnt_multi_data, refillCycles)
|
val (refill_cnt, refill_count_done) = Counter(io.mem_grant.valid && gnt_multi_data, refillCycles)
|
||||||
val refill_done = io.mem_grant.valid && (!gnt_multi_data || refill_count_done)
|
val refill_done = io.mem_grant.valid && (!gnt_multi_data || refill_count_done)
|
||||||
|
val sec_rdy = idx_match &&
|
||||||
|
(stateIsOneOf(states_before_refill) ||
|
||||||
|
(stateIsOneOf(s_refill_req, s_refill_resp) &&
|
||||||
|
!cmd_requires_second_acquire && !refill_done))
|
||||||
|
|
||||||
val rpq = Module(new Queue(new ReplayInternal, p(ReplayQueueDepth)))
|
val rpq = Module(new Queue(new ReplayInternal, p(ReplayQueueDepth)))
|
||||||
rpq.io.enq.valid := (io.req_pri_val && io.req_pri_rdy || io.req_sec_val && sec_rdy) && !isPrefetch(io.req_bits.cmd)
|
rpq.io.enq.valid := (io.req_pri_val && io.req_pri_rdy || io.req_sec_val && sec_rdy) && !isPrefetch(io.req_bits.cmd)
|
||||||
@ -308,7 +317,7 @@ class MSHR(id: Int)(implicit p: Parameters) extends L1HellaCacheModule()(p) {
|
|||||||
|
|
||||||
val coh_on_grant = req.old_meta.coh.onGrant(
|
val coh_on_grant = req.old_meta.coh.onGrant(
|
||||||
incoming = io.mem_grant.bits,
|
incoming = io.mem_grant.bits,
|
||||||
pending = req.cmd)
|
pending = Mux(dirties_coh, M_XWR, req.cmd))
|
||||||
val coh_on_hit = io.req_bits.old_meta.coh.onHit(io.req_bits.cmd)
|
val coh_on_hit = io.req_bits.old_meta.coh.onHit(io.req_bits.cmd)
|
||||||
|
|
||||||
when (state === s_drain_rpq && !rpq.io.deq.valid) {
|
when (state === s_drain_rpq && !rpq.io.deq.valid) {
|
||||||
@ -344,10 +353,12 @@ class MSHR(id: Int)(implicit p: Parameters) extends L1HellaCacheModule()(p) {
|
|||||||
when(cmd_requires_second_acquire) {
|
when(cmd_requires_second_acquire) {
|
||||||
req.cmd := io.req_bits.cmd
|
req.cmd := io.req_bits.cmd
|
||||||
}
|
}
|
||||||
|
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) {
|
||||||
val coh = io.req_bits.old_meta.coh
|
val coh = io.req_bits.old_meta.coh
|
||||||
req := io.req_bits
|
req := io.req_bits
|
||||||
|
dirties_coh := isWrite(io.req_bits.cmd)
|
||||||
when (io.req_bits.tag_match) {
|
when (io.req_bits.tag_match) {
|
||||||
when(coh.isHit(io.req_bits.cmd)) { // set dirty bit
|
when(coh.isHit(io.req_bits.cmd)) { // set dirty bit
|
||||||
state := s_meta_write_req
|
state := s_meta_write_req
|
||||||
@ -379,7 +390,7 @@ class MSHR(id: Int)(implicit p: Parameters) extends L1HellaCacheModule()(p) {
|
|||||||
val meta_hazard = Reg(init=UInt(0,2))
|
val meta_hazard = Reg(init=UInt(0,2))
|
||||||
when (meta_hazard =/= UInt(0)) { meta_hazard := meta_hazard + 1 }
|
when (meta_hazard =/= UInt(0)) { meta_hazard := meta_hazard + 1 }
|
||||||
when (io.meta_write.fire()) { meta_hazard := 1 }
|
when (io.meta_write.fire()) { meta_hazard := 1 }
|
||||||
io.probe_rdy := !idx_match || (!states_before_refill.contains(state) && meta_hazard === 0)
|
io.probe_rdy := !idx_match || (!stateIsOneOf(states_before_refill) && meta_hazard === 0)
|
||||||
|
|
||||||
io.meta_write.valid := state === s_meta_write_req || state === s_meta_clear
|
io.meta_write.valid := state === s_meta_write_req || state === s_meta_clear
|
||||||
io.meta_write.bits.idx := req_idx
|
io.meta_write.bits.idx := req_idx
|
||||||
|
Loading…
Reference in New Issue
Block a user