Avoid data corruption under correctable tag error during flush
This esoteric bug manifests if a tag-read error occurs when a FENCE.I is executed, even if the error was correctable. Subsequently, an attempt to flush a dirty line may flush the wrong line's data.
This commit is contained in:
		| @@ -196,7 +196,7 @@ class DCacheModule(outer: DCache) extends HellaCacheModule(outer) { | ||||
|       val s1_tag = s1_paddr >> untagBits | ||||
|       val s1_meta_hit_way = s1_meta_uncorrected.map(r => r.coh.isValid() && r.tag === s1_tag).asUInt | ||||
|       val s1_meta_hit_state = ClientMetadata.onReset.fromBits( | ||||
|         s1_meta_uncorrected.map(r => Mux(r.tag === s1_tag, r.coh.asUInt, UInt(0))) | ||||
|         s1_meta_uncorrected.map(r => Mux(r.tag === s1_tag && !s1_flush_valid, r.coh.asUInt, UInt(0))) | ||||
|         .reduce (_|_)) | ||||
|       (s1_meta_hit_way, s1_meta_hit_state, s1_meta, s1_meta_uncorrected(s1_victim_way)) | ||||
|     } | ||||
| @@ -243,7 +243,7 @@ class DCacheModule(outer: DCache) extends HellaCacheModule(outer) { | ||||
|   val s2_probe_way = RegEnable(s1_hit_way, s1_probe) | ||||
|   val s2_probe_state = RegEnable(s1_hit_state, s1_probe) | ||||
|   val s2_hit_way = RegEnable(s1_hit_way, s1_valid_not_nacked) | ||||
|   val s2_hit_state = RegEnable(s1_hit_state, s1_valid_not_nacked) | ||||
|   val s2_hit_state = RegEnable(s1_hit_state, s1_valid_not_nacked || s1_flush_valid) | ||||
|   val s2_waw_hazard = RegEnable(s1_waw_hazard, s1_valid_not_nacked) | ||||
|   val s2_store_merge = Wire(Bool()) | ||||
|   val s2_hit_valid = s2_hit_state.isValid() | ||||
| @@ -262,9 +262,9 @@ class DCacheModule(outer: DCache) extends HellaCacheModule(outer) { | ||||
|   val s2_valid_cached_miss = s2_valid_miss && !s2_uncached && !uncachedInFlight.asUInt.orR | ||||
|   val s2_victimize = Bool(!usingDataScratchpad) && (s2_valid_cached_miss || s2_valid_data_error || s2_flush_valid) | ||||
|   val s2_valid_uncached_pending = s2_valid_miss && s2_uncached && !uncachedInFlight.asUInt.andR | ||||
|   val s2_victim_way = Mux(s2_hit_valid && !s2_flush_valid_pre_tag_ecc, s2_hit_way, UIntToOH(RegEnable(s1_victim_way, s1_valid_not_nacked || s1_flush_valid))) | ||||
|   val s2_victim_way = Mux(s2_hit_valid, s2_hit_way, UIntToOH(RegEnable(s1_victim_way, s1_valid_not_nacked || s1_flush_valid))) | ||||
|   val s2_victim_tag = Mux(s2_valid_data_error, s2_req.addr >> untagBits, RegEnable(s1_victim_meta.tag, s1_valid_not_nacked || s1_flush_valid)) | ||||
|   val s2_victim_state = Mux(s2_hit_valid && !s2_flush_valid, s2_hit_state, RegEnable(s1_victim_meta.coh, s1_valid_not_nacked || s1_flush_valid)) | ||||
|   val s2_victim_state = Mux(s2_hit_valid, s2_hit_state, RegEnable(s1_victim_meta.coh, s1_valid_not_nacked || s1_flush_valid)) | ||||
|  | ||||
|   val (s2_prb_ack_data, s2_report_param, probeNewCoh)= s2_probe_state.onProbe(probe_bits.param) | ||||
|   val (s2_victim_dirty, s2_shrink_param, voluntaryNewCoh) = s2_victim_state.onCacheControl(M_FLUSH) | ||||
|   | ||||
		Reference in New Issue
	
	Block a user